Signatur
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
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);
}
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`);
});
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);
// Wichtig · Fallstricke
- Nur XPath 1.0: Funktionen aus XPath 2.0 oder neuer wie
matches(),lower-case()oderends-with()gibt es nicht. Wer sie benutzt, bekommt eineSyntaxError-DOMException. - Iteratoren sind fragil: Ändert sich das DOM, während man über ein Ergebnis vom Typ
*_ITERATOR_TYPEläuft, wirftiterateNext()einenInvalidStateError. Wenn man während der Schleife Knoten ändert, besserORDERED_NODE_SNAPSHOT_TYPEverwenden. - Standard-Namespaces: In XML-Dokumenten mit
xmlns="…"findet//titlenichts. 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.
jsdomoderxpath.