是否可以在XML属性中包含HTML文本或CDATA?

时间:2009-08-17 18:13:48

标签: html xml

当我尝试将HTML文本或CDATA放入XML属性中时,我的解析器继续“XML解析器失败:未终止的属性”。有没有办法做到这一点,还是标准不允许这样做?

6 个答案:

答案 0 :(得分:22)

不,CDATA不能是属性的值。它只能在元素内部。

答案 1 :(得分:13)

属性内部只能包含纯文本,没有标签,注释或其他结构化数据。您需要使用字符实体来转义任何特殊字符。例如:

<code text="&lt;a href=&quot;/&quot;&gt;">

这会为text属性赋予值<a href="/">。请注意,这只是纯文本,因此如果您想将其视为HTML,则必须自己通过HTML解析器运行该字符串。 XML DOM不会为您解析text属性。

答案 2 :(得分:9)

如果属性不是标记化或枚举类型,则将其作为CDATA处理。有关如何处理属性的详细信息,请参阅Extensible Markup Language (XML) 1.0 (Fifth Edition)

  

3.3.1 Attribute Types

     

XML属性类型有三种:字符串类型,一组标记化类型和枚举类型。字符串类型可以将任何文字字符串作为值;标记化类型更受约束。语法中记录的有效性约束在属性值已经规范化之后应用,如3.3.3属性值规范化中所述。

[54]  AttType       ::=    StringType | TokenizedType | EnumeratedType
[55]  StringType    ::=    'CDATA'
[56]  TokenizedType ::=    'ID' [VC: ID]
            [VC: One ID per Element Type]
            [VC: ID Attribute Default]
        | 'IDREF'      [VC: IDREF]
        | 'IDREFS'     [VC: IDREF]
        | 'ENTITY'     [VC: Entity Name]
        | 'ENTITIES'   [VC: Entity Name]
        | 'NMTOKEN'    [VC: Name Token]
        | 'NMTOKENS'   [VC: Name Token]

...

  

3.3.3 Attribute-Value Normalization

     

在将属性的值传递给应用程序或检查其有效性之前,XML处理器必须通过应用下面的算法或通过使用其他方法使传递给应用程序的值相同来规范化属性值。正如算法产生的那样。

     
      
  1. 所有换行必须按照2.11 End-of-Line Handling中的描述对#xA的输入进行标准化,因此该算法的其余部分对以这种方式标准化的文本进行操作。
  2.   
  3. 以包含空字符串的标准化值开头。
  4.   
  5. 对于非标准化属性值中的每个字符,实体引用或字符引用,从第一个开始并继续到最后一个,执行以下操作:      
        
    • 对于字符引用,将引用的字符附加到规范化值。
    •   
    • 对于实体引用,递归地将此算法的第3步应用于实体的替换文本。
    •   
    • 对于空格字符(#x20,#xD,#xA,#x9),请在标准化值后附加空格字符(#x20)。
    •   
    • 对于另一个角色,将角色附加到标准化值。
    •   
  6.         

    如果属性类型不是CDATA,则XML处理器必须通过丢弃任何前导和尾随空格(#x20)字符,并通过用单个空格替换空格(#x20)字符序列来进一步处理规范化的属性值(#x20)角色。

         

    请注意,如果非标准化属性值包含对空格以外的空格字符的字符引用(#x20),则标准化值包含引用的字符本身(#xD,#xA或#x9)。这与非标准化值包含空白字符(不是引用)的情况形成对比,后者在标准化值中用空格字符(#x20)替换,并且与非标准化值包含实体引用的情况形成对比。替换文本包含空格字符;在递归处理时,空格字符被标准化值中的空格字符(#x20)替换。

         

    未读取任何声明的所有属性应由非验证处理器处理,就像声明 CDATA 一样。

         

    如果attribute value包含reference到未读取声明的实体,则会出错。

答案 3 :(得分:5)

不幸的是,{p> CDATA在这里说的含糊不清。有"CDATA Sections""CDATA Attribute Type"

您的属性值 可以 属于CDATA类型,并带有“CDATA属性类型”。

这是一个包含“CDATA Section”aka. CDSect)的xml:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<elemke>
<![CDATA[
foo
]]>
</elemke>

这是一个包含“CDATA属性类型”(作为AttType)的xml:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE elemke [
<!ATTLIST brush wood CDATA #REQUIRED>
]>

<elemke>
<brush wood="guy&#xA;threep"/>
</elemke>

无法 使用“CDATA部分”作为属性值:错误: <brush wood=<![CDATA[foo]]>/>

可以 使用“CDATA属性类型”作为属性的类型,我认为这实际上是通常情况下发生的情况,您的属性值 实际上是CDATA:对于像<brush wood="guy&#xA;threep"/>这样的元素,在原始二进制字节字符串.xml文件中,您有guy&#xA;threep但是在处理文件时,内存中的属性值将

guy
threep

您的问题可能在于:1)生成正确的xml文件; 2)配置“xml处理器”以生成所需的输出。

例如,如果您手动将原始二进制文件写为xml ,则需要将这些转义放在原始文件的属性值部分中,就像我写的{{1}一样在这里,而不是 <brush wood="guy&#xA;threep"/>(换行符)<brush wood="guy

然后解析实际上会给你一个换行符,我用处理器试过了。

您可以使用像saxon这样的处理器或像浏览器这样的穷人实验来尝试它,在firefox 中打开xml并将复制到文本编辑器 - firefox 显示< / em>换行符作为空格,但将字符串复制到文本编辑器显示换行符。 (可能使用更合适的处理器,您可以立即保存直接输出。)

现在你需要做的“唯一”事情是确保你适当地处理这个C​​DATA。例如,如果你有一个XSL样式表,那就会产生一个html,你可以使用像这样的threep"/>这样的xml:

.xsl

使用<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template name="split"> <xsl:param name="list" select="''" /> <xsl:param name="separator" select="'&#xA;'" /> <xsl:if test="not($list = '' or $separator = '')"> <xsl:variable name="head" select="substring-before(concat($list, $separator), $separator)" /> <xsl:variable name="tail" select="substring-after($list, $separator)" /> <xsl:value-of select="$head"/> <br/><xsl:text>&#xA;</xsl:text> <xsl:call-template name="split"> <xsl:with-param name="list" select="$tail" /> <xsl:with-param name="separator" select="$separator" /> </xsl:call-template> </xsl:if> </xsl:template> <xsl:template match="brush"> <html> <xsl:call-template name="split"> <xsl:with-param name="list" select="@wood"/> </xsl:call-template> </html> </xsl:template> </xsl:stylesheet> saxon home edition 9.5在浏览器或saxon等处理器中生成类似html的内容:

java -jar saxon9he.jar -s:eg2.xml -xsl:eg2.xsl -o:eg2.html

在浏览器中显示如下:

<html>guy<br>
   threep<br>

</html>  

由于我的目标处理器既不支持版本from Tomalak也不支持guy threep ,因此我使用递归模板'split'Mads Hansen,感谢string-join仅限2.0。

答案 4 :(得分:2)

是的,您可以在XML标记内对内容进行编码。 即使用&amp; &lt; &gt; &quot; &apos;,这样就不会将其视为标记内的标记。

答案 5 :(得分:2)

我们不能使用CDATA作为属性,但我们可以使用HTML代码绑定html。 这是一个例子:

实现这一目标:<span class="abc"></span>

使用这样的XML代码:

<xmlNode attibuteName="&lt;span class=&quot;abc&quot;&gt;Your Text&lt;&#47;span&gt;"></xmlNode>