You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-users@xmlgraphics.apache.org by "Berg, Philip" <pc...@indiana.edu> on 2002/10/03 01:12:19 UTC

Grouping

Hi everybody,

I'm a one month young fop user and ran into a grouping problem. I made
up a scenario that represents what I have to accomplish on my present
project (attached below).

Basically what I'm trying to do is exactly as described on this page
(Muenchian Grouping Method):
http://www.jenitennison.com/xslt/grouping/muenchian.html
I hope that is something people are familiar with.  The one thing that
is different about my situation is that I have multiple sets of
"records."

I attached below a sample XML and XSL-FO (w/2 solutions I worked on)
plus my desired solution (to the given XML file).

I spend quiet some time playing around and surfing on message boards to
find similar scenarios.  But the only thing I can find is the "Muenchian
Grouping Method" which I can get to work but not if my data has the
added complexity as you see in my XML below.
I apologize for the length of the code below, but I truly hope somebody
can help me. 

thanks,
Philip
********************* XML
<addybook>
  <building id="A">
	<contact id="0001">
		<forename>John</forename>
		<surname>Smith</surname>
	</contact>
	<contact id="0002">
		<forename>Amy</forename>
		<surname>Jones</surname>
	</contact>
	<contact id="0003">
		<forename>Johnny</forename>
		<surname>Smith</surname>
	</contact>
	<contact id="0004">
		<forename>Amyyys</forename>
		<surname>Jones</surname>
	</contact>
	<contact id="0005">
		<forename>Philip</forename>
		<surname>Todson</surname>
	</contact>
  </building>
  <building id="B">
	<contact id="0001">
		<forename>Trish</forename>
		<surname>Somebody</surname>
	</contact>
	<contact id="0002">
		<forename>Jennifer</forename>
		<surname>Trapp</surname>
	</contact>
	<contact id="0003">
		<forename>Trob</forename>
		<surname>Todson</surname>
	</contact>
	<contact id="0004">
		<forename>Jenny</forename>
		<surname>Johnson</surname>
	</contact>
  </building>
  <building id="C">
	<contact id="0001">
		<forename>Grab</forename>
		<surname>Hand</surname>
	</contact>
	<contact id="0002">
		<forename>Tom</forename>
		<surname>Todson</surname>
	</contact>
	<contact id="0003">
		<forename>Grab</forename>
		<surname>Hand</surname>
	</contact>
	<contact id="0004">
		<forename>Tom</forename>
		<surname>Todson</surname>
	</contact>
  </building>
</addybook>
********************* DESIRED SOLUTION
       ===>    Building  id#  A
       ** Jones
       Amy
       Amyyys
       ** Smith
       John
       Johnny
       ** Todson
       Philip
       ===>    Building  id#  B
       ** Johnson
       Jenny
       ** Somebody
       Trish
       ** Todson
       Trob
       ** Trapp
       Jennifer
       ===>    Building  id#  C
       ** Hand
       Grab
       Grab
       ** Todson
       Tom
       Tom
********************* XSL-FO
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:fo="http://www.w3.org/1999/XSL/Format"
  xmlns:xalan="http://xml.apache.org/xalan" 
  exclude-result-prefixes="xalan">

  <xsl:key name="contacts-by-surname" match="contact" use="surname" />

  <xsl:template match="/">
    <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
      <fo:layout-master-set>
        <fo:simple-page-master master-name="Legal"
           page-width="216mm" page-height="279mm"
           margin-top="12mm"  margin-bottom="6mm"
           margin-left="12mm" margin-right="12mm">
          <fo:region-body margin-top="0mm"
                          margin-bottom="15mm"/>
          <fo:region-after extent="10mm"/>
        </fo:simple-page-master>
      </fo:layout-master-set>
      <fo:page-sequence master-reference="Legal"
        initial-page-number="1" language="en" country="us">
        <fo:flow flow-name="xsl-region-body">
          <xsl:apply-templates/>
        </fo:flow>
      </fo:page-sequence>
    </fo:root>
  </xsl:template>

  <xsl:template match="addybook/building">
    <fo:block> 
      ===> Building id# <xsl:value-of select="@id" />
    </fo:block>
    <xsl:call-template name="printBuildingPpl"/>
  </xsl:template>

  <xsl:template name="printBuildingPpl">
    <!--             Solution 1                                      -->
    <!--  Output:
       ===>    Building  id#  A
       **  Jones
       Amy
       Amyyys
       **  Smith
       John
       Johnny
       **  Todson
       Philip
       Tom
       Tom
       Trob
       ===>    Building  id#  B
       **  Johnson
       Jenny
       **  Somebody
       Trish
       **  Trapp
       Jennifer
       ===>    Building  id#  C
       **  Hand
       Grab
       Grab
    -->
    <!-- This for-loop is equivalent to the for-loop following (same
result)
    <xsl:for-each select="contact[generate-id() =
      generate-id(key('contacts-by-surname', surname)[1])]">
    -->
    <xsl:for-each select="contact[count(. | key('contacts-by-surname',
surname)[1]) = 1]">
      <xsl:sort select="surname" />
      <fo:block>                   
        ** <xsl:value-of select="surname" />
      </fo:block>
      <xsl:for-each select="key('contacts-by-surname', surname)">
        <xsl:sort select="forename" />
        <fo:block> 
          <xsl:value-of select="forename" />
        </fo:block>
      </xsl:for-each>
    </xsl:for-each>
    <!--             Solution 2                                      -->
    <!--  Outputs:
       ===>    Building  id#  A
       ** Jones
       Amy
       Amyyys
       ** Smith
       John
       Johnny
       ** Todson
       Philip
       ===>    Building  id#  B
       ** Johnson
       Jenny
       ** Somebody
       Trish
       ** Trapp
       Jennifer
       ===>    Building  id#  C
       ** Hand
       Grab
       Grab
    -->
    <!-- Comment Solution 1 out, and comment this on in if needed.
    <xsl:for-each select="contact">
      <xsl:sort select="surname" />
      <xsl:if test="(position() = 1) or not(preceding::contact[surname =
current()/surname])">
        <fo:block>
          ** <xsl:value-of select="surname" />
        </fo:block>
        <xsl:for-each select="../contact[surname = current()/surname]">
          <xsl:sort select="forename" />
          <fo:block> 
            <xsl:value-of select="forename" />
          </fo:block>
        </xsl:for-each>
      </xsl:if>
    </xsl:for-each>
    -->

  </xsl:template>
</xsl:stylesheet>
********************* La (?Le) Fin

RE: Grouping

Posted by Roland Neilands <rn...@pulsemining.com.au>.
Phillip,

> Basically what I'm trying to do is exactly as described on this page
> (Muenchian Grouping Method):
> http://www.jenitennison.com/xslt/grouping/muenchian.html
> I hope that is something people are familiar with.  The one thing that
> is different about my situation is that I have multiple sets of
> "records."

You can find or ask for an expert answer to this faster here:
http://www.mulberrytech.com/xsl/xsl-list/

Something of a FAQ I believe.

Cheers,
Roland