[英]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.