Skip to content

Instantly share code, notes, and snippets.

@willsthompson
Created March 22, 2017 19:12
Show Gist options
  • Save willsthompson/22c04a6aaf6e6c1e10cf27635290f177 to your computer and use it in GitHub Desktop.
Save willsthompson/22c04a6aaf6e6c1e10cf27635290f177 to your computer and use it in GitHub Desktop.
Transform XSLT 2 stylesheet into XSLT 1 stylesheet. Only supports a couple XSLT 2 features, partially.
<?xml version="1.0" encoding="UTF-8"?>
<!-- TODO
- Tunnel params
- distinct-values()
- tokenize()
- group-by
- handle namespaced modes and param names
- Handle space delimited list of template modes?
-->
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:axsl="http://www.w3.org/1999/XSL/TransformAlias">
<xsl:namespace-alias stylesheet-prefix="axsl" result-prefix="xsl"/>
<xsl:template mode="#all" match="/">
<xsl:variable name="mode-expanded">
<xsl:apply-templates mode="mode-expand" select="node()">
<xsl:with-param name="modes" tunnel="yes" as="xs:string*">
<xsl:call-template name="get-modes">
<xsl:with-param name="node" select="."/>
</xsl:call-template>
</xsl:with-param>
</xsl:apply-templates>
</xsl:variable>
<xsl:variable name="tunnel-expanded">
<xsl:apply-templates mode="tunnel-expand" select="$mode-expanded/node()">
<xsl:with-param name="tunnel-params" tunnel="yes" as="xs:string*">
<xsl:call-template name="get-tunnel-params">
<xsl:with-param name="node" select="$mode-expanded/node()"/>
</xsl:call-template>
</xsl:with-param>
</xsl:apply-templates>
</xsl:variable>
<xsl:copy-of select="$tunnel-expanded"/>
</xsl:template>
<!-- Tunnel expand -->
<xsl:template name="get-tunnel-params">
<xsl:param name="node"/>
<xsl:sequence select="distinct-values($node//xsl:param[@tunnel = 'yes']/@name)"/>
</xsl:template>
<xsl:template mode="tunnel-expand" match="xsl:param/@tunnel"/>
<xsl:template mode="tunnel-expand" match="xsl:template">
<xsl:param name="tunnel-params" tunnel="yes"/>
<xsl:variable name="local-params" select="xsl:param/@name/string()"/>
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:for-each select="$tunnel-params[not(. = $local-params)]">
<axsl:param name="{.}"/>
</xsl:for-each>
<xsl:apply-templates mode="tunnel-expand" select="node()"/>
</xsl:copy>
</xsl:template>
<xsl:template mode="tunnel-expand" match="xsl:apply-templates">
<xsl:param name="tunnel-params" tunnel="yes"/>
<xsl:variable name="local-params" select="xsl:with-param/@name/string()"/>
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:for-each select="$tunnel-params[not(. = $local-params)]">
<axsl:with-param name="{.}"/>
</xsl:for-each>
<xsl:apply-templates mode="tunnel-expand" select="node()"/>
</xsl:copy>
</xsl:template>
<!-- Mode expand -->
<xsl:template name="get-modes">
<xsl:param name="node"/>
<xsl:sequence select="distinct-values($node//xsl:template/@mode)[. != '#all']"/>
</xsl:template>
<xsl:template mode="mode-expand" match="xsl:template[@mode='#all']">
<xsl:param name="modes" tunnel="yes"/>
<xsl:variable name="context" select="."/>
<xsl:for-each select="$modes">
<axsl:template mode="{.}">
<xsl:apply-templates mode="mode-expand" select="$context/(@*[. != $context/@mode] | node())">
<xsl:with-param name="current-mode" select="." tunnel="yes"/>
</xsl:apply-templates>
</axsl:template>
</xsl:for-each>
</xsl:template>
<xsl:template mode="mode-expand" match="xsl:apply-templates[@mode='#current'] | xsl:call-template[@mode='#current']">
<xsl:param name="current-mode" tunnel="yes"/>
<xsl:copy>
<xsl:attribute name="mode"><xsl:value-of select="$current-mode"/></xsl:attribute>
<xsl:apply-templates mode="mode-expand" select="@*[. != @mode]|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template mode="mode-expand" match="xsl:apply-templates[@mode='#default'] | xsl:call-template[@mode='#default']">
<xsl:copy>
<xsl:apply-templates mode="mode-expand" select="@*[. != @mode]|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template mode="#all" match="@*|node()" priority="-1">
<xsl:copy>
<xsl:apply-templates mode="#current" select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment