views:

28

answers:

2

I'm working on an interface with a 3rd party app that basically needs to take XML that was spat out by the app and convert it into XML our system can deal with. It's basically just applying a stylesheet to the original XML to make it looks like "our" XML. I've noticed that in other stylesheets we have, there are constructs like this:

<xsl:for-each select="State">
    <StateAbbreviation>
        <xsl:value-of select="."/>
    </StateAbbreviation>
</xsl:for-each>

Basically, the "in" XML has a State tag that I need to output as our recognized StateAbbreviation tag. However, I want to ONLY output the StateAbbreviation tag if the "in" XML contains the State tag. The block above accomplishes this just fine, but is not very intuitive (at least it wasn't to me), as every time I see a for-each I assume there is more than one, whereas in these cases there is 0 or 1.

My question: is that a standard-ish construct? If not, is there a more preferred way to do it? I could obviously check the string length (which is also being done in other stylesheets), but would like to do it the same, "best" way everywhere (assuming of course that a "best" way exists. Advice? Suggestions?

+3  A: 

You could replace the for-each with:

<xsl:if test="State">
Ben
It occurs to me you might also need to change the <xsl:value-of> to: <xsl:value-of select="State" />.
Ben
Wow, that's such a ridiculously obvious answer, I don't know why a) the original developer didn't do that and why b) I wasn't able to figure that out on my own. Guess I've powerfully demonstrated my XSL newb-ness today. Thanks for the help!
Morinar
+1  A: 

It is a recommended good practice in XSLT to prefer using xsl:apply-templates over xsl:for-each.

In this case a simple

<xsl:apply-templates select="State"/>

solves the problem in a most elegant way. No conditionals are necessary and the XSLT processor does all the work to apply the template best matching each State child.

Dimitre Novatchev