0

次のような構造のドキュメントがあります。

<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 DB バージョン 11.2.0.3 の XmlQuery を使用しています。

4

2 に答える 2

1

name() は XML に表示されるとおりに名前を返すため、name() での一致はエラーが発生しやすくなります。2 つの入力が異なるプレフィックスを名前空間名にバインドする場合、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>

ノードがまったく置換されていない場合、考えられる原因の 1 つは XPath 式のエラーです (それらはすべて正しいですか? タイプミスはありませんか?)。もう 1 つは、意図したとおりに $oldXml または $newXml をバインドできないことです。

于 2013-08-25T22:02:04.430 に答える
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 

助けてくれてありがとう!

于 2013-09-05T15:03:12.710 に答える