I am defining a JavaScript variable from XSLT and am getting an error due to an unescaped string. I understand that I need to replace this to '
, but I'm unsure how to do that in XSLT 1.0.
XSLT example:
var currentComment = '<xsl:value-of select="root/Reviews/Review/Comment" />';
Rendered javascript with unescaped single quote:
var currentComment = 'Let's test a string.',
// Causing an error ------^
You can use the built-in entities ' and " In XSLT 1.0: Alternatively, you can define your $Q and $APOS variables (put the content (the literal " or the literal ' character) in the body of the xsl:variable , not in the select attribute).
The <xsl:text> element is used to write literal text to the output. Tip: This element may contain literal text, entity references, and #PCDATA.
Specifies the format pattern. Here are some of the characters used in the formatting pattern: 0 (Digit) # (Digit, zero shows as absent)
Definition and Usage The <xsl:value-of> element extracts the value of a selected node. The <xsl:value-of> element can be used to select the value of an XML element and add it to the output.
As Ian Roberts pointed out in his comment, you need to account for backslashes and not just apostrophes. Dimitre's answer can be modified as follows to account for this:
<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="/">
<xsl:text>var currentComment = '</xsl:text>
<xsl:apply-templates select="root/value" mode="escape" />
<xsl:text>'
</xsl:text>
<!-- Example with placing the escaped value in a variable first -->
<xsl:variable name="escapedOther">
<xsl:apply-templates select="root/otherValue" mode="escape" />
</xsl:variable>
<xsl:value-of select='concat("var otherComment = '", $escapedOther, "'")' />
</xsl:template>
<xsl:template match="@* | node()" mode="escape">
<!-- Escape the apostrophes second -->
<xsl:call-template name="replace">
<xsl:with-param name="pTarget" select='"'"' />
<xsl:with-param name="pReplacement" select='"\'"'/>
<xsl:with-param name="pText">
<!-- Escape the backslashes first, and then pass that result directly into the next template -->
<xsl:call-template name="replace">
<xsl:with-param name="pTarget" select="'\'" />
<xsl:with-param name="pReplacement" select="'\\'" />
<xsl:with-param name="pText" select="." />
</xsl:call-template>
</xsl:with-param>
</xsl:call-template>
</xsl:template>
<xsl:template name="replace">
<xsl:param name="pText"/>
<xsl:param name="pTarget" select='"'"'/>
<xsl:param name="pReplacement" select="'\"'"/>
<xsl:if test="$pText">
<xsl:value-of select='substring-before(concat($pText,$pTarget),$pTarget)'/>
<xsl:if test='contains($pText, $pTarget)'>
<xsl:value-of select='$pReplacement'/>
</xsl:if>
<xsl:call-template name="replace">
<xsl:with-param name="pText" select='substring-after($pText, $pTarget)'/>
<xsl:with-param name="pTarget" select="$pTarget"/>
<xsl:with-param name="pReplacement" select="$pReplacement"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Any time you need to escape something, you can just use apply-templates
on it with mode escape
. For this input XML:
<?xml version="1.0" encoding="utf-8"?>
<root>
<value>Let's test a string that refers to something like the C:\ drive's \Program Files Directory.</value>
<otherValue>This value has a bunch of apostrophes '''' and backslashes \\\\ in it</otherValue>
</root>
This produces:
var currentComment = 'Let\'s test a string that refers to something like the C:\\ drive\'s \\Program Files Directory.'
var otherComment = 'This value has a bunch of apostrophes \'\'\'\' and backslashes \\\\\\\\'
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