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 для случая, когда список необходимых элементов может присутствовать в любом порядке.
Ответы
Ответ 1
ChrisF ошибается, заявляя, что вы не можете этого сделать (но при этом для проверки спецификации!); DevNull [теперь известный как Daniel Haley] прав, чтобы сказать, что вы можете.
Однако существует одно осложнение: модель контента, заданная DevNull для родителя, нарушает правила детерминизма XML. Неформально эти правила говорят, что анализатор должен знать, не глядя, какой токен в модели контента соответствует каждому элементу в документе. Если в родительском элементе синтаксический анализатор видит дочерний элемент 1, он не может без него узнать, совпало ли оно с первым или вторым введением child1 в модели контента DevNull. Это ошибка (но, как это бывает, ошибка, которую процессоры не обязаны сообщать, - это ошибка, которая означает "все ставки отключены, процессор может что-то здесь сделать, в том числе не заметить, что что-то не так" ).
Модель контента для родителя, которая подчиняется правилам детерминизма, может быть сформирована путем разложения общих префиксов, таким образом:
<!ELEMENT parent (
(child1, ( (child2,child3)
| (child3,child2)))
| (child2, ( (child1,child3)
| (child3,child1)))
| (child3, ( (child1,child2)
| (child2,child1)))
) >
Это менее удобно, чем объявления для этой модели могут быть на других языках схемы, а для более чем трех элементов это ошибка склонна и крайне утомительна для выполнения вручную. Но это не невозможно объявить модель контента, которую вы хотите, с DTD. Или, может быть, я должен сказать, что это невозможно только для авторов DTD, которые не могут смириться с любыми неудобствами.
Заметим также, что, если последовательность детей не несет какую-либо информацию, некоторые авторитетные органы утверждают, что лучше исправить последовательность.
Ответ 2
Try:
<!ELEMENT parent (child1 | child2 | child3)*>
Должен разрешить ноль или более любого дочернего элемента в любом порядке.
Ответ 3
Чтение появится спецификация, которую вы не можете.
Когда дети объявляются в последовательности, разделенной запятыми, дети должны отображаться в одной и той же последовательности в документе. В полной декларации дети также должны быть объявлены, а дети также могут иметь детей.
Я думаю, это потому, что вы объявляете последовательность (или упорядоченный список, если хотите), а не коллекцию (или неупорядоченный список).
Ответ 4
Это сложно, если вам нужен только один из дочерних элементов. Это единственный способ, о котором я могу думать, и это не очень красиво. Он работает, хотя...
<!ELEMENT parent (
(child1,child2,child3)|
(child1,child3,child2)|
(child2,child1,child3)|
(child2,child3,child1)|
(child3,child1,child2)|
(child3,child2,child1)
)>
В основном я указываю каждую возможную комбинацию только одного элемента child1, child2 и child3.
Вот пример экземпляра. child1
, child2
и child3
могут быть в любом порядке, но каждый из них должен происходить ровно один раз.
<!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>