48 votes

Comment calculer la position XPath d'un élément en utilisant Javascript ?

Disons que j'ai un gros fichier HTML avec différents types de balises, semblable à celui de StackOverflow que vous regardez en ce moment.

Maintenant, disons que vous cliquez sur un élément de la page, à quoi ressemblerait la fonction Javascript qui calcule le XPath le plus basique faisant référence à cet élément spécifique ?

Je sais qu'il y a une infinité de façons de faire référence à cet élément dans XPath, mais je cherche quelque chose qui regarde simplement l'arbre DOM, sans tenir compte des ID, des classes, etc.

Exemple :

<html>
<head><title>Fruit</title></head>
<body>
<ol>
  <li>Bananas</li>
  <li>Apples</li>
  <li>Strawberries</li>
</ol>
</body>
</html>

Disons que vous cliquez sur Pommes . La fonction Javascript renverrait le résultat suivant :

/html/body/ol/li[2]

Il s'agit en fait de remonter l'arbre DOM jusqu'à l'élément HTML.

Juste pour clarifier, le gestionnaire d'événement "on-click" n'est pas le problème. Je peux le faire fonctionner. Je ne sais simplement pas comment calculer la position de l'élément dans l'arbre DOM et la représenter sous forme de XPath.

PS Toute réponse avec ou sans l'utilisation de la bibliothèque JQuery est appréciée.

PPS Je suis complètement novice en matière de XPath, il se peut donc que j'aie fait une erreur dans l'exemple ci-dessus, mais vous aurez l'idée.

Modifié le 11 août 2010 : Il semble que quelqu'un d'autre ait posé une question similaire : générer/obtenir le Xpath pour un textnode sélectionné

7 votes

XPath utilise une indexation basée sur 1, donc c'est li[2] .

0 votes

Merci, j'ai modifié le code.

4voto

krock Points 13537

Il n'y a rien d'intégré pour obtenir le xpath d'un élément HTML, mais l'inverse est courant, par exemple en utilisant le sélecteur xpath de jQuery .

Si vous devez déterminer le xpath d'un élément HTML, vous devrez fournir une fonction personnalisée pour le faire. Voici quelques exemples de exemple javascript/jQuery impls pour calculer le xpath.

0 votes

En fait, j'utilise également le sélecteur XPath de jQuery, mais j'avais besoin d'un moyen pour que l'utilisateur génère lui-même un XPath. La deuxième page dont vous avez donné le lien contient quelques exemples intéressants. Merci.

0 votes

Exemple de lien javascript/jQuery n'est plus disponible

3voto

Juste pour le plaisir, un XPath 2.0 en une ligne mise en œuvre :

string-join(ancestor-or-self::*/concat(name(),
                                       '[',
                                       for $x in name() 
                                          return count(preceding-sibling::*
                                                          [name() = $x]) 
                                                 + 1,
                                       ']'),
            '/')

3voto

wadim Points 132

La solution ci-dessous est préférable si vous devez déterminer de manière fiable la valeur absolue de XPath d'un élément.

D'autres réponses s'appuient en partie sur l'identifiant de l'élément (ce qui n'est pas fiable car il peut y avoir plusieurs éléments avec des identifiants identiques) ou génèrent des XPaths qui spécifient en fait plus d'éléments que celui donné (en omettant par erreur l'index des frères et sœurs dans certaines circonstances).

Le code a été adapté à partir du code source de Firebug en corrigeant les problèmes mentionnés ci-dessus.

getXElementTreeXPath = function( element ) {
    var paths = [];

    // Use nodeName (instead of localName) so namespace prefix is included (if any).
    for ( ; element && element.nodeType == Node.ELEMENT_NODE; element = element.parentNode )  {
        var index = 0;

        for ( var sibling = element.previousSibling; sibling; sibling = sibling.previousSibling ) {
            // Ignore document type declaration.
            if ( sibling.nodeType == Node.DOCUMENT_TYPE_NODE ) {
                continue;
            }

            if ( sibling.nodeName == element.nodeName ) {
                ++index;
            }
        }

        var tagName = element.nodeName.toLowerCase();

        // *always* include the sibling index
        var pathIndex = "[" + (index+1) + "]";

        paths.unshift( tagName + pathIndex );
    }

    return paths.length ? "/" + paths.join( "/") : null;
};

1voto

stijn de ryck Points 291

Voir mon exemple qui va au moins essayer de raccourcir l'expression s'il y a un identifiant unique. Javascript obtient le XPath d'un noeud

0voto

Robusto Points 17430
function getPath(event) {
  event = event || window.event;

  var pathElements = [];
  var elem = event.currentTarget;
  var index = 0;
  var siblings = event.currentTarget.parentNode.getElementsByTagName(event.currentTarget.tagName);
  for (var i=0, imax=siblings.length; i<imax; i++) {
      if (event.currentTarget === siblings[i] {
        index = i+1; // add 1 for xpath 1-based
      }
  }

  while (elem.tagName.toLowerCase() != "html") {
    pathElements.unshift(elem.tagName);
    elem = elem.parentNode;
  }
  return pathElements.join("/") + "[" + index + "]";
}

MODIFIÉ POUR AJOUTER L'INFORMATION SUR L'INDEX DES FRÈRES ET SŒURS

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X