Re: [xsl] Need assistance with conditional logic and counter in XSLT 2.0

Subject: Re: [xsl] Need assistance with conditional logic and counter in XSLT 2.0
From: Terry Badger <terry_badger@xxxxxxxxx>
Date: Wed, 14 Mar 2012 12:05:21 -0700 (PDT)
This should do the job:<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheetxmlns:xsl="http://www.w3.org/1999/XSL/Transform"xmlns:xs="http
://www.w3.org/2001/XMLSchema"exclude-result-prefixes="xs"
version="2.0">
<xsl:strip-spaceelements="*"/>
<xsl:outputmethod="text"/>
<!-- convert
elements to output strings -->
<xsl:variablename="names-to-strings">
<items>
<item>
<element>OrderNumber</element>
<string> Order Number: </string>
</item>
<item>
<element>CustomerID</element>
<string> Customer ID: </string>
</item>
<item>
<element>Total</element>
<string> Total: </string>
</item>
<item>
<element>ReturnDate</element>
<string> Return Date: </string>
</item>
<item>
<element>ReturnReason</element>
<string> Return Reason: </string>
</item>
</items>
</xsl:variable>
<!-- start here -->
<xsl:templatematch="/wrapper">
<xsl:apply-templates/>
</xsl:template>
<!-- process order element -->
<xsl:templatematch="Order">
<xsl:text>&#x0A;Order&#x0A;</xsl:text>
<!-- don't
process Return with no children -->
<xsl:for-eachselect="./*[not(name() =
'Return' and not(./ReturnDate | ./ReturnReason))]">
<xsl:variablename="level-1"select="concat(position() , '.')"/>
<xsl:choose>
<xsl:whentest="name() = 'Return' ">
<xsl:for-eachselect="./*">
<xsl:value-ofselect="$level-1"/>
<xsl:iftest="position() -1 != 0">
<xsl:value-ofselect="position() - 1"/>
</xsl:if>
<xsl:value-ofselect="$names-to-strings/items/item[element =
current()/name()]/string"/>
<xsl:value-ofselect="."/>
<xsl:text>&#x0A;</xsl:text>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:value-ofselect="$level-1"/>
<xsl:value-ofselect="$names-to-strings/items/item[element =
current()/name()]/string"/>
<xsl:text>&#x0A;</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
<!-- turn off default templates
-->
<xsl:templatematch="processing-instruction()|comment()|*|@*|text()"/>
</xsl:stylesheet>
Terry


________________________________
From: Jennifer
Elkhouri <jwelkhouri@xxxxxxxxx>
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx 
Sent:
Wednesday, March 14, 2012 8:58 AM
Subject: [xsl] Need assistance with
conditional logic and counter in XSLT 2.0

I am very new to XSLT, so thank you
in advance for helping me out. My
issue is related to wanting to print output
conditionally using
counters. If an element returns no data, I do not want to
print the
header for that section (easy enough). However, these headers need
to
be numbered ... which is where I am having a problem.

For example, given:
 (XML for record 1234):
 <Order>
  <OrderNumber>1234</OrderNumber>
 
<CustomerID>111</CustomerID>
  <Return/>
  <Total>$344</Total>
 </Order>
 (XML for record 1235):
 <Order>
   <OrderNumber>1235</OrderNumber>
  
<CustomerID>233</CustomerID>
   <Return>
     
<ReturnDate>3/15/2011</ReturnDate>
      <ReturnReason>Too small</ReturnDate>
   </Return>
   <Total>$455</Total>
 </Order>

 If someone selected record 1,
they expect the transformed html output to be:

 1. Order Number: 1234
 2.
Customer ID: 111
 3. Total: $344

 If someone selected record 2, they expect
the transformed html output to be:
 1. Order Number: 1235
 2. Customer ID: 233
 3. Return Date: 3/15/2011
 3.1. Return Reason: Too small
 4. Total: $455

I
learned quite quickly that I can't do a simple counter. From what
I've read,
it is suggested that I use a recursive template. Can you
please help me?
Below is my sample code ... (only showing a snippet for brevity. I am
using
XSLT 2.0 and have set a global variable of newLine for a
carriage return.)
<xsl:value-of select="/Order/OrderNumber" /><xsl:text>Order Number:
</xsl:text>
<xsl:call-template name="counter">
   <xsl:with-param name="index"
select="position()"/>
</xsl:call-template> <xsl:value-of select="$newLine" />
<xsl:value-of select="/Order/CustomerID" /><xsl:text>Customer ID: </xsl:text>
<xsl:call-template name="counter">
<xsl:with-param name="index"
select="position()"/>
</xsl:call-template> <xsl:value-of select="$newLine" />
<xsl:if test="/Order/Return/ReturnDate">
   <xsl:value-of
select="/Order/Return/ReturnDate" /><xsl:text>Return
Date: </xsl:text>
  
<xsl:call-template name="counter">
    <xsl:with-param name="index"
select="position()"/>
   </xsl:call-template> <xsl:value-of select="$newLine"
/>

   <xsl:value-of select="/Order/Return/ReturnReason"
/><xsl:text>Return
Reason: </xsl:text>
   <xsl:call-template name="counter">
   <xsl:with-param
name="index" select="position()"/>
   </xsl:call-template> <xsl:value-of
select="$newLine" />

</xsl:if>

<xsl:value-of select="/Order/Total"
/><xsl:text>Total: </xsl:text>
<xsl:call-template name="counter">
<xsl:with-param name="index" select="position()"/>
</xsl:call-template>
<xsl:value-of select="$newLine" />

<xsl:template name="counter">
  <xsl:param
name="index" select="1"/>
  <xsl:if test="$index &lt;= 10">            <!-- I
put this in here
so it doesn't fall into an infinite loop. There's got to be a
better
way? -->
    <xsl:value-of select="$index"/>
    <xsl:call-template
name="counter">
      <xsl:with-param name="index" select="$index + 1"/>
   
</xsl:call-template>
  </xsl:if>
</xsl:template>

Current Thread