xsl-list
[Top] [All Lists]

[xsl] Help to unflatten xml file

2010-11-30 15:43:31
I want to nest sections from a flat XML file based on the value of a section 
attribute. I have done this before with a similar but slightly different 
situation. I'm missing something with the behavior of xsl:for-each-group.

Thanks in advance for any help that can be provided.
Steve

My example data:

<?xml version="1.0" encoding="UTF-8"?>
<book type="Tech_Manual">
    <bookinfo>
        <title>client manual</title>
        <subtitle>performance data</subtitle>
    </bookinfo>
    <section id="a--21" label="1">
        <title lang="en">Preface</title>
        <para>some interesting stuff</para>
    </section>
    <section id="a--22" label="2">
        <title lang="en">Preface</title>
        <para>some more interesting stuff</para>
    </section>
    <section id="a--23" label="2">
        <title lang="en">Preface</title>
        <para>some more interesting stuff</para>
    </section>
    <section id="a--24" label="3">
        <title lang="en">Preface</title>
        <para>some more interesting stuff</para>
    </section>
    <section id="a--25" label="1">
        <title lang="en">Cautions</title>
        <para>some interesting stuff</para>
    </section>
</book>

My stylesheet:
<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
    xmlns:xs="http://www.w3.org/2001/XMLSchema";>

    
    <xsl:output
        method="xml" 
        omit-xml-declaration="no" 
        encoding="utf-8" 
        indent="yes"/>
    <xsl:strip-space elements="*"/>
  

<!-- Pass one - recognize section headers and create nested <sections/> -->
   <xsl:template match="/">
       <xsl:variable name="unflattenedDoc">
           <book>
              <xsl:copy>
                <xsl:for-each-group select="*" 
group-starting-with="section[(_at_)label=1]">
                  <xsl:apply-templates select="." mode="group"/>
                </xsl:for-each-group>
              </xsl:copy>   
          </book>
       </xsl:variable>
       <xsl:apply-templates select="$unflattenedDoc" mode="pass2"/>
   </xsl:template>
    
  <xsl:template match="section[(_at_)label=1]" mode="group">
    <section>
        <xsl:for-each-group select="current-group()" 
group-starting-with="section[(_at_)label=2]">
            <xsl:apply-templates select="." mode="group"/>
        </xsl:for-each-group>
    </section>
  </xsl:template>
    
  <xsl:template match="section[(_at_)label=2]" mode="group">
    <section>
        <xsl:for-each-group select="current-group()" 
group-starting-with="section[(_at_)label=3]">
            <xsl:apply-templates select="." mode="group"/>
        </xsl:for-each-group>
    </section>
  </xsl:template>
    
  <xsl:template match="section[(_at_)label=3]" mode="group">
     <section>
         <xsl:copy-of select="current-group()"/>
     </section>
  </xsl:template>


<xsl:template match="node()" mode="group">
    <xsl:copy-of select="current-group()"/> </xsl:template>
    
   
  <!-- 2nd pass -->  
    <xsl:template match="book" mode="pass2">
        <xsl:copy-of select="."/>
    </xsl:template>   
     
</xsl:stylesheet>

My desired result:

<book type="Tech_Manual">
    <bookinfo>
        <title>client manual</title>
        <subtitle>performance data</subtitle>
    </bookinfo>
    <section id="a--21" label="1">
        <title lang="en">Preface</title>
        <para>some interesting stuff</para>
    
    <section id="a--22" label="2">
        <title lang="en">Preface</title>
        <para>some more interesting stuff</para>
    </section>
    <section id="a--23" label="2">
        <title lang="en">Preface</title>
        <para>some more interesting stuff</para>

    <section id="a--24" label="3">
        <title lang="en">Preface</title>
        <para>some more interesting stuff</para>
    </section>
    </section>
    </section>
    <section id="a--25" label="1">
        <title lang="en">Cautions</title>
        <para>some interesting stuff</para>
    </section>
</book>

My actual result:

<book xmlns:xs="http://www.w3.org/2001/XMLSchema";>
   <book type="Tech_Manual">
      <bookinfo>
         <title>client manual</title>
         <subtitle>performance data</subtitle>
      </bookinfo>
      <section id="a--21" label="1">
         <title lang="en">Preface</title>
         <para>some interesting stuff</para>
      </section>
      <section id="a--22" label="2">
         <title lang="en">Preface</title>
         <para>some more interesting stuff</para>
      </section>
      <section id="a--23" label="2">
         <title lang="en">Preface</title>
         <para>some more interesting stuff</para>
      </section>
      <section id="a--24" label="3">
         <title lang="en">Preface</title>
         <para>some more interesting stuff</para>
      </section>
      <section id="a--25" label="1">
         <title lang="en">Cautions</title>
         <para>some interesting stuff</para>
      </section>
   </book>
</book>

--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--

<Prev in Thread] Current Thread [Next in Thread>