nat
nat

Reputation: 2197

XSLT Choose based on a node

I have some XML thus

<root>
  <TemplateNode>
    <Heading>
      <ID>1</ID>
      <Name>HeadingNodeTest</Name>
      <Order>1</Order>
      <Text>This is a Heading Node</Text>
    </Heading>
  </TemplateNode>
  <TemplateNode>
    <SimpleText>
      <ID>2</ID>
      <Name>PlainTextNode</Name>
      <Order>2</Order>
      <Text>This is some plain text. Blah blah blah .. etc</Text>
     </SimpleText>
  </TemplateNode>
  <TemplateNode>
    <RadioTemplateNode>

...etc

I would like to be able to do an xslt choose based on the Heading/SimpleText type bit for example

<xsl:for-each select="TemplateNode">
   <xsl:choose>
       <xsl:when test="TemplateNode/* = Header">
           ..do stuff
       </xsl:when>
       <xsl:when test="TemplateNode/* = SimpleText">
           ..do other stuffstuff
       </xsl:when>
       ...etc
   </xsl:choose>
</xsl:for-each select="TemplateNode">

*<xsl:when test="TemplateNode/* = Header"> can I even do something like this, or am I better off changing the XML to and selecting on that?

or do I need to set a variable and choose on that..?

thanks nat

Upvotes: 2

Views: 174

Answers (2)

Dimitre Novatchev
Dimitre Novatchev

Reputation: 243459

It is a good principle in XSLT to avoid conditionals as much as possible.

Instead of

<xsl:for-each select="TemplateNode"> 
   <xsl:choose> 
       <xsl:when test="TemplateNode/* = Header"> 
           ..do stuff 
       </xsl:when> 
       <xsl:when test="TemplateNode/* = SimpleText"> 
           ..do other stuffstuff 
       </xsl:when> 
       ...etc 
   </xsl:choose> 
</xsl:for-each select="TemplateNode"> 

Write:

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

And also have these templates:

 <xsl:template match="TemplateNode[Heading]">
  <!-- Processing here -->
 </xsl:template>

 <xsl:template match="TemplateNode[SimpleText]">
  <!-- Processing here -->
 </xsl:template>

 <xsl:template match="TemplateNode[RadioTemplateNode]">
  <!-- Processing here -->
 </xsl:template>

This code is simpler and easier to understand and maintain.

Upvotes: 0

Lukas Eder
Lukas Eder

Reputation: 220762

You shouldn't adapt your data to your code. If the XML is OK with you, then leave it as it is. This would work, for instance

<xsl:for-each select="/root/TemplateNode">
  <xsl:choose>
    <xsl:when test="Heading">
      ..do stuff
    </xsl:when>
    <xsl:when test="SimpleText">
      ..do other stuff
    </xsl:when>
  ...

Of course, this only works if the various TemplateNode child elements mutually exclude each other. This is another option:

<xsl:apply-templates select="/root/TemplateNode/*"/>

And then

<xsl:template match="/root/TemplateNode/Heading">
    ..do stuff
</xsl:template>
<xsl:template match="/root/TemplateNode/SimpleText">
    ..do other stuff
</xsl:when>

Upvotes: 1

Related Questions