Exemple de XPath en JavaScript
J'ai un vieux tableau dans lequel j'aimerais cocher les cases de toutes les lignes qui ont un lien qui commence par 2021 :
Ce n'est pas possible simplement avec document.querySelectorAll. Voici le code JS simplifié qui utilise XPath en partant du principe que rien d'autre ne va modifier la page pendant son exécution :
var iterateur = document.evaluate("//td/a[starts-with(., '2021')]/../preceding-sibling::td/input", document); var nœud = iterateur.iterateNext(); while (nœud) { nœud.checked = true; nœud = iterateur.iterateNext(); }
Mais si je veux aussi au passage mettre sur fond vert tous les liens qui commencent par 2021, je modifie le document et ça lance une exception :
DOMException: XPathResult.iterateNext: The document has been mutated since the result was returned
var iterateur = document.evaluate("//td/a[starts-with(., '2021')]", document); var nœud = iterateur.iterateNext(); while (nœud) { nœud.style = 'background: limegreen'; var ite2 = document.evaluate("../preceding-sibling::td/input", nœud); var n2 = ite2.iterateNext(); n2.checked = true; nœud = iterateur.iterateNext(); }
Dans ce cas, il faut que je demande un cliché (snapshot) du DOM :
var cliché = document.evaluate("//td/a[starts-with(., '2021')]", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE); for (var i = 0; i < cliché.snapshotLength; i++) { var nœud = cliché.snapshotItem(i); nœud.style = 'background: limegreen'; var itérateur = document.evaluate("../preceding-sibling::td/input", nœud); var n2 = itérateur.iterateNext(); n2.checked = true; }
Note au passage : si je veux cocher les cases dont les liens se terminent par 2021, je ne peux malheureusement pas utiliser ends-with
dans le navigateur parce que c'est une fonction XPath 2.0 et les navigateurs ne gèrent que XPath 1.0 donc il faut ruser avec
//td/a[substring(., string-length(.) - string-length('2021') + 1) = '2021']/../preceding-sibling::td/input
😕
cf référence XPath sur MDN