Skip to content

Instantly share code, notes, and snippets.

Created October 26, 2012 11:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/3958391 to your computer and use it in GitHub Desktop.
Save anonymous/3958391 to your computer and use it in GitHub Desktop.
<data>
<target id="2">
<foo>
<baz></baz>
<bar attr="test" foo="bar">baz</bar>
<foo/>
</foo>
<bar>
<test></test>
</bar>
<test>
foo
<bar/>
</test>
</target>
</data>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:template match="/">
<xsl:apply-templates select="target | target[text()]" mode="nodetostring"/>
</xsl:template>
<!--
Converts a nodeset to string, especially useful for json conversions.
===================================================================================
Copyright 2011, Thomas Appel, http://thomas-appel.com, mail(at)thomas-appel.com
dual licensed under MIT and GPL license
http://dev.thomas-appel.com/licenses/mit.txt
http://dev.thomas-appel.com/licenses/gpl.txt
===================================================================================
Example usage:
(convert a exsl nodeset to string: )
___
<xsl:variable name="somelink">
<a href="{url}" class="some-class"><xsl:value-of select="name"/></a>
</xsl:variable>
<xsl:apply-templates select="exsl:node-set($somelink)/* | exsl:node-set($some-link)/text()"/>
___
(convert xml noset to string: )
___
<xsl:apply-templates select="node | node[text()]"/>
___
Format result
___
<xsl:apply-templates select="node | node[text()]">
<xsl:with-param name="format" select="true()"/>
</xsl:apply-templates>
-->
<xsl:template match="* | text()" mode="nodetostring">
<xsl:param name="format" select="false()"/>
<xsl:param name="format-tab" select="'&#09;'"/>
<xsl:choose>
<xsl:when test="boolean(name())">
<xsl:variable name="empty"/>
<xsl:choose>
<!--
if element has children
-->
<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:if test="$format">
<xsl:text>&#10;</xsl:text>
</xsl:if>
<xsl:apply-templates select="*" mode="nodetostring">
<xsl:with-param name="format" select="$format"/>
</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:when>
<!--
if element has text
-->
<xsl:when test="normalize-space(.) != $empty">
<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:apply-templates select="text()" mode="nodetostring">
<xsl:with-param name="format" select="$format"/>
</xsl:apply-templates>
<xsl:apply-templates select="." mode="nodetostring-closetag"/>
</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:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="."/>
</xsl:otherwise>
</xsl:choose>
<xsl:if test="$format">
<xsl:text>&#10;</xsl:text>
</xsl:if>
</xsl:template>
<xsl:template match="*" mode="nodetostring-selfclosetag">
<xsl:text>&lt;</xsl:text>
<xsl:value-of select="name()"/>
<xsl:apply-templates select="@*" mode="nodetostring-attribs"/>
<xsl:text>/&gt;</xsl:text>
</xsl:template>
<xsl:template match="*" mode="nodetostring-opentag">
<xsl:text>&lt;</xsl:text>
<xsl:value-of select="name()"/>
<xsl:apply-templates select="@*" mode="nodetostring-attribs"/>
<xsl:text>&gt;</xsl:text>
</xsl:template>
<xsl:template match="*" mode="nodetostring-closetag">
<xsl:text>&lt;/</xsl:text>
<xsl:value-of select="name()"/>
<xsl:text>&gt;</xsl:text>
</xsl:template>
<xsl:template match="@*" mode="nodetostring-attribs">
<xsl:value-of select="concat(' ', name(), '=', '&#34;', ., '&#34;')"/>
</xsl:template>
<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>
</xsl:stylesheet>
</xsl:stylesheet>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment