可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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]
回答1:
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.
回答2:
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.
回答3:
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.
回答4:
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;
}
回答5:
Are you sure X-Path is implemented in your version of Internet Explorer? As in: what version are you using?
回答6:
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)
回答7:
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]"
回答8:
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.
回答9:
Another JavaScript implementation of W3C Dom Level 3 XPath can be found on Source Forge. But does not appear to be active.
回答10:
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....