Removing Elements

DocBook has a large number of elements. In some authoring environments, it may be useful or necessary to remove some of these elements.

Removing MsgSet

MsgSet is a favorite target. It has a complex internal structure designed for describing interrelated error messages, especially on systems that may exhibit messages from several different components. Many technical documents can do without it, and removing it leaves one less complexity to explain to your authors.

Example 5-2 shows a customization layer that removes the MsgSet element from DocBook:

Example 5-2. Removing MsgSet


<!ENTITY % compound.class "Procedure|SideBar"> (1)
<!ENTITY % msgset.content.module "IGNORE">     (2)
<!-- load DocBook -->
<!ENTITY % DocBookDTD PUBLIC "-//OASIS//DTD DocBook V3.1//EN">
%DocBookDTD;
(1)
Remove MsgSet from the compound.class. This is the only place in the DTD where MsgSet is referenced.
(2)
Exclude the definition of MsgSet and all of its subelements from the DTD.

Removing Computer Inlines

DocBook contains a large number of computer inlines. The DocBook inlines define a domain-specific vocabulary. If you're working in another domain, many of them may be unnecessary. You can remove a bunch of them by redefining the tech.char.class parameter entity and then excluding the declarations for the elements removed. The initial definition of tech.char.class is:


<!ENTITY % tech.char.class
    "Action|Application|ClassName|Command|ComputerOutput
    |Database|Email|EnVar|ErrorCode|ErrorName|ErrorType|Filename
    |Function|GUIButton|GUIIcon|GUILabel|GUIMenu|GUIMenuItem
    |GUISubmenu|Hardware|Interface|InterfaceDefinition|KeyCap
    |KeyCode|KeyCombo|KeySym|Literal|Markup|MediaLabel|MenuChoice
    |MouseButton|MsgText|Option|Optional|Parameter|Prompt|Property
    |Replaceable|ReturnValue|SGMLTag|StructField|StructName
    |Symbol|SystemItem|Token|Type|UserInput
    %local.tech.char.class;">

When examining this list, it seems that you can delete all of the inlines except, perhaps, Application, Command, Email, Filename, Literal, Replaceable, Symbol, and SystemItem. The following customization layer removes them.

Example 5-3. Removing Computer Inlines


<!ENTITY % tech.char.class
        "Application|Command|Email|Filename|Literal
        |Replaceable|Symbol|SystemItem">
<!ENTITY % action.module "IGNORE">
<!ENTITY % classname.module "IGNORE">
<!ENTITY % computeroutput.module "IGNORE">
<!ENTITY % database.module "IGNORE">
<!ENTITY % envar.module "IGNORE">
<!ENTITY % errorcode.module "IGNORE">
<!ENTITY % errorname.module "IGNORE">
<!ENTITY % errortype.module "IGNORE">
<!--<!ENTITY % function.module "IGNORE">-->
<!ENTITY % guibutton.module "IGNORE">
<!ENTITY % guiicon.module "IGNORE">
<!ENTITY % guilabel.module "IGNORE">
<!ENTITY % guimenu.module "IGNORE">
<!ENTITY % guimenuitem.module "IGNORE">
<!ENTITY % guisubmenu.module "IGNORE">
<!ENTITY % hardware.module "IGNORE">
<!ENTITY % interface.module "IGNORE">
<!ENTITY % interfacedefinition.module "IGNORE">
<!--<!ENTITY % keycap.module "IGNORE">-->
<!ENTITY % keycode.module "IGNORE">
<!--<!ENTITY % keycombo.module "IGNORE">-->
<!--<!ENTITY % keysym.module "IGNORE">-->
<!ENTITY % markup.module "IGNORE">
<!ENTITY % medialabel.module "IGNORE">
<!ENTITY % menuchoice.module "IGNORE">
<!--<!ENTITY % mousebutton.module "IGNORE">-->
<!--<!ENTITY % msgtext.module "IGNORE">-->
<!--<!ENTITY % option.module "IGNORE">-->
<!--<!ENTITY % optional.module "IGNORE">-->
<!--<!ENTITY % parameter.module "IGNORE">-->
<!ENTITY % prompt.module "IGNORE">
<!ENTITY % property.module "IGNORE">
<!ENTITY % returnvalue.module "IGNORE">
<!ENTITY % sgmltag.module "IGNORE">
<!ENTITY % structfield.module "IGNORE">
<!ENTITY % structname.module "IGNORE">
<!ENTITY % token.module "IGNORE">
<!ENTITY % type.module "IGNORE">
<!ENTITY % userinput.module "IGNORE">
<!-- load DocBook --> 
<!ENTITY % DocBookDTD PUBLIC "-//OASIS//DTD DocBook V3.1//EN">
%DocBookDTD;

