Convert XML-nodesets to string
This is an open discussion with 8 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
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']"/>
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.
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.