Search

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.

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="'&#09;'"/>

        <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>&#10;</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>&#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>

                    <!--
                         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>&#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>

Here's an xPathr with the above in action.

cool, thanks

Hi, I'm a beginner with XSLT

I have a string variable inside my XSL template The content in this string variable is a XML - couldnt use XPath to retrieve values Could some one please let me know if there is a way to convert this String-xml content to a XML-document so that I can refer to values using XPath.

Thanks, -Panay

Hi @Panayappan. Add the EXSLT namespace and extension prefix to your stylesheet node:

<xsl:stylesheet
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:exsl="http://exslt.org/common"
    extension-element-prefixes="exsl">

Then, to use XPath on your variable, something like:

<xsl:value-of select="exsl:node-set($variable)/node[@attr='value']"/>

See EXSLT - exsl:node-set.

may a d an exclude prefix:

<xsl:stylesheet version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:exsl="http://exslt.org/common"
  exclude-result-prefixes="exsl" >

Create an account or sign in to comment.

Symphony • Open Source XSLT CMS

Server Requirements

  • PHP 5.3-5.6 or 7.0-7.3
  • PHP's LibXML module, with the XSLT extension enabled (--with-xsl)
  • MySQL 5.5 or above
  • An Apache or Litespeed webserver
  • Apache's mod_rewrite module or equivalent

Compatible Hosts

Sign in

Login details