Explainer
DITA Specialization: When and How to Extend

The Short Answer
Derived Types That Still Behave
In most XML applications, an element's meaning is bound to its name. Nothing in XML says that one element is a kind of another. The OASIS DITA 1.3 specification adds that relationship: a specialized element type or attribute is derived from an ancestor, inherits its semantics and default processing, and can optionally get processing of its own.
That is why a task is still a topic, and why a step in a task still behaves like a list item in tools that know nothing about tasks. For the standard types built this way, see DITA topic types; for what the markup looks like in practice, DITA XML examples.
Two Kinds
Structural and Domain Specialization
- Structural specialization
- A new topic or map type. Concept, task, and reference are specialized from topic; bookmap is specialized from map. You use it when a whole kind of document has its own shape, such as a procedure with fixed parts that the standard task does not model.
- Domain specialization
- New elements for a subject area, built from elements in topic or map (or from the @props or @base attributes). A domain can be added to any map or topic type that includes it. You use it when a kind of phrase or data needs its own name wherever it occurs, such as a part identifier, a torque value, or a software command.
Each kind is an "is a" hierarchy. A specialization of task is still a task, and a specialization of a domain is still part of that domain. Every element type is declared in exactly one vocabulary module, which is either a structural module, an element domain module, or an attribute domain module.
How Tools Cope
The @class Attribute Is the Whole Trick
The ancestry lives in the @class attribute, declared as a default value in the grammar. The value is a leading - (structural modules) or + (domain modules), then tokens of the form module/type ordered from most general to most specific, then a trailing space. The specification's own example is - topic/li task/step : a step is a list item from the base topic vocabulary, and a step from the task module.
Processors, including stylesheets and plug-ins, match on those tokens instead of on element names. A processor that knows topic/keyword can handle any descendant of keyword without ever hearing its name. Authors should not edit the value; it arrives with the document type. A fictitious domain element looks like this:
<!-- Illustrative only: a fictitious domain element, not a complete module. -->
<!ELEMENT fastenerid (#PCDATA)>
<!ATTLIST fastenerid class CDATA "+ topic/keyword fastener-d/fastenerid "><p>Install bolt <fastenerid>FB-2210</fastenerid> in the lower bracket.</p>A tool with no knowledge of fastenerid still sees a keyword. A publishing rule written for fastener-d/fastenerid can bold it, link it to a parts catalog, or check it against a list. The grammar also contributes a value to the root @domains attribute, which lets tools judge whether two documents use compatible domains when content is pasted or a conref points at a more specialized element.
The Other Directions
Generalization and Constraints
Generalization moves content up the hierarchy to any ancestor type. For the example above it produces a plain keyword:
<p>Install bolt <keyword>FB-2210</keyword> in the lower bracket.</p>Teams use it to migrate off a specialization they no longer want, to hand content to a process that is not specialization aware, or to share specialized content where its domain is not available. When it is temporary, the original @class and @domains values should be kept so the content can be specialized again.
Constraints are the opposite move. A constraint simplifies a grammar so that any instance valid under the constrained version is also valid under the original. It can remove optional elements, make optional elements required, fix an order, limit attribute values, or trim a domain. It cannot make a required element optional or reorder an ordered model. Because a constrained document is still valid against the unconstrained grammar, removing a constraint means rebinding to a less restricted document type, with no element renaming. The strict task in the standard is built this way.
Constraints are weak by default. A strong constraint is one a processor should check for compatibility when resolving @conref or @conkeyref, and the grammar marks it with an s prefix in the @domains contribution:
<!-- A constraint contributes to @domains. The "s" prefix marks it strong. -->
domains="(topic task strictTaskbody-c)" weak (the default)
domains="s(topic task strictTaskbody-c)" strongDecision
Specialize, Constrain, or Use an Attribute
- Need only a style or a label? Use @outputclass.
- The attribute exists to carry a role for styling during output processing, and HTML output typically keeps it for CSS. It is cheap, but nothing validates its values, and nothing in the content model knows what it means.
- Need a controlled list of values? Use a subject scheme.
- A subject scheme map defines the allowed values for an attribute, such as audience or product, and binds them without defining a specialization or a constraint. Changing the list is an edit to a map, not to a grammar.
- Need fewer elements, not different ones? Use a constraint.
- The specification is direct about this: do not specialize merely to remove element types from a content model. Constrain instead.
- Need a new meaning that tools and checks can act on? Specialize.
- The case for specialization is new semantics, or output processing that the current content model cannot support. If a reviewer, a validator, or a stylesheet must tell this thing apart from every other phrase or section, a name in the grammar is worth considering.
A useful test: write down what each team would do differently because the new name exists. If the answer is nothing but a look in the output, it is an @outputclass job. If the answer is a rule, a check, or a separate output path, specialization may earn its keep.
The Cost
What a Specialization Commits You To
A specialization is a grammar you own. Each module needs a DTD, RELAX NG, or XSD implementation with correct @class and @domains values, shared document type shells, and a way to deliver it to every authoring tool. Publishing needs a plug-in or stylesheet changes for any behavior beyond the inherited default (see the DITA Open Toolkit). Training, templates, and review checklists all have to cover it.
The cost recurs. When the standard moves, your modules move with it: the DITA 2.0 drafts rename the domains attribute, so every specialization with a hand-written grammar is in scope for migration review. The kind of question to ask before building is whether the same value could come from a standard type, a constraint, or a subject scheme; for how this fits a first migration, see DITA migration.
FAQ
Questions We Hear
What is DITA specialization in one sentence?
It is the mechanism for defining a new element type or attribute as a descendant of an existing one, so the new type inherits its meaning and default processing and tools that do not know it can treat it as the ancestor.
What does the @class attribute do?
It records an element's ancestry as an ordered list of module and type names, general to specific, such as topic/keyword fastener-d/fastenerid. Specialization-aware processing is defined in terms of those values. Authors normally never type it; it comes from the grammar as a default, and the specification says authors should not modify it.
What is the difference between specialization and a constraint?
Specialization adds new element types derived from existing ones. A constraint removes options: it narrows a content model or attribute set so that anything valid under the constrained grammar is still valid under the original. If you only want fewer choices, constrain.
Can specialized content be turned back into standard DITA?
Yes. Generalization converts content to any of its ancestor types, either permanently (for migration, when a specialization is dropped) or temporarily for round-tripping through a process that is not specialization aware. It depends on the @class values being intact.
Does DITA 2.0 change specialization?
DITA 1.3 is the published OASIS standard as of this writing. The 2.0 drafts replace the @domains attribute with @specializations, which matters to any grammar you maintain; see our DITA 2.0 briefing for the status and the full list of removals.
Get In Touch
Decide Before You Extend
Send us a sample of your content and the reuse you need. We will tell you whether the standard types, a constraint, or a specialization fits.