HTML XPath - How to get the XPath of an element ba

2019-04-14 19:55发布

I have the following HTML code:

<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>

My question is if I know the value of the 'Card No' element, how can I get the XPath of the Update link? For example, If I know the Card No is "5123 4567 8901 2346", how can I get the XPath of the link element "<a href="/admin?cpm_id=905">"?

Update from comments

I'm using an automation test tool called QTP. I need to get the XPath of the update link element to identify it on the webpage based on the value of the Credit Card number. What I'm after is to get the XPath such as"/html/body/table/tbody/tr[3]/td[1]/a". However, this is the static path of the update link element. I would like to be able to get the XPath based on a Credit Card number.

标签: html xslt xpath
3条回答
手持菜刀,她持情操
2楼-- · 2019-04-14 20:40

Dimitre's answer is good for an XSLT solution but just for completeness, here is another perspective. Since the data is in a table with uniform structure, in a sense the XPath for any one element is the same when you consider the card number as a parameter. In C# for example, the string.Format method uses {0} as a placeholder, as shown in the XPATH_TEMPLATE below. Simply fill in the place holder in this template with the card number to get the requisite XPath expression.

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

The above yields this resulting XPath expression:

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

So whether you are working in XSLT or C# or something else, this flavor of XPath is more meaningful (than e.g. /table/tbody/tr[3]/td[1]/a) because it is self-contained with context information.

查看更多
姐就是有狂的资本
3楼-- · 2019-04-14 20:44

Ran across a concept called bookmarklets. Using the given bookmarklets on your HTML code produced the result, /HTML/BODY/TABLE/TBODY/TR[3]/TD[1]/A.

The URL is Equivalent of Firebug's "Copy XPath" in Internet Explorer?

Executing the bookmarks on the name and email edit boxes on this page produces

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

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

Hope this helps

查看更多
太酷不给撩
4楼-- · 2019-04-14 20:50

This is not a difficult task for 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>

when this transformation is applied on the provided XML document:

<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>

the wanted, correct result is produced:

/table/tbody/tr[3]/td[1]/a
查看更多
登录 后发表回答