将新行字符替换为
XSL
我有一个 Sharepoint 列表,我想通过 XSL 数据视图将其转换为 JSON。
我有一个 XSL 递归替换函数,用于替换所有特殊字符(转义反斜杠、双引号 " 等),这为我提供了干净的 JSON,可以在用户浏览器中正确解析。
我需要转义/替换的最后一件事是新行字符。新行会导致某些浏览器中解析 JSON 时出错。
这是一些 xsl,它测试 title 的内容是否有换行符,如果有,我们输出一个段落:
<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>
这是一些示例 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”应该是唯一通过测试的项目,但所有三个标题都通过if 语句 和 被输出。
编辑
修改下面的解决方案,我认为如果我想在单个节点的基础上进行搜索和替换,这应该可行?直到明天我才能在 Sharepoint 中测试它。
<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>
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>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
无法重现所声称的问题 - 使用 9 个不同的 XSLT 处理器进行测试,包括所有来自 Microsoft 的处理器。
无论如何:
此转换将文本节点中的任何 NL 字符替换为
br
元素:当应用于以下 XML 文档时(提供的文档带有添加的
cd
使其更有趣):产生了想要的正确结果:
解释:
身份规则/模板副本每个节点“按原样”。
匹配任何文本节点(也称为“repNL”)的覆盖模板执行以下处理:
如果确实包含 NL 字符,则会生成
br
元素,模板会递归调用自身以获取该 NL 字符之后的剩余字符串。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
br
element:when applied on the following XML document (the provided one with an added
cd
to 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
br
element is generated and the template calls itself recursively for the remaining string after this NL character.如果您使用XslCompiledTransform(C#),我相信您在使用以下API来转换XML时会遇到这个问题:
XslCompiledTransform.Transform(XmlReader input, XmlWriter results)
但是,以下 API 运行良好:
XslCompiledTransform.Transform(字符串,字符串);
这是有线的,但我不明白为什么......
If you are using XslCompiledTransform(C#), I believe you will encounter the issue if you use below API to transform the XML:
XslCompiledTransform.Transform(XmlReader input, XmlWriter results)
However, below API works well:
XslCompiledTransform.Transform(string, string);
This is wired, but I don't figure out why...