Сводная информация о том, что вам нужно:
<!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, который допускает недетерминированные модели.