Recipe8.6.Splitting Documents


Recipe 8.6. Splitting Documents

Problem

You want to partition elements from a single document into subdocuments.

Solution

XSLT 1.0

For XSLT 1.0, you must rely on a widely available but nonstandard extension that allows multiple output documents.[3] The solution determines the level in the document structure to serialize and determines the name of the resulting file. The following stylesheet splits the salesBySalesPerson.xml from Chapter 4 into separate files for each salesperson. The stylesheet works in Saxon. Saxon allows use of the XSLT 1.1 xsl:document element when the stylesheet version is set to 1.1 and some processors support exslt:document from exslt.org.[4]

[3] In XSLT 2.0, this facility is available and uses a new element called xsl:result-document. See Chapter 6 for details.

[4] XSLT 1.1 is no longer an official version. It was abandoned in favor of XSLT 2.0.

If you prefer not to use version 1.1, then you can use the saxon:output extension:

<xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">     <xsl:include href="copy.xslt"/>     <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> <xsl:strip-space elements="*"/>     <xsl:template match="salesperson">   <xsl:variable name="outFile"    select="concat('salesperson.',translate(@name,' ','_'),'.xml')"/>           <!-- Non-standard saxon xsl:document! -->   <xsl:document href="{$outFile}">         <xsl:copy>               <xsl:copy-of select="@*"/>             <xsl:apply-templates/>        </xsl:copy>   </xsl:document> </xsl:template>     <xsl:template match="salesBySalesperson">   <xsl:apply-templates/> </xsl:template>     </xsl:stylesheet>

Discussion

Although the previous stylesheet is specific to Saxon, the technique works with most XSLT 1.0 processors with only minor changes. Saxon also has the saxon:output extension element (xmlns:saxon = "http://icl.com/saxon"). Xalan uses xalan:redirect (xmlns:xalan = "http://xml.apache.org/xalan").

An interesting variation of splitting also produces an output file that xincludes the generated subfiles:

<xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">     <xsl:import href="copy.xslt"/>     <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> <xsl:strip-space elements="*"/>       <xsl:template match="salesperson">   <xsl:variable name="outFile"        select="concat('salesperson.',translate(@name,' ','_'),'.xml')"/>           <xsl:document href="{$outFile}">        <xsl:copy>               <xsl:copy-of select="@*"/>             <xsl:apply-templates/>        </xsl:copy>   </xsl:document>       <xi:include href="{$outFile}"                          xmlns:xi="http://www.w3.org/2001/XInclude"/>    </xsl:template>        </xsl:stylesheet>

If you worry that your XSLT processor might someday recognize XInclude and mistakenly try to include the same file that was just output, you can replace the xi:include literal result element with xsl:element:

  <xsl:element name="xi:include"           xmlns:xi="http://www.w3.org/2001/XInclude">     <xsl:attribute name="href">       <xsl:value-of select="$outFile"/>     </xsl:attribute>    </xsl:element>

See Also

Recipe 14.1 contains more examples that use multiple output document extensions.




XSLT Cookbook
XSLT Cookbook: Solutions and Examples for XML and XSLT Developers, 2nd Edition
ISBN: 0596009747
EAN: 2147483647
Year: 2003
Pages: 208
Authors: Sal Mangano

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net