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

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

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

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

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

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

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

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

Вы говорите «только интернет-обозреватель». Означает ли это, что вы даже не можете открыть приложение в Firefox? Или просто он должен безупречно работать в IE, независимо от того, работает ли он в других браузерах?

pkaeding 18.10.2008 16:15

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

PhiLho 19.10.2008 01:04

Да, это действительно только IE. Он даже не загружается в Firefox (приложение явно проверяет тип браузера)

The Archetypal Paul 21.10.2008 19:36
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
12
3
36 941
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

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

Два сайта букмарклетов для веб-разработчиков из моих закладок: Букмарклеты 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.

Теперь версии букмарклета (спасибо Конструктор букмарклетов):

IE
(Мне пришлось разбить его на две части, потому что IE не любит очень длинные букмарклеты (максимальный размер зависит от версии IE!). Вы должны активировать первый (function 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();

Выглядит интересно, но я понятия не имею, как добавить букмарклет :( Вы можете указать мне на что-нибудь, что объясняет это?

The Archetypal Paul 19.10.2008 17:26

Надеюсь, вы получите такой ответ ... Добавить букмарклет очень просто: скопируйте строку javascript: (одну за другой в случае моих марклетов IE) и вставьте ее в адресную строку браузера (и нажмите Return). Затем вы можете добавить его в избранное (они тоже называются избранными), чтобы перезвонить им. Затем запускается JS.

PhiLho 20.10.2008 02:09

Я получаю сообщение «Ошибка: ps имеет значение null. Исходный файл: javascript: function% ...» Этот код больше не работает в FF 3.5.5?

Photodeus 08.11.2009 23:17

@Photodeus: Ой! Очевидно, вы первый, кто протестировал версию FF ... У меня была опечатка, ps вместо ns (в ns = ps.nextSibling). Исправлено в ответе. Спасибо за сообщение.

PhiLho 09.11.2009 13:32

Интересный код. Интересно, можно ли адаптировать этот код для проверки заданного XPath элемента в DOM. Например. передать XPath и вернуть ссылку на элемент DOM, если он найден, или null / undefined в противном случае. Что-то вроде document.getElementByXPath (), document.getElementsByXPath (). Есть способ сделать это для других браузеров, но похоже, что код такой же техники не работает в IE. autumnator.wordpress.com/2013/05/02/…

David 29.06.2013 02:52

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

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

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

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

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

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

Как бы вы тогда использовали эту версию C#?

David 29.06.2013 02:47

Я попробовал этот код, и он отлично работает, за исключением того, что он не может преобразовать COM-объект в IHTMLElement, когда HTML-элемент имеет значение INPUT <code> mshtml.IHTMLElement ps = psDom as mshtml.IHTMLElement; </code> кто-нибудь может указать причину?

Tejas 28.09.2013 21:32

Другие вопросы по теме