Hacking and specialization
The most complex type of modification you can make to the DITA OT is specialization. A strict interpretation of the DITA OT documentation would hold that “specialization” means creating an entirely new topic type based on an existing topic type. However, in the spirit of hacking the DITA OT, it is possible to change, add, or remove any of the sub-elements within a given topic type.
Specialization provides support for content that isn’t handled in standard DITA topic specializations (concept, task, and reference). Specializations themselves can range from adding new -elements to existing topics all the way up to the complete implementation of a new topic type.
The reasons for modifying or specializing the DITA OT include:
- Refining a set of elements. You might want to enforce a particular order for a set of elements.
- Defining new elements that clarify or better identify certain pieces of content. The example shown below involves adding an ingredient list to the <prereq> element in a task topic.
- Greater semantic accuracy. Specialization allows you to attach specific names to elements. These semantic elements will aid your content creators in making decisions about what goes where.
- Providing formatting information. Sometimes the organization of content doesn’t follow neat rules that can be codified in the XSL transforms. Sometimes a human needs to indicate where something happens, which cannot be deduced automatically.
It is possible to create most aspects of a specialization by modifying the existing files in the DITA OT. As your work progresses, you can move your changes to a separate set of files and create a DITA plugin. When you get to the level of creating new topic types, you usually need to create dtd files that reflect your topic type, and unless you’re interested in diving down into the inner workings of DITA OT, it’s usually best to add these with a plugin.
Building a specialized structure
Because specialization affects the structure of your topics, it means that you will need to modify your DTDs. As described before in this paper, there are a number of levels at which you can change your DTDs. The hacker’s solution is to modify existing dtd files (the dtd files actually define the domain integration and then point to the mod files, where the structure is formally defined). There are more formal strategies in which you create a new set of dtd and mod files and add them to the DITA catalog. Unfortunately there isn’t room to discuss catalog modifications in this paper.
The following example adds a new <ilist> (ingredient list) element to the task topic <prereq> element. The DITA Language Reference indicates that <prereq> contains text data, a number of standard in-line elements, and several block elements, such as <p>, <ul>, and <ol>. We will specialize the <ul> element to create our <ilist> element. The <ilist> can contain one or more <ingr> (ingredient) element; <ingr> is an element specialization of the <li> element.
| NOTE: | When you specialize an element, the content model for the new element can only contain elements, or specializations of the elements, that are in the content model of the original element. That is, you cannot add new element types that do not exist in the content model of the original element. |
To find out where to modify the structure, search the ditaot/dtd folder for the file in which <prereq> is defined. The file is task.mod.
There are three areas in task.mod that require changes: adding entity declarations for the new elements, modifying and adding new content models, and adding inheritance information about the new elements.
Near the top of the file is an area labeled “ELEMENT NAME ENTITIES.” Find this section and scroll to the last of the entity declarations. After the last entity declaration, add a comment indicating the purpose of the modifications, and then add entity declarations for the two new -elements:
<!-- Added new elements for ingredient lists -->
<!ENTITY % ilist>
<!ENTITY % ingr"ingr">
| NOTE: | The percent sign (%) in the entity declaration indicates this is a parameter entity, which is used only in the DTD. |
It’s a good idea to add your changes at the end of each section in the dtd and mod files. That way you can locate your changes quickly.
A number of lines below the entity declarations are the element declarations. Scroll down until you find the declaration for the <prereq> element.
<!ELEMENT prereq (%section.notitle.cnt;)* >
Copy and paste the declaration line and comment one of the copies (that way you can remember what you changed). Modify the other declaration, adding the changes shown here in bold (the line that is commented out is also shown).
<!-- <!ELEMENT prereq (%section.notitle.cnt;)* >
-->
<!ELEMENT prereq ( %section.notitle.cnt; | %ilist; )* >
Note that a more sophisticated change would entail finding the definition of section.notitle.cnt and adding the <ilist> element to that definition.
At the end of the other element declarations, add the content model declarations for the <ilist> and <ingr> elements:
<!-- LONG NAME: Ingredient List -->
<!ELEMENT ilist (%ingr;)+ >
<!ATTLIST ilist
%univ-atts;
outputclass CDATA #IMPLIED >
<!-- LONG NAME: Ingredient Item -->
<!ELEMENT ingr (%listitem.cnt;)* >
<!ATTLIST ingr
%univ-atts;
outputclass CDATA #IMPLIED >
These declarations were modeled on declarations of <ul> and <li> found in commonElements.mod. Because < ingr> and <li> both use the entity listitem.cnt for their content, the <ingr> element can contain the same content elements as the <li> element.
At the bottom of the file, under “SPECIALIZATION ATTRIBUTE DECLARATIONS,” add inheritance information for the new elements. Again, make your changes at the end of these declarations, so that you can find them more easily.
<!-- Inheritance for ingredient list -->
<!ATTLIST ilist %global-atts; class CDATA "- topic/ul
task/ilist " >
<!ATTLIST ingr %global-atts; class CDATA "- topic/li
task/ingr " >
Because <ilist> inherits from <ul> and <ingr> inherits from <li>, it’s not necessary to create an XSL template that handles <ilist> and <ingr>. The DITA OT will process this list as if it were a standard <ul> element.
Testing the modification
To test the modification, you need a file that employs the <ilist> element.
Use the following XML to create a new file in ditaot/samples/tasks named bubbleformula.xml:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE task PUBLIC "-//OASIS//DTD DITA Task//EN"
"../../dtd/task.dtd">
<task id="bubbles" xml:lang="en-us">
<title>Big Bubble formula</title>
<shortdesc>Entertain your kids with this great recipe for big bubbles.</shortdesc>
<taskbody>
<prereq>Gather these ingredients:
<ilist>
<ingr>1 gallon tap water</ingr>
<ingr>2/3 cup liquid detergent</ingr>
<ingr>1 Tbsp glycerine</ingr>
</ilist></prereq>
<context>
<p>Using a suitable container, such as a bucket:</p>
</context>
<steps>
<step><cmd>Mix the glycerine with the water.</cmd></step>
<step><cmd>Carefully add in the liquid detergent.</cmd></step>
<step><cmd>Gently stir the mixture, so as not to create too many bubbles.</cmd></step>
<step><cmd>Allow to sit for 24 hours.</cmd></step>
</steps>
<postreq>Use a large hoop to create spectacular bubbles.</postreq>
</taskbody>
<related-links>
<link href="../concepts/waterhose.xml" format="dita" type="concept">
<linktext>Water hose</linktext>
</link>
</related-links>
</task>
Edit ditaot/samples/hierarchy.ditamap and add a new <topicref> element that references the new bubbleformula.xml file (shown in bold):
...
<topicref href="tasks/washingthecar.xml" type="task"/>
<topicref href="tasks/bubbleformula.xml" type="task"/>
</topicref>
Run the DITA OT and check the log file for errors. Now you can view your specialized topic:

Now you can apply all that you’ve learned in this paper to create CSS and XSL transform rules to handle <ilist> and <ingr> uniquely.
Next Page:
Summary
