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>