2010-11-02 21 views
11

Ich habe eine XPath-Abfrage, die tut, was ich will, nämlich eine Union von 'Nachname' & 'gegebene Namen' mit den gegebenen Prädikaten (Es ist entweder entweder/oder das ich brauche, aber die Vereinigung funktioniert gut):XPath Auswahl mehrerer Elemente mit Prädikaten

/header/authors/surname[./text() and @id='1'] 
| 
/header/authors/given-names[./text() and @id='1'] 

doch diese allzu langatmig scheint mir, und ich fühle, dass es möglich sein sollte, etwas prägnanter zu tun wie:

/header/authors/(surname|given-names)[./text() and @id='1'] 

... aber das Version ist nicht gültig XPath.

Kann mir jemand von einer saubereren Art des Schreibens des ursprünglichen XPath-Ausdrucks erzählen, der nicht erfordert, dass der vollständige Pfad zweimal geschrieben wird?

Dank

Richard

+0

Was meinst du mit "entweder/oder"? –

+0

@Alejandro: Bei einer ID könnte das erforderliche Element "Nachname" oder "Vorname" sein. Das habe ich versucht zu sagen. Ich denke, dass es die Union ist, die ich brauche. –

Antwort

24

Erstens ist diese gültig XPath 2.0:

/header/authors/(surname|given-names)[./text() and @id='1'] 

Zweitens diese XPath 1.0:

/header/authors/*[self::surname|self::given-names][text()][@id='1'] 
+1

Das ist ausgezeichnet und ich war dabei, es +1 zu geben. In der XPath 1.0-Version ist es jedoch besser, '|' nicht innerhalb des Prädikats zu verwenden. Der richtige Operator ist 'oder'. In diesem Fall wählt der Ausdruck immer noch die gewünschten Knoten aus, aber in anderen Fällen erzeugt das Ersetzen durch "oder" mit "|" keinen äquivalenten Ausdruck. +1 sowieso. –

+1

@Dimitre: Sie haben Recht mit '| 'Union-Set-Operator, aber ich habe es ** in diesem Fall ** verwendet, weil beide Begriffe Knoten-Sets sind (und weil prägnant war der Schlüssel). Das gleiche gilt für die Sequenz der Prädikate. –

+0

Diese Antwort erklärt beide, warum ich fühlte, dass ich '(Nachname | gegebene Namen) verwenden sollte' (das aktuelle Projekt verwendet nicht XPath 2.0) und stellte auch eine große XPath 1.0 Alternative zur Verfügung. Vielen Dank. –

4

Wie wäre es

/header/authors/*[(name() = "surname" or name()="given-names") and ./text() and @id='1'] 
+0

Das wird funktionieren, aber es ist noch schöner ... – annakata

+0

Danke für Ihre Antwort. Es spart zwar zweimal den Weg, aber ist immer noch etwas unhandlich im Vergleich zu dem, was ich mir vorgestellt habe. –

2

Neben Alejandros und gute Antworten der Seva, eine andere Alternative ist

(/header/authors/surname | /header/authors/given-names)[text() and @id='1'] 

Diese in XPath 1.0 gültig ist. Es ist immer noch ein wenig überflüssig, aber ist prägnanter als die langatmige Version in Ihrer Frage.

Eine weitere Alternative wäre, eine Variable für Nachnamen Elemente zu deklarieren und eine Variable für given-name-Elemente und dann

($surnames | $given-names)[text() and @id='1'] 

, die wahrscheinlich länger insgesamt wäre, aber einfacher als die oben zu lesen.