DTD - DTD Declaration Ordering and Declaration Conflicts

DTD declaration ordering and declaration conflicts refer to the rules that determine how declarations are arranged inside a Document Type Definition (DTD) and what happens when the same XML component is declared more than once or when declarations contradict each other. Understanding these rules is important because an XML document can become invalid or behave differently depending on how its DTD declarations are written.

1. What Is Declaration Ordering in a DTD?

A DTD contains declarations that define the structure and allowed content of an XML document. These declarations can define elements, attributes, entities, and notations.

For example:

<!ELEMENT student (name, age)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>

Here, the student element is declared first, followed by its child elements.

In many situations, XML processors can resolve declarations regardless of their order. Therefore, the following can also be valid:

<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
<!ELEMENT student (name, age)>

The important point is that the referenced elements must ultimately have valid declarations available to the DTD.

Declaration ordering becomes more significant when multiple declarations, parameter entities, conditional sections, or internal and external subsets are involved.

2. Declaration Conflicts

A declaration conflict occurs when the same XML component receives incompatible or duplicate declarations.

For example:

<!ELEMENT student (name)>
<!ELEMENT student (name, age)>

Both declarations attempt to define the same student element, but they specify different content models.

The first declaration says:

student → name

The second says:

student → name, age

This creates a conflicting element declaration and should not be used in a valid DTD.

3. Duplicate Element Declarations

An element should not be given two different content models.

For example:

<!ELEMENT employee (name, id)>
<!ELEMENT employee (name, department)>

The declarations conflict because employee cannot simultaneously have both structures.

A better DTD would combine the required structure into one declaration:

<!ELEMENT employee (name, id, department)>

The XML document can then follow this single, unambiguous definition.

4. Duplicate Attribute Declarations

Attribute declarations can also create conflicts.

Consider:

<!ATTLIST student
    id ID #REQUIRED
>

<!ATTLIST student
    id CDATA #IMPLIED
>

The attribute id is first declared as an ID type and later as CDATA.

These definitions are incompatible. An XML processor cannot treat the same attribute as both an ID and ordinary character data.

Therefore, attributes should be declared consistently.

A correct declaration would be:

<!ATTLIST student
    id ID #REQUIRED
>

Additional attributes can be declared separately if necessary, but an existing attribute should not be redefined with a contradictory type.

5. Internal and External DTD Declarations

XML documents can use both an internal subset and an external DTD.

For example:

<!DOCTYPE student SYSTEM "student.dtd" [
    <!ELEMENT student (name)>
]>

Here, the document contains an internal declaration while also referencing an external DTD.

When declarations occur in both places, conflicts can arise. This is particularly important when the same element or attribute is declared differently in the internal and external subsets.

The XML processor must apply XML's DTD rules when resolving these declarations. Developers should therefore avoid defining the same component differently in multiple locations.

6. Parameter Entities and Declaration Ordering

Parameter entities can insert DTD declarations into another DTD.

For example:

<!ENTITY % commonElements "
    <!ELEMENT name (#PCDATA)>
    <!ELEMENT age (#PCDATA)>
">

%commonElements;

When the parameter entity is referenced, its contents become part of the DTD.

This means that declaration order can become less obvious because declarations may be introduced indirectly.

For example:

<!ENTITY % studentElement "<!ELEMENT student (name, age)>">
%studentElement;

The actual student declaration appears when %studentElement; is expanded.

When working with parameter entities, developers should make sure that expansion does not accidentally introduce duplicate or conflicting declarations.

7. Conditional Sections

Conditional sections can also affect which declarations become part of a DTD.

For example:

<![INCLUDE[
    <!ELEMENT student (name, age)>
]]>

The INCLUDE section makes its declarations active.

An IGNORE section, on the other hand, prevents its contents from being considered as active declarations.

This can be useful for creating configurable DTDs, but careless use can lead to unexpected duplicate declarations when multiple sections are included.

8. Why Declaration Conflicts Are a Problem

Declaration conflicts can cause several problems.

First, they can make the DTD invalid.

Second, they make the structure of the XML document difficult to understand.

Third, different developers may interpret the intended structure differently.

Fourth, debugging becomes more difficult when declarations are distributed across several files or parameter entities.

For large XML applications, these problems can become significant because DTDs may contain hundreds of declarations.

9. Best Practices for Declaration Ordering

A clear declaration structure makes DTDs easier to maintain.

A commonly useful organization is:

<!-- Entity declarations -->

<!ENTITY company "Example Company">

<!-- Element declarations -->

<!ELEMENT student (name, age)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>

<!-- Attribute declarations -->

<!ATTLIST student
    id ID #REQUIRED
>

This arrangement is not simply about making the DTD technically valid. It improves readability and helps developers quickly locate different types of declarations.

For larger DTDs, related declarations should be grouped together and parameter entities should be clearly documented.

10. Avoiding Declaration Conflicts

A good approach is to maintain one authoritative declaration for each element and attribute.

For example, instead of:

<!ELEMENT book (title)>
<!ELEMENT book (title, author)>

use:

<!ELEMENT book (title, author)>

Similarly, avoid redefining attributes with different types or default rules.

It is also useful to separate common declarations into external DTD modules when a project contains many XML document types. This reduces accidental duplication and makes the DTD easier to maintain.

11. Practical Example

Consider this DTD:

<!ELEMENT course (name, duration)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT duration (#PCDATA)>

<!ATTLIST course
    code ID #REQUIRED
>

This DTD clearly defines:

  • course as an element containing name followed by duration.

  • name as text content.

  • duration as text content.

  • code as a required unique identifier for the course element.

Now suppose someone adds:

<!ELEMENT course (name)>

This creates a conflicting declaration because course has already been defined with a different content model.

The correct solution is to modify the original declaration if the structure needs to change, rather than adding a second contradictory declaration.

Conclusion

DTD declaration ordering and declaration conflicts are important when designing reliable XML document structures. Although many simple DTD declarations do not depend heavily on their physical order, the situation becomes more complex when parameter entities, internal and external subsets, conditional sections, and multiple DTD modules are involved.

The key principle is to keep declarations consistent and unambiguous. Each element and attribute should have a clear definition, conflicting declarations should be avoided, and related declarations should be organized logically. Following these practices makes DTDs easier to validate, debug, understand, and maintain in large XML-based applications.