Chapitre 4. Espaces de noms

4.1. Introduction

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.

4.2. Identification d'un espace de noms

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.

4.3. Déclaration d'un espace de noms

Un espace de noms est déclaré par un pseudo attribut dont le nom prend la forme xmlns:prefixprefix 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 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'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:prefix. Dans l'exemple suivant, on déclare également l'espace de noms de MathML et on l'associe au préfixe 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>

4.4. Portée d'une déclaration

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>

4.5. Espace de noms par défaut

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.

4.6. Attributs

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">

4.7. Espace de noms XML

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.

4.8. Espaces de noms et DTD

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>

4.9. Quelques espaces de noms classiques

XML

http://www.w3.org/XML/1998/namespace

XInclude

http://www.w3.org/2001/XInclude

XLink

http://www.w3.org/1999/xlink

MathML

http://www.w3.org/1998/Math/MathML

XHTML

http://www.w3.org/1999/xhtml

SVG

http://www.w3.org/2000/svg

Schémas

http://www.w3.org/2001/XMLSchema

Instances de schémas

http://www.w3.org/2001/XMLSchema-instance

Schematron

http://purl.oclc.org/dsdl/schematron

XSLT

http://www.w3.org/1999/XSL/Transform

XSL-FO

http://www.w3.org/1999/XSL/Format

DocBook

http://docbook.org/ns/docbook

Dublin Core

http://purl.org/dc/elements/1.1/