The following script illustrates a silent failure in Chrome 42.0.2311.135 when attempting to apply a recursive template escapeStringForJson
to a string longer a certain length (1874 chars for me). I filed this as a bug, but is there a way to rewrite the template so that it is not recursive?
var transformXml = function (xml, xslt) {
var xmlScrapeResult = (new DOMParser()).parseFromString(xml, 'text/xml');
var transform = (new DOMParser()).parseFromString(xslt, 'text/xml');
var xsltProcessor = new XSLTProcessor();
xsltProcessor.importStylesheet(transform);
var transformed = xsltProcessor.transformToFragment(xmlScrapeResult, document);
if (transformed != null) {
return transformed;
}
else {
throw 'xsltProcessor.transformToFragment() unexpectedly returned null';
}
}
var xslt = '<?xml version="1.0"?>\
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">\
<xsl:preserve-space elements="*" />\
<xsl:template match="/MyRoot">\
{\n\
"escapedDoubleQuotesAndNewlines": "<xsl:call-template name="escapeStringForJson"><xsl:with-param name="text" select="MyElement"/></xsl:call-template>"\n\
}\
</xsl:template>\
<xsl:template name="escapeStringForJson">\
<xsl:param name="text"/>\
<xsl:if test="$text != \'\'">\
<xsl:variable name="head" select="substring($text, 1, 1)"/>\
<xsl:variable name="tail" select="substring($text, 2)"/>\
<xsl:variable name="apos">\'</xsl:variable>\
<xsl:variable name="quot">"</xsl:variable>\
<xsl:variable name="nl"><xsl:text> </xsl:text></xsl:variable>\
<xsl:variable name="cr"><xsl:text> </xsl:text></xsl:variable>\
<xsl:variable name="sl">\</xsl:variable>\
<xsl:choose>\
<!--<xsl:when test="$head = $apos">\\\'</xsl:when>-->\
<xsl:when test="$head = $quot">\\"</xsl:when>\
<xsl:when test="$head = $nl">\\n</xsl:when>\
<xsl:when test="$head = $cr">\\r</xsl:when>\
<xsl:when test="$head = $sl">\\\\</xsl:when>\
<xsl:otherwise><xsl:value-of select="$head"/></xsl:otherwise>\
</xsl:choose>\
<xsl:call-template name="escapeStringForJson">\
<xsl:with-param name="text" select="$tail"/>\
</xsl:call-template>\
</xsl:if>\
</xsl:template>\
</xsl:stylesheet>';
var works1 = '<?xml version="1.0"?>\
<MyRoot>\
<MyElement>This is "test 1" illustrating escapeStringForJson purpose.</MyElement>\
</MyRoot>';
var works2 = '<?xml version="1.0"?>\
<MyRoot>\
<MyElement>' +
'0123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 12345 100' +
' 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 12345 200' +
' 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 12345 300' +
' 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 12345 400' +
' 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 12345 500' +
' 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 12345 600' +
' 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 12345 700' +
' 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 12345 800' +
' 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 12345 900' +
' 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 1234 1000' +
' 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 1234 1100' +
' 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 1234 1200' +
' 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 1234 1300' +
' 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 1234 1400' +
' 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 1234 1500' +
' 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 1234 1600' +
' 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 1234 1700' +
' 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 1234 1800' +
' 123456789 123456789 123456789 123456789 123456789 123456789 12345678 1874' +
'</MyElement>\
</MyRoot>';
var nowork = '<?xml version="1.0"?>\
<MyRoot>\
<MyElement>' +
'0123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 12345 100' +
' 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 12345 200' +
' 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 12345 300' +
' 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 12345 400' +
' 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 12345 500' +
' 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 12345 600' +
' 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 12345 700' +
' 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 12345 800' +
' 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 12345 900' +
' 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 1234 1000' +
' 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 1234 1100' +
' 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 1234 1200' +
' 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 1234 1300' +
' 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 1234 1400' +
' 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 1234 1500' +
' 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 1234 1600' +
' 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 1234 1700' +
' 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 1234 1800' +
' 123456789 123456789 123456789 123456789 123456789 123456789 123456789 1875' +
'</MyElement>\
</MyRoot>';
console.log(new XMLSerializer().serializeToString(transformXml(works1, xslt)));
console.log(new XMLSerializer().serializeToString(transformXml(works2, xslt))); // these two length-related test-cases do not have any characters that need escaping
console.log(new XMLSerializer().serializeToString(transformXml(nowork, xslt))); // these two length-related test-cases do not have any characters that need escaping
(See your developer console output)