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

Flat to hierarchical with for-each-group (XSLT 2.0 so

Subject: Flat to hierarchical with for-each-group (XSLT 2.0 solution)
From: JBryant@xxxxxxxxx
Date: Wed, 25 May 2005 11:33:55 -0500
flat to hierarchical
Nadia's question yesterday set me to thinking about how to turn flat XML 
into hierarchical XML by using XSLT 2.0's for-each-group instruction.

To simplify matters, I wrote a solution against a generic data structure 
rather than against Nadia's specific structure (from FrameMaker). Nadia: 
I'm sure you can translate this solution to your specific source files. If 
you do have trouble, though, I'll be happy to help.

I think this will become an increasingly common problem as more and more 
companies try to use FrameMaker and Word as front ends to XML-based 
single-sourcing document-production systems.

So, without further ado, here's the source file (flat as the proverbial 
pancake):

<?xml version="1.0" encoding="UTF-8"?>
<doc>
  <heading1>H11</heading1>
  <para>P1</para>
  <para>P2</para>
  <para>P3</para>
  <heading2>H21</heading2>
  <para>P4</para>
  <para>P5</para>
  <heading3>H31</heading3>
  <para>P6</para>
  <heading2>H22</heading2>
  <para>P7</para>
  <para>P8</para>
  <heading1>H12</heading1>
  <para>P9</para>
</doc>

Here's the XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:template match="doc">
    <doc>
      <xsl:for-each-group select="*" group-starting-with="heading1">
        <heading1 title="{current-group()[1]}">
          <xsl:for-each-group select="current-group()" 
group-starting-with="heading2">
            <xsl:choose>
              <xsl:when test="current-group()[1]/name() = 'heading2'">
                <heading2 title="{current-group()[1]}">
                  <xsl:for-each-group select="current-group()" 
group-starting-with="heading3">
                    <xsl:choose>
                      <xsl:when test="current-group()[1]/name() = 
'heading3'">
                        <heading3 title="{current-group()[1]}">
                          <xsl:apply-templates select="current-group()"/>
                        </heading3>
                      </xsl:when>
                      <xsl:otherwise>
                        <xsl:apply-templates select="current-group()"/>
                      </xsl:otherwise>
                    </xsl:choose>
                  </xsl:for-each-group>
                </heading2>
              </xsl:when>
              <xsl:otherwise>
                <xsl:apply-templates select="current-group()"/>
              </xsl:otherwise>
            </xsl:choose>
          </xsl:for-each-group>
        </heading1>
      </xsl:for-each-group>
    </doc>
  </xsl:template>

  <xsl:template match="heading1|heading2|heading3"/>

  <xsl:template match="para">
    <xsl:copy-of select="."/>
  </xsl:template>

</xsl:stylesheet>

And here's the result (now hierarchical):

<?xml version="1.0" encoding="UTF-8"?>
<doc>
  <heading1 title="H11">
    <para>P1</para>
    <para>P2</para>
    <para>P3</para>
    <heading2 title="H21">
      <para>P4</para>
      <para>P5</para>
      <heading3 title="H31">
        <para>P6</para>
      </heading3>
    </heading2>
    <heading2 title="H22">
      <para>P7</para>
      <para>P8</para>
    </heading2>
  </heading1>
  <heading1 title="H12">
    <para>P9</para>
  </heading1>
</doc>

The only mystery to me is why I had to use test="current-group()[1]/name() 
= 'heading2'" rather than test="current-group()/heading2" or just 
test="heading2". I'd love to hear the explanation for that one.

Thanks.

Jay Bryant
Bryant Communication Services
(presently consulting at Synergistic Solution Technologies)

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.