xsl-list
[Top] [All Lists]

Re: [xsl] streaming XSLT creating a header from a first record

2018-05-08 10:58:38
Interesting Martin, thanks, will give that a go

Best regards, 

Geert Bormans 

-------------------------------------------------------------- 
Markup UK - a conference about XML and other mark-up languages 
London, June 9–10 2018 
Programme now available at [ http://markupuk.org/speakers.xhtml | 
http://markupuk.org/speakers.xhtml ] 
Early bird registration extended [ http://markupuk.org/registration.xhtml | 
http://markupuk.org/registration.xhtml ]

----- Oorspronkelijk bericht -----
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: Dinsdag 8 mei 2018 17:55:05
Onderwerp: Re: [xsl] streaming XSLT creating a header from a first record

On 08.05.2018 17:33, Martin Honnen martin(_dot_)honnen(_at_)gmx(_dot_)de wrote:
On 08.05.2018 17:19, Geert Bormans geert(_at_)gbormans(_dot_)telenet(_dot_)be 
wrote:
All,

I have a potentially huge tabular structure in an XML file: one 
"table'' element, many "row" elements, each having a series of attributes

I want to process them using a streaming XSLT, but I am hitting an issue

I want to use information from the first row in a header construct, in 
a way using the first row information twice
That is fairly easy done if the result were something like CSV, 
because then I can deal with the header and first row in one go
but now I need the header in some sort of metadata section at the 
start of the document
and all the rows including row one in an adjacent structure, but 
wrapped (the results of the row processing in a container)

I tried to create the full structure in a template for the first row 
and process the following siblings of the first row... but that can't 
be done "when the context posture is striding" (sic)

Any ideas? Thanks,

How about setting up an accumulator

<xsl:accumulator name="first-row-values" as="map(xs:string, xs:string)" 
initial-value="map{}" streamable="yes">
   <xsl:accumulator-rule match="table/row[1]"
      select="map:merge(@*!map { node-name() : data(.) })"/>
</xsl:accumulator>

then you can use that map in all following rows.


Hm, I forgot that you can't have positional predicates in a streamable 
match pattern so it seems you first need to set up an additional 
accumulator counting the rows and then to make sure the other 
accumulator only stores the attribute values for the first row. 
Additionally I had the wrong map type, so

        <xsl:mode streamable="yes" on-no-match="shallow-copy" 
use-accumulators="#all"/>
        
        
        <xsl:accumulator name="row-count" as="xs:integer" streamable="yes" 
initial-value="0">
                <xsl:accumulator-rule match="table/row" select="$value + 1"/>
        </xsl:accumulator>
        
        <xsl:accumulator name="first-row-values" as="map(xs:QName, xs:string)" 
initial-value="map{}" streamable="yes">
                <xsl:accumulator-rule match="table/row"
                        select="if (accumulator-before('row-count') eq 1)
                                then map:merge(@*!map { node-name() : string(.) 
})
                                else $value"/>
        </xsl:accumulator>
        

should work better. Only drawback is that maps don't preserve the order 
of entries although as the data comes from XML attributes which aren't 
ordered either that might not matter.
--~----------------------------------------------------------------
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>