【问题标题】:What is an empty element?什么是空元素?
【发布时间】:2011-01-17 18:44:23
【问题描述】:

根据 XML 规范,这是一个空元素的定义:

一个没有内容的元素被称为是空的。] 一个空元素的表示要么是一个开始标签紧跟一个结束标签,要么是一个空元素标签。

(见:http://www.w3.org/TR/REC-xml/#NT-content

现在,我对空元素标签的理解没有问题:<i-am-empty/>,也不会产生误解。但在我看来,该标准在另一种情况下自相矛盾:一方面它说任何没有content 的标签都是空的,另一方面它说这可以用一个开始标签来表示,然后紧跟一个结束标签。但是如果我们看content的定义:

[43] content ::= CharData? ((element | Reference | CDSect | PI | Comment) CharData?)*

在我看来content 由两个可选部分组成,CharData? 和一个组()*。但是由于这两个部分都是可选的,这意味着没有任何东西(例如,没有字符)与这个产生相匹配。因此,如果我尝试将此内容定义与<am-i-empty-or-not></am-i-empty-or-not> 中的任何内容相匹配,我会得到一个肯定的匹配。所以,一方面这是一个空标签,因为它是“一个开始标签紧跟一个结束标签”,另一方面它不是空的,因为在标签之间我可以肯定地匹配生产规则的定义[ 43] 对于内容,在这种情况下它包含内容,这意味着它不能为空。

谁能解释一下哪些规则优先?有人知道对此有不同看法的任何 DOM 或解析器实现吗?

【问题讨论】:

    标签: xml dom


    【解决方案1】:

    我想检查 "empty" 的哪些不同变体实际上是空的。

    变体 A

    <Santa/>

    给出一棵树

    |- NODE_DOCUMENT #document ""
       |- NODE_ELEMENT Santa ""
    

    变体 B

    <Santa></Santa>

    给出一个 DOM 树:

    |- NODE_DOCUMENT #document ""
       |- NODE_ELEMENT Santa ""
    

    变体 C

    <Santa>空格</Santa>

    给出一个 DOM 树:

    |- NODE_DOCUMENT #document ""
       |- NODE_ELEMENT Santa ""
    

    变体 D

    <Santa>标签</Santa>

    给出一个 DOM 树:

    |- NODE_DOCUMENT #document ""
       |- NODE_ELEMENT Santa ""
    

    变体 E

    <Santa>CRLF
    </Santa>

    给出一个 DOM 树:

    |- NODE_DOCUMENT #document ""
       |- NODE_ELEMENT Santa ""
    

    文本的所有变体都给出相同的 DOM 树。当一个 XML 文档被要求序列化自己时,DOM 树:

    |- NODE_DOCUMENT #document ""
       |- NODE_ELEMENT Santa ""
    

    序列化文本的结果:

    <?xml version="1.0"?>
    <Santa/>
    

    手动添加空文本节点

    我想看看如果我构建 DOM 树会发生什么:

    |- NODE_DOCUMENT #document ""
       |- NODE_ELEMENT Santa ""
          |- NODE_TEXT #text ""
    

    使用伪代码:

    XmlDocument doc = new XmlDocument();
    XmlElement santa = doc.appendChild(doc.CreateElement("Santa"));
    santa.appendChild(doc.CreateText(""));
    

    当该 DOM 文档保存到流中时,它会显示为:

    <?xml version="1.0"?>
    <Santa/>
    

    即使元素被强制有一个子元素(即强制不为空),DOM 也会将其设为空。

    强制文本节点带有空格

    然后,如果我确保在 TEXT 节点中添加一些空格:

    XmlDocument doc = new XmlDocument();
    XmlElement santa = doc.appendChild(doc.CreateElement("Santa"));
    santa.appendChild(doc.CreateText(" "));
    

    它以 XML 形式出现:

    <?xml version="1.0" ?>
    <Santa> </Santa>
    

    使用 DOM 树:

    |- NODE_DOCUMENT #document ""
       |- NODE_ELEMENT Santa ""
          |- NODE_TEXT #text " "
    

    有趣;它不能往返。

    强制使用 TAB CRLF

    XmlDocument doc = new XmlDocument();
    XmlElement santa = doc.appendChild(doc.CreateElement("Santa"));
    santa.appendChild(doc.CreateText(TAB+LF+CR));
    

    它以 XML 形式出现:

    TABLF CR 圣诞老人>

    使用 DOM 树:

    |- NODE_DOCUMENT #document ""
       |- NODE_ELEMENT Santa ""
          |- NODE_TEXT #text "\t\n\n"
    

    是的,XML 将所有 CR 转换为 LF,是的,它不是可往返的。如果你解析:

    TABLF CR 圣诞老人>

    你会得到以下的 DOM 树:

    |- NODE_DOCUMENT #document ""
       |- NODE_ELEMENT Santa ""
    

    设置元素.text

    最后我们来看看如果你通过它的.text 属性设置一个元素的文本会发生什么。

    不设置文字

    XmlDocument doc = new XmlDocument();
    XmlElement santa = doc.appendChild(doc.CreateElement("Santa"));
    //santa.text = ""; example where we don't set the text
    

    给出 DOM 树:

    |- NODE_DOCUMENT #document ""
       |- NODE_ELEMENT Santa ""
    

    和 XML:

    <?xml version="1.0"?>
    <Santa/>
    

    设置空文本

    XmlDocument doc = new XmlDocument();
    XmlElement santa = doc.appendChild(doc.CreateElement("Santa"));
    santa.text = ""; //example where we do set the text
    

    给出 DOM 树:

    |- NODE_DOCUMENT #document ""
       |- NODE_ELEMENT Santa ""
          |- NODE_TEXT #text ""
    

    和 XML:

    <?xml version="1.0"?>
    <Santa/>
    

    设置单个空格

    XmlDocument doc = new XmlDocument();
    XmlElement santa = doc.appendChild(doc.CreateElement("Santa"));
    santa.text = " ";
    

    给出 DOM 树:

    |- NODE_DOCUMENT #document ""
       |- NODE_ELEMENT Santa ""
          |- NODE_TEXT #text " "
    

    和 XML:

    <?xml version="1.0"?>
    <Santa> </Santa>
    

    设置更多的空白

    XmlDocument doc = new XmlDocument();
    XmlElement santa = doc.appendChild(doc.CreateElement("Santa"));
    santa.text = LF+TAB+CR;
    

    给出 DOM 树:

    |- NODE_DOCUMENT #document ""
       |- NODE_ELEMENT Santa ""
          |- NODE_TEXT #text "\n\t\n"
    

    和 XML:

    LF TABLF 圣诞老人>

    所以从某种角度来看,他们告诉你的是真的。

    • 元素中仅包含空格的 xml 字符串在解析时将为空
    • 文本节点中仅包含空格的 DOM 元素在转换为 xml 字符串时将呈现空格

    【讨论】:

    • 感谢您抽出宝贵时间对此进行测试!你用什么 DOM 库来尝试这个?跨 DOM 实现的结果是否稳定?
    • @RolandBouman 我使用 MSXML 6(Microsoft XML 库,版本 6)
    【解决方案2】:

    但是由于这两个部分都是可选的,这意味着没有任何东西(如缺少字符)与这个产生式匹配。

    这可能是真的,但规范中关于这个问题的措辞非常明确。下一段中甚至还有空元素的示例。

    <IMG align="left"
     src="http://www.w3.org/Icons/WWW/w3c_home" />
    <br></br>
    <br/>
    

    所以阅读的唯一方法(在这种情况下,加上周围的措辞和例子)

    没有内容的元素

    将包括“(在匹配生产时)完全为空的内容”(即长度为零,甚至没有空格)。

    【讨论】:

    • 好吧,我想这个例子确实有所作为,但我不同意阅读“没有内容的元素”的唯一方法就是你所描述的。我的意思是,在规范中,这种“内容”超链接的出现指向生产规则 43。我开始相信生产规则 43 是不可靠的,应该被定义为始终匹配至少一个字符或元素。
    • 好的 - 考虑到这个答案,因为示例显示了它。谢谢!
    【解决方案3】:
    <element />
    

    <element></element>
    

    都是空元素。任何来自标准的产品都必须解释为具有此结果。

    【讨论】:

    • 我很高兴相信这一点,但是您如何解释我从规范中引用的文字。换句话说,为什么规则优先所以这是结果?
    • @Roland:我不解释。也许你看错了,或者误解了。
    • @JohnSaunders 不,他既没有误读也没有误解。该规范自相矛盾,特别是 [43] 与“定义”和示例相矛盾。
    猜你喜欢
    • 1970-01-01
    • 2010-11-10
    • 2011-12-07
    • 2013-03-05
    • 2016-10-17
    • 1970-01-01
    • 1970-01-01
    • 2019-04-23
    • 1970-01-01
    相关资源
    最近更新 更多