admin管理员组

文章数量:1221322

I'm trying to select a specific HTML element in a document, for firefox i just use:

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

which works fine. However when I try the IE equivilent:

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

I get no object returned. So my question is there an easy way to use XPath to get to the element I want in IE? The XPath I'm using looks like

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

I'm trying to select a specific HTML element in a document, for firefox i just use:

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

which works fine. However when I try the IE equivilent:

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

I get no object returned. So my question is there an easy way to use XPath to get to the element I want in IE? The XPath I'm using looks like

/HTML/BODY/DIV[9]/DIV[2]
Share Improve this question edited Dec 20, 2011 at 20:19 Wayne 60.4k15 gold badges135 silver badges128 bronze badges asked Oct 7, 2008 at 11:23 user11198user11198 1312 silver badges6 bronze badges
Add a comment  | 

10 Answers 10

Reset to default 3

Take a look at http://dev.abiss.gr/sarissa/ project. They have migrated most of XML-related APIs to IE. Otherwise it is indeed also easy to implement. The problems you would need to solve would be: serialization of HTML into valid XML, syncing result of XMLDOM XPath query with original HTMLDOM. To my knowledge they've done it in their library, however, its performance could have been better.

The problem may be that in IE5+ [1] is in fact [2] in FF. Microsoft solely decided that the numbering should start at [0] and not [1] as specified by w3c.

Hi well in the end i came up with my own dodgy solution, any sugestions on improving it would be greatly apreciated. It makes use of some prototype functionality:

Works in IE5+ with xpath of the form "/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;

}

Thanks to everyone for thier help, either way i learnt a fair bit about various javascript frameworks.

There are some bugs in oly1234's code I try to fix it as follows:

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;
}

Are you sure X-Path is implemented in your version of Internet Explorer? As in: what version are you using?

jQuery implements a cross-browser-compatible subset of xPath selectors with a plug-in. Your example "/HTML/BODY/DIV[9]/DIV[2]" should work in it.

(edit - corrected thanks to Sergey Ilinsky)

Instead of doing

xmlDoc.load(document); 

try

xmlDoc.loadXML(document.body.outerHTML)

This would only really work if your your HTML document is formatted to XHTML standards. Also, the BODY tag would be the root node, so you would have to change your XPATH to "/BODY/DIV[9]/DIV[2]"

I'd be a bit worried about using xml like this, as you cannot be sure what version (if any) of the XML DLL a person has. There are still companies using IE5.0 out there in droves, and 5.5 had a particularly ropey XML implementation.

Another JavaScript implementation of W3C Dom Level 3 XPath can be found on Source Forge. But does not appear to be active.

I can not find a simple and common solution, you can write custom function to implement a little of xpath but it is hard to get complete in internet explorer 6 or lower version....

本文标签: