我无法弄清楚如何为XML文件编写DTD,它可以包含混合顺序的相同元素。
显示问题的小例子如下:
<root>
<element>
<one></one>
<two></two>
</element>
<element>
<two></two>
<one></one>
</element>
<element>
<two></two>
<two></two>
<two></two>
<two></two>
<one></one>
<one></one>
</element>
</root>
我的DTD:
<!ELEMENT root(element*)>
<!ELEMENT element((one*,two*)|(two*,one*))>
我找到了similar topic,但解决方案在我的情况下不起作用(我不确定我的DTD目前有什么问题)。 我收到此错误消息:
xmllint: Content model of Instructors is not determinist: ((one* , two*) | (two* , one*))
答案 0 :(得分:9)
<!ELEMENT element (one|two)*>
(如果您必须至少有一个,请+
。)
答案 1 :(得分:4)
您的解决方案不具有确定性,因为
<element>
<two/>
</element>
是与两个分支匹配的案例之一:(one*, two*)
和(two*, one*)
。
就像@Cristopher所说,@ Dave的答案允许混合排序,他的答案修复了这个问题。但实际上克里斯托弗的回答是不确定性,因为在验证输入时
<element>
<two/>
</element>
并且验证器遇到第一个<two>
,它不知道它应该选择哪个分支。在读取所有<two>
元素后,它才会知道此。
为了在保持模型确定性的同时保持订单一致,请使用
<!ELEMENT element ( (one+, two*) | (two+, one*) )? >
这里的关键点是:1)通过使用不同的强制元素开始每个分支来保持模型的确定性2)但仍允许空<element/>
最后使用?
,这使得内容模型可选
答案 2 :(得分:0)
给定的DTD不是确定性的,并且xml解析器可能会出错。 (参见Section 3.2.1(规范)和Appendix E(非规范性)XML规范。原因是与SGML的兼容性,如果有人记得的话。)
在您的DTD中,空元素将匹配两个分支。戴夫的解决方案改变了DTD的含义,因为它接受了
<root>
<element>
<one />
<two />
<one />
</element>
</root>
如果您不想这样,请确保在每个“或”分支处,您只需提前查看一个标记就可以确切地知道要采取哪一个,例如,通过编写
<!ELEMENT element ((one+, two*) | (two+, one*))? >