Home > database >  Why doesn't my XPath expression return any results?
Why doesn't my XPath expression return any results?

Time:12-01

I have the following html:

<html>
  <body>
    <table>
      <tr>
      <tr>
      <tr>
      <tr>
      <tr>
        <td>Color Digest </td>
        <td>AgArAQICGQMVBBwTIRQHIwg0GUMURAZTBWQJcwV0AoEDAQ </td>
      </tr>
      <tr>
        <td>Color Digest </td>
        <td>2,43,2,25,21,28,0,0,0,0,0,0,0,0,0,0,0,0,0,0,33,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, </td>
      </tr>
    </table>
  </body>
</html>

and the following xpath:

tr[td='Color Digest']/td

and I'm getting zero results. Can someone explain why?

enter image description here

CodePudding user response:

In xPath expression we can use attribute name but not tag name. Here both <tr> and <td> are tag names. The valid xPath expressio be like,

//tagname[@attributeName='value']

but you wrote like,

//tagname[@tagname='value']

Inside td there is only text available so you need to write xPath like

//td[text()='Color Digest ']

instead of

//tr[td='Color Digest ']

If you need to use specific element then please use the match number like below,

(//td[text()='Color Digest '])[1]

CodePudding user response:

There are a few issues with your XPath

tr[td='Color Digest']/td
^ 1
   ^ 2
                     ^ 3
  1. XPaths should start with a / (child) or // (descendant). Child basically means one level down where descendant means one or more levels down.

    tr should be //tr in this case since there are no root TRs.

  2. You've used td when it looks like you meant to use . or text() which indicates two variations of text within the element. . means squash the contained text of all descendant nodes and text() means the contained text of just the current node.

    Either text() or . will work in this case but I would generally use text() just to be safe.

    [td='Color Digest'] should be [text()='Color Digest']

  3. If you look at the HTML you provided, the text in the first TD actually contains a space at the end, e.g. 'Color Digest ' vs 'Color Digest'. That space is required unless you use a function like contains().

    [td='Color Digest'] should be [text()='Color Digest ']

  4. For this last one, I'm not sure what you are actually looking for, /td.

    For the TD that contains the "Color Digest " text, it has no child. If you meant sibling TD, that would require /following-sibling.

    /td should be /following-sibling::td[1].

Putting all of this together,

//tr[text()='Color Digest ']/following-sibling::td[1]

and it would return the following elements

<td>AgArAQICGQMVBBwTIRQHIwg0GUMURAZTBWQJcwV0AoEDAQ </td>
<td>2,43,2,25,21,28,0,0,0,0,0,0,0,0,0,0,0,0,0,0,...</td>
  • Related