Все решения пропускают текст после узла и атрибуты в одинарных кавычках.
Пример
<b f1='"' f2="'">one</b>
,
<b>two</b>
Мое решение на основе @ Илья-Харламов
<xsl:template name="f_serialize_node_to_string" xmlns:exsl="http://exslt.org/common" extension-element-prefixes="exsl">
<xsl:param name="node"/>
<xsl:variable name="node_" select="exsl:node-set($node)"/>
<xsl:variable name="name" select="name($node_)"/>
<xsl:variable name="q">'</xsl:variable>
<xsl:variable name="qq">"</xsl:variable>
<xsl:if test="$name">
<xsl:value-of select="concat('<',$name)"/>
<xsl:for-each select="$node_/@*">
<xsl:choose>
<xsl:when test="contains(., $qq)">
<xsl:value-of select="concat(' ',name(),'=',$q,.,$q,' ')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat(' ',name(),'="',.,'" ')"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
<xsl:value-of select="concat('>', ./text())"/>
</xsl:if>
<xsl:for-each select="$node_/*">
<xsl:call-template name="f_serialize_node_to_string">
<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:if test="$node_/following-sibling::text()">
<xsl:value-of select="$node_/following-sibling::text()" />
</xsl:if>
</xsl:template>