[xsl] Conditional Grouping

Subject: [xsl] Conditional Grouping
From: "Alex Zelinski" <Alex.Zelinski@xxxxxxxxxxxx>
Date: Wed, 09 Mar 2005 12:28:04 -0600
Hi,
 
I am trying to set up my XSLT (version 1.0) to process the XML and
group only if a condition is met.  I would like to only group records
if
the REF_DOC_NO begins with a 7.  Otherwise there would be no grouping.

For a particular set of XML, either all of the records would have
REF_DOC_NOs that start with a 7 or none of them would.
 
Sample XML that should not be grouped because the REF_DOC_NOs do not
start with a 7:
 
<LINEITEMS>
      <item>
        <ITEM_ID>1</ITEM_ID>
        <ACCOUNT>0800000003</ACCOUNT>
        <DOC_NO>1400000131</DOC_NO>
        <ITEM_NUM>002</ITEM_NUM>
        <REF_DOC_NO></REF_DOC_NO>
      </item>
      <item>
        <ITEM_ID>2</ITEM_ID>
        <ACCOUNT>0800000003</ACCOUNT>
        <DOC_NO>1600000098</DOC_NO>
        <ITEM_NUM>001</ITEM_NUM>
        <REF_DOC_NO></REF_DOC_NO>
      </item>
      <item>
        <ITEM_ID>3</ITEM_ID>
        <ACCOUNT>0800000003</ACCOUNT>
        <DOC_NO>1600000099</DOC_NO>
        <ITEM_NUM>001</ITEM_NUM>
        <REF_DOC_NO></REF_DOC_NO>
      </item>
      <item>
        <ITEM_ID>4</ITEM_ID>
        <ACCOUNT>0800000003</ACCOUNT>
        <DOC_NO>1400000160</DOC_NO>
        <ITEM_NUM>002</ITEM_NUM>
        <REF_DOC_NO>TEST</REF_DOC_NO>
      </item>
      <item>
        <ITEM_ID>5</ITEM_ID>
        <ACCOUNT>0800000003</ACCOUNT>
        <DOC_NO>0900000317</DOC_NO>
        <ITEM_NUM>001</ITEM_NUM>
        <REF_DOC_NO>TEST 2</REF_DOC_NO>
      </item>
    </LINEITEMS>
 
Sample XML that should be grouped because the REF_DOC_NOs start with a
7:
 
<LINEITEMS>
      <item>
        <ITEM_ID>1</ITEM_ID>
        <ACCOUNT>0800000002</ACCOUNT>
        <DOC_NO>1400000131</DOC_NO>
        <ITEM_NUM>002</ITEM_NUM>
        <REF_DOC_NO>7000000195</REF_DOC_NO>
      </item>
      <item>
        <ITEM_ID>2</ITEM_ID>
        <ACCOUNT>0800000002</ACCOUNT>
        <DOC_NO>1600000098</DOC_NO>
        <ITEM_NUM>001</ITEM_NUM>
        <REF_DOC_NO>7000000195</REF_DOC_NO>
      </item>
      <item>
        <ITEM_ID>3</ITEM_ID>
        <ACCOUNT>0800000002</ACCOUNT>
        <DOC_NO>1600000099</DOC_NO>
        <ITEM_NUM>001</ITEM_NUM>
        <REF_DOC_NO>7000000195</REF_DOC_NO>
      </item>
      <item>
        <ITEM_ID>4</ITEM_ID>
        <ACCOUNT>0800000002</ACCOUNT>
        <DOC_NO>1400000160</DOC_NO>
        <ITEM_NUM>002</ITEM_NUM>
        <REF_DOC_NO>7000000195</REF_DOC_NO>
      </item>
      <item>
        <ITEM_ID>5</ITEM_ID>
        <ACCOUNT>0800000002</ACCOUNT>
        <DOC_NO>0900000317</DOC_NO>
        <ITEM_NUM>001</ITEM_NUM>
        <REF_DOC_NO>7000000195</REF_DOC_NO>
      </item>
    </LINEITEMS>
 
This is the XSLT that I have come up with that works but is not very
elegant.  I had to duplicate the HTML.  There is a lot more HTML than
what I have put in the post.
 
<xsl:key name="refdocno-group" match="item" use="REF_DOC_NO" />
 
<xsl:template match="LINEITEMS">
  <xsl:for-each select="//item[generate-id() =
generate-id(key('refdocno-group', REF_DOC_NO)[1])]">
    <xsl:choose>  
 
<!-- Display all documents if not for invoice list -->
      <xsl:when test="substring(REF_DOC_NO,1,1)!='7'">
        <xsl:for-each select="key('refdocno-group', REF_DOC_NO)">
          <tr>
           <td>
             <xsl:value-of select="DOC_NO"/>
          </td>
          <td>
            <xsl:value-of select="REF_DOC_NO"/>
          </td>
        </tr>
      </xsl:for-each>
    </xsl:when>
 
<!-- Display only unique documents if for invoice list -->
    <xsl:otherwise>
      <tr>
        <td>
          <xsl:value-of select="DOC_NO"/>
        </td>
        <td>
          <xsl:value-of select="REF_DOC_NO"/>
        </td>
      </tr>
    </xsl:otherwise>
    </xsl:choose>
  </xsl:for-each>
</xsl:template>
 

Does anyone know a better way to do this?  Please let me know if you
have any questions.  Thank you for your assistance.
 
Alex Zelinski

Current Thread