[英]How to delete a node from Oracle XMLTYPE based on a condition?
I have a XML data stored in a CLOB
column and I would like to delete some nodes based on a specific condition.我有一个存储在
CLOB
列中的 XML 数据,我想根据特定条件删除一些节点。
Example XML Data : 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>
I need a Oracle PLSQL script to delete all the person tags if it contains TEST.如果包含 TEST,我需要一个 Oracle PLSQL 脚本来删除所有人员标签。
Final output would be :最终输出将是:
<?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>
Thanks in advance.提前致谢。
Your provided XML doesn't have a root and can't be parsed by XML parser. 您提供的XML没有根,因此XML解析器无法对其进行解析。
Assuming it does (say payments
) as shown below: 假设确实如此(例如
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>');
You can use this: 您可以使用此:
update t
set txt = to_clob(deletexml(
xmltype(t.txt),
'//payment/person[./name[text()="TEST"]]'
));
Produces: 产生:
<?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>
If you want to delete a node that doesn't have a given child, use this: 如果要删除没有给定子节点的节点,请使用以下命令:
update t
set txt = to_clob(deletexml(
xmltype(t.txt),
'//payment[not(./person)]'
));
It'll delete all the payment tags that don't have a person in it. 它将删除所有没有人的付款标签。
deleteXML() has been deprecated. deleteXML()已被弃用。 If possible you should use XQuery update.
如果可能的话,您应该使用XQuery更新。 Also try to avoid the use of '//' if the full path is fixed.
如果完整路径是固定的,也请尝试避免使用'//'。
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
/
You can try this code snipped using the SQL Workbench at livesql.oracle.com 您可以在livesql.oracle.com上尝试使用SQL Workbench删除此代码
Thanks for the sample. 感谢您的样品。
<payment>
<person>
<surname>XYZ</surname>
<name>TEST</name>
<salary>1234</salary>
</person>
<id>person 4</id>
</payment>
If one of the node contains above data then after using deletexml i get this : 如果节点之一包含上述数据,则在使用deletexml之后,我得到以下信息:
<payment>
<id>person 4</id>
</payment>
How to delete this node if it does not contain any <person>
tag ? 如果该节点不包含任何
<person>
标记,如何删除?
ie How to delete the below Node as it does not contain <person>
tag : 即如何删除下面的节点,因为它不包含
<person>
标签:
<payment>
<id>person 4</id>
</payment>
This works 这有效
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> SQL>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.