Search code examples
sqlxsltinputsanitizeapostrophe

Sanitizing DB inputs with XSLT


I've been looking for a method to strip my XML content of apostrophes (') since my DBMS is complaining of receiving those.

I need

<name> Jim O'Connor</name>

to become:

<name> Jim O''Connor</name>

By looking at the example described here, that is supposed to replace ' with '', I constructed the following script:

    <xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output omit-xml-declaration="yes" indent="yes" />

      <xsl:template match="node()|@*">
        <xsl:copy>
          <xsl:apply-templates select="node()|@*" />
        </xsl:copy>
      </xsl:template>

      <xsl:template name="sqlApostrophe">
        <xsl:param name="string" />
        <xsl:variable name="apostrophe">'</xsl:variable>
        <xsl:choose>
          <xsl:when test="contains($string,$apostrophe)">
            <xsl:value-of select="concat(substring-before($string,$apostrophe), $apostrophe,$apostrophe)"
            disable-output-escaping="yes" />
            <xsl:call-template name="sqlApostrophe">
              <xsl:with-param name="string"
              select="substring-after($string,$apostrophe)" />
            </xsl:call-template>
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="$string"
            disable-output-escaping="yes" />
          </xsl:otherwise>
        </xsl:choose>
      </xsl:template>

      <xsl:template match="text()">
        <xsl:call-template name="sqlApostrophe">
          <xsl:with-param name="string" select="."/>
        </xsl:call-template>
      </xsl:template>

    </xsl:stylesheet>

UPDATE: it works fine

Thanks for your help


Solution

  • The main problem is in your last template. As dacracot points out, xsl:apply-templates does not take a name attribute. To call a named template, you'd use xsl:call-template.

    If you want to apply your SQL escaping to all text nodes, you could try replacing your last template with something like this:

    <xsl:template match="text()">
      <xsl:call-template name="sqlApostrophe">
        <xsl:with-param name="string" select="."/>
      </xsl:call-template>
    </xsl:template>
    

    Also, why disable-output-escaping? If the text contains special characters (<, >, &), you'll get malformed XML as the output.