Hi Ragulf,
I realized after sending my answer that it contained various flaws. You will
have to divide by
larger numbers (powers of 100 or 1000) to cope with more child STRUC elements.
But dividing by
larger numbers cannot be done endlessly. I think the precision of real numbers
usually ends around 1
divided by 2 billion. So you either can handle more depth or more children, not
both to a reasonable
extend. Next to this, number() and format-number() of an empty node-set returns
'NaN'. So, sorting
on numbers might look smart, but is actually a lot more complicated...
But your format-number brings me to the following idea. Why not use it to
construct a string that
can be used to sort alphanumerically:
<xsl:sort select="concat(format-number(@pos, '000'),
translate(format-number(STRUC/@pos, '000'), 'Na',
'00'),
translate(format-number(STRUC/STRUC/@pos, '000'), 'Na',
'00'))"
data-type="text" />
The 'NaN's are less problematic here. Just convert the characters to zeros and
alphanumerical
ordering will not be disturbed. This however still limits the nesting level to
the amount of levels
you anticipated. If you want to do better (in XSLT 1.0?), you will have to do
two steps.
In the first step you add the string that is constructed with the select
expression of the sort as
an attribute to the top-most STRUC element, extending the sort-key as long as
the nesting continues,
and using a format-string with more zeros if more child elements have to be
supported.
<xsl:attribute name="sort-key">
<xsl:value-of select="format-number(@pos, '000')" />
<!-- recurse over nested levels -->
<xsl:apply-templates select="STRUC" mode="add-sort-key" />
</xsl:attribute>
...
<xsl:template match="STRUC/STRUC" mode="add-sort-key">
<xsl:value-of select="format-number(@pos, '000')" />
<xsl:apply-templates select="STRUC" mode="add-sort-key" />
</xsl:template>
In the second step you simply sort on that attribute:
<xsl:apply-templates select="STRUC" mode="remove-sort-key">
<xsl:sort select="@sort-key" data-type="number" />
</xsl:apply-templates>
(removing the attribute again if it disturbs further processing)
You could use the node-set() extension function that is supported by most
parsers to perform the two
passes in one stylesheet, if you like. Simply gather the result of the first
pass in a variable and
pass the variable as an argument to the node-set() function and pass the result
to another
apply-templates:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common">
...
<xsl:variable name="rtf">
<xsl:apply-templates select="STRUC" mode="add-sort-key" />
</xsl:variable>
<xsl:apply-templates select="exsl:node-set($rtf)/STRUC"
mode="remove-sort-key">
<xsl:sort select="@sort-key" data-type="number" />
</xsl:apply-templates>
Note, I'm using the exslt namespace for lesser dependence on the actual parser.
Just a last remark. It would be much easier to solve this problem if the STRUC
elements were nested
as a tree. Something like:
<TOC>
<STRUC pos="2">
<STRUC pos="1" />
<STRUC pos="12" />
</STRUC>
<STRUC pos="3">
<STRUC pos="4" />
<STRUC pos="4">
<STRUC pos="1" />
</STRUC>
</STRUC>
</TOC>
HTH,
Geert
--~------------------------------------------------------------------
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>
--~--