Cours accéléré sur les espaces de noms
En tant que dialecte de XML, SVG utilise des espaces de noms. Il est important de comprendre le concept d'espaces de noms et leur utilisation si vous souhaitez créer du contenu SVG. Les espaces de noms sont essentiels pour les agents utilisateur qui prennent en charge plusieurs dialectes XML ; les navigateurs doivent être très stricts. Prendre le temps de comprendre les espaces de noms maintenant vous évitera bien des soucis à l'avenir.
Contexte
Un objectif de longue date des différentes spécifications du W3C est de permettre à différents types de contenus basés sur XML d'être mélangés dans un même fichier XML ou HTML. Par exemple, SVG et MathML peuvent être incorporés directement dans un document scientifique basé sur HTML. Pouvoir mélanger ainsi les types de contenus présente de nombreux avantages, mais cela a aussi nécessité de résoudre un problème bien réel.
Naturellement, chaque dialecte XML définit la signification des noms d'éléments de balisage décrits dans sa spécification. Le problème du mélange de contenus issus de différents dialectes XML dans un même document est que les éléments définis par un dialecte peuvent porter le même nom que ceux d'un autre. Par exemple, HTML et SVG possèdent tous deux un élément <title>. Comment l'agent utilisateur fait-il la distinction entre les deux ? Comment les styles CSS font-ils la distinction ? En fait, comment l'agent utilisateur sait-il quand le contenu est quelque chose qu'il connaît, et non simplement un élément personnalisé HTML non défini ou un fichier XML contenant des noms d'éléments arbitraires qui lui sont inconnus ?
Contrairement à une idée répandue, la réponse à cette question n'est pas « il peut le savoir grâce à la déclaration DOCTYPE ». Les DTD n'ont jamais été conçus pour le contenu mixte, et les tentatives passées de création de DTD pour contenu mixte sont désormais considérées comme des échecs. XML, et certains dialectes XML (y compris SVG et HTML), ne nécessitent pas de déclaration DOCTYPE. SVG 1.2 n'en possède même pas. Le fait que les déclarations DOCTYPE correspondent (généralement) au contenu dans les fichiers à type de contenu unique est purement fortuit. Les DTD servent uniquement à la validation, pas à l'identification du contenu. Tout agent utilisateur qui identifie le contenu XML à l'aide de sa déclaration DOCTYPE n'est pas fiable.
La véritable réponse à cette question est que le contenu XML indique à l'agent utilisateur à quel dialecte appartiennent les noms d'éléments en leur fournissant des « déclarations d'espaces de noms » explicites.
Déclaration des espaces de noms
À quoi ressemblent donc ces déclarations d'espaces de noms, et où doivent-elles être placées ? Voici un court exemple.
<svg xmlns="http://www.w3.org/2000/svg">
<!-- d'autres balises ici -->
</svg>
La déclaration d'espace de noms est fournie par le paramètre xmlns. Ce paramètre indique que l'élément <svg> et ses éléments enfants appartiennent au dialecte XML dont le nom d'espace de noms est http://www.w3.org/2000/svg, c'est-à-dire SVG. Notez que la déclaration d'espace de noms n'est fournie qu'une seule fois sur un élément racine (et elle est implicite si elle est omise). La déclaration définit l'espace de noms par défaut, de sorte que l'agent utilisateur sait que tous les descendants de l'élément <svg> appartiennent également au même espace de noms. Les agents utilisateur vérifient s'ils reconnaissent le nom d'espace de noms pour déterminer s'ils savent comment traiter le balisage.
Notez que les noms d'espaces de noms sont simplement des chaînes de caractères, donc le fait que le nom d'espace de noms SVG ressemble aussi à un URI n'a pas d'importance. Les URI sont couramment utilisés car ils sont uniques, mais l'objectif n'est pas de « lien » vers un endroit. (En fait, les URI sont utilisés si fréquemment que le terme « URI d'espace de noms » est couramment employé à la place de « nom d'espace de noms ».)
Redéclaration de l'espace de noms par défaut
Si tous les descendants de l'élément racine sont également définis dans l'espace de noms par défaut, comment mélanger du contenu provenant d'un autre espace de noms ? Pour inclure l'espace de noms SVG dans HTML, vous insérez <svg>. En XML, vous déclarez un espace de noms. Voici un court exemple.
<report xmlns="https://www.acme.org/reports">
<title>Quelques statistiques</title>
<summary>...</summary>
<statTable xmlns="https://www.acme.org/tables">
<content>...</content>
<!-- redéclaration de l'espace de noms par défaut de la racine -->
<summary xmlns="https://www.acme.org/reports">...</summary>
</statTable>
</report>
Dans cet exemple, le paramètre xmlns sur l'élément racine <report> déclare que l'espace de noms par défaut est https://www.acme.org/reports, ou reports. Par conséquent, lui-même et tous ses éléments enfants sont interprétés par l'agent utilisateur comme appartenant à reports, à l'exception de l'élément <content>, qui appartient à l'espace de noms https://www.acme.org/tables, ou tables. L'élément <summary> possède son propre paramètre xmlns, et en redéclarant l'espace de noms reports, cela indique à l'agent utilisateur que l'élément <summary> et ses descendants (sauf s'ils redéclarent aussi un autre espace de noms) appartiennent à reports.
Avec HTML, l'espace de noms implicite est http://www.w3.org/1999/xhtml. Avec SVG, c'est http://www.w3.org/2000/svg. Pour MathML, il s'agit de http://www.w3.org/1998/Math/MathML.
Déclaration des préfixes d'espaces de noms
Les dialectes XML ne définissent pas seulement leurs propres éléments, ils déclarent aussi leurs propres paramètres.
Par défaut, les paramètres n'ont pas d'espace de noms. Ils ne sont considérés comme uniques que parce qu'ils apparaissent sur un élément qui a lui-même un nom unique. Cependant, il est parfois nécessaire de définir des paramètres afin qu'ils puissent être réutilisés sur de nombreux éléments différents et être considérés comme le même paramètre, indépendamment de l'élément avec lequel ils sont utilisés. Un très bon exemple est le paramètre href défini par la spécification XLink. Ce paramètre est couramment utilisé par d'autres dialectes XML comme moyen de lier à des ressources externes. Mais comment indiquer à l'agent utilisateur à quel dialecte appartient le paramètre, dans ce cas XLink ? Considérez l'exemple suivant.
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<script xlink:href="cool-script.js" type="text/javascript" />
</svg>
Cet exemple présente le paramètre xmlns:xlink, qui peut sembler inhabituel. Comme vous pouvez le deviner à partir du premier xmlns, il s'agit d'une autre déclaration d'espace de noms. Cependant, au lieu de définir l'espace de noms par défaut, cette déclaration définit l'espace de noms pour ce qu'on appelle un « préfixe d'espace de noms ». Dans ce cas, nous avons choisi d'utiliser le préfixe xlink (la seconde partie) puisque ce préfixe servira à indiquer à l'agent utilisateur les attributs qui appartiennent à XLink.
Comme leur nom l'indique, les préfixes d'espaces de noms servent à préfixer les noms de paramètres et d'éléments. Cela se fait en plaçant le préfixe d'espace de noms et un deux-points avant le nom du paramètre, comme illustré sur l'élément <script> dans l'exemple ci-dessus. Cela indique à l'agent utilisateur que le paramètre en question appartient à l'espace de noms assigné au préfixe (XLink), et qu'il s'agit d'un paramètre pouvant être utilisé avec la même signification sur d'autres éléments.
Notez que, dans XML, il s'agit d'une erreur XML d'utiliser un préfixe qui n'a pas été lié à un nom d'espace de noms. L'association créée par le paramètre xmlns:xlink dans l'exemple ci-dessus est requise pour que le paramètre xlink:href ne provoque pas d'erreur. Ce paramètre XLink est également fréquemment utilisé dans SVG sur les éléments <a>, <use> et <image> entre autres, il est donc recommandé d'inclure systématiquement la déclaration XLink dans vos documents.
Par ailleurs, il est utile de savoir que les préfixes d'espaces de noms peuvent aussi être utilisés pour les noms d'éléments. Cela indique à l'agent utilisateur que l'élément en question (mais pas ses enfants cette fois !) appartient à l'espace de noms assigné au préfixe. Savoir cela vous évitera des confusions si vous rencontrez un balisage comme dans l'exemple suivant :
<html
lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:svg="http://www.w3.org/2000/svg">
<body>
<h1>SVG intégré en ligne dans XHTML</h1>
<svg:svg width="300px" height="200px">
<svg:circle cx="150" cy="100" r="50" fill="red" />
</svg:svg>
</body>
</html>
Note :
Il s'agit d'un fichier XHTML, et non d'un fichier HTML. Les espaces de noms XML ne sont pas valides en HTML. Pour essayer cet exemple, vous devez enregistrer votre fichier avec l'extension .xhtml.
Notez que, parce qu'un préfixe d'espace de noms est utilisé pour l'élément <svg:svg> et son enfant <svg:circle>, il n'a pas été nécessaire de redéclarer l'espace de noms par défaut. En général, il est préférable de redéclarer l'espace de noms par défaut plutôt que de préfixer de nombreux éléments de cette manière.
Scripting in namespaced XML
Namespaces affect markup and scripting (and even CSS). If you write scripts for namespaced XML such as SVG, read on.
The DOM Level 1 recommendation was created before the original Namespaces in XML recommendation was released; therefore, DOM1 isn't namespace-aware. This causes problems for namespaced XML such as SVG. To resolve these problems, DOM Level 2 Core added namespace-aware equivalents of all the applicable DOM Level 1 methods. When scripting SVG, it is important to use the namespace-aware methods. The table below lists the DOM1 methods that shouldn't be used in SVG, along with their equivalent DOM2 counterparts that should be used instead.
Le premier paramètre de toutes les méthodes DOM2 prenant en charge les espaces de noms doit être le nom de l'espace de noms (aussi appelé URI d'espace de noms) de l'élément ou du paramètre concerné. Pour les éléments SVG, il s'agit de http://www.w3.org/2000/svg. Cependant, attention : la recommandation Espaces de noms dans XML 1.1 (angl.) indique que le nom d'espace de noms pour les paramètres sans préfixe n'a pas de valeur. En d'autres termes, bien que les paramètres appartiennent à l'espace de noms de l'élément, vous n'utilisez pas le nom d'espace de noms de la balise. À la place, vous devez utiliser null comme nom d'espace de noms pour les paramètres non qualifiés (sans préfixe). Ainsi, pour créer un élément SVG rect avec document.createElementNS(), vous devez écrire :
document.createElementNS("http://www.w3.org/2000/svg", "rect");
Mais pour récupérer la valeur du paramètre x sur un élément SVG rect, vous devez écrire :
rect.getAttributeNS(null, "x");
Notez que ce n'est pas le cas pour les paramètres avec un préfixe d'espace de noms (paramètres qui n'appartiennent pas au même dialecte XML que l'élément). Les paramètres comme xlink:href nécessitent le nom d'espace de noms qui a été assigné à ce préfixe (http://www.w3.org/1999/xlink pour XLink). Ainsi, pour obtenir la valeur du paramètre xlink:href d'un élément <a> en SVG, vous écririez :
elt.getAttributeNS("http://www.w3.org/1999/xlink", "href");
Pour définir des paramètres qui ont un espace de noms, il est recommandé (mais pas obligatoire) d'inclure aussi leur préfixe dans le second paramètre afin que le DOM puisse être plus facilement reconverti en XML par la suite (par exemple, si vous souhaitez le renvoyer au serveur). Exemple :
elt.setAttributeNS(
"http://www.w3.org/1999/xlink",
"xlink:href",
"other-doc.svg",
);
Pour finir, voici un exemple montrant comment créer dynamiquement un élément <image> en JavaScript :
const SVG_NS = "http://www.w3.org/2000/svg";
const XLINK_NS = "http://www.w3.org/1999/xlink";
const image = document.createElementNS(SVG_NS, "image");
image.setAttributeNS(null, "width", "100");
image.setAttributeNS(null, "height", "100");
image.setAttributeNS(XLINK_NS, "xlink:href", "flower.png");
Conclusion
Pour SVG, HTML et MathML, l'espace de noms est implicite et donc optionnel. Il est obligatoire de déclarer l'espace de noms pour les fichiers XML. Si vous ne le faites pas, les agents utilisateur ne reconnaîtront pas le contenu et afficheront le balisage XML ou indiqueront qu'il y a une erreur dans le XML.
Lorsque vous écrivez du SVG, il est utile d'utiliser un modèle qui inclut toutes les déclarations d'espaces de noms courantes lors de la création de nouveaux fichiers. Si vous n'en avez pas déjà un, créez-en un en partant du code suivant :
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"></svg>
Même si vous n'utilisez pas tous ces espaces de noms dans un document particulier, il n'y a aucun inconvénient à inclure les déclarations d'espaces de noms. Cela peut vous éviter des erreurs gênantes si vous ajoutez plus tard du contenu provenant d'un des espaces de noms non utilisés.
Exemple complet
Pour un exemple complet, voir SVG : Cours accéléré sur les espaces de noms : Exemple.