【问题标题】:How to delete a node from Oracle XMLTYPE based on a condition?如何根据条件从 Oracle XMLTYPE 中删除节点?
【发布时间】:2017-01-07 07:55:29
【问题描述】:

我有一个 XML 数据存储在 CLOB 列中,我想根据特定条件删除一些节点。

示例 XML 数据:

<?xml version="1.0" encoding="UTF-8"?>
<payment>
  <person>
    <surname>Marco</surname>
    <name>Gralike</name>
    <salary>2345</salary>
  </person>
  <person>
    <surname>ABC</surname>
    <name>TEST</name>
    <salary>1234</salary>
    <person>
    <surname>Tiger</surname>
    <name>Scott</name>
    <salary>2222</salary>
  </person>
  </person>
 </payment>
 <payment>
  <person>
    <surname>BertJan</surname>
    <name>Meinders</name>
    <salary>3456</salary>
    <salary>125</salary>
  </person>
  <person>
    <surname>XYZ</surname>
    <name>TEST</name>
    <salary>1234</salary>
  </person>
 </payment>
 <payment>
  <person>
    <surname>Chris</surname>
    <name>Gralike</name>
    <salary>4567</salary>
  </person>
  <person>
    <surname>LMN</surname>
    <name>TEST</name>
    <salary>1234</salary>
  </person>
 </payment>

如果包含 TEST,我需要一个 Oracle PLSQL 脚本来删除所有人员标签。

最终输出是:

<?xml version="1.0" encoding="UTF-8"?>
<payment>
  <person>
    <surname>Marco</surname>
    <name>Gralike</name>
    <salary>2345</salary>
  </person>
 </payment>
 <payment>
  <person>
    <surname>BertJan</surname>
    <name>Meinders</name>
    <salary>3456</salary>
    <salary>125</salary>
  </person>
 </payment>
 <payment>
  <person>
    <surname>Chris</surname>
    <name>Gralike</name>
    <salary>4567</salary>
  </person>
 </payment>

提前致谢。

【问题讨论】:

  • 对不起。最终输出将是 MarcoGralike 2345TigerScott2222BertJanMeinders3456125ChrisGralike4567
  • 您应该能够编辑您的问题并将显示的 XML 更改为正确的 XML,它作为评论不太可读。
  • 您的 XML 没有根目录。

标签: sql xml oracle xmltype


【解决方案1】:

您提供的 XML 没有根,无法被 XML 解析器解析。

假设是这样(比如payments),如下所示:

