1 users online. Create an account or sign in to join them.Users
Convert XML-nodesets to string
This is an open discussion with 5 replies, filed under XSLT.
Search
I needed some preparation work for converting nodesets to JSON using Doeke Zanstras xslt utility "xml2json".
Maybe useful for someone out there.
Convert XML-nodesets to string updated to version 1.2 on 29th of February 2012
I added formatting support to this utility.
This output is made of prettyPrint, Bootstrap and <xsl:apply-templates select="/data/events" mode="nodetostring"/>
Changes:
- Added formatting.
- Namespaced matched templates mode names.
- Removed global variables.
Result:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<!--
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="'	'"/>
<xsl:choose>
<xsl:when test="boolean(name())">
<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:apply-templates select="text()" mode="nodetostring">
<xsl:with-param name="format" select="false()"/>
</xsl:apply-templates>
<xsl:apply-templates select="." mode="nodetostring-closetag"/>
</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:if test="$format">
<xsl:text> </xsl:text>
</xsl:if>
<xsl:apply-templates select="* | text()" 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 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:if test="$format">
<xsl:text> </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>
<!--
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: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:value-of select="."/>
</xsl:otherwise>
</xsl:choose>
<xsl:if test="$format">
<xsl:text> </xsl:text>
</xsl:if>
</xsl:template>
<xsl:template match="*" mode="nodetostring-selfclosetag">
<xsl:text><</xsl:text>
<xsl:value-of select="name()"/>
<xsl:apply-templates select="@*" mode="nodetostring-attribs"/>
<xsl:text>/></xsl:text>
</xsl:template>
<xsl:template match="*" mode="nodetostring-opentag">
<xsl:text><</xsl:text>
<xsl:value-of select="name()"/>
<xsl:apply-templates select="@*" mode="nodetostring-attribs"/>
<xsl:text>></xsl:text>
</xsl:template>
<xsl:template match="*" mode="nodetostring-closetag">
<xsl:text></</xsl:text>
<xsl:value-of select="name()"/>
<xsl:text>></xsl:text>
</xsl:template>
<xsl:template match="@*" mode="nodetostring-attribs">
<xsl:value-of select="concat(' ', name(), '=', '"', ., '"')"/>
</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>
Here's an xPathr with the above in action.
cool, thanks
Create an account or sign in to comment.
A new XSLT utility, "Convert XML-nodesets to string" is now available for download. Comments and feedback can be left here but if you discover any issues, please post it on the issue tracker.