Tutorial: Specializing DITA Conditional Attributes
A new feature in DITA 1.1 is the ability to specialize from the base= and props= attributes. For conditional processing, this lets you add your own attributes rather than using otherprops=, which can be clearer to authors and implementors. [NOTE: at the time of writing the DITA Open Toolkit does not implement support for specializations of props=, but it should be added soon.]
This form of specialization is fairly easy to implement. This tutorial shows you how to do it using DTDs (the mechanism using Schemas is essentially the same and if you've stepped up to using the DITA 1.1 schemas I'm going presume you can figure this out on your own).
The specialization requires two things:
1. Modification of any shell DTDs that need to reflect the specialized attribute (e.g., topic.dtd, reference.dtd, or your own specialized topic types' shell DTDs). You integrate the specialization attribute domain through the shell DTDs.
2. For each specialization of props=, a .ent declaration set that defines the attribute and a corresponding domain declaration. This is the "attribute domain specialization module".
Note that as a rule, any production use of DITA will likely require local versions of the DITA-provided shell DTDs, if only to do configuration of the domains you need, so unless you are using DITA very informally, you should already have local copies of all the DITA-provided shell DTDs. Just saying.
For this tutorial we want to create a specialization of "props=" called "phase-of-moon" that takes as its value one or more moon phase names (e.g., "full", "new", "waning", "waxing", etc.). We will call our domain "moonPhaseProp". (Domains must have unique names within the scope of the shell DTDs or schemas that use them.)
For organizing the files, I like to create a separate directory to put my local shell DTDs and specializations in. For this tutorial assume we're putting everything in the directory dtd/myspecs within the normal DITA Open Toolkit distribution structure. (It can go anywhere as long as you configure the entity resolution catalogs appropriately, but for initial development and testing I find it convenient to use relative paths to the various declaration components as that eliminates a variable from the configuration (resolution via catalogs) that can lead to confusing errors. Once you've established that the declarations are correct you should replace all relative paths with absolute URLs or (if you must) PUBLIC IDs that are resolved via catalogs. For my development work I use the OxygenXML editor, which makes it easy to set up catalog configurations for testing resolution via catalogs (and generally testing the correctness of all the parts). Similar tools like XML Spy are probably comparable (but I don't use them).
Step 1 is to create the attribute domain declaration:
1.a. Create a file named moonPhasePropsDomain.ent
1.b. In that file, create these two declarations:
The first declaration declares the "phase-of-moon=" attribute and puts it in a parameter entity so we can add it to the DITA-defined
<!ENTITY % moon-phase-props-d-attribute
%selection-attsparameter entity via the
%props-attribute-extensionsconfiguration parameter entity.
The second declaration is the domain declaration string for the attribute domain. It will be added to the value of the "domains=" attribute declared for each topic-type element type.
You should of course add an appropriate descriptive header to the file as well as a little documentation for the attribute itself.
This is all that is required for the attribute domain module.
Step 2 is to integrate the domain into your local copy of each shell DTD. The pattern is the same for each shell. For this tutorial I'm using a copy of the topic.dtd shell.
2.a. Find the comment that reads "DOMAIN ATTRIBUTE DECLARATIONS". Following that comment, add this declaration:
<!ENTITY % moon-phase-props-d-decThis pulls in the attribute domain module.
2.b. Find the comment that reads "DOMAIN ATTRIBUTE EXTENSIONS". Following that comment you should see a declaration for the
%props-attribute-extensionsparameter entity. It will probably be declared as an empty string.
Modify the entity replacement text to include a reference to the
<!ENTITY % props-attribute-extensionsThis adds the "phase-of-moon=" attribute to the
%selection-attsparameter entity which is then included in the
%univ-attsparameter entity, making this new attribute available on most elements (some elements, such as title, are not selection candidates).
2.c. Find the comment that reads "DOMAINS ATTRIBUTE OVERRIDE". Following that you should see the declaration of the text entity
included-domainsand it should include references to a number of "x-d-att" text entities.
To this entity add a reference to the
<!ENTITY included-domainsThis formally declares your props= attribute specialization so that DITA 1.1 processors will know that "phase-of-moon=" is in fact a conditional attribute and that they should filter on it as appropriate.
That's all there is to it. Now just repeat Step 2 for each shell DTD you use and you're done.
Step 3 is to test your declarations to make sure they work. This is simply a matter of creating an XML document that uses your local shell DTD as its DTD and verifying that the "phase-of-moon=" attribute is now available on all elements that allow the selection attributes.