Subject: [xsl] 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) |
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>
</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 |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] Formatting Date in xsl, cutlass | Thread | [xsl] Preceding Ancestors, Richard Mitchell |
RE: [xsl] xml2xml problem!, Ivan Pedruzzi | Date | [xsl] Preceding Ancestors, Richard Mitchell |
Month |