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 identifiant les principaux espaces de noms est donnée à la fin du chapitre.
Un espace de noms est déclaré par un pseudo attribut dont le nom
prend la forme xmlns:
où prefix
prefix
est un nom XML ne contenant pas le caractère
':'
. La valeur de ce pseudo attribut est
l'URI qui identifie l'espace de noms. La déclaration associe cet URI au
nom prefix
. Ce préfixe 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, par
exemple, les attributs des déclarations d'espaces de noms. Ces dernières
sont manipulées par des fonctions
spécifiques de XPath.
Un nom qualifié d'élément prend la forme
où prefix
:local
prefix
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'URI
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 précé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
. La
seul contrainte est d'ê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 particuliers pour certains
espaces de noms. Ainsi, on prend souvent html
pour
XHTML, xsd
ou xs
pour les schémas XML et xsl
les
feuilles de style XSLT.
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 prefix
mml
.
<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
lequel 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> <!-- L'espace de noms MathML n'est maintenant plus disponible --> ... </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"> <!-- L'espace de noms par defaut est celui de 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> <!-- L'espace de noms MathML n'est maintenant plus disponible --> ... </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"> <!-- L'espace de noms par defaut est celui de XHTML --> <head> <title>Espaces de noms</title> </head> <body> ... <math xmlns="http://www.w3.org/1998/Math/MathML"> <!-- L'espace de noms par defaut est maintenant celui de MathML --> <apply> <eq/> ... </apply> </math> <!-- L'espace de noms par défaut est à nouveau celui de XHTML --> ... </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 maitenant l'espace de noms XHTML --> <!-- Tous les éléments html, head, title, body, ... appartiennent à l'espace de noms XHTML qui est 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. Cet espace de noms est identifié par l'URI
http://www.w3.org/2001/XMLSchema-instance
. Le nom de
l'attribut noNamespaceSchemaLocation
doit donc avoir
un préfixe associé à cet 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é
n'appartiennent à aucun espace de noms. Ils 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
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'URI http://www.omega-one.org/~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.omega-one.org/~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.omega-one.org/~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/