XSLT 特殊字符

8
在以下的XSL转换中,如何输出'<'和'>'符号?
输入XML:
<TestResult bugnumber="3214" testname="display.methods::close->test_ManyInvoke" errortype="Failure"><ErrorMessage><![CDATA[calling close() method failed - expected:<2>]]></ErrorMessage>

XSLT:

<xsl:template match="TestResult">
  <xsl:variable name="errorMessage">
   <xsl:value-of select="ErrorMessage" disable-output-escaping="yes"/>
  </xsl:variable>
  <Test name='{@testname}'>
   <TestResult>
    <Passed>false</Passed>
    <State>failure</State>
    <Metadata>
     <Entry name='bugnumber' value='{@bugnumber}' />
    </Metadata>
    <TestOutput>
     <Metadata>
      <Entry name='ErrorMessage' value='{$errorMessage}' />
     </Metadata>
    </TestOutput>
   </TestResult>
  </Test>
 </xsl:template>

输出的XML:

<Test name="display.methods::close-&gttest_ManyInvoke"> 
 <TestResult>
  <Passed>false</Passed>
  <State>failure</State>
  <Metadata>
   <Entry name="bugnumber" value="3214"/>
  </Metadata>
  <TestOutput>
   <Metadata>
    <Entry name="ErrorMessage" value="calling close() method failed - expected:&lt;2&gt;"/>
   </Metadata>
  </TestOutput>
 </TestResult>
</Test>

好问题(+1)。请查看我的答案,其中包含完整的解决方案。 - Dimitre Novatchev
5个回答

10

简短回答: 你不能。

详细回答: 属性值中不能包含一些特殊字符,例如'<''>''&'

如果存在这些字符,它们将被转义为:'&lt;''&gt;''&amp;'

这些字符可能会在输出方法为“文本”时产生,但这不是你的情况。

如果在浏览器中显示这些字符,则可以使用:'&lt;''&gt;''&amp;'

最后,您可以使用CDATA部分作为文本节点的一部分来生成这些字符。以下示例说明了这一点:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
 <xsl:output cdata-section-elements="t"
  omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/">
  <t> &lt; &amp; &gt;</t>
 </xsl:template>
</xsl:stylesheet>

当这种转换应用于任何XML文档(未使用),结果如下:
<t><![CDATA[ < & >]]></t>

4

这是一个非常老的问题,其他评论者可能会质疑为什么你需要这样做,但如果你只想知道如何在输出中添加<或>,那么下面就是您所需的方法。

<xsl:value-of disable-output-escaping="yes" select="string('&lt;')"/>

更多信息请参见MSDN网站


哇,我找了好久终于找到了! - undefined

2
如果在您的属性中出现&gt;是一个问题,那么问题出现在如何消费XML上,而不是如何生成XML。任何XML解析器在用于检索属性值时都会取消转义字符实体。如果您在XML文档的消费中使用XML解析器,则永远不会看到这个问题;解析器将告诉您属性的值是display.methods::close->test_ManyInvoke
我认为这个“问题”只有两种情况下才会出现:
1.不懂XML如何工作的人正在查看输出并说:“嘿,它不应该这样做。”
2.不懂XML如何工作的人编写了自己的逻辑来解析XML。(“为什么我要使用别人的XML解析器,当我可以编写简单的正则表达式?”好吧,这就是其中一个原因。)
总的来说,如果您发现自己在XSLT中使用disable-output-escaping='yes'或创建CDATA部分,那么您可能在做错事情。虽然不是一定的 - 两者都有适当的用途 - 但根据我的经验,绝大多数情况下,如果答案是“使用CDATA”,那么您正在问错问题。

0

如果你试图在字符串文字中转义除和号以外的任何内容,请小心。例如,

test="$some_variable = 'Wendy&apos;s'"

不会起作用。您必须先转义转义字符串中的第一个“&”符号,因此您需要使用

test="$some_variable = 'Wendy&amp;apos;s'

0

如果有人需要括号的输出,就不应该有任何疑问。我使用 XSLT 生成纯文本,非常确定需要输出什么,但 XslCompiledTransform 类 却出于某种原因对其进行了编码。

作为 GMK 回答的更简短的替代方案,我想到了以下方法:

<xsl:text disable-output-escaping="yes">&lt; ... &gt;</xsl:text>

查看MSDN网站

上下文示例:

<xsl:template match="data">
        /// <xsl:text disable-output-escaping="yes">&lt;summary&gt;</xsl:text>
        ///     <xsl:value-of select="value"/>
        /// <xsl:text disable-output-escaping="yes">&lt;/summary&gt;</xsl:text>
        public static <xsl:text disable-output-escaping="yes">Func&lt;string&gt; </xsl:text><xsl:value-of select="@name"/>
        <xsl:text disable-output-escaping="yes"> =&gt; () =&gt;</xsl:text> I18n.<xsl:value-of select="@name"/>;
</xsl:template>

这部分为C#资源文件生成类似于此的内容。

        /// <summary>
        ///     Abbrechen
        /// </summary>
        public static Func<string> Abort => () => I18n.Abort;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接