Signatur
Beschreibung
Die Methode iterateNext() des Interfaces XPathResult liefert Schritt für Schritt die Knoten eines Knotensatz-Ergebnisses, das mit document.evaluate() erzeugt wurde. Jeder Aufruf gibt den nächsten Knoten zurück. Wenn keine Knoten mehr übrig sind, ist der Rückgabewert null. So lassen sich alle Treffer eines XPath-Ausdrucks ganz einfach in einer while-Schleife abarbeiten.
Die Methode funktioniert nur bei Ergebnissen vom Typ XPathResult.UNORDERED_NODE_ITERATOR_TYPE (4) oder XPathResult.ORDERED_NODE_ITERATOR_TYPE (5). Übergibt man XPathResult.ANY_TYPE (0) und liefert der Ausdruck einen Knotensatz, wählt der Browser automatisch einen Iterator-Typ. Bei Snapshot-Typen verwendet man stattdessen snapshotItem() und snapshotLength.
Iteratoren sind live an das Dokument gebunden: Ändert sich das Dokument während der Iteration, wird der Iterator ungültig (invalidIteratorState wird true). Der nächste Aufruf von iterateNext() wirft dann einen Fehler. Wer beim Durchlaufen Knoten verändern oder entfernen will, sollte deshalb zuerst alle Knoten sammeln oder gleich einen Snapshot-Typ verwenden.
Rückgabewert
Node im Ergebnis oder null, wenn keine weiteren Knoten vorhanden sind.Beispiele
Alle Links einer Seite durchlaufen
const result = document.evaluate(
'//a[@href]',
document,
null,
XPathResult.ORDERED_NODE_ITERATOR_TYPE,
null
);
let node;
while ((node = result.iterateNext()) !== null) {
console.log(node.textContent.trim(), '→', node.href);
}
Treffer sammeln und danach das DOM ändern
// Erst sammeln: Änderungen während der Iteration würden den Iterator ungültig machen
const collectNodes = (xpath, context = document) => {
const result = document.evaluate(
xpath, context, null,
XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null
);
const nodes = [];
for (let n = result.iterateNext(); n; n = result.iterateNext()) {
nodes.push(n);
}
return nodes;
};
const emptyParagraphs = collectNodes('//p[not(normalize-space())]');
emptyParagraphs.forEach((p) => p.remove());
console.log(`${emptyParagraphs.length} leere Absätze entfernt`);
XML-Antwort auswerten und ungültigen Iterator abfangen
const xml = new DOMParser().parseFromString(
'<buecher><buch preis="12">JS</buch><buch preis="30">DOM</buch></buecher>',
'application/xml'
);
const result = xml.evaluate('//buch[@preis > 10]', xml, null, XPathResult.ANY_TYPE, null);
try {
let buch = result.iterateNext();
while (buch) {
console.log(buch.textContent, buch.getAttribute('preis'));
buch = result.iterateNext();
}
} catch (err) {
// Tritt auf, wenn das Dokument während der Iteration geändert wurde
console.error('Iterator ungültig:', err.name);
}
// Wichtig · Fallstricke
- Falscher Ergebnistyp: Wird
iterateNext()auf einem Ergebnis aufgerufen, das kein Iterator-Typ ist (z. B.NUMBER_TYPEoderORDERED_NODE_SNAPSHOT_TYPE), wirft der Browser einenTypeError(früherXPathExceptionmit CodeTYPE_ERR). - Dokumentänderungen: Wird das Dokument während der Iteration verändert, ist
invalidIteratorStatetrueunditerateNext()wirft eineDOMExceptionvom TypInvalidStateError. Beim Bearbeiten von Knoten deshalb erst sammeln oderORDERED_NODE_SNAPSHOT_TYPEverwenden. UNORDERED_NODE_ITERATOR_TYPEgarantiert keine Reihenfolge nach Dokumentposition. Wenn die Reihenfolge wichtig ist,ORDERED_NODE_ITERATOR_TYPEnutzen.- Ein Iterator lässt sich nicht zurücksetzen. Für einen erneuten Durchlauf muss
evaluate()noch einmal aufgerufen werden. - Kompatibilität: Die Methode wird von allen modernen Browsern unterstützt, aber nicht von Node.js ohne DOM-Bibliothek (z. B. jsdom). Bei HTML-Dokumenten mit Namespaces (SVG, XHTML-XML) braucht man eventuell einen Namespace-Resolver.