XSLT字符转义

时间:2012-08-24 05:26:45

标签: c# xslt escaping

我的xml中有以下项目名称要转换

<title>abc \" &gt; &lt; script &gt; alert(1) &lt; /script &gt;</title>

我在我的XSL文件中使用以下内容进行转换:

<xsl:attribute name="itemTitle"><xsl:value-of select="title"/></xsl:attribute>

我正在使用C#的XSLCompiledTransform的Transform函数。我的代码是:

XPathDocument xpTemplate = new XPathDocument("articlesLookupTemplate.xsl");
XslCompiledTransform xsl = new XslCompiledTransform();
XsltArgumentList xslArg = new XsltArgumentList();
xsl.Load(xpTemplate);

using (StringReader reader = new StringReader(xmlData))
{
    xsl.Transform(XmlReader.Create(reader), xslArg, output);
} 

其中output是HtmlTextWriter。 通过XSLT转换后,我希望它保持转义,即输出应该保持

itemTitle="abc&quot; &gt; &lt; script &gt; alert(1) &lt; /script &gt;"

但我得到的是:

itemTitle="abc&quot;><script>alert(1)</script>"

我在我的xsl文件中使用html输出方法,并且没有禁用 - 输出 - 转义。如果我尝试文本输出方法,我得到截断输出。如何确保文本保持原样。

---更新--- 我在www.xmlper.com上尝试了我的xsl和xml

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  version="1.0">
<xsl:output method="html" />
<xsl:template match="/articles">
<table id="TemplateTable">
     <xsl:for-each select="articletemplate">
        <li class="Dialog-ListItem">
           <xsl:attribute name="itemTitle"><xsl:value-of select="title"/></xsl:attribute>
           <xsl:value-of select="title"/>
        </li>
      </xsl:for-each>  
</table>
</xsl:template>
</xsl:stylesheet>

和XML文件:

<articles >
  <articletemplate>  
  <title>abc " &gt; &lt; script &gt; alert(1) &lt; /script &gt;</title>
  </articletemplate>
</articles>

对于xmlattribute中的那个我得到了

itemTitle="abc &quot; > < script > alert(1) < /script >"

对于没有它的那个我得到了

abc " &gt; &lt; script &gt; alert(1) &lt; /script &gt;

我希望xmlattribute中的那个也被编码。

3 个答案:

答案 0 :(得分:2)

首先,让我评论一下你的输出;您正在使用以下内容:

<table id="TemplateTable">
     <xsl:for-each select="articletemplate">
        <li class="Dialog-ListItem">
           <xsl:attribute name="itemTitle"><xsl:value-of select="title"/></xsl:attribute>
           <xsl:value-of select="title"/>
        </li>
      </xsl:for-each>  
</table>

作为li的孩子会产生table - 这不是很好的HTML(当我在w3c.org上试用它时肯定不会验证)。 <li>应该是<ul><ol>

的孩子

除此之外,这实际上是一个非常有趣的问题。我认为其原因是由于对规范的不同意见:

  

html输出方法不应该转义&lt;字符发生在   属性值。

(资料来源:http://www.xm.co.nz/ShoXS/xsloutput.htm

以下是我的想法:

解析器中的xsl:value-of会看到abc \&quot; &amp;gt; &amp;lt; script &amp;gt; alert(1) &amp;lt; /script &amp;gt;,它会立即转换为abc \&quot; > < script > alert(1) < /script >。然后,根据上面的规则,这应该逐字地放入属性值(这也是我所观察到的)。

这几乎可以肯定是由于html输出声明。如果我将输出更改为XML,则将值逐字放入属性中。

所以你有两个选择:

  1. 直接转换为XML(通过将输出更改为xml)并尝试将其写入客户端。它可能是XML,但如果您将其作为HTML发送(通过省略XML声明并使用HTTP的正确内容类型),则应按预期编写。

  2. 将文本放置为CDATA:<![CDATA[abc " &gt; &lt; script &gt; alert(1) &lt; /script &gt;]]> - 这似乎强制.Net Xml解析器不将文本视为HTML(因此在输出方法输出时,它不会在输出之前被翻译html),结果如你所愿

  3. 值得注意的是disable-output-escaping在这里没有效果。这几乎可以肯定是由于输出方法为html

    时对规范的解释

    使用XmlDocument,XSLTransform,.Net 3.5进行测试

    这是我写的XSLT:

    <?xml version="1.0" encoding="utf-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                    version="1.0">
      <xsl:output method="html" />
      <xsl:template match="/">
        <html>
          <head></head>
          <body>
            <ul>
              <xsl:apply-templates select="/articles/articletemplate" />
            </ul>
          </body>
        </html>
      </xsl:template>
    
    
      <xsl:template match="articletemplate">
        <li class="Dialog-ListItem" itemTitle="{title}">
          <xsl:value-of select="title"/>
        </li>
      </xsl:template>  
    </xsl:stylesheet>
    

    我使用的示例XML(注意CDATA与非CDATA):

    <?xml version="1.0" encoding="utf-8" ?>
    <articles>
      <articletemplate>
        <title><![CDATA[abc \" &gt; &lt; script &gt; alert(1) &lt; /script &gt;]]></title>
      </articletemplate>
      <articletemplate>
        <title>abc " &gt; &lt; script &gt; alert(1) &lt; /script &gt;</title>
      </articletemplate>
      <articletemplate>
        <title>test</title>
      </articletemplate>
    </articles>
    

    输出:

    <html>
      <head>
        <META http-equiv="Content-Type" content="text/html; charset=utf-8">
      </head>
      <body>
        <ul>
          <li class="Dialog-ListItem" itemTitle="abc \&quot; &amp;gt; &amp;lt; script &amp;gt; alert(1) &amp;lt; /script &amp;gt;">abc \" &amp;gt; &amp;lt; script &amp;gt; alert(1) &amp;lt; /script &amp;gt;</li>
          <li class="Dialog-ListItem" itemTitle="abc &quot; > < script > alert(1) < /script >">abc " &gt; &lt; script &gt; alert(1) &lt; /script &gt;</li>
          <li class="Dialog-ListItem" itemTitle="test">test</li>
        </ul>
      </body>
    </html>
    

答案 1 :(得分:1)

没有办法保留属性值的原始形式,因为XSLT处理器不知道原始形式是什么;属性值中的实体引用由XML解析器扩展,并以“扩展”形式传递给XSLT处理器(即,&lt;被转换为<,依此类推)。 xsl:value-of的最终结果取决于HTML序列化方法,该方法可以在属性值中以&quot;&#34;或其他各种等效方式自由输出“”。没有仔细调查是否输出'&lt;'和'&gt;'在HTML中未转义的形式是合法与否 - 我的第一个问题是它不合法,这是你的处理器中的一个错误。

答案 2 :(得分:0)

我无法重现你的问题。

在www.xmlper.com上,我得到了输出:

<t itemTitle="abc \&quot; &gt; &lt; script &gt; alert(1) &lt; /script &gt;" />

有了Saxon,我得到了输出:

<t itemTitle="abc \&#34; &gt; &lt; script &gt; alert(1) &lt; /script &gt;"/>

我不知道怎么可能得到你声称你得到的东西。您的XSLT处理器是不符合要求的,或者您在输出属性的值与某些DOM解析器报告它时混淆了输出属性的词汇呈现。