1

我的 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);
} 

其中输出是一个 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 中的那个也被编码。

4

3 回答 3

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 输出方法不应转义出现在属性值中的 < 字符。

(来源: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),结果如您所愿

值得注意的是,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>
于 2012-08-24T14:01:02.963 回答
1

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

于 2012-08-24T08:19:47.927 回答
0

我无法重现您的问题。

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

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

对于撒克逊人,我得到了输出:

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

我不明白怎么可能得到你声称你拥有的东西。您的 XSLT 处理器不符合标准,或者您将某些 DOM 解析器报告的输出属性的值与输出属性的词法呈现混淆了。

于 2012-08-24T07:32:03.863 回答