|
|
Table of Contents |
|
Recipe 8.6. Splitting DocumentsProblemYou want to partition elements from a single document into subdocuments. SolutionXSLT 1.0For 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]
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>DiscussionAlthough 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 AlsoRecipe 14.1 contains more examples that use multiple output document extensions. |
|
|
Table of Contents |
|