[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Can fold-left process the attributes nodes of a stream

Subject: Can fold-left process the attributes nodes of a streamed element?
From: "Martin Honnen martin.honnen@xxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Tue, 27 Jul 2021 14:02:21 -0000
 Can fold-left process the attributes nodes of a stream
I am struggling to find a compact way to use XSLT 3 streaming and an
accumulator to sum up the attribute values of certain elements,e.g.
xsl:accumulator name="attribute-sums" as="map(xs:QName, xs:decimal)"
initial-value="map{}" streamable="yes" to accumulate the sum of each
attribute by the name of the attribute.


One problem is that accumulators don't fire on attribute nodes, only on element nodes, therefore I have to write the accumulator-rule to match on the parent element of the attributes and compute all the sums in a single rule;

B  fold-left(@*, $value, function($v, $a) { map:put($v, node-name($a),
(map:get($v, node-name($a)), 0)[1] + xs:decimal($a)) })

seemed like a compact and elegant use of XPath 3.1 but using a dynamic
inline function as the argument to fold-left doesn't seem to pass the
streamability analysis.

Then I tried to set up a user-defined function to be passed in as the
third argument to fold-left, but somehow that approach doesn't seem to
work either as a streamable stylesheet function needs to take the
streamable nodes as the first parameter while the signature of the
function $f of fold-left would make the attribute node the second parameter.

So the only options I could think of is not passing the attribute nodes
themselves to fold-left but rather an array or map of the name and value
I need to store in the accumulator e.g.

fold-left(@* ! [node-name(), xs:decimal(.)], $value, function($v, $anv)
{ map:put($v, $anv?1, (map:get($v, $anv?1), 0)[1] + $anv?2) })

or to abandon fold-left and use xsl:iterate in the accumulator rules

B B <xsl:accumulator name="attribute-sums" as="map(xs:QName,
xs:decimal)" initial-value="map{}" streamable="yes">
B B B B B B B <xsl:accumulator-rule match="Book">
B B B B B B B B B B B <xsl:iterate select="@*">
B B B B B B B B B B B B B B B <xsl:param name="accumulator-map"
select="$value"/>
B B B B B B B B B B B B B B B <xsl:on-completion
select="$accumulator-map"/>
B B B B B B B B B B B B B B B <xsl:next-iteration>
B B B B B B B B B B B B B B B B B B B <xsl:with-param
name="accumulator-map"
B B B B B B B B B B B B B B B B B B B B B B B select="map:put($accumulator-map, node-name(),
(map:get($accumulator-map, node-name()), 0)[1] + xs:decimal(.))"/>
B B B B B B B B B B B B B B B </xsl:next-iteration>
B B B B B B B B B B B </xsl:iterate>
B B B B B B B </xsl:accumulator-rule>
B B B </xsl:accumulator>



The xsl:iterate approach feels too verbose, I kind of think fold-left should suffice to process the sequence of attributes (without that escape hatch to map them first to an array or map).

Any ideas or opinions whether I have missed an approach to use fold-left?

Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.