RE: [xsl] How to convert flat data to hierarchical data

Subject: RE: [xsl] How to convert flat data to hierarchical data
From: "Jacoby, Peter R." <PJACOBY@xxxxxxxxxxxx>
Date: Mon, 26 Apr 2004 13:57:43 -0400
I see that Andreas has provided a very similar solution, but here is an
alternative.  You could probably use the Schema nil value in a more direct
way, but I use it here as a simple attribute value.

The main idea is to use the same template matching EmplyoeeGroup no matter
what level you are on.  Since the top level nodes and deeply nested nodes
will have the same behavior (namely, copy it's attributes, two of its
children, and then apply templates on any siblings), you can use one
template for all EmployeeGroup nodes.  If speed is an issue and your input
data is very large, you can try using the following-sibling axis instead of
all siblings as long as you can guarantee document order will follow
hierarchical order.


<?xml version="1.0" ?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";>
<xsl:output method="xml" encoding="UTF-8"/>

<xsl:template match="/">
	<xsl:apply-templates select="EmployeeGroups"/>
</xsl:template>

<xsl:template match="EmployeeGroups">
	<xsl:copy>
		<xsl:apply-templates
select="EmployeeGroup[Parent/@xsi:nil='true']"/>
	</xsl:copy>
</xsl:template>

<xsl:template match="EmployeeGroup">
	<xsl:copy>
		<xsl:copy-of select="@* | EmployeeGroupTree | Code" />
		<xsl:apply-templates select="../EmployeeGroup[Parent/@SK =
current()/@SK]" />
	</xsl:copy>
</xsl:template>

</xsl:stylesheet> 

Hope this helps.

-Peter


-----Original Message-----
From: Hansen, John [mailto:John.Hansen@xxxxxxxxxx] 
Sent: Monday, April 26, 2004 1:00 PM
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject: [xsl] How to convert flat data to hierarchical data

Is there a simple stylesheet that will transform the flat data shown below
into the hierarchical form that is at the end of this email?  I hate to ask
for your help but I'm stumped at the moment.  EmployeeGroup elements, while
presented in a flat form in the initial XML output need to be nested based
on their EmployeeGroupTree child element's SK attribute and their Parent
child element's SK attribute (or xsi:nil attribute).  Each level in the
hierarchy can have zero or more child EmployeeGroup elements.  The root of
each tree is the EmployeeGroup with a <Parent xsi:nil="true"/> child.

<!-- Original XML with flat structure -->

<EmployeeGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";>

<EmployeeGroup SK="1">
<EmployeeGroupTree SK="1"/>
<Code>AB_GP1</Code>
<Parent xsi:nil="true"/>
</EmployeeGroup>

<EmployeeGroup SK="2">
<EmployeeGroupTree SK="2"/>
<Code>AB_GP2</Code>
<Parent xsi:nil="true"/>
</EmployeeGroup>

<EmployeeGroup SK="3">
<EmployeeGroupTree SK="1"/>
<Code>AB1_G1</Code>
<Parent SK="1"/>
</EmployeeGroup>

<EmployeeGroup SK="4">
<EmployeeGroupTree SK="2"/>
<Code>AB2_G1</Code>
<Parent SK="2"/>
</EmployeeGroup>

<EmployeeGroup SK="5">
<EmployeeGroupTree SK="3"/>
<Code>CATGRY</Code>
<Parent xsi:nil="true"/>
</EmployeeGroup>

<EmployeeGroup SK="6">
<EmployeeGroupTree SK="4"/>
<Code>CSV   </Code>
<Parent xsi:nil="true"/>
</EmployeeGroup>

<EmployeeGroup SK="7">
<EmployeeGroupTree SK="5"/>
<Code>HEAP  </Code>
<Parent xsi:nil="true"/>
</EmployeeGroup>

<EmployeeGroup SK="8">
<EmployeeGroupTree SK="5"/>
<Code>H1    </Code>
<Parent SK="7"/>
</EmployeeGroup>

<EmployeeGroup SK="9">
<EmployeeGroupTree SK="5"/>
<Code>H10   </Code>
<Parent SK="7"/>
</EmployeeGroup>

<EmployeeGroup SK="10">
<EmployeeGroupTree SK="5"/>
<Code>H11   </Code>
<Parent SK="7"/>
</EmployeeGroup>

<EmployeeGroup SK="11">
<EmployeeGroupTree SK="5"/>
<Code>H12   </Code>
<Parent SK="7"/>
</EmployeeGroup>

<EmployeeGroup SK="12">
<EmployeeGroupTree SK="5"/>
<Code>H13   </Code>
<Parent SK="7"/>
</EmployeeGroup>

<EmployeeGroup SK="13">
<EmployeeGroupTree SK="1"/>
<Code>TEST  </Code>
<Parent SK="3"/>
</EmployeeGroup>

<EmployeeGroup SK="14">
<EmployeeGroupTree SK="1"/>
<Code>TEST2 </Code>
<Parent SK="13"/>
</EmployeeGroup>

</EmployeeGroups>

<!-- desired hierarchical output of XSL transformation -->

<EmployeeGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";>

<EmployeeGroup SK="1">
  <EmployeeGroupTree SK="1"/>
  <Code>AB_GP1</Code>
  <EmployeeGroup SK="3">
    <EmployeeGroupTree SK="1"/>
    <Code>AB1_G1</Code>
    <EmployeeGroup SK="13">
      <EmployeeGroupTree SK="1"/>
      <Code>TEST </Code>
      <EmployeeGroup SK="14">
        <EmployeeGroupTree SK="1"/>
        <Code>TEST2 </Code>
      </EmployeeGroup>
    </EmployeeGroup>
  </EmployeeGroup>
</EmployeeGroup>

<EmployeeGroup SK="2">
  <EmployeeGroupTree SK="2"/>
  <Code>AB_GP2</Code>
  <EmployeeGroup SK="4">
    <EmployeeGroupTree SK="2"/>
    <Code>AB2_G1</Code>
  </EmployeeGroup>
</EmployeeGroup>


<EmployeeGroup SK="5">
  <EmployeeGroupTree SK="3"/>
  <Code>CATGRY</Code>
</EmployeeGroup>

<EmployeeGroup SK="6">
  <EmployeeGroupTree SK="4"/>
  <Code>CSV   </Code>
</EmployeeGroup>

<EmployeeGroup SK="7">
  <EmployeeGroupTree SK="5"/>
  <Code>HEAP  </Code>
  <EmployeeGroup SK="8">
    <EmployeeGroupTree SK="5"/>
    <Code>H1    </Code>
  </EmployeeGroup>
  <EmployeeGroup SK="9">
    <EmployeeGroupTree SK="5"/>
    <Code>H10   </Code>
  </EmployeeGroup>
  <EmployeeGroup SK="10">
    <EmployeeGroupTree SK="5"/>
    <Code>H11   </Code>
  </EmployeeGroup>
  <EmployeeGroup SK="11">
    <EmployeeGroupTree SK="5"/>
    <Code>H12   </Code>
  </EmployeeGroup>
  <EmployeeGroup SK="12">
    <EmployeeGroupTree SK="5"/>
    <Code>H13   </Code>
  </EmployeeGroup>
</EmployeeGroup>

</EmployeeGroups>

Current Thread