【问题标题】:Is it possible to have HTML text or CDATA inside an XML attribute?是否可以在 XML 属性中包含 HTML 文本或 CDATA?
【发布时间】:2010-11-20 08:16:20
【问题描述】:

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

【问题讨论】:

  • 您能添加一个源代码示例,向我们展示您的结构是什么样的吗?
  • 示例:
  • @Pradyumna 您在尝试使用 CDATA 部分时感到困惑,而您的属性可能只是 CDATA 属性类型,请参阅my answer。
  • @naxa 我知道,我只是在回复 Jordan Parmer 上面的评论,该评论要求从 OP 获得样本。我猜 OP 正试图做我在我的例子中写的东西。 (这不是答案)顺便说一句,这个问题已经超过 5 年了 :)

标签: html xml


【解决方案1】:

不,表示CDATA 节 的标记不允许作为属性的值。

根据规范,这种禁止是间接的而不是直接的。规范说属性值must not have an open angle bracket。必须对开尖括号和 & 符号进行转义。因此,您不能插入 CDATA 节。呜呜呜。

只有在元素的文本节点中才会解释 CData 节。

【讨论】:

  • 虽然接受的只是引用文档,但您在没有任何来源或支持信息的情况下给出了正确的答案。谁规定 CDATA 只能在元素内部使用而不是属性值?
  • 我更新了答案以引用 XML 规范中说 attr 值不能包含开放尖括号的部分。
【解决方案2】:

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

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

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

【讨论】:

    【解决方案3】:

    如果属性不是标记化或枚举类型,则将其作为 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. 对于非规范化属性值中的每个字符、实体引用或字符引用,从第一个开始到最后一个,执行以下操作:
      • 对于字符引用,将引用的字符附加到规范化值。
      • 对于实体引用,递归地将此算法的第 3 步应用于实体的替换文本。
      • 对于空格字符(#x20、#xD、#xA、#x9),将空格字符 (#x20) 附加到标准化值。
      • 对于另一个字符,将该字符附加到标准化值。

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

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

    所有未读取声明的属性都应该被非验证处理器视为声明为 CDATA。

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

    【讨论】:

    • 我可能有解释困难。 myattr="a&amp;#xA;b" 属性是否会导致标准化值 a b?
    【解决方案4】:

    CDATA 不幸的是,在这里说起来模棱两可。有"CDATA Sections"和"CDATA Attribute Type"。

    您的属性值可以是具有“CDATA 属性类型”的 CDATA 类型。

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

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

    这是一个包含“CDATA Attribute Type”的xml(如AttType):

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

    您不能对属性值使用“CDATA 部分”:错误:&lt;brush wood=&lt;![CDATA[foo]]&gt;/&gt;

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

    guy
    threep
    

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

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

    那么解析实际上会给你一个换行符,我已经用处理器试过了。

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

    现在您需要做的“唯一”事情是确保正确处理此 CDATA。例如,如果你有一个 XSL 样式表,它会生成一个 html,你可以使用类似 .xsl 这样的 xml:

    <?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>
    

    在浏览器或像撒克逊这样的处理器中使用 java -jar saxon9he.jar -s:eg2.xml -xsl:eg2.xsl -o:eg2.html saxon home edition 9.5 会产生类似 html 的东西:

    <html>guy<br>
       threep<br>
    
    </html>  
    

    在浏览器中看起来像这样:

    guy
    threep
    

    这里我使用递归模板'split'from Tomalak,感谢Mads Hansen,因为我的目标处理器既不支持string-join也不支持tokenize,它们仅支持2.0版。

    【讨论】:

    【解决方案5】:

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

    实现这一点:&lt;span class="abc"&gt;&lt;/span&gt;

    像这样使用 XML 代码:

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

    【讨论】:

      【解决方案6】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-03-07
        • 2011-08-26
        • 1970-01-01
        • 2011-09-25
        • 1970-01-01
        • 2021-10-15
        • 1970-01-01
        相关资源
        最近更新 更多