web-dev-qa-db-ja.com

XPathを使用して、テキストコンテンツと属性の値に基づいてノードを選択するにはどうすればよいですか?

このXMLを考えます:

_<DocText>
<WithQuads>
    <Page pageNumber="3">
        <Word>
            July
            <Quad>
                <P1 X="84" Y="711.25" />
                <P2 X="102.062" Y="711.25" />
                <P3 X="102.062" Y="723.658" />
                <P4 X="84.0" Y="723.658" />
            </Quad>
        </Word>
        <Word>
        </Word>
        <Word>
            30,
            <Quad>
                <P1 X="104.812" Y="711.25" />
                <P2 X="118.562" Y="711.25" />
                <P3 X="118.562" Y="723.658" />
                <P4 X="104.812" Y="723.658" />
            </Quad>
        </Word>
    </Page>
</WithQuads>
_

「7月」のテキストと90を超えるQuad/P1/X属性を持つノードを検索したいので、この場合、一致を返すことはできません。ただし、GT(>)またはLT(<)を使用すると、最初のWord要素に一致します。eq(=)を使用すると一致しません。

そう:

_//Word[text()='July' and //P1[@X < 90]]
_

同様にtrueを返します

_//Word[text()='July' and //P1[@X > 90]]
_

P1 @ X属性でこれを適切に制限するにはどうすればよいですか?

さらに、ページ番号が異なる複数のPage要素があるとします。 text()='July', P1@X < 90、およびPage _@pageNumber=3_を含むノードを見つけるために、上記の検索をさらに制約する方法を教えてください。

66
marc esher

一般に、接頭辞のない//の使用はXPathの悪臭と見なします。

これを試して:-

/DocText/WithQuads/Page/Word[text()='July' and Quad/P1/@X > 90]

問題は、//P1[@X < 90]は、ドキュメントの先頭から開始し、P1したがって、常に真になります。同様に//P1[@X > 90]は常に真です。

75
AnthonyWJones

「//」問題とは別に、このXMLは混合コンテンツの非常に奇妙な使用法です。子テキストノードが7月に正確に等しい場合、述部text()='July'は要素に一致します。これは、周囲の空白のために、この例では当てはまりません。ソースXMLの正確な定義に応じて、[text()[normalize-space(.)='July'] and Quad/P1/@X > 90]を選択します

26
Michael Kay