XML,DTD:如何使顺序不重要

Posted

技术标签:

【中文标题】XML,DTD:如何使顺序不重要【英文标题】:XML, DTD: how to make the order not important 【发布时间】:2011-06-12 06:49:54 【问题描述】:

我开始使用 XML 文件和解析器作为存储数据的便捷方式

我想使用 DTD 在 xml 文件到达时检查它们的结构。

这是我的 DTD 文件

< ?xml version="1.0" encoding="UTF-8"?>
< !ELEMENT document (level*)>
< !ELEMENT level (file,filelName?,fileNumber?)>
< !ELEMENT file (#PCDATA)>
< !ELEMENT filelName (#PCDATA)>
< !ELEMENT fileNumber (#PCDATA)>

(请注意,fileName 和 fileNumber 实际上是纯可选的)

<document>
 <level>
  <file>group1file01</file>
 </level>
 <level>
  <file>group1file02</file>
  <fileName>file 2</fileName>
  <fileNumber>0</fileNumber>
 </level>
...

因此,这一切都很好。 (我现在使用 eclipse“验证”选项来测试它)

但是在测试时我发现了一个我认为很奇怪的错误

如果我这样做了

 <level>
  <levelName>Level 2</levelName>
  <levelNumber>0</levelNumber>
        <file>group1level02</file>
 </level>

更改行的顺序,Eclipse 拒绝验证它...

我想知道这是否是 Eclipse 的问题,或者顺序是否真的很重要。

如果顺序很重要,无论元素的顺序如何,我如何更改 DTD 以使其正常工作?

我无法真正更改 XML,因为我已经编写了所有 XML 文件和解析器(我知道我做错了,哈哈)。

【问题讨论】:

【参考方案1】:

正如罗杰所说,只有有序列表,但您可以使用运算符 OR | 来定义所有接受的组合

<!ELEMENT level ((file,filelName?,fileNumber?)|(filelName?,fileNumber?,file))>

看here,在Choices部分有一个例子

【讨论】:

哼...我原以为它会更灵活...我不得不去||因为我必须对读取 xml 的顺序进行假设,哈哈。感谢您的解决方案 这不是一个有效的 DTD,因为它不是确定性的。即使它是有效的,它也不允许子元素以任何可能的顺序排列。【参考方案2】:

在 DTD 中声明带有出现约束的无序列表通常会导致声明冗长或复杂。这样做的一个重要原因是 DTD 必须是确定性的,因此即使切换到 XML 模式也不一定有帮助。

这里是元素 &lt;level&gt; 的 DTD 声明,其中包含:

正好是 1 个&lt;file&gt; 元素 0-1 &lt;fileName&gt; 元素 0-1 &lt;fileNumber&gt; 元素 以任何可能的顺序

代码:

<!ELEMENT level ( (file, ((fileName, fileNumber?) | (fileNumber, fileName?))?)
                 |(fileName, ((file, fileNumber?) | (fileNumber, file)))
                 |(fileNumber, ((file, fileName?) | (fileName, file))) )>

【讨论】:

【参考方案3】:

如果你不太关心有效性,你可以使用ANY关键字:

<!ELEMENT level ANY>

我遇到过类似的问题here,可能会出现这两种情况:

<Instructors>
  <Lecturer>
  </Lecturer>
  <Professor>
  </Professor>
</Instructors>

<Instructors>
  <Lecturer>
  </Lecturer>
  <Professor>
  </Professor>
</Instructors>

我找到的唯一解决方案是:

<!ELEMENT Instructors ANY>

也许有更好的解决方案,但它适用于我的特定问题。

【讨论】:

最好使用: 看来是这样。一年前,我找不到更好的主意。 看来你正在做 Jennifer Widom 的斯坦福数据库 MOOC 的 XML 练习...我来到这里是因为同样的问题 :-) 与 我不再从 xmllint 得到错误。 感谢@Suzana_K 和 Alexander_Gryanko。我在括号内的属性之后包括运算符...【参考方案4】:

对于 DTD,子节点必须按照元素定义中列出的顺序出现。除非您想升级到 XSD 架构,否则无法允许其他顺序。

附录:根据@Gaim,您可以使用 (a,b,c...)|(b,a,c...) 语法提供替代订单,但这不是对于超过 3 个嵌套元素来说真的很实用,因为任意顺序允许阶乘的顺序 - 6 个用于 3 个元素,24 个用于 4 个元素,120 个用于 5 个元素 - 并且巧妙地使用 ?运算符肯定会导致奇怪情况的错误验证。

【讨论】:

它是一个非常小的系统,所以我认为更改为 XSD 不会很有趣,但我会调查一下,谢谢 不完全正确。您可以允许交替排序,您只需明确列出所有您想要允许的排序。 XML 模式和 DTD 中允许的排序规则之间没有太大区别,在模式中表达它们只是不那么痛苦。【参考方案5】:

如果您可以猜测元素的子元素数量的合理上限,那么解决问题的方法非常肮脏。以 0-3 个孩子为例:

<!ELEMENT myUnorderedElement ( (option1 | option2 | option3)?, (option1 | option2 | option3)?, (option1 | option2 | option3)? >

因此,您允许元素“myUnorderedElement”拥有 0-3 个选项 1、选项 2 或选项 3 类型的子元素。

【讨论】:

以上是关于XML,DTD:如何使顺序不重要的主要内容,如果未能解决你的问题,请参考以下文章

懂XML的进!

java - 如何将本地DTD文件的验证应用于java中的xml文件?

eclipse如何在不联网的情况下引入dtd约束文件

如何从键盘获取 dtd 和 xml 文件?

xmllint:如何使用本地 DTD 文件验证 XML

XML--- XML文档类型定义(DTD)