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.