Re: [xsl] Fwd: level grouping problem

Subject: Re: [xsl] Fwd: level grouping problem
From: "G. Ken Holman" <gkholman@xxxxxxxxxxxxxxxxxxxx>
Date: Wed, 05 Sep 2007 22:57:29 -0400
At 2007-09-06 12:24 +1000, Maria Shvedova wrote:
My appologies in advance for the possible incorrect use of
terminology, I'm still new to xslt.

It sure sounds like you know what you are talking about.


I have an xml file that looks like that:
...
and the output that I'm trying to achieve is the following:  (the
grouping needs to occur within each <reference> tag,  i.e. I need to
get)
...
what is happening instead, though, is that elements are being grouped
together, so the output that I get is:

Yes, because you've used the XSLT 1.0 document-wide grouping method based on keys.


here is the stylesheet that I'm using:
<xsl:stylesheet xmlns:xsl=" http://www.w3.org/1999/XSL/Transform "
version="1.0">
<xsl:key name="det" match="/export/references/reference/detail" use="@name"/>
<xsl:template match="/export/references">
<html>
<body>
<table>

I'm not sure what you are doing with the <table> element so it is not in my solutions below.


          <xsl:apply-templates select="reference"/>
          </table>
      </body>
      </html>
  </xsl:template>

  <xsl:template match="reference">
      <xsl:for-each
select="detail[generate-id(.)=generate-id(key('det', @name))]/@name">

You've implemented a classic application of the Muenchian method, which is just fine for document-wide grouping, but your sub-document grouping can get awkward when using keys. Below I've used a variable-based method for XSLT 1.0 for sub-document grouping.


I wasn't exactly sure where you were going with the sorting, so I sorted by @name, and then I sorted the group by title. You can remove what you don't need.

Any help would me much appreciated!! its probably obvious, but I've
been staring at it for hours....
(The  parser we have can work with both xslt  1.0 and 2.0)

Then I suggest you switch to XSLT 2.0 which has built-in facilities for grouping. It has greatly simplified my teaching of this requirement.


I hope this helps.

. . . . . . . . . . . . . Ken


T:\ftemp>type maria.xml <export> <references> <reference> <detail name="Detail1"> <title>Detail 1 text</title> </detail> <detail name="Detail2"> <title>Detail2 text</title> </detail> <detail name="Detail2"> <title>Detail2 text</title> </detail> </reference> <reference> <detail name="Detail1"> <title>Detail 1 text</title> </detail> <detail name="Detail2"> <title>Detail2 text</title> </detail> <detail name="Detail2"> <title>Detail2 text</title> </detail> </reference> </references> </export>

T:\ftemp>type maria.xsl
<?xml version="1.0" encoding="US-ASCII"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
                version="1.0">

<xsl:output indent="yes"/>

<xsl:template match="/">
  <html>
    <body>
      <xsl:apply-templates select="export/references/reference"/>
    </body>
  </html>
</xsl:template>

<xsl:template match="reference">
  <!--put what is being grouped in a variable-->
  <xsl:variable name="details" select="detail"/>
  <!--walk through the variable-->
  <xsl:for-each select="detail">
    <xsl:sort select="@name"/>
    <!--act on the first in document order-->
    <xsl:if test="generate-id(.)=
                  generate-id($details[@name=current()/@name][1])">
      <h2>
        <xsl:value-of select="@name"/>
      </h2>
      <!--revisit all-->
      <xsl:for-each select="$details[@name=current()/@name]">
        <xsl:sort select="title"/>
        <i><xsl:value-of select="title"/></i>
        <br/>
      </xsl:for-each>
    </xsl:if>
  </xsl:for-each>
</xsl:template>

</xsl:stylesheet>
T:\ftemp>call xslt maria.xml maria.xsl maria.htm

T:\ftemp>type maria.htm
<html>
<body>
<h2>Detail1</h2><i>Detail 1 text</i><br><h2>Detail2</h2><i>Detail2 text</i><br><i>Detail2 text</i><br><h2>Detail1</h2><i>Detail 1 text</i><br><h2>Detail2</h2><i>Detail2 text</i><br><i>Detail2 text</i><br></body>
</html>
T:\ftemp>type maria2.xsl
<?xml version="1.0" encoding="US-ASCII"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
version="2.0">


<xsl:output indent="yes"/>

<xsl:template match="/">
  <html>
    <body>
      <xsl:apply-templates select="export/references/reference"/>
    </body>
  </html>
</xsl:template>

<xsl:template match="reference">
  <xsl:for-each-group select="detail" group-by="@name">
    <xsl:sort select="@name"/>
    <h2>
      <xsl:value-of select="@name"/>
    </h2>
    <xsl:for-each select="current-group()">
      <xsl:sort select="title"/>
      <i><xsl:value-of select="title"/></i>
      <br/>
    </xsl:for-each>
  </xsl:for-each-group>
</xsl:template>

</xsl:stylesheet>
T:\ftemp>call xslt2 maria.xml maria2.xsl maria2.htm
<html>
<body>
<h2>Detail1</h2><i>Detail 1 text</i><br><h2>Detail2</h2><i>Detail2 text</i><br><i>Detail2 text</i><br><h2>Detail1</h2><i>Detail 1 text</i><br><h2>Detail2</h2><i>Detail2 text</i><br><i>Detail2 text</i><br></body>
</html>



-- Upcoming public training: XSLT/XSL-FO Sep 10, UBL/code lists Oct 1 World-wide corporate, govt. & user group XML, XSL and UBL training RSS feeds: publicly-available developer resources and training G. Ken Holman mailto:gkholman@xxxxxxxxxxxxxxxxxxxx Crane Softwrights Ltd. http://www.CraneSoftwrights.com/s/ Box 266, Kars, Ontario CANADA K0A-2E0 +1(613)489-0999 (F:-0995) Male Cancer Awareness Jul'07 http://www.CraneSoftwrights.com/s/bc Legal business disclaimers: http://www.CraneSoftwrights.com/legal

Current Thread