问题描述
我有这个简单的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>
我希望这是有效的,但是一些在线验证器报告说这是无效的,因为输入和文件元素包含非文本节点。
如果我删除了input元素内的file元素,那么报告的结果XML是有效的,因此我希望“非文本节点”是子元素(输入中的文件以及名称和类型的文件)。 / p>
我希望这是有效的,因为XML specification for an element指定一个元素如果与一组条件之一匹配则是有效的,其中一个条件是:
声明与Mixed匹配,并且内容(在用其替换文本替换所有实体引用之后)由字符数据(包括CDATA部分),注释,PI和子元素组成,其类型与内容模型中的名称匹配。
请注意结尾处的“和子元素...”。
混合生产为:
Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*'
| '(' S? '#PCDATA' S? ')'
第二种情况是我需要输入和文件:(#PCDATA)
混合内容的有效性要求是,可以存在子元素,只要它们的名称与内容模型中的名称匹配即可。
我误解了规范还是这些验证器不正确?
如果我从DTD中删除了文件,名称和类型元素的声明,但是将子元素保留在输入元素的内容中,那么我将收到其他验证错误,表明没有这些类型的声明。我预计会出现这些错误,因为验证要求是子元素名称与内容模型中的名称匹配,并且在删除这些声明后,它们与内容模型中的名称不匹配。
但是,即使在DTD中没有声明文件,名称和类型元素,也有其他验证器报告XML是有效的。这也似乎是验证者的错,因为验证要求明确指出,子元素名称必须与内容模型中的名称匹配,而在删除那些元素声明时,子元素名称必须与内容模型中的名称不匹配。
我知道有各种各样的XML验证实现,它们的工作方式不尽相同,因此不能完全正确。我对完全正确理解该规范很感兴趣。
严格符合内容为(#PCDATA)
的元素的有效性要求:
规范似乎只要求子元素的名称与DTD中元素的名称相匹配,但我认为此类元素的内容和属性也应与DTD中的声明相匹配,但该规范实际上并未说明这个。因此,再次严格遵循规范的有效性要求,具有内容(#PCDATA)
的元素的子元素的内容和属性是否必须与DTD中的声明相匹配?如果是这样,那么它在规范中的何处说明呢?
最后,是否有任何易于使用的(在线或可安装到Linux的)XML验证器根据您所推荐的规范严格正确?
解决方法
您的元素声明,
<!ELEMENT input (#PCDATA)>
从技术上讲是允许混合的内容,但不允许混入任何元素。
您引用的section表示内容混合
可能包含字符数据,并可选地插入子元素。
该部分的产品对此提供了支持。请参见下面的^^^
,如果Name
提供了元素,则可以将元素混入其中:
Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*'
^^^^^^^^^^^^^^^^^
| '(' S? '#PCDATA' S? ')'
但是,您的声明实际上并不允许元素。如果您希望允许混入file
之类的元素,请这样声明input
:
<!ELEMENT input (#PCDATA|file)*>
更新以处理后续评论
在解析的字符数据中出现的任何&
和<
字符都将被解析:即,被解释为标记。格式正确的规则适用,并且在验证期间,解析后的标记必须遵循架构给出的语法规则。内容模型中仅包含#PCDATA
的元素不会隐式允许内容模型中未提及的散布元素。
通俗地说,混合内容通常表示存在散布的元素;从技术上讲,混合内容可能具有零个或多个元素 1 。无论哪种方式,如果元素都散布有解析数据但未在内容模型中指定,则该文档无效。
1 再次注意,规范指出可选地穿插。这是完整的定义: