DTD需要元素排序

时间:2010-06-11 12:52:00

标签: xml dtd

我希望以dtd中定义的任何顺序列出所需元素,但不知道如何执行此操作。

例如,我有以下定义:

<!ELEMENT parent (child1, child2, child3)>

此dtd声明将成功验证以下xml:

<parent>
   <child1></child1>
   <child2></child2>
   <child3></child3>
</parent>

但在以下情况下,xml不会通过验证:

<parent>
   <child2></child2>
   <child1></child1>
   <child3></child3>
</parent>

可能的解决方案之一是声明

<!ELEMENT parent (child1 | child2 | child3)>

但是在这种情况下,虽然验证会成功,但其中一个孩子可能会丢失。

当所需元素的列表可以按任何顺序出现时,我需要正确的dtd元素声明。

4 个答案:

答案 0 :(得分:11)

ChrisF说你不能这样做是错误的(但是要检查规格是否值得称赞!); DevNull [现在称为Daniel Haley]说你可以这样说。

然而,有一个复杂因素:DevNull为 parent 提供的内容模型违反了XML的确定性规则。非正式地,这些规则说解析器必须知道文档中每个元素匹配的内容模型中的哪个令牌,而不是预测。如果在 parent 元素中,解析器会看到 child1 ,那么它无法预知是否刚刚匹配 child1 在DevNull的内容模型中。这是一个错误(但是当发生这是一个错误,处理器没有义务报告 - 这是一个错误,意味着“所有赌注都关闭,处理器可以在这里做任何事情,包括没有注意到任何错误”)。 / p>

符合确定性规则的的内容模型可以通过分解出公共前缀来形成,因此:

<!ELEMENT parent ( 
                   (child1, ( (child2,child3)
                            | (child3,child2)))
                 | (child2, ( (child1,child3)
                            | (child3,child1)))
                 | (child3, ( (child1,child2)
                            | (child2,child1)))
                 ) >

这比使用其他模式语言的此模型的声明更不方便,并且对于三个以上的元素,它容易出错并且手动执行非常繁琐。但是使用DTD声明所需的内容模型并非不可能。或许我应该说,只有DTD作者无法承受任何不便,这是不可能的。

另请注意,除非儿童序列携带一些信息,否则一些设计机构强烈反对修复序列更好。

答案 1 :(得分:9)

尝试:

<!ELEMENT parent (child1 | child2 | child3)*>

任何孩子的任何顺序都应该允许零个或多个。

答案 2 :(得分:2)

看来你不能阅读the spec

  

如果以逗号分隔的顺序声明子项,则子项必须在文档中以相同的顺序出现。在完整的声明中,孩子们也必须被宣布,孩子们也可以有孩子。

我认为这是因为你要声明一个序列(或者你喜欢的有序列表),而不是一个集合(或无序列表)。

答案 3 :(得分:2)

当您需要每个子元素中的一个时,这很棘手。这是我能想到的唯一方式,而且不是很漂亮。它虽然有效......

<!ELEMENT parent ( 
                 (child1,child2,child3)|
                 (child1,child3,child2)|
                 (child2,child1,child3)|
                 (child2,child3,child1)|
                 (child3,child1,child2)|
                 (child3,child2,child1)
                )>

基本上我正在指定一个child1,child2和child3元素的每个可能组合。

这是一个示例实例。 child1child2child3可以按任何顺序排列,但每次都必须出现一次。

<!DOCTYPE parent [
<!ELEMENT parent ( 
                 (child1,child2,child3)|
                 (child1,child3,child2)|
                 (child2,child1,child3)|
                 (child2,child3,child1)|
                 (child3,child1,child2)|
                 (child3,child2,child1)
                )>
<!ELEMENT child1 (#PCDATA)>
<!ELEMENT child2 (#PCDATA)>
<!ELEMENT child3 (#PCDATA)>
]>
<parent>
  <child2></child2>
  <child1></child1>
  <child3></child3>
</parent>