No, there isn't a generic way to reverse an XSLT. In fact, I'd say the majority of XSLTs are not reversible. It is possible, however, to design your example above so that it can be run in the forward direction or reverse direction by changing a parameter value:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exslt="http://exslt.org/common">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:param name="direction" select="'forward'" />
<xsl:variable name="mappingNF">
<map from="greeting" to="H1" />
<map from="pleasantry" to="H2" />
</xsl:variable>
<xsl:variable name="mapping" select="exslt:node-set($mappingNF)" />
<xsl:template match="@* | node()" priority="-1" name="Copy">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*" mode="copy">
<xsl:call-template name="Copy" />
</xsl:template>
<xsl:template match="*">
<xsl:variable name="mappingItem"
select="$mapping/*[$direction = 'forward' and @from = local-name(current()) or
$direction = 'reverse' and @to = local-name(current())]" />
<xsl:apply-templates select="current()[$mappingItem]" mode="rename">
<xsl:with-param name="mappingItem" select="$mappingItem" />
</xsl:apply-templates>
<xsl:apply-templates select="current()[not($mappingItem)]" mode="copy" />
</xsl:template>
<xsl:template match="*" mode="rename">
<xsl:param name="mappingItem" />
<xsl:element name="{$mappingItem/@to[$direction = 'forward'] |
$mappingItem/@from[$direction = 'reverse']}">
<xsl:apply-templates select ="@* | node()" />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
The mappingNF
indicates the correspondence between node names, and this can be augmented with as many map
s as needed. The direction of the conversion can be switched back and forth by changing the value of the direction
parameter between "forward" and "reverse".