Hi All,
I've been working on an XSLT for days now, and cannot find the solution to
one problem. I have a source XML document containing one level of elements.
Each element contains a path element that holds information on what path
the element was extracted from.
Now, through XSL transformation, I would like to recreate the tree
structure of the items.
To make things clearer, I created an example.
The source XML looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<items>
<item id="1">
<path>root\folderA\folderB\folderC</path>
</item>
<item id="2">
<path>root\folderA\folderB\folderD</path>
</item>
<item id="3">
<path>root\folderA\folderE\folderF</path>
</item>
<item id="4">
<path>root\folderG</path>
</item>
<item id="5">
<path>root\folderA\folderB\folderD</path>
</item>
</items>
This is what I would like to get when done transforming:
<?xml version="1.0" encoding="UTF-8"?>
<transformedDocument>
<path name="root">
<path name="folderA">
<path name="folderB">
<path name="folderC">
<item id="1"/>
</path>
<path name="folderD">
<item id="2"/>
<item id="5"/>
</path>
</path>
<path name="folderE">
<path name="folderF">
<item id="3"/>
</path>
</path>
</path>
<path name="folderG">
<item id="4"/>
</path>
</path>
</transformedDocument>
So far, my transformation groups the paths using the Muenchian method,
sorts by path and then calls a template that calls itself recursively,
splitting at each '\' character and inserts all items with a matching path:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="
http://www.w3.org/1999/XSL/Transform">
<xsl:key name="items" match="item" use="path"/>
<xsl:variable name="pathSeparator">
<xsl:text>\</xsl:text>
</xsl:variable>
<xsl:template match="/items">
<transformedDocument>
<xsl:for-each select="//item[generate-id(.)=generate-id(key('items',
path))]">
<xsl:sort select="path"/>
<xsl:call-template name="item">
<xsl:with-param name="path" select="path"/>
<xsl:with-param name="fullPath" select="path"/>
</xsl:call-template>
</xsl:for-each>
</transformedDocument>
</xsl:template>
<xsl:template name="item">
<xsl:param name="path" select="$path"/>
<xsl:param name="fullPath" select="$fullPath"/>
<xsl:variable name="name">
<xsl:value-of select="substring-before($path, $pathSeparator)"/>
</xsl:variable>
<xsl:choose>
<xsl:when test="contains($path, $pathSeparator)">
<path>
<xsl:attribute name="name"><xsl:value-of select="$name"/></
xsl:attribute>
<xsl:call-template name="item">
<xsl:with-param name="path" select="substring-after($path,
$pathSeparator)"/>
<xsl:with-param name="fullPath" select="$fullPath"/>
</xsl:call-template>
</path>
</xsl:when>
<xsl:otherwise>
<path>
<xsl:attribute name="name"><xsl:value-of select="$path"/></
xsl:attribute>
<xsl:comment>
<xsl:value-of select="$fullPath"/>
</xsl:comment>
<xsl:for-each select="//item">
<xsl:if test="path[.=$fullPath]">
<item>
<xsl:attribute name="id"><xsl:value-of select="
attribute::id"/></xsl:attribute>
</item>
</xsl:if>
</xsl:for-each>
</path>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
The problem - I canot figure out how to group parent path names in the
destination document. I cannot come up with a solution and would be glad to
be able to avoid this:
<?xml version="1.0" encoding="UTF-8"?>
<transformedDocument>
<path name="root">
<path name="folderA">
<path name="folderB">
<path name="folderC">
<!--root\folderA\folderB\folderC-->
<item id="1" />
</path>
</path>
</path>
</path>
<path name="root">
<path name="folderA">
<path name="folderB">
<path name="folderD">
<!--root\folderA\folderB\folderD-->
<item id="2" />
<item id="5" />
</path>
</path>
</path>
</path>
<path name="root">
<path name="folderA">
<path name="folderE">
<path name="folderF">
<!--root\folderA\folderE\folderF-->
<item id="3" />
</path>
</path>
</path>
</path>
<path name="root">
<path name="folderG">
<!--root\folderG-->
<item id="4" />
</path>
</path>
</transformedDocument>
I hope to hear from you all soon. Thank you very much.
Mit freundlichen Grüßen / Sincerely
Daniel Geske
Telematik/Infotainment, AE-V32
Telematics/Infotainment, AE-V32
IAV GmbH
Ingenieurgesellschaft Auto und Verkehr
Carnotstraße 1
10587 Berlin
Germany
Tel.: +49 (30) 3 99 78 - 90 44
Fax: +49 (30) 3 99 78 - 94 11
E-mail: <mailto:daniel(_dot_)geske(_at_)iav(_dot_)de>
Internet: http://www.iav.de