XSL can be so frustrating.
So today, I wanted to be able to do something like this:
<xsl:variable name="foo"> <xsl:choose> <xsl:when test="bar"> <xsl:copy-of select="bar"/> </xsl:when> <xsl:otherwise> <xsl:copy-of select="bat"/> </xsl:otherwise> </xsl:choose> </xsl:variable>
(Set the variable “foo” to the contents of the node “bar” if available, otherwise “bat”.)
<xsl:value-of select="$foo/childNode1"/> <xsl:value-of select="$foo/childNode2"/>
(Get child nodes of either “bar” or “bat”, depending on whether “bar” is present in the XML or not.)
Seems simple and logical enough, don’t you think?
However, I kept getting a ClassCastException when I tried this.
So, Google to the rescue. I found this post which explained the problem. Basically, the contents of the variable $foo aren’t a normal node set. Why not? Beats me. So what are they? Something called a result tree fragment. And you can’t select nodes from a result tree fragment. Darn!
However, if you set the variable using a select attribute instead of the body, you’ll get a proper node set. That doesn’t help in this case, though, since I need a choose to determine what will go in the variable.
In this case, I was able to work around the limitation by using more verbose code - creating more variables and choose expressions. But that type of code could get really out of hand if you needed to select lots of child nodes, instead of just the two I needed in this instance.
Most of the time XSL is a pretty ok language (once you get past the initial learning curve), but it’s these occasional weird cases that make you just want to shake the people that designed the language.