Initially we removed several more elements from tech.char.class (function.module, keycap.module), but using the testing procedure described in the Section called Testing Your Work, we discovered that these elements are used in other content models. Because they are used in other content modules, they cannot simply be removed from the DTD by deleting them from tech.char.class. Even though they can't be deleted outright, we've taken them out of most inline contexts.

It's likely that a customization layer that removed this many technical inlines would also remove some larger technical structures (MsgSet, FuncSynopsis), which allows you to remove additional elements from the DTD.

Removing Synopsis Elements

Another possibility is removing the complex Synopsis elements. The customization layer in Example 5-4 removes CmdSynopsis and FuncSynopsis.

Example 5-4. Removing CmdSynopsis and FuncSynopsis


<!ENTITY % synop.class "Synopsis">
<!-- Instead of "Synopsis|CmdSynopsis|FuncSynopsis %local.synop.class;" -->

<!ENTITY % funcsynopsis.content.module "IGNORE">
<!ENTITY % cmdsynsynopsis.content.module "IGNORE">

<!-- load DocBook --> 
<!ENTITY % DocBookDTD PUBLIC "-//OASIS//DTD DocBook V3.1//EN">
%DocBookDTD;

Completely removing all Synopsis elements would require a more extensive customization. You can't make any of the *.class parameter entities completely empty without changing all of the parameter entities that use them. See the Section called Removing an Entire Class.

Removing Sectioning Elements

Perhaps you want to restrict your authors to only three levels of sectioning. To do that, you must remove the Sect4 and Sect5 elements, as shown in Example 5-5.

Example 5-5. Removing Sect4 and Sect5 Elements

<!ENTITY % sect3.module "IGNORE">
<!ENTITY % sect4.module "IGNORE">
<!ENTITY % sect5.module "IGNORE">

<!ENTITY % DocBookDTD PUBLIC "-//OASIS//DTD DocBook V3.1//EN">
%DocBookDTD;

<!ENTITY % local.sect3.attrib "">
<!ENTITY % sect3.role.attrib "%role.attrib;">
<!ELEMENT Sect3 - O (Sect3Info?, (%sect.title.content;), (%nav.class;)*,
                (((%divcomponent.mix;)+, 
                ((%refentry.class;)* | SimpleSect*))
                | (%refentry.class;)+ | SimpleSect+), (%nav.class;)*)>
<!ATTLIST Sect3
                --
                Renderas: Indicates the format in which the heading should
                appear
                --
                Renderas        (Sect1
                                |Sect2
                                |Sect4
                                |Sect5)         #IMPLIED
                %label.attrib;
                %status.attrib;
                %common.attrib;
                %sect3.role.attrib;
                %local.sect3.attrib;
>


In order to completely remove an element that isn't in the information pool, it is usually necessary to redefine the elements that include it. In this case, because we're removing the Sect4 element, we must redefine the Sect3 element that uses it.

Removing Admonitions from Table Entries

All of the customization layers that we've examined so far have been fairly straightforward. This section describes a much more complex customization layer. Back in the Section called DocBook Modules we mentioned that several additional modules existed for "redeclaration." The customization layer developed in this section cannot be written without them.

The goal is to remove admonitions (Warning, Caution, Note) from table entries.

Example 5-6 is a straightforward, and incorrect, attempt.

Example 5-6. Removing Admonitions (First Attempt: Incorrect)


