XQuery比较两个文档并替换具有相同名称的节点



我有一个文档的结构如下:

<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 

谢谢你的帮助!

相关内容

  • 没有找到相关文章

最新更新