Start · Sprachen · JavaScript · Referenz · XPathEvaluator.evaluate()

XPathEvaluator.evaluate()

Methode

Führt einen XPath-Ausdruck auf einem Knoten oder Dokument aus und gibt das Ergebnis als <code>XPathResult</code> zurück.

seit JavaScript Baseline: alle Browser (DOM Level 3 XPath) Kategorie: webapi

Signatur

XPathEvaluator.prototype.evaluate(expression, contextNode, resolver, type, result)

Beschreibung

Die Methode evaluate() der Schnittstelle XPathEvaluator wertet einen XPath-1.0-Ausdruck relativ zu einem Kontextknoten aus. Je nach angefordertem Ergebnistyp bekommst du eine Zahl, eine Zeichenkette, einen Wahrheitswert, einen einzelnen Knoten oder eine Knotenmenge (als Iterator oder Snapshot) zurück, jeweils verpackt in ein XPathResult-Objekt.

Nützlich ist XPath immer dann, wenn CSS-Selektoren nicht ausreichen: etwa beim Suchen nach Textinhalten (//button[contains(., "Speichern")]), beim Navigieren zu Eltern- oder Geschwisterknoten (.., following-sibling::), bei Berechnungen wie count() oder sum() und beim Durchsuchen von XML-Dokumenten, die per DOMParser oder fetch geladen wurden.

Funktional ist die Methode identisch mit Document.prototype.evaluate(). Ein eigenständiger new XPathEvaluator() lohnt sich vor allem, wenn du Ausdrücke mit createExpression() vorkompilieren willst oder unabhängig von einem bestimmten Dokument arbeitest.

Parameter

Name Typ Default Beschreibung
$expression Pflicht string Der auszuwertende XPath-Ausdruck (XPath 1.0).
$contextNode Pflicht Node Knoten, relativ zu dem der Ausdruck ausgewertet wird, meist document oder ein Element.
$resolver XPathNSResolver|Function|null null Löst Namensraum-Präfixe im Ausdruck zu URIs auf. Entweder eine Funktion (prefix) => uri, ein Objekt mit lookupNamespaceURI() oder null, wenn keine Präfixe verwendet werden.
$type number XPathResult.ANY_TYPE (0) Gewünschter Ergebnistyp, z. B. XPathResult.NUMBER_TYPE, STRING_TYPE, BOOLEAN_TYPE, ORDERED_NODE_SNAPSHOT_TYPE, FIRST_ORDERED_NODE_TYPE oder ORDERED_NODE_ITERATOR_TYPE.
$result XPathResult|null null Ein vorhandenes XPathResult zur Wiederverwendung. In der Praxis fast immer null.

Rückgabewert

Typ
XPathResult
Beschreibung
Ein XPathResult-Objekt. Welche Eigenschaft gilt (numberValue, stringValue, booleanValue, singleNodeValue, snapshotItem(), iterateNext()), hängt von resultType ab.

Beispiele

Button anhand seines Textes finden

const evaluator = new XPathEvaluator();

const result = evaluator.evaluate(
  '//button[normalize-space(.)="Speichern"]',
  document,
  null,
  XPathResult.FIRST_ORDERED_NODE_TYPE,
  null
);

const button = result.singleNodeValue;
console.log(button ? button.outerHTML : 'Kein Button gefunden');
<button type="submit">Speichern</button>

Alle Links als Snapshot einsammeln

const evaluator = new XPathEvaluator();
const snapshot = evaluator.evaluate(
  '//a[starts-with(@href, "https://")]',
  document,
  null,
  XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
  null
);

const urls = [];
for (let i = 0; i < snapshot.snapshotLength; i++) {
  urls.push(snapshot.snapshotItem(i).href);
}
console.log(`${urls.length} externe Links`, urls);
3 externe Links ["https://example.com/", ...]

Berechnung in einem geparsten XML-Dokument

const xml = `<bestellung>
  <posten preis="19.90"/>
  <posten preis="5.10"/>
  <posten preis="25.00"/>
</bestellung>`;

const doc = new DOMParser().parseFromString(xml, 'application/xml');
const evaluator = new XPathEvaluator();

const summe = evaluator.evaluate(
  'sum(/bestellung/posten/@preis)',
  doc,
  null,
  XPathResult.NUMBER_TYPE,
  null
).numberValue;

const anzahl = evaluator.evaluate('count(//posten)', doc, null, XPathResult.NUMBER_TYPE, null).numberValue;
console.log(`${anzahl} Posten, Summe: ${summe.toFixed(2)} €`);
3 Posten, Summe: 50.00 €

Namensräume mit einem Resolver auflösen

const xml = `<feed xmlns="http://www.w3.org/2005/Atom">
  <entry><title>Erster Beitrag</title></entry>
  <entry><title>Zweiter Beitrag</title></entry>
</feed>`;

const doc = new DOMParser().parseFromString(xml, 'application/xml');
const resolver = (prefix) => (prefix === 'atom' ? 'http://www.w3.org/2005/Atom' : null);

const iter = new XPathEvaluator().evaluate(
  '//atom:entry/atom:title',
  doc,
  resolver,
  XPathResult.ORDERED_NODE_ITERATOR_TYPE,
  null
);

let node;
while ((node = iter.iterateNext())) {
  console.log(node.textContent);
}
Erster Beitrag Zweiter Beitrag

// Wichtig · Fallstricke

  • Iterator ungültig nach DOM-Änderung: Bei *_ITERATOR_TYPE wirft iterateNext() einen InvalidStateError, wenn das Dokument während der Iteration verändert wird. Willst du gefundene Knoten verändern oder entfernen, nimm ORDERED_NODE_SNAPSHOT_TYPE.
  • Falscher Ergebnistyp: Greifst du auf eine Eigenschaft zu, die nicht zum resultType passt (z. B. numberValue bei einer Knotenmenge), wird ein TypeError geworfen. Bei ANY_TYPE immer result.resultType prüfen.
  • Namensräume: In XML-Dokumenten mit Standard-Namensraum (z. B. XHTML, Atom, SVG) findet //entry nichts. Hier brauchst du ein Präfix und einen Resolver. In HTML-Dokumenten können Elementnamen dagegen ohne Präfix verwendet werden.
  • Nur XPath 1.0: Browser unterstützen ausschließlich XPath 1.0, also keine Funktionen wie matches(), lower-case() oder Sequenzen aus XPath 2.0/3.x.
  • Ungültige Ausdrücke lösen eine SyntaxError-DOMException aus. Deshalb Ausdrücke aus Benutzereingaben in try…catch auswerten und nie ungeprüft per Zeichenkettenverkettung zusammenbauen (XPath-Injection).
  • Kompatibilität: Wird von allen modernen Browsern unterstützt. Der Internet Explorer kannte die Methode nicht. Node.js hat kein eingebautes DOM/XPath, dort brauchst du Bibliotheken wie jsdom oder xpath.
  • Leistung: Wird derselbe Ausdruck oft ausgewertet, kompiliere ihn einmal mit createExpression() vor und rufe dann XPathExpression.evaluate() auf.