I haven't had a chance to study all of this, but please note that if you want
to use the XPath 3.1 function then you should be using a more recent Saxon
release than 9.3. The current version is 9.9. Also, only the 1-argument version
of sort() will work in Saxon-HE; the more useful versions of the function (that
allow a user-defined sort key) are higher order functions and therefore require
Saxon-PE or Saxon-EE. The syntax would be
<xsl:for-each-group select=“sort(entry[location=$undulator], function($entry)
{data($entry/(isodate,time))})" group-by="statistics_category">
Michael Kay
Saxonica
On 8 May 2019, at 18:08, Raimund Kammering
raimund(_dot_)kammering(_at_)desy(_dot_)de
<xsl-list-service(_at_)lists(_dot_)mulberrytech(_dot_)com> wrote:
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> <——— 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>
‘Normal’ processing of this is no problem with the following XSLT
<xsl:template match=“list”>
…
<xsl:apply-templates select="entry">
<xsl:sort order=“descending" select="isodate"/>
<xsl:sort order=“descending" select="time"/>
</xsl:apply-templates>
…
</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=‘STATISTICS’ 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=“list”>
…
<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="undulator”>SASE1</xsl:with-param>
</xsl:call-template>
<xsl:call-template name="statistics_summary">
<xsl:with-param name="undulator”>SASE2</xsl:with-param>
</xsl:call-template>
<xsl:call-template name="statistics_summary">
<xsl:with-param name="undulator”>SASE3</xsl:with-param>
</xsl:call-template>
...
<xsl:apply-templates select="entry">
<xsl:sort order=“descending" select="isodate"/>
<xsl:sort order=“descending" select="time"/>
</xsl:apply-templates>
…
</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 I’m 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=“sort(entry[location=$undulator]”, (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 I’m now finally complete stuck to find an reasonable solution
(without reworking the whole statistics calculation)! Any help would be very
appreciated!
Greetings,
Raimund
--~----------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
EasyUnsubscribe: http://lists.mulberrytech.com/unsub/xsl-list/1167547
or by email: xsl-list-unsub(_at_)lists(_dot_)mulberrytech(_dot_)com
--~--