Reputation: 3920
<element>
<bye>do not delete me</bye>
<hello>do not delete me</hello>
<hello>delete me</hello>
<hello>delete me</hello>
</element>
Applied to the above xml, this deletes all the nodes except the first hello
child of /element
:
<xsl:template match="hello[not(current() = parent::element/hello[1])]" />
Why these ones doesn't work? (assuming the first node is not a text node)
<xsl:template match="hello[not(self::hello/position() = 1)]" />
<xsl:template match="hello[not(./position() = 1)]" />
Or this one?
<xsl:template match="hello[not(self::hello[1])]" />
What is the self
axis selecting? Why isn't this last example equivalent to not(hello[1])
?
Upvotes: 0
Views: 4152
Reputation: 163575
Using position() on the RHS of the "/" operator is never useful -- and in XSLT 1.0, which is the tag on your question, it's not actually permitted.
In XSLT 2.0, the result of the expression X/position() is a sequence of integers 1..count(X). If the LHS is a singleton, like self::E, then count(X) is one so the result is a single integer 1.
Upvotes: 2
Reputation: 117102
First, you are wrong when you say that:
This deletes all the nodes except the first
hello
child of/element
The truth is that it deletes (if that's the correct word) any hello
child of /element
whose value is not the same as the value of the first one of these. For example, given:
XML
<element>
<hello>a</hello>
<hello>b</hello>
<hello>c</hello>
<hello>a</hello>
</element>
the template:
<xsl:template match="hello[not(current() = parent::element/hello[1])]" />
will match the second and the third hello
nodes - but not the first or the fourth.
Now, with regard to your question: in XSLT 1.0, position()
is not a valid location step - so this:
<xsl:template match="hello[not(self::hello/position() = 1)]" />
should return an error.
In XSLT 2.0, the pattern hello[not(self::hello/position() = 1)]
will not match any hello
element - because there is only one node on the self axis, and therefore its position is always 1.
Similarly:
<xsl:template match="hello[not(./position() = 1)]" />
is invalid in XSLT 1.0.
In XSLT 2.0, ./position()
will always return 1 for the same reason as before: .
is short for self::node()
and there is only one such node.
Finally, this template:
<xsl:template match="hello[not(self::hello[1])]" />
is looking for a node that doesn't have (the first instance of) itself. Of course, no such node can exist.
Upvotes: 3