Signatur
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./liausgewertet werden.type(number, optional, StandardXPathResult.ANY_TYPE= 0): gewünschter Ergebnistyp, etwaXPathResult.ORDERED_NODE_SNAPSHOT_TYPEoderXPathResult.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
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}`);
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);
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`);
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);
// Wichtig · Fallstricke
- Kein Konstruktor:
new XPathExpression()löst einenTypeErroraus. Einen Ausdruck erhält man nur übercreateExpression(). - Syntaxfehler werden schon beim Kompilieren gemeldet:
createExpression()wirft dann eineDOMExceptionvom TypSyntaxError. Unbekannte Namensraum-Präfixe führen zu einemNamespaceError. - Ergebnisse vom Typ
*_ITERATOR_TYPEwerden ungültig, sobald sich das DOM ändert. Wer beim Durchlaufen Knoten verändert, sollte deshalb*_SNAPSHOT_TYPEverwenden. - Unterstützt wird nur XPath 1.0, also keine Funktionen aus XPath 2.0 oder 3.x wie
matches()oderlower-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
jsdomoderxpath. - Sicherheit: Baue keine Benutzereingaben ungeprüft in Ausdrücke ein. Das kann zu einer XPath-Injection führen.