XPATH Query: How to get two elements?

10,124

Solution 1

I think what you might be looking for is something along the lines of

[position() > 2]

which retrieves all elements after the first two.

Solution 2

First notice that the provided XML is not well-formed!

I assume that intended wellformed XML more or less looks like this:

<table>
    <tr>
        <td class="data1"><p>1</p></td>
        <td class="data1"><p>2</p></td>
        <td class="data1"><p>3</p></td>
        <td class="data1"><p>4</p></td>
    </tr>
    <tr>
        <td class="data1"><p>5</p></td>
        <td class="data1"><p>6</p></td>
        <td class="data1"><p>7</p></td>
        <td class="data1"><p>8</p></td>
    </tr>
</table>

For this XML document here are my answers.

Use:

/*/*/td[position() = 3 or position() = 4]/p

Or, you can use the XPath union operator:

/*/*/td[3]/p | /*/*/td[4]/p

The following is wrong:

/*/*/td[3] [4]/p

This specifies the selection of 4th node of /*/*/td[3] and will select nothing because /*/*/td[3] only selects two nodes.

Lastly, here is a transformation that when run demonstrates the result of all XPath expressions above:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/">
  <xsl:copy-of select=" /*/*/td[position() = 3 or position() = 4]/p"/>

  ----------------------

  <xsl:copy-of select="   /*/*/td[3]/p  | /*/*/td[4]/p"/>

  ----------------------

  <xsl:copy-of select=" /*/*/td[3][4]/p"/>

 </xsl:template>
</xsl:stylesheet>
Share:
10,124

Related videos on Youtube

Damiano
Author by

Damiano

Updated on June 04, 2022

Comments

  • Damiano
    Damiano about 2 years

    My HTML code is:

    <table>
    <tr>
    <td class="data1"><p>1</td></td>
    <td class="data1"><p>2</td></td>
    <td class="data1"><p>3</td></td>
    <td class="data1"><p>4</td></td>
    </tr>
    <tr>
    <td class="data1"><p>5</td></td>
    <td class="data1"><p>6</td></td>
    <td class="data1"><p>7</td></td>
    <td class="data1"><p>8</td></td>
    </tr>
    </table>
    

    My query is:

    xpath='//tr//td[@class="data1"][4]/p'
    

    The results is:

    <p>4</p>
    <p>8</p>
    

    The results is correct! but, if I want to get example:

    <p>3</p> <p>4</p>
    
    <p>7</p> <p>8</p>
    

    So

    [3]/p and [4]/p

    How to get these two elements each <tr> ?

    Thank you so much!

    • Lars Andren
      Lars Andren about 14 years
      something along the lines of [position()] might be useful
    • Dimitre Novatchev
      Dimitre Novatchev about 14 years
      Good Question (+1). See my answer that corrects your XML and discusses two correct solutions and why a third proposed XPath expression is wrong.
  • Damiano
    Damiano about 14 years
    Perfect! Thank you. Could I use? [position() = 1][position() = 4] if i want to get only the first and the fouth element?
  • Mads Hansen
    Mads Hansen about 14 years
    @Damiano - If you evaluate those two predicate filters separately, you will get the information you want. If you want to evaluate them in a single XPATH expression, then you will need to combine them in a single predicate filter and use the or operator: [position()=1 or position()=4] Otherwise, it will evaluate to see if both predicate filters are true(and no element will be both the 1st AND the 4th).