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.
--~------------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--
--~------------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--