tags:

views:

1943

answers:

4

Let's say I have an XML doc like this:

<books>
    <book>1110</book>
    <book>1111</book>
    <book>1112</book>
    <book>1113</book>
</books>

I'm trying to setup a condition that tests the value of the current node in the for-each, but I'm doing something wrong:

<xsl:for-each select="/books/book">
    <xsl:if test=".[='1112']">
        Success
    </xsl:if>
</xsl:for-each>

What am I doing incorrectly?

+1  A: 

Using . can, indeed, refer to the current (or "context") node, but not the way you're using it here. In XPath, .[foo] is not valid syntax — you need to use self::node()[foo] instead. Also, the = operator needs something to match against, in this case the text() selector to access the element's text contents:

<xsl:for-each select="/books/book">
    <xsl:if test="self::node()[text()='1112']">
        Success
    </xsl:if>
</xsl:for-each>

As stated in the other answers, however, unless your for-each is performing other operations as well, you don't need to iterate at all and can use just if to accomplish the same task:

<xsl:if test="/books/book[. = 1112]">
    Success
</xsl:if>
Ben Blank
.[someBoolean] is syntactically invalid in XPath 1.0.
Dimitre Novatchev
Thanks; when testing, I'd actually actually tested the non-looping version and so never encountered the `.[…]` problem. *blush*
Ben Blank
But plese, do correct your answer -- it is still the accepted one. If you mention that .[something] is incorrect syntax, then I'll cancel my downvote.
Dimitre Novatchev
Re-clarified my clarifications. :-)
Ben Blank
You read between the lines and answered my question Ben. Thanks again, as yours was and is still the only helpful answer here for my particular problem.
+1  A: 

While Ben has answered your question correctly, using for-each is most definitely the wrong general approach. After all this is XSLT. So you are probably more looking for something like this:

<xsl:if test="/books/book[text()='1112']">
  Success
</xsl:if>
tcurdt
True; I assumed the OP was just snipping out the relevant portion of a larger `for-each` block, but if that's the entirety of it, it would be far better to use this simple `if` instead.
Ben Blank
+2  A: 

I'm trying to setup a condition that tests the value of the current node in the for-each, but I'm doing something wrong:

The first thing that is incorrect is the syntax:

   .[='1112']

There are two things wrong here:

  1. Within [ and ] there is no predicate: the "=" operator needs two arguments but only one is provided.

  2. .[x = y] is still invalid syntax, although the predicate is OK. This has to be specified as:

    self::node()[condition]

The second thing in the provided code that can be improved is the <xsl:for-each> instruction, which isn't necessary at all; A single XPath expression will be sufficient.

To summarize, one possible XPath expression that evaluates to the required boolean value is:

   /books/book[. = '1112']

If it is really necessary that the condition be tested inside the <xsl:for-each> instruction, then one correct XPath expression I would use is:

   . = '1112'

The above is a string comparison and may not evaluate to true() if there are spaces around. Therefore, a numerical comparison may be better:

  . = 1112
Dimitre Novatchev
A: 

XSLT has a function specially for this problem.

http://www.w3.org/TR/xslt#function-current

Dominic Cronin