-1

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.

Community
  • 1
  • 1
  • Did you make an effort to understand the solution provided by Dimitre and modify it? You are expected to put forth some effort, not just keep asking for people to do your work. – Jim Garrison Nov 06 '12 at 18:55
  • Yes, I have been trying to see how to get matching levels to group together. Actually my xml contains far more data than in the example but the basic is to see how to put level2 elements under the right level1 and level3 elements under the right level1->level2. Thought someone would have a clue on how to achieve that. – user1766784 Nov 06 '12 at 20:27
  • I am unable to determine how to change dmitri code to do 4 levels of grouping now. Any help is appreciated. – user1766784 Nov 07 '12 at 07:42

1 Answers1

0

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>