Subject: [xsl] Problem sorting incoming node list From: "Raimund Kammering raimund.kammering@xxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> Date: Wed, 8 May 2019 17:07:57 -0000 |
Hello, I have simple sorting problem but none the less am completely stuck! I know the standard techniques for sorting and how and where to apply it - at least I thought so! But for the given set of transformations I fail to fiddle in the sorting for one part of the transformations! Problem is as follows: XML is like this (sorry for the long example, but to make the not nice order clear I need to supply such a sequence) <list> <entry> <severity>NONE</severity> <isodate>2019-05-06</isodate> <time>07:01:03</time> <location>not set</location> <category>USERLOG</category> </entry> <entry> <severity>STATISTICS</severity> <isodate>2019-05-06</isodate> <time>07:00:00</time> <location>SASE1</location> <statistics_category>SASE_delivery</statistics_category> <SASE_tuning>not_set</SASE_tuning> <Linac_setup>not_set</Linac_setup> <Down>not_set</Down> <category>STATISTICS</category> </entry> <entry> <severity>STATISTICS</severity> <isodate>2019-05-06</isodate> <time>07:00:00</time> <location>SASE2</location> <statistics_category>SASE_delivery</statistics_category> <SASE_tuning>not_set</SASE_tuning> <Linac_setup>not_set</Linac_setup> <Down>not_set</Down> <category>STATISTICS</category> </entry> <entry> <severity>STATISTICS</severity> <isodate>2019-05-06</isodate> <time>07:00:00</time> <location>SASE3</location> <statistics_category>SASE_delivery</statistics_category> <SASE_tuning>not_set</SASE_tuning> <Linac_setup>not_set</Linac_setup> <Down>not_set</Down> <category>STATISTICS</category> </entry> <entry> <severity>NONE</severity> <isodate>2019-05-06</isodate> <time>07:15:53</time> <location>not set</location> <category>USERLOG</category> </entry> ... <entry> <severity>NONE</severity> <isodate>2019-05-06</isodate> <time>08:57:47</time> <category>USERLOG</category> </entry> <entry> <severity>STATISTICS</severity> <isodate>2019-05-06</isodate> <time>08:30:00</time> <bbb This <entry> is NOT sorted according to time! <location>ACCELERATOR</location> <statistics_category>Linac_setup</statistics_category> <Linac_setup>not_set</Linac_setup> <SASE_tuning>not_set</SASE_tuning> <Down>not_set</Down> <category>STATISTICS</category> </entry> <entry> <severity>NONE</severity> <isodate>2019-05-06</isodate> <time>09:08:45</time> <category>USERLOG</category> </entry> </list> bNormalb processing of this is no problem with the following XSLT <xsl:template match=blistb> b& <xsl:apply-templates select="entry"> <xsl:sort order=bdescending" select="isodate"/> <xsl:sort order=bdescending" select="time"/> </xsl:apply-templates> b& </xsl:template> This correctly produces one to one processing of the standard entries (category=USERLOG). But now I need to do some bulk processing to evaluate some time differences. Logic is roughly like this: 1. get (first) category=bSTATISTICSb entry 2. find next one (smaller times since descending) with same location 3. Calculate time difference (done by a function f:duration-in-hours()) 4. Advance to new found time step 5. repeat This is done for all possible locations and even allows easily summing up the partial time spans like this: <xsl:template name="statistics_summary"> <xsl:param name="undulator"/> <xsl:for-each-group select="entry[location=$undulator]" group-by="statistics_category"> <xsl:value-of select="current-grouping-key()"/> <xsl:text>:  </xsl:text> <xsl:value-of select="format-number(sum(current-group()/f:duration-in-hours(.,$undulator)), '0.00'), ' h'"/> </xsl:for-each-group> </xsl:template> This template is called from the list template like this: <xsl:template match=blistb> b& <xsl:call-template name="statistics_summary"> <xsl:with-param name="undulator">ACCELERATOR</xsl:with-param> </xsl:call-template> <xsl:call-template name="statistics_summary"> <xsl:with-param name="undulatorb>SASE1</xsl:with-param> </xsl:call-template> <xsl:call-template name="statistics_summary"> <xsl:with-param name="undulatorb>SASE2</xsl:with-param> </xsl:call-template> <xsl:call-template name="statistics_summary"> <xsl:with-param name="undulatorb>SASE3</xsl:with-param> </xsl:call-template> ... <xsl:apply-templates select="entry"> <xsl:sort order=bdescending" select="isodate"/> <xsl:sort order=bdescending" select="time"/> </xsl:apply-templates> b& </xsl:template> The whole transformations work well except for that the incorrect order in respect to the <time> value make the result incorrect! So idea is clearly: Sort the entries according to the <time> element before processing with for-each-group. But here I completely failed! First idea would be to use apply-templates instead of call-template to allow the use of xsl:sort, but this breaks all logic implemented for the time span calculations. Next would be to sort within the statistics_summary template, but here I guess Ibm on the wrong axis - right? Even tried to do a copy-of to create a small node set only containing the relevant entries and sort these prior to passing it to the for-each-group but did not manage to do so and might anyhow not be very clever. Naively thinking I would love to have a kind of xpath sort to allow something like this: <xsl:for-each-group select=bsort(entry[location=$undulator]b, (isodate,time)) group-by="statistics_category"> and found this to be present in xpath 3.1. But here I ran into transformer exceptions concerning the syntax (using Saxon 9.3.0.5 HE) So that Ibm now finally complete stuck to find an reasonable solution (without reworking the whole statistics calculation)! Any help would be very appreciated! Greetings, Raimund
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] Using XSLT to process a d, Michael Kay mike@xxx | Thread | Re: [xsl] Problem sorting incoming , Michael Kay mike@xxx |
Re: [xsl] Using XSLT to process a d, Michael Kay mike@xxx | Date | Re: [xsl] Problem sorting incoming , Michael Kay mike@xxx |
Month |