web-dev-qa-db-fra.com

Comment utiliser document.evaluate () et XPath pour obtenir une liste d'éléments?

J'utilise la méthode JavaScript document.evaluate() pour obtenir un élément pointé par une expression XPath:

var element = document.evaluate(path, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;

Mais comment puis-je obtenir une liste d'éléments au cas où l'expression XPath pointe vers plus d'un élément sur la page?

J'ai essayé le code suivant, mais cela ne fonctionne pas:

var element = document.evaluate(path, document, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
12
Abhishek Tripathi

J'ai trouvé la solution suivante dans le livre je suis en train de lire. Il dit que le code provient de Bibliothèque de prototypes .

function getElementsByXPath(xpath, parent)
{
    let results = [];
    let query = document.evaluate(xpath, parent || document,
        null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
    for (let i = 0, length = query.snapshotLength; i < length; ++i) {
        results.Push(query.snapshotItem(i));
    }
    return results;
}

Utilisez-le comme ceci:

let items = getElementsByXPath("//*"); // return all elements on the page
14
Jenny O'Reilly

De la documentation

var iterator = document.evaluate('//phoneNumber', documentNode, null, XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null );

try {
  var thisNode = iterator.iterateNext();

  while (thisNode) {
    alert( thisNode.textContent );
    thisNode = iterator.iterateNext();
  } 
}
catch (e) {
  dump( 'Error: Document tree modified during iteration ' + e );
}
3
kernowcode

Je travaillais dur avec le même problème il y a quelques semaines. J'ai découvert que le résultat représente déjà une liste d'éléments (le cas échéant) et que l'on peut le parcourir. J'avais besoin de construire un plugin jQuery pour réaliser une recherche de chaînes de texte partielles ou complètes, ce qui signifie le texte intérieur de tout élément DOM comme LI ou H2. J'ai eu la compréhension initiale sur sa page: Document.evaluate () | MDN

Après quelques heures, j'ai lancé le plugin: Recherchez le mot "architecture" uniquement dans les éléments "p", recherchez des chaînes de correspondance partielles ("true" pour <p>todays architecture in Europe</p>) au lieu des correspondances de texte entier (<h2>architecture</h2>).

var found = $('div#pagecontent').findtext('architecture','p',true);

Les résultats trouvés sont des objets jQuery classiques, qui peuvent être utilisés normalement.

found.css({ backgroundColor: 'tomato'});

L'exemple d'utilisation ci-dessus peut être modifié comme ceci pour la recherche dans tout le document et tous les types de nœuds comme celui-ci (résultats partiels).

var found = $('body').findtext('architecture','',true);

ou seulement des correspondances exactes

var found = $('div#pagecontent').findtext('architecture');

Le plugin lui-même affiche une variable "es" qui est le pluriel d'un seul "e" pour "élément". Et vous pouvez voir comment les résultats sont itérés et rassemblés dans un groupe d'objets avec f = f.add($(e)) (où "f" signifie "trouvé"). Le début de la fonction traite différentes conditions, telles que la recherche complète ou partielle ("c" pour la condition) et la plage de documents pour la recherche ("d").

Il peut être optimisé au besoin, peut ne pas représenter le maximum de possibilités, mais il représente mes meilleures connaissances actuelles, fonctionne sans erreurs et peut éventuellement répondre à votre question. Et le voici:

(function($) {
    $.fn.findtext = function(s,t,p) {
        var c, d;
        if (!this[0]) d = document.body;
        else d = this[0];
        if (!t || typeof t !== 'string' || t == '') t = '*';
        if (p === true) c = './/'+t+'[contains(text(), "'+s+'")]';
        else c = './/'+t+'[. = "'+s+'"]';
        var es = document.evaluate(c, d, null, XPathResult.ANY_TYPE, null); 
        var e = es.iterateNext();
        var f = false;
        while (e) {
            if (!f) f = $(e);
            else f = f.add($(e));
            e = es.iterateNext();
        }
        return f || $();
    };
})(jQuery);
0
ddlab