Skip to content

Instantly share code, notes, and snippets.

@fidothe
Created October 30, 2014 17:28
Show Gist options
  • Save fidothe/9da736aadee12629f5df to your computer and use it in GitHub Desktop.
Save fidothe/9da736aadee12629f5df to your computer and use it in GitHub Desktop.
escaping double quotes in XSLT
<?xml version="1.0" encoding="UTF-8"?>
<r>"hi"</r>
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="1.0">
<xsl:output media-type="text/plain" omit-xml-declaration="yes"/>
<xsl:template name="encode-string">
<xsl:param name="s" select="''"/>
<xsl:value-of select="translate($s, '&quot;', '\&quot;')"/>
</xsl:template>
<xsl:template match="/">
<xsl:call-template name="encode-string"><xsl:with-param name="s" select="*"/></xsl:call-template>
</xsl:template>
</xsl:stylesheet>
@ndw
Copy link

ndw commented Oct 30, 2014

Because translate() doesn't do what you think it does :-)

What you want is replace() but if you're determined to do it with XSLT 1.0, you have to roll that one by hand:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="1.0">
    <xsl:output media-type="text/plain" omit-xml-declaration="yes"/>

    <xsl:template name="encode-string">
        <xsl:param name="s" select="''"/>
        <xsl:param name="encoded" select="''"/>

        <xsl:choose>
          <xsl:when test="$s = ''">
            <xsl:value-of select="$encoded"/>
          </xsl:when>
          <xsl:when test="contains($s, '&quot;')">
            <xsl:call-template name="encode-string">
              <xsl:with-param name="s" select="substring-after($s,'&quot;')"/>
              <xsl:with-param name="encoded"
                              select="concat($encoded,substring-before($s,'&quot;'),'\&quot;')"/>
            </xsl:call-template>
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="concat($encoded, $s)"/>
          </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <xsl:template match="/">
        <xsl:call-template name="encode-string"><xsl:with-param name="s" select="*"/></xsl:call-template>
    </xsl:template>
</xsl:stylesheet>

So much easier if you can use XSLT 2.0:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">
    <xsl:output media-type="text/plain" omit-xml-declaration="yes"/>

    <xsl:template name="encode-string">
        <xsl:param name="s" select="''"/>
        <xsl:value-of select="replace($s, '&quot;', '\\&quot;')"/>
    </xsl:template>

    <xsl:template match="/">
        <xsl:call-template name="encode-string"><xsl:with-param name="s" select="*"/></xsl:call-template>
    </xsl:template>
</xsl:stylesheet>

Hope that helps...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment