Написание DTD: Как добиться этой настройки детей - PullRequest
2 голосов
/ 03 марта 2010

Элемент tasklist может содержать не более одного title и не более одного description, дополнительно любое количество (включая 0) task элементов в любом порядке.

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

<!ELEMENT tasklist (title?, description?, task*) >

В качестве альтернативы, я мог бы явно назвать all возможные опции:

(title, description?, task*) |
(title, task+, description?, task*) |
(task+, title, task*, description?, task*) |
(description, title?, task*) |
(description, task+, title?, task*) |
(task+, description, task*, title?, task*) |
(task*)

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

И нет, XSD или RelaxNG не вариант. Мне нужен простой старый DTD.

Ответы [ 2 ]

3 голосов
/ 19 мая 2010

Сводная информация о том, что вам нужно:

<!ELEMENT tasklist (task*, ((title?, task*, description?) |
                    (description?, task*, title?)), task*)>

Чередование для title, появляющегося до / после description.

Однако , это не детерминированная модель контента, как объясняет @ 13ren в своем ответе . [Вот еще один пример от Microsoft] (http://msdn.microsoft.com/en-us/library/9bf3997x(VS.71).aspx).

Короче

Ваши требования состоят в том, чтобы иметь недетерминированную модель, и поэтому для вашего сценария невозможно допустимое DTD.

Альтернативы

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

<!ELEMENT tasklist (
  task*,
  ((title, task*, description?) | 
  (description, task*, title?))?
)>

Примеры:

<!-- Valid -->
<tasklist>
  <task></task>
  <task></task>
  <task></task>
  <title></title>
  <task></task>
  <description></description>
</tasklist>
<!-- Valid -->
<tasklist>
  <title></title>
  <task></task>
  <task></task>
  <task></task>
</tasklist>
<!-- Invalid
<tasklist>
  <task></task>
  <title></title>
  <task></task>
  <description></description>
  <task></task>
</tasklist>
-->

Или, возможно, более естественно, принудительно установить, что элемент title или description должен быть первым элементом, и оба элемента title и description должны существовать или не существовать.

<!ELEMENT tasklist (
  ((title, task*, description) | 
  (description, task*, title))?,
  task*
)>

Примеры:

<!-- Valid -->
<tasklist>
  <title></title>
  <task></task>
  <description></description>
  <task></task>
  <task></task>
</tasklist>
<!-- Invalid
<tasklist>
  <task></task>
  <title></title>
  <description></description>
  <task></task>
  <task></task>
</tasklist>

<tasklist>
  <title></title>
  <task></task>
  <task></task>
  <task></task>
</tasklist>
-->

В противном случае

В противном случае вам необходимо использовать RELAX NG, который допускает недетерминированные модели.

0 голосов
/ 03 марта 2010

Почему заказ не важен?

Мне кажется, что порядок здесь довольно важен; и что единственным разумным порядком является заголовок ?, описание ?, задача *.

Гибкость хороша и все, но иногда это просто не нужно.

...