1. ホーム
  2. xpath

[解決済み] XPath contains(text(),'some string') は、複数の Text サブノードを持つノードで使用すると動作しません。

2022-03-27 20:44:07

質問

私はXpathがdom4jで含まれているとの小さな問題を抱えている...

私のXMLが次のようなものだとします。

<Home>
    <Addr>
        <Street>ABC</Street>
        <Number>5</Number>
        <Comment>BLAH BLAH BLAH <br/><br/>ABC</Comment>
    </Addr>
</Home>

例えば、ルート要素から、テキストに ABC を含むすべてのノードを見つけたいとします。

ということで、xpathは以下のように書く必要がある。

//*[contains(text(),'ABC')]

しかし、これはDom4jが返すものではありません...これはDom4jの問題なのか、それともxpathの動作方法を私が理解しているのでしょうか。

DOM は Comment 要素を 4 つのタグを持つ複合要素とし、2 つの

[Text = 'XYZ'][BR][BR][Text = 'ABC'] 

要素を見つけ、それに対してcontainsを実行するはずなので、クエリはまだその要素を返すはずだと思うのですが、そうではありません... ....

次のクエリは要素を返しますが、要素だけでなく、親要素も返します...これは問題にとって望ましくありません...。

//*[contains(text(),'ABC')]

要素のみを返す xpath クエリをご存知の方はいらっしゃいますか? <Street/><Comment/> ?

解決方法は?

その <Comment> タグには2つのテキストノードと2つの <br> ノードを子として持つ。

あなたのxpath式は

//*[contains(text(),'ABC')]

これを分解すると

  1. * は任意の要素(つまりタグ)にマッチするセレクタで、ノードセットを返します。
  2. [] は、そのノードセット内の個々のノードに対して操作する条件である。操作する個々のノードが括弧の中の条件にマッチする場合にマッチする。
  3. text() セレクタ は、コンテキストノードの子であるすべてのテキストノードにマッチする -- ノードセットを返す。
  4. contains は、文字列を操作する関数である。ノードセットを渡された場合、ノードセットは を文字列に変換し,文書順が最初のノードセットのノードの文字列値を返す。 . したがって、これは <Comment> 要素、すなわち BLAH BLAH BLAH . これが一致しないので、あなたは <Comment> が表示されます。

に変更する必要があります。

//*[text()[contains(.,'ABC')]]

  1. * は、任意の要素(つまりタグ)にマッチするセレクタで、ノードセットを返します。
  2. 外側の [] は、そのノードセット内の個々のノードに対して操作する条件です。ここでは、ドキュメント内の各要素に対して操作しています。
  3. text() セレクタ は、コンテキストノードの子であるすべてのテキストノードにマッチする -- ノードセットを返す。
  4. 内側の [] は、そのノードセット内の各ノード(ここでは個々のテキストノード)に対して操作する条件である。個々のテキストノードは、括弧内のあらゆるパスの出発点となり、また、明示的に . を括弧の中に入れる。操作する個々のノードのいずれかが、大括弧内の条件に一致した場合にマッチする。
  5. contains は、文字列を操作する関数である。ここでは、個々のテキストノード( . ). の2番目のテキストノードが渡されます。 <Comment> タグを個々に見るので 'ABC' の文字列とマッチングできるようになります。