Flatten XML using XSLT but based on nesting level
        Posted  
        
            by 
                user2532750
            
        on Stack Overflow
        
        See other posts from Stack Overflow
        
            or by user2532750
        
        
        
        Published on 2013-06-28T17:43:36Z
        Indexed on 
            2013/06/29
            10:21 UTC
        
        
        Read the original article
        Hit count: 390
        
I'm new to XSLT and I'm trying to write some XSLT that will flatten any given XML such that a new line occurs whenever the nesting level changes. My input can be any XML document, with any number of nested levels so the structure isn't known to the XSLT. Due to the tools available to me, my solution has to use XSLT version 1.0.
For example.
<?xml version="1.0"?>
<ROWSET>
  <ROW>
    <CUSTOMER_ID>0</CUSTOMER_ID>
    <NAME>Default Company</NAME>
    <BONUSES>
      <BONUSES_ROW>
        <BONUS_ID>21</BONUS_ID>
        <DESCRIPTION>Performance Bonus</DESCRIPTION>
      </BONUSES_ROW>
      <BONUSES_ROW>
        <BONUS_ID>26</BONUS_ID>
        <DESCRIPTION>Special Bonus</DESCRIPTION>
      </BONUSES_ROW>
    </BONUSES>
  </ROW>
  <ROW>
    <CUSTOMER_ID>1</CUSTOMER_ID>
    <NAME>Dealer 1</NAME>
    <BONUSES>
      <BONUSES_ROW>
        <BONUS_ID>27</BONUS_ID>
        <DESCRIPTION>June Bonus</DESCRIPTION>
        <BONUS_VALUES>
          <BONUS_VALUES_ROW>
            <VALUE>10</VALUE>
            <PERCENT>N</PERCENT>
          </BONUS_VALUES_ROW>
          <BONUS_VALUES_ROW>
            <VALUE>11</VALUE>
            <PERCENT>Y</PERCENT>
          </BONUS_VALUES_ROW>
        </BONUS_VALUES>
      </BONUSES_ROW>
    </BONUSES>
  </ROW>
<ROWSET>
needs to becomes....
0, Default Company
21, Performance Bonus
26, Special Bonus
1, Dealer 1
27, June Bonus
10, N
11, Y
The XSLT I've written so far is...
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text" encoding="iso-8859-1"/>
  <xsl:strip-space elements="*" />
  <xsl:template match="/*/child::*">
    <xsl:apply-templates select="*"/> 
  </xsl:template>
   <xsl:template match="*">
     <xsl:value-of select="text()" />
     <xsl:if test="position()!= last()"><xsl:text>,</xsl:text></xsl:if>
     <xsl:if test="position()= last()"><xsl:text>
</xsl:text></xsl:if>     
     <xsl:apply-templates select="./child::*"/>          
   </xsl:template>
</xsl:stylesheet> 
but my output just isn't correct, with gaps and unnecessary data.
0,Default Company,
,21,Performance Bonus
26,Special Bonus
1,Dealer 1,
27,June Bonus,
,10,N
11,Y
It seems there needs to be a check as whether or not a node can contain text, but I'm stuck and could do with an XSLT expert's help.
© Stack Overflow or respective owner