The xsl:include/@mode patchset I have developed to ease XML Pipeline in XSLT is not good. The major problem is it won't work on closed-source XSLT processors (Saxon PE/EE for example).
As suggested by Michael Kay, there is a standard compliant way to implement above:
<xsl:include href="link1.xsl?mode=link1"/>
It would work by means of custom URIResolver performing XSLT preprocessing.
Using this approach chain.xsl would look like
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exsl="http://exslt.org/common"> <xsl:output method="xml" omit-xml-declaration="no" indent="no" encoding="UTF-8"/> <xsl:include href="link1.xsl?mode=link1"/> <xsl:include href="link2.xsl?mode=link2"/> <xsl:include href="link3.xsl?mode=link3"/> <xsl:template match="/"> <xsl:variable name="link1"> <xsl:apply-templates mode="link1" select="node()"/> </xsl:variable> <xsl:variable name="link2"> <xsl:apply-templates mode="link2" select="exsl:node-set($link1)/node()"/> </xsl:variable> <xsl:variable name="link3"> <xsl:apply-templates mode="link3" select="exsl:node-set($link2)/node()"/> </xsl:variable> <xsl:copy-of select="exsl:node-set($link3)/node()"/> </xsl:template> </xsl:stylesheet>
, link1.xsl, link2.xsl, link3.xsl and identity.xsl will be the same as in previous variant.
I have implemented ?mode in xsl:include/@href, and it works great.
The implementation works by using custom URIResolver and SAX ContentHandler transformation. The ContentHandler transformation is implemented in Java and is on-the-fly transforming XSLT source code adding mode attribute where necessary.
The reason I choose SAX ContentHandler approach over simpler XSLT like
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" omit-xml-declaration="no" indent="no" encoding="UTF-8"/> <xsl:param name="mode"/> <xsl:template priority="-9" match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:template match="xsl:template[@match and not(@mode)] | xsl:apply-templates[not(@mode)]"> <xsl:copy> <xsl:attribute name="mode"> <xsl:value-of select="$mode"/> </xsl:attribute> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:template match="xsl:include/@href | xsl:import/@href"> <xsl:attribute name="{name()}"> <xsl:choose> <xsl:when test="contains(., '?')"> <xsl:value-of select="concat(., '&mode=', $mode)"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="concat(., '?mode=', $mode)"/> </xsl:otherwise> </xsl:choose> </xsl:attribute> </xsl:template> </xsl:stylesheet>
is because ContentHandler approach preserves line number information: if you'll make an error in the source, processor will report exact line/col position of error; w/ above XSLT that is not possible.
You can find ZIP w/ full source code attached below.
Attachment | Size |
---|---|
xml-pipeline3.zip | 8.88 KB |
Comments
Post new comment