Each DITA element declares its specialization hierarchy as the value of the @class
attribute. The @class attribute usually provides a mapping from the element's current
name to
its more general equivalents, but it can also provide a mapping from the current name
to more
general and more specialized equivalents. All specialization-aware processing can
be defined in
terms of @class attribute values without reference to a given element's tagname.
Specialization hierarchy declaration requirements
Values for the @class attribute
must conform to the following syntax
requirements:
- An initial "-" or "+" character followed by one or more spaces, "-" for element types
defined in structural vocabulary modules, "+" for element types defined in domain
modules.
- A sequence of one or more module/type pair tokens of the form
"modulename/typename", with each pair of tokens
separated by one or more spaces, where modulename is the short name
of the vocabulary module and typename is the element type name.
Tokens are ordered left to right from most general to most specialized.
- At least one trailing space character (" "). The trailing space ensures that string
matches on module/name pairs can always include a leading and trailing space in order
to
reliably match full tokens.
When the @class attribute is declared in a DTD or XSD, it must be
declared with a default value. In order to support generalization round-tripping
(generalizing specialized content into a generic form and then returning it to the
specialized form) the default value must not be fixed. This allows a
generalization process to overwrite the default values defined by a general document
type
with specialized values taken from the document being generalized.
When a vocabulary module declares new element types, it must provide a
@class attribute for each element type that it declares. The @class attribute
must include a mapping for every structural type or domain in the
specialized type's ancestry, even those in which no element renaming occurred. The
mapping
must start with the value for the base type (for example topic or map),
and finish with the current element type.
A vocabulary module must not change the @class attribute for elements
that it does not specialize, but simply reuses by reference from more generic levels.
For
example, since task, bctask, and guitask use the <p> element without specializing
it,
they must not declare mappings for it.
The @class attribute should not be modified by authors.
Examples (non-normative)
The @class attribute for the task topic type's <step> element
is:
<!ATTLIST step class CDATA "- topic/li task/step ">
This tells us that the <step> element is equivalent to the <li> element in a generic
topic. It also tells us that <step> is equivalent to a <step> in a task topic, which
we already knew, but it's worth noting this in the attribute because it enables round-trip
migration between upper level and lower level types without loss of information.
While a given element's tagname is normally the same as the typename of the last token
in
the @class value, this is not required. Processors that perform generalization
may transform elements from specialized types to less-specialized types, leaving the
values
of the @class attribute unchanged (thus preserving knowledge of the original
most-specialized form). For example, if a user runs a generalizing transformation
that maps
all elements to their first @class value, but preserves their content and attribute
values,
then the user can follow it up with a "specialize" transformation that maps all elements
to
their last @class value (preserving content and attribute values), and provide a full
round
trip for all content between the two document types, using nothing but two generic
transformations and the information in the @class attribute.
The
@class attribute tells a processor what general classes of elements the current element
belongs to. DITA scopes elements by module type (for example topic type, domain type,
or map
type) instead of document type, which lets document type developers combine multiple
topic
types in a single document without complicating transformation logic.
The sequence of values in the @class attribute is important because it tells processors
which value is the most general and which is most specific. This is especially important
for
"specializing" transformations, where you can apply a general rule that says: if the
element
doesn't have a mapping to the target topic type, simply use the last value of the
@class
attribute (and assume that the specialized topic type is reusing some general element
declarations, which only have mappings for the level at which they were declared).
Figure 2-8. Example of structural type element with @class attribute
<appstep class="- topic/li task/step bctask/appstep ">
<cmd class="- topic/ph task/cmd ">A specialized step</cmd>
</appstep>
Figure 2-9. Example of domain element with @class attribute
<wintitle class="+ topic/keyword ui-d/wintitle ">A specialized keyword</wintitle>
While this example is trivial, more complicated hierarchies (say, five levels deep,
with renaming occurring at levels two and four only) make explicit intermediate values
essential.
The specialization hierarchy for a given element type must reflect any intermediate
modules between the base type and the specialization type, as shown in this example:
Figure 2-10. Example of @class attribute with intermediate value
<windowname class="- topic/keyword task/keyword guitask/windowname ">
The intermediate values are necessary so that generalizing and specializing transformations
can map values simply and accurately. For example, if task/keyword was missing as
a value,
and a user decided to generalize this guitask up to a task topic, then the transformation
would have to guess whether to map to keyword (appropriate if task is more general
than
guitask, which it is) or leave it as windowname (appropriate if task were more specialized,
which it isn't). By always providing mappings for more general values, processors
can then
apply the simple rule that missing mappings must by default be to more specialized
values
than the one we are generalizing to, which means the last value in the list is appropriate.
For example, when generalizing <guitask> to <task>, if a <p> element has no target
value for <task>, we can safely assume that <p> does not specialize from <task> and
should not be generalized.