Reputation: 82804
The element tasklist
may contain at most one title
and at most one description
, additionally any number (incl. 0) task
elements in any order.
The naive approach is not applicable, since the order should not matter:
<!ELEMENT tasklist (title?, description?, task*) >
Alternatively, I could explicitly name all possible options:
(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*)
but then it's quite easy to write a non-deterministic rule, and furthermore it looks like the direct path to darkest madness. Any ideas, how this could be done more elegantly?
And no, an XSD or RelaxNG is no option. I need a plain, old DTD.
Upvotes: 2
Views: 458
Reputation: 6097
This summarises what you need:
<!ELEMENT tasklist (task*, ((title?, task*, description?) |
(description?, task*, title?)), task*)>
Alternation for the title
appearing before/after description
.
However, this is not a deterministic content model, as @13ren explains in his answer. [Here is another example from Microsoft](http://msdn.microsoft.com/en-us/library/9bf3997x(VS.71).aspx).
Your requirements is to have a non-deterministic model, and as such, there is no possible valid DTD for your scenario.
If you place a simple restriction that either task
or description
must be the last element if both task
and description
are provided, you can use this deterministic DTD declaration:
<!ELEMENT tasklist (
task*,
((title, task*, description?) |
(description, task*, title?))?
)>
Examples:
<!-- 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>
-->
Or, possibly more naturally, enforce that a title
or description
element must be the first element, and both title
and description
elements must exist or be non-existent.
<!ELEMENT tasklist (
((title, task*, description) |
(description, task*, title))?,
task*
)>
Examples:
<!-- 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>
-->
Otherwise, you need to use RELAX NG, which allows for non-deterministic models.
Upvotes: 3
Reputation: 29029
Why is the order unimportant?
It seems to me as if the order is rather a bit important right here; and that the only sensible order is title?, description?, task*.
Flexibility is nice and all, but sometimes it's just not neccessary.
Upvotes: 0