我有一个文档的结构如下:
<INVT_DATA xmlns="http://www.mrbook.com/InventoryData">
<AUTHOR>...</AUTHOR>
<TITLE>...</TITLE>
<PUBLISHER>...</PUBLISHER>
</INVT_DATA>
INVT_DATA的子类始终是元素,而不是文本节点。我想使用XQuery来比较具有相同结构的新文档。如果一个子元素存在于新元素和原始元素中,则应将其替换。如果一个子元素存在于新元素中,但不在旧元素中,则应将其附加到INVT_DATA。
我认为这个XQuery是可行的,但它似乎总是只附加节点:
declare namespace invtdata="http://www.mrbook.com/InventoryData";
copy $oldInvtData := $oldXml
modify
(
for $mpf in $newXml/invtdata:INVT_DATA/*
let $oldMpf := $oldInvtData/invtdata:INVT_DATA/*[name()=name($mpf)]
return if(exists($oldMpf)) then
replace node $oldMpf with $mpf
else insert node $mpf into $oldInvtData
)
return $oldInvtData
我搜索了其他类似的问题,发现了这个,但这对我想做的事情来说有点过头了。有什么建议吗?如果有帮助的话,我将使用Oracle XML数据库11.2.0.3版本中的XmlQuery。
对name()进行匹配很容易出错,因为name()返回XML中显示的名称——如果您的两个输入将不同的前缀绑定到命名空间名称,则检查name()的相等性将不会成功。如果您将谓词更改为
[local-name() = local-name($mpf)
and
namespace-uri() = namespace-uri($mpf)]
您的代码应该工作得更好。
附录:
也就是说,给定一个包含以下内容的XML文档Brad1.XML:
<INVT_DATA xmlns="http://www.mrbook.com/InventoryData">
<AUTHOR>old author</AUTHOR>
<TITLE>old title</TITLE>
<PUBLISHER>old publisher</PUBLISHER>
</INVT_DATA>
以及具有以下内容的XML文档Brad2.XML:
<id:INVT_DATA xmlns:id="http://www.mrbook.com/InventoryData">
<id:AUTHOR>new author</id:AUTHOR>
<id:PUBLISHER>new publisher</id:PUBLISHER>
</id:INVT_DATA>
代码:
declare namespace invtdata="http://www.mrbook.com/InventoryData";
declare variable $oldXml := doc('.../Brad1.xml');
declare variable $newXml := doc('.../Brad2.xml');
copy $oldInvtData := $oldXml
modify
(
for $mpf in $newXml/invtdata:INVT_DATA/*
let $oldMpf := $oldInvtData/invtdata:INVT_DATA/*
[local-name() = local-name($mpf)
and namespace-uri() = namespace-uri($mpf)]
return if(exists($oldMpf)) then
replace node $oldMpf with $mpf
else insert node $mpf into $oldInvtData
)
return $oldInvtData
评估为:
<INVT_DATA xmlns="http://www.mrbook.com/InventoryData"
xmlns:id="http://www.mrbook.com/InventoryData">
<id:AUTHOR>new author</id:AUTHOR>
<TITLE>old title</TITLE>
<id:PUBLISHER>new publisher</id:PUBLISHER>
</INVT_DATA>
如果您根本没有看到任何节点被替换,一个可能的原因是XPath表达式中的错误(您确定它们都是正确的吗?没有拼写错误?);另一个是未能按您的意愿绑定$oldXml或$newXml。
这是正确的代码。。。。只是一个小调整。
declare namespace invtdata="http://www.mrbook.com/InventoryData";
declare variable $oldXml := doc('.../Brad1.xml');
declare variable $newXml := doc('.../Brad2.xml');
copy $oldInvtData := $oldXml
modify
(
for $mpf in $newXml/invtdata:INVT_DATA/*
let $oldMpf := $oldInvtData/invtdata:INVT_DATA/*
[local-name() = local-name($mpf)
and namespace-uri() = namespace-uri($mpf)]
return if(exists($oldMpf)) then
replace node $oldMpf with $mpf
else insert node $mpf into $oldInvtData/invtdata:INVT_DATA
)
return $oldInvtData
谢谢你的帮助!