This is an extension to the question I asked earlier - XSLT 1.0 Grouping with multiple elements with same name The output format has changed and hence reposting.
I have an XML that looks like -
<resultset>
<hit>
<content>
<ITEM>
<TITLE>Office Cleaning1</TITLE>
<DESCRIPTION>blah blah blah</DESCRIPTION>
<Hierarchy>level1A~level2A~level3A</Hierarchy>
<Hierarchy>level1B~level2B~level3B</Hierarchy>
</ITEM>
</content>
</hit>
<hit>
<content>
<ITEM>
<TITLE>Office Cleaning2</TITLE>
<DESCRIPTION>blah blah blah</DESCRIPTION>
<Hierarchy>level1A~level2A~level3B</Hierarchy>
</ITEM>
</content>
</hit>
<hit>
<content>
<ITEM>
<TITLE>Office Cleaning3</TITLE>
<DESCRIPTION>blah blah blah</DESCRIPTION>
<Hierarchy>level1A~level2B~level3C</Hierarchy>
</ITEM>
</content>
</hit>
<hit>
<content>
<ITEM>
<TITLE>Office Cleaning4</TITLE>
<DESCRIPTION>blah blah blah</DESCRIPTION>
<Hierarchy>level1A~level2B~level3B</Hierarchy>
<Hierarchy>level1A~level2B~level3C</Hierarchy>
</ITEM>
</content>
</hit>
<hit>
<content>
<ITEM>
<TITLE>Office Cleaning5</TITLE>
<DESCRIPTION>blah blah blah</DESCRIPTION>
<Hierarchy>level1B~level2B~level3B</Hierarchy>
</ITEM>
</content>
</hit>
</resultset>
Note that there are multiple hierarchy elements which is a concatenated string of level1~level2~level3 I am looking to transform this into something like this -
<TREE>
<LEVELS>
<LEVEL1 name="level1A">
<LEVEL2 name="level2A">
<LEVEL3 name="level3A">
<ITEM Name="Office Cleaning1"/>
</LEVEL3>
<LEVEL3 name="level3B">
<ITEM Name="Office Cleaning2"/>
</LEVEL3>
</LEVEL2>
<LEVEL2 name="level2B">
<LEVEL3 name="level3B">
<ITEM Name="Office Cleaning4"/>
</LEVEL3>
<LEVEL3 name="level3C">
<ITEM Name="Office Cleaning3"/>
<ITEM Name="Office Cleaning4"/>
</LEVEL3>
</LEVEL2>
</LEVEL1>
<LEVEL1 name="level1B">
<LEVEL2 name="level2B">
<LEVEL3 name="level3B">
<ITEM Name="Office Cleaning1"/>
<ITEM Name="Office Cleaning5"/>
</LEVEL3>
</LEVEL2>
</LEVEL1>
</TREE>
Basically each item has multiple hierarchy associated with it. I need to group them together and each levels to be grouped together as well.
I can actually change the values in the HIERARCHY element in the input XML to any format that might be easier to extract. For e.g. I can make it look like LEVEL1:level1A~LEVEL2:level2A~LEVEL3:level3A but I cannot add new elements.
I got it working myself. Ignore the extra namespaces. I edited the hierarchy field to have format of level1:value~level2:value~level3:value for ease of substring.
I am sure there is a better way but this works for me.
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:autn="http://schemas.autonomy.com/aci/">
<xsl:output method="xml" omit-xml-declaration="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="TOPLEVEL" match="autnresponse/responsedata/autn:hit/autn:content/DOCUMENT/HIERARCHY" use="substring-before(substring-after(.,'LEVEL1:'),'~')"/>
<xsl:key name="MIDLEVEL" match="autnresponse/responsedata/autn:hit/autn:content/DOCUMENT/HIERARCHY" use="substring-before(substring-after(.,'LEVEL2:'),'~')"/>
<xsl:key name="BOTTOMLEVEL" match="autnresponse/responsedata/autn:hit/autn:content/DOCUMENT/HIERARCHY" use="substring-before(substring-after(.,'LEVEL3:'),'~')"/>
<xsl:template match="/">
<TREE>
<xsl:for-each select="autnresponse/responsedata/autn:hit/autn:content/DOCUMENT/HIERARCHY[generate-id() = generate-id(key('TOPLEVEL',substring-before(substring-after(.,'LEVEL1:'),'~') )[1])]">
<xsl:variable name="TOP" select="substring-before(substring-after(.,'LEVEL1:'),'~')"/>
<LEVEL1>
<xsl:attribute name="name"><xsl:value-of select="substring-after($TOP,'+')"/></xsl:attribute>
<xsl:attribute name="id"><xsl:value-of select="substring-before($TOP,'+')"/></xsl:attribute>
<xsl:for-each select="//autnresponse/responsedata/autn:hit/autn:content/DOCUMENT/HIERARCHY[substring-before(substring-after(.,'LEVEL1:'),'~')=$TOP and generate-id() = generate-id(key('MIDLEVEL',substring-before(substring-after(.,'LEVEL2:'),'~') )[1])]">
<xsl:variable name="MID" select="substring-before(substring-after(.,'LEVEL2:'),'~')"/>
<LEVEL2>
<xsl:attribute name="name"><xsl:value-of select="substring-after($MID,'+')"/></xsl:attribute>
<xsl:attribute name="id"><xsl:value-of select="substring-before($MID,'+')"/></xsl:attribute>
<xsl:for-each select="//autnresponse/responsedata/autn:hit/autn:content/DOCUMENT/HIERARCHY[substring-before(substring-after(.,'LEVEL1:'),'~')=$TOP and substring-before(substring-after(.,'LEVEL2:'),'~')=$MID and generate-id() = generate-id(key('BOTTOMLEVEL',substring-before(substring-after(.,'LEVEL3:'),'~') )[1])]">
<xsl:variable name="BOTTOM" select="substring-before(substring-after(.,'LEVEL3:'),'~')"/>
<LEVEL3>
<xsl:attribute name="name"><xsl:value-of select="substring-after($BOTTOM,'+')"/></xsl:attribute>
<xsl:attribute name="id"><xsl:value-of select="substring-before($BOTTOM,'+')"/></xsl:attribute>
<xsl:apply-templates select="//HIERARCHY[substring-before(substring-after(.,'LEVEL1:'),'~')=$TOP and substring-before(substring-after(.,'LEVEL2:'),'~')=$MID and substring-before(substring-after(.,'LEVEL3:'),'~')=$BOTTOM]"/>
</LEVEL3>
</xsl:for-each>
</LEVEL2>
</xsl:for-each>
</LEVEL1>
</xsl:for-each>
</TREE>
</xsl:template>
<xsl:template match="HIERARCHY">
<ITEM>
<xsl:attribute name="name"><xsl:value-of select="../DRETITLE"/></xsl:attribute>
<xsl:attribute name="id"><xsl:value-of select="../ID"/></xsl:attribute>
</ITEM>
</xsl:template>
</xsl:stylesheet>