[英]Equivalent of Firebug's “Copy XPath” in Internet Explorer?
我有一个仅Internet Explorer的Web应用程序。
我正在探索如何使测试自动化。
Selenium看起来是一个很好的工具,但是要能够激活链接等,我需要告诉它它们在哪里。 应用程序的构建并不是考虑到这种测试的,因此通常在关键元素上没有id
属性。
我认为没问题,我可以使用XPath表达式。 但是,如果要通过检查页面源代码来找到正确的XPath(例如某个按钮),将是一件很痛苦的事情。
使用Firefox / Firebug,我可以选择元素,然后使用“复制XPath”获取表达式。
我有IE开发人员工具栏,它非常令人沮丧。 我可以单击以选择感兴趣的元素,并显示有关它的各种信息。 但我找不到确定它的XPath的任何便捷方法。
那么,使用IE可以做到这一点吗?
我会用小书签。 我有一个与XPath相关的文件,但我不知道它是否可以在IE中使用。 我得走了,但是如果它在IE上可以工作,我会对其进行测试并给出。
Web开发人员从我的书签中获得的两个小书签站点: Subsimple的小书签和Squarefree的小书签 。 那里有很多有用的东西...
[编辑]好,我回来了。 我拥有的书签仅用于FF,不是最佳选择。 我终于重写了它,尽管使用了最初的想法。 无法找到我找到它的地方。
扩展的JS:
function getNode(node)
{
var nodeExpr = node.tagName;
if (nodeExpr == null) // Eg. node = #text
return null;
if (node.id != '')
{
nodeExpr += "[@id='" + node.id + "']";
// We don't really need to go back up to //HTML, since IDs are supposed
// to be unique, so they are a good starting point.
return "/" + nodeExpr;
}
// We don't really need this
//~ if (node.className != '')
//~ {
//~ nodeExpr += "[@class='" + node.className + "']";
//~ }
// Find rank of node among its type in the parent
var rank = 1;
var ps = node.previousSibling;
while (ps != null)
{
if (ps.tagName == node.tagName)
{
rank++;
}
ps = ps.previousSibling;
}
if (rank > 1)
{
nodeExpr += '[' + rank + ']';
}
else
{
// First node of its kind at this level. Are there any others?
var ns = node.nextSibling;
while (ns != null)
{
if (ns.tagName == node.tagName)
{
// Yes, mark it as being the first one
nodeExpr += '[1]';
break;
}
ns = ns.nextSibling;
}
}
return nodeExpr;
}
var currentNode;
// Standard (?)
if (window.getSelection != undefined)
currentNode = window.getSelection().anchorNode;
// IE (if no selection, that's BODY)
else
currentNode = document.selection.createRange().parentElement();
if (currentNode == null)
{
alert("No selection");
return;
}
var path = [];
// Walk up the Dom
while (currentNode != undefined)
{
var pe = getNode(currentNode);
if (pe != null)
{
path.push(pe);
if (pe.indexOf('@id') != -1)
break; // Found an ID, no need to go upper, absolute path is OK
}
currentNode = currentNode.parentNode;
}
var xpath = "/" + path.reverse().join('/');
alert(xpath);
// Copy to clipboard
// IE
if (window.clipboardData) clipboardData.setData("Text", xpath);
// FF's code to handle clipboard is much more complex
// and might need to change prefs to allow changing the clipboard content.
// I omit it here as it isn't part of the original request.
您必须选择元素并激活小书签以获取其XPath。
现在,小书签版本(感谢Bookmarklet Builder ):
IE浏览器
(我不得不将其分为两部分,因为IE不喜欢很长的书签(最大大小取决于IE版本!)。您必须先激活第一个(功能def),然后激活第二个(已通过IE6测试)。 )
javascript:function getNode(node){var nodeExpr=node.tagName;if(!nodeExpr)return null;if(node.id!=''){nodeExpr+="[@id='"+node.id+"']";return "/"+nodeExpr;}var rank=1;var ps=node.previousSibling;while(ps){if(ps.tagName==node.tagName){rank++;}ps=ps.previousSibling;}if(rank>1){nodeExpr+='['+rank+']';}else{var ns=node.nextSibling;while(ns){if(ns.tagName==node.tagName){nodeExpr+='[1]';break;}ns=ns.nextSibling;}}return nodeExpr;}
javascript:function o__o(){var currentNode=document.selection.createRange().parentElement();var path=[];while(currentNode){var pe=getNode(currentNode);if(pe){path.push(pe);if(pe.indexOf('@id')!=-1)break;}currentNode=currentNode.parentNode;}var xpath="/"+path.reverse().join('/');clipboardData.setData("Text", xpath);}o__o();
FF
javascript:function o__o(){function getNode(node){var nodeExpr=node.tagName;if(nodeExpr==null)return null;if(node.id!=''){nodeExpr+="[@id='"+node.id+"']";return "/"+nodeExpr;}var rank=1;var ps=node.previousSibling;while(ps!=null){if(ps.tagName==node.tagName){rank++;}ps=ps.previousSibling;}if(rank>1){nodeExpr+='['+rank+']';}else{var ns=node.nextSibling;while(ns!=null){if(ns.tagName==node.tagName){nodeExpr+='[1]';break;}ns=ns.nextSibling;}}return nodeExpr;}var currentNode=window.getSelection().anchorNode;if(currentNode==null){alert("No selection");return;}var path=[];while(currentNode!=undefined){var pe=getNode(currentNode);if(pe!=null){path.push(pe);if(pe.indexOf('@id')!=-1)break;}currentNode=currentNode.parentNode;}var xpath="/"+path.reverse().join('/');alert(xpath);}o__o();
由于小书签的使用使Paul感到困惑,因此我应该对其用法进行一些介绍。 我在单独的消息中这样做是为了避免混淆。
书签(也称为收藏夹)是一些JavaScript小脚本(原文如此),旨在将其粘贴到浏览器的地址栏中(与其他任何URL一样),从而可以在当前页面上运行。
运行它(粘贴,按Enter键)后,您可以将其添加为书签以重用(将其添加到IE中的收藏夹中)。 请注意,浏览器可能会将原始URL标记为书签,然后您必须编辑书签并将URL替换为脚本。
当然,您也可以将其添加到URL栏中以便快速访问。
这些脚本的行为就像是当前页面的一部分,访问全局JS变量和函数,Dom对象等。
它们可以非常简单,就像开创性的javascript: alert("Hello world!");
或像上面的那样非常复杂。 如果返回值(或者最后一个表达式具有值),则该值将替换当前页面。 为避免这种情况,您可以像上面我一样,以alert
结束脚本(以显示结果)或将脚本包装在函数定义中并调用此函数。 (有些人最后还把void(0);放到了最后,但是我看到这被认为是不好的做法。)
函数解决方案的优点是使脚本的所有变量都位于applet本地(当然,如果使用var
声明),避免了本地页面上的脚本的干扰/副作用。 这就是为什么包装函数应具有不太可能与本地脚本冲突的名称的原因。
请注意,某些浏览器(阅读:“ IE”)可能会限制收藏夹的大小,即最大 长度随版本而变化(趋于减少)。 这就是为什么删除所有无用的空格的原因(上面链接的小册子生成器对此非常有用),并且我删除了通常使用null和undefined进行的显式比较。 我还必须将favlet分为两部分,第一部分定义一个函数(只要不更改/刷新页面就可以使用),第二部分使用它。
有用的工具,特别是在不允许用户脚本(例如Greasemonkey)或没有此扩展名的浏览器上。
我已将小书签代码重写为C#,因此,如果您发现它有用,请使用它;-)
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
namespace Anotation.Toolbar
{
class XPath
{
public static string getXPath(mshtml.IHTMLElement element)
{
if (element == null)
return "";
mshtml.IHTMLElement currentNode = element;
ArrayList path = new ArrayList();
while (currentNode != null)
{
string pe = getNode(currentNode);
if (pe != null)
{
path.Add(pe);
if (pe.IndexOf("@id") != -1)
break; // Found an ID, no need to go upper, absolute path is OK
}
currentNode = currentNode.parentElement;
}
path.Reverse();
return join(path, "/");
}
private static string join(ArrayList items, string delimiter)
{
StringBuilder sb = new StringBuilder();
foreach (object item in items)
{
if (item == null)
continue;
sb.Append(delimiter);
sb.Append(item);
}
return sb.ToString();
}
private static string getNode(mshtml.IHTMLElement node)
{
string nodeExpr = node.tagName;
if (nodeExpr == null) // Eg. node = #text
return null;
if (node.id != "" && node.id != null)
{
nodeExpr += "[@id='" + node.id + "']";
// We don't really need to go back up to //HTML, since IDs are supposed
// to be unique, so they are a good starting point.
return "/" + nodeExpr;
}
// Find rank of node among its type in the parent
int rank = 1;
mshtml.IHTMLDOMNode nodeDom = node as mshtml.IHTMLDOMNode;
mshtml.IHTMLDOMNode psDom = nodeDom.previousSibling;
mshtml.IHTMLElement ps = psDom as mshtml.IHTMLElement;
while (ps != null)
{
if (ps.tagName == node.tagName)
{
rank++;
}
psDom = psDom.previousSibling;
ps = psDom as mshtml.IHTMLElement;
}
if (rank > 1)
{
nodeExpr += "[" + rank + "]";
}
else
{ // First node of its kind at this level. Are there any others?
mshtml.IHTMLDOMNode nsDom = nodeDom.nextSibling;
mshtml.IHTMLElement ns = nsDom as mshtml.IHTMLElement;
while (ns != null)
{
if (ns.tagName == node.tagName)
{ // Yes, mark it as being the first one
nodeExpr += "[1]";
break;
}
nsDom = nsDom.nextSibling;
ns = nsDom as mshtml.IHTMLElement;
}
}
return nodeExpr;
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.