[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Re: Help to unflatten xml file

Subject: Re: Help to unflatten xml file
From: "G. Ken Holman" <gkholman@xxxxxxxxxxxxxxxxxxxx>
Date: Tue, 30 Nov 2010 17:16:06 -0500
Re:  Help to unflatten xml file
At 2010-11-30 15:43 -0600, Steve Ylvisaker wrote:
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.

Actually, you missed a very basic first step and were off on a tangent with your testing. Once that first step is made correctly, then it was just a matter of finding out what was missing.


<xsl:template match="/">
<xsl:variable name="unflattenedDoc">
<book>
<xsl:copy>
<xsl:for-each-group select="*" group-starting-with="section[@label=1]">

Note that you are selecting all of the children of the *root* node, not of the document element ... in my example before I'm selecting "*/*".


With that first step made correctly, then the rest falls into place.

I hope the answer below helps.

. . . . . . . . . Ken

p.s. I'm assuming your "pass2" is going to eventually be more detailed than simply preserving the nodes, because if not then you don't need the second pass.

T:\ftemp>type steve.xml
<?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>

T:\ftemp>call xslt2 steve.xml steve.xsl
<?xml version="1.0" encoding="utf-8"?>
<book>
   <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>
T:\ftemp>type steve.xsl
<?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"
    exclude-result-prefixes="xs">


<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[@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[@label=1]" mode="group">
    <section>
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates mode="group"/>
        <xsl:for-each-group select="current-group()[position()>1]"
                            group-starting-with="section[@label=2]">
            <xsl:apply-templates select="." mode="group"/>
        </xsl:for-each-group>
    </section>
  </xsl:template>

  <xsl:template match="section[@label=2]" mode="group">
    <section>
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates mode="group"/>
        <xsl:for-each-group select="current-group()[position()>1]"
                            group-starting-with="section[@label=3]">
            <xsl:apply-templates select="." mode="group"/>
        </xsl:for-each-group>
    </section>
  </xsl:template>

  <xsl:template match="section[@label=3]" mode="group">
     <section>
       <xsl:copy-of select="@*"/>
       <xsl:apply-templates mode="group"/>
     </section>
  </xsl:template>


<xsl:template match="node()" mode="group"> <xsl:copy-of select="."/> </xsl:template>


<!-- 2nd pass --> <xsl:template match="book" mode="pass2"> <xsl:copy-of select="."/> </xsl:template>

</xsl:stylesheet>

T:\ftemp>rem Done!



--
Contact us for world-wide XML consulting & instructor-led training
Crane Softwrights Ltd.          http://www.CraneSoftwrights.com/s/
G. Ken Holman                 mailto:gkholman@xxxxxxxxxxxxxxxxxxxx
Legal business disclaimers:  http://www.CraneSoftwrights.com/legal

Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.