RE: [xsl] GROUPING AND KEYS

Subject: RE: [xsl] GROUPING AND KEYS
From: Cleyton Jordan <cleytonjordan@xxxxxxxxxxx>
Date: Wed, 29 Apr 2009 03:25:14 -0700 (PDT)
Hi Michael,

I would like to thank you for your explanation. It was brillant.

So this bit of code will output only one value when they are the same.

<xsl:for-each select="foo/shift/partNo[count(. | key('partNo', @num)[=
1]) = 1]">

And this bit will output all values.

 <xsl:for-each select="key('partNo', @num)">

It is a like a one to many relationship or header / values.

Cheers

C


--- On Wed, 29/4/09, xsl-list-digest-help@xxxxxxxxxxxxxxxxxxxxxx
<xsl-list-digest-help@xxxxxxxxxxxxxxxxxxxxxx> wrote:

> From: xsl-list-digest-help@xxxxxxxxxxxxxxxxxxxxxx
<xsl-list-digest-help@xxxxxxxxxxxxxxxxxxxxxx>
> Subject: xsl-list Digest 29 Apr 2009 05:10:00 -0000 Issue 1832
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Date: Wednesday, 29 April, 2009, 6:10 AM
> xsl-list Digest 29 Apr 2009 05:10:00 -0000 Issue 1832
>
> Topics (messages 50662 through 50668):
>
> GROUPING AND KEYS
> 	50662 by: Cleyton Jordan
> 	50663 by: Michael Kay
>
> Re: How to cast current-group() ?
> 	50664 by: Studer Leo
> 	50665 by: David Carlisle
> 	50666 by: Studer Leo
>
> Placing an element in a very specific position
> 	50667 by: Anders.Svensson.sorman.com
> 	50668 by: G. Ken Holman
>
> Administrivia:
>
> To subscribe to the digest, e-mail:
> 	<xsl-list-digest-subscribe@xxxxxxxxxxxxxxxxxxxxxx>
>
> To unsubscribe from the digest, e-mail:
> 	<xsl-list-digest-unsubscribe@xxxxxxxxxxxxxxxxxxxxxx>
>
> To post to the list, e-mail:
> 	<xsl-list@xxxxxxxxxxxxxxxxxxxxxx>
>
>
> ----------------------------------------------------------------------
> Date: Tue, 28 Apr 2009 03:21:09 -0700 (PDT)
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> From: Cleyton Jordan <cleytonjordan@xxxxxxxxxxx>
> Subject: GROUPING AND KEYS
> Message-ID:
> <723360.94134.qm@xxxxxxxxxxxxxxxxxxxxxxxxxxx>
>
> Hi,
>
> I would like to understand how keys and grouping work in
> XSLT and I came ac=
> ross a post that might help me. However, I have some
> questions regarding th=
> e code and would appreciate if someone could shed some
> light about sections=
>  of the code I do not understand.
>
> "I have Nodes that all have "Shift" data.
> Within these Shifts, I have a Pa=
> rt Number.  Now, I want to be able to group and add
> together all the data a=
> ssociated with a Part Number, regardless of what Shift it
> was produced in.=
> =20
>
> For example, I want to be able to add together all the
> "counts" for part nu=
> mber 1. "=20
>
> <foo>
> <shift>
>   <partNo num=3D"1">
>     <data count=3D"2"/>
>     <data time=3D"3"/>
>   </partNo>
> </shift>
> <shift>
>   <partNo num=3D"1">
>     <data count=3D"1"/>
>     <data time=3D"5"/>
>   </partNo>
> </shift>
> <shift>
>   <partNo num=3D"2">
>     <data count=3D"5"/>
>     <data time=3D"7"/>
>   </partNo>
> </shift>
> <foo>
> 1 - Is there a way to visualise in XSLT what this key looks
> like?
>
> <xsl:key name=3D"partNo"
> match=3D"partNo" use=3D"@num" />
>
> In this statement <xsl:for-each
> select=3D"foo/shift/partNo[count(. | key('p=
> artNo', @num)[1]) =3D 1]">
>
> we are selecting all partNo nodes where count(. | key(
> 'partNo', @num)[1]) =
> =3D 1]
>
> 2 - What does . mean in this expression? the partNo
> node?=20
>
> 3 - What does | mean?=20
>
> 4 - key( 'partNo', @num) - this is the key. Are we
> using the current @num a=
> ttribute to get all the partNo whose @num =3D 1 then 2
> etc...?
>
> 5 - )[1]) =3D 1 - Why is it using an array index [1] to get
> the first one a=
> nd then using =3D 1 ?
>
> I would very much appreciate some feedback and help to
> understand this code=
> ..
>
> CJ
>
> CODE
>
> <xsl:key name=3D"partNo"
> match=3D"partNo" use=3D"@num" />
>
> <xsl:template match=3D"/">
>     <xsl:for-each
> select=3D"foo/shift/partNo[count(. |
> key('partNo', @num)[=
> 1]) =3D 1]">
>         <xsl:sort select=3D"@num" />
>         Part num: <xsl:value-of
> select=3D"@num" />
>         <xsl:for-each
> select=3D"key('partNo', @num)">
>             [<xsl:value-of
> select=3D"data/@count" />,
>             <xsl:value-of
> select=3D"data/@time" />]
>         </xsl:for-each>
>         <br />
>
>     </xsl:for-each>
> </xsl:template>
> </xsl:stylesheet>=0A=0A=0A
>
> ------------------------------
>
> Date: Tue, 28 Apr 2009 11:41:57 +0100
> To: <xsl-list@xxxxxxxxxxxxxxxxxxxxxx>
> From: "Michael Kay" <mike@xxxxxxxxxxxx>
> Subject: RE: [xsl] GROUPING AND KEYS
> Message-ID:
> <5E5B62704D0144729D28C826C55063DD@Sealion>
>
> It's worth being clear that we're talking here
> about the Muenchian method of
> grouping in XSLT 1.0. Grouping in XSLT 2.0 is much much
> simpler.
>
> > 1 - Is there a way to visualise in XSLT what this key
> looks like?
> >
> > <xsl:key name="partNo"
> match="partNo" use="@num" />
>
> You can think of it like this: "Each document that
> contains partNo elements
> has an index, allowing a partNo element to be found quickly
> if the value of
> its @num attribute is known". For example,
> key('partNo', 'P123') returns all
> the partNo elements whose @num value is P123.
> >
> >
> > In this statement <xsl:for-each
> > select="foo/shift/partNo[count(. |
> key('partNo', @num)[1]) = 1]">
>
> In XSLT 1.0, there is no simple way of asking "$A is
> $B", that is, testing
> whether two expressions refer to the same node. There are
> two common
> workarounds to this:
>
> generate-id($A) = generate-id($B)
>
> which relies on the fact that if two nodes have the same
> generated ID then
> they are the same node, and
>
> count($A|$B) = 1
>
> which relies on the fact that the union of two singleton
> sets is a singleton
> only if both sets have the same member. In your example,
> this is the
> expression you are seeing.
>
> Specifically, it's selecting every partNo that is the
> first partNo with a
> given @num value. That is "." (the partNo being
> tested) is the same node as
> key('partNo', @num)[1], which is the first partNo
> with that @num value.
> >
> > we are selecting all partNo nodes where count(. | key(
>
> > 'partNo', @num)[1]) = 1]
> >
> > 2 - What does . mean in this expression? the partNo
> node?
>
> Yes, in a predicate "." refers to the node being
> tested.
> >
> > 3 - What does | mean?
>
> It's a union operator, it forms the union of two sets.
>
> Hope this helps.
>
> Michael Kay
> http://www.saxonica.com/
>
> ------------------------------
>
> Date: Tue, 28 Apr 2009 17:19:07 +0200
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> From: Studer Leo <leo.studer@xxxxxx>
> Subject: Re: [xsl] How to cast current-group() ?
> Message-id:
> <D707EA35-3AA7-42F2-8AB8-C4891670FAD7@xxxxxx>
>
> Dear Michael
>
> thank you for your input. I work with Saxon SA-9.1.0.6
> which is not to
> bad with typing and not foolish strict neither...
>
> The problem is the XSLT processor allows me to use this
> code snippet
>
>    <xsl:for-each-group select="/results/match"
> group-by="team">
>           <xsl:copy-of
> select="myfn:MakeTableRow(current-grouping-
> key(),current-group())"/>
>    </xsl:for-each-group>
>
> with the function only without the type control...
>
>      <xsl:function name="myf:MakeTableRow"
> as="schema-
> element(xhtml:tr)">
>          <xsl:param name="team"/>   <!--
> as="schema-element(res:team)"
> -->
>          <xsl:param name="matches"/>
> <!-- as="schema-
> element(res:match)*" -->
>          <tr xsl:validation="strict">
>             ...
>          </tr>
>      </xsl:function>
>
> your comment
>
> > current-grouping-key() is an atomic value, not an
> element. You could
> > construct an element and give it a type by validating
> it, but I
> > suspect
> > that's not what you want to do.
>
> is a solution to the problem, however not the most elegant
> one. Type
> casting would be nicer...
>
> I put the whole file in the end.
>
> Thanks again
> Leo
>
> <?xml version="1.0"
> encoding="ISO-8859-1"?>
> <xsl:stylesheet version="2.0"
> xmlns:xsl="http://www.w3.org/1999/XSL/Transform
> "
>      xmlns:xs="http://www.w3.org/2001/XMLSchema";
>      xmlns:res="http://results.bla";
>      xmlns:myf="http://leostuder.ch/funtions";
>
>      xmlns="http://www.w3.org/1999/xhtml";
>      xmlns:xhtml="http://www.w3.org/1999/xhtml";
> exclude-result-
> prefixes="xs res myf xhtml">
>
>      <xsl:output method="xhtml"
> encoding="ISO-8859-1" indent="yes"
>          doctype-public="-//W3C//DTD XHTML 1.0
> Strict//EN"
>
> doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd
>
> "/>
>
>      <xsl:import-schema
> namespace="http://results.bla"; schema-
> location="results.xsd"/>
>
>      <xsl:import-schema
> namespace="http://www.w3.org/1999/xhtml";
>
> schema-location="http://www.w3.org/2002/08/xhtml/xhtml1-strict.xsd
>
> "/>
>
>      <xsl:function name="myf:MakeTableRow"
> as="schema-
> element(xhtml:tr)">
>          <xsl:param name="team"/>   <!--
> as="schema-element(res:team)"
> -->
>          <xsl:param name="matches"/>
> <!-- as="schema-
> element(res:match)*" -->
>          <tr xsl:validation="strict">
>              <td>
>                  <xsl:value-of
> select="$team"/>
>              </td>
>              <td>
>                  <xsl:value-of
> select="count($matches)"/>
>              </td>
>              <xsl:variable name="won"
>
> select="count($matches[res:team[.=$team]/@score  gt
> res:team[.!=$team]/@score])"
>                  as="xs:integer"/>
>              <td>
>                  <xsl:value-of
> select="$won"/>
>              </td>
>              <td>
>                  <xsl:value-of
>
> select="count($matches[res:team[.=$team]/@score
> lt res:team[.!=$team]/@score])"/>
>              </td>
>              <xsl:variable name="drawn"
>
> select="count($matches[res:team[.=$team]/@score  eq
> res:team[.!=$team]/@score])"
>                  as="xs:integer"/>
>              <td>
>                  <xsl:value-of
> select="$drawn"/>
>              </td>
>              <td>
>                  <xsl:value-of
> select="sum($matches/res:team[.=$team]/
> @score)"/>
>              </td>
>              <td>
>                  <xsl:value-of
> select="sum($matches/res:team[.!=$team]/
> @score)"/>
>              </td>
>              <td>
>                  <xsl:number
> value="3*$won+$drawn"/>
>              </td>
>          </tr>
>      </xsl:function>
>
>      <xsl:template match="/">
>          <html xsl:validation="strict">
>              <!-- xsl:validation="strict"
> possible in html tag -->
>              <head>
>                  <title>Spielresultate</title>
>              </head>
>              <body>
>                  <xsl:apply-templates/>
>              </body>
>          </html>
>      </xsl:template>
>
>      <xsl:template match="res:results">
>          <h2>Results</h2>
>
>          <table cellpadding="10">
>              <thead>
>                  <tr>
>                      <td>Team</td>
>                      <td>Played</td>
>                      <td>Won</td>
>                      <td>Lost</td>
>                      <td>Drawn</td>
>                      <td>For</td>
>                      <td>Against</td>
>                      <td>Points</td>
>                  </tr>
>              </thead>
>
>              <xsl:variable name="teamResults"
> as="schema-
> element(xhtml:tr)*">
>                  <xsl:for-each-group
> select="/res:results/res:match"
> group-by="res:team">
>                      <xsl:sequence
> select="myf:MakeTableRow(current-
> grouping-key(),current-group())"/>
>                  </xsl:for-each-group>
>              </xsl:variable>
>              <xsl:for-each
> select="$teamResults">
>                  <xsl:sort
> select="./xhtml:td[8]"
> order="descending"
> data-type="number"/>
>                  <xsl:sort
> select="./xhtml:td[6]"
> order="descending"/>
>                  <xsl:sort
> select="./xhtml:td[7]"
> order="ascending"/>
>                  <xsl:copy-of select="."/>
>              </xsl:for-each>
>
>          </table>
>
>      </xsl:template>
>
> </xsl:stylesheet>
>
> ------------------------------
>
> Date: Tue, 28 Apr 2009 16:33:47 +0100
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> From: David Carlisle <davidc@xxxxxxxxx>
> Subject: Re: [xsl] How to cast current-group() ?
> Message-Id:
> <200904281533.n3SFXlrS029185@xxxxxxxxxxxxxxxxxxx>
>
> as Michael said the problem isn't so much the schema
> typing as the fact
> that you are passing a string when the function expects an
> element.
> this fails
>  as="schema-element(res:team)"
> but so would
>     as="element()"
>
> Your function expects a team element so just give it one
> instead of a
> string, there will (presumably) necessarily be a team
> element child of
> the current node in a valid document so
>
>   <xsl:copy-of
> select="myfn:MakeTableRow(team,current-group())"/>
>
> should work and be able to cope with any typing of the
> first parameter.
>
> David
>
> ________________________________________________________________________
> The Numerical Algorithms Group Ltd is a company registered
> in England
> and Wales with company number 1249803. The registered
> office is:
> Wilkinson House, Jordan Hill Road, Oxford OX2 8DR, United
> Kingdom.
>
> This e-mail has been scanned for all viruses by Star. The
> service is
> powered by MessageLabs.
> ________________________________________________________________________
>
> ------------------------------
>
> Date: Tue, 28 Apr 2009 18:55:37 +0200
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> From: Studer Leo <leo.studer@xxxxxx>
> Subject: Re: [xsl] How to cast current-group() ?
> Message-id:
> <0DAFB6BC-B67E-4160-A896-9EEA5657A620@xxxxxx>
>
> David
>
> thanks for caring!
>
> > as Michael said the problem isn't so much the
> schema typing as the
> > fact
> > that you are passing a string when the function
> expects an element.
>
> Finally I get it. current-grouping-key() is
> xs:anyAtomicType and not
> en element...
>
> blessings
> Leo
>
> ------------------------------
>
> Date: Wed, 29 Apr 2009 00:42:25 +0200
> To: <xsl-list@xxxxxxxxxxxxxxxxxxxxxx>
> From: <Anders.Svensson@xxxxxxxxxx>
> Subject: Placing an element in a very specific position
> Message-ID:
> <D69E5A9D77766E43ADB213473C2F82BB02AE9AE1@xxxxxxxxxxxx>
> Keywords: disclaimer
>
> Hi,=20
>
> I have a problem where I have been asked if I can put an
> element in the
> top of the third column in a three-column page. My initial
> thought is
> that this can't be done. I have tried to investigate
> absolute-positioning and floats, but cannot find anything
> that would
> seem to do this. I have no idea how it would be possible to
> decide that
> it should end up in the top of the third column
> specifically. In the
> first column would be easy, and if I could put it in the
> header that
> should be easy too, but unfortunately the header is not an
> option due to
> the fact that there are space requirements so that each
> column needs to
> be utilized completely.=20
>
> Is there any way to do this, or do I need to tell my client
> that it
> can't be done?=20
>
> Any suggestions greatly appreciated!=20
>
> Regards,=20
>
> Anders
> ###########################################=0A=
> =0A=
> This message has been scanned by F-Secure Anti-Virus for
> Microsoft =
> Exchange.=0A=
> For more information, connect to http://www.f-secure.com/
>
> ------------------------------
>
> Date: Tue, 28 Apr 2009 20:39:59 -0400
> To: <xsl-list@xxxxxxxxxxxxxxxxxxxxxx>
> From: "G. Ken Holman"
> <gkholman@xxxxxxxxxxxxxxxxxxxx>
> Subject: Re: [xsl] Placing an element in a very specific
> position
> Message-Id:
> <7.0.1.0.2.20090428202827.02505178@xxxxxxxxxxxxxxxxxxxxxx>
>
> I regret to confirm your suspicions, unless perhaps there
> is an out
> that you have not described.
>
> The column geometry in XSL-FO does not allow you to key out
> a hole at
> the top of the third column and flow around it.
>
> But, I can give you a fixed size box at the top of what
> looks like
> the third column, into which you flow your element.  But
> the box
> cannot grow, so I don't know if you can use it.
>
> And you have to use XSL-FO 1.1.
>
> Create three body regions, each with one column (or two
> body regions,
> the first with two columns and the second with one column).
>  Create a
> flow map such that the region on the right flows after the
> other.
>
> Size this right-most body region shorter than the other,
> leaving the
> hole at the top.  This gives the appearance of a third
> column when,
> technically, it is a different region.
>
> Into this hole you can place an absolutely-positioned block
>
> container.  If this is only on the first page, then your
> absolutely-positioned block container can be flowed at the
> start of
> the flow.  If this is on every page then you can flow that
> absolutely-positioned block container in one of the static
> content
> areas.  Whether the content in that hole changes or not
> might be an
> issue, but you may be able to use markers to make it vary.
>
> I hope this helps!
>
> . . . . . . . . . . . Ken
>
> p.s. if Mats Hultemark is still with Sorman, please pass on
> my
> regards (but I know it is a big company and you may not
> know him).
>
> At 2009-04-29 00:42 +0200, Anders.Svensson@xxxxxxxxxx
> wrote:
> >Hi,
> >
> >I have a problem where I have been asked if I can put
> an element in the
> >top of the third column in a three-column page. My
> initial thought is
> >that this can't be done. I have tried to
> investigate
> >absolute-positioning and floats, but cannot find
> anything that would
> >seem to do this. I have no idea how it would be
> possible to decide that
> >it should end up in the top of the third column
> specifically. In the
> >first column would be easy, and if I could put it in
> the header that
> >should be easy too, but unfortunately the header is not
> an option due to
> >the fact that there are space requirements so that each
> column needs to
> >be utilized completely.
> >
> >Is there any way to do this, or do I need to tell my
> client that it
> >can't be done?
> >
> >Any suggestions greatly appreciated!
> >
> >Regards,
> >
> >Anders
>
> --
> XSLT/XSL-FO/XQuery hands-on training - Los Angeles, USA
> 2009-06-08
> Crane Softwrights Ltd.
> http://www.CraneSoftwrights.com/s/
> Training tools: Comprehensive interactive XSLT/XPath
> 1.0/2.0 video
> Video lesson:
> http://www.youtube.com/watch?v=PrNjJCh7Ppg&fmt=18
> Video overview:
> http://www.youtube.com/watch?v=VTiodiij6gE&fmt=18
> G. Ken Holman
> mailto:gkholman@xxxxxxxxxxxxxxxxxxxx
> Male Cancer Awareness Nov'07
> http://www.CraneSoftwrights.com/s/bc
> Legal business disclaimers:
> http://www.CraneSoftwrights.com/legal
>
> ------------------------------
>
> End of xsl-list Digest
> ***********************************

Current Thread