create table t(txt clob);
insert into t values('<?xml version="1.0" encoding="UTF-8"?>
<payments>
    <payment>
        <person>
            <surname>Marco</surname>
            <name>Gralike</name>
            <salary>2345</salary>
        </person>
        <person>
            <surname>ABC</surname>
            <name>TEST</name>
            <salary>1234</salary>
            <person>
                <surname>Tiger</surname>
                <name>Scott</name>
                <salary>2222</salary>
            </person>
        </person>
    </payment>
    <payment>
        <person>
            <surname>BertJan</surname>
            <name>Meinders</name>
            <salary>3456</salary>
            <salary>125</salary>
        </person>
        <person>
            <surname>XYZ</surname>
            <name>TEST</name>
            <salary>1234</salary>
        </person>
    </payment>
    <payment>
        <person>
            <surname>Chris</surname>
            <name>Gralike</name>
            <salary>4567</salary>
        </person>
        <person>
            <surname>LMN</surname>
            <name>TEST</name>
            <salary>1234</salary>
        </person>
    </payment>
</payments>');

你可以用这个:

update t
set txt = to_clob(deletexml(
  xmltype(t.txt),
  '//payment/person[./name[text()="TEST"]]'
));

生产:

<?xml version="1.0" encoding="UTF-8"?>
<payments>
    <payment>
        <person>
            <surname>Marco</surname>
            <name>Gralike</name>
            <salary>2345</salary>
        </person>
    </payment>
    <payment>
        <person>
            <surname>BertJan</surname>
            <name>Meinders</name>
            <salary>3456</salary>
            <salary>125</salary>
        </person>
    </payment>
    <payment>
        <person>
            <surname>Chris</surname>
            <name>Gralike</name>
            <salary>4567</salary>
        </person>
    </payment>
</payments>

编辑:

如果要删除没有给定子节点的节点,请使用:

update t
set txt = to_clob(deletexml(
  xmltype(t.txt),
  '//payment[not(./person)]'
));

它会删除所有没有人的支付标签。

【讨论】:

  • 您好,感谢您的样品。 XYZTEST1234person 4 如果其中之一该节点包含上述数据,然后在使用 deletexml 后我得到这个: person 4 如果该节点不包含任何 标签,如何删除它?问候,拉维
  • @Ravi - 更新了我的答案。请看一看。
【解决方案2】:

deleteXML() 已被弃用。如果可能,您应该使用 XQuery 更新。如果完整路径是固定的,也尽量避免使用'//'。

with XML_TABLE as 
(
   select XMLTYPE('<?xml version="1.0" encoding="UTF-8"?>
<payments>
<payment>
    <person>
        <surname>Marco</surname>
        <name>Gralike</name>
        <salary>2345</salary>
    </person>
    <person>
        <surname>ABC</surname>
        <name>TEST</name>
        <salary>1234</salary>
        <person>
            <surname>Tiger</surname>
            <name>Scott</name>
            <salary>2222</salary>
        </person>
    </person>
</payment>
<payment>
    <person>
        <surname>BertJan</surname>
        <name>Meinders</name>
        <salary>3456</salary>
        <salary>125</salary>
    </person>
    <person>
        <surname>XYZ</surname>
        <name>TEST</name>
        <salary>1234</salary>
    </person>
</payment>
<payment>
    <person>
        <surname>Chris</surname>
        <name>Gralike</name>
        <salary>4567</salary>
    </person>
    <person>
        <surname>LMN</surname>
        <name>TEST</name>
        <salary>1234</salary>
    </person>
</payment>
</payments>') as XML_COLUMN from dual
)
SELECT XMLQuery(
    'copy $NEWXML := $XML modify (
      delete nodes $NEWXML/payments/payment/person[name[text()=$NAME]]
     )
     return $NEWXML'
     passing XML_COLUMN as "XML",
             'TEST' as "NAME"
     returning CONTENT
   )
from XML_TABLE
/

您可以尝试使用 livesql.oracle.com 上的 SQL 工作台截取的这段代码

【讨论】:

    【解决方案3】:

    这行得通

    with XML_TABLE as
    (
       select XMLTYPE('<?xml version="1.0" encoding="UTF-8"?>
    <payments>
      <payment>
        <person>
         <surname>XYZ</surname>
      <name>TEST</name>
      <salary>1234</salary>
    </person>
    <id>person 4</id>
     </payment>
     <payment>
    <id>person 5</id>
    </payment>
     </payments>') as XML_COLUMN from dual
    )
    SELECT XMLQuery(
    'copy $NEWXML := $XML modify (
      delete nodes $NEWXML/payments/payment[not(person)]
     )
     return $NEWXML'
     passing XML_COLUMN as "XML",
             'TEST' as "NAME"
     returning CONTENT
    )
    from XML_TABLE
    
    <?xml version="1.0" encoding="WINDOWS-1252"?>
    <payments>
      <payment>
     <person>
      <surname>XYZ</surname>
      <name>TEST</name>
      <salary>1234</salary>
    </person>
      <id>person 4</id>
     </payment>
    </payments>
    

    SQL>

    【讨论】:

      猜你喜欢
      • 2022-01-14
      • 2021-05-22
      • 1970-01-01
      • 2014-11-21
      • 1970-01-01
      • 2010-10-11
      • 1970-01-01
      • 1970-01-01
      • 2011-12-09
      相关资源
      最近更新 更多