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: HowTo - Nested for-each XSLSort on multi-column display


Hi Jim,

This is an interesting problem because it combines grouping by value
(the Type of the dog) with grouping by position. I think that the
simplest and easiest method is to create an intermediate node set that
holds the elements grouped by value, and then uses a
grouping-by-position method to group by position.

So, you could create a new node tree that contains the grouped DogAge
elements:

  <xsl:variable name="grouped-dogages">
     <xsl:for-each select="/Dogs/BreedTypes/Type">
        <xsl:sort select="." />
        <Breed Type="{.}">
           <xsl:for-each
                 select="/Dogs/DogName/DogAge[@Type = current()]">
              <xsl:sort select="@PetName" />
              <xsl:copy select="." />
           </xsl:for-each>
        </Breed>
     </xsl:for-each>
  </xsl:variable>

You can access this as a node set using the node-set() extension
function in whatever namespace is supported by the processor you're
using.

  <xsl:apply-templates
        select="exsl:node-set($grouped-dogages)/Breed" />

[Note: The EXSLT namespace very probably won't work yet - substitute
whatever namespace is appropriate for the processor you're using.]

And you can then operate over it just as if the original structure was
grouped. So you make a new table row per Breed element, and within
that apply templates to the odd DogAge elements, with each of those
creating the row including their following siblings, the even ones:

<xsl:template match="Breed">
   <tr>
      <td colspan="4">Breed Type = <xsl:value-of select="@Type" /></td>
   </tr>
   <tr>
      <th>Pet Name</th><th>Age</th>
      <th>Pet Name</th><th>Age</th>
   </tr>
   <xsl:apply-templates select="DogAge[position() mod 2 = 1]" />
</xsl:template>

<xsl:template match="DogAge">
   <xsl:variable name="next" select="following-sibling::DogAge" />
   <tr>
      <td><xsl:value-of select="@PetName"></td>
      <td><xsl:value-of select="." /></td>
      <td><xsl:value-of select="$next/@PetName" /></td>
      <td><xsl:value-of select="$next" /></td>
   </tr>
</xsl:template>

It is possible to do it without the intermediate node set (of course),
but it's a lot uglier (let me know if you want to see it). I'm sure
that the XSL WG would be grateful if you sent this to them as an
example use case for the XSLT 2.0 requirements - there are use cases
that show two levels of grouping by value, but not one like this.

I hope that helps anyway,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/



 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]