XPROC - Generation of files in secondary port

644 Views Asked by At

My requirement is to generate one XML file and few HTML files in the secondary port. I have configured few steps in XProc.

Here’s the sample code:

<p:xslt name="create-document">
    <p:input port="stylesheet">
      <p:document href="stylesheet.xsl" />
    </p:input>  
  </p:xslt>  
  <p:for-each>
    <p:iteration-source>
      <p:pipe step="create-document" port="secondary" />
    </p:iteration-source>
   <p:store>
    <p:with-option name="doctype-public" select="'-//W3C//DTD XHTML 1.0 Frameset//EN'" />
    <p:with-option name="doctype-system" select="'http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd'" />
    <p:with-option name="encoding" select="'UTF-8'" />
    <p:with-option name="media-type" select="'text/html'" />
    <p:with-option name="method" select="'xhtml'" />
    <p:with-option name="omit-xml-declaration" select="'no'" />
  </p:store>
  </p:for-each>

The problem here is HTML file is generated properly. And the XML file is generated, but I am not able to view the XML content. Instead it displays everything in HTML format.This is because of <p:store> in the above code snippet.

How do you have two <p:store> steps? (One for HTML and the other for XML)

1

There are 1 best solutions below

0
On

It would be nice if you could somehow determine with which xsl:result-document parameters each document on the secondary output was written. You would be able to duplicate those for your p:store. But you can derive other things from each document. You can retrieve the document name using base-uri(), and you can look at for instance the root element. You can put these values in a variable using:

<p:variable name="path" select="base-uri(/*)"/>
<p:variable name="root" select="local-name(/*)"/>

(Put these just below the p:iteration-source.)

You then need to decide how to call p:store. You could use XPath if, provided your XProc parser supports XPath 2.0 (like XMLCalabash does). But I’d recommend using a p:choose like this:

<p:choose>
    <p:when test="ends-with($path, '.xhtml')">
        <p:store
            doctype-public="-//W3C//DTD XHTML 1.0 Frameset//EN"
            doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"
            encoding="UTF-8"
            media-type="text/html"
            method="xhtml"
            omit-xml-declaration="no">
            <p:with-option name="href" select="$path"/>
        </p:store>
    </p:when>
    <p:otherwise>
        <p:store
            encoding="UTF-8"
            media-type="application/xml"
            method="xml"
            omit-xml-declaration="no">
            <p:with-option name="href" select="$path"/>
        </p:store>
    </p:otherwise>
</p:choose>

(This entire p:choose replaces the p:store you already have.)

The test in p:when only looks at $path, but you could include a test for $root as well, if you like.

It also requires you to use .xhtml as extension in your xsl:result-document statements for the HTML output, but you can easily tweak that if you like.

The var and the choose should be enough to get your XML written properly, at least.

Good luck!