Différents résultats sélectionnant des éléments HTML avec XPath dans Firefox et Internet Explorer

J'essaie de sélectionner un élément HTML spécifique dans un document, pour Firefox je viens d'utiliser:

xpathobj = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null); 

Qui fonctionne bien. Cependant, lorsque j'essaie IE équivavent:

 xmlDoc=new ActiveXObject("Microsoft.XMLDOM"); xmlDoc.async=false; xmlDoc.load(document); xmlDoc.setProperty("SelectionLanguage", "XPath"); xpathobj = xmlDoc.selectNodes(xpath); 

Je ne reçois aucun objet retourné. Donc, ma question est-il un moyen simple d'utiliser XPath pour accéder à l'élément que je veux dans IE? Le XPath que j'utilise ressemble à

 /HTML/BODY/DIV[9]/DIV[2] 

Consultez http://dev.abiss.gr/sarissa/ project. Ils ont migré la plupart des API liées à XML vers IE. Sinon, il est en effet également facile à mettre en œuvre. Les problèmes que vous devriez résoudre seraient: la sérialisation du HTML en XML valide, le résultat de synchronisation de la demande XMLDOM XPath avec le HTMLDOM d'origine. À ma connaissance, ils l'ont fait dans leur bibliothèque, mais sa performance aurait pu être meilleure.

Le problème peut être que dans IE5 + [1] est en fait [2] dans FF. Microsoft a uniquement décidé que la numérotation devrait commencer à [0] et non [1] comme spécifié par w3c.

Bonjour, à la fin, j'ai trouvé ma propre solution dodgy, toute suggestion pour l'améliorer serait très appréciée. Il utilise des fonctionnalités de prototypes:

Fonctionne dans IE5 + avec xpath de la forme "/ HTML / BODY / DIV [9] / DIV [2]"

Function getXPathElement (xpath, element) {

 //Specific to project, here i know that the body element will always have the id "top" //but otherwise the element that is passed in should be first element in the xpath //statement eg. /HTML/BODY/DIV the element passed in should be HTML if(!element){ element = $("top"); var xpathArrayIndex = 3; } else { var xpathArrayIndex = 1; } //split the xpath statement up var xpathArray = xpath.split("/"); var carryOn = true; while(carryOn){ decendents = element.childElements(); //check to see if we are at the end of the xpath statement if(xpathArrayIndex == xpathArray.length){ return element; } //if there is only one decendent make it the next element if(decendents.size() == 1) { element = decendents.first(); } else { //otherwise search the decendents for the next element element = getXPathElementByIndex(decendents, xpathArray[xpathArrayIndex]); } xpathArrayIndex++; } 

}

Function getXPathElementByIndex (decendents, xpathSegment) {

 var decendentsArray = decendents.toArray(); //seperate the index from the element name var temp = xpathSegment.split("["); var elementName = temp[0]; //get the index as a number eg. "9]" to 9 var elementIndex = +temp[1].replace("]", ""); //the number of matching elements var count = 0; //keeps track of the number of iterations var i = 0; while(count != elementIndex) { //if the decendent's name matches the xpath element name increment the count if(decendentsArray[i].nodeName == elementName){ count++; } i++; } var element = decendentsArray[i - 1]; return element; 

}

Merci à tous pour votre aide, de l'une ou l'autre façon, j'ai bien compris quelques exemples de javascript.

Il y a des bugs dans le code oly1234, j'essaie de le réparer comme suit:

 function getXPathElement(xpath, element){ if(!element){ element = document; } var xpathArray = xpath.split("/"); element = findXPathRoot(xpathArray[0],xpathArray[1],element); for(var i=1; i<xpathArray.length; i++){ if(xpathArray[i].toLowerCase()=="html"){ continue; } if(!element){ return element; } element = getXPathElementByIndex(element.childNodes,xpathArray[i]); } return element; } function findXPathRoot(rootPath,htmlPath,element){ if(rootPath == ""&&htmlPath.toLowerCase() == "html"){ return element.documentElement; } return document.getElementsByTagName(rootPath)[0]; } function getXPathElementByIndex(decendents, xpathSegment){ //seperate the index from the element name var temp = xpathSegment.split("["); var elementName = temp[0]; //get the index as a number eg. "9]" to 9 if(temp[1]){ var elementIndex = temp[1].replace("]", ""); }else{ var elementIndex = 1; } //the number of matching elements var count = 0; for(var i=0;i < decendents.length; i++){ if (decendents[i].nodeName.toLowerCase() == elementName.toLowerCase()) { count++; if(count==elementIndex){ return decendents[i]; } } } return null; } 

Êtes-vous sûr que X-Path est implémenté dans votre version d'Internet Explorer? Comme dans: quelle version utilisez-vous?

JQuery implémente un sous-ensemble compatible avec le navigateur des sélecteurs xPath avec un plug-in . Votre exemple "/ HTML / BODY / DIV [9] / DIV [2]" devrait fonctionner.

(Edit – corrigé grâce à Sergey Ilinsky)

Au lieu de faire

 xmlDoc.load(document); 

essayer

 xmlDoc.loadXML(document.body.outerHTML) 

Cela ne fonctionnerait vraiment que si votre document HTML était formaté aux normes XHTML. En outre, la balise BODY serait le noeud racine, donc vous devriez changer votre XPATH en "/ BODY / DIV [9] / DIV [2]"

Je serais un peu inquiet d'utiliser xml comme ça, car vous ne pouvez pas être sûr de la version (si aucune) de la DLL XML d'une personne. Il existe encore des entreprises qui utilisent IE5.0 en masse, et 5.5 a eu une implémentation XML particulièrement efficace.

Une autre implémentation JavaScript du W3C Dom Level 3 XPath se trouve sur Source Forge . Mais ne semble pas être actif.

Je ne peux pas trouver une solution simple et commune, vous pouvez écrire une fonction personnalisée pour implémenter un peu de xpath mais il est difficile d'obtenir une version complète de Internet Explorer 6 ou inférieure ….