Created
September 6, 2013 16:00
-
-
Save andrewminton/6465924 to your computer and use it in GitHub Desktop.
Nodetostring test
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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" | |
extension-element-prefixes="exsl"> | |
<!-- | |
Converts a nodeset to string, especially useful for json conversions. | |
=================================================================================== | |
Adapted from @Thomas Appel's nodetostring utility at http://www.getsymphony.com/download/xslt-utilities/view/79266/ | |
This version adds formatting capabilities. Very useful for displaying code snippets. | |
=================================================================================== | |
Example usage: | |
(convert a nodeset to string: ) | |
___ | |
<xsl:call-template name="nodetostring"> | |
<xsl:with-param name="node" select="YOUR_XML"/> | |
</xsl:template> | |
___ | |
Format result | |
___ | |
<xsl:call-template name="nodetostring"> | |
<xsl:with-param name="node" select="YOUR_XML"/> | |
<xsl:with-param name="format" select="true()"/> | |
</xsl:template> | |
___ | |
Escape double quotes | |
___ | |
<xsl:call-template name="nodetostring"> | |
<xsl:with-param name="node" select="YOUR_XML"/> | |
<xsl:with-param name="esc-dblq" select="true()"/> | |
</xsl:template> | |
--> | |
<xsl:template name="nodetostring"> | |
<!-- Incoming XML --> | |
<xsl:param name="node"/> | |
<!-- Turn format on and off --> | |
<xsl:param name="format" select="false()"/> | |
<!-- Format indent --> | |
<xsl:param name="format-tab" select="'	'"/> | |
<!-- Escape double quotes in strings --> | |
<xsl:param name="esc-dblq" select="false()"/> | |
<xsl:apply-templates select="exsl:node-set($node)/* | exsl:node-set($node)/text()" mode="nodetostring"> | |
<xsl:with-param name="format" select="$format"/> | |
<xsl:with-param name="format-tab" select="$format-tab"/> | |
<xsl:with-param name="esc-dblq" select="$esc-dblq"/> | |
</xsl:apply-templates> | |
</xsl:template> | |
<!-- Render nodes --> | |
<xsl:template match="*" mode="nodetostring"> | |
<xsl:param name="format" select="false()"/> | |
<xsl:param name="format-tab" select="'	'"/> | |
<xsl:param name="esc-dblq" select="false()"/> | |
<xsl:variable name="empty"/> | |
<xsl:choose> | |
<!-- | |
if element has text only | |
--> | |
<xsl:when test="normalize-space(.) != $empty and not(*)"> | |
<xsl:if test="$format"> | |
<xsl:apply-templates select="ancestor::*[1]" mode="nodetostring-format"> | |
<xsl:with-param name="format-tab" select="$format-tab"/> | |
</xsl:apply-templates> | |
</xsl:if> | |
<xsl:apply-templates select="." mode="nodetostring-opentag"> | |
<xsl:with-param name="esc-dblq" select="$esc-dblq"/> | |
</xsl:apply-templates> | |
<xsl:apply-templates select="text()" mode="nodetostring"> | |
<xsl:with-param name="format" select="false()"/> | |
<xsl:with-param name="esc-dblq" select="$esc-dblq"/> | |
</xsl:apply-templates> | |
<xsl:apply-templates select="." mode="nodetostring-closetag"> | |
<xsl:with-param name="esc-dblq" select="$esc-dblq"/> | |
</xsl:apply-templates> | |
</xsl:when> | |
<!-- | |
if element has text and children | |
--> | |
<xsl:when test="normalize-space(.) != $empty and *"> | |
<xsl:if test="$format"> | |
<xsl:apply-templates select="ancestor::*[1]" mode="nodetostring-format"> | |
<xsl:with-param name="format-tab" select="$format-tab"/> | |
</xsl:apply-templates> | |
</xsl:if> | |
<xsl:apply-templates select="." mode="nodetostring-opentag"> | |
<xsl:with-param name="esc-dblq" select="$esc-dblq"/> | |
</xsl:apply-templates> | |
<xsl:if test="$format"> | |
<xsl:text> </xsl:text> | |
</xsl:if> | |
<xsl:apply-templates select="* | text()" mode="nodetostring"> | |
<xsl:with-param name="format" select="$format"/> | |
<xsl:with-param name="esc-dblq" select="$esc-dblq"/> | |
</xsl:apply-templates> | |
<xsl:if test="$format"> | |
<xsl:apply-templates select="ancestor::*[1]" mode="nodetostring-format"> | |
<xsl:with-param name="format-tab" select="$format-tab"/> | |
</xsl:apply-templates> | |
</xsl:if> | |
<xsl:apply-templates select="." mode="nodetostring-closetag"> | |
<xsl:with-param name="esc-dblq" select="$esc-dblq"/> | |
</xsl:apply-templates> | |
</xsl:when> | |
<!-- | |
if element has children only | |
--> | |
<xsl:when test="*"> | |
<xsl:if test="$format"> | |
<xsl:apply-templates select="ancestor::*[1]" mode="nodetostring-format"> | |
<xsl:with-param name="format-tab" select="$format-tab"/> | |
</xsl:apply-templates> | |
</xsl:if> | |
<xsl:apply-templates select="." mode="nodetostring-opentag"> | |
<xsl:with-param name="esc-dblq" select="$esc-dblq"/> | |
</xsl:apply-templates> | |
<xsl:if test="$format"> | |
<xsl:text> </xsl:text> | |
</xsl:if> | |
<xsl:apply-templates select="*" mode="nodetostring"> | |
<xsl:with-param name="format" select="$format"/> | |
<xsl:with-param name="esc-dblq" select="$esc-dblq"/> | |
</xsl:apply-templates> | |
<xsl:if test="$format"> | |
<xsl:apply-templates select="ancestor::*[1]" mode="nodetostring-format"> | |
<xsl:with-param name="format-tab" select="$format-tab"/> | |
</xsl:apply-templates> | |
</xsl:if> | |
<xsl:apply-templates select="." mode="nodetostring-closetag"> | |
<xsl:with-param name="esc-dblq" select="$esc-dblq"/> | |
</xsl:apply-templates> | |
</xsl:when> | |
<!-- | |
assuming empty tags are self closing, e.g. <img/>, <source/>, <input/> | |
--> | |
<xsl:otherwise> | |
<xsl:if test="$format"> | |
<xsl:apply-templates select="ancestor::*[1]" mode="nodetostring-format"> | |
<xsl:with-param name="format-tab" select="$format-tab"/> | |
</xsl:apply-templates> | |
</xsl:if> | |
<xsl:apply-templates select="." mode="nodetostring-selfclosetag"> | |
<xsl:with-param name="esc-dblq" select="$esc-dblq"/> | |
</xsl:apply-templates> | |
</xsl:otherwise> | |
</xsl:choose> | |
<xsl:if test="$format"> | |
<xsl:text> </xsl:text> | |
</xsl:if> | |
</xsl:template> | |
<!-- Render text --> | |
<xsl:template match="text()" mode="nodetostring"> | |
<xsl:param name="format" select="false()"/> | |
<xsl:param name="format-tab" select="'	'"/> | |
<xsl:param name="esc-dblq" select="false()"/> | |
<xsl:if test="$format"> | |
<xsl:apply-templates select="ancestor::*[1]" mode="nodetostring-format"> | |
<xsl:with-param name="format-tab" select="$format-tab"/> | |
</xsl:apply-templates> | |
</xsl:if> | |
<xsl:choose> | |
<xsl:when test="$esc-dblq"> | |
<xsl:call-template name="nodetostring.replace"> | |
<xsl:with-param name="in" select="."/> | |
<xsl:with-param name="needle" select="'"'"/> | |
<xsl:with-param name="replace" select="'\"'"/> | |
</xsl:call-template> | |
</xsl:when> | |
<xsl:otherwise> | |
<xsl:value-of select="."/> | |
</xsl:otherwise> | |
</xsl:choose> | |
<xsl:if test="$format"> | |
<xsl:text> </xsl:text> | |
</xsl:if> | |
</xsl:template> | |
<!-- Render self closing tags --> | |
<xsl:template match="*" mode="nodetostring-selfclosetag"> | |
<xsl:param name="esc-dblq" select="false()"/> | |
<xsl:text><</xsl:text> | |
<xsl:value-of select="name()"/> | |
<xsl:apply-templates select="@*" mode="nodetostring-attribs"> | |
<xsl:with-param name="esc-dblq" select="$esc-dblq"/> | |
</xsl:apply-templates> | |
<xsl:text>/></xsl:text> | |
</xsl:template> | |
<!-- Render open tag --> | |
<xsl:template match="*" mode="nodetostring-opentag"> | |
<xsl:param name="esc-dblq" select="false()"/> | |
<xsl:text><</xsl:text> | |
<xsl:value-of select="name()"/> | |
<xsl:apply-templates select="@*" mode="nodetostring-attribs"> | |
<xsl:with-param name="esc-dblq" select="$esc-dblq"/> | |
</xsl:apply-templates> | |
<xsl:text>></xsl:text> | |
</xsl:template> | |
<!-- Render close tag --> | |
<xsl:template match="*" mode="nodetostring-closetag"> | |
<xsl:text></</xsl:text> | |
<xsl:value-of select="name()"/> | |
<xsl:text>></xsl:text> | |
</xsl:template> | |
<!-- Render attributes --> | |
<xsl:template match="@*" mode="nodetostring-attribs"> | |
<xsl:param name="esc-dblq" select="false()"/> | |
<xsl:variable name="dbl-quotes"> | |
<xsl:if test="$esc-dblq">\</xsl:if> | |
<xsl:text>"</xsl:text> | |
</xsl:variable> | |
<xsl:value-of select="concat(' ', name(), '=', $dbl-quotes, ., $dbl-quotes)"/> | |
</xsl:template> | |
<!-- Formatter utility. Inserts $format-tab as long as parents exist --> | |
<xsl:template match="*" mode="nodetostring-format"> | |
<xsl:param name="format-tab"/> | |
<xsl:value-of select="$format-tab"/> | |
<xsl:apply-templates select="ancestor::*[1]" mode="nodetostring-format"> | |
<xsl:with-param name="format-tab" select="$format-tab"/> | |
</xsl:apply-templates> | |
</xsl:template> | |
<!-- Utility to replace a string in another string --> | |
<xsl:template name="nodetostring.replace"> | |
<xsl:param name="in" select="''"/> | |
<xsl:param name="needle" select="''"/> | |
<xsl:param name="replace" select="''"/> | |
<xsl:choose> | |
<xsl:when test="contains($in, $needle)"> | |
<xsl:value-of select="substring-before($in, $needle)"/> | |
<xsl:value-of select="$replace"/> | |
<xsl:call-template name="nodetostring.replace"> | |
<xsl:with-param name="in" select="substring-after($in, $needle)"/> | |
<xsl:with-param name="needle" select="$needle"/> | |
<xsl:with-param name="replace" select="$replace"/> | |
</xsl:call-template> | |
</xsl:when> | |
<xsl:otherwise> | |
<xsl:value-of select="$in"/> | |
</xsl:otherwise> | |
</xsl:choose> | |
</xsl:template> | |
</xsl:stylesheet> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment