Эквивалент Firebug «Скопировать XPath» в Internet Explorer?

У меня есть веб-приложение только для Internet Explorer.

Я изучаю, что мы можем сделать, чтобы автоматизировать тестирование.

Селен выглядит как хороший инструмент, но чтобы активировать ссылки и т. Д. Мне нужно сказать, где они. Приложение не было построено с учетом такого типа тестов, поэтому в ключевых элементах обычно нет атрибутов id .

Без проблем, я думаю, я могу использовать выражения XPath. Но найти правильный XPath для, скажем, кнопки, является королевской болью, если это делается путем проверки источника страницы.

С Firefox / Firebug я могу выбрать элемент, а затем использовать «Copy XPath», чтобы получить выражение.

У меня есть панель инструментов IE Developer, и это расстраивает. Я могу щелкнуть, чтобы выбрать интересующий элемент и отобразить всевозможную информацию об этом. но я не вижу удобного способа определения XPath для этого.

Так есть ли способ сделать это с IE?

Я бы использовал букмарклеты. У меня есть один связанный XPath, но я не знаю, работает ли он в IE. Я должен идти, но я буду проверять его и давать, если он работает на IE.

Два закладок для веб-разработчиков из моих закладок: букмарклеты Subsimple и закладки Bookmarks Squarefree . Много полезных вещей там …

[EDIT] Хорошо, я вернулся. Я имел в виду только для 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.

Теперь, версии букмарклета (благодаря закладок 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(); 

Поскольку использование букмарклов озадачило Пола, я должен добавить небольшое введение в их использование. Я делаю это в отдельном сообщении, чтобы не смешивать вещи.

Bookmarklets (также называемые favlets) – это небольшие скрипты JavaScript (sic), предназначенные для вставки в адресную строку браузера (как и любой другой URL) и, таким образом, для запуска на текущей странице.
После запуска (вставить, нажмите Enter) вы можете пометить его для повторного использования (добавьте его в избранное в IE). Обратите внимание, что браузер может вместо этого добавлять закладки к исходному URL, тогда вы должны отредактировать закладку и заменить URL своим скриптом.
Конечно, вы можете добавить его в строку URL для быстрого доступа.

Эти сценарии действуют как часть текущей страницы, обращаются к глобальным переменным и функциям JS, объектам Dom и т. Д.
Они могут быть супер простыми, например семантический javascript: alert("Hello world!"); или довольно сложно, как выше. Если он возвращает значение (или если последнее выражение имеет значение), значение заменяет текущую страницу. Чтобы этого избежать, вы можете закончить скрипт с alert (для отображения результата) или обернуть скрипт в определение функции и вызвать эту функцию, как я сделал выше. (Некоторые также помещают void (0), в конце, но я видел, что это рассматривается как плохая практика.)

Решение функции имеет то преимущество, что все переменные скрипта локальны для апплета (если, конечно, объявлено с помощью var ), избегая помех / побочных эффектов со сценариями на локальной странице. Вот почему функция wrapping должна иметь имя, которое вряд ли столкнется с локальным скриптом.

Обратите внимание, что некоторые браузеры (читайте: «IE») могут ограничить размер favlets, макс. длина варьируется от версии (имеет тенденцию к уменьшению). Вот почему все бесполезные пробелы удаляются (построитель bookmarlet, связанный выше, хорош для этого), и я удалил эксплицитные сравнения с нулевым и неопределенным, как я обычно делаю. Мне также пришлось разделить ящерицу на две части, первую часть которой определяет функцию (живущая до тех пор, пока страница не будет изменена / обновлена), вторая часть будет использоваться.

Полезный инструмент, особенно в браузерах, не разрешающих пользовательские скрипты (à la 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; } } } 
Давайте будем гением компьютера.