XHTML 1.1 divides the three XHTML DTDs into individual modules. Parameter entities connect the modules by including or leaving out particular modules. Modules include:
%xhtml-struct.module;
The absolute bare minimum of elements needed for an HTML
document: html
, head
, title
, and body
%xhtml-text.module;
The basic elements that contain text and other inline
elements: abbr
, acronym
, address
, blockquote
, br
, cite
, code
, dfn
, div
, em
, h1
, h2
, h3
, h4
, h5
, h6
, kbd
, p
, pre
, q
, samp
, span
, strong
, and var
%xhtml-hypertext.module;
Elements used for linking, that is, the a
element
%xhtml-list.module;
Elements used for the three kinds of lists: dl
, dt
, dd
, ul
, ol
, and li
%xhtml-applet.module;
%xhtml-pres.module;
Presentation oriented markup, that is, the b
, big
, hr
, i
, small
, sub
, sup
, and tt
elements
%xhtml-edit.module;
Elements for revision tracking: del
and ins
%xhtml-bdo.module;
An indication of directionality when text in left-to-right languages, like English and French, is mixed with text in right-to-left languages, like Hebrew and Arabic
%xhtml-basic-form.module;
Forms as defined in HTML 3.2 using the form
, input
, select
, option
, and textarea
elements
%xhtml-form.module;
Forms as defined in HTML 4.0 using the form
, input
, select
, option
, textarea
, button
, fieldset
, label
, legend
, and optgroup
elements
%xhtml-basic-table.module;
Minimal table support including only the table
, caption
, th
, tr
, and td
elements
%xhtml-table.module;
More complete table support including not only the
table
, caption
, th
, tr
, and td
elements, but also the col
, colgroup
, tbody
, thead
, and tfoot
elements
%xhtml-image.module;
%xhtml-csismap.module;
The map
and area
elements, as well as extra
attributes for several other elements needed to support
client-side image maps
%xhtml-ssismap.module;
Doesn't provide any new elements, but adds the ismap
attribute to the img
element
%xhtml-object.module;
The object
element used to embed executable content like Java applets and
ActiveX controls in web pages
%xhtml-param.module;
The param
element
used to pass parameters from web pages to their
embedded executable content, such as Java applets and ActiveX
controls
%xhtml-frames.module;
The elements needed to implement frames including
frame
, frameset
, and noframes
%xhtml-iframe.mod;
The iframe
element used
for inline frames
%xhtml-events.module;
Attributes to support scripting like onsubmit
and onfocus
that are attached to elements
declared in other modules
%xhtml-meta.module;
%xhtml-script.module;
Elements that support JavaScript and VBScript: script
and noscript
%xhtml-style.module;
%xhtml-link.module;
The link
element that specifies relationships to various external
documents, such as translations, glossaries, and previous and
next pages
%xhtml-base.module;
The base
element that specifies a URL against which relative URLs are
resolved
%xhtml-target.module;
The target
attribute that specifies the destination frame or window of a
link
%xhtml-inlstyle.module;
The style
attribute that applies CSS styles to individual elements in the
document
%xhtml-nameident.module;
The name
attribute, a deprecated earlier version of the id
attribute
%xhtml-legacy.module;
Deprecated elements and attributes including the
basefont
, center
, font
, s
, strike
, and u
elements
%xhtml11-ruby.module;
The ruby
,
rbc
, rtc
, rb
, rt
, and rp
elements used in East Asian text to
place small amounts of text next to body text, generally
indicating pronunciation
The advantage to dividing HTML into all these different modules is that you can pick and choose the pieces you want. If your documents use tables, include the Tables module. If your documents don't use tables, then leave it out. You get only the functionality you actually need.
For example, let's suppose you're designing a DTD for a
catalog. Each item in the catalog is a catalog_entry
element. Each catalog_entry
contains a name
, price
, item_number
, color
, size
, and various other common elements
you're likely to find in catalogs. Furthermore, each catalog_entry
contains a description
of the item. The description
contains formatted narrative
text. In other words, it looks something like this:
<catalog_entry> <name>Aluminum Duck Drainer</name> <price>34.99</price> <item_number>54X8</item_number> <color>silver</color> <size>XL</size> <description> <p> This sturdy <strong>silver</strong> colored sink stopper dignifies the <em>finest kitchens</em>. It makes a great gift for </p> <ul> <li>Christmas</li> <li>Birthdays</li> <li>Mother's Day</li> </ul> <p>and all other occasions!</p> </description> </catalog_entry>
It's easy enough to write this markup. The tricky part is validating it. Rather than reinventing a complete DTD to describe all the formatting that's needed in straightforward narrative descriptions, you can reuse XHTML. The XHTML 1.1 DTD makes heavy use of parameter entity references to define content specifications and attribute lists for the different elements. Three entity references are of particular note:
%Inline.mix;
A choice containing all the elements that don't
generally require a line break, such as em
, a
, and q
. That is, it resolves to:
br | span | em | strong | dfn | code | samp | kbd | var | cite | abbr | acronym | q | tt | i | b | big | small | sub | sup | bdo | a | img | map | applet | ruby | input | select | textarea | label | button | ins | del | script | noscript
%Block.mix;
A choice containing all the elements that
generally require a line break, like p
, blockquote
, and ul
. That is, it resolves to:
h1 | h2 | h3| h4 | h5 | h6| ul| ol| dl| p | div | pre| blockquote | address | hr | table | form | fieldset | ins | del | script | noscript
%Flow.mix;
A choice containing both of the previous; that is, it resolves to:
h1 | h2 | h3 | h4 | h5 | h6 | ul | ol | dl | p | div | pre | blockquote | address | hr | table | form | fieldset | br | span | em | strong | dfn | code | samp | kbd | var | cite | abbr | acronym | q | tt | i | b | big | small | sub | sup | bdo | a | img | map | applet | ruby | input | select | textarea | label | button | ins | del | script | noscript
You can declare that the description
element contains essentially
any legal XHTML fragment, like this:
<!ENTITY % xhtml PUBLIC "-//W3C//DTD XHTML 1.1//EN" "xhtml11.dtd"> %xhtml; <!ELEMENT description (#PCDATA | %Flow.mix;)*>
If you wanted to require description
to contain only block elements
at the top level, you'd instead declare it like this:
<!ENTITY % xhtml PUBLIC "-//W3C//DTD XHTML 1.1//EN" "xhtml11.dtd"> %xhtml; <!ELEMENT description ((%Block.mix;)*)>
The first two lines import the XHTML driver DTD from a relative URL. You can get this
DTD and the other local files it depends on from the zip archive at
http://www.w3.org/TR/xhtml11/xhtml11.zip. The
second line uses an entity reference defined in that DTD to set the
content specification for the description
element.
The XHTML 1.1 driver DTD imports modules from two other W3C specifications, Modularization of XHTML (http://www.w3.org/TR/xhtml-modularization) and Ruby Annotation (http://www.w3.org/TR/ruby), using absolute URLs that point to the W3C's web site. If you're not reliably connected to the Internet at high speed, you might want to use the flat version of this DTD, xhtml11-flat.dtd, instead. This bundles all the different modules in a single file.
Unfortunately, this goes a little too far. It includes not
only the pieces of HTML you want, such as p
, em
,
and ul
, but also a lot of
elements you don't want in a printed catalog, such as a
, applet
, map
, and a lot more. However, you can omit
these. The main XHTML DTD imports each module inside an INCLUDE
/IGNORE
block, such as this one for the
hypertext module:
<!-- Hypertext Module (required) ................................. --> <!ENTITY % xhtml-hypertext.module "INCLUDE" > <![%xhtml-hypertext.module;[ <!ENTITY % xhtml-hypertext.mod PUBLIC "-//W3C//ELEMENTS XHTML Hypertext 1.0//EN" "http://www.w3.org/TR/xhtml-modularization/DTD/xhtml-hypertext-1.mod" > %xhtml-hypertext.mod;]]>
If the %xhtml-hypertext.module;
parameter entity
reference has previously been defined as IGNORE
instead of INCLUDE
, that declaration takes
precedence; all the elements and attributes defined in the Hypertext
module (specifically, the a
element) are left out of the resulting DTD.
Let's say you just want the Structure, Basic Text, and List
modules. Then you use a driver DTD that redefines the parameter
entity references for the other modules as IGNORE
. Example 7-4 demonstrates.
Example 7-4. A catalog DTD that uses basic XHTML but omits a lot of elements
<!ELEMENT catalog (catalog_entry*)> <!ELEMENT catalog_entry (name, price, item_number, color, size, description)> <!ELEMENT name (#PCDATA)> <!ELEMENT size (#PCDATA)> <!ELEMENT price (#PCDATA)> <!ELEMENT item_number (#PCDATA)> <!ELEMENT color (#PCDATA)> <!-- throw away the modules we don't need --> <!ENTITY % xhtml-hypertext.module "IGNORE" > <!ENTITY % xhtml-ruby.module "IGNORE" > <!ENTITY % xhtml-edit.module "IGNORE" > <!ENTITY % xhtml-pres.module "IGNORE" > <!ENTITY % xhtml-applet.module "IGNORE" > <!ENTITY % xhtml-param.module "IGNORE" > <!ENTITY % xhtml-bidi.module "IGNORE" > <!ENTITY % xhtml-form.module "IGNORE" > <!ENTITY % xhtml-table.module "IGNORE" > <!ENTITY % xhtml-image.module "IGNORE" > <!ENTITY % xhtml-csismap.module "IGNORE" > <!ENTITY % xhtml-ssismap.module "IGNORE" > <!ENTITY % xhtml-meta.module "IGNORE" > <!ENTITY % xhtml-script.module "IGNORE" > <!ENTITY % xhtml-style.module "IGNORE" > <!ENTITY % xhtml-link.module "IGNORE" > <!ENTITY % xhtml-base.module "IGNORE" > <!-- import the XHTML DTD, at least those parts we aren't ignoring. You will probably need to change the system ID to point to whatever directory you've stored the DTD in. --> <!ENTITY % xhtml11.mod PUBLIC "-//W3C//DTD XHTML 1.1//EN" "xhtml11/DTD/xhtml11.dtd"> %xhtml11.mod; <!ELEMENT description ( %Block.mix; )+>
An even more important feature of Modular XHTML is the
option to add new elements that HTML doesn't support. For instance,
to include SVG pictures in your documents, you just have to import
the SVG DTD and redefine the Misc.extra
parameter entity to allow the
SVG root element svg
. (This only
lets you validate XHTML documents that contain SVG markup. It
doesn't magically give the browser the ability to render these
pictures.) You accomplish this by redefining any of these three
parameter entity references:
%Inline.extra;
Place the root elements of your application here
if you want them to be added to the content specifications of
inline elements, such as span
, em
, code
, and textarea
.
%Block.extra;
Place the root elements of your application here
if you want them to be added to the content specifications of
block elements, such as div
, h1
, p
, and pre
.
%Misc.extra;
Place the root elements of your application here if you want them to be added to the content specifications of both block and inline elements.
The definition of each of these parameter entities should be a
list of the elements you want to add to the content specification
separated by vertical bars and beginning with a vertical bar. For
instance, to include MathML equations as both inline and block
elements, you'd import the MathML DTD and redefine the Misc.extra
parameter entity to include the
MathML root element math
like
this:
<!ENTITY % Misc.extra "| math">
If you wanted to allow block-level MathML equations and SVG
pictures, you'd import their respective DTDs and redefine the
Block.extra
parameter entity like
this:
<!ENTITY % Block.extra "| math | svg">
Order is important here. The MathML DTD and the Block.extra
declaration both have to be
parsed before the XHTML DTD is parsed. Example 7-5 demonstrates with a
DTD that mixes MathML 1.0 and XHTML, throwing in a namespace
declaration for good measure.
Example 7-5. A DTD that mixes MathML into XHTML and MathML
<!ENTITY % mathml SYSTEM "mathml/mathml.dtd"> %mathml; <!ATTLIST math xmlns CDATA #FIXED "http://www.w3.org/1998/Math/MathML"> <!ENTITY % Misc.extra "| math"> <!ENTITY % xhtml PUBLIC "-//W3C//DTD XHTML 1.1//EN" "xhtml11/DTD/xhtml11.dtd"> %xhtml;
You can also mix new elements like math
into individual elements like
p
without changing all the other
block elements. The content specification for each XHTML element is
defined by a parameter entity named
Element
.content
, for example, %p.content;
, %em.content;
, %td.content;
and so forth. The standard
definition of p.content
looks
like this:
<!ENTITY % p.content "( #PCDATA | %Inline.mix; )*" >
To allow the math
element
to be a child of p
elements, but
not of every other block element, you would redefine p.content
like this:
<!ENTITY % p.content "( #PCDATA | %Inline.mix; | math )*" >
The XHTML 1.1 DTD is quite sophisticated. There are a lot more tricks you can play by mixing and matching different parts of the DTD, mostly by defining and redefining different parameter entity references. The easiest way to learn about these is by reading the raw DTDs. In many cases, the comments in the DTD are more descriptive and accurate than the prose specification.
The XHTML 1.1 DTD does not include all of the modules that are available. For instance, frames and the legacy presentational elements are deliberately omitted and cannot easily be turned on. This is the W3C's not-so-subtle way of telling you that you shouldn't be using these elements in the first place. If you do want to use them, you'll need to create your own complete DTD using the individual modules you require.
To do this, you must first define the namespace URI and
prefixed names for your elements and attributes. The W3C provides a template you can adapt for this purpose
at http://www.w3.org/TR/xhtml-modularization/DTD/templates/template-qname-1.mod.
Example 7-6 demonstrates
with a DTD fragment that defines the names for the today
and quoteoftheday
elements that one of the
authors (Harold) uses on his web sites. The module is based on the
W3C-provided template.
Example 7-6. A DTD module to define the today and quoteoftheday elements' names and namespaces
<!-- ........................................................... --> <!-- CafeML Qualified Names Module ............................. --> <!-- file: cafe-qname-1.mod This is an extension of XHTML, a reformulation of HTML as a modular XML application. This DTD module is identified by the PUBLIC and SYSTEM identifiers: PUBLIC "-//Elliotte Rusty Harold//ELEMENTS CafeML Qualified Names 1.0//EN" "cafe-qname-1.mod" ........................................................... --> <!-- NOTES: Using the CafeML Qualified Names Extension This is a module for a markup language 'CafeML', which currently declares two extension elements, quoteoftheday and today. The parameter entity naming convention uses uppercase for the entity name and lowercase for namespace prefixes, hence this example uses 'CAFEML' and 'cafeml' respectively. Please note the three case variants: 'CafeML' the human-readable markup language name 'CAFEML' used as a parameter entity name prefix 'cafeml' used as the default namespace prefix The %NS.prefixed; conditional section keyword must be declared as "INCLUDE" in order to allow prefixing to be used. --> <!-- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: --> <!-- CafeML Qualified Names This module is contained in two parts, labeled Section 'A' and 'B': Section A declares parameter entities to support namespace- qualified names, namespace declarations, and name prefixing for CafeML. Section B declares parameter entities used to provide namespace-qualified names for all CafeML element types. The recommended step-by-step program for creating conforming modules is enumerated below, and spans both the CafeML Qualified Names Template and CafeML Extension Template modules. --> <!-- Section A: CafeML XML Namespace Framework :::::::::::::::::::: --> <!-- 1. Declare a %CAFEML.prefixed; conditional section keyword, used to activate namespace prefixing. The default value should inherit '%NS.prefixed;' from the DTD driver, so that unless overridden, the default behavior follows the overall DTD prefixing scheme. --> <!ENTITY % NS.prefixed "IGNORE" > <!ENTITY % CAFEML.prefixed "%NS.prefixed;" > <!-- 2. Declare a parameter entity (e.g., %CAFEML.xmlns;) containing the URI reference used to identify the Module namespace: --> <!ENTITY % CAFEML.xmlns "http://www.cafeconleche.org/xmlns/cafeml" > <!-- 3. Declare parameter entities (e.g., %CAFEML.prefix;) containing the default namespace prefix string(s) to use when prefixing is enabled. These may be overridden in the DTD driver or the internal subset of a document instance. If no default prefix is desired, this may be declared as an empty string. NOTE: As specified in [XMLNAMES], the namespace prefix serves as a proxy for the URI reference and is not in itself significant. --> <!ENTITY % CAFEML.prefix "cafeml" > <!-- 4. Declare parameter entities (e.g., %CAFEML.pfx;) containing the colonized prefix(es) (e.g., '%CAFEML.prefix;:') used when prefixing is active, an empty string when it is not. --> <![%CAFEML.prefixed;[ <!ENTITY % CAFEML.pfx "%CAFEML.prefix;:" > ]]> <!ENTITY % CAFEML.pfx "" > <!-- 5. The parameter entity %CAFEML.xmlns.extra.attrib; may be redeclared to contain any non-CafeML namespace declaration attributes for namespaces embedded in CafeML. When prefixing is active it contains the prefixed xmlns attribute and any namespace declarations embedded in CafeML, otherwise an empty string. --> <![%CAFEML.prefixed;[ <!ENTITY % CAFEML.xmlns.extra.attrib "xmlns:%CAFEML.prefix; %URI.datatype; #FIXED '%CAFEML.xmlns;'" > ]]> <!ENTITY % CAFEML.xmlns.extra.attrib "" > <!ENTITY % XHTML.xmlns.extra.attrib "%CAFEML.xmlns.extra.attrib;" > <!-- Section B: CafeML Qualified Names ::::::::::::::::::::::::::::: --> <!-- This section declares parameter entities used to provide namespace-qualified names for all CafeML element types. --> <!-- module: cafe-1.mod --> <!ENTITY % CAFEML.quoteoftheday.qname "%CAFEML.pfx;quoteoftheday" > <!ENTITY % CAFEML.today.qname "%CAFEML.pfx;today" > <!-- end of cafe-qname-1.mod -->
Next you have to define the elements and attributes with these
names in a module of your own creation. The W3C provides a template, which you can adapt for this
purpose, at http://www.w3.org/TR/xhtml-modularization/DTD/templates/template-1.mod.
This template uses the same techniques and follows the same patterns
as XHTML's built-in modules, for example, parameter entity
references that resolve to INCLUDE
or IGNORE
.
Example 7-7
demonstrates with a DTD fragment that defines the today
and quoteoftheday
elements. The today
element can contain any block-level
content through the Block.mix
parameter entity and has a required date
attribute. The quoteoftheday
element always contains
exactly one blockquote
element
followed by exactly one p
element
with no attributes.
Example 7-7. A DTD module to define the today and quoteoftheday elements
<!-- ............................................................ --> <!-- CAFEML Extension Template Module ........................... --> <!-- file: CafeML-1.mod This is an extension of XHTML, a reformulation of HTML as a modular XML application. This DTD module is identified by the PUBLIC and SYSTEM identifiers: PUBLIC "Elliotte Rusty Harold//ELEMENTS CafeML Qualified Names 1.0//EN" SYSTEM "CafeML-1.mod" Revisions: (none) ........................................................... --> <!-- Extension Template This sample template module declares two extension elements, today and quoteoftheday. The parameter entity naming convention uses uppercase for the entity name and lowercase for namespace prefixes. Hence this example uses 'CAFEML' and 'cafe' respectively. This module declares parameter entities used to provide namespace-qualified names for all CAFEML element types, as well as an extensible framework for attribute-based namespace declarations on all element types. The %NS.prefixed; conditional section keyword must be declared as "INCLUDE" in order to allow prefixing to be used. By default, foreign (i.e., non-XHTML) namespace modules should inherit %NS.prefixed; from XHTML, but this can be overridden when prefixing of only the non-XHTML markup is desired. XHTML's default value for the 'namespace prefix' is an empty string. The Prefix value can be redeclared either in a DTD driver or in a document's internal subset as appropriate. NOTE: As specified in [XMLNAMES], the namespace prefix serves as a proxy for the URI reference and is not in itself significant. --> <!-- ................................................................ --> <!-- 1. Declare the xmlns attributes used by CAFEML dependent on whether CAFEML's prefixing is active. This should be used on all CAFEML element types as part of CAFEML's common attributes. If the entire DTD is namespace-prefixed, CAFEML should inherit %NS.decl.attrib;. Otherwise it should declare %NS.decl.attrib; plus a default xmlns attribute on its own element types. --> <![%CAFEML.prefixed;[ <!ENTITY % CAFEML.xmlns.attrib "%NS.decl.attrib;" > ]]> <!ENTITY % CAFEML.xmlns.attrib "xmlns %URI.datatype; #FIXED '%CAFEML.xmlns;'" > <!-- now include the module's various markup declarations ........ --> <!ENTITY % CAFEML.Common.attrib "%CAFEML.xmlns.attrib; id ID #IMPLIED" > <!-- 2. In the attribute list for each element, declare the XML Namespace declarations that are legal in the document instance by including the %NamespaceDecl.attrib; parameter entity in the ATTLIST of each element type. --> <!ENTITY % CAFEML.today.qname "today" > <!ELEMENT %CAFEML.today.qname; ( %Flow.mix; )* > <!ATTLIST %CAFEML.today.qname; %CAFEML.Common.attrib; date CDATA #REQUIRED > <!ENTITY % CAFEML.quoteoftheday.qname "quoteoftheday" > <!ELEMENT %CAFEML.quoteoftheday.qname; ( %blockquote.qname;, %p.qname; ) > <!ATTLIST %CAFEML.quoteoftheday.qname; %CAFEML.Common.attrib; > <!-- 3. If the module adds attributes to elements defined in modules that do not share the namespace of this module, declare those attributes so that they use the %CAFEML.pfx; prefix. For example: <!ENTITY % CAFEML.img.myattr.qname "%CAFEML.pfx;myattr" > <!ATTLIST %img.qname; %CAFEML.img.myattr.qname; CDATA #IMPLIED > This would add a myattr attribute to the img element of the Image Module, but the attribute's name will be the qualified name, including prefix, when prefixes are selected for a document instance. We do not need to do this for this module. --> <!-- end of CafeML-1.mod -->
Next you need to write a document model module that defines the parameter entities used for content specifications in the various modules—not only the CafeML modules, but the XHTML modules as well. (This is how your elements become part of the various XHTML elements.) The W3C does not provide a template for this purpose. However, it's normally easy to adapt the document model module from either XHTML 1.1 or XHTML Basic to include your new elements. Example 7-8 is a document model module based on the XHTML 1.1 document model module.
Example 7-8. A document model module for CafeML
<!-- ............................................................ --> <!-- CafeML Model Module ....................................... --> <!-- file: CafeML-model-1.mod PUBLIC "-//Elliotte Rusty Harold//ELEMENTS XHTML CafeML Model 1.0//EN" SYSTEM "CafeML-model-1.mod" xmlns:cafeml="http://www.cafeconleche.org/xmlns/cafeml" ............................................................ --> <!-- Define the content model for Misc.extra --> <!ENTITY % Misc.extra "| %CAFEML.today.qname; | %CAFEML.quoteoftheday.qname; "> <!-- .................... Inline Elements ..................... --> <!ENTITY % HeadOpts.mix "( %meta.qname; )*" > <!ENTITY % I18n.class "" > <!ENTITY % InlStruct.class "%br.qname; | %span.qname;" > <!ENTITY % InlPhras.class "| %em.qname; | %strong.qname; | %dfn.qname; | %code.qname; | %samp.qname; | %kbd.qname; | %var.qname; | %cite.qname; | %abbr.qname; | %acronym.qname; | %q.qname;" > <!ENTITY % InlPres.class "" > <!ENTITY % Anchor.class "| %a.qname;" > <!ENTITY % InlSpecial.class "| %img.qname; " > <!ENTITY % Inline.extra "" > <!-- %Inline.class; includes all inline elements, used as a component in mixes --> <!ENTITY % Inline.class "%InlStruct.class; %InlPhras.class; %InlPres.class; %Anchor.class; %InlSpecial.class;" > <!-- %InlNoAnchor.class; includes all non-anchor inlines, used as a component in mixes --> <!ENTITY % InlNoAnchor.class "%InlStruct.class; %InlPhras.class; %InlPres.class; %InlSpecial.class;" > <!-- %InlNoAnchor.mix; includes all non-anchor inlines --> <!ENTITY % InlNoAnchor.mix "%InlNoAnchor.class; %Misc.class;" > <!-- %Inline.mix; includes all inline elements, including %Misc.class; --> <!ENTITY % Inline.mix "%Inline.class; %Misc.class;" > <!-- ..................... Block Elements ...................... --> <!ENTITY % Heading.class "%h1.qname; | %h2.qname; | %h3.qname; | %h4.qname; | %h5.qname; | %h6.qname;" > <!ENTITY % List.class "%ul.qname; | %ol.qname; | %dl.qname;" > <!ENTITY % BlkStruct.class "%p.qname; | %div.qname;" > <!ENTITY % BlkPhras.class "| %pre.qname; | %blockquote.qname; | %address.qname;" > <!ENTITY % BlkPres.class "| %hr.qname;" > <!ENTITY % Block.extra "" > <!ENTITY % Table.class "| %table.qname;" > <!ENTITY % BlkSpecial.class "%Table.class;" > <!-- %Block.class; includes all block elements, used as an component in mixes --> <!ENTITY % Block.class "%BlkStruct.class; %BlkPhras.class; %BlkPres.class; %BlkSpecial.class; %Block.extra;" > <!-- %Block.mix; includes all block elements plus %Misc.class; --> <!ENTITY % Block.mix "%Heading.class; | %List.class; | %Block.class; %Misc.class;" > <!-- ................ All Content Elements .................. --> <!-- %Flow.mix; includes all text content, block and inline --> <!ENTITY % Flow.mix "%Heading.class; | %List.class; | %Block.class; | %Inline.class; %Misc.class;" > <!-- special content model for pre element --> <!ENTITY % pre.content "( #PCDATA | %Inline.class; )*" > <!-- end of CafeML-model-1.mod -->
Finally, replace the standard XHTML DTD, which only imports the normal XHTML modules, with a new one that imports the standard modules you want as well as any new modules you've defined. Again, the W3C offers a template for this purpose, which you can download from http://www.w3.org/TR/xhtml-modularization/DTD/templates/template.dtd. This template is a minimal DTD that makes the necessary imports and declares the necessary parameter entity references upon which all the other modules depend. Example 7-9 is a DTD based on this template. It merges in the element module defined in Example 7-7, as well as the standard XHTML tables, images, meta, and block presentation modules.
Example 7-9. An XHTML DTD that mixes in the Cafe DTD
<!-- ................................................................. --> <!-- XHTML + CafeML DTD ............................................. --> <!-- file: CafeML.dtd --> <!-- CafeML DTD --> <!-- Please use this formal public identifier to identify it: "-//Elliotte Rusty Harold//DTD XHTML CafeDTD//EN" --> <!ENTITY % XHTML.version "-//W3C//DTD XHTML CafeDTD//EN" > <!-- Bring in any qualified name modules outside of XHTML --> <!ENTITY % CAFEML-qname.mod SYSTEM "cafe-qname-1.mod"> %CAFEML-qname.mod; <!-- Define any extra prefixed namespaces that this DTD relies upon --> <!ENTITY NS.prefixed.extras.attrib "" > <!-- Define the Content Model file for the framework to use --> <!ENTITY % xhtml-model.mod SYSTEM "CafeML-model-1.mod" > <!-- reserved for future use with document profiles --> <!ENTITY % XHTML.profile "" > <!-- Bi-directional text support This feature-test entity is used to declare elements and attributes used for internationalization support. Set it to INCLUDE or IGNORE as appropriate for your markup language. --> <!ENTITY % XHTML.bidi "IGNORE" > <!-- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: --> <!-- Pre-Framework Redeclaration placeholder .................... --> <!-- This serves as a location to insert markup declarations into the DTD prior to the framework declarations. --> <!ENTITY % xhtml-prefw-redecl.module "IGNORE" > <![%xhtml-prefw-redecl.module;[ %xhtml-prefw-redecl.mod; <!-- end of xhtml-prefw-redecl.module -->]]> <!-- The events module should be included here if you need it. In this skeleton it is IGNOREd. --> <!ENTITY % xhtml-events.module "IGNORE" > <!-- Modular Framework Module ................................... --> <!ENTITY % xhtml-framework.module "INCLUDE" > <![%xhtml-framework.module;[ <!ENTITY % xhtml-framework.mod PUBLIC "-//W3C//ENTITIES XHTML 1.1 Modular Framework 1.0//EN" "xhtml-framework-1.mod" > %xhtml-framework.mod;]]> <!-- Post-Framework Redeclaration placeholder ................... --> <!-- This serves as a location to insert markup declarations into the DTD following the framework declarations. --> <!ENTITY % xhtml-postfw-redecl.module "IGNORE" > <![%xhtml-postfw-redecl.module;[ %xhtml-postfw-redecl.mod; <!-- end of xhtml-postfw-redecl.module -->]]> <!-- Text Module (required) ............................... --> <!ENTITY % xhtml-text.module "INCLUDE" > <![%xhtml-text.module;[ <!ENTITY % xhtml-text.mod PUBLIC "-//W3C//ELEMENTS XHTML 1.1 Text 1.0//EN" "xhtml-text-1.mod" > %xhtml-text.mod;]]> <!-- Hypertext Module (required) ................................. --> <!ENTITY % xhtml-hypertext.module "INCLUDE" > <![%xhtml-hypertext.module;[ <!ENTITY % xhtml-hypertext.mod PUBLIC "-//W3C//ELEMENTS XHTML 1.1 Hypertext 1.0//EN" "xhtml-hypertext-1.mod" > %xhtml-hypertext.mod;]]> <!-- Lists Module (required) .................................... --> <!ENTITY % xhtml-list.module "INCLUDE" > <![%xhtml-list.module;[ <!ENTITY % xhtml-list.mod PUBLIC "-//W3C//ELEMENTS XHTML 1.1 Lists 1.0//EN" "xhtml-list-1.mod" > %xhtml-list.mod;]]> <!-- Your modules can be included here. Use the basic form defined above, and be sure to include the public FPI definition in your catalog file for each module that you define. You may also include W3C-defined modules at this point. --> <!-- CafeML Module (custom module) ....................... --> <!ENTITY % cafeml.module "INCLUDE" > <![%cafeml.module;[ <!ENTITY % cafeml.mod PUBLIC "-//Cafe con Leche//XHTML Extensions today 1.0//EN" "CafeML-1.mod" > %cafeml.mod;]]> <!-- Tables Module (optional) ....................... --> <!ENTITY % xhtml-table.module "INCLUDE" > <![%xhtml-table.module;[ <!ENTITY % xhtml-table.mod PUBLIC "-//W3C//ELEMENTS XHTML Tables 1.0//EN" "xhtml-table-1.mod" > %xhtml-table.mod;]]> <!-- Meta Module (optional) ....................... --> <!ENTITY % xhtml-meta.module "INCLUDE" > <![%xhtml-meta.module;[ <!ENTITY % xhtml-meta.mod PUBLIC "-//W3C//ELEMENTS XHTML Meta 1.0//EN" "xhtml-meta-1.mod" > %xhtml-meta.mod;]]> <!-- Image Module (optional) ....................... --> <!ENTITY % xhtml-image.module "INCLUDE" > <![%xhtml-image.module;[ <!ENTITY % xhtml-image.mod PUBLIC "-//W3C//ELEMENTS XHTML Images 1.0//EN" "xhtml-image-1.mod" > %xhtml-image.mod;]]> <!-- Block Presentation Module (optional) ....................... --> <!ENTITY % xhtml-blkpres.module "INCLUDE" > <![%xhtml-blkpres.module;[ <!ENTITY % xhtml-blkpres.mod PUBLIC "-//W3C//ELEMENTS XHTML Block Presentation 1.0//EN" "xhtml-blkpres-1.mod" > %xhtml-blkpres.mod;]]> <!-- Document Structure Module (required) ....................... --> <!ENTITY % xhtml-struct.module "INCLUDE" > <![%xhtml-struct.module;[ <!ENTITY % xhtml-struct.mod PUBLIC "-//W3C//ELEMENTS XHTML 1.1 Document Structure 1.0//EN" "xhtml-struct-1.mod" > %xhtml-struct.mod;]]> <!-- end of CAFEML DTD .............................................. --> <!-- ................................................................. -->