Start · Sprachen · JavaScript · Referenz · XPathEvaluator

XPathEvaluator

Schnittstelle

Das <code>XPathEvaluator</code>-Interface kompiliert und wertet XPath-1.0-Ausdrücke gegen HTML- oder XML-Dokumente aus.

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

Signatur

interface XPathEvaluator

Beschreibung

Mit XPathEvaluator werden XPath-Ausdrücke auf einen DOM-Baum angewendet. Das Interface hat drei Methoden: evaluate() wertet einen Ausdruck direkt aus, createExpression() kompiliert ihn zu einem wiederverwendbaren XPathExpression-Objekt und createNSResolver() liefert einen Resolver für Namensraum-Präfixe. Eine eigenständige Instanz legt man mit new XPathEvaluator() an.

Auch Document stellt diese Methoden bereit. Deshalb schreibt man in der Praxis meist einfach document.evaluate(...). Eine eigene XPathEvaluator-Instanz lohnt sich vor allem, wenn man Ausdrücke vorkompilieren und oft wiederverwenden will oder mit Dokumenten aus DOMParser bzw. XMLHttpRequest.responseXML arbeitet.

XPath kann mehr als CSS-Selektoren: Man kann nach Textinhalt suchen (contains(text(), "…")), auf Vorfahren zugreifen (ancestor::, ..) und Zahlen, Zeichenketten oder Wahrheitswerte berechnen (count(), sum()). Die Browser unterstützen nur XPath 1.0.

Parameter

Name Typ Default Beschreibung
$expression Pflicht string Der XPath-1.0-Ausdruck. Gilt für evaluate() und createExpression().
$contextNode Pflicht Node Der Kontextknoten, von dem aus der Ausdruck ausgewertet wird. Nur bei evaluate(), z. B. document.
$resolver XPathNSResolver | ((prefix: string) => string | null) | null null Ordnet Namensraum-Präfixen ihre URI zu. Bei HTML-Dokumenten ohne Präfixe genügt null.
$type number XPathResult.ANY_TYPE (0) Gewünschter Ergebnistyp, z. B. XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, FIRST_ORDERED_NODE_TYPE, NUMBER_TYPE oder STRING_TYPE.
$result XPathResult | null null Ein vorhandenes XPathResult, das wiederverwendet werden soll. Browser ignorieren diesen Wert meist und liefern ein neues Objekt.

Rückgabewert

Typ
XPathEvaluator
Beschreibung
new XPathEvaluator() gibt eine neue Instanz zurück. evaluate() liefert ein XPathResult, createExpression() ein XPathExpression und createNSResolver() einen XPathNSResolver.

Beispiele

Instanz erzeugen und alle Links mit bestimmtem Text finden

const evaluator = new XPathEvaluator();

// Alle Links, deren Text "Impressum" enthält
const result = evaluator.evaluate(
  '//a[contains(normalize-space(.), "Impressum")]',
  document,
  null,
  XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
  null
);

for (let i = 0; i < result.snapshotLength; i++) {
  console.log(result.snapshotItem(i).href);
}
https://example.com/impressum

Ausdruck vorkompilieren und mehrfach verwenden

const evaluator = new XPathEvaluator();
const expr = evaluator.createExpression('count(.//li[@class="done"])');

// Dieselbe kompilierte Abfrage auf mehrere Listen anwenden
document.querySelectorAll('ul.todo').forEach((list) => {
  const done = expr.evaluate(list, XPathResult.NUMBER_TYPE).numberValue;
  console.log(`${list.id}: ${done} erledigt`);
});
arbeit: 3 erledigt privat: 1 erledigt

XML mit Namensräumen aus DOMParser auswerten

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 evaluator = new XPathEvaluator();

// Das Standard-Namespace braucht in XPath 1.0 ein eigenes Präfix
const resolver = (prefix) =>
  prefix === 'atom' ? 'http://www.w3.org/2005/Atom' : null;

const first = evaluator.evaluate(
  '/atom:feed/atom:entry[1]/atom:title',
  doc,
  resolver,
  XPathResult.FIRST_ORDERED_NODE_TYPE,
  null
).singleNodeValue;

console.log(first.textContent);
Erster Beitrag

// Wichtig · Fallstricke

  • Nur XPath 1.0: Funktionen aus XPath 2.0 oder neuer wie matches(), lower-case() oder ends-with() gibt es nicht. Wer sie benutzt, bekommt eine SyntaxError-DOMException.
  • Iteratoren sind fragil: Ändert sich das DOM, während man über ein Ergebnis vom Typ *_ITERATOR_TYPE läuft, wirft iterateNext() einen InvalidStateError. Wenn man während der Schleife Knoten ändert, besser ORDERED_NODE_SNAPSHOT_TYPE verwenden.
  • Standard-Namespaces: In XML-Dokumenten mit xmlns="…" findet //title nichts. Man braucht einen Resolver mit eigenem Präfix. In HTML-Dokumenten gilt diese Einschränkung nicht, dort funktionieren Ausdrücke ohne Präfix.
  • createNSResolver() gibt heute nur noch den übergebenen Knoten zurück. Man kann stattdessen direkt eine Funktion übergeben.
  • Sicherheit: Baue XPath-Ausdrücke nicht per Zeichenkettenverkettung aus Benutzereingaben zusammen. Sonst drohen XPath-Injections, also Abfragen, die mehr oder andere Knoten liefern als gedacht. Eingaben vorher prüfen oder Anführungszeichen korrekt maskieren.
  • Unterstützt von allen modernen Browsern. In Node.js gibt es das Interface nicht von Haus aus, dort braucht man z. B. jsdom oder xpath.