Javascript获取节点的XPath
Javascript中是否有返回DOM元素XPath字符串的方法?节点没有唯一的XPath,因此您必须确定构建路径的最合适方法。在可用的地方使用ID?文档中的数字位置?相对于其他元素的位置Javascript获取节点的XPath,javascript,dom,xpath,Javascript,Dom,Xpath,Javascript中是否有返回DOM元素XPath字符串的方法?节点没有唯一的XPath,因此您必须确定构建路径的最合适方法。在可用的地方使用ID?文档中的数字位置?相对于其他元素的位置 请参阅中的getPathTo(),了解一种可能的方法。我从另一个示例重构了它。它将尝试检查是否存在唯一id,如果是,则使用该大小写来缩短表达式 函数createXPathFromElement(elm){ var allNodes=document.getElementsByTagName('*'); for
请参阅中的
getPathTo()
,了解一种可能的方法。我从另一个示例重构了它。它将尝试检查是否存在唯一id,如果是,则使用该大小写来缩短表达式
函数createXPathFromElement(elm){
var allNodes=document.getElementsByTagName('*');
for(var segs=[];elm&&elm.nodeType==1;elm=elm.parentNode)
{
if(elm.hasAttribute('id')){
var uniqueIdCount=0;
对于(var n=0;n1)中断;
};
如果(uniqueIdCount==1){
segs.unshift('id('+elm.getAttribute('id')+'));
返回segs.join('/');
}否则{
segs.unshift(elm.localName.toLowerCase()+”[@id=“”+elm.getAttribute('id')+“]);
}
}else if(elm.hasAttribute('class')){
segs.unshift(elm.localName.toLowerCase()+”[@class=“”+elm.getAttribute('class')+“]);
}否则{
对于(i=1,sib=elm.previousSibling;sib;sib=sib.previousSibling){
if(sib.localName==elm.localName)i++;};
segs.unshift(elm.localName.toLowerCase()++'['+i+']');
};
};
返回segs.length?'/'+segs.join('/'):null;
};
函数lookupElementByXPath(路径){
var evaluator=新的XPathEvaluator();
var result=evaluator.evaluate(路径,document.documentElement,null,XPathResult.FIRST\u ORDERED\u NODE\u TYPE,null);
返回result.singleNodeValue;
}
MDN上的函数给出了类似的解决方案:
函数getXPathForElement(el,xml){
var xpath='';
var pos,临时项目2;
而(el!==xml.documentElement){
pos=0;
tempitem2=el;
while(临时项目2){
if(tempitem2.nodeType==1&&tempitem2.nodeName==el.nodeName){//如果它是同名的元素\节点
pos+=1;
}
tempitem2=tempitem2.previousSibling;
}
xpath=“*[name()='”+el.nodeName+“'和namespace-uri()='”+(el.namespaceURI==null?“”:el.namespaceURI)+“][”+pos+']'+'/'+xpath;
el=el.parentNode;
}
xpath='/*'+“[name()=”+xml.documentElement.nodeName+”,namespace-uri()='+(el.namespaceURI===null?'':el.namespaceURI)+“]+'+'/'+xpath;
xpath=xpath.replace(/\/$/,“”);
返回xpath;
}
也可能值得一试。以下是一个函数式编程风格的ES6函数:
函数getXPathForElement(元素){
常量idx=(sib,名称)=>sib
?idx(sib.previousElementSibling,name | | sib.localName)+(sib.localName==name)
: 1;
常量segs=elm=>!elm | | elm.nodeType!==1
? ['']
:elm.id&&document.getElementById(elm.id)==elm
?[`id(${elm.id})`]
:[…segs(elm.parentNode),`${elm.localName.toLowerCase()}[${idx(elm)}]`];
返回segs(元素).join('/');
}
函数getElementByXPath(路径){
返回(新的XPathEvaluator())
.evaluate(路径,document.documentElement,null,
XPathResult.FIRST_ORDERED_NODE_TYPE,null)
.singleNodeValue;
}
//演示:
const li=document.querySelector('li:n个子(2)');
const path=getXPathForElement(li);
console.log(路径);
log(li==getElementByXPath(path));//正确
- 选项
标题
- abc
- 选择这个
函数getElementXPath(元素){
如果(!element)返回null
if(element.id){
返回`/*[@id=${element.id}]`
}else if(element.tagName==='BODY'){
返回“/html/body”
}否则{
const sameTagSiblings=Array.from(element.parentNode.childNodes)
.filter(e=>e.nodeName===element.nodeName)
const idx=sameTagSiblings.indexOf(元素)
返回getElementXPath(element.parentNode)+
'/' +
element.tagName.toLowerCase()+
(sameTagSiblings.length>1?`[${idx+1}]``:“”)
}
}
log(getElementXPath(document.querySelector('a div')))
def
只需在函数getXPathOfElement
中传递元素,就可以得到Xpath
function getXPathOfElement(elt)
{
var path = "";
for (; elt && elt.nodeType == 1; elt = elt.parentNode)
{
idx = getElementIdx(elt);
xname = elt.tagName;
if (idx > 1) xname += "[" + idx + "]";
path = "/" + xname + path;
}
return path;
}
function getElementIdx(elt)
{
var count = 1;
for (var sib = elt.previousSibling; sib ; sib = sib.previousSibling)
{
if(sib.nodeType == 1 && sib.tagName == elt.tagName) count++
}
return count;
}
我已经修改了,以便从下面的devtools计算XPath
要以书面形式使用它,您需要调用Elements.DOMPath.xPath(,false)
。最后一个参数控制是获取较短的“复制XPath”(iftrue
)还是“复制完整XPath”
//作者版权所有。版权所有。
//此源代码的使用受BSD样式许可证的约束,该许可证可以
//在许可证文件中找到。
元素={};
Elements.DOMPath={};
/**
*@param{!Node}Node
*@param{boolean=}已优化
*@return{string}
*/
Elements.DOMPath.xPath=函数(节点,优化){
if(node.nodeType==node.DOCUMENT\u节点){
返回“/”;
}
常数步长=[];
让contextNode=node;
while(contextNode){
const step=Elements.DOMPath.\u xPathValue(contextNode,优化);
如果(!步){
打破
}//错误-提前退出。
步骤。推(步骤);
如果(步骤优化){
打破
}
contextNode=contextNode.parentNode;
}
步骤。反向();
返回(steps.length&&steps[0]。优化?“”:“/”)+steps.join(“/”);