使用XPath,如何根据文本内容和属性值选择节点?

mar*_*her 66 xml xpath xquery

鉴于此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>
Run Code Online (Sandbox Code Playgroud)

我想找到具有'July'文本和Quad/P1/X属性大于90的节点.因此,在这种情况下,它不应该返回任何匹配.但是,如果我使用GT(>)或LT(<),我会在第一个Word元素上得到匹配.如果我使用eq(=),我得不到匹配.

所以:

//Word[text()='July' and //P1[@X < 90]]
Run Code Online (Sandbox Code Playgroud)

将会返回true

//Word[text()='July' and //P1[@X > 90]]
Run Code Online (Sandbox Code Playgroud)

如何在P1 @ X属性上正确约束?

另外,想象一下,我有多个Page元素,用于不同的页码.我如何另外约束上面的搜索以找到节点text()='July', P1@X < 90和Page @pageNumber=3

Ant*_*nes 75

一般来说,我会考虑使用未加前缀的//作为XPath中的难闻气味.

试试这个:-

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

你的问题是你使用的//P1[@X < 90]是从文档开头开始并开始搜索任何P1因此它将永远是真的.同样//P1[@X > 90]总是如此.


Mic*_*Kay 26

除了形成"//"问题之外,这种XML对混合内容的使用非常奇怪.text()='July'如果任何子文本节点完全等于July,则谓词将匹配该元素,由于周围的空格,在您的示例中不是这样.根据源XML的确切定义,我会选择[text()[normalize-space(.)='July'] and Quad/P1/@X > 90]