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

XPathEvaluator.createExpression()

Methode

Kompiliert einen XPath-Ausdruck zu einem <code>XPathExpression</code>-Objekt, das sich beliebig oft und effizient gegen verschiedene Kontextknoten auswerten lässt.

seit JavaScript Baseline: alle Browser Kategorie: webapi

Signatur

XPathEvaluator.prototype.createExpression(expression, resolver)

Beschreibung

createExpression() übersetzt einen XPath-Ausdruck als Zeichenkette in ein vorkompiliertes XPathExpression-Objekt. Anschließend führt man mit dessen Methode evaluate(contextNode, type, result) Abfragen aus, ohne dass der Ausdruck jedes Mal neu geparst wird.

Das lohnt sich vor allem, wenn derselbe Ausdruck oft ausgewertet wird, zum Beispiel in Schleifen über viele Knoten, bei der Verarbeitung großer XML-Dokumente oder bei wiederholten Abfragen auf dynamisch geänderten DOM-Bäumen. Für einmalige Abfragen reicht meist document.evaluate().

Die Methode gibt es auf XPathEvaluator-Instanzen (new XPathEvaluator()) und genauso direkt auf document, weil Document die gleiche Schnittstelle umsetzt. Nutzt der Ausdruck Namensraum-Präfixe (etwa bei XHTML, SVG oder eigenen XML-Formaten), muss als zweites Argument ein Namespace-Resolver übergeben werden, der Präfixe auf Namensraum-URIs abbildet.

Syntaktische Fehler im Ausdruck fallen schon beim Kompilieren auf: createExpression() wirft dann sofort eine DOMException, und zwar nicht erst beim Auswerten.

Parameter

Name Typ Default Beschreibung
$expression Pflicht string Der zu kompilierende XPath-Ausdruck (XPath 1.0), z. B. //li[@class='aktiv'].
$resolver XPathNSResolver | ((prefix: string) => string | null) | null null Löst Namensraum-Präfixe im Ausdruck auf. Möglich sind eine Funktion, ein Objekt mit Methode lookupNamespaceURI(prefix) oder ein DOM-Knoten (etwa das Ergebnis von createNSResolver()). Für Ausdrücke ohne Präfixe kann man ihn weglassen oder null übergeben.

Rückgabewert

Typ
XPathExpression
Beschreibung
Ein kompiliertes XPathExpression-Objekt. Seine Methode evaluate(contextNode, type, result) liefert ein XPathResult.

Beispiele

Ausdruck einmal kompilieren, mehrfach auswerten

const evaluator = new XPathEvaluator();
const expr = evaluator.createExpression('.//a[@href]');

// Links in jedem Artikel zählen – der Ausdruck wird nur einmal geparst
for (const article of document.querySelectorAll('article')) {
  const result = expr.evaluate(article, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  console.log(`${article.id}: ${result.snapshotLength} Links`);
}
intro: 3 Links news: 5 Links

Zahlenwert aus einem XML-Dokument berechnen

const xml = new DOMParser().parseFromString(
  `<bestellung>
     <posten preis="12.5" menge="2"/>
     <posten preis="4" menge="3"/>
   </bestellung>`,
  'application/xml'
);

const summePreise = document.createExpression('sum(//posten/@preis)');
const anzahl = document.createExpression('count(//posten)');

const summe = summePreise.evaluate(xml, XPathResult.NUMBER_TYPE).numberValue;
const n = anzahl.evaluate(xml, XPathResult.NUMBER_TYPE).numberValue;
console.log(summe, n);
16.5 2

Namensräume mit einem Resolver auflösen

const xml = new DOMParser().parseFromString(
  `<feed xmlns="http://www.w3.org/2005/Atom">
     <entry><title>Erster Beitrag</title></entry>
     <entry><title>Zweiter Beitrag</title></entry>
   </feed>`,
  'application/xml'
);

const ns = { atom: 'http://www.w3.org/2005/Atom' };
const resolver = (prefix) => ns[prefix] ?? null;

const expr = new XPathEvaluator().createExpression('//atom:entry/atom:title', resolver);
const it = expr.evaluate(xml, XPathResult.ORDERED_NODE_ITERATOR_TYPE);

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

Syntaxfehler früh abfangen

const compile = (xpath) => {
  try {
    return document.createExpression(xpath);
  } catch (err) {
    console.error(`Ungültiger XPath "${xpath}": ${err.name}`);
    return null;
  }
};

compile('//div[@id=');
Ungültiger XPath "//div[@id=": SyntaxError

// Wichtig · Fallstricke

  • Nur XPath 1.0: Browser können ausschließlich XPath 1.0. Funktionen aus XPath 2.0 und neuer (z. B. matches(), lower-case()) werfen einen Fehler.
  • Standard-Namensraum: Hat ein XML-Dokument einen Standard-Namensraum (xmlns="…"), findet //entry nichts. Man muss ein Präfix verwenden und es über den Resolver auflösen. In HTML-Dokumenten, die als text/html geladen wurden, ist das bei HTML-Elementen nicht nötig.
  • Fehlerarten: Ungültige Syntax führt zu einer DOMException vom Typ SyntaxError. Ein nicht auflösbares Präfix führt zu NamespaceError.
  • Iterator-Ergebnisse: Ändert sich das DOM, während man über ein *_ITERATOR_TYPE-Ergebnis läuft, wird der Iterator ungültig und iterateNext() wirft einen Fehler. Wer das DOM verändert, sollte *_SNAPSHOT_TYPE verwenden.
  • Sicherheit: Baut man Ausdrücke aus Benutzereingaben per String-Verkettung, ist XPath-Injection möglich. Werte sollten korrekt maskiert werden, besonders Anführungszeichen.
  • In allen modernen Browsern verfügbar. Node.js hat die Methode nicht eingebaut, dort braucht man Bibliotheken wie jsdom oder xpath.