DTD, когда порядок элементов не имеет значения - PullRequest
2 голосов
/ 20 октября 2011

Я не могу понять, как написать DTD для файла XML, который может содержать одинаковые элементы в смешанном порядке.

Небольшой пример, который показывает проблему ниже:

<root>

  <element>
    <one></one>
    <two></two>
  </element>

  <element>
    <two></two>
    <one></one>
  </element>

  <element>
    <two></two>
    <two></two>
    <two></two>
    <two></two>
    <one></one>
    <one></one>
  </element>

</root>

Мой DTD:

<!ELEMENT root(element*)>
<!ELEMENT element((one*,two*)|(two*,one*))>

Я нашел похожую тему , но решение не работает в моем случае (и я не уверен, что не так с моим DTD в данный момент). Я получаю это сообщение об ошибке:

xmllint: Content model of Instructors is not determinist: ((one* , two*) | (two* , one*))

Ответы [ 3 ]

9 голосов
/ 20 октября 2011
<!ELEMENT element (one|two)*>

(или +, если у вас должен быть хотя бы один.)

4 голосов
/ 16 декабря 2011

Ваше решение не является детерминированным, потому что

<element>
    <two/>
</element>

- это один из случаев, который соответствует обеим ветвям: (one*, two*) и (two*, one*).

Как заметил @Cristopher, ответ @ Dave допускает смешанное упорядочение, и его ответ решает эту проблему. Но на самом деле ответ Кристофера тоже не детерминированный , потому что при проверке ввода

<element>
    <two/>
</element>

и валидатор встречает первый <two>, который не знает, какую ветку он должен выбрать. Он знает это только после прочтения всех элементов <two>.

Чтобы сохранить порядок при сохранении детерминированности модели, используйте

<!ELEMENT element ( (one+, two*) | (two+, one*) )? >

Ключевыми моментами здесь являются: 1) сохранение модели детерминированной, начиная каждую ветвь с различным обязательным элементом 2), но при этом оставляя пустым <element/> с ? в конце, что делает модель содержимого необязательной.

0 голосов
/ 16 декабря 2011

DTD, как указано, не является детерминистским, и в этом может произойти ошибка синтаксического анализатора xml.(См. Раздел 3.2.1 (нормативный) и Приложение E (ненормативный) спецификации XML. Причина заключается в совместимости с SGML, если кто-то это помнит.)

В вашем DTD пустой элемент будет соответствовать обеим ветвям.Решение Дейва меняет значение DTD в том смысле, что оно принимает

<root>
  <element>
    <one />
    <two />
    <one />
  </element>
</root>

. Если вы этого не хотите, убедитесь, что на каждом «или» филиале вы точно знаете, какой из них выбратьвпереди только один токен, например, написав

<!ELEMENT element ((one+, two*) | (two+, one*))? >
...