使用 FLWOR 从选定节点删除 xml 子元素
Delete a xml child element from a selected node using FLWOR
我正在尝试删除 "number" 子元素:
@tsip:表格="wila"
从下面的 "applications" 节点使用 flwor 查询。数据在 Oracle 11g 数据库中,在 xml_type 列中,Oracle 使用 xquery 1.0。我已经设法在下面完成了这个,但是我的尝试非常笨拙而且冗长,因为我已经硬编码了父 "applications" 元素和子 "number" 元素之间的中间元素,所以如果格式xml 更改我的查询可能不起作用。谁能提供更通用的解决方案。
它必须比这更容易:
创建 table:
CREATE TABLE XML_DOCUMENT_TMP
(
DOCUMENT_ID NUMBER(12) NOT NULL,
XML_DATA SYS.XMLTYPE NOT NULL,
CREATED_DATE TIMESTAMP(6) NOT NULL
);
将一些数据插入 XML_DOCUMENT_TMP:
insert into XML_DOCUMENT_TMP
(document_id,created_date,xml_data)
values(6,sysdate,'<patent xmlns="http://schemas.xx.com/ts/20041221/tsip"
xmlns:tsip="http://schemas.xx.com/ts/20041221/tsip"
tsip:action="replace" tsip:cc="CA" tsip:se="2715340" tsip:ki="C">
<keepThis>data</keepThis>
<applications tsip:action="new">
<application tsip:cc="GB" tsip:se="2338695" tsip:ki="A" tsip:priorityCode="A2">
<applicationId>
<number tsip:form="wila">9813397</number>
<number tsip:form="original">9813397</number>
<number tsip:form="tsip">000013397</number>
<countryCode>GB</countryCode>
<applicationYear>1998</applicationYear>
<date>1998-06-23</date>
</applicationId>
</application>
</applications>
<keepThis2>data2</keepThis2>
</patent>
');
Select 除了带有@tsip:form="wila"
的 "number" 元素之外的所有数据
SELECT /*+ NO_XML_QUERY_REWRITE */ xA.document_id ,
XMLSerialize(DOCUMENT
XMLQuery('xquery version "1.0";
declare default element namespace "http://schemas.xx.com/ts/20041221/tsip";
declare namespace tsip="http://schemas.xx.com/ts/20041221/tsip";
<patent xmlns="http://schemas.xx.com/ts/20041221/tsip" xmlns:tsip="http://schemas.xx.com/ts/20041221/tsip" >{$a/*:patent/@*}
{
for $s in $a/*:patent/*
return
if ($s = $a/*:patent/applications)
then
<applications>{$a/*:patent/applications/@*}
<application>{$a/*:patent/applications/application/@*}
<applicationId>
{
(: Use the "except" clause to remove the unwanted <number> element with the "wila" attribute value :)
$a/*:patent/applications/application/applicationId/* except $a/*:patent/applications/application/applicationId/number[@tsip:form="wila"]
}
</applicationId>
</application>
</applications>
else $s
}
</patent>'
PASSING xA.xml_data as "a"
RETURNING CONTENT) ) newXml
FROM XML_DOCUMENT_TMP xA
WHERE document_id=6;
在 XQuery 中,您可以使用递归函数访问每个节点并测试是否应删除该节点。如果它应该被删除,你什么都不做,如果它不应该被删除,你将它复制为一个同名的新节点 element {node-name(.)} { ...
并继续访问它的子节点:
declare namespace tsip="http://schemas.xx.com/ts/20041221/tsip";
declare function local:transform($root) {
$root / (typeswitch (.)
case element(tsip:number) return
if (@tsip:form = "wila") then ()
else .
case element() return
element {node-name(.)} {
@*, for $n in node() return local:transform($n)
}
default return .
)
};
local:transform($a)
我正在尝试删除 "number" 子元素: @tsip:表格="wila" 从下面的 "applications" 节点使用 flwor 查询。数据在 Oracle 11g 数据库中,在 xml_type 列中,Oracle 使用 xquery 1.0。我已经设法在下面完成了这个,但是我的尝试非常笨拙而且冗长,因为我已经硬编码了父 "applications" 元素和子 "number" 元素之间的中间元素,所以如果格式xml 更改我的查询可能不起作用。谁能提供更通用的解决方案。 它必须比这更容易:
创建 table:
CREATE TABLE XML_DOCUMENT_TMP
(
DOCUMENT_ID NUMBER(12) NOT NULL,
XML_DATA SYS.XMLTYPE NOT NULL,
CREATED_DATE TIMESTAMP(6) NOT NULL
);
将一些数据插入 XML_DOCUMENT_TMP:
insert into XML_DOCUMENT_TMP
(document_id,created_date,xml_data)
values(6,sysdate,'<patent xmlns="http://schemas.xx.com/ts/20041221/tsip"
xmlns:tsip="http://schemas.xx.com/ts/20041221/tsip"
tsip:action="replace" tsip:cc="CA" tsip:se="2715340" tsip:ki="C">
<keepThis>data</keepThis>
<applications tsip:action="new">
<application tsip:cc="GB" tsip:se="2338695" tsip:ki="A" tsip:priorityCode="A2">
<applicationId>
<number tsip:form="wila">9813397</number>
<number tsip:form="original">9813397</number>
<number tsip:form="tsip">000013397</number>
<countryCode>GB</countryCode>
<applicationYear>1998</applicationYear>
<date>1998-06-23</date>
</applicationId>
</application>
</applications>
<keepThis2>data2</keepThis2>
</patent>
');
Select 除了带有@tsip:form="wila"
的 "number" 元素之外的所有数据SELECT /*+ NO_XML_QUERY_REWRITE */ xA.document_id ,
XMLSerialize(DOCUMENT
XMLQuery('xquery version "1.0";
declare default element namespace "http://schemas.xx.com/ts/20041221/tsip";
declare namespace tsip="http://schemas.xx.com/ts/20041221/tsip";
<patent xmlns="http://schemas.xx.com/ts/20041221/tsip" xmlns:tsip="http://schemas.xx.com/ts/20041221/tsip" >{$a/*:patent/@*}
{
for $s in $a/*:patent/*
return
if ($s = $a/*:patent/applications)
then
<applications>{$a/*:patent/applications/@*}
<application>{$a/*:patent/applications/application/@*}
<applicationId>
{
(: Use the "except" clause to remove the unwanted <number> element with the "wila" attribute value :)
$a/*:patent/applications/application/applicationId/* except $a/*:patent/applications/application/applicationId/number[@tsip:form="wila"]
}
</applicationId>
</application>
</applications>
else $s
}
</patent>'
PASSING xA.xml_data as "a"
RETURNING CONTENT) ) newXml
FROM XML_DOCUMENT_TMP xA
WHERE document_id=6;
在 XQuery 中,您可以使用递归函数访问每个节点并测试是否应删除该节点。如果它应该被删除,你什么都不做,如果它不应该被删除,你将它复制为一个同名的新节点 element {node-name(.)} { ...
并继续访问它的子节点:
declare namespace tsip="http://schemas.xx.com/ts/20041221/tsip";
declare function local:transform($root) {
$root / (typeswitch (.)
case element(tsip:number) return
if (@tsip:form = "wila") then ()
else .
case element() return
element {node-name(.)} {
@*, for $n in node() return local:transform($n)
}
default return .
)
};
local:transform($a)