Reputation: 73
I have this XML file and want to perform an Xslt 2.0 Transformation.
The Problem is, that the the nodes are at the same Level and reference to each other with ID's, for example:
<?xml version="1.0" encoding="UTF-8"?>
<Data id = "1" referenceID = "2 3">
Text1
</Data>
<Data id = "2" referenceID = "4">
Text2
</Data>
<Data id = "3" referenceID = "5">
Text3
</Data>
<Data id = "4">
Text4
</Data>
<Data id = "5">
Text5
</Data>
The desired Output should look like this:
<?xml version="1.0" encoding="UTF-8"?>
<Level1>
Text1
<Level2>
Text2
<Level3>
Text4
</Level3>
</Level2>
<Level2>
Text3
<Level3>
Text5
</Level3>
</Level2>
</Level1>
I already tried to use templates and call them recursively but with no success. Maybe there is a easy way to tackle this kind of problem. Thank you for your help in advance!
Upvotes: 0
Views: 134
Reputation: 167716
You can use a key to identify Data
elements by the id
attribute and then follow references using the key
function on the tokenize(@referenceID, '\s+')
sequence:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="3.0">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="ref" match="Data" use="@id"/>
<xsl:template match="*[Data[@id]]">
<xsl:apply-templates select="key('ref', '1')"/>
</xsl:template>
<xsl:template match="Data">
<xsl:param name="level" as="xs:integer" select="1"/>
<xsl:element name="Level{$level}">
<xsl:apply-templates select="node(), key('ref', tokenize(@referenceID, '\s+'))">
<xsl:with-param name="level" select="$level + 1"/>
</xsl:apply-templates>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
That gives the right structure http://xsltfiddle.liberty-development.net/gWcDMek/2, identation with mixed contents is difficult.
Upvotes: 1