I have a Sharepoint list which I want to convert to a JSON via an XSL dataview.
I have an XSL recursive replace function which I use to replace all special characters (escape backslash, double quotes to " etc) which gives me nice clean JSON which parses correctly in the users browser.
The final thing that I need to escape / replace is the new line char. The new line causes errors in parsing the JSON in some browsers.
Here is some xsl which tests if the contents of title has a new line char, if it does we output a paragraph:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:for-each select="catalog/cd">
<xsl:if test='contains(title,"
")'>
<p>Found <xsl:value-of select="title" /></p>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Here is some sample xml:
<catalog>
<cd>
<title>Empire
Burlesque</title>
<artist>Bob Dylan</artist>
<country>USA</country>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
</cd>
<cd>
<title>Hide your heart</title>
<artist>Bonnie Tyler</artist>
<country>UK</country>
<company>CBS Records</company>
<price>9.90</price>
<year>1988</year>
</cd>
<cd>
<title>Greatest Hits</title>
<artist>Dolly Parton</artist>
<country>USA</country>
<company>RCA</company>
<price>9.90</price>
<year>1982</year>
</cd>
</catalog>
“Empire Burlesque” should be the only item to pass the test, but all three titles pass the if statement and are outputted.
EDIT
Modifying the solution below, I assume this should work if I wanted to do the search and replace on a individual node basis? I won’t be able to test it in Sharepoint until tomorrow.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:for-each select="catalog/cd">
<xsl:variable name="title_clean">
<xsl:call-template name="repNL">
<xsl:with-param name="pText" select="title"/>
</xsl:call-template>
</xsl:variable>
<p><xsl:value-of select='$title_clean' /></p>
</xsl:for-each>
</xsl:template>
<xsl:template name="repNL">
<xsl:param name="pText" select="."/>
<xsl:copy-of select="substring-before(concat($pText,'
'),'
')"/>
<xsl:if test="contains($pText, '
')">
<br />
<xsl:call-template name="repNL">
<xsl:with-param name="pText" select=
"substring-after($pText, '
')"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Cannot reproduce the alleged problem — tested with 9 different XSLT processors, including all from Microsoft.
Anyway:
This transformation replaces any NL character in a text node with a
brelement:when applied on the following XML document (the provided one with an added
cdto make it more interesting):the wanted, correct result is produced:
Explanation:
The identity rule/template copies every node “as-is”.
The overriding template that matches any text node (also named as “repNL”) prforms the following processing:
Using a sentinel (a NL character appended to the string), the substring before the first NL character (or the complete string, if th no NL character is contained) is copied to the output.
If a NL character is really contained, then a
brelement is generated and the template calls itself recursively for the remaining string after this NL character.