472,960 Members | 1,776 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,960 software developers and data experts.

Listing distinct nodes and sibling elements

I have a problem with grouping elements in my XSL. What I want to do
is select all of the distinct SCE_CGPC records, then by the FSG_SNAM
records for each SCE_CGPC and then again by MOA_NAME for each SCE_CGPC
and FSG_SNAM.

I have included a achunk of my XML to help expalin this:

This is a chunk of the XML file

<z:row SCE_CGPC='PGRE' FSG_SNAM='HOME' MOA_NAME='Full time'

<z:row SCE_CGPC='PGRE' FSG_SNAM='OVERSEAS' MOA_NAME='Full time'

<z:row SCE_CGPC='PGRE' FSG_SNAM='HOME MOA_NAME='Full time'

<z:row SCE_CGPC='PGRE' FSG_SNAM='HOME' MOA_NAME='Part-Time'

<z:row SCE_CGPC='PGRE' FSG_SNAM='OVERSEAS' MOA_NAME='Full time'

So for this chunk of data I would like to see the following:

PGRE - HOME - FULL TIME PART TIME
- OVERSEAS - FULL TIME

So effectively what I am trying to do is group by distinct (SCE_CGPC,
FSG_SNAM, MOA_NAME)

I have managed to get the distinct list of SCE_CGPC using the
following:


<xsl:key name="group-by-cgpc" match="/xml/rs:data/z:row"
use="@SCE_CGPC"/>

<xsl:template match="/">
<xsl:for-each select="/xml/rs:data/z:row[generate-id(.)=
generate-id(key('group-by-cgpc',@SCE_CGPC))]/@SCE_CGPC">
<xsl:value-of select="."/>
<xsl:call-template name="firstlevel">
<xsl:with-param name="coursegroupcode" select="." />
</xsl:call-template>
</xsl:for-each>
</xsl:template>
<xsl:template name="firstlevel">
<xsl:param name="coursegroupcode" />
<xsl:value-of select="concat('', @SCE_CGPC,' - There are
',count(key('group-by-cgpc', $coursegroupcode)),' records:')"/><br/>
</xsl:template>
</xsl:stylesheet>

But what this does not to do and where I am struggling is getting the
vales of FSG_SNAM for each of the SCE_CGPC's and the values of MOA_NAME
for each FSG_SNAM.

Any help would be greatly appreciated
Chris

Jun 19 '06 #1
1 1484
On Mon, 19 Jun 2006 12:56:42 +0200, Chris <c.******@swansea.ac.uk> wrote:
I have a problem with grouping elements in my XSL. What I want to do
is select all of the distinct SCE_CGPC records, then by the FSG_SNAM
records for each SCE_CGPC and then again by MOA_NAME for each SCE_CGPC
and FSG_SNAM.

I have included a achunk of my XML to help expalin this:


This problem is easily solved with concat-augmented muenchian grouping
(http://www.dpawson.co.uk/xsl/sect2/N...tml#d5171e685).

However, a generic solution to group nodes to an arbitrary level in XSLT
1.0 is quite tempting.
Here's my attempt:

==input==
<xml xmlns:z="z" xmlns:rs="rs">
<rs:data>
<z:row SCE_CGPC='PGRE' FSG_SNAM='HOME' MOA_NAME='Full time'/>
<z:row SCE_CGPC='PGRE' FSG_SNAM='OVERSEAS' MOA_NAME='Full time'/>
<z:row SCE_CGPC='PGRE' FSG_SNAM='HOME MOA_NAME' MOA_NAME='Full time'/>
<z:row SCE_CGPC='PGRE' FSG_SNAM='HOME' MOA_NAME='Part-Time'/>
<z:row SCE_CGPC='PGRE' FSG_SNAM='OVERSEAS' MOA_NAME='Full time'/>
</rs:data>
</xml>

==XSLT==
<?xml version='1.0' encoding='utf-8' ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0" xmlns:z="z" xmlns:rs="rs">
<xsl:output method="xml" indent="yes"/>

<xsl:key name="row" match="z:row" use="@SCE_CGPC"/>
<xsl:key name="row" match="z:row" use="@FSG_SNAM"/>
<xsl:key name="row" match="z:row" use="@MOA_NAME"/>

<xsl:variable name="keys"
select="document('')/xsl:stylesheet/xsl:key[@name='row']/@use"/>

<xsl:template match="rs:data">
<grouped>
<xsl:call-template name="group"/>
</grouped>
</xsl:template>

<xsl:template match="z:row">
<xsl:copy-of select="."/>
</xsl:template>

<xsl:template name="group">
<xsl:param name="level" select="1"/>
<xsl:param name="nodes" select="/xml/rs:data/z:row"/>
<xsl:param name="groupkey" select="$keys[$level]"/>
<xsl:param name="groupkeys" select="$keys[position() &lt;= $level ]"/>
<xsl:for-each
select="/xml/rs:data/z:row[generate-id(.)=generate-id(key('row',@*[concat('@',name())=$groupkey]))]">
<group foo="{count($nodes)}" level="{$level}"
groupcode="{concat($groupkey,'=',@*[concat('@',name())=$groupkey])}">
<xsl:for-each
select="$nodes[@*[concat('@',name())=$groupkey]=current()/@*[concat('@',name())=$groupkey]][1]">
<xsl:variable name="all"
select="key('row',@*[concat('@',name())=$groupkeys])"/>
<xsl:variable name="set"
select="key('row',@*[concat('@',name())=$groupkeys])|dummy"/>
<xsl:variable name="filter">
<xsl:for-each select="$set">
<xsl:variable name="numoccur"
select="count($all[generate-id(.)=generate-id(current())])"/>
<xsl:if test="$numoccur=$level">+</xsl:if>
<xsl:if test="not($numoccur=$level)">-</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="pre_filtered"
select="$set[substring($filter,position(),1)='+']"/>
<xsl:variable name="filtered"
select="$nodes[count(.|$pre_filtered)=count($pre_filtered)]"/>
<xsl:if test="$level = 3">
<xsl:apply-templates select="$filtered"/>
</xsl:if>
<xsl:if test="$level != 3">
<xsl:call-template name="group">
<xsl:with-param name="level" select="$level + 1" />
<xsl:with-param name="nodes" select="$filtered" />
</xsl:call-template>
</xsl:if>
</xsl:for-each>
</group>
</xsl:for-each>
</xsl:template>

</xsl:stylesheet>

==output==

<?xml version="1.0" encoding="UTF-8"?>
<grouped xmlns:rs="rs" xmlns:z="z">
<group foo="5" level="1" groupcode="@SCE_CGPC=PGRE">
<group foo="5" level="2" groupcode="@FSG_SNAM=HOME">
<group foo="2" level="3" groupcode="@MOA_NAME=Full time">
<z:row SCE_CGPC="PGRE" FSG_SNAM="HOME" MOA_NAME="Full time"/>
</group>
<group foo="2" level="3" groupcode="@MOA_NAME=Part-Time">
<z:row SCE_CGPC="PGRE" FSG_SNAM="HOME" MOA_NAME="Part-Time"/>
</group>
</group>
<group foo="5" level="2" groupcode="@FSG_SNAM=OVERSEAS">
<group foo="2" level="3" groupcode="@MOA_NAME=Full time">
<z:row SCE_CGPC="PGRE" FSG_SNAM="OVERSEAS" MOA_NAME="Full time"/>
<z:row SCE_CGPC="PGRE" FSG_SNAM="OVERSEAS" MOA_NAME="Full time"/>
</group>
<group foo="2" level="3" groupcode="@MOA_NAME=Part-Time"/>
</group>
<group foo="5" level="2" groupcode="@FSG_SNAM=HOME MOA_NAME">
<group foo="1" level="3" groupcode="@MOA_NAME=Full time">
<z:row SCE_CGPC="PGRE" FSG_SNAM="HOME MOA_NAME" MOA_NAME="Full time"/>
</group>
<group foo="1" level="3" groupcode="@MOA_NAME=Part-Time"/>
</group>
</group>
</grouped>

This code relies on the observation that the xslt 'key' function does not
remove duplicates in the node-set it returns.
It is possible that this observation is a result of an erroneous
implementation of my xslt-processor. This would of course render the
solution useless...

regards,
--
Joris Gillis (http://users.telenet.be/root-jg/me.html)
«Εν οίδα ότι ουδ*ν οίδα» - Σωκρατης
Jun 19 '06 #2

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: kristofera | last post by:
I am trying to do a distinct grouping of some nodes sorted by a numeric value but for some reason the distinct (preceding-sibling filter) is applied to the result as if not sorted. If I don't use...
2
by: Greg | last post by:
Hi. I have a rather large xml document (object) that can have one or more nodes with a certain attribute throughout (at ANY depth, not at the same level necessarily). I need to find this...
1
by: Patrick.O.Ige | last post by:
I have a xml file and i want to format it using XSL My XSL file and XML below I needed to do a distinct which is ok on the first node "Code" For the "programDescription" i did below which gets the...
3
by: Yoav Shapira | last post by:
Hi, I have a well-formed XHTML document that, among other content, has the following segment: <img src="uniqueUrl1" /> <p>some text</p> <p>some other text</p> <p>some more text</p> <img...
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 4 Oct 2023 starting at 18:00 UK time (6PM UTC+1) and finishing at about 19:15 (7.15PM) The start time is equivalent to 19:00 (7PM) in Central...
0
by: Aliciasmith | last post by:
In an age dominated by smartphones, having a mobile app for your business is no longer an option; it's a necessity. Whether you're a startup or an established enterprise, finding the right mobile app...
0
tracyyun
by: tracyyun | last post by:
Hello everyone, I have a question and would like some advice on network connectivity. I have one computer connected to my router via WiFi, but I have two other computers that I want to be able to...
2
by: giovanniandrean | last post by:
The energy model is structured as follows and uses excel sheets to give input data: 1-Utility.py contains all the functions needed to calculate the variables and other minor things (mentions...
4
NeoPa
by: NeoPa | last post by:
Hello everyone. I find myself stuck trying to find the VBA way to get Access to create a PDF of the currently-selected (and open) object (Form or Report). I know it can be done by selecting :...
3
NeoPa
by: NeoPa | last post by:
Introduction For this article I'll be using a very simple database which has Form (clsForm) & Report (clsReport) classes that simply handle making the calling Form invisible until the Form, or all...
1
by: Teri B | last post by:
Hi, I have created a sub-form Roles. In my course form the user selects the roles assigned to the course. 0ne-to-many. One course many roles. Then I created a report based on the Course form and...
0
NeoPa
by: NeoPa | last post by:
Introduction For this article I'll be focusing on the Report (clsReport) class. This simply handles making the calling Form invisible until all of the Reports opened by it have been closed, when it...
2
by: GKJR | last post by:
Does anyone have a recommendation to build a standalone application to replace an Access database? I have my bookkeeping software I developed in Access that I would like to make available to other...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.