web-dev-qa-db-ja.com

SelectSingleNodeでのXPathの使用:存在する場合はXMLから個々の要素を取得する

私のXMLは次のようになります:

_<?xml version=\"1.0\"?>
<itemSet>
       <Item>one</Item>
       <Item>two</Item>
       <Item>three</Item>
       .....maybe more Items here.
</itemSet>
_

一部の個人アイテム存在する場合と存在しない場合があります。要素_<Item>_two _</Item>_が存在する場合は、それを取得したいとします。次のXPathを(C#で)試しました。

  • XMLNode node = myXMLdoc.SelectSingleNode("/itemSet[Item='two']") --- Itemtwoが存在する場合、最初の要素のみが返されます。 )one。子として値2のItemがある場合、このクエリはitemSetの最初の要素を指しているだけかもしれません。この解釈は正しいですか?

だから私は試しました:

  • XMLNode node = myXMLdoc.SelectSingleNode("/itemSet[Item='two']/Item[1]") ---このクエリを次のように読み取り、値=を持つitemSet内の最初の_<Item>_要素を返します。 '二'。私は正しいですか?

これでも、最初の要素oneのみが返されます。私は何が間違っているのですか?どちらの場合も、兄弟を使用して子ノードをトラバースし、twoに到達できますが、それは私が見ているものではありません。また、2つが存在しない場合、SelectSingleNodeはnullを返します。したがって、正常な戻りノードを取得しているという事実は、要素2の存在を示しているので、twoの存在をchkするブールテストが必要でした。 、上記のXPathのいずれでも十分ですが、実際には、戻りノードとして完全な要素_<Item>two</Item>_が必要です。

[ここでの最初の質問であり、Webプログラミングを初めて使用したので、SOでの過去の質問から、上記のXPathと関連するxmlの内容をその場で学びました。ですから、優しくして、私が馬鹿なのか、コミュニティのルールを無視しているのかを知らせてください。ありがとう。]

13
user108324

私はあなたが欲しいと思います:

_myXMLdoc.SelectSingleNode("/itemSet/Item[text()='two']")
_

つまり、itemSetに含まれているのではなく、2つのテキストを持つItemが必要です。

次の場合は、単一のドットを使用してコンテキストノードを示すこともできます。

_myXMLdoc.SelectSingleNode("/itemSet/Item[.='two']")
_

編集:_._とtext()の違いは、_._は事実上「このノード」を意味し、text()は「このノードのすべてのテキストノードの子」を意味することです。 "。どちらの場合も、比較はLHSの「文字列値」に対して行われます。要素ノードの場合、文字列値は「要素ノードのすべてのテキストノードの子孫の文字列値をドキュメント順に連結したもの」であり、テキストノードのコレクションの場合、比較により、テキストノードがあなたがテストしているもの。

したがって、要素のコンテンツにテキストノードが1つしかない場合は問題ではありませんが、次のようになっているとします。

_<root>
  <item name="first">x<foo/>y</item>
  <item name="second">xy<foo/>ab</item>
</root>
_

次に、「_root/item[.='xy']_」のXPath式は最初の項目に一致しますが、「root/item[text()='xy']」は2番目の項目に一致します。

23
Jon Skeet