DTD - DTD Conditional Entity Usage and Entity Expansion Rules
In XML Document Type Definitions (DTD), entities provide a way to define reusable pieces of content. Instead of writing the same text repeatedly throughout an XML document, you can define it once as an entity and reference it wherever required. Entity processing becomes particularly important when working with parameter entities, external entities, and conditional sections.
1. What is Entity Expansion?
Entity expansion is the process by which an XML processor replaces an entity reference with the content associated with that entity.
For example:
<!DOCTYPE book [
<!ENTITY publisher "ABC Publications">
]>
<book>
<publisher>&publisher;</publisher>
</book>
Here, the entity publisher is declared as:
<!ENTITY publisher "ABC Publications">
The XML document uses:
&publisher;
When the XML processor reads the document, it expands the entity reference to:
ABC Publications
Conceptually, the processed XML becomes:
<publisher>ABC Publications</publisher>
This allows frequently used information to be defined once and reused multiple times.
2. General Entities
A general entity is normally referenced from the XML document using the &name; syntax.
Example:
<!DOCTYPE company [
<!ENTITY companyName "Tech Solutions Pvt Ltd">
]>
<company>
<name>&companyName;</name>
</company>
The entity declaration defines companyName, and the XML document references it using:
&companyName;
The processor expands the reference to its declared value.
General entities are useful for:
-
Repeated text
-
Company names
-
Copyright notices
-
Common descriptions
-
Frequently repeated XML content
3. Parameter Entities
Parameter entities are different from general entities because they are primarily used inside the DTD itself.
They are declared using %:
<!ENTITY % commonElements "
<!ELEMENT name (#PCDATA)>
<!ELEMENT address (#PCDATA)>
">
They are referenced using:
%commonElements;
For example:
<!DOCTYPE person [
<!ENTITY % commonElements "
<!ELEMENT name (#PCDATA)>
<!ELEMENT address (#PCDATA)>
">
%commonElements;
<!ELEMENT person (name, address)>
]>
When the DTD is processed, %commonElements; is expanded and its declarations become part of the DTD.
This is especially useful when several DTD declarations need to be reused.
4. Internal Entity Expansion
An entity can be defined directly inside the internal DTD subset.
Example:
<!DOCTYPE message [
<!ENTITY greeting "Welcome to XML">
]>
<message>
<text>&greeting;</text>
</message>
The entity greeting is replaced by its value during XML processing.
This is called internal entity expansion because the entity's replacement text is stored directly in the DTD.
5. External Entity Expansion
An entity can also refer to content stored in an external file.
Example:
<!DOCTYPE document [
<!ENTITY information SYSTEM "information.xml">
]>
The XML document can then reference it:
<document>
&information;
</document>
The XML processor may retrieve the contents of information.xml and replace the entity reference with that content.
External entities can be useful when large or reusable XML content needs to be maintained separately from the main document.
However, external entity processing introduces security considerations. Applications should configure XML parsers carefully when processing XML from untrusted sources.
6. Conditional Sections in DTDs
DTD conditional sections allow parts of a DTD to be either included or ignored during DTD processing.
The two main keywords are:
INCLUDE
and
IGNORE
A basic example is:
<![INCLUDE[
<!ELEMENT book (title, author)>
]]>
The declarations inside the section are included in the DTD.
An ignored section looks like:
<![IGNORE[
<!ELEMENT price (#PCDATA)>
]]>
The declarations inside this section are ignored by the XML processor.
Conditional sections are mainly useful in external DTD subsets and DTD modularization.
7. Using Parameter Entities with Conditional Sections
Parameter entities become particularly useful when conditional sections need to be controlled dynamically.
For example:
<!ENTITY % includeAuthor "INCLUDE">
<![%includeAuthor;[
<!ELEMENT author (#PCDATA)>
]]>
Here:
<!ENTITY % includeAuthor "INCLUDE">
defines a parameter entity whose value is INCLUDE.
The conditional section then uses:
<![%includeAuthor;[
After parameter-entity expansion, the processor effectively sees:
<![INCLUDE[
Therefore, the declaration inside the section is included.
The important idea is that parameter entity expansion occurs while the DTD is being processed, allowing the DTD structure to be controlled through reusable declarations.
8. Switching Between INCLUDE and IGNORE
A similar mechanism can be used to control whether a group of declarations is included.
For example:
<!ENTITY % feature "IGNORE">
<![%feature;[
<!ELEMENT advancedInfo (#PCDATA)>
]]>
Because the parameter entity contains IGNORE, the section is ignored.
If the declaration is changed to:
<!ENTITY % feature "INCLUDE">
the same section becomes active.
This provides a way to maintain optional sections of a DTD without completely removing their declarations.
9. Why Conditional Entity Usage Is Useful
Conditional entity usage is useful when designing DTDs that need to support different configurations.
For example, a company could have different XML document types for:
-
Basic documents
-
Advanced documents
-
Internal documents
-
Public documents
-
Different versions of a document standard
Instead of creating a completely separate DTD for every variation, parameter entities and conditional sections can be used to activate or deactivate particular declarations.
This can make a large DTD easier to maintain.
10. Entity Expansion and Nested Entities
Entities can also reference other entities.
For example:
<!DOCTYPE example [
<!ENTITY first "Hello">
<!ENTITY second "&first; World">
]>
<message>&second;</message>
The processor first resolves the reference to second:
&first; World
It then resolves first:
Hello World
The resulting content is therefore:
<message>Hello World</message>
This is known as nested entity expansion.
When entities reference other entities, the XML processor must repeatedly resolve those references until the appropriate replacement text is produced.
11. Important Rules for Entity Expansion
Several rules should be understood when working with DTD entities.
Entity names must be declared before they are normally used. The declaration establishes what the entity represents.
General and parameter entities have different purposes. General entities are commonly referenced in XML content using &name;, while parameter entities are used within DTD declarations using %name;.
Entity references use specific syntax. A general entity is referenced as:
&entityName;
A parameter entity is referenced as:
%entityName;
Entities can contain text or declarations depending on their type. General entities commonly provide replacement text, while parameter entities can be used to construct reusable DTD declarations.
Recursive entity definitions should be avoided. An entity that ultimately refers back to itself can create processing problems.
12. Entity Expansion and Security
Entity expansion must be handled carefully when XML documents originate from untrusted users or external systems.
For example, malicious XML can attempt to exploit external entity processing or excessive entity expansion. Such attacks can cause unauthorized access to external resources, information disclosure, or excessive consumption of system resources.
Therefore, applications that process untrusted XML should generally configure their XML parser to restrict or disable unnecessary external entity processing and external resource access.
This is one reason why understanding entity expansion is important not only for DTD syntax but also for secure XML application development.
13. Entity Expansion vs. Text Substitution
It is useful to think of entity expansion as a form of controlled replacement.
Suppose the DTD contains:
<!ENTITY country "India">
and the XML contains:
<location>&country;</location>
The entity reference:
&country;
is replaced with:
India
The original XML source contains the entity reference, while the XML processor works with the entity's replacement value.
This makes entities useful for representing reusable information without repeatedly writing the same content.
14. Summary
DTD conditional entity usage combines parameter entities with conditional sections to control which portions of a DTD are active. The INCLUDE keyword activates a section, while IGNORE prevents that section from being processed. Parameter entities make it possible to control these conditions through reusable declarations.
Entity expansion is the process of replacing an entity reference with its declared replacement content. General entities are normally referenced using &name;, whereas parameter entities use %name; and are primarily processed within the DTD.
Understanding these mechanisms is important when working with complex and modular DTDs because they allow declarations to be reused, organized, and selectively activated. At the same time, external entity processing and unrestricted entity expansion can create security risks, so XML applications should use secure parser configurations when processing untrusted documents.