【问题标题】:XPath given by Chrome DevTools could not be found找不到 Chrome DevTools 提供的 XPath
【发布时间】:2015-01-10 16:32:15
【问题描述】:

当我在回答 another question 关于 Selenium 时尝试使用一些 XPath SVG 路径时,我发现 Chrome 上的 XPath 有一个奇怪的行为(我没有在其他浏览器上尝试过)。

http://www.amcharts.com/svg-maps/?map=usa,为什么 XPath 工作?

//*[@id="chartdiv"]/div/div[1]/svg/g[7]/g/g[1]

而这个

//*[@id="chartdiv"]/div/div[1]/*[name()="svg"]/*[name()="g"][7]/*[name()="g"]/*[name()="g"][2]


我必须进行以下更改:

  • /g 变为 /*[name()="g"]
  • /svg 变为 /*[name()="svg"]
  • /path 变为 /*[name()="path"]

奇怪的是,我通过右键单击元素 HTML 获得了第一个 XPath,并从那里复制了 XPath。


我在http://gmsgroup.com/municenter.asp 上还有另一个例子:

  • //*[@id='ext-gen203']/*[name()='svg']/*[name()='a']/*[name()='path'][starts-with(@d, 'M136.65')]/.. 工作,
  • //*[@id='ext-gen203']/*[name()='svg']/*[name()='a'][@title='Hawaii'] 没有。

这里,/*[name()='a'][@title='Hawaii'] 无法获取<a title="Hawaii"></a>,为什么?

【问题讨论】:

  • 并非所有元素都在页面的 HTML 源中(例如,a[@title='Hawaii'] 是由脚本添加的)。您在什么应用程序中使用 XPath?
  • Chrome 开发工具。确实,这些元素当时是由 Javascript 生成的,但它们仍然存在,因为一些不同的 XPath 可以找到它们!
  • Chrome 开发工具如何处理命名空间? SVG 通常位于命名空间中。 (不熟悉那些开发工具,只是好奇)。可能/svg 排除了svg 的默认命名空间,而使用/*[name()='svg'] 只排除了前缀命名空间。

标签: html google-chrome selenium xpath svg


【解决方案1】:

命名空间可以加前缀:

<root xmlns:ns="www.example.com"/>

或默认命名空间:

<root xmlns="www.example.com"/>

SVG 位于默认命名空间中。像/svg 这样的路径表达式告诉XPath 处理器寻找一个名为“svg”的元素,并且该元素不在任何命名空间中。因此,这个表达式只匹配:

<svg/>   or <svg xmlns=""/>

使用/*[name()='svg'] 只会排除前缀命名空间。它仍然允许一个名为“svg”的元素,它位于默认命名空间中,没有前缀。第二个表达式匹配

<svg xmlns="http://www.w3.org/2000/svg"/>

但不是

<ns:svg xmlns:ns="http://www.w3.org/2000/svg"/>

为了证明这一点,请考虑以下 XSLT 样式表:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">

    <xsl:template match="*[name() ='svg']">
        <hit/>
    </xsl:template>

</xsl:transform>

应用于以下输入,一个缩短的 SVG 文档:

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg"/>

结果:

<?xml version="1.0" encoding="UTF-8"?>
<hit/>

在线查看here


编辑(回复您的评论)

更清楚地说,这是否意味着 SVG 默认命名空间会覆盖页面中的命名空间,因此不处理诸如 [@title='Hawaii'] 之类的表达式?

HTML 元素本身没有命名空间 - SVG 不会“覆盖”页面的命名空间。 svg 元素上的默认命名空间仅适用于自身和所有子元素(包括其中的 a[@title='Hawaii'] 元素。

//*[@id='ext-gen203']/*[name()='svg']/*[name()='a'][@title='Hawaii']应该能够找到a元素,我很惊讶它没有。

在哪里可以找到该默认命名空间的规范?

如果您指的是一般的默认命名空间,请看这里:http://www.w3.org/TR/REC-xml-names/#scoping-defaulting。如果您指的是 SVG 规范,请研究 SVG 规范的以下章节:http://www.w3.org/TR/SVG/struct.html

这是否也意味着没有比 //[@id='ext-gen203']/[name()='svg']/[name()='a']/[name()='path'][starts-wit‌​h(@d, 'M136.65')]/..?

做到这一点的更好方法是注册声明这些命名空间,从而通过前缀使它们可用于Xpath表达式(正如Martin Honnen指出的那样出去)。 Chrome 开发工具不是我的专业领域,我无法评论如何去做。

【讨论】:

  • 好的,我知道这都是关于命名空间的。更清楚地说,这是否意味着 SVG 默认命名空间会覆盖页面中的命名空间,因此不处理 [@title='Hawaii'] 之类的表达式?在哪里可以查看我的 SVG 可用的表达式?在哪里可以找到该默认命名空间的规范?
  • 这是否也意味着没有比//*[@id='ext-gen203']/*[name()='svg']/*[name()='a']/*[name()='path'][starts-with(@d, 'M136.65')]/.. 更好的获取&lt;a title="Hawaii"&gt;&lt;/a&gt; 的方法?
  • @StéphaneBruckert 查看我(仅部分令人满意)的编辑。
  • @StéphaneBruckert a 的情况令人费解。你试过了吗://*[name()='a'][@*[name()='title'][.='Hawaii']]
  • 感谢您的帮助编辑! //*[name()='a'][@*[name()='title'][.='Hawaii']] 确实有效!谢谢,你肯定回答了我的问题。
【解决方案2】:

HTML5 和 text/html 允许您在一个文档中混合 HTML、MathML 和 SVG 元素,并且不需要您使用与不同词汇关联的命名空间。但是,使用 XPath,您需要确保将前缀绑定到 SVG 命名空间并在查询中使用该前缀,因为在 DOM 树中,SVG 元素与 HTML 元素位于不同的命名空间中。我不知道在开发人员工具中这是否可行,但使用 API 通常可以设置命名空间解析器,将您想在 XPath 表达式中使用的前缀映射到命名空间 URL。

【讨论】:

  • 这如何解释一些不同的 XPath 路径可以在不处理命名空间的情况下找到我的元素?
  • 那是像divp 这样的HTML 元素吗?我认为 HTML5 让浏览器实现了一些xpath-default-namespace="http://www.w3.org/1999/xhtml",这样你就可以在不使用前缀的情况下选择 HTML 元素。
  • 请参阅w3.org/TR/html5/… 了解有关该 HTML5 要求的详细信息。
  • @MartinHonnen 据我了解,这只发生在 svg 或其子元素中。
  • @MartinHonnen 只有以下情况才会发生:路径表达式//svg 不返回任何内容,而//*[name()='svg'] 确实找到svg 元素。这就是我假设的 OP 的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-11-12
  • 2014-11-24
  • 1970-01-01
  • 1970-01-01
  • 2019-05-04
  • 2020-05-30
  • 2022-01-15
相关资源
最近更新 更多