[xsl] RE: SQL BTree to XML Tree?

Subject: [xsl] RE: SQL BTree to XML Tree?
From: "mnews-xsl@xxxxxx" <mnews-xsl@xxxxxx>
Date: Mon, 23 Jan 2006 01:10:55 +0100
Hello,

the following is intended to work in XSLT 1.0 (libxslt):
It's a recursive template, hopefully not to wastefull on the ressources.


<?xml version="1.0" encoding="utf8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>

<xsl:output method="xml" encoding="utf8" indent="yes"/>

<!-- Conditions equivalent to
   <xsl:sequence select="$boss/../item[lh gt $boss/lh and rh le $boss/rh]"/>
-->

<xsl:template match="item">
   <xsl:param name="context"/>
   <xsl:if test="not($context[current()/lh > lh and rh >= current()/rh])">
     <xsl:variable name="context-inner"
       select="$context[lh > current()/lh and current()/rh >= rh]"/>
     <department title="{name}">
       <xsl:apply-templates select="$context-inner">
         <xsl:with-param name="context" select="$context-inner"/>
       </xsl:apply-templates>
     </department>
   </xsl:if>
</xsl:template>

<xsl:template match="/">
   <group>
     <xsl:apply-templates select="output/item">
       <xsl:with-param name="context" select="output/item"/>
     </xsl:apply-templates>
   </group>
</xsl:template>

</xsl:stylesheet>

Phillip B Oldham schrieb:
Hi

Thanks for your help with this.

Unfortunately I'm stuck with XSLT 1.0, and I've been trying to re-write what you've done but with little success.

Could you possibly point me in the right direction to getting the desired output using the data I already have? Or would there be a better way to organise the data in SQL to use an already widely-used XSL method?

Thanks!


I'm storing a btree in sql in the following manner:


+----------------------------+
| Table: Departments |
+----------------------------+
| id | name | lh | rh |
+----------------------------+
| 1 | Managers | 1 | 6 |
| 2 | Supervisors | 2 | 5 |
| 3 | Employees | 3 | 4 |
| 4 | Directors | 7 | 8 |
+----------------------------+



The Celko technique. Illustrating the lengths people will go to to bend
their data to make it fit in a relational database!

This is being converted to xml, resulting in:

<output>
<item>
<id>1</id>
<name>Managers</name>
<lh>1</lh>
<rh>2</rh>


----------^ should be 6, I assume

</item>
<!-- etc -->
</output>

I need to translate this using XSL to this:

<group>
<department title="Managers">
<department title="Supervisors" />
<department title="Employees" />
</department>
<department title="Directors" />
</group>



May not be very efficient, but what comes to mind is that your data gives
you the descendant relationship very easily:

<xsl:function name="f:descendants" as="element(item)*">
<xsl:param name="boss" as="element(item)"/>
<xsl:sequence select="$boss/../item[lh gt $boss/lh and rh le $boss/rh]"/>
</xsl:function>

and you can deduce from this the child relationship (as being those
descendants who are not descendants of a descendant):

<xsl:function name="f:children" as="element(item)*">
<xsl:param name="boss" as="element(item)"/>
<xsl:variable name="descendants" select="f:descendants($boss)
<xsl:sequence select="$descendants except
(for $i in $descendants return f:descendant($i))"/>
</xsl:function>

and then you can do a recursive descent using the logical child relationship
in the usual way:


<xsl:template match="item">
<department title="@name">
<xsl:apply-templates select="f:children(.)"/>
</department>
</xsl:template>

Not tested and almost certainly needs a bit of fine tuning. And of course if
you're in XSLT 1.0 you'll have to rewrite the algorithm completely.

Current Thread