XML,DTD:如何使订单不重要

时间:2011-01-20 07:30:14

标签: xml dtd

我开始使用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“validate”选项来测试它)

然而,在测试时我得到了我认为是一个奇怪的错误

如果我这样做

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

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

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

如果订单很重要,我怎样才能更改DTD以使其无论元素的排序如何都能正常工作?

我无法真正更改XML,因为我已经编写了所有XML文件和解析器(我知道我在错误的方式上做了大声笑)。

5 个答案:

答案 0 :(得分:9)

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

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

查看here选择

部分中有一个示例

答案 1 :(得分:8)

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

以下是元素<level>的DTD声明,其中包含:

  • 正好是1 <file>元素
  • 0-1 <fileName>个元素
  • 0-1 <fileNumber>个元素
  • 以任何可能的顺序

代码:

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

答案 2 :(得分:6)

如果您没有太多关于有效性的话,可以使用ANY关键字:

<!ELEMENT level ANY>

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

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

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

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

<!ELEMENT Instructors ANY>

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

答案 3 :(得分:4)

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

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

答案 4 :(得分:0)

如果你可以为你的元素猜测孩子数量的合理上限,那么如何克服这个问题就会有极其肮脏的方式。按照0-3个孩子的例子:

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

因此,您允许元素“myUnorderedElement”包含任意类型为option1,option2或option3的0-3个子元素。