RE: [xsl] Split into numbered files: without side-effect? (XSLT 2)

Subject: RE: [xsl] Split into numbered files: without side-effect? (XSLT 2)
From: "Michael Kay" <mike@xxxxxxxxxxxx>
Date: Wed, 26 Sep 2007 19:48:38 +0100
I may have missed something, but I can't see why the following doesn't work:

<xsl:variable name="root" select="/"/>
<xsl:for-each select="doc('startingElements.xml')/element">
  <xsl:variable name="path" select="string(.)"/>
  <xsl:for-each select="$root/saxon:evaluate($path)">
    <xsl:result-document href="chunk{position()}.xml">
      <xsl:copy-of select="."/>
    </
  </
</

with a bit of elaboration to put leading zeros in the filename, etc.

Michael Kay
http://www.saxonica.com/

 

> -----Original Message-----
> From: Yves Forkl [mailto:Y.Forkl@xxxxxx] 
> Sent: 26 September 2007 16:43
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: [xsl] Split into numbered files: without 
> side-effect? (XSLT 2)
> 
> Hi all,
> 
> until now I have been coping quite well without being able to 
> use any side effects in XSLT, but for the ridiculously simple 
> task I am trying to do, I just don't see how to avoid 
> "cheating" by shamefully falling back on saxon:assign in XSLT 2.
> 
> I would like to split the contents of my input file into a 
> series of chunks, each going into a separate text file, 
> consecutively numbered in the order in which the chunks are 
> created (and all of the text nodes should go into the main 
> result document as well). The trouble comes in from these 
> requirements:
> 
> a) The list of elements making up the chunks should be configurable:
>     their paths from the root node are to be read from an XML file.
> 
> b) The chunks need not be rooted at the same level in the tree.
> 
> For instance, assume I have this input document:
> 
> <?xml version="1.0" encoding="iso-8859-1"?> <root>
>    <a>
>      <content>text of a</content>
>    </a>
>    <b>
>      <b1>
>        <content>text of b1</content>
>      </b1>
>      <b2>
>        <content>text of b2</content>
>      </b2>
>    </b>
>    <c>
>      <content>text of c</content>
>    </c>
> </root>
> 
> Another file, named chunk_starting_elements.xml, says for 
> which element instances to start a new chunk, by giving their 
> local name (this is just for simplicity's sake, in reality I 
> am using their paths from the root node):
> 
> <?xml version="1.0" encoding="iso-8859-1"?> <chunks>
>    <element>a</element>
>    <element>b1</element>
>    <element>b2</element>
>    <element>c</element>
> </chunks>
> 
> The desired result of the transformation is a series of 4 files named
> 
> chunk_01_a.txt
> chunk_02_b1.txt
> chunk_03_b2.txt
> chunk_04_c.txt
> 
> each of them containing the text nodes from the corresponding 
> element as given in chunk_starting_elements.xml (plus all of 
> it in the main result document).
> 
> While the stylesheet below certainly does the job (provided 
> it's Saxon which processes it), I wonder how to adapt it into 
> pure, side-effect free XSLT 2. Any suggestions?
> 
>    Yves
> 
> 
> <?xml version="1.0" encoding="iso-8859-1"?> <xsl:stylesheet 
> version="2.0" 
> xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
>    xmlns:xs="http://www.w3.org/2001/XMLSchema";
>    xmlns:my="http://xmlns.srz.de/yforkl/xslt/functions";
>    xmlns:saxon="http://saxon.sf.net/";
>    extension-element-prefixes="saxon"
>    exclude-result-prefixes="my xs saxon">
> 
>    <xsl:output method="text" indent="yes"/>
> 
>    <xsl:variable name="chunk-number" saxon:assignable="yes" 
> select="0"/>
> 
>    <xsl:function name="my:chunk-started-by" as="node()*">
>      <xsl:param name="context-element" as="node()"/>
>      <xsl:sequence
>        select="document('chunk_starting_elements.xml')
>                  /chunks/element[. = local-name($context-element)]"/>
>    </xsl:function>
> 
>    <xsl:template match="*">
> 
>      <xsl:variable name="new-chunk-name"
>        select="my:chunk-started-by(.)"/>
> 
>      <xsl:if test="$new-chunk-name">
>        <xsl:result-document
>          href="{concat('chunk_', format-number($chunk-number 
> + 1, '00'),
>                        '_', $new-chunk-name, '.txt')}">
>          <saxon:assign name="chunk-number" 
> select="$chunk-number + 1"/>
>          <xsl:apply-templates/>
>        </xsl:result-document>
>      </xsl:if>
> 
>      <xsl:apply-templates/>
> 
>    </xsl:template>
> 
> </xsl:stylesheet>

Current Thread