web-dev-qa-db-fra.com

À l'aide de XPath, comment sélectionner un nœud en fonction de son contenu textuel et de la valeur d'un attribut?

Compte tenu de ce 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>

Je voudrais trouver les nœuds qui ont le texte de "juillet" et un attribut Quad/P1/X supérieur à 90. Ainsi, dans ce cas, il ne devrait renvoyer aucune correspondance. Cependant, si j'utilise GT (>) ou LT (<), j'obtiens une correspondance sur le premier élément Word. Si j'utilise eq (=), je n'obtiens aucune correspondance.

Alors:

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

reviendra vrai, tout comme

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

Comment puis-je contraindre cela correctement sur l'attribut P1 @ X?

De plus, imaginez que j'ai plusieurs éléments Page, pour différents numéros de page. Comment pourrais-je également restreindre la recherche ci-dessus pour trouver des nœuds avec text()='July', P1@X < 90 et Page @pageNumber=3?

66
marc esher

En général, je considérerais l'utilisation d'un // non préfixé comme une mauvaise odeur dans un XPath.

Essaye ça:-

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

Votre problème est que vous utilisez le //P1[@X < 90] qui commence au début du document et commence à rechercher tout P1 donc ce sera toujours vrai. De même //P1[@X > 90] est toujours vrai.

75
AnthonyWJones

Mis à part le problème "//", ce XML est une utilisation très étrange de contenu mixte. Le prédicat text()='July' correspondra à l'élément si un nœud de texte enfant est exactement égal à juillet, ce qui n'est pas vrai dans votre exemple en raison des espaces blancs environnants. En fonction de la définition exacte du XML source, j'opterais pour [text()[normalize-space(.)='July'] and Quad/P1/@X > 90]

26
Michael Kay