2

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.

3
  • In what context are you going to USE the resulting XPATH? Commented Mar 8, 2011 at 1:44
  • Thanks Jim. 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. Does this make sense? Commented Mar 8, 2011 at 2:19
  • Good question, +1. See my answer for a complete, short and easy XSLT solution. :) Commented Mar 8, 2011 at 4:25

3 Answers 3

1

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
Sign up to request clarification or add additional context in comments.

2 Comments

Hi Dimitre,Thanks for your answer and I tested and it worked fine. However, what I'm really after is not a XSLT solution. I would like to have something like a single line of XPath expression with the Credit Card number as a parameter. Based on the value of this parameter, I will get the XPath of the update link element. I'm not sure if this is possible. Cheers. /Allen
@Allen: This cannot be accomplished with single XPath 1.0 expression and I guess you do not have an XPath 2.0 engine available. For any such task XSLT is your friend.
0

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.

1 Comment

Thanks Msorens for your comment. Inspired by your suggestion, I finally got a workaround. I am now able to get the XPath of the Update link by the following expression: //td[contains(text(), '"& cardNo &"')]/preceding-sibling::td[1]/a The cardNo is a parameter and the expression will return the XPath of the Update link element. Thank you all for your help.
0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.