私は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がどのように機能するのか私の理解です。そのクエリはStreet要素のみを返し、Comment要素は返さないからです。
DOMはComment要素を4つのタグを持つ複合要素にします
[Text = 'XYZ'][BR][BR][Text = 'ABC']
私はそれが要素を見つけて実行する必要がありますが、それはしていないので、クエリはまだ要素を返すべきだと思いますが... ...
次のクエリは要素を返しますが、それは単なる要素よりもはるかに多くを返し、それは親要素も返します...これは問題には望ましくありません...
//*[contains(text(),'ABC')]
要素<Street/>
と<Comment/>
だけを返すxpathクエリを知っている人はいますか
<Comment>
タグには、子として2つのテキストノードと2つの<br>
ノードが含まれています。
あなたのxpath式は
//*[contains(text(),'ABC')]
これを打破するには、
*
は、任意の要素(つまりタグ)に一致するセレクタです - ノードセットを返します。[]
は、そのノードセット内の個々のノードごとに動作する条件です。それが操作する個々のノードのいずれかが括弧内の条件に一致する場合に一致します。text()
は、セレクタで、コンテキストノードの子であるすべてのテキストノードに一致します。ノードセットを返します。contains
は文字列を操作する関数です。ノードセットを渡すと、ノードセット内のノードの文字列値をドキュメント順で最初に返すことで、ノードセットは に変換されます 。したがって、それはあなたの<Comment>
要素の最初のテキストノード、すなわちBLAH BLAH BLAH
だけにマッチすることができます。それが一致しないので、あなたはあなたの結果に<Comment>
を得ません。これをに変更する必要があります
//*[text()[contains(.,'ABC')]]
*
は、任意の要素(つまりタグ)に一致するセレクタです - ノードセットを返します。[]
は、そのノードセット内の個々のノードごとに動作する条件式です。ここでは、ドキュメント内の各要素について動作します。text()
は、セレクタで、コンテキストノードの子であるすべてのテキストノードに一致します。ノードセットを返します。[]
は、そのノードセットの各ノード(ここでは個々のテキストノード)に対して作用する条件です。個々のテキストノードはそれぞれ括弧内のパスの開始点であり、括弧内で.
として明示的に表すこともできます。それが操作する個々のノードのいずれかが括弧内の条件に一致する場合に一致します。contains
は文字列を操作する関数です。ここには個々のテキストノード(.
)が渡されます。これは<Comment>
タグ内の2番目のテキストノードに個別に渡されるため、'ABC'
文字列が表示され、それを照合できます。[contains(text(),'')]
はtrueまたはfalseのみを返します。要素の結果は返されません。
少し時間がかかりましたが、ついに考え出しました。以下のテキストを含むカスタムxpathは私にとっては完璧に機能しました。
//a[contains(text(),'JB-')]
XMLドキュメント:
<Home>
<Addr>
<Street>ABC</Street>
<Number>5</Number>
<Comment>BLAH BLAH BLAH <br/><br/>ABC</Comment>
</Addr>
</Home>
XPath式:
//*[contains(text(), 'ABC')]
//*
は、 ルートノード の 子孫要素 に一致します。つまり、ルートノード以外の要素。
[...]
は 述語 で、ノードセットをフィルタリングします。 ...
がtrue
であるノードを返します。
述語はノードセット[...]をフィルタリングして、新しいノードセットを生成します。フィルタリングされるノードセット内の各ノードに対して、PredicateExprが評価されます[...];そのノードでPredicateExprがtrueと評価された場合、そのノードは新しいノードセットに含まれます。それ以外の場合は含まれません。
contains('haystack', 'needle')
はtrue
を返しますhaystack
の場合 含むneedle
:
関数:boolean contains(string、string)
Contains関数は、最初の引数文字列に2番目の引数文字列が含まれる場合はtrueを返し、それ以外の場合はfalseを返します。
ただし、contains()
は文字列を最初のパラメーターとして受け取ります。そして、ノードを渡しました。最初のパラメーターとして渡されたすべてのノードまたはノードセットが、string()
関数によって文字列に 変換済み であることに対処するには:
引数は、string関数を呼び出した場合のように、string型に変換されます。
string()
関数は、 最初のノード のstring-value
を返します。
ノードセットは、ドキュメント順で最初のノードセット内のノードの文字列値を返すことにより、文字列に変換されます。ノードセットが空の場合、空の文字列が返されます。
要素ノード のstring-value
:
要素ノードの文字列値は、要素ノードのすべてのテキストノードの子孫の文字列値をドキュメント順に連結したものです。
string-value
の- テキストノード :
テキストノードの文字列値は文字データです。
したがって、基本的にstring-value
は、ノードに含まれるすべてのテキスト(すべての子孫テキストノードの連結)です。
text()
は、任意のテキストノードに一致するノードテストです。
ノードテストtext()は、すべてのテキストノードに対してtrueです。たとえば、child :: text()はコンテキストノードのテキストノードの子を選択します。
そうは言っても、//*[contains(text(), 'ABC')]
は、最初のテキストノードにABC
が含まれる任意の要素(ただしルートノード)に一致します。 text()
は、(式の評価に関連する)コンテキストノードのすべての子テキストノードを含むノードセットを返すため。しかし、contains()
は最初のもののみを取ります。したがって、上記のドキュメントの場合、パスはStreet
要素と一致します。
次の式//*[text()[contains(., 'ABC')]]
は、ABC
を含む少なくとも1つの子テキストノードを持つ任意の要素(ただしルートノード)に一致します。 .
はコンテキストノードを表します。この場合、それはルートノード以外の任意の要素の子テキストノードです。そのため、上記のドキュメントの場合、パスはStreet
およびComment
要素と一致します。
ここで、//*[contains(., 'ABC')]
は、ABC
(子孫テキストノードの連結内)を含む任意の要素(ただしルートノード)と一致します。上記のドキュメントでは、Home
、Addr
、Street
、およびComment
エレメントと一致します。そのため、//*[contains(., 'BLAH ABC')]
は、Home
、Addr
、およびComment
要素と一致します。