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

Document.evaluate()

Methode

Wertet einen XPath-Ausdruck relativ zu einem Kontextknoten aus und liefert das Ergebnis als <code>XPathResult</code> (Knotenmenge, Zahl, String oder Boolean).

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

Signatur

Document.prototype.evaluate(xpathExpression, contextNode, namespaceResolver, resultType, result)

Beschreibung

document.evaluate() führt einen XPath-1.0-Ausdruck gegen ein HTML- oder XML-Dokument aus. Im Gegensatz zu querySelectorAll() kann XPath Knoten auch anhand ihres Textinhalts auswählen, in der Baumstruktur nach oben navigieren (ancestor::, parent::), Geschwister gezielt ansprechen und direkt Werte wie Zahlen oder Strings berechnen (count(), string(), sum()).

Das Ergebnis ist immer ein XPathResult-Objekt. Welche Eigenschaften oder Methoden darauf sinnvoll sind, hängt vom gewählten resultType ab: singleNodeValue für Einzelknoten, snapshotItem(i)/snapshotLength für Snapshots, iterateNext() für Iteratoren sowie numberValue, stringValue und booleanValue für primitive Ergebnisse.

Typische Einsatzgebiete sind Web-Scraping, Browser-Erweiterungen, End-to-End-Tests, das Auswerten von per DOMParser geladenen XML-Dokumenten (RSS, SVG, XHTML) sowie Fälle, in denen CSS-Selektoren nicht ausdrucksstark genug sind.

Parameter

Name Typ Default Beschreibung
$xpathExpression Pflicht string Der auszuwertende XPath-1.0-Ausdruck, z. B. //a[@href] oder count(//li).
$contextNode Pflicht Node Knoten, relativ zu dem der Ausdruck ausgewertet wird. Relevant für relative Pfade wie ./td; meist document.
$namespaceResolver XPathNSResolver|Function|null null Funktion, die Namensraum-Präfixe (z. B. svg) auf Namensraum-URIs abbildet. Für normales HTML null.
$resultType number XPathResult.ANY_TYPE (0) Konstante aus XPathResult, z. B. ORDERED_NODE_SNAPSHOT_TYPE, FIRST_ORDERED_NODE_TYPE, ORDERED_NODE_ITERATOR_TYPE, NUMBER_TYPE, STRING_TYPE, BOOLEAN_TYPE.
$result XPathResult|null null Vorhandenes XPathResult zur Wiederverwendung. In der Praxis fast immer null.

Rückgabewert

Typ
XPathResult
Beschreibung
Ein XPathResult, dessen Inhalt vom resultType abhängt. Bei ANY_TYPE wählt der Browser den natürlichen Typ (Knotenmengen werden zu UNORDERED_NODE_ITERATOR_TYPE).

Beispiele

Button anhand seines Textes finden

// HTML: <button>Abbrechen</button><button>Speichern</button>
const result = document.evaluate(
  "//button[normalize-space(text())='Speichern']",
  document,
  null,
  XPathResult.FIRST_ORDERED_NODE_TYPE,
  null
);

const saveButton = result.singleNodeValue;
console.log(saveButton?.textContent);
Speichern

Alle externen Links als Snapshot sammeln

const $x = (xpath, context = document) => {
  const snap = document.evaluate(
    xpath, context, null,
    XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null
  );
  return Array.from({ length: snap.snapshotLength }, (_, i) => snap.snapshotItem(i));
};

const externalLinks = $x("//a[starts-with(@href, 'http') and not(contains(@href, location.host))]");
// Snapshot bleibt stabil, auch wenn wir das DOM verändern
externalLinks.forEach((a) => a.setAttribute('rel', 'noopener noreferrer'));
console.log(`${externalLinks.length} externe Links markiert`);
3 externe Links markiert

Zahlen und Strings direkt berechnen

const count = document.evaluate(
  'count(//table[@id="orders"]/tbody/tr)',
  document, null, XPathResult.NUMBER_TYPE, null
).numberValue;

const title = document.evaluate(
  'string(//h1)', document, null, XPathResult.STRING_TYPE, null
).stringValue;

console.log(count, title);
12 "Bestellübersicht"

XML mit Namensraum auswerten (DOMParser)

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 === 'a' ? 'http://www.w3.org/2005/Atom' : null);

const iter = doc.evaluate('//a:entry/a: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

  • Nur XPath 1.0: Funktionen aus XPath 2.0/3.x wie matches(), lower-case() oder ends-with() gibt es nicht; Groß-/Kleinschreibung lässt sich nur mit translate() umgehen.
  • Iteratoren sind fragil: Wird das DOM verändert, während ein *_ITERATOR_TYPE-Ergebnis durchlaufen wird, wirft iterateNext() eine InvalidStateError-Ausnahme. Zum Verändern von Knoten besser ORDERED_NODE_SNAPSHOT_TYPE verwenden.
  • Falscher Zugriff je nach Typ: Wer z. B. singleNodeValue auf einem Snapshot-Ergebnis liest, bekommt einen TypeError. Den resultType also immer ausdrücklich angeben, statt sich auf ANY_TYPE zu verlassen.
  • Namensräume: In XML-Dokumenten mit Standard-Namensraum (Atom, SVG, XHTML) findet //entry nichts. Nötig sind ein Präfix und ein namespaceResolver. In HTML-Dokumenten werden HTML-Elemente dagegen ohne Präfix gefunden.
  • Sicherheit: Nutzereingaben nie ungeprüft in XPath-Ausdrücke einsetzen (XPath-Injection). Anführungszeichen maskieren oder das Ergebnis erst nachträglich in JavaScript filtern.
  • Leistung: Für einfache Abfragen ist querySelector() meist schneller und besser lesbar. // am Anfang durchsucht das ganze Dokument, deshalb besser einen engen contextNode mit relativem Pfad (.//) nutzen.
  • Kompatibilität: Wird von allen modernen Browsern unterstützt, im Internet Explorer gab es das nicht. In Node.js fehlt es ohne DOM-Bibliothek; jsdom bringt es mit.