用XSL替换新行char

时间:2011-05-15 16:12:56

标签: sharepoint xslt dataview

我有一个Sharepoint列表,我想通过XSL数据视图转换为JSON。

我有一个XSL递归替换函数,我用它来替换所有特殊字符(转义反斜杠,双引号到& quot;等),这给了我很好的干净JSON,它在用户浏览器中正确解析。

我需要逃脱/替换的最后一件事是新行char。新行在某些浏览器中导致解析JSON时出错。

这里有一些xsl测试title的内容是否有新的行char,如果是,我们输出一个段落:

<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,"&#xA;")'>   
                <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,'&#xA;'),'&#xA;')"/>

  <xsl:if test="contains($pText, '&#xA;')">
  <br />
  <xsl:call-template name="repNL">
  <xsl:with-param name="pText" select=
  "substring-after($pText, '&#xA;')"/>
  </xsl:call-template>
  </xsl:if>
</xsl:template>

</xsl:stylesheet>

2 个答案:

答案 0 :(得分:2)

  

“Empire Burlesque”应该是唯一的   项目通过测试,但所有三个   标题通过if语句并且是   输出。

无法重现所谓的问题 - 使用9种不同的XSLT处理器进行测试,包括所有来自Microsoft的处理器。

反正:

此转换使用br元素替换文本节点中的任何NL字符

<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="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="text()" name="repNL">
  <xsl:param name="pText" select="."/>

  <xsl:copy-of select=
  "substring-before(concat($pText,'&#xA;'),'&#xA;')"/>

  <xsl:if test="contains($pText, '&#xA;')">
   <br />
   <xsl:call-template name="repNL">
    <xsl:with-param name="pText" select=
    "substring-after($pText, '&#xA;')"/>
   </xsl:call-template>
  </xsl:if>
 </xsl:template>
</xsl:stylesheet>

应用于以下XML文档(提供的文档添加了cd以使其更有趣):

<catalog>
    <cd>
        <title>Line1
        Line2
        Line3
        </title>
        <artist>Bob Dylan</artist>
        <country>USA</country>
        <company>Columbia</company>
        <price>10.90</price>
        <year>1985</year>
    </cd>
    <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>

产生了想要的正确结果

<catalog>
   <cd>
      <title>Line1<br/>     Line2<br/>      Line3<br/>      
      </title>
      <artist>Bob Dylan</artist>
      <country>USA</country>
      <company>Columbia</company>
      <price>10.90</price>
      <year>1985</year>
   </cd>
   <cd>
      <title>Empire<br/>        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>

<强>解释

  1. 身份规则/模板“按原样”复制每个节点。

  2. 匹配任何文本节点(也称为“repNL”)的覆盖模板执行以下处理:

  3. 使用sentinel(附加到字符串的NL字符),第一个NL字符之前的子字符串(如果不包含NL字符,则为完整字符串)将被复制到输出中。

  4. 如果确实包含了NL字符,则会生成br元素,并且该模板会在此NL字符后为剩余字符串递归调用自身。

答案 1 :(得分:0)

如果您使用的是XslCompiledTransform(C#),我相信如果您使用以下API转换XML,您将遇到此问题:
XslCompiledTransform.Transform(XmlReader input, XmlWriter results)

但是,以下API效果很好:
XslCompiledTransform.Transform(string, string);
这是有线的,但我不明白为什么......