开发者

Navigate HTML table columns with XPath 1.0

开发者 https://www.devze.com 2023-01-10 16:40 出处:网络
Using only an XPath expression (and not in XSLT or DOM - just pure XPath), I\'m trying to create a relative path from the current node (in a td) to an associated td in the same column of the same HTML

Using only an XPath expression (and not in XSLT or DOM - just pure XPath), I'm trying to create a relative path from the current node (in a td) to an associated td in the same column of the same HTML table.

For example, suppose I have this type of data:

<table>
  <tr> <td><a>Blue Jeans</a></td> <td><a>Shirt</a></开发者_开发技巧td> </tr>
  <tr> <td><span>$21.50</span></td> <td><span>$18.99</span></td> </tr>
</table>

and I'm on the a with "Blue Jeans" and want to find the price ($21.50). In XSLT, I could use the current() function to get the answer like this:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text" />
    <xsl:template match="/">
        <xsl:apply-templates select="//a" />
    </xsl:template>

    <xsl:template match="a"> 
        Name: <xsl:value-of select="."/>
        Price: <xsl:value-of select="../../following-sibling::tr[1]/td[position() = count(current()/../preceding-sibling::td) + 1]" />
    </xsl:template>

</xsl:stylesheet>

But the problem I'm running into is that there is no current() defined in XPath 1.0. I tried using the self:: axis, but like the "." shorthand, that only points to the "context" node, not the "current" node. The language that I'm seeing in the XPath standard suggests that XPath doesn't have a concept of "current node."

Is there perhaps another way to form this path or is this a limitation of XPath?


In XPath 1.0 you could do:

/table/tr/td/a[.='Blue Jeans']/following::td[count(../td)]/span

Of course, this assumes there is no colspan.

EDIT: The proof. This stylesheet:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="text"/>
    <xsl:param name="pProduct" select="'Blue Jeans'"/>
    <xsl:template match="/">
        <xsl:value-of select="/table/tr/td/a[.=$pProduct]
                                    /following::td[count(../td)]/span"/>
    </xsl:template>
</xsl:stylesheet>

Output:

$21.50

With param pProduct set to 'Shirt', output:

$18.99

Note: Of course, you need the a element in context in order to select the span element. So, with your stylesheet:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="text"/>
    <xsl:template match="text()"/>
    <xsl:template match="a">
        Name: <xsl:value-of select="."/>
        Price: <xsl:value-of select="following::td[count(../td)]/span" />
    </xsl:template>
</xsl:stylesheet>

Output:

Name: Blue Jeans
Price: $21.50
Name: Shirt
Price: $18.99


This cannot be achieved with a single XPath 1.0 expression.

In XPath 2.0 one could write:

for $vPreceeding in count(../preceding-sibling::td)
  return ../../following-sibling::tr[1]/td[$vPreceeding]
0

精彩评论

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