Les espaces de noms ont été introduits en XML afin de pouvoir mélanger plusieurs vocabulaires au sein d'un même document. De nombreux dialectes XML ont été définis pour des utilisations diverses et il est préférable de les réutiliser au maximum. Il est, en effet, fastidieux de redéfinir plusieurs fois les mêmes vocabulaires. Le recyclage des dialectes fait d'ailleurs partie des objectifs de XML.
Le mélange de plusieurs vocabulaires au sein d'un même document ne doit pas empêcher la validation de celui-ci. Il devient indispensable d'identifier la provenance de chaque élément et de chaque attribut afin de le valider correctement. Les espaces de noms jouent justement ce rôle. Chaque élément ou attribut appartient à un espace de noms qui détermine le vocabulaire dont il est issu. Cette appartenance est marquée par la présence dans le nom d'un préfixe associé à l'espace de noms.
Le mélange de plusieurs vocabulaires est illustré par l'exemple
suivant. Afin d'insérer des métadonnées dans des documents, il est
nécessaire de disposer d'éléments pour présenter celles-ci. Il existe
déjà un standard, appelé Dublin Core, pour organiser ces métadonnées. Il
comprend une quinzaine d'éléments dont title,
creator, subject et
date qui permettent de décrire les caractéristiques
principales d'un document. Il est préférable d'utiliser le vocabulaire
Dublin Core, qui est un standard international, plutôt que d'introduire
un nouveau vocabulaire. Le document suivant est le document principal
d'un livre au format DocBook. Les métadonnées sont contenues dans un
élément metadata. Celui-ci contient plusieurs
éléments du Dublin Core dont les noms commencent par le préfixe
dc. L'élément include de XInclude
fait partie d'un autre espace de noms marqué par le préfixe
xi.
<?xml version="1.0" encoding="iso-8859-1"?>
<book version="5.0" xml:lang="fr"
xmlns="http://docbook.org/ns/docbook"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:xi="http://www.w3.org/2001/XInclude">
<!-- Titre DocBook du document -->
<title>Langages formels, calculabilité et complexité</title>
<!-- Métadonnées -->
<metadata>
<dc:title>Langages formels, calculabilité et complexité</dc:title>
<dc:creator>Olivier Carton</dc:creator>
<dc:date>2008-10-01</dc:date>
<dc:identifier>urn:isbn:978-2-7117-2077-4</dc:identifier>
</metadata>
<!-- Import des chapitres avec XInclude -->
<xi:include href="introduction.xml" parse="xml"/>
<xi:include href="chapter1.xml" parse="xml"/>
<xi:include href="chapter2.xml" parse="xml"/>
<xi:include href="chapter3.xml" parse="xml"/>
<xi:include href="chapter4.xml" parse="xml"/>
<index/>
</book>
Comme en C++, les espaces de noms évitent les conflits de noms
entre différents vocabulaires. Le dialecte DocBook dispose d'un élément
title de même nom que l'élément
title du Dublin Core. Ces deux éléments ne sont pas
confondus dans le document précédent, car l'élément
title du Dublin Core a le préfixe
dc.
Un espace de noms est identifié par un URI appelé URI de l'espace de noms. Cet URI est très souvent une URL mais il est sans importance que l'URL pointe réellement sur un document. Cet URI garantit seulement que l'espace de noms soit identifié de manière unique. Dans la pratique, l'URL permet aussi souvent d'accéder à un document qui décrit l'espace de noms. Une liste des URI associés aux principaux espaces de noms est donnée à la fin du chapitre.
Un espace de noms déclaré par un pseudo attribut de forme
xmlns:
dont la valeur est une URL qui identifie l'espace de noms. Le préfixe
prefixprefix est un nom XML ne contenant pas le caractère
':'. Il est ensuite utilisé pour
qualifier les noms d'éléments. Bien que la
déclaration d'un espace de noms se présente comme un attribut, celle-ci
n'est pas considérée comme un attribut. Le langage XPath distingue en effet les attributs des
déclarations d'espaces de noms. Ces dernières sont manipulées de façon
particulière.
Un nom qualifié d'élément prend la forme
où prefix:localprefix est un préfixe associé à un espace
de noms et local est le nom
local de l'élément. Ce nom local est également un nom XML ne
contenant pas le caractère ':'. Dans la terminologie
XML, les noms sans caractère ':' sont appelés
NCNAME qui est l'abréviation de No Colon
Name et les noms qualifiés sont appelés
QNAME qui est, bien sûr, l'abréviation de
Qualified Name.
Dans l'exemple suivant, on associe le préfixe
hns à l'espace de noms de XHTML identifié par l'URL
http://www.w3.org/1999/xhtml. Ensuite, tous les
éléments de cet espace de noms sont préfixés par
hns:.
<hns:html xmlns:hns="http://www.w3.org/1999/xhtml"> <hns:head> <hns:title>Espaces de noms</hns:title> </hns:head> <hns:body> ... </hns:body> </hns:html>
Il est habituel d'associer l'espace de noms XHTML au
préfixe html plutôt qu'à hns.
L'exemple precédent devient alors l'exemple suivant qui est un document
équivalent.
<html:html xmlns:html="http://www.w3.org/1999/xhtml"> <html:head> <html:title>Espaces de noms</html:title> </html:head> <html:body> ... </html:body> </html:html>
Le choix du préfixe est complètement arbitraire. Dans l'exemple
précédent, on aurait pu utiliser foo ou
bar à la place du préfixe html. Il
faut par contre être cohérent entre la déclaration du préfixe et son
utilisation. Même si les préfixes peuvent être librement choisis, il est
d'usage d'utiliser certains préfixes pour certains espaces de noms.
Ainsi, on prend souvent html pour XHTML,
xsd ou xs pour les schémas XML et
xsl pour les feuilles de style XSL.
Il est bien sûr possible de déclarer plusieurs espaces de noms en
utilisant plusieurs attributs de la forme
xmlns:. Dans
l'exemple suivant, on déclare également l'espace de noms de MathML et on
l'associe au préfixe prefixmml.
<html:html xmlns:html="http://www.w3.org/1999/xhtml" xmlns:mml="http://www.w3.org/1998/Math/MathML"> <html:head> <html:title>Espaces de noms</html:title> </html:head> <html:body> ... <mml:math> <mml:apply> <mml:eq/> ... </mml:apply> </mml:math> ... </html:body> </html:html>
C'est l'URI associé au préfixe qui détermine l'espace de noms. Le
préfixe est juste une abréviation pour l'URI. Deux préfixes associés au
même URI déterminent le même espace de noms. Dans l'exemple suivant, les
deux éléments firstname et surname
font partie du même espace de noms. L'exemple suivant est uniquement donné
pour illustrer le propos mais il n'est pas à suivre. C'est une mauvaise
pratique d'associer deux préfixes au même URI.
<name xmlns:foo="http://www.somewhere.org/uri" xmlns:bar="http://www.somewhere.org/uri"> <!-- Les deux éléments firstname et surname appartiennent au même espace de noms. --> <foo:firstname>Gaston<foo:firstname> <bar:surname>Lagaffe<bar:surname> </name>
La portée d'une déclaration d'un espace de noms est l'élément dans
laquelle elle est faite. L'exemple précédent aurait pu aussi être écrit
de la manière suivante. Il faut remarquer que la portée de la
déclaration comprend les balises de l'élément qui la contient. Il est
ainsi possible d'utiliser le préfixe html dans
l'élément html pour obtenir le nom qualifié
html:html.
<html:html xmlns:html="http://www.w3.org/1999/xhtml"> <html:head> <html:title>Espaces de noms</html:title> </html:head> <html:body> ... <mml:math xmlns:mml="http://www.w3.org/1998/Math/MathML"> <mml:apply> <mml:eq/> ... </mml:apply> </mml:math> ... </html:body> </html:html>
Il existe un espace de noms par défaut associé au préfixe vide. Son utilisation permet d'alléger l'écriture des documents XML en évitant de mettre un préfixe aux éléments les plus fréquents. Lorsque plusieurs espaces de noms coexistent au sein d'un document, il faut, en général, réserver l'espace de noms par défaut à l'espace de noms le plus utilisé. Dans le cas des schémas, il est souvent pratique de prendre pour espace de noms par défaut l'espace de noms cible.
L'espace de noms par défaut peut être spécifié par un pseudo
attribut de nom xmlns dont la valeur est l'URI de
l'espace de noms. Lorsque celui a été spécifié, les éléments dont le nom
n'est pas qualifié font partie de l'espace de noms par défaut. L'exemple
précédent aurait pu être simplifié de la façon suivante.
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Espaces de noms</title> </head> <body> ... <mml:math xmlns:mml="http://www.w3.org/1998/Math/MathML"> <mml:apply> <mml:eq/> ... </mml:apply> </mml:math> ... </body> </html>
Comme la déclaration de l'espace de noms est locale à l'élément,
l'exemple précédent aurait pu être écrit de façon encore plus simplifiée
en changeant localement dans l'élément math l'espace
de noms par défaut.
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Espaces de noms</title> </head> <body> ... <math xmlns="http://www.w3.org/1998/Math/MathML"> <apply> <eq/> ... </apply> </math> ... </body> </html>
Tant que l'espace de noms par défaut n'a pas été spécifié, les
éléments dont le nom n'est pas qualifié ne font partie d'aucun espace de
noms. Leur propriété espace de noms n'a pas de
valeur. Il est possible de revenir à l'espace de noms par défaut non
spécifié en affectant la chaîne vide à l'attribut
xmlns comme dans l'exemple suivant.
<html xmlns="http://www.w3.org/1999/xhtml"> <!-- L'espace de noms par défaut est spécifié --> <!-- Tous les éléments html, head, title, body, ... appartiennent à l'espace de noms par défaut. --> <head> <title>Espaces de noms</title> </head> <body> ... <name xmlns=""> <!-- L'espace de noms par défaut n'est plus spécifié --> <!-- Les trois éléments name, firstname et surname n'appartiennent à aucun espace de noms. --> <firstname>Gaston<firstname> <surname>Lagaffe<surname> </name> ... </body> </html>
Une conséquence de la remarque précédente est que dans un document XML sans déclaration d'espace de noms, tous les éléments ne font partie d'aucun espace de noms. Ce comportement assure une compatibilité des applications avec les documents sans espace de noms.
Les attributs peuvent également avoir des noms qualifiés formés
d'un préfixe et d'un nom local. Ils font alors partie de l'espace de
noms auquel est associé le préfixe. Dans l'exemple suivant, l'attribut
noNamespaceSchemaLocation fait partie de l'espace de
noms des instances de schémas identifié par l'URI
http://www.w3.org/2001/XMLSchema-instance. Le nom de
l'attribut noNamespaceSchemaLocation doit donc avoir
un préfixe associé à cette URI. La déclaration de l'espace de noms peut
avoir lieu dans le même élément, comme dans l'exemple ci-dessous, puisque
la portée de celle-ci est l'élément tout entier.
<?xml version="1.0" encoding="iso-8859-1"?> <bibliography xsi:noNamespaceSchemaLocation="bibliography.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> ...
En revanche, les attributs dont le nom n'est pas qualifié ne font
jamais partie de l'espace de noms par défaut. Cette règle s'applique que
l'espace de noms par défaut soit spécifié ou non. Dans l'exemple
ci-dessous, l'élément book appartient à l'espace de
noms DocBook puisque celui-ci est déclaré comme l'espace de noms par
défaut. L'attribut id appartient à l'espace de noms
XML et l'attribut version n'appartient à aucun espace
de noms.
<book version="5.0"
xml:id="course.xml"
xmlns="http://docbook.org/ns/docbook">
Le préfixe xml est toujours implicitement lié à
l'espace de noms XML identifié par l'URI est
http://www.w3.org/XML/1998/namespace. Cet espace de
noms n'a pas besoin d'être déclaré. Les quatre attributs particuliers
xml:lang, xml:space,
xml:base et xml:id font partie de
cet espace de noms.
Ces quatre attributs sont déclarés par le schéma XML qui se trouve à l'URL
http://www.w3.org/2001/xml.xsd. Ce schéma peut être importé par un autre schéma pour
ajouter certains de ces attributs à des éléments.
Les DTD ne prennent pas compte les espaces de noms. Il est
cependant possible de valider, avec une DTD, un document avec des
espaces de noms au prix de quelques entorses à l'esprit des espaces de
noms. Il y a, en effet, quelques contraintes. D'une part, la
déclaration d'espace de noms est vue comme un attribut de nom commençant
par xmlns:. Il est donc nécessaire de le déclarer
comme tout autre attribut. D'autre part, les noms qualifiés des
éléments sont considérés comme des noms contenant le caractère
':'. Il faut donc déclarer les éléments avec leur
nom qualifié.
Les éléments du document suivant font partie de l'espace de
noms identifié par l'URL http://www.liafa.jussieu.fr/~carton/
qui est associé au préfixe tns.
<?xml version="1.0" encoding="iso-8859-1"?> <!DOCTYPE list SYSTEM "valid.dtd"> <tns:list xmlns:tns="http://www.liafa.jussieu.fr/~carton/"> <tns:item>Item 1</tns:item> <tns:item>Item 2</tns:item> </tns:list>
La DTD suivante valide le document précédent. Elle déclare un
attribut xmlns:tns pour la déclaration d'espace de
noms. De plus, les éléments sont déclarés avec leurs noms qualifiés
tns:list et tns:item.
<!-- Fichier "valid.dtd" --> <!ELEMENT tns:list (tns:item)+> <!ATTLIST tns:list xmlns:tns CDATA #REQUIRED> <!ELEMENT tns:item (#PCDATA)>
En revanche, le document suivant n'est pas valide pour la
DTD précédent alors qu'il est équivalent au document précédent.
Le préfixe tns a simplement été remplacé par
le préfixe ons.
<?xml version="1.0" encoding="iso-8859-1"?> <!DOCTYPE list SYSTEM "valid.dtd"> <ons:list xmlns:ons="http://www.liafa.jussieu.fr/~carton/"> <ons:item>Item 1</ons:item> <ons:item>Item 2</ons:item> </ons:list>
http://www.w3.org/XML/1998/namespace
http://www.w3.org/2001/XInclude
http://www.w3.org/1999/xlink
http://www.w3.org/1998/Math/MathML
http://www.w3.org/1999/xhtml
http://www.w3.org/2000/svg
http://www.w3.org/2001/XMLSchema
http://www.w3.org/2001/XMLSchema-instance
http://purl.oclc.org/dsdl/schematron
http://www.w3.org/1999/XSL/Transform
http://www.w3.org/1999/XSL/Format
http://docbook.org/ns/docbook
http://purl.org/dc/elements/1.1/