D. DTD Modules bouwen

Inhoud

Deze appendix is normatief.

XHTML modules worden geïmplementeerd als DTD fragmenten. Wanneer deze fragmenten op een specifieke mannier samengebracht worden (omschreven in DTD's ontwerpen met gedefinieerde en uitbreidingsmodules), is de resulterende DTD een representatie van een compleet document type. Deze representatie kan dan gebruikt worden voor validatie van gevallen van het document type.

De sleutel in combinatie van deze fragmenten in een betekenisvolle DTD zijn de regels die gebruikt worden om de fragmenten te definiëren. Dit deel definieert deze regels. Als deze regels gevolgd worden, kunnen DTD auteurs er zeker van zijn dat hun modules op een zuivere manier zullen interfacen met andere XHTML-compatiebele modules.

Modules conform aan deze regels moeten ook voldoen aan de conformiteitseisen gedefinieerd in XHTML Family Module Conformiteit opdat ze XHTML Family Modules genoemd kunnen worden.

D.1. Parameter Entiteits Naamgeving

Deze specificatie classificeert parameter entiteiten in zeven categorieën en benoemt deze op consequente manier door het gebruik van de volgende achtervoegsels:

.mod
parameter entiteiten gebruiken het achtervoegsel .mod als ze gebruikt worden om een DTD module (een collectie van elementen, attributen, parameter entiteiten, enz) te representeren. In deze specificatie is elke module een atomaire eenheid en kan voorgesteld worden als een afzonderlijk bestand.
.module
parameter entiteiten gebruiken het achtervoegsel .module als ze gebruikt worden om de opname van een DTD module te controleren door één van beide conditionele sectie sleutelwoorden INCLUDE of IGNORE op te nemen.
.qname
parameter entiteiten gebruiken het achtervoegsel .qname als ze gebruikt worden om de bevoegde naam van een element voor te stellen. Raadpleeg Definitie van de Namespace van een Module voor meer informatie over bevoegde namen.
.content
parameter entiteiten gebruiken het achtervoegsel .content als ze gebruikt worden om het inhoudsmodel van een element type voor te stellen.
.class
parameter entiteiten gebruiken het achtervoegsel .class als ze gebruikt worden om elementen van dezelfde class voor te stellen.
.mix
parameter entiteiten gebruikten het achtervoegsel .mix als ze gebruikt worden om een verzameling van element types van verschillende classes voor te stellen.
.attrib
parameter entiteiten gebruiken het achtervoegsel .attrib als ze gebruikt worden om een groep van tokens voor te stellen die één of meer complete attribuutspecificaties voorstellen binnen een ATTLIST declaratie.

In HTML 4 wordt de %block; parameter entiteit bijvoorbeeld gedefinieerd om de heterogene collectie van element types voor te stellen die block-level elementen zijn. In deze specificatie is de overeenkomende parameter entiteit %Block.mix;.

Wanneer parameter entiteiten gedefinieerd worden in de classes die hier gedefinieerd worden, zouden de modules de namen van de entiteiten moeten omvatten door unieke voorvoegsels te gebruiken. Het inhoudsmodel voor het element mijnelement in de module mijnmodule zou MIJNMODULE.mijnelement.inhoud genoemd kunnen worden. Andere schema's zijn mogelijk. Onafhankelijk van het gebruikte scheam zouden module auteurs ernaar moeten streven dat parameter entiteiten die ze definië:ren uniek benoemd worden zodat ze niet botsen met andere parameter entiteiten en zodat de interface methodes voor de module duidelijk zijn voor de gebruikers ervan.

D.2. Definitie van de Namespace van een Module

XHTML vereist dat de elementen en attributen die gedeclareerd worden in een module in een gedefinieerde XML namespace [XMLNAMES] zitten. De identificatie van deze namespace is een willekeurige URI. XHTML vereist dat wanneer een module geïmplementeerd wordt door gebruik van een XML DTD, de module de namespace declareert op een speciale mannier. Het doel hiervan is de selectie toelaten, in document parse/validatie tijd, van het gebruik van namespace voorvoegsels en van het voorvoegsel dat gebruikt wordt om elementen en attributen van de module te identificeren.

Inhoudontwikkelaars die documenten wensen te ontwerpen gebaseerd op hybride document types kunnen kiezen om XML namespace voorvoegsels te gebruiken op elementen van de XHTML namespace, op elementen van andere namespaces of op beide. Om te verzekeren dat zulke documenten XHTML conform zijn en backward compatible aijn met niet-namespace bewuste toepassingen, beveelt W3C aan dat inhoudontwikkelaars geen XML namespace voorvoegsels gebruiken op elementen van de XHTML namespace. Als inhoudontwikkelaars interesse hebben om hun inhoud verwerkt te laten worden door namespace-bewuste processors, raad W3C verder aan dat elementen in niet-XHTML namespaces gespecificeerd worden door gebruik van een XML namespace voorvoegsel in plaats van vertrouwen op standaard XML namespace mechanismen.

Elke XHTML-conforme module geïmplementeerd als een XML DTD moet een standaard XML namespace voorvoegsel definiëren, een methode voor wijziging van dit voorvoegsel binnen een document en een kenmerkend deel dat zich baseert op de verwerking van het voorvoegsel.

Merk op dat het geldig is en verwacht wordt dat meerdere modules deel uitmaken van dezelfde namespace als ze gerelateerd zijn. Alle XHTML modules zijn bijvoorbeeld deel van dezelfde namespace.

D.2.1. Kwalificerende Names sub-module

Om te beginnen moet je een kwalificerende names sub-module definiëren (een sub-module is enkel een bestand entiteit die gescheiden is zodat het opgenomen kan worden in de allerbeste DTD op het gepaste punt). De kwalificerende names sub-module wordt opgebouwd door gebruik te maken van de volgende stappen (waar de string MODULE vervangen is door een gepaste string voor de nieuwe module):

  1. Definieer een parameter entiteit MODULE.prefixed die aangeeft of de elementen in de module gebruik gaan maken van XML namespace voorvoegselnamen of niet. De standaard waarde van deze parameter entiteiten zou "%NS.prefixed;" moeten zijn. De NS.prefixed parameter entiteit wordt gedefinieerd door het XHTML framework zodat deze standaard wordt GENEGEERD en kan gebruikt worden in een document om te schakelen tussen voorvoegsels voor alle opgenomen namespaces (inclusief van de XHTML modules).
  2. Definieer een parameter entiteit MODULE.xmlns die de namespace identificator voor deze module bevat.
  3. Definieer een parameter entiteit MODULE.prefix die de standaard voorvoegsel string bevat die gebruikt wordt wanneer voorvoeging geactiveerd is.
  4. Definieer een parameter entiteit MODULE.pfx die "%MODULE.prefix;:" is als voorvoeging geactiveerd is en "" is wanneer dit niet het geval is.
  5. Definieer een parameter entiteit MODULE.xmlns.extra.attrib dat de declaratie van alle XML namespace attributen voor namespaces waarnaar verwezen wordt door deze module bevat (zoals xmlns:xlink). Als %MODULE.prefixed ingesteld is op INCLUDE, zou dit attribuut de xmlns:%MODULE.prefix; declaratie evenens moeten opnemen.
  6. Definieer een parameter entiteit XHTML.xmlns.extra.attrib als MODULE.xmlns.extra.attrib. Hieraan wordt gewoonlijk voorbijgegaan door het document type stuurbestand. Als dit niet het geval is neemt deze definitie de standaard waarde over.
  7. Maak voor elk van de elementen gedefinieerd door de module, een parameter entiteit van de vorm "MODULE.NAME.qname" om de gekwalificeerde naam te bewaren. De waarde voor deze parameter entiteit moet "%MODULE.pfx;NAME" zijn. Op deze manier zal de parsed waarde "PREFIX:NAME" zijn wanneer voorvoegsels geactiveerd zijn en "NAME" in het andere geval.

    Als de module attributen toevoegt aan elementen gedefinieerd in modules die niet de namespace van deze module gemeenschappelijk hebben, moeten deze attributen gedeclareerd worden zodat ze het %MODULE.pfx voorvoegsel gebruiken. Bijvoorbeeld:

    <ENTITY % MODULE.img.mijnattr.qname "%MODULE.pfx;mijnattr" >
    

Een voorbeeld van een qname sub-module voor een hypothetische Inventaris Module wordt hierna opgegeven:

<!-- ........................................................................... -->
<!-- Inventaris Qname Module ................................................... -->
<!-- file: inventaris-qname-1.mod

     PUBLIC "-//MIJN BEDRIJF//ELEMENTS XHTML Inventaris Qnames 1.0//EN"
     SYSTEM "http://www.voorbeeld.com/DTDs/inventaris-qname-1.mod"

     xmlns:inventaris="http://www.voorbeeld.com/xmlns/inventaris"
     ...................................................................... -->

<!-- Declareer de standaard waarde voor voorvoeging van de elementen van deze module -->
<!-- Merk op dat de NS.prefixed voorbijgegaan zal worden door de XHTML Framework of door een document. -->
<!ENTITY % NS.prefixed "IGNORE" >
<!ENTITY % Inventaris.prefixed "%NS.prefixed;" >

<!-- Declareer de eigenlijke namespace van deze module -->
<!ENTITY % Inventaris.xmlns "http://www.voorbeeld.com/xmlns/inventaris" >

<!-- Declareer het standaard voorvoegsel voor deze module -->
<!ENTITY % Inventaris.prefix "inventaris" >

<!-- Declareer het voorvoegsel voor deze module -->
<![%Inventaris.prefixed;[
<!ENTITY % Inventaris.pfx "%Inventaris.prefix;:" >
]]>
<!ENTITY % Inventaris.pfx "" >

<!-- Declareer het xml namespace attribuut voor deze module -->
<![%Inventaris.prefixed;[
<!ENTITY % Inventaris.xmlns.extra.attrib
    "xmlns:%Inventaris.prefix;   %URI.datatype;  #FIXED  '%Inventaris.xmlns;'" >
]]>
<!ENTITY % Inventaris.xmlns.extra.attrib "" >

<!-- Declareer de extra namespace die opgenomen kan worden in de XHTML elementen -->
<!ENTITY % XHTML.xmlns.extra.attrib
    %Inventaris.xmlns.extra.attrib; >

<!-- Declareer nu de gekwalificeerde namen voor alle elementen in de module -->
<!ENTITY % Inventaris.boekenplank.qname "%Inventaris.pfx;boekenplank" >
<!ENTITY % Inventaris.item.qname "%Inventaris.pfx;item" >
<!ENTITY % Inventaris.omschrijving.qname "%Inventaris.pfx;omschrijving" >
<!ENTITY % Inventaris.sku.qname "%Inventaris.pfx;sku" >
<!ENTITY % Inventaris.prijs.qname "%Inventaris.pfx;prijs" >

D.2.2. Declaratie sub-module(s)

De volgende stap is de definitie van één of meer "declaratie sub-modules". Het doel van deze bestandentiteiten is de declaratie van de XML DTD elementen en attribuutlijsten. Een XHTML declaratie module kan gemaakt worden door het volgende process te volgen:

  1. Definieer een parameter entiteit om te gebruiken binnen de ATTLIST van elk gedeclareerd element. Deze parameter entiteit zou %NS.decl.attrib; moeten bevatten wanneer %MODULE.prefixed; ingesteld is op INCLUDE en %NS.decl.attrib; plus "xmlns %URI.datatype; #FIXED '%MODULE.xmlns;'" wanneer %MODULE.prefixed; ingesteld is op IGNORE.
  2. Declareer alle elementen en attributen voor de module. Neem binnen elke ATTLIST voor een element de parameter entiteit hierboven gedefinieerd op zodat alle vereiste xmlns attributen beschikbaar zijn op elk element in de module.
  3. Als de module attributen toevoegt aan elementen gedefinieerd in modules die de namespace van deze module niet delen, declareer dan deze attributen zodat ze de %MODULE.pfx prefix gebruiken. Bijvoorbeeld:

    <ENTITY % MODULE.img.mijnattr.qname "%MODULE.pfx;mijnattr" >
    <!ATTLIST %img.qname;
          %MODULE.img.mijnattr.qname;    CDATA          #IMPLIED
    >
    

    Dit zou een attribuut moeten toevoegen aan het img element van de Image Module, maar de naam van het attribuut zal een gekwalificeerde naam, met prefix, zijn wanneer prefixes geselecteerd zijn voor een document. Het voegt ook het xmlns:MODULE_PREFIX attribuut toe aan de img element attribuutlijst zodat een XML Namespace-bewuste parser zou weten hoe de namespace gebaseerd op de prefix ervan moet opgelost worden.

Het volgende voorbeeld toont een declaratie sub-module voor een hypothetische Inventaris module.

<!-- ...................................................................... -->
<!-- Inventaris Elements Module ................................................... -->
<!-- file: Inventaris-1.mod

     PUBLIC "-//MIJN BEDRIJF//ELEMENTS XHTML Inventaris Elements 1.0//EN"
     SYSTEM "http://www.voorbeeld.com/DTDs/Inventaris-1.mod"

     xmlns:Inventaris="http://www.voorbeeld.com/xmlns/Inventaris"
     ...................................................................... -->

<!-- Inventaris Module

     boekenplank
        item
       sku
       omschrijving
       prijs

     Deze module definieert een eenvoudige Inventaris item structuur
-->

<!-- Definieer de globale namespace attributen -->
<![%Inventaris.prefixed;[
<!ENTITY % Inventaris.xmlns.attrib
    "%NS.decl.attrib;"
>
]]>
<!ENTITY % Inventaris.xmlns.attrib
     "xmlns %URI.datatype;  #FIXED '%Inventaris.xmlns;'"
>

<!-- Definieer een algemene set van attributen voor alle module elementen -->
<!ENTITY % Inventaris.Common.attrib
         "%Inventaris.xmlns.attrib;
      id               ID                   #IMPLIED
>

<!-- Definieer de elementen en attributen van de module -->
<!ELEMENT %Inventaris.boekenplank.qname;
     ( %Inventaris.item.qname; )* >
<!ATTLIST %Inventaris.boekenplank.qname;
     location   CDATA   #IMPLIED
     %Inventaris.Common.attrib;
>
<!ELEMENT %Inventaris.item.qname;
     ( %Inventaris.omschrijving.qname;, %Inventaris.sku.qname;, %Inventaris.prijs.qname;) >
<!ATTLIST %Inventaris.item.qname;
     location   CDATA   #IMPLIED
     %Inventaris.Common.attrib;
>

<!ELEMENT %Inventaris.omschrijving.qname; ( #PCDATA ) >
<!ATTLIST %Inventaris.omschrijving.qname;
     %Inventaris.Common.attrib;
>

<!ELEMENT %Inventaris.sku.qname; ( #PCDATA ) >
<!ATTLIST %Inventaris.sku.qname;
     %Inventaris.Common.attrib;
>

<!ELEMENT %Inventaris.prijs.qname; ( #PCDATA ) >
<!ATTLIST %Inventaris.prijs.qname;
     %Inventaris.Common.attrib;
>

<!-- einde van Inventaris-1.mod -->

D.2.3. Gebruik van de module als een stand-alone DTD

Het is soms gewenst om een XHTML module te hebben die ook gebruikt kan worden als een stand alone DTD. Een goed voorbeeld hiervan is onze Inventaris module hierboven. Deze items moeten opneembaar zijn in een XHTML document en moeten ook beschikbaar zijn als free-standing documenten gegenereerd uit een database (bijvoorbeeld). De eenvoudigste manier om dit te realiseren is om een DTD bestand te definiëren dat de componenten van de module opdeelt. Zo een DTD zou deze structuur hebben:

  1. Neem de XHTML Datatypes Module op (jouw qnames module gebruikt waarschijnlijk sommige van deze datatypes - het gebruikt zeker het URI datatype voor het xmlns attribuut).
  2. Neem de Qnames Module voor jouw module op.
  3. Definieer de parameter entiteit NS.decl.attrib zodat deze %MODULE.xmlns.extra.attrib; is.
  4. Neem de Declaratie Module(s) voor jouw module op.

Een voorbeeld hiervan voor onze Inventaris module is hierna opgenomen:

<!-- ...................................................................... -->
<!-- Inventaris Elementen DTD ............................................... -->
<!-- file: Inventaris-1.dtd

     PUBLIC "-//MIJN BEDRIJF//DTD XHTML Inventaris 1.0//EN"
     SYSTEM "http://www.voorbeeld.com/DTDs/Inventaris-1.dtd"

     xmlns:Inventaris="http://www.voorbeeld.com/xmlns/Inventaris"
     ...................................................................... -->

<!-- Inventaris Module

     boekenplank
        item
       sku
       omschrijving
       prijs

     Deze module definieert een eenvoudige Inventaris item structuur
-->

<!-- Voeg de datatypes in -->
<!ENTITY % xhtml-datatypes.mod
         PUBLIC "-//W3C//ENTITIES XHTML Datatypes 1.0//EN"
         "http://www.w3.org/TR/xhtml-modularization/DTD/xhtml-datatypes-1.mod" >
%xhtml-datatypes.mod;

<!-- Voeg de qualified namen in -->
<!ENTITY % Inventaris-qname.mod SYSTEM "Inventaris-qname-1.mod" >
%Inventaris-qname.mod;

<!ENTITY % NS.decl.attrib "%Inventaris.xmlns.extra.attrib;">

<!ENTITY % Inventaris.mod SYSTEM "Inventaris-1.mod" >
%Inventaris.mod;

<!-- einde van Inventaris-1.dtd -->

Er kan dan naar deze DTD verwezen worden door documenten die enkel de elementen van jouw module gebruiken:

<!DOCTYPE boekenplank SYSTEM "Inventaris-1.dtd">
<boekenplank xmlns="http://www.voorbeeld.com/xmlns/Inventaris">
  <item>
    <omschrijving>
      dit is een omschrijving.
    </omschrijving>
    <sku>
      dit is de prijs.
    </sku>
    <prijs>
      dit is de prijs.
    </prijs>
  </item>
</boekenplank>

Deze methode laat de definitie van elementen en attributen die beperkt zijn tot hun eigen namespace toe. Het laat inhoudsontwikkelaars ook toe om de standaard prefix voor de elementen en attributen te gebruiken:

<!DOCTYPE Inventaris:boekenplank SYSTEM "Inventaris-1.dtd" [
    <!ENTITY % Inventaris.prefixed "INCLUDE">
]>
<Inventaris:boekenplank xmlns:Inventaris="http://www.voorbeeld.com/xmlns/Inventaris">
    <Inventaris:item>
        <Inventaris:omschrijving>
          dit is een omschrijving.
        </Inventaris:omschrijving>
        <Inventaris:sku>
          dit is de sku.
        </Inventaris:sku>
        <Inventaris:prijs>
          dit is de prijs.
        </Inventaris:prijs>
    </Inventaris:item>
</Inventaris:boekenplank>

Tot slot kan een document een andere XML namespace prefix gebruiken door redeclaratie ervan in de DOCTYPE header en de interne subset ervan:

<!DOCTYPE i:boekenplank SYSTEM "Inventaris-1.dtd" [
    <!ENTITY % Inventaris.prefixed "INCLUDE">
    <!ENTITY % Inventaris.prefix "i">
]>
<i:boekenplank xmlns:i="http://www.voorbeeld.com/xmlns/Inventaris">
    <i:item>
        <i:omschrijving>
          dit is een omschrijving.
        </i:omschrijving>
        <i:sku>
          dit is de prijs.
        </i:sku>
        <i:prijs>
          dit is de prijs.
        </i:prijs>
    </i:item>
</i:boekenplank>

D.2.4. Namespace Eigenaardigheden

Hoewel de benadering hier gedefinieerd de definitie van opmaaktalen toelaat die XML en XML namespaces conform zijn, worden sommige gedragingen gedefinieerd door de XML namespaces specificatie niet ondersteund:

  1. XML namespaces laten de redeclaratie van het xmlns attribuut voor een namespace op elk ount in de boom toe. Het laat deze redeclaratie verder toe om te switchen tussen namespace standaard en prefixed gebruik en laat wijzigen van de prefix toe. De methode gedefinieerd in dit document laat dit niet toe. Doorheen een document moet een gegeven namespace dezelfde namespace prefix (wanneer prefixing gebruikt wordt) blijven gebruiken of de standaard blijven gebruiken.

  2. Wanneer XML namespace standaard gebruikt wordt is het geldig om te vertrouwen op de DTD van het document om parsers te informeren van de namespace van elementen. Hoewel namespace bewuste processors de DTD niet verplicht moeten opnemen wanneer een document geëvalueerd wordt, zouden inhoudontwikkelaars de XML namespace van een element best declareren telkens de namespace wijzigt:

    ...
    <p>
       <mijnelement xmlns="..." />
    </p>