[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Re: Concatenating a nodeset (set of attributes)

Subject: Re: Concatenating a nodeset (set of attributes)
From: Geert Josten <Geert.Josten@xxxxxxxxxxx>
Date: Mon, 10 Oct 2005 02:02:38 +0200
xsl add nodeset
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: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" />

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" />

(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

<xsl:stylesheet version="1.0"


      <xsl:variable name="rtf">
        <xsl:apply-templates select="STRUC" mode="add-sort-key" />

      <xsl:apply-templates select="exsl:node-set($rtf)/STRUC" mode="remove-sort-key">
        <xsl:sort select="@sort-key" data-type="number" />

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:

  <STRUC pos="2">
    <STRUC pos="1" />
    <STRUC pos="12" />
  <STRUC pos="3">
    <STRUC pos="4" />
    <STRUC pos="4">
      <STRUC pos="1" />


Current Thread


Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
First Name
Last Name
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.