<ROOT>
<A>
<B>TESTING</B>
</A>
</ROOT>
XSL:
<xsl:variable name="nodestring" select="//A"/>
<xsl:value-of select="$nodestring"/>
I am trying to convert XML nodeset to string using XSL. Any thoughts?
Based on @jelovirt solution, here is a more complete piece of code:
<xsl:template match="*" mode="serialize">
<xsl:text><</xsl:text>
<xsl:value-of select="name()"/>
<xsl:apply-templates select="@*" mode="serialize" />
<xsl:choose>
<xsl:when test="node()">
<xsl:text>></xsl:text>
<xsl:apply-templates mode="serialize" />
<xsl:text></</xsl:text>
<xsl:value-of select="name()"/>
<xsl:text>></xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text> /></xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="@*" mode="serialize">
<xsl:text> </xsl:text>
<xsl:value-of select="name()"/>
<xsl:text>="</xsl:text>
<xsl:value-of select="."/>
<xsl:text>"</xsl:text>
</xsl:template>
<xsl:template match="text()" mode="serialize">
<xsl:value-of select="."/>
</xsl:template>
In XSLT Version 3.0. See this W3 link for fn:serialize. This worked for me using SaxonPE.
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:output="http://www.w3.org/2010/xslt-xquery-serialization">
<xsl:variable name="output">
<output:serialization-parameters>
<output:method value="html"/>
</output:serialization-parameters>
</xsl:variable>
<xsl:template match="div">
<xsl:value-of select="serialize(., $output/output:serialization-parameters)" />
</xsl:template>
</xsl:stylesheet>
You need to serialize the nodes. The most simple for your example would be something like
<xsl:template match="ROOT">
<xsl:variable name="nodestring">
<xsl:apply-templates select="//A" mode="serialize"/>
</xsl:variable>
<xsl:value-of select="$nodestring"/>
</xsl:template>
<xsl:template match="*" mode="serialize">
<xsl:text><</xsl:text>
<xsl:value-of select="name()"/>
<xsl:text>></xsl:text>
<xsl:apply-templates mode="serialize"/>
<xsl:text></</xsl:text>
<xsl:value-of select="name()"/>
<xsl:text>></xsl:text>
</xsl:template>
<xsl:template match="text()" mode="serialize">
<xsl:value-of select="."/>
</xsl:template>
The above serializer templates do not handle e.g. attributes, namespaces, or reserved characters in text nodes, but the concept should be clear. XSLT process works on a node tree and if you need to have access to "tags", you need to serialize the nodes.
<xsl:template name="serializeNodeToString">
<xsl:param name="node"/>
<xsl:variable name="name" select="name($node)"/>
<xsl:if test="$name">
<xsl:value-of select="concat('<',$name)"/>
<xsl:for-each select="$node/@*">
<xsl:value-of select="concat(' ',name(),'="',.,'" ')"/>
</xsl:for-each>
<xsl:value-of select="concat('>',./text())"/>
</xsl:if>
<xsl:for-each select="$node/*">
<xsl:call-template name="serializeNodeToString">
<xsl:with-param name="node" select="."/>
</xsl:call-template>
</xsl:for-each>
<xsl:if test="$name">
<xsl:value-of select="concat('</',$name,'>')"/>
</xsl:if>
</xsl:template>
Saxon required for following solution. I find it here
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:saxon="http://saxon.sf.net/"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- To serialize with saxon:serialize() -->
<xsl:output name="default" indent="yes"
omit-xml-declaration="yes" />
<xsl:template match="*">
<xsl:variable name="node-set">
<xsl:element name="level1">
<xsl:element name="level2" />
<xsl:element name="level2" />
</xsl:element>
</xsl:variable>
<xsl:element name="input">
<xsl:copy-of select="$node-set" />
</xsl:element>
<xsl:element name="output">
<xsl:value-of select="saxon:serialize($node-set, 'default')" />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With