xsl-list
[Top] [All Lists]

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

2018-05-08 11:12:16
Thanks Michael, worth trying, will do

Best regards, 

Geert Bormans 

----- 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 18:03:51
Onderwerp: Re: [xsl] streaming XSLT creating a header from a first record

I don't think you need two accumulators, you can have a single accumulator that 
matches every row and only creates the map if the current value is an empty map.

Another way to do this is with xsl:iterate: iterate over the rows with an 
xsl:param holding the column names found in the first row (initial value is 
map{}); within the xsl:iterate, do an xsl:choose; when test="position()=1" do 
an xsl:next-iteration with a populated map as the xsl:with-param parameter 
value; otherwise process the row and just do a defaulted xsl:next-iteration 
which processes the next row with unchanged parameter values.

Michael Kay
Saxonica 

On 8 May 2018, at 16:55, Martin Honnen martin(_dot_)honnen(_at_)gmx(_dot_)de 
<xsl-list-service(_at_)lists(_dot_)mulberrytech(_dot_)com> wrote:

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>