我的文档结构如下:
<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
我搜索了其他类似问题并找到了this,但这对我想做的事情来说有点过分。有什么建议?如果有帮助,我使用的是Oracle XML DB 11.2.0.3版本中的XmlQuery。
答案 0 :(得分:1)
在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。
答案 1 :(得分:0)
这证明是正确的代码....只是一个小调整。
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
感谢您的帮助!