【问题标题】:HTML XPath - How to get the XPath of an element based on the value of another element?html xpath - 如何基于另一个元素的值获取元素的XPath?
【发布时间】:2011-07-10 18:49:51
【问题描述】:

我有以下 HTML 代码:

<table>
<tbody>
    <tr>
        <th class="colhead" nowrap="nowrap">Update</th>
        <th class="colhead" nowrap="nowrap">Card No</th>
    </tr>
    <tr>
        <td nowrap="nowrap"><a href="/admin?cpm_id=1043">
        Update</a></td>
        <td nowrap="nowrap">4987 6543 2109 8769</td>
    </tr>
    <tr>
        <td nowrap="nowrap"><a href="/admin?cpm_id=905">
        Update</a></td>
        <td nowrap="nowrap">5123 4567 8901 2346</td>
    </tr>
</tbody>

我的问题是,如果我知道“卡号”元素的值,我怎样才能获得更新链接的 XPath?例如,如果我知道卡号是“5123 4567 8901 2346”,如何获取链接元素"&lt;a href="/admin?cpm_id=905"&gt;"的XPath?

来自 cmets 的更新

我正在使用自动化测试工具 称为 QTP。我需要得到 XPath 用于识别它的更新链接元素 在网页上基于价值 信用卡号码。我所追求的 是得到这样的XPath 如“/html/body/table/tbody/tr[3]/td[1]/a”。 但是,这是静态路径 更新链接元素。我想 能够获得基于 信用卡号。

【问题讨论】:

  • 您将在什么情况下使用生成的 XPATH?
  • 谢谢吉姆。我正在使用一个名为 QTP 的自动化测试工具。我需要获取更新链接元素的 XPath,以根据信用卡号的值在网页上识别它。我所追求的是获得诸如“/html/body/table/tbody/tr[3]/td[1]/a”之类的XPath。但是,这是更新链接元素的静态路径。我希望能够根据信用卡号获取 XPath。这有意义吗?
  • 好问题,+1。请参阅我的答案以获得完整、简短且简单的 XSLT 解决方案。 :)

标签: html xslt xpath


【解决方案1】:

这对 XSLT 来说并不难

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>
 <xsl:strip-space elements="*"/>

 <xsl:param name="pCardNo" select=
 "'5123 4567 8901 2346'"/>

 <xsl:template match="/">
  <xsl:variable name="vNode" select=
  "/*/*/tr[td[2] = $pCardNo]/td[1]
                     /a/ancestor-or-self::*"/>

  <xsl:apply-templates select="$vNode" mode="path"/>
 </xsl:template>

 <xsl:template match="*" mode="path">
  <xsl:value-of select="concat('/',name())"/>

  <xsl:variable name="vnumPrecSiblings" select=
    "count(preceding-sibling::*[name()=name(current())])"/>

  <xsl:variable name="vnumFollSiblings" select=
    "count(following-sibling::*[name()=name(current())])"/>

  <xsl:if test="$vnumPrecSiblings or $vnumFollSiblings">
   <xsl:value-of select=
      "concat('[', $vnumPrecSiblings +1, ']')"/>
  </xsl:if>
 </xsl:template>

</xsl:stylesheet>

当此转换应用于提供的 XML 文档时:

<table>
    <tbody>
        <tr>
            <th class="colhead" nowrap="nowrap">Update</th>
            <th class="colhead" nowrap="nowrap">Card No</th>
        </tr>
        <tr>
            <td nowrap="nowrap">
                <a href="/admin?cpm_id=1043">         Update</a>
            </td>
            <td nowrap="nowrap">4987 6543 2109 8769</td>
        </tr>
        <tr>
            <td nowrap="nowrap">
                <a href="/admin?cpm_id=905">         Update</a>
            </td>
            <td nowrap="nowrap">5123 4567 8901 2346</td>
        </tr>
    </tbody>
</table>

产生了想要的正确结果:

/table/tbody/tr[3]/td[1]/a

【讨论】:

  • 您好 Dimitre,感谢您的回答,我进行了测试,效果很好。但是,我真正追求的不是 XSLT 解决方案。我希望有类似单行 XPath 表达式的东西,其中信用卡号作为参数。根据这个参数的值,我会得到更新链接元素的 XPath。我不确定这是否可能。干杯。 /艾伦
  • @Allen:这不能用单一的 XPath 1.0 表达式来完成,我猜你没有可用的 XPath 2.0 引擎。对于任何此类任务,XSLT 都是您的朋友。
  • 感谢您的帮助 Dimitre。
【解决方案2】:

Dimitre 的回答对 XSLT 解决方案很有用,但只是为了完整性,这里是另一种观点。由于数据在一个具有统一结构的表中,在某种意义上,当您将卡号视为参数时,任何一个元素的 XPath都是相同的。例如,在 C# 中,string.Format 方法使用{0} 作为占位符,如下面的 XPATH_TEMPLATE 所示。只需在此模板中的占位符中填写卡号即可获得所需的 XPath 表达式。

string XPATH_TEMPLATE = 
  "//td[normalize-space(.)='{0}']/preceding-sibling::td/a";
string CardNumber = "4987 6543 2109 8769";
string XPathExpression = string.Format(XPATH_TEMPLATE, CardNumber);

上面产生了这个 XPath 表达式:

//td[normalize-space(.)='4987 6543 2109 8769']/preceding-sibling::td/a

因此,无论您是使用 XSLT 还是 C# 或其他方式,这种 XPath 风格都更有意义(比 /table/tbody/tr[3]/td[1]/a 等),因为它是自包含的上下文信息。

【讨论】:

  • 感谢 Msorens 的评论。受您建议的启发,我终于找到了解决方法。我现在可以通过以下表达式获取更新链接的 XPath: //td[contains(text(), '"& cardNo &"')]/preceding-sibling::td[1]/a CardNo是一个参数,表达式将返回更新链接元素的 XPath。谢谢大家的帮助。
【解决方案3】:

遇到了一个叫做书签的概念。在您的 HTML 代码上使用给定的小书签会产生结果,/HTML/BODY/TABLE/TBODY/TR[3]/TD[1]/A。

网址是Equivalent of Firebug's "Copy XPath" in Internet Explorer?

执行此页面上名称和电子邮件编辑框上的书签会产生

//INPUT[@id='display-name']

//INPUT[@id='m-address']

希望对你有帮助

【讨论】:

    猜你喜欢
    • 2020-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-14
    • 2022-08-17
    • 2017-08-20
    • 1970-01-01
    • 2014-10-17
    相关资源
    最近更新 更多