Search code examples
xmlxsltxproc

Saving each node of a xml document as a file with XProc


I got a xml document with follwing structure

<listOfNodes>
    <node name="file1">content1</node>
    <node name="file2">content2</node>
    ...
    <node name="fileN">contentN</node>
</listOfNodes>

I want to create a xproc pipeline with the result:

  • file1.txt with content1
  • file2.txt with content2
  • ...
  • fileN.txt with contentN

My first approach is:

<p:declare-step name="step_1" type="ts:Extract">
        <p:input port="source" />
        <p:filter select="nodes" name="step_1.1" />
         <p:for-each name="step_1.2">
            <p:iteration-source><p:pipe port="result" step="step_1.1"/></p:iteration-source>
            <p:store method="text" >
                 <p:with-option name="href" select="concat('file:/', 'step_1_',iteration-position(),'.txt')"/>
            </p:store>
        </p:for-each>
</p:declare-step>

But I get a DX0006 error on this.

Can anybody help me, please?


Solution

  • Provided content1, ..., contentN are well-formed XML, the following pipeline does the trick:

    <p:declare-step version="1.0" xmlns:p="http://www.w3.org/ns/xproc">
      <p:input port="source"/>
      <p:for-each>
        <p:iteration-source select="/*/node"/>
        <p:variable name="filename" select="concat(/node/@name, '.txt')"/>
        <p:unwrap match="/*"/>
        <p:store>
          <p:with-option name="href" select="$filename"/>
        </p:store>
      </p:for-each>
    </p:declare-step>
    

    If content1, ..., contentN are not well-wormed XML (plain text, multiple sibling elements etc.), then you can wrap them in an XML wrapper element before you apply p:store (or simply don't apply the p:unwrap step). If you don't want to use a wrapper element, then standard p:store will not work (some XProc implementations may support extension attributes on p:store to store only the contents of the document element; but that is another story). One possibility is to use p:xslt instead.