145 votes

XPath pour sélectionner plusieurs balises

Compte tenu de cette simplifié format des données:

<a>
    <b>
        <c>C1</c>
        <d>D1</d>
        <e>E1</e>
        <f>don't select this one</f>
    </b>
    <b>
        <c>C2</c>
        <d>D2</d>
        <e>E1</e>
        <g>don't select me</g>
    </b>
    <c>not this one</c>
    <d>nor this one</d>
    <e>definitely not this one</e>
</a>

Comment choisissez-vous tous les Cs, Ds et Es, qui sont des enfants d' B éléments?

En gros, quelque chose comme:

a/b/(c|d|e)

Dans ma propre situation, au lieu de simplement en a/b/, la requête menant à la sélection de ceux - C, D, E des nœuds est en fait assez complexe donc je voudrais éviter de le faire:

a/b/c|a/b/d|a/b/e

Est-ce possible?

230voto

Dimitre Novatchev Points 147842

Une seule réponse correcte est:

     /a/b/*[self::c or self::d or self::e]

Notez que cela est incorrect:

a/b/*[local-name()='c' or local-name()='d' or local-name()='e']

est à la fois trop long et incorrect. Cette expression XPath permettra de sélectionner des nœuds comme:

  • OhMy:c

  • NotWanted:d

  • QuiteDifferent:e

48voto

annakata Points 42676

Vous pouvez éviter la répétition avec un attribut de test à la place:

a/b/*[local-name()='c' or local-name()='d' or local-name()='e']

Contrairement à Dimitre de l'antagoniste de l'opinion, le ci-dessus est incorrecte dans un vide où l'OP n'a pas spécifié de l'interaction avec les espaces de noms. Le self:: l'axe est l'espace de noms restrictive, local-name() ne l'est pas. Si l'OP a l'intention de capturer c|d|e indépendamment de l'espace de noms (que je suggérerais, c'est même un scénario le plus probable compte tenu de la nature OU du problème) ensuite, il est "une autre réponse qui a encore quelques votes positifs" ce qui est incorrect.

Vous ne pouvez pas être définitif, sans définition, même si je suis assez heureux pour supprimer ma réponse en tant que véritablement incorrect si l'OP précise sa question, telle que je suis incorrect.

16voto

Pavel Repin Points 13751

Pourquoi ne pas a/b/(c|d|e)? J'ai juste essayé avec Saxon bibliothèque XML (enveloppés bien avec une certaine Clojure la bonté), et il semble fonctionner. abc.xml est le doc décrit par l'OP.

(require '[saxon :as xml])
(def abc-doc (xml/compile-xml (slurp "abc.xml")))
(xml/query "a/b/(c|d|e)" abc-doc)
=> (#<XdmNode <c>C1</c>>
    #<XdmNode <d>D1</d>>
    #<XdmNode <e>E1</e>>
    #<XdmNode <c>C2</c>>
    #<XdmNode <d>D2</d>>
    #<XdmNode <e>E1</e>>)

-1voto

Calvin Points 2800

Vous ne savez pas si cela aide, mais avec XSL, je ferais quelque chose comme:

<xsl:for-each select="a/b">
    <xsl:value-of select="c"/>
    <xsl:value-of select="d"/>
    <xsl:value-of select="e"/>
</xsl:for-each>

et de ne pas ce XPath sélectionnez tous les enfants de B noeuds:

a/b/*

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X