【问题标题】:XML validation of #PCDATA#PCDATA 的 XML 验证
【发布时间】:2021-01-30 13:22:45
【问题描述】:

我有这个简单的 XML:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE input[
<!ELEMENT input (#PCDATA)>
<!ELEMENT file (#PCDATA)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT type (#PCDATA)>
]>
<input>
This is the content <file><name>test.png</name><type>Image</type></file>
</input>

我希望这是有效的,但一些在线验证器报告它是无效的,因为输入和文件元素包含非文本节点。

如果我删除输入元素中的文件元素,则报告生成的 XML 是有效的,所以我希望“非文本节点”是子元素(输入中的文件和文件中的名称和类型)。

我希望这是有效的,因为XML specification for an element 指定一个元素如果匹配一组条件之一是有效的,其中一个条件是:

声明与 Mixed 匹配,并且内容(在将任何实体引用替换为其替换文本之后)由字符数据(包括 CDATA 部分)、cmets、PI 和其类型与内容模型中的名称匹配的子元素组成。

注意最后的“和子元素...”。

混合的产生是:

    Mixed      ::=      '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*'  
            | '(' S? '#PCDATA' S? ')' 

第二种情况是我的输入和文件:(#PCDATA)

混合内容的有效性要求是可以存在子元素,只要它们的名称与内容模型中的名称匹配即可。

我误解了规范还是这些验证器不正确?

如果我从 DTD 中删除了文件、名称和类型元素的声明,但将子元素保留在输入元素的内容中,那么我会收到额外的验证错误,表明没有声明这些类型。我预计会出现这些错误,因为验证要求是子元素名称与内容模型中的名称匹配,并且在删除这些声明后,它们与内容模型中的名称不匹配。

但是,即使没有在 DTD 中声明文件、名称和类型元素,也有其他验证器报告 XML 是有效的。这似乎也是验证器的错误,因为验证要求清楚地表明子元素名称必须与内容模型中的名称匹配,而当这些元素声明被删除时,它们不会匹配。

我知道有多种 XML 验证实现,它们的工作方式不尽相同,因此它们不可能都严格正确。我最感兴趣的是对规范有一个严格正确的理解。

严格遵守内容(#PCDATA)的元素的有效性要求:

  1. 该元素的内容可以包含子元素吗?
  2. 如果是,这些元素的名称必须与 DTD 中的元素名称匹配吗?

规范似乎只要求子元素的名称与 DTD 中元素的名称相匹配,但我认为这些元素的内容和属性也应该与 DTD 中的声明相匹配,但规范实际上并没有说这。因此,再次严格遵守规范的有效性要求,内容为(#PCDATA) 的元素的子元素的内容和属性是否必须与DTD 中的这些声明相匹配?如果是这样,规范中的什么地方是这样说的?

最后,是否有任何易于使用(在线或可安装到 Linux)的 XML 验证器,根据您可以推荐的规范严格正确?

【问题讨论】:

    标签: xml validation dtd pcdata


    【解决方案1】:

    你的元素声明,

    <!ELEMENT input (#PCDATA)>
    

    技术上允许混合内容,但不允许混合任何元素。

    您引用的section 表示混合内容 可能包含字符数据,可选地穿插子元素。 该部分的生产支持这一点。请参阅下面的^^^,如果Name 提供,则允许混合元素:

    Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*'  
                               ^^^^^^^^^^^^^^^^^       
            | '(' S? '#PCDATA' S? ')' 
    

    但是,您的声明实际上不允许元素。如果您希望允许混入诸如file 之类的元素,请改为声明input,如下所示:

    <!ELEMENT input (#PCDATA|file)*>
    

    更新以解决后续 cmets

    任何出现在已解析字符数据中的&amp;&lt; 字符都将被解析:即解释为标记。格式良好的规则适用,并且在验证期间,解析的标记必须遵循模式给出的语法规则。在其内容模型中仅包含 #PCDATA 的元素不会隐式允许散布在内容模型中未提及的元素。

    通俗地说,混合内容通常意味着存在散布的元素;从技术上讲,混合内容可能有零个或多个元素1。无论哪种方式,如果元素散布有已解析的数据但未在内容模型中指定,则文档无效。


    1 同样,请注意规范说可选地穿插。这是完整的定义:

    3.2.2 Mixed Content

    [定义:当元素type具有混合内容 该类型的可能包含字符数据,可选地穿插 child元素。]

    【讨论】:

    • 我想这可能是答案。另一方面,我的声明就像是混合内容声明的显式示例之一,如果它不允许带有散布元素的字符 - 混合内容的定义,它就不是混合内容。我发现规范很模棱两可。 #PCDATA 本身是否有任何生产?
    • 另外,来自第 2.2 节:[定义:解析的实体包含文本,一个字符序列,可以表示标记或字符数据。]。而且我假设#PCDATA 内容是一个已解析的实体,但也许我错了,但如果是,那么它可以包含标记,即元素。
    • 第 1 部分似乎更加清晰:XML 文档由称为实体的存储单元组成,其中包含已解析或未解析的数据。解析的数据由字符组成,其中一些构成字符数据,而另一些构成标记。 #PCDATA 不对应解析数据由字符组成的情况吗?
    • 感谢您的更新。与此同时,我一直在查看Extensible Markup Language (XML) Conformance Test Suites 中的测试。还没有看到像我的例子,但还没有审查所有。我所看到的一切都与您的解释一致,因此,虽然规范对我来说仍然模棱两可,但我怀疑您所说的是通常的解释。
    猜你喜欢
    • 1970-01-01
    • 2017-06-02
    • 2013-12-26
    • 2016-02-13
    • 2021-02-12
    • 2011-10-12
    • 1970-01-01
    • 1970-01-01
    • 2011-03-23
    相关资源
    最近更新 更多