Start · Sprachen · JavaScript · Referenz · XPathExpression

XPathExpression

Schnittstelle

Ein vorkompilierter XPath-Ausdruck, der mit <code>evaluate()</code> wiederholt auf ein Dokument oder einen beliebigen Knoten angewendet werden kann.

seit JavaScript Baseline: alle Browser Kategorie: webapi

Signatur

interface XPathExpression

Beschreibung

XPathExpression steht für einen bereits geparsten und kompilierten XPath-Ausdruck. Man erhält ihn nicht über einen Konstruktor, sondern über document.createExpression(ausdruck, resolver) oder XPathEvaluator.prototype.createExpression(). Die einzige Methode ist evaluate(contextNode, type, result). Sie liefert ein XPathResult.

Ein kompilierter Ausdruck lohnt sich, wenn derselbe XPath-Ausdruck mehrfach ausgewertet wird, zum Beispiel in einer Schleife über viele Kontextknoten. Das Parsen passiert dann nur ein einziges Mal. Wird ein Ausdruck nur einmal gebraucht, reicht document.evaluate() völlig aus.

Die Methode evaluate() hat folgende Parameter:

  • contextNode (Node, Pflicht): Knoten, von dem aus relative Pfade wie ./li ausgewertet werden.
  • type (number, optional, Standard XPathResult.ANY_TYPE = 0): gewünschter Ergebnistyp, etwa XPathResult.ORDERED_NODE_SNAPSHOT_TYPE oder XPathResult.STRING_TYPE.
  • result (XPathResult | null, optional): ein vorhandenes Ergebnisobjekt, das wiederverwendet werden darf. Browser ignorieren diesen Parameter in der Praxis meist und geben ein neues Objekt zurück.

Der Rückgabewert ist ein XPathResult. Je nach resultType liest man daraus numberValue, stringValue, booleanValue oder singleNodeValue aus, oder man durchläuft die Treffer mit iterateNext() bzw. snapshotItem(i).

Parameter

Name Typ Default Beschreibung
$contextNode Pflicht Node Parameter von evaluate(): Kontextknoten, auf den der Ausdruck angewendet wird.
$type number XPathResult.ANY_TYPE (0) Parameter von evaluate(): eine der XPathResult-Konstanten für den gewünschten Ergebnistyp.
$result XPathResult | null null Parameter von evaluate(): vorhandenes Ergebnisobjekt zur Wiederverwendung. Wird in der Praxis meist ignoriert.

Rückgabewert

Typ
XPathResult
Beschreibung
Rückgabewert von evaluate(): das Ergebnis der Auswertung im angeforderten Typ.

Beispiele

Ausdruck erzeugen und einmal auswerten

// Kompilierten Ausdruck erzeugen (kein Konstruktor, sondern Fabrikmethode)
const expr = document.createExpression('count(//a[@href])', null);

const result = expr.evaluate(document, XPathResult.NUMBER_TYPE);
console.log(`Links auf der Seite: ${result.numberValue}`);
Links auf der Seite: 12

Einen Ausdruck auf viele Kontextknoten anwenden

// Einmal kompilieren, für jede Tabellenzeile wiederverwenden
const priceExpr = document.createExpression('string(./td[@class="preis"])', null);

const rows = document.querySelectorAll('table#produkte tbody tr');
const preise = [...rows].map((row) =>
  parseFloat(priceExpr.evaluate(row, XPathResult.STRING_TYPE).stringValue)
);

console.log(preise);
[19.99, 4.5, 129]

Knoten als Snapshot sammeln

const expr = document.createExpression('//li[contains(@class, "offen")]', null);
const snap = expr.evaluate(document, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);

for (let i = 0; i < snap.snapshotLength; i++) {
  snap.snapshotItem(i).classList.add('hervorgehoben');
}
console.log(`${snap.snapshotLength} offene Aufgaben markiert`);
3 offene Aufgaben markiert

Namensräume in XML-Dokumenten auflösen

const xml = new DOMParser().parseFromString(
  '<feed xmlns="http://www.w3.org/2005/Atom"><entry><title>Hallo</title></entry></feed>',
  'application/xml'
);

// Resolver ordnet dem Präfix "atom" die Namensraum-URI zu
const resolver = (prefix) => (prefix === 'atom' ? 'http://www.w3.org/2005/Atom' : null);
const expr = xml.createExpression('//atom:entry/atom:title', resolver);

const node = expr.evaluate(xml, XPathResult.FIRST_ORDERED_NODE_TYPE).singleNodeValue;
console.log(node.textContent);
Hallo

// Wichtig · Fallstricke

  • Kein Konstruktor: new XPathExpression() löst einen TypeError aus. Einen Ausdruck erhält man nur über createExpression().
  • Syntaxfehler werden schon beim Kompilieren gemeldet: createExpression() wirft dann eine DOMException vom Typ SyntaxError. Unbekannte Namensraum-Präfixe führen zu einem NamespaceError.
  • Ergebnisse vom Typ *_ITERATOR_TYPE werden ungültig, sobald sich das DOM ändert. Wer beim Durchlaufen Knoten verändert, sollte deshalb *_SNAPSHOT_TYPE verwenden.
  • Unterstützt wird nur XPath 1.0, also keine Funktionen aus XPath 2.0 oder 3.x wie matches() oder lower-case().
  • In HTML-Dokumenten liegen Elemente im XHTML-Namensraum, trotzdem funktionieren Pfade ohne Präfix. In echten XML-Dokumenten mit Standard-Namensraum braucht man dagegen einen Resolver mit Präfix.
  • Die Schnittstelle wird von allen modernen Browsern unterstützt. In Node.js gibt es sie nicht nativ, dort helfen Bibliotheken wie jsdom oder xpath.
  • Sicherheit: Baue keine Benutzereingaben ungeprüft in Ausdrücke ein. Das kann zu einer XPath-Injection führen.