<!-- THIS CUSTOMIZATION LAYER CONTAINS ERRORS -->
<!ENTITY % tabentry.mix
        "%list.class;
        |%linespecific.class;
        |%para.class;        |Graphic
        %local.tabentry.mix;">
<!-- load DocBook -->
<!ENTITY % DocBookDTD PUBLIC "-//OASIS//DTD DocBook V3.1//EN">
%DocBookDTD;
Because the parameter entity tabentry.mix defines the mixture of elements allowed in table entries, you should remove admonitions.

If you attempt to parse this DTD, you'll find that the declaration of tabentry.mix contains errors. While you can redefine parameter entities, you cannot make reference to entities that have not been defined yet, so the use of list.class, linespecific.class, and so on, aren't allowed.

Your second attempt might look like Example 5-7.

Example 5-7. Removing Admonitions (Second Attempt: Incorrect)


<!-- THIS CUSTOMIZATION LAYER DOESN'T WORK -->
<!-- load DocBook -->
<!ENTITY % DocBookDTD PUBLIC "-//OASIS//DTD DocBook V3.1//EN">
%DocBookDTD;
<!ENTITY % tabentry.mix
        "%list.class;
        |%linespecific.class;
        |%para.class;        |Graphic
        %local.tabentry.mix;">
Declaring tabentry.mix after the DTD has been loaded removes the errors.

This example contains no errors, but it also doesn't have any effect. Remember, only the first entity declaration counts, so the declaration of tabentry.mix in dbpool.mod is the one used, not your redeclaration.

The only way to fix this problem is to make use of one of the redeclaration placeholders in DocBook.

Redeclaration placeholders are spots in which you can insert definitions into the middle of the DTD. There are four redeclaration placeholders in DocBook:

rdbmods

Inserted in docbook.dtd, between dbpool.mod and dbhier.mod. This placeholder is controlled by the intermod.redecl.module marked section.

rdbpool

Inserted in the middle of dbpool.mod, between the *.class and *.mix entity declarations. This placeholder is controlled by the dbpool.redecl.module marked section.

rdbhier

Inserted in the middle of dbhier.mod, between the *.class and *.mix entity declarations. This placeholder is controlled by the dbhier.redecl.module marked section.

rdbhier2

Also inserted into dbhier.mod, after the *.mix entity declarations. This placeholder is controlled by the dbhier.redecl2.module marked section.



Use the redeclaration placeholder that it occurs nearest to, but before the entity that you want to redeclare. In our case, this is rdbpool, as seen in Example 5-8.

Example 5-8. Removing Admonitions (Third Attempt: Correct, if confusing)


<!ENTITY % dbpool.redecl.module "INCLUDE">
<!ENTITY % rdbpool
'<!ENTITY % local.tabentry.mix "">
<!ENTITY % tabentry.mix
        "&#37;list.class;
        |&#37;linespecific.class;
        |&#37;para.class;        |Graphic
        &#37;local.tabentry.mix;">'>

<!-- load DocBook -->
<!ENTITY % DocBookDTD PUBLIC "-//OASIS//DTD DocBook V3.1//EN">
%DocBookDTD;


Example 5-8 uses numeric character entity references to escape the % signs in the entity declarations and nests an entity declaration in another parameter entity. All of this is perfectly legal, but a bit confusing. A clearer solution, and the only practical solution if you're doing anything more than a single redeclaration, is to place the new declarations in another file and include them in your customization layer by reference, like this:

Example 5-9. Removing Admonitions (Fourth Attempt: Correct)

In your customization layer:


<!ENTITY % dbpool.redecl.module "INCLUDE">
<!ENTITY % rdbpool SYSTEM "rdbpool.mod">

<!-- load DocBook -->
<!ENTITY % DocBookDTD PUBLIC "-//OASIS//DTD DocBook V3.1//EN">
%DocBookDTD;

In rdbpool.mod:

<!ENTITY % local.tabentry.mix "">
<!ENTITY % tabentry.mix
        "%list.class;
        |%linespecific.class;
        |%para.class;        |Graphic
        %local.tabentry.mix;">

Removing an Entire Class

