Devant la complexité et la verbosité des langages de schémas XML, de nombreux experts regrettent que l'on n'ait pas cherché à faire évoluer les DTDs (et les dizaines d'années d'expérience qui y sont associées) plutôt que de réinventer la roue. Dans cette logique, François Perrad propose ici une extension des DTDs permettant d'utiliser des expressions régulières pour spécifier le contenu des attributs et des éléments.
Par François Perrad (francois.perrad(at)gadz.org).
mardi 29 juillet 2003
Contenu
Introduction
L'idée d'ajouter des expressions régulières aux DTD XML m'est venue, il y a quelque temps déjà. Mais c'est la lecture récente de deux livres : 'Mastering Regular Expressions' de Jeffrey E. F. Friedl et 'XML Schema' de Eric van der Vlist qui m'a poussé à la formaliser et à écrire cet article.
Cette idée m'est venue naturellement car j'ai une vue très grammaticale des DTD, ce qui est certainement dû à des souvenirs de lex et yacc.
XML est un langage puissant pour décrire toutes sortes de données. Mais c'est surtout un moyen pour les échanger, donc une syntaxe de transfert. Pour être comprises, ces données doivent respecter un schéma c'est-à-dire correspondre à une syntaxe abstraite. Les DTD ont été le premier type schéma. Les DTD n'utilisent pas elles-mêmes XML.
Je comprends mal pourquoi les nouveaux types de schéma tel que W3C XML Schema et RELAX NG qui ont pour but de décrire une syntaxe abstraite, le font en utilisant XML qui est une syntaxe de transfert. Le résultat est verbeux et rend la conception inintelligible à la lecture bien qu'humainement lisible (ce qui est une des forces de XML). Ces deux approches montrent une des limites de XML, il peut tout représenter, mais pas toujours très efficacement. D'ailleurs, James Clark vient d'ajouter une syntaxe compacte à RELAX NG dont le premier objectif est de maximiser la lisibilité.
Mon objectif n'est pas de concurrencer ces nouveaux types de schéma. Ils reposent sur une approche orientée objet et correspondent à un certain type de besoin.
Mes objectifs sont :
- de garder la simplicité des DTD et leur approche grammaticale.
- d'augmenter le niveau de validation
Si on reprend l'approche grammaticale, les DTD permettent une bonne validation au niveau de la structure syntaxique (c'est-à-dire correspondant à yacc), mais au niveau des lexèmes (correspondant à lex) elles n'offrent pas beaucoup de possibilités : soit un ensemble de valeurs prédéfinies, soit un texte libre ou presque comme les NMTOKEN, mais rien ne ressemblant à un motif d'expression régulière.
D'où l'idée simple d'ajouter des expressions régulières aux DTD et le nom DTD+RE.
Mais, cette approche ne respecte pas l'objectif 3 ayant servi à la conception de XML, c'est-à-dire :
-
XML doit être compatible avec SGML
Spécification
Seules trois productions de la grammaire de XML sont modifiées. Il s'agit de la production 46 (XML 3.2 Element Type Declaration) et des productions 55 et 56 (XML 3.3 Attribute-List Declaration). Elles sont modifiées comme suit :
[46] contentspec ::= 'EMPTY' | 'ANY' | Mixed | children | 'REGEX' S RegexType
[55] StringType ::= 'CDATA' | RegexType
[56] TokenizedType ::= 'ID' | 'ID_REGEX' S RegexType | 'IDREF' | 'IDREFS'
| 'ENTITY'| 'ENTITIES' | 'NMTOKEN' | 'NMTOKENS'
Les productions suivantes sont ajoutées :
RegexType ::= '/' regex '/' RegexModifier ?
RegexModifier ::= 'i'
Un attribut de type 'ID_REGEX' doit respecter les mêmes contraintes de validité qu'un attribut de type 'ID'.
regex est une expression régulière étendue au sens de la définition des Extended Regular Expressions (ERE) définies par POSIX (volume Base Definitions, chapitre 9 - Regular Expressions). Les propriétés d'internationalisation définies par POSIX doivent être prises en compte.
Le caractère '/' servant de délimiteur doit être échappé par "\/" à l'intérieur d'une expression régulière. Et cet échappement doit être retiré avant de fournir l'expression au moteur d'expression régulière.
Traitement des entités
Toutes les références à des entités paramètres doivent être remplacées par leur valeur avant de fournir l'expression au moteur d'expression régulière.
<!-- range [0..255] -->
<!ENTITY % oct_dec "[0-1]?[0-9][0-9]?|2[0-4][0-9]|25[0-5]" >
<!ENTITY % ip_dec "%oct_dec\.%oct_dec\.%oct_dec\.%oct_dec" >
<!ATTLIST mach ip /%ip_dec;/ >
L'utilisation d'entités paramètres permet de fractionner l'écriture d'expression régulière, ce qui a deux avantages :
- augmenter la lisibilité des expressions régulières (ce qui a toujours été leur problème)
- faciliter la réutilisation d'expression
Les entités prédéfinies de XML (< > & ' et ") ne doivent pas être utilisées à l'intérieur d'une expression régulière (et généralement à l'intérieur de la partie DTD). Les caractères < > & ' " doivent être utilisés directement.
En revanche, le caractère '%' doit être doublé à l'intérieur d'une expression régulière pour éviter la confusion avec le début d'une entité paramètre.
<!ENTITY % pe "PE" >
<!ATTLIST elt attr1 /%pe;/ > <!-- regex: PE -->
<!ATTLIST elt attr2 /%%pe;/ > <!-- regex: %pe; -->
<!ATTLIST elt attr3 /%%%pe;/ > <!-- regex: %PE -->
Ajouts implicites à l'expression régulière
Si xml:space='default', le préfixe "^[:space:]*" et le suffixe "[:space:]*$" sont concaténés à l'expression régulière. Si xml:space='preserve', le préfixe "^" et le suffixe "$" sont concaténés à l'expression régulière.
Il est inutile de spécifier explicitement une ancre dans une expression régulière. De plus, l'ancre "$" doit être comprise comme la fin de l'élément ou de la valeur d'un attribut et non comme une fin de ligne. Les caractères de fin de ligne peuvent être utilisés dans une expression régulière et sont reconnus par les expressions "." et "[:space:]".
Modificateur
La valeur 'i' permet de rendre l'expression régulière insensible à la casse.
<!ELEMENT bool REGEX /(true|false)/i >
Entités paramètres prédéfinies
Ces entités correspondent à certains des types prédéfinis de W3C XML Schema Datatypes.
<!ENTITY % re._boolean "(true|false|1|0)" >
<!ENTITY % re.boolean "/%re._boolean;/" >
<!ENTITY % re._integer "[+\-]?[:digit:]+" >
<!ENTITY % re.integer "/%re._integer;/" >
<!ENTITY % re._decimal "[+\-]?([:digit:]+(\.[:digit:]+)?|\.[:digit:]+)" >
<!ENTITY % re.decimal "/%re._decimal;/" >
<!ENTITY % re._float "%re._decimal;([Ee][+/-]?[:digit:]+)?" >
<!ENTITY % re.float "/%re._float;/" >
<!ENTITY % re._language "([:lower:]{2,3}(-[:upper:]{2})?|[ix]-.*)" >
<!ENTITY % re.language "/%re._language;/" >
<!ENTITY % re.__date "[:digit:]{4}-[:digit:]{2}-[:digit:]{2}" >
<!ENTITY % re.__time "[:digit:]{2}:[:digit:]{2}:[:digit:]{2}" >
<!ENTITY % re.__tz "Z|[+/-][:digit:]{2}:[:digit:]{2}" >
<!ENTITY % re._datetime "%re.__date;T%re.__time;(%re.__tz;)?" >
<!ENTITY % re.datetime "/%re._datetime;/" >
<!ENTITY % re._date "%re.__date;(%re.__tz;)?" >
<!ENTITY % re.date "/%re._date;/" >
<!ENTITY % re._time "%re.__time;(%re.__tz;)?" >
<!ENTITY % re.time "/%re._time;/" >
<!-- URI : RFC2396 -->
<!ENTITY % re.__escaped "%[:xdigit:]{2}" >
<!ENTITY % re.__mark "[\-_\.!~\*'\(\)]" >
<!ENTITY % re.__unreserved "([:alnum:]|%re.__mark;)" >
<!ENTITY % re.__reserved "[;\/\?:@&=\+\$,]" >
<!ENTITY % re.__uric "(%re.__reserved;|%re.__unreserved;|%re.__escaped;)" >
<!ENTITY % re.__uric_no_slash "(%re.__unreserved;|%re.__escaped;|[;\?:@&=\+\$,])" >
<!ENTITY % re.__pchar "(%re.__unreserved;|%re.__escaped;|[:@&=\+\$,])" >
<!ENTITY % re.__param "%re.__pchar;*" >
<!ENTITY % re.__segment "%re.__pchar;*(;%re.__param;)*" >
<!ENTITY % re.__path_segments "%re.__segment;(\/%re.__segment;)*" >
<!ENTITY % re.__abs_path "\/%re.__path_segments;" >
<!ENTITY % re.__opaque_part "%re.__uric_no_slash;%re.__uric;*" >
<!ENTITY % re.__path "(%re.__abs_path;|%re.__opaque_part;)" >
<!ENTITY % re.__port "[:digit:]*" >
<!ENTITY % re.__IPv4address "[:digit:]+\.[:digit:]+\.[:digit:]+\.[:digit:]+" >
<!ENTITY % re.__toplabel "([:alpha:]|[:alpha:]([:alnum:]|-)*)[:alnum:]" >
<!ENTITY % re.__domainlabel "([:alnum:]|[:alnum:]([:alnum:]|-)*)[:alnum:]" >
<!ENTITY % re.__hostname "(%re.__domainlabel;\.)*%re.__toplabel;[\.]?" >
<!ENTITY % re.__host "(%re.__hostname;|%re.__IPv4address;)" >
<!ENTITY % re.__hostport "%re.__host;(:%re.__port;)?" >
<!ENTITY % re.__userinfo "(%re.__unreserved;|%re.__escaped;|[;:&=\+\$,])*" >
<!ENTITY % re.__server "((%re.__userinfo;@)?%re.__hostport;)?" >
<!ENTITY % re.__reg_name "(%re.__unreserved;|%re.__escaped;|[\$,;:@&=\+])+" >
<!ENTITY % re.__authority "(%re.__server;|%re.__reg_name;)+" >
<!ENTITY % re.__scheme "[:alpha:]([:alnum:]|[\+\-\.])*" >
<!ENTITY % re.__rel_segment "(%re.__unreserved;|%re.__escaped;|[;@&=\+\$,])+" >
<!ENTITY % re.__rel_path "%re.__rel_segment;(%re.__abspath;)?" >
<!ENTITY % re.__net_path "\/\/%re.__authority;(%re.__abspath;)?" >
<!ENTITY % re.__query "%re.__uric;*" >
<!ENTITY % re.__hier_part "(%re.__net_path;|%re.__abs_path;)(\?%re.__query;)?" >
<!ENTITY % re.__absoluteURI "%re.__scheme;:(%re.__hier_part;|%re.__opaque_part;)" >
<!ENTITY % re.__relativeURI
"(%re.__net_path;|%re.__abs_path;|%re.__rel_path;)(\?%re.__query;)?" >
<!ENTITY % re.__fragment "%re.__uric;*" >
<!ENTITY % re._uri "(%re.__absoluteURI;|%re.__relativeURI;)(#%re.__fragment;)?" >
<!ENTITY % re.uri "/%re._uri;/" >
L'entité suivante doit permettre de rédiger des DTD compatibles avec des parseurs supportant ou non DTD+RE.
<!ENTITY % xml-dtd-regex "INCLUDE" >
Exemple 1 Pour ce premier exemple, je vais réutiliser celui du livre 'XML Schema' de Eric van der Vlist. Voici l'instance de document : <library>
<book id="b0836217462" available="true">
<isbn>0836217462</isbn>
<title xml:lang="en">Being a Dog Is a Full-Time Job</title>
<author id="CMS">
<name>Charles M Schulz</name>
<born>1922-11-26</born>
<dead>2000-02-12</dead>
</author>
<character id="PP">
<name>Peppermint Patty</name>
<born>1966-08-22</born>
<qualification>bold, brash and tomboyish</qualification>
</character>
<character id="Snoopy">
<name>Snoopy</name>
<born>1950-10-04</born>
<qualification>extroverted beagle</qualification>
</character>
<character id="Schroeder">
<name>Schroeder</name>
<born>1951-05-30</born>
<qualification>brought classical music to the Peanuts strip</qualification>
</character>
<character id="Lucy">
<name>Lucy</name>
<born>1952-03-03</born>
<qualification>bossy, crabby and selfish</qualification>
</character>
</book>
</library>
Voici la DTD XML 1.0 :
<!ELEMENT library (book+) >
<!ELEMENT book (isbn, title, author+, character*) >
<!ATTLIST book id ID #REQUIRED >
<!ATTLIST book available (true|false) #REQUIRED >
<!ELEMENT isbn (#PCDATA) >
<!ELEMENT title (#PCDATA) >
<!ATTLIST title xml:lang NMTOKEN #IMPLIED >
<!ELEMENT author (name, born?, dead?) >
<!ATTLIST author id ID #REQUIRED >
<!ELEMENT name (#PCDATA) >
<!ELEMENT born (#PCDATA) >
<!ELEMENT dead (#PCDATA) >
<!ELEMENT character (name, born?, dead?, qualification) >
<!ATTLIST character id ID #REQUIRED >
<!ELEMENT qualification (#PCDATA) >
Maintenant en utilisant DTD+RE :
<!ENTITY % date "/[:digit:]{4}-[:digit:]{2}-[:digit:]{2}/" >
<!ENTITY % _isbn "[:digit:]{10}" >
<!ELEMENT library (book+) >
<!ELEMENT book (isbn, title, author+, character*) >
<!ATTLIST book id ID_REGEX /b%_isbn;/ #REQUIRED >
<!ATTLIST book available %re.boolean; #REQUIRED >
<!ELEMENT isbn REGEX /%_isbn;/ >
<!ELEMENT title (#PCDATA) >
<!ATTLIST title xml:lang %re.language; #IMPLIED >
<!ELEMENT author (name, born?, dead?) >
<!ATTLIST author id ID #REQUIRED >
<!ELEMENT name (#PCDATA) >
<!ELEMENT born REGEX %date; >
<!ELEMENT dead REGEX %date; >
<!ELEMENT character (name, born?, dead?, qualification) >
<!ATTLIST character id ID #REQUIRED >
<!ELEMENT qualification (#PCDATA) >
En supposant que ces deux DTD soient stockées respectivement dans les fichiers library.10.dtd et library.dre, il est possible de déclarer un point d'entrée commun entre un parseur DTD standard et un parseur DTD+RE de la façon suivante :
<!ENTITY % xml-dtd-regex "IGNORE" >
<![%xml-dtd-regex;[
<!ENTITY % library.dtd SYSTEM "library.dre" >
]]>
<!ENTITY % library.dtd SYSTEM "library.10.dtd" >
%library.dtd;
Exemple 2 Pour ce deuxième exemple, je vais réutiliser de la documentation du module Perl PPM::XML::PPD qui décrit une application XML de Perl Package Distribution. Voici l'instance de document : <SOFTPKG NAME="Math-MatrixBool" VERSION="4,2,0,0">
<TITLE>Math-MatrixBool</TITLE>
<ABSTRACT>Easy manipulation of matrices of booleans (Boolean Algebra)</ABSTRACT>
<AUTHOR>Steffen Beyer (sb@sdm.de)</AUTHOR>
<LICENSE HREF="http://www.ActiveState.com/packages/Math-MatrixBool/license.html" />
<IMPLEMENTATION>
<OS VALUE="WinNT" />
<OS VALUE="Win95" />
<PROCESSOR VALUE="x86" />
<CODEBASE
HREF="http://www.ActiveState.com/packages/Math-MatrixBool/Math-MatrixBool-4.2-bin-1-Win32.tar.gz" />
<DEPENDENCY NAME="Bit-Vector" />
<INSTALL>
</INSTALL>
<UNINSTALL>
</UNINSTALL>
</IMPLEMENTATION>
<IMPLEMENTATION>
<DEPENDENCY NAME="Bit-Vector" />
<CODEBASE
HREF="http://www.cpan.org/CPAN/modules/by-module/Math/Math-MatrixBool-4.2.tar.gz" />
<INSTALL>
system("make"); ;;
system("make test"); ;;
system("make install"); ;;
</INSTALL>
</IMPLEMENTATION>
</SOFTPKG>
Voici la DTD XML 1.0 (cette version commentée en HTML a été générée par le module Perl dtd2html) :
<!ELEMENT SOFTPKG (ABSTRACT | AUTHOR | IMPLEMENTATION | LICENSE | TITLE)*>
<!ATTLIST SOFTPKG NAME CDATA #REQUIRED>
<!ATTLIST SOFTPKG VERSION CDATA #IMPLIED>
<!ELEMENT TITLE (#PCDATA)>
<!ELEMENT ABSTRACT (#PCDATA)>
<!ELEMENT AUTHOR (#PCDATA)>
<!ELEMENT LICENSE EMPTY>
<!ATTLIST LICENSE HREF CDATA #REQUIRED>
<!ELEMENT IMPLEMENTATION (CODEBASE | DEPENDENCY | LANGUAGE | OS |
OSVERSION | PERLCORE | PROCESSOR | INSTALL |
UNINSTALL )* >
<!ELEMENT CODEBASE EMPTY>
<!ATTLIST CODEBASE FILENAME CDATA #IMPLIED>
<!ATTLIST CODEBASE HREF CDATA #REQUIRED>
<!ELEMENT DEPENDENCY EMPTY>
<!ATTLIST DEPENDENCY VERSION CDATA #IMPLIED>
<!ATTLIST DEPENDENCY NAME CDATA #REQUIRED>
<!ELEMENT LANGUAGE EMPTY>
<!ATTLIST LANGUAGE VALUE CDATA #REQUIRED>
<!ELEMENT OS EMPTY>
<!ATTLIST OS VALUE CDATA #REQUIRED>
<!ELEMENT OSVERSION EMPTY>
<!ATTLIST OSVERSION VALUE CDATA #REQUIRED>
<!ELEMENT PERLCORE EMPTY>
<!ATTLIST PERLCORE VERSION CDATA #REQUIRED>
<!ELEMENT PROCESSOR EMPTY>
<!ATTLIST PROCESSOR VALUE CDATA #REQUIRED>
<!ELEMENT INSTALL (#PCDATA)>
<!ATTLIST INSTALL HREF CDATA #IMPLIED>
<!ATTLIST INSTALL EXEC CDATA #IMPLIED>
<!ELEMENT UNINSTALL (#PCDATA)>
<!ATTLIST UNINSTALL HREF CDATA #IMPLIED>
<!ATTLIST UNINSTALL EXEC CDATA #IMPLIED>
Maintenant en utilisant DTD+RE :
<!ENTITY % ppd.name "/([:alnum:]|[\-_])+/" >
<!ENTITY % ppd.version "/[:digit:]+(,[:digit:]+){3}/" >
<!ELEMENT SOFTPKG (ABSTRACT | AUTHOR | IMPLEMENTATION | LICENSE | TITLE)*>
<!ATTLIST SOFTPKG NAME %ppd.name; #REQUIRED>
<!ATTLIST SOFTPKG VERSION %ppd.version; #IMPLIED>
<!ELEMENT TITLE REGEX %ppd.name; >
<!ELEMENT ABSTRACT (#PCDATA)>
<!ELEMENT AUTHOR (#PCDATA)>
<!ELEMENT LICENSE EMPTY>
<!ATTLIST LICENSE HREF %re.uri; #REQUIRED>
<!ELEMENT IMPLEMENTATION (CODEBASE | DEPENDENCY | LANGUAGE | OS |
OSVERSION | PERLCORE | PROCESSOR | INSTALL |
UNINSTALL )* >
<!ELEMENT CODEBASE EMPTY>
<!ATTLIST CODEBASE FILENAME CDATA #IMPLIED>
<!ATTLIST CODEBASE HREF %re.uri; #REQUIRED>
<!ELEMENT DEPENDENCY EMPTY>
<!ATTLIST DEPENDENCY VERSION %ppd.version; #IMPLIED>
<!ATTLIST DEPENDENCY NAME %ppd.name; #REQUIRED>
<!ELEMENT LANGUAGE EMPTY>
<!ATTLIST LANGUAGE VALUE CDATA #REQUIRED>
<!ELEMENT OS EMPTY>
<!ATTLIST OS VALUE CDATA #REQUIRED>
<!ELEMENT OSVERSION EMPTY>
<!ATTLIST OSVERSION VALUE %ppd.version; #REQUIRED>
<!ELEMENT PERLCORE EMPTY>
<!ATTLIST PERLCORE VERSION %ppd.version; #REQUIRED>
<!ELEMENT PROCESSOR EMPTY>
<!ATTLIST PROCESSOR VALUE CDATA #REQUIRED>
<!ELEMENT INSTALL (#PCDATA)>
<!ATTLIST INSTALL HREF %re.uri; #IMPLIED>
<!ATTLIST INSTALL EXEC CDATA #IMPLIED>
<!ELEMENT UNINSTALL (#PCDATA)>
<!ATTLIST UNINSTALL HREF %re.uri; #IMPLIED>
<!ATTLIST UNINSTALL EXEC CDATA #IMPLIED>
Exemple 3 Ce troisième exemple concerne XHTML et plus particulièrement XHTML 1.1 qui est la version modularisée. Cette version va me faciliter le travail. En effet, il suffit uniquement de réécrire un module pour commencer à profiter des avantages de DTD+RE. Il s'agit du fichier xhtml-datatypes-1.mod qui spécifie des types d'attribut en utilisant "CDATA", "NMTOKEN" et "NMTOKENS". Les expressions régulières suivantes sont des versions naïves, mon objectif n'est pas ici de donner les meilleures expressions régulières mais seulement de montrer les avantages de cette technique. De plus, si on veut appliquer la règle : soyez tolérant à propos de ce que vous acceptez et strict dans ce que vous produisez
Il sera peut-être utile de définir deux versions suivant le coté où l'on se place.
<!-- Datatypes
defines containers for the following datatypes, many of
these imported from other specifications and standards.
-->
<!-- Length defined for cellpadding/cellspacing -->
<!-- nn for pixels or nn% for percentage length -->
<!ENTITY % Length.datatype "/[:digit:]+%?/" >
<!-- space-separated list of link types -->
<!ENTITY % LinkTypes.re "(next|prev|head|toc|parent|child|index|glossary)" >
<!ENTITY % LinkTypes.datatype "/%LinkTypes.re;([:space:]+%LinkTypes.re;)*/" >
<!-- single or comma-separated list of media descriptors -->
<!ENTITY % MediaDesc.re "(screen|tty|tv|projection|handheld|print|braille|aural|all)" >
<!ENTITY % MediaDesc.datatype "/%MediaDesc.re;(,%MediaDesc.re;)*/" >
<!-- pixel, percentage, or relative -->
<!ENTITY % MultiLength.datatype "/[:digit:]+%?/" >
<!-- one or more digits (NUMBER) -->
<!ENTITY % Length.datatype "/[:digit:]+/" >
<!-- integer representing length in pixels -->
<!ENTITY % Pixels.datatype "/\+?[:digit:]+/" >
<!-- script expression -->
<!ENTITY % Script.datatype "CDATA" >
<!-- textual content -->
<!ENTITY % Text.datatype "CDATA" >
<!-- Imported Datatypes ................................ -->
<!-- a single character from [ISO10646] -->
<!ENTITY % Character.datatype "/./" >
<!-- a character encoding, as per [RFC2045] -->
<!ENTITY % Charset.re "([\.\-_:]|[:alnum:])+" >
<!ENTITY % Charset.datatype "/%Charset.re;/" >
<!-- a space separated list of character encodings, as per [RFC2045] -->
<!ENTITY % Charsets.datatype "/%Charset.re;(,%Charset.re;)*/" >
<!-- Color specification using color name or sRGB (#RRGGBB) values -->
<!ENTITY % Color.datatype "/([:alpha:][:alnum:]*|#[:xdigit:]{6})/" >
<!-- media type, as per [RFC2045] -->
<!ENTITY % ContentType.re.type "([:alnum:]|-)+" >
<!ENTITY % ContentType.re.subtype "([:alnum:]|-)+" >
<!ENTITY % ContentType.re.parameter "[^=]+=[^;]+" >
<!ENTITY % ContentType.re
"%ContentType.re.type;\/%ContentType.re.subtype;(;%ContentType.re.parameter;)*" >
<!ENTITY % ContentType.datatype "/%ContentType.re;/" >
<!-- comma-separated list of media types, as per [RFC2045] -->
<!ENTITY % ContentTypes.datatype "/%ContentType.re;(,%ContentType.re;)*/" >
<!-- date and time information. ISO date format -->
<!ENTITY % Datetime.datatype "/%re._datetime;/" >
<!-- formal public identifier, as per [ISO8879] -->
<!ENTITY % FPI.datatype "CDATA" >
<!-- a language code, as per [RFC3066] -->
<!ENTITY % LanguageCode.datatype "/%re._language;/" >
<!-- a Uniform Resource Identifier, see [URI] -->
<!ENTITY % URI.datatype "/%re._uri;/" >
<!-- a space-separated list of Uniform Resource Identifiers, see [URI] -->
<!ENTITY % URIs.datatype "/%re._uri;([:space:]+%re._uri;)*/" >
Ce n'est certainement pas la meilleure utilisation de DTD+RE possible, mais c'est un début par rapport au riche existant concernant XHTML.
Conclusion
DTD+RE est basé sur une idée simple. Cela doit permettre :
- de faciliter l'implantation d'un parseur à partir d'un parseur validant de DTD, en effet des moteurs d'expression sont disponibles dans les langages qui sont utilisés pour écrire des parseurs (Java, C, ...)
- de faciliter l'apprentissage, en effet il n'y a pas là de nouvelles technologies nécessitant d'épaisse documentation
De plus, la technique des expressions régulières est bien connue et a largement fait ses preuves dans le domaine du traitement des chaînes de caractères.
Les techniques de modularisation des DTD permettent d'obtenir une réutilisation de macro-composants, comme pour XHTMLMOD. L'utilisation d'entités paramètres pour des fragments d'expression régulière permettra une réutilisation de micro-composants. Cette réutilisation commence par la liste d'entités paramètres prédéfinies qui devra être affinée et enrichie.
L'intérêt majeur de cette approche est de proposer une compatibilité ascendante, une DTD XML 1.0 est une DTD+RE. Cela permet la migration d'application en enrichissant progressivement des DTD avec des expressions régulières.
Références
-
[RELAX NG]
- REgular LAnguage description for XML - Next Generation See: http://www.oasis-open.org/committees/relax-ng/
-
[POSIX]
- Portable Operating System Interface (POSIX), IEEE Std 1003.1-2001 See: http://www.unix.org/version3/ieee_std.html
-
[SGML]
- Standard Generalized Markup Language, ISO 8879:1986
-
[WXS]
- XML Schema Part 2: Datatypes, W3C Recommendation. See: http://www.w3.org/TR/2001/REC-xmlschema-2-20010502
-
[XHTML]
- Module-based XHTML, W3C Recommendation. See: http://www.w3.org/TR/2001/REC-xhtml11-20010531
-
[XHTMLMOD]
- Modularization of XHTML, W3C Recommendation. See: http://www.w3.org/TR/2001/REC-xhtml-modularization-20010410
-
[XML]
- Extensible Markup Language (XML) 1.0 (Second Edition), W3C Recommendation. See: http://www.w3.org/TR/2000/REC-xml-20001006
Copyright 2003,
François Perrad.
|