This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

RE: (xsl) processing siblings based on sorted order, not document order


There is a way to do it without an extension function but it's not pretty
nor efficient. It involves iterating over your nodes multiple times using
xsl:for-each.

Here's a sample:

<xsl:transform
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
    
  <xsl:output method="xml" encoding="UTF-8" indent="yes"/>
  
  <xsl:template match="foo">
    <table>
      <xsl:for-each select="bar">
        <xsl:sort select="@id"/>

        <xsl:if test="position() mod 3 = 1">
          <tr>
            <xsl:variable name="next" select="position() + 1"/>
            <xsl:apply-templates select="."/>

            <xsl:for-each select="../bar">
              <xsl:sort select="@id"/>

              <xsl:if test="position() = $next or position() = $next + 1">
                <xsl:apply-templates select="."/>
              </xsl:if>

            </xsl:for-each>
          </tr>
        </xsl:if>
      </xsl:for-each>
    </table>
  </xsl:template>
  
  <xsl:template match="bar">  
    <td><xsl:value-of select="@id"/></td>
  </xsl:template>
  
</xsl:transform>

Hope this helps,
Jason.

-----Original Message-----
From: Stephen Cunliffe [mailto:scunliffe@digitalfairway.com]
Sent: Friday, May 25, 2001 12:03 PM
To: XSL List
Subject: [xsl] (xsl) processing siblings based on sorted order, not
document order


Problem:
I have an xml node-set that resembles the following;

<foo>
   <bar id="Red"/>
   <bar id="Orange"/>
   <bar id="Blue"/>
   <bar id="Green"/>
   <bar id="Yellow"/>
   <bar id="Purple"/>
   <bar id="Magenta"/>
   <bar id="Indigo"/>
   <bar id="Cyan"/>
   <bar id="Teal"/>
   ...
</foo>

I need to do (2) things.

First, I need to sort by id. (not a problem)

<table>
   <xsl:apply-templates select="foo/bar">
      <xsl:sort select="@id" data-type="text" order="ascending"/>
   </xsl:apply-templates>
</table>


Second, place the (sorted) bar id's, in a table, 3 per row.

E.g.

<tr>
   <td>Blue</td><td>Cyan</td><td>Green</td>
</tr>
<tr>
   <td>Indigo</td><td>Magenta</td><td>Orange</td>
</tr>
<tr>
   <td>Purple</td><td>Red</td><td>Teal</td>
</tr>
<tr>
   <td>Yellow</td>
</tr>

So, the logic as I see it, would be to process through each "bar" (the
siblings), and find the first item in every row,...

<xsl:template match="bar">
   <xsl:if test="position() mod 3 = 1">
      <tr>
         <!-- apply a template here, where
select=".|following-sibling::bar[position() < 3]" -->
      </tr>
   </xsl:if>
</xsl:template>

::::: The issue, is that "position()" and "following-sibling" are in the
xml document order [XPath] and thus the results are not sorted in the
output.
======================================
Q.) Is there a way in XSLT / XPath to apply-templates / do a for-each,
that will "select" based on sorted order vs. document order... or a way
to create a new (sorted) node-set, without limiting myself to a specific
Xalan / Saxon / XSLT Processor.

Q2). If I *have* to use a specific XSLT Processor, anyone have a
solution for Xalan?

Cheers and TIA,

Steve








 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list

 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]