Perhaps the modification that you want to make is to completely remove an entire class of elements. (If you have no need for synopsis elements of any sort, why not remove them?) In order to remove an entire class of elements, you must not only redefine the class as empty, but you must also redefine all of the parameter entities that use that class. The customization layer below completely removes the synop.class from DocBook. It requires a customization layer, shown in Example 5-10, that includes both a redeclaration module in dbpool.mod and a redeclaration module in dbhier.mod.

Example 5-10. Removing synop.class

In the customization layer:

<!ENTITY % synop.class "">

<!ENTITY % dbpool.redecl.module "INCLUDE">
<!ENTITY % rdbpool SYSTEM "remv.synop.class.rdbpool.mod">

<!ENTITY % dbhier.redecl.module "INCLUDE">
<!ENTITY % rdbhier SYSTEM "remv.synop.class.rdbhier.mod">

<!-- load DocBook --> 
<!ENTITY % DocBookDTD PUBLIC "-//OASIS//DTD DocBook V3.1//EN"> 
%DocBookDTD;

In remv.synop.class.rdbpool.mod:

<!ENTITY % local.component.mix "">
<!ENTITY % component.mix
                "%list.class;           |%admon.class;
                |%linespecific.class;
                |%para.class;           |%informal.class;
                |%formal.class;         |%compound.class;
                |%genobj.class;         |%descobj.class;
                %local.component.mix;">

<!ENTITY % local.sidebar.mix "">
<!ENTITY % sidebar.mix
                "%list.class;           |%admon.class;
                |%linespecific.class;
                |%para.class;           |%informal.class;
                |%formal.class;         |Procedure
                |%genobj.class;
                %local.sidebar.mix;">

<!ENTITY % local.footnote.mix "">
<!ENTITY % footnote.mix
                "%list.class;
                |%linespecific.class;
                |%para.class;           |%informal.class;
                %local.footnote.mix;">

<!ENTITY % local.example.mix "">
<!ENTITY % example.mix
                "%list.class;
                |%linespecific.class;
                |%para.class;           |%informal.class;
                %local.example.mix;">

<!ENTITY % local.admon.mix "">
<!ENTITY % admon.mix
                "%list.class;
                |%linespecific.class;
                |%para.class;           |%informal.class;
                |%formal.class;         |Procedure|Sidebar
                |Anchor|BridgeHead|Comment
                %local.admon.mix;">

<!ENTITY % local.figure.mix "">
<!ENTITY % figure.mix
                "%linespecific.class;
                                        |%informal.class;
                %local.figure.mix;">

<!ENTITY % local.glossdef.mix "">
<!ENTITY % glossdef.mix
                "%list.class;
                |%linespecific.class;
                |%para.class;           |%informal.class;
                |%formal.class;
                |Comment
                %local.glossdef.mix;">

<!ENTITY % local.para.char.mix "">
<!ENTITY % para.char.mix
                "#PCDATA
                |%xref.char.class;      |%gen.char.class;
                |%link.char.class;      |%tech.char.class;
                |%base.char.class;      |%docinfo.char.class;
                |%other.char.class;     |%inlineobj.char.class;
                %local.para.char.mix;">

In remv.synop.class.rdbhier.mod:

<!ENTITY % local.divcomponent.mix "">
<!ENTITY % divcomponent.mix
                "%list.class;           |%admon.class;
                |%linespecific.class;
                |%para.class;           |%informal.class;
                |%formal.class;         |%compound.class;
                |%genobj.class;         |%descobj.class;
                %local.divcomponent.mix;">

<!ENTITY % local.refcomponent.mix "">
<!ENTITY % refcomponent.mix
                "%list.class;           |%admon.class;
                |%linespecific.class;
                |%para.class;           |%informal.class;
                |%formal.class;         |%compound.class;
                |%genobj.class;         |%descobj.class;
                %local.refcomponent.mix;">

<!ENTITY % local.indexdivcomponent.mix "">
<!ENTITY % indexdivcomponent.mix
                "ItemizedList|OrderedList|VariableList|SimpleList
                |%linespecific.class;
                |%para.class;           |%informal.class;
                |Anchor|Comment
                |%link.char.class;
                %local.indexdivcomponent.mix;">