webentwicklung-frage-antwort-db.com.de

XPath, um mehrere Tags auszuwählen

Angesichts dieses vereinfachten Datenformats:

<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>

Wie würden Sie alle Cs, Ds und Es auswählen, die untergeordnete Elemente von B sind?

Grundsätzlich so etwas wie:

a/b/(c|d|e)

In meiner eigenen Situation statt nur a/b/, die Abfrage, die zur Auswahl dieser C, D, E Knoten führt, ist eigentlich recht komplex, daher möchte ich dies vermeiden:

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

Ist das möglich?

117
nickf

Eine richtige Antwort ist:

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

Beachten Sie, dass dies

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

ist zu lang und falsch. Dieser XPath-Ausdruck wählt Knoten aus wie:

OhMy:c

NotWanted:d 

QuiteDifferent:e
189

Sie können die Wiederholung stattdessen mit einem Attributtest vermeiden:

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

Entgegen der antagonistischen Meinung von Dimitre ist das oben Gesagte nicht falsch in einem Vakuum, in dem das OP die Interaktion mit Namespaces nicht spezifiziert hat. Die self:: - Achse ist Namespace-restriktiv, local-name() nicht. Wenn das OP die Absicht hat, c|d|e Unabhängig vom Namespace zu erfassen (was ich angesichts der OR Art des Problems) sogar als ein wahrscheinliches Szenario vorschlagen würde), dann ist es "eine andere Antwort das hat noch einige positive stimmen "was falsch ist.

Sie können ohne Definition nicht endgültig sein, obwohl ich meine Antwort sehr gerne als wirklich falsch lösche, wenn das OP seine Frage so klärt, dass ich falsch bin.

42
annakata

Warum nicht a/b/(c|d|e)? Ich habe es gerade mit sächsische XML-Bibliothek versucht (gut verpackt mit etwas Clojure-Güte), und es scheint zu funktionieren. abc.xml ist das von OP beschriebene Dokument.

(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>>)
13
Pavel Repin