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 |
---|
|
<- Previous | Index | Next -> |
---|---|---|
RE: [xsl] GROUPING AND KEYS, Michael Kay | Thread | [xsl] Placing an element in a very , Anders.Svensson |
Re: [xsl] Placing an element in a v, G. Ken Holman | Date | [xsl] Validate using MSXML, Michael Nielsen |
Month |