xsl-list
[Top] [All Lists]

Re: [xsl] how to make a group-by multiple attributes motionless

2019-09-26 08:35:14
Thank you Michael, the copy-of() used this way makes perfect sense. 
Works like a charm now, thanks a lot 

Met vriendelijke groeten, 
Best regards, 

Geert Bormans 


Van: "Abel Braaksma, (Exselt) abel(_at_)exselt(_dot_)net" 
<xsl-list-service(_at_)lists(_dot_)mulberrytech(_dot_)com> 
Aan: "xsl-list" <xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com> 
Verzonden: Donderdag 26 september 2019 00:55:50 
Onderwerp: Re: [xsl] how to make a group-by multiple attributes motionless 

This code passes Saxon's streamability tests: 

<xsl:stylesheet version = "3.0" xmlns:xs = " [ http://www.w3.org/2001/XMLSchema 
| http://www.w3.org/2001/XMLSchema ] " 
xmlns:xsl = " [ http://www.w3.org/1999/XSL/Transform | 
http://www.w3.org/1999/XSL/Transform ] " > 

<xsl:mode streamable = "yes" /> 

<xsl:template match = "/" > 
<out> 
<xsl:fork> 
<xsl:for-each-group select = "/*/row" group-by = "((@* => copy-of() => sort((), 
function($x){name($x)})) ! (name() || '=' || string(.))) => string-join(' ')" > 
<xsl:sequence select = "current-group()" /> 
</xsl:for-each-group> 
</xsl:fork> 
</out> 
</xsl:template> 
</xsl:stylesheet> 

Note that the sort() function requires XPath 3.1 so its streamability analysis 
isn't covered in the XSLT 3.0 spec, but Saxon applies similar rules to 
functions such as fn:filter: if the first argument is grounded then the 
function is streamable. 

The key here is the use of copy-of() to copy the attributes before sorting; 
this enables the compiler to know that the sort function isn't going to do any 
non-streamable navigation starting at the attribute node. In fact, after 
sorting you could equally well call a user-defined function that sorts using 
xsl:perform-sort. 

Michael Kay 
Saxonica 




On 25 Sep 2019, at 22:44, Geert Bormans [ 
mailto:geert(_at_)gbormans(_dot_)telenet(_dot_)be | 
geert(_at_)gbormans(_dot_)telenet(_dot_)be ] < [ 
mailto:xsl-list-service(_at_)lists(_dot_)mulberrytech(_dot_)com | 
xsl-list-service(_at_)lists(_dot_)mulberrytech(_dot_)com ] > wrote: 

All, 

I a streaming XSLT 3.0, I have to group a series of elements by their attribute 
names and values 
I have issues making the group-by motionless 

In a simplified example 

<rows> 
<row a="val-a-1" b="b-val"/> 
<row a="val-a-2" b="b-val"/> 
<row a="val-a-1" b="b-val"/> 
<row a="val-a-2"/> 
</rows> 

I need grouping this way 

<rowgroups> 
<rowgroup hash="|a=val-a-1|b=b-val"/> 
<rowgroup hash="|a=val-a-2|b=b-val"/> 
<rowgroup hash="|a=val-a-2"/> 
</rowgroups> 

easily achieved this way 

<xsl:fork> 
<xsl:for-each-group select="*" group-by="string-join(@*/concat('|', name(), 
'=', .), '')"> 
<rowgroup hash="{current-grouping-key()}"/> 
</xsl:for-each-group> 
</xsl:fork> 

but, I could have data like this (third line attribute order swapped) 

<rows> 
<row a="val-a-1" b="b-val"/> 
<row a="val-a-2" b="b-val"/> 
<row b="b-val" a="val-a-1"/> 
<row a="val-a-2"/> 
</rows> 

and this basically gives me a fourth group using the code above 

So I want to make sure that the attributes order can be controlled when I 
prepare the group-by, but any sorting attempt I make, leads to the group-by no 
longer being motionless 

I would welcome your suggestions 

Thanks 

Met vriendelijke groeten, 
Best regards, 

Geert Bormans 
[ http://www.mulberrytech.com/xsl/xsl-list | 
XSL-List info and archive ] 
[ http://lists.mulberrytech.com/unsub/xsl-list/293509 | EasyUnsubscribe ] ( [ 
https://mail.telenet.be/zimbra/mail?client=advanced | by email ] ) 




[ http://www.mulberrytech.com/xsl/xsl-list | 
XSL-List info and archive ] 
[ http://lists.mulberrytech.com/unsub/xsl-list/554170 | EasyUnsubscribe ] ( [  
| by email ] ) 
--~----------------------------------------------------------------
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
--~--
<Prev in Thread] Current Thread [Next in Thread>