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

Re: Transforming non structured XML into structured XM

Subject: Re: Transforming non structured XML into structured XML with XSLT
From: Dimitre Novatchev <dnovatchev@xxxxxxxxx>
Date: Wed, 8 Aug 2001 08:13:26 -0700 (PDT)
concat xm
bruno.o.faure@xxxxxxxxxxxxxx wrote:

> I'm trying to write a XSLT style sheet that transforms a non-structured xml
> document to a structured xml document and am in troubles :
> 
> My xml documents looks like a flat modelization of a treeview :
> 
> <row lib="data1" folder1="A" folder2="C" />
> <row lib="data2" folder1="A" folder2="C" />
> <row lib="data3" folder1="A" folder2="C" />
> <row lib="data1" folder1="A" folder2="D" />
> <row lib="data2" folder1="A" folder2="D" />
> <row lib="data3" folder1="A" folder2="D" />
> <row lib="data1" folder1="B" folder2="E" />
> <row lib="data2" folder1="B" folder2="E" />
> <row lib="data3" folder1="B" folder2="E" />
> <row lib="data1" folder1="B" folder2="F" />
> <row lib="data2" folder1="B" folder2="F" />
> <row lib="data3" folder1="B" folder2="F" />
> <row lib="data1" folder1="B" folder2="G" />
> <row lib="data2" folder1="B" folder2="G" />
> <row lib="data3" folder1="B" folder2="G" />
> <row lib="data1" folder1="B" folder2="H" />
> <row lib="data2" folder1="B" folder2="H" />
> <row lib="data3" folder1="B" folder2="H" />
> 
> Basically the first line means that the folder A contains the folder C  which 
> contains data1
> And so on for the others
> I would need to transform it in the following structured XML document :
> 
> <A>
>      <C>
>      <data1/>
>      <data2/>
>      <data3/>
>      </C>
>      <D>
>      <data1/>
>      <data2/>
>      <data3/>
>      </D>
> </A>
> <B>
>      <E>
>      <data1/>
>      <data2/>
>      <data3/>
>      </E>
>      <F>
>      <data1/>
>      <data2/>
>      <data3/>
>      </F>
>      [...]
> </B>
> 
> The XML file is dynamically generated so folder names and folder depth are not 
> know in advance.
> I can't see how to do that, and I don't event know if it is possible.

Hi Bruno,

Here's the solution:

xml source:
----------
<rows>
    <row lib="data1" folder1="A" folder2="C" />
    <row lib="data2" folder1="A" folder2="C" />
    <row lib="data3" folder1="A" folder2="C" />
    <row lib="data1" folder1="A" folder2="D" />
    <row lib="data2" folder1="A" folder2="D" />
    <row lib="data3" folder1="A" folder2="D" />
    <row lib="data1" folder1="B" folder2="E" />
    <row lib="data2" folder1="B" folder2="E" />
    <row lib="data3" folder1="B" folder2="E" />
    <row lib="data1" folder1="B" folder2="F" />
    <row lib="data2" folder1="B" folder2="F" />
    <row lib="data3" folder1="B" folder2="F" />
    <row lib="data1" folder1="B" folder2="G" />
    <row lib="data2" folder1="B" folder2="G" />
    <row lib="data3" folder1="B" folder2="G" />
    <row lib="data1" folder1="B" folder2="H" />
    <row lib="data2" folder1="B" folder2="H" />
    <row lib="data3" folder1="B" folder2="H" />
</rows>


xsl stylesheet:
--------------
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes" omit-xml-declaration="yes"/>
  <xsl:key name="kRow_f1_f2" match="row" use="concat(@folder1, '~', @folder2)"/>
  <xsl:key name="kRow_f1" match="row" use="@folder1"/>
  <xsl:key name="kRow_f2" match="row" use="@folder2"/>
  <xsl:variable name="manySpaces" select="'                              '"/>
  <xsl:variable name="linkList" select="/rows/row" />

  <xsl:template match="/">
    <xsl:call-template name="constructHierarchy">
      <xsl:with-param name="linkList" select="$linkList" />
    </xsl:call-template>
  </xsl:template>

  <xsl:template name="constructHierarchy">
    <xsl:param name="linkList" select="/.." />

       <xsl:for-each select="$linkList[not(key('kRow_f2', @folder1))]">
         <xsl:if test="count(. | key('kRow_f1', @folder1)[1])=1">
           <xsl:call-template name="makeElement">
             <xsl:with-param name="pElement" select="@folder1"/>
             <xsl:with-param name="indent" select="0"/>
           </xsl:call-template>
        </xsl:if>
      </xsl:for-each>
  </xsl:template>

  <xsl:template name="makeElement">
    <xsl:param name="pElement" select="'ErrorUnknown'"/>
    <xsl:param name="indent" select="0"/>

    <xsl:text>&#xA;</xsl:text>
    <xsl:value-of select="substring($manySpaces, 1, $indent)"/>
    <xsl:element name="{$pElement}">
      <xsl:for-each select="key('kRow_f1', $pElement)
                                    [
                                      count(. | key('kRow_f1_f2', 
                                                     concat(@folder1, 
                                                            '~', 
                                                            @folder2
                                                            )
                                                    )[1]
                                           ) = 1
                                     ]">
           <xsl:call-template name="makeElement">
             <xsl:with-param name="pElement" select="@folder2"/>
             <xsl:with-param name="indent" select="$indent + 2"/>
           </xsl:call-template>
      </xsl:for-each>
      
      <xsl:for-each select="key('kRow_f2', $pElement)">
        <xsl:element name="{@lib}"/>
      </xsl:for-each>
         
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

Result:
------

<A>
  <C>
<data1 />
<data2 />
<data3 />
</C>
  <D>
<data1 />
<data2 />
<data3 />
</D>
</A>
<B>
  <E>
<data1 />
<data2 />
<data3 />
</E>
  <F>
<data1 />
<data2 />
<data3 />
</F>
  <G>
<data1 />
<data2 />
<data3 />
</G>
  <H>
<data1 />
<data2 />
<data3 />
</H>
</B>

As you can see, a minor thing remainds -- the indentation (if needed at all) could
be improved.

Hope this helped.

Cheers,
Dimitre Novatchev.




__________________________________________________
Do You Yahoo!?
Make international calls for as low as $.04/minute with Yahoo! Messenger
http://phonecard.yahoo.com/

 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


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.