xsl-list
[Top] [All Lists]

Re: flat xml to full tree with no repeating

2004-09-22 13:01:06
Hi Steve,

You don't want to group your employees here, you want to nest them. 
Let's start with the top level: the one that doesn't have a manager:

 <xsl:variable name="big-boss-id" select="key('by-manager', '')/uid"/>

Then you can start the tree from there and use apply-templates
on all employees that have the big boss as manager:

 <xsl:template match="employees">
  <nodes>
   <node>
    <top><xsl:value-of select="$big-boss-id"/></top>
    <xsl:apply-templates select="key('by-manager', $big-boss-id)">
     <xsl:sort select="uid"/>
    </xsl:apply-templates>
   </node>
  </nodes>
 </xsl:template>

You now need a template to match="employee", that adds new
employees if he/she is somebody else's manager:

 <xsl:template match="employee">
  <node>
   <bottom><xsl:value-of select="uid"/></bottom>
   <xsl:apply-templates select="key('by-manager', uid)">
    <xsl:sort select="uid"/>
   </xsl:apply-templates>
  </node>
 </xsl:template>

That will keep adding deeper levels recursively, and give you the
output you wanted.

Cheers
Anton


Steve Lenhart wrote:

I have a flat xml file that i'm trying to make into a tree format with 
out repeats, and still keep all the child nodes.

the input xml file looks like.....

<employees>
    <employee>
        <uid>ceo</uid>
        <manager-uid></manager-uid>
    </employee>
    <employee>
        <uid>vp-1</uid>
        <manager-uid>ceo</manager-uid>
    </employee>
    <employee>
        <uid>vp-2</uid>
        <manager-uid>ceo</manager-uid>
    </employee>
    <employee>
        <uid>vp-1-secratary</uid>
        <manager-uid>vp-1</manager-uid>
    </employee>
    <employee>
        <uid>vp-1-assistant</uid>
        <manager-uid>vp-1</manager-uid>
    </employee>
    <employee>
        <uid>vp-1-secratary2</uid>
        <manager-uid>vp-1</manager-uid>
    </employee>
    <employee>
        <uid>vp-1-secretary2assistant</uid>
        <manager-uid>vp-1-secratary2</manager-uid>
    </employee>
    <employee>
        <uid>vp-2-secretary</uid>
        <manager-uid>vp-2</manager-uid>
    </employee>
</employees>
--------

id like the output to look like....

<?xml version="1.0"?>
<nodes>
    <node>
        <top>ceo</top>
        <node>
            <bottom>vp-1</bottom>
            <node>
                <bottom>vp-1-assistant</bottom>
            </node>
            <node>
                <bottom>vp-1-secratary</bottom>
            </node>
            <node>
                <bottom>vp-1-secratary2</bottom>
                <node>
                    <bottom>vp-1-secretary2assistant</bottom>
                </node>
            </node>
        </node>
        <node>
            <bottom>vp-2</bottom>
            <node>
                <bottom>vp-2-secretary</bottom>
            </node>
        </node>
    </node>
</nodes>
-------

the xslt file im using makes it into a tree but i cant make it do the 
full grouping that i want. the xsl file looks like.......

<?xml version='1.0'?>
<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
<xsl:key name="all-reports" match="employee" use="manager-uid" />

<xsl:template match="employees">
<nodes>
    <xsl:for-each select="employee[generate-id() = 
generate-id(key('all-reports',manager-uid)[1])]">
     <xsl:sort select="manager-uid" />
     <xsl:if test="not(manager-uid = '')">
       <node>
        <top><xsl:value-of select="manager-uid" /></top>
          <xsl:for-each select="key('all-reports', manager-uid)">
            <xsl:sort select="uid" />
            <node>
              <bottom><xsl:value-of select="uid" /></bottom>
            </node>
          </xsl:for-each>
       </node>
       </xsl:if>
    </xsl:for-each>
  </nodes>
</xsl:template>
</xsl:stylesheet>

thanks in advance for your help



Steve Lenhart <slenhart(_at_)teleflex(_dot_)com>
Corporate IT Department
Teleflex Incorporated



<Prev in Thread] Current Thread [Next in Thread>