RELAX NG: Coding requirements for document-type shells

A document-type shell integrates one or more topic type or map type modules, zero or more domain modules, and zero or more constraint modules.

Because RELAX NG modules are self-integrating, document-type shells only need to include vocabulary modules. Unlike DTDs, there is no separate specification required in order to integrate domain and nested topic elements into the base content models.

Root element declaration

Document type shells use the RELAX NG start declaration to specify the root element of the document type. The <start> element defines one root element, using a reference to a tagname.element pattern.

For example:
<div>
  <a:documentation>ROOT ELEMENT DECLARATION</a:documentation>
  <start combine="choice">
    <ref name="topic.element"/>
  </start>
</div>
DITA domains attribute

The document-type shell must list the domain or structural modules that are named as dependencies in the @domains attribute value. Unlike DTDs, a default value for @domains cannot automatically be constructed using RELAX NG facilities. Instead, the values used to construct @domains are taken from each vocabulary and constraint module, in addition to any domains contributions based on constraints implemented within the shell.

For example:
<div>
  <a:documentation>DOMAINS ATTRIBUTE</a:documentation>
  <define name="domains-att">
    <optional>
      <attribute name="domains"
                 a:defaultValue="(topic hazard-d)
                                 (topic hi-d)
                                 (topic indexing-d)
                                 (topic ut-d)
                                 a(props deliveryTarget)"
      />
    </optional>
  </define>
</div>
Content constraint integration

The document-type shell must include any constraint modules. Constraint modules include the module they override and override the patterns that they constrain directly in the constraint module itself. Any module that is constrained in this section (including the base topic or map modules) will be left out of the following section.

For example, when the following constraint is included for the task module, the task module itself will not be included in the shell; the task module itself is included within strictTaskbodyConstraintMod.rng:
<div>
<a:documentation>CONTENT CONSTRAINT INTEGRATION</a:documentation>
  <include href="strictTaskbodyConstraintMod.rng">
    <define name="task-info-types">
      <ref name="task.element"/>
    </define>            
  </include>
</div>
Module inclusions

The document-type shell must include any unconstrained domain or structural module. If the top-level map or topic type is unconstrained, it is also included in this section.

For example:
<div>
  <a:documentation>MODULE INCLUSIONS</a:documentation>
  <include href="topicMod.rng"/>
  <include href="highlightDomainMod.rng"/>
  <include href="utilitiesDomainMod.rng"/>
  <include href="indexingDomainMod.rng"/>
  <include href="hazardstatementDomainMod.rng"/>
</div>
Constraining domains in the shell

Domains can be constrained to disallow some extension elements without the use of a separate module file. This is done by overriding the base type pattern within the reference to the domain module. In this case, the constraint represented by the pattern redefinition still must be declared in the @domains attribute; the @domains contribution should be documented in the document-type shell with the constraint. There is not a designated section of the document-type shell for this type of constraint; it can be placed either in Content constraint integration or Module inclusions.

The following example demonstrates the portion of a document type shell that includes the highlight domain module while directly constraining that module to remove the <u> element. The <ditaarch:domainsContribution> element is used to document the @domains contribution for this constraint.

  <div>
    <a:documentation>MODULE INCLUSIONS</a:documentation>
    <include href="topicMod.rng"/>
    <include href="hazardstatementDomainMod.rng"/>
    <include href="highlightDomainMod.rng">
      <ditaarch:domainsContribution
        >(topic hi-d-noUnderline-c)</ditaarch:domainsContribution>
      <define name="u">
        <notAllowed></notAllowed>
      </define>
    </include>
    <include href="indexingDomainMod.rng"/>
    <include href="utilitiesDomainMod.rng"/>
  </div>
ID-defining element overrides

This section must declare any element in the document type that uses an @id attribute with an XML data type of "ID". This declaration is required in order to avoid errors from RELAX NG parsers that would otherwise complain about different uses of the @id attribute.

Typically, this section lists only a few elements, such as topic types or the <anchor> element, but it could include specializations that constrain @id. In addition, foreign vocabularies require you to include exclusions for the namespaces used by those domains.

For example, this section declares that <topic> and <task> use an @id attribute with an XML data type of ID, along with any elements in the SVG or MathML namespaces. Each of these is excluded from the "any" pattern by placing them within the <except> rule as shown below:
  <div>
      <a:documentation> ID-DEFINING-ELEMENT OVERRIDES </a:documentation>
      <define name="any">
         <zeroOrMore>
            <choice>
               <ref name="idElements"/>
               <element>
                  <anyName>
                     <except>
                        <name>topic</name>
                        <name>task</name>
                        <nsName ns="http://www.w3.org/2000/svg"/>
                        <nsName ns="http://www.w3.org/1998/Math/MathML"/>
                     </except>
                  </anyName>
                  <zeroOrMore>
                     <attribute>
                        <anyName/>
                     </attribute>
                  </zeroOrMore>
                  <ref name="any"/>
               </element>
               <text/>
            </choice>
         </zeroOrMore>
      </define>
  </div>