开发者

HTML XPath - How to get the XPath of an element based on the value of another element?

开发者 https://www.devze.com 2023-02-15 05:05 出处:网络
I have the following HTML code: <table> <tbody> <tr> <th class=\"colhead\" nowrap=\"nowrap\">Update</th>

I have the following HTML code:

<table>
<tbody>
    <tr>
        <th class="colhead" nowrap="nowrap">Update</th>
        <th class="colhead" nowrap="nowrap"&g开发者_JS百科t;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.


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


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.


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

0

精彩评论

暂无评论...
验证码 换一张
取 消