Last Updated: $Date: 2001/08/01 19:26:28 $
Copyright ©2001 W3C® (MIT, INRIA, Keio), All Rights Reserved. W3C liability, trademark, document use and software licensing rules apply.
XHTML Modularization provides a structure for the creation of new markup languages through the extension of the XHTML Core modules and the use of the XHTML Module Framework. In some instances, people will want to create complete, proprietary markup languages through these mechanisms. In other instances, people may wish to create new, reusable modules that will be used by their organization or by others in the definition of markup languages. In either case, the mechanics of the modules added and the markup language definition are the same. This document describes the manner in which such modules are defined, and the way in which modules should be combined to create new markup languages.
XHTML Modules are made up of at least two modules - a Qname Module and a Declaration Module. In this section we will walk through building each of these. In the next section we will use this new module with another XHTML-family module and some XHTML Core modules to define a new markup language.
An XHTML Qname Module should be constructed using the following process:
<!ENTITY % MODULE.myelement.qname "%MODULE.pfx;myelement" >
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 %MODULE.pfx prefix. For example:
<ENTITY % MODULE.img.myattr.qname "%MODULE.pfx;myattr" >
An XHTML Declaration Module should be constructed using the following process:
It is sometimes desirable to have an XHTML module also usable as a stand alone DTD. A good example of this might be a module that defines inventory items. These items need to be embeddable in an XHTML document, and also need to be available as free-standing documents extracted from a database (or something). The easiest way to accomplish this is to define a DTD file that instantiates the components of your module. Such a DTD would have this structure:
This DTD can then be referenced by documents that use only the elements from your module.
Once you have defined your module(s), you are going to want to combine them with XHTML and other modules to create a new markup language. Since in this document we are talking about building these markup languages using DTDs, what you need to do is define a DTD that reflects the markup language. In the remainder of this section, we will explore the process for creating such a "hybrid markup language".
A Model Module is an XHTML Module that defines the content model for your new markup language. This module can be extremely complex, or it can be as simple as the declaration of a parameter entity and the inclusion of some other Model Module. Regardless, the purpose is the same: Define the structure of all of the elements in your markup language.
Your markup language may include one or more additional XHTML-family Modules. Each of these Modules will have a Qname Module. The qualified names collection is a module in which all of the Qname Modules are instantiated, and the set of prefixed attributes are defined. Specifically, a qualified names collection module contains:
The driver is the actual file that is referenced by documents written in your new markup language. The driver may be complex or simple, depending upon the markup language. However, each XHTML-family markup language driver must contain the following elements in order to work well:
Now you are ready to go. Your new Markup Language, defined via a DTD, can be referenced in the DOCTYPE declaration of a document, and that document can be validated against your new DTD using common commercial and free-ware tools.
In the following sections, you will see examples of each type of module referred to in this document, as well as the components that make up two different markup language definitions.
This first qname module is for an inventory module. The second is for some extensions to the inventory module.
<!-- ...................................................................... --> <!-- Inventory Qname Module ................................................... --> <!-- file: inventory-qname-1.mod PUBLIC "-//MY COMPANY//ELEMENTS XHTML Inventory Qnames 1.0//EN" SYSTEM "http://www.my.org/DTDs/inventory-qname-1.mod" xmlns:inventory="http://www.my.org/xmlns/inventory" ...................................................................... --> <!-- Declare the default value for prefixing of this module's elements --> <!-- Note that the NS.prefixed will get overridden by the XHTML Framework or by a document instance. --> <!ENTITY % NS.prefixed "IGNORE" > <!ENTITY % Inventory.prefixed "%NS.prefixed;" > <!-- Declare the actual namespace of this module --> <!ENTITY % Inventory.xmlns "http://www.my.org/xmlns/inventory" > <!-- Declare the default prefix for this module --> <!ENTITY % Inventory.prefix "inventory" > <!-- Declare the prefix and any prefixed namespaces that are required by this module --> <![%Inventory.prefixed;[ <!ENTITY % Inventory.pfx "%Inventory.prefix;:" > <!ENTITY % Inventory.xmlns.extra.attrib "xmlns:%Inventory.prefix; %URI.datatype; #FIXED '%Inventory.xmlns;'" > ]]> <!ENTITY % Inventory.pfx "" > <!ENTITY % Inventory.xmlns.extra.attrib "" > <!ENTITY % XHTML.xmlns.extra.attrib "%Inventory.xmlns.extra.attrib;" > <!ENTITY % Inventory.shelf.qname "%Inventory.pfx;shelf" > <!ENTITY % Inventory.item.qname "%Inventory.pfx;item" > <!ENTITY % Inventory.desc.qname "%Inventory.pfx;desc" > <!ENTITY % Inventory.sku.qname "%Inventory.pfx;sku" > <!ENTITY % Inventory.price.qname "%Inventory.pfx;price" >
<!-- ...................................................................... --> <!-- Extension Qname Module ............................................... --> <!-- file: extension-qname-1.mod xmlns:invext="http://www.my.org/xmlns/invext" ...................................................................... --> <!-- Declare the default value for prefixing of this module's elements --> <!-- Note that the NS.prefixed will get overridden by the XHTML Framework or by a document instance. --> <!ENTITY % NS.prefixed "IGNORE" > <!ENTITY % Extension.prefixed "%NS.prefixed;" > <!-- Declare the actual namespace of this module --> <!ENTITY % Extension.xmlns "http://www.my.org/xmlns/invext" > <!-- Declare the default prefix for this module --> <!ENTITY % Extension.prefix "invext" > <!-- Declare the prefix and any prefixed namespaces that are required by this module --> <![%Extension.prefixed;[ <!ENTITY % Extension.pfx "%Extension.prefix;:" > <!ENTITY % Extension.xmlns.extra.attrib "xmlns:%Extension.prefix; %URI.datatype; #FIXED '%Extension.xmlns;'" > ]]> <!ENTITY % Extension.pfx "" > <!ENTITY % Extension.xmlns.extra.attrib "" > <!ENTITY % Extension.store.qname "%Extension.pfx;store" > <!ENTITY % Extension.aisle.qname "%Extension.pfx;aisle">
The first declaration module is for the inventory module elements. The second is for the extension elements.
<!-- ...................................................................... --> <!-- Inventory Elements Module ................................................... --> <!-- file: inventory-1.mod PUBLIC "-//MY COMPANY//ELEMENTS XHTML Inventory Elements 1.0//EN" SYSTEM "http://www.my.org/DTDs/inventory-1.mod" xmlns:inventory="http://www.my.org/xmlns/inventory" ...................................................................... --> <!-- Inventory Module item sku desc price This module defines a simple inventory item structure --> <!-- Define the global namespace attributes --> <![%Inventory.prefixed;[ <!ENTITY % Inventory.xmlns.attrib "%NS.decl.attrib;" > ]]> <!ENTITY % Inventory.xmlns.attrib "%NS.decl.attrib; xmlns %URI.datatype; #FIXED '%Inventory.xmlns;'" > <!ELEMENT %Inventory.shelf.qname; ( %Inventory.item.qname; )* > <!ATTLIST %Inventory.shelf.qname; location CDATA #IMPLIED %Inventory.xmlns.attrib; > <!ELEMENT %Inventory.item.qname; ( %Inventory.desc.qname;, %Inventory.sku.qname;, %Inventory.price.qname;) > <!ATTLIST %Inventory.item.qname; location CDATA #IMPLIED %Inventory.xmlns.attrib; > <!ELEMENT %Inventory.desc.qname; ( #PCDATA ) > <!ATTLIST %Inventory.desc.qname; %Inventory.xmlns.attrib; > <!ELEMENT %Inventory.sku.qname; ( #PCDATA ) > <!ATTLIST %Inventory.sku.qname; %Inventory.xmlns.attrib; > <!ELEMENT %Inventory.price.qname; ( #PCDATA ) > <!ATTLIST %Inventory.price.qname; %Inventory.xmlns.attrib; > <!-- end of inventory-1.mod -->
<!-- ...................................................................... --> <!-- Extension Elements Module ................................................... --> <!-- file: extension-1.mod SYSTEM "extension-1.mod" xmlns:invext="http://www.my.org/xmlns/invext" ...................................................................... --> <!-- Extension Module store aisle This module defines an extension to the inventory structure --> <!-- Define the global namespace attributes --> <![%Extension.prefixed;[ <!ENTITY % Extension.xmlns.attrib "%NS.decl.attrib;" > ]]> <!ENTITY % Extension.xmlns.attrib "%NS.decl.attrib; xmlns %URI.datatype; #FIXED '%Extension.xmlns;'" > <!ELEMENT %Extension.store.qname; ( %Extension.aisle.qname; )* > <!ATTLIST %Extension.store.qname; name CDATA #IMPLIED %Extension.xmlns.attrib; > <!ELEMENT %Extension.aisle.qname; ( %Inventory.shelf.qname; )* > <!ATTLIST %Extension.aisle.qname; number CDATA #IMPLIED %Extension.xmlns.attrib; > <!-- end of extension-1.mod -->
This markup language complies with all of the requirements for an XHTML family markup language. It uses the XHTML Core Modules, and extends that with the Inventory and Inventory Extensions modules defined above.
<!-- Bring in the inventory qualified names --> <!ENTITY % Inventory-qname.mod PUBLIC "-//MY COMPANY//ENTITIES XHTML Inventory Qnames 1.0//EN" "inventory-qname-1.mod" > %Inventory-qname.mod; <!-- Bring in the local extension module --> <!ENTITY % Extension-qname.mod SYSTEM "extension-qname-1.mod" > %Extension-qname.mod; <!-- Define the xmlns extension attributes --> <!ENTITY % XHTML.xmlns.extra.attrib "%Inventory.xmlns.extra.attrib; %Extension.xmlns.extra.attrib;" >
<!-- ...................................................................... --> <!-- Inventory Extension Model Module .................................... --> <!-- file: xhtml-invext-model-1.mod SYSTEM "xhtml-invext-model-1.mod" ...................................................................... --> <!-- Define the content model for Misc.extra --> <!ENTITY % Misc.class "| %script.qname; | %noscript.qname; | %Extension.store.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 "| %tt.qname; | %i.qname; | %b.qname; | %big.qname; | %small.qname; | %sub.qname; | %sup.qname;" > <!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 "" > <!-- %Block.class; includes all block elements, used as an component in mixes --> <!ENTITY % Block.class "%Blkstruct.class; %Blkphras.class; %Blkpres.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;" > <!-- end of xhtml-invext-model-1.mod -->
<!-- ....................................................................... --> <!-- Inventory Extension DTD .............................................. --> <!-- file: xhtml-invext-1.dtd --> <!-- This is the DTD driver for inventory extension 1.0. Please use this formal public identifier to identify it: "-//MY COMPANY//DTD XHTML Inventory Extension 1.0//EN" And this namespace for extension-unique elements: xmlns:inventory="http://www.my.org/xmlns/invext" Other namespaces are also included. --> <!ENTITY % XHTML.version "-//MY COMPANY//DTD XHTML Inventory Extension 1.0//EN" > <!-- Define the xhtml qualified names module to be ours --> <!ENTITY % xhtml-qname-extra.mod SYSTEM "xhtml-invext-qname-1.mod" > <!-- reserved for use with document profiles --> <!ENTITY % XHTML.profile "" > <!-- Define the Content Model for the framework to use --> <!ENTITY % xhtml-model.mod SYSTEM "xhtml-invext-model-1.mod" > <!-- Disable bidirectional text support --> <!ENTITY % XHTML.bidi "INCLUDE" > <!-- Bring in the XHTML Framework --> <!ENTITY % xhtml-framework.mod PUBLIC "-//W3C//ENTITIES XHTML Modular Framework 1.0//EN" "http://www.w3.org/TR/xhtml-modularization/DTD/xhtml-framework-1.mod" > %xhtml-framework.mod; <!-- Text Module (Required) ............................... --> <!ENTITY % xhtml-text.mod PUBLIC "-//W3C//ELEMENTS XHTML Text 1.0//EN" "http://www.w3.org/TR/xhtml-modularization/DTD/xhtml-text-1.mod" > %xhtml-text.mod; <!-- Hypertext Module (required) ................................. --> <!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; <!-- Lists Module (required) .................................... --> <!ENTITY % xhtml-list.mod PUBLIC "-//W3C//ELEMENTS XHTML Lists 1.0//EN" "http://www.w3.org/TR/xhtml-modularization/DTD/xhtml-list-1.mod" > %xhtml-list.mod; <!-- Inventory Module ........................................ --> <!ENTITY % Inventory-elements.mod SYSTEM "inventory-1.mod" > %Inventory-elements.mod; <!-- Inventory Extension Module .............................. --> <!ENTITY % Invext-elements.mod SYSTEM "extension-1.mod" > %Invext-elements.mod; <!-- XHTML Images module ........................................ --> <!ENTITY % xhtml-image.mod PUBLIC "-//W3C//ELEMENTS XHTML Images 1.0//EN" "http://www.w3.org/TR/xhtml-modularization/DTD/xhtml-image-1.mod" > %xhtml-image.mod; <!-- Document Metainformation Module ............................ --> <!ENTITY % xhtml-meta.mod PUBLIC "-//W3C//ELEMENTS XHTML Metainformation 1.0//EN" "xhtml-meta-1.mod" > %xhtml-meta.mod; <!-- Document Structure Module (required) ....................... --> <!ENTITY % xhtml-struct.mod PUBLIC "-//W3C//ELEMENTS XHTML Document Structure 1.0//EN" "http://www.w3.org/TR/xhtml-modularization/DTD/xhtml-struct-1.mod" > %xhtml-struct.mod;
This example uses the new markup language in its default form - with no prefixes being defined for any module.
<!DOCTYPE html SYSTEM "xhtml-invext-1.dtd" > <html xmlns="http://www.w3.org/1999/xhtml" > <head> <title>An example using defaults</title> </head> <body> <p>This is content in the XHTML namespace</p> <shelf> <item> <desc> this is a description. </desc> <sku> this is the price. </sku> <price> this is the price. </price> </item> </shelf> </body> </html>
This example uses the new markup language with prefixes enabled for just the inventory and extension components.
r!DOCTYPE html SYSTEM "xhtml-invext-1.dtd" [ <!ENTITY % Inventory.prefixed "INCLUDE"> <!ENTITY % Inventory.prefix "i"> ]> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:i="http://www.my.org/xmlns/inventory" > <head> <title>An example using prefixes</title> </head> <body> <p>This is content in the XHTML namespace</p> <i:shelf> <i:item> <i:desc> this is a description. </i:desc> <i:sku> this is the sku. </i:sku> <i:price> this is the price. </i:price> </i:item> </i:shelf> </body> </html>
This example places a prefix on every element.
<!DOCTYPE x:html SYSTEM "xhtml-invext-1.dtd" [ <!ENTITY % NS.prefixed "INCLUDE"> <!ENTITY % XHTML.prefix "x" > <!ENTITY % Inventory.prefix "i"> ]> <x:html xmlns:x="http://www.w3.org/1999/xhtml" xmlns:i="http://www.my.org/xmlns/inventory" > <x:head> <x:title>An example using prefixes</x:title> </x:head> <x:body> <x:p>This is content in the XHTML namespace</x:p> <i:shelf> <i:item> <i:desc> this is a description. </i:desc> <i:sku> this is the sku. </i:sku> <i:price> this is the price. </i:price> </i:item> </i:shelf> </x:body> </x:html>