[XSL-LIST Mailing List Archive Home]
[By Thread]
[By Date]
Re: [xsl] Group and sort nodes by attribut in child node
Subject: Re: [xsl] Group and sort nodes by attribut in child node From: "Jens Burkhardt" <JensBurkhardt@xxxxxx> Date: Mon, 17 Oct 2011 13:06:21 +0200 (CEST) |
Hi Brandon, thank you so much for your help. As far as I can see this is excactly what I needed. Thanks to everyone else who tried to help me! Best, Jens -----UrsprC<ngliche Nachricht----- Von: "Brandon Ibach" <brandon.ibach@xxxxxxxxxxxxxxxxxxx> Gesendet: 17.10.2011 10:43:26 An: xsl-list@xxxxxxxxxxxxxxxxxxxxxx Betreff: Re: [xsl] Group and sort nodes by attribut in child node >Yes, the approach can be adapted fairly easily. We can start with the >same first step, building a list of the records sorted by the >Start_Date field, then output that list in order, except that whenever >we hit the first record in each group, we output the header and walk >the rest of the list, outputting only records in that group, then >continue with the rest of the list where we left off. > >The only part of the transform that needs to change is the >"group-records" template. > > <xsl:template name="group-records"> > <xsl:param name="id-list" select="''"/> > <xsl:param name="do-group" select="''"/> > <xsl:param name="done" select="' '"/> > <xsl:if test="$id-list"> > <xsl:variable name="record" select="key('records', >substring-before($id-list, ' '))"/> > <xsl:variable name="group" >select="string($record/column[@field='Group']/@value)"/> > <xsl:choose> > <xsl:when test="$group = $do-group"> > <xsl:if test="$group"><xsl:text> </xsl:text></xsl:if> > <xsl:value-of >select="concat($record/column[@field='keyword']/@value, ' - ', >$record/column[@field='Start_Date']/@value, ' ')"/> > </xsl:when> > <xsl:when test="not($do-group) and not(contains($done, >concat(' ', $group, ' ')))"> > <xsl:value-of select="concat($group, ' ')"/> > <xsl:call-template name="group-records"> > <xsl:with-param name="id-list" select="$id-list"/> > <xsl:with-param name="do-group" select="$group"/> > </xsl:call-template> > </xsl:when> > </xsl:choose> > <xsl:call-template name="group-records"> > <xsl:with-param name="id-list" select="substring-after($id-list, ' ')"/> > <xsl:with-param name="do-group" select="$do-group"/> > <xsl:with-param name="done" select="concat($done, $group, ' ')"/> > </xsl:call-template> > </xsl:if> > </xsl:template> > >-Brandon :) > > >On Mon, Oct 17, 2011 at 3:27 AM, Jens Burkhardt <JensBurkhardt@xxxxxx> wrote: >> Hello Brandon, >> >> i was able to test your approach and youB4re right, i have to group the records by their group (with its own group for null values) and sort the values within their group by date and finally >> sort the groupy by their date. >> The output should be like MartinB4s output: >> >> A - 23.12.2010 >> X_Group >> B C - 23.12.2010 >> B B - 24.12.2010 >> B D - 25.12.2010 >> Y_Group >> B D - 25.12.2010 >> B E - 26.12.2010 >> >> Howevery, is this possible? I will try to rewrite your approach but will be thankful for every hint :). >> >> Thanks in advance. >> >> Best, >> Jens >> >> >> -----UrsprC<ngliche Nachricht----- >> Von: "Brandon Ibach" <brandon.ibach@xxxxxxxxxxxxxxxxxxx> >> Gesendet: 14.10.2011 21:22:49 >> An: xsl-list@xxxxxxxxxxxxxxxxxxxxxx >> Betreff: Re: [xsl] Group and sort nodes by attribut in child node >> >>>Here's a version of Martin's approach that works in XSLT 1.0. >>>However, is this really a match for your requirements? I got the >>>impression from your initial post that the goal was more like "group >>>the records by their 'Group' value, putting each record with a null >>>'Group' in its own group, then sort the records by date within their >>>group and sort the groups by the earliest date in the group". >>> >>><?xml version="1.0" encoding="utf-8"?> >>><xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> >>> <xsl:output method="text"/> >>> >>> <xsl:key name="records" match="record" use="generate-id(.)"/> >>> >>> <xsl:template match="records"> >>> <xsl:call-template name="group-records"> >>> <xsl:with-param name="id-list"> >>> <xsl:for-each select="record"> >>> <xsl:sort >>>select="concat(substring-after(substring-after(column[@field='Start_Date'] /@value, >>>'.'), '.'), >>> >>>substring-before(substring-after(column[@field='Start_Date']/@value, >>>'.'), '.'), >>> >>>substring-before(column[@field='Start_Date']/@value, '.'))"/> >>> <xsl:value-of select="generate-id(.)"/><xsl:text> </xsl:text> >>> </xsl:for-each> >>> </xsl:with-param> >>> </xsl:call-template> >>> </xsl:template> >>> >>> <xsl:template name="group-records"> >>> <xsl:param name="id-list" select="''"/> >>> <xsl:param name="last" select="''"/> >>> <xsl:if test="$id-list"> >>> <xsl:variable name="record" select="key('records', >>>substring-before($id-list, ' '))"/> >>> <xsl:variable name="group" >>>select="string($record/column[@field='Group']/@value)"/> >>> <xsl:if test="$group and $group != $last"> >>> <xsl:value-of select="concat($group, ' ')"/> >>> </xsl:if> >>> <xsl:if test="$group"><xsl:text> </xsl:text></xsl:if> >>> <xsl:value-of >>>select="concat($record/column[@field='keyword']/@value, ' - ', >>>$record/column[@field='Start_Date']/@value, ' ')"/> >>> <xsl:call-template name="group-records"> >>> <xsl:with-param name="id-list" select="substring-after($id-list, ' ')"/> >>> <xsl:with-param name="last" select="$group"/> >>> </xsl:call-template> >>> </xsl:if> >>> </xsl:template> >>></xsl:stylesheet> >>> >>>-Brandon :) >>> >>> >>>On Fri, Oct 14, 2011 at 11:21 AM, Jens Burkhardt <JensBurkhardt@xxxxxx> wrote: >>>> Wow. Thanks for the quick reply. First of all, sorry for not telling that i have to use XSLT 1.0. I knew i forgot something. The result your style sheet produces meets my requirement >>>> perfectly but i need it, as I said for XSLT 1.0. >>>> Nodes where the group value is empty should not be in the same group so what you did is perfect. Is there any way to do this for xslt 1.0? >>>> >>>> Thank you. >>>> >>>> Jens >>>> >>>>>Martin Honnen wrote: >>>>>> Jens Burkhardt wrote: >>>>>> >>>>>>> The result should be like this: >>>>>>> A - 23.10.2010 >>>>>>> X_Group >>>>>>> C - 23.10.2010 >>>>>>> B - 24.12.2010 >>>>>>> D - 25.10.2010 >>>>>>> Y_Group >>>>>>> D - 25.12.2010 >>>>>>> E - 26.12.2010 >>>>>>> >>>>>>> I want to group by the value of the group field in the column node and >>>>>>> everything should be sorted by start_date. The name of the group (e.g. >>>>>>> X_Group) should start a group-block, followed by the record nodes >>>>>>> which belong to the group value. >>>>>>> Another problem is that i donB4t know the group value in advance, >>>>>>> because they can be set to whatever the user want. >>>>>> >>>>>> Do you use XSLT 2.0 or 1.0? >>>>>> And what about the record with keyword value "A" and the one with >>>>>> keyword value "D" where the group value is an empty string? Shouldn't >>>>>> they be in the same group? >>>>> >>>>>Here is an XSLT 2.0 stylesheet that sorts first and the groups adjacent >>>>>records in the sorted sequence: >>>>> >>>>><xsl:stylesheet >>>>> xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >>>>> xmlns:xs="http://www.w3.org/2001/XMLSchema" >>>>> exclude-result-prefixes="xs" >>>>> version="2.0"> >>>>> >>>>> <xsl:output method="text"/> >>>>> >>>>> <xsl:template match="records"> >>>>> <xsl:variable name="sorted" as="element(record)*"> >>>>> <xsl:perform-sort select="record"> >>>>> <xsl:sort select="xs:date(concat(substring(column[@field = >>>>>'Start_Date']/@value, 7), '-', >>>>> substring(column[@field = >>>>>'Start_Date']/@value, 4, 2), '-', >>>>> substring(column[@field = >>>>>'Start_Date']/@value, 1, 2)))"/> >>>>> </xsl:perform-sort> >>>>> </xsl:variable> >>>>> <xsl:for-each-group select="$sorted" group-adjacent="column[@field >>>>>= 'Group']/@value"> >>>>> <xsl:choose> >>>>> <xsl:when test="current-grouping-key()"> >>>>> <xsl:value-of select="current-grouping-key()"/> >>>>> <xsl:text> </xsl:text> >>>>> <xsl:value-of select="current-group()/concat(' ', >>>>>column[@field = 'keyword']/@value, ' - ', column[@field = >>>>>'Start_Date']/@value)" >>>>> separator=" "/> >>>>> <xsl:text> </xsl:text> >>>>> </xsl:when> >>>>> <xsl:otherwise> >>>>> <xsl:value-of select="current-group()/concat(column[@field = >>>>>'keyword']/@value, ' - ', column[@field = 'Start_Date']/@value)"/> >>>>> <xsl:text> </xsl:text> >>>>> </xsl:otherwise> >>>>> </xsl:choose> >>>>> </xsl:for-each-group> >>>>> </xsl:template> >>>>> >>>>></xsl:stylesheet> >>>>> >>>>>With that stylesheet Saxon 9.3 HE, when applying it to the input >>>>> >>>>><records> >>>>><record> >>>>> <column field="keyword" value="A"></column> >>>>> <column field="Start_Date" value="23.12.2010"></column> >>>>> <column field="Group" value=""></column> >>>>></record> >>>>><record> >>>>> <column field="keyword" value="B"></column> >>>>> <column field="Start_Date" value="24.12.2010"></column> >>>>> <column field="Group" value="X_Group"></column> >>>>></record> >>>>><record> >>>>> <column field="keyword" value="D"></column> >>>>> <column field="Start_Date" value="25.12.2010"></column> >>>>> <column field="Group" value=""></column> >>>>></record> >>>>><record> >>>>> <column field="keyword" value="C"></column> >>>>> <column field="Start_Date" value="23.12.2010"></column> >>>>> <column field="Group" value="X_Group"></column> >>>>></record> >>>>><record> >>>>> <column field="keyword" value="D"></column> >>>>> <column field="Start_Date" value="25.12.2010"></column> >>>>> <column field="Group" value="Y_Group"></column> >>>>></record> >>>>><record> >>>>> <column field="keyword" value="E"></column> >>>>> <column field="Start_Date" value="26.12.2010"></column> >>>>> <column field="Group" value="Y_Group"></column> >>>>></record> >>>>></records> >>>>> >>>>>outputs >>>>> >>>>>A - 23.12.2010 >>>>>X_Group >>>>> C - 23.12.2010 >>>>> B - 24.12.2010 >>>>>D - 25.12.2010 >>>>>Y_Group >>>>> D - 25.12.2010 >>>>> E - 26.12.2010 >>>>> >>>>> >>>>>Does that solution meet your requirement? ___________________________________________________________ SMS schreiben mit WEB.DE FreeMail - einfach, schnell und kostenguenstig. Jetzt gleich testen! http://f.web.de/?mc=021192
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] Group and sort nodes by a, Brandon Ibach | Thread | [no subject], Unknown |
Re: [xsl] Speed problem, Michael Kay | Date | Re: [xsl] "grouping" footnote numbe, Wendell Piez |
Month |
Keywords