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)>

(обратите внимание, что имя_файла и имя_файла фактически являются необязательными)

и

<document>
 <level>
  <file>group1file01</file>
 </level>
 <level>
  <file>group1file02</file>
  <fileName>file 2</fileName>
  <fileNumber>0</fileNumber>
 </level>
...

как таковое все это прекрасно работает. (Я использую параметр "проверять" eclipse для проверки его на данный момент)

однако во время тестирования я получил то, что, по моему мнению, является wierd error

если я делаю

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

изменение порядка строк, Eclipse отказывается его проверять...

Мне было интересно, если это проблема с Eclipse или если порядок действительно важен.

Если порядок важен, как я могу изменить DTD, чтобы заставить его работать независимо от порядка его элементов?

Я не могу изменить XML, потому что у меня уже есть все файлы XML и написанный синтаксический анализатор (я знаю, что я сделал это неправильно).

Ответы

Ответ 1

Как сказал Роджер, есть только упорядоченные списки, но вы можете использовать оператор OR | для определения всех принятых комбинаций

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

Посмотрите здесь, есть пример в разделе Выбор

Ответ 2

Объявление неупорядоченных списков с ограничениями на появление в DTD часто приводит к длинным или сложным поисковым объявлениям. Одной из важных причин этого является то, что DTD должны быть детерминированными, поэтому даже переход на XML-схемы не обязательно помогает.

Вот объявление DTD для элемента <level>, которое содержит:

  • точно 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))) )>

Ответ 3

Вы можете использовать ключевое слово ANY, если вы не слишком беспокоитесь о действительности:

<!ELEMENT level ANY>

Я столкнулся с аналогичной проблемой здесь, это могут быть два случая:

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

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

Единственное решение, которое я нашел, следующее:

<!ELEMENT Instructors ANY>

Возможно, есть лучшее решение, но оно отлично подходит для моей конкретной проблемы.

Ответ 4

При использовании DTD дочерние узлы должны появляться в порядке, указанном в определении элемента. Невозможно разрешить альтернативные заказы, если вы не хотите перейти на схему XSD.

Добавление: Per @Gaim вы можете предлагать альтернативные заказы с использованием синтаксиса (a, b, c...) | (b, a, c...), но это не очень практично для более чем, скажем, 3 вложенных элемента, так как произвольный порядок допускает факторное число порядков - 6 для 3 элементов, 24 для 4 элементов, 120 для 5 элементов - и умное использование? операторы обязательно приведут к ложной проверке для странных случаев.

Ответ 5

Если вы можете угадать разумную верхнюю границу для количества детей для вашего элемента, то есть чрезвычайно грязный способ преодоления проблемы. Ниже приведен пример для 0-3 детей:

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

Таким образом, вы позволяете элементу "myUnorderedElement" иметь 0-3 дочерних элементов любого типа option1, option2 или option3.