XML, DTD: как сделать заказ не важно - PullRequest
16 голосов
/ 20 января 2011

Я начал с использования 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)>

(обратите внимание, что fileName и fileNumber на самом деле являются необязательными)

и

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

, поэтому все это работает нормально.(Я использую опцию eclipse «validate», чтобы проверить это сейчас)

однако во время тестирования я получил то, что я считаю странной ошибкой

, если я сделаю

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

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

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

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

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

Ответы [ 5 ]

9 голосов
/ 20 января 2011

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

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

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

8 голосов
/ 20 октября 2011

Объявление неупорядоченных списков с ограничениями на вхождение в 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))) )>
6 голосов
/ 22 января 2013

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

<!ELEMENT level ANY>

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

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

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

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

<!ELEMENT Instructors ANY>

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

4 голосов
/ 20 января 2011

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

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

0 голосов
/ 30 сентября 2013

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

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

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

...