• Aucun résultat trouvé

3.5. Entités

Les entités constituent un mécanisme hérité de SGML. Elles sont des macros semblables aux #define du langage C. Elles permettent également de réaliser des inclusions de documents comme la directive #include du langage C. Les entités sont définies dans la DTD du document. Il existe deux types d'entités. Les entités générales, appelées simplement entités dans cet ouvrage, sont destinées à être utilisées dans le corps du document. Les entités paramètres sont destinées à être utilisées au sein de la DTD.

Une entité est, en quelque sorte, un nom donné à un fragment de document. Ce fragment peut être donné explicitement à la définition de l'entité dans la DTD. Il peut également provenir d'un fichier externe. Dans ce cas, la définition de l'entité donne un FPI et/ou une URL permettant d'accéder au document. Le fragment de document peut être inséré dans le document en utilisant simplement le nom de l'entité. Lorsque le fragment provient d'un autre fichier, l'utilisation de l'entité provoque l'inclusion du fichier en question. Le nom de chaque entité générale ou paramètre doit être un nom XML [Section 2.2.3].

3.5.1. Entités générales

Les entités générales sont les entités les plus courantes et les plus utiles puisqu'elles peuvent être utilisées dans le corps du document.

3.5.1.1. Déclaration et référence

La déclaration d'une entité commence par <!ENTITY suivi du nom de l'entité. Elle prend une des trois formes suivantes où name est le nom de l'entité, fragment est un fragment de document, fpi et url sont un FPI et une URL.

<!ENTITY name "fragment">

<!ENTITY name SYSTEM "url">

<!ENTITY name PUBLIC "fpi" "url">

Lorsque l'entité est déclarée avec la première syntaxe, elle est dite interne car le fragment est explicitement donné dans la DTD du document. Lorsqu'elle est déclarée avec une des deux dernières syntaxes, elle est dite externe car le fragment provient d'un autre document. Ces deux dernières syntaxes sont semblables à la déclaration d'une DTD externe [Section 3.2.2] dans un document XML. Les règles pour l'utilisation des apostrophes ''' et des guillemets '"' sont identiques à celles pour les valeurs d'attributs [Section 2.7.3]. Le fragment, le FPI et l'URL doivent être délimités par une paire d'apostrophes ou de guillemets. Si le fragment est délimité par des apostrophes, les guillemets peuvent être introduits directement sans entité et inversement.

Une entité de nom name est référencée, c'est-à-dire utilisée, par &name; où le nom name de l'entité est encadré par les caractères '&' et ';'. Lorsque le document est traité, la référence à une entité est remplacée par le fragment de document correspondant. Une entité interne peut être référencée dans les contenus d'éléments et dans les valeurs d'attribut alors qu'une entité externe peut seulement être référencée dans les contenus d'éléments.

<tag meta="attribute: &name;">Content: &name;</tag>

3.5.1.2. Entités prédéfinies

Il existe des entités prédéfinies permettant d'inclure les caractères spéciaux [Section 2.2.1] '<', '>', '&', ''' et '"' dans les contenus d'éléments et dans les valeurs d'attributs. Ces entités sont les suivantes.

Entité Caractère

&lt; <

DTD

Entité Caractère

&gt; >

&amp; &

&apos; '

&quot; "

Tableau 3.1. Entités prédéfinies

Les trois entités &lt;, &gt; et &amp; doivent être utilisées aussi bien dans le contenus des éléments que dans les valeurs des attributs puisque les caractères '<', '>' et '&' ne peuvent pas y apparaître directement. Les deux entités &apos; et &quot; sont uniquement nécessaires pour inclure le caractère ''' ou le caractère '"' dans la valeur d'un attribut délimitée par le même caractère. Lors de l'utilisation XPath [Chapitre 6] avec XSLT [Chapitre 8], il n'est pas rare d'inclure ces deux caractères dans la valeur d'un attribut. Une des deux entités &apos;

ou &quot; devient alors indispensable. L'exemple suivant est extrait d'une feuille de style XSLT. La valeur de l'attribut test est une expression XPath qui teste si la valeur de la variable string contient le caractère '"'.

<xsl:when test="contains($string, '&quot;')">

Les nombreuses entités prédéfinies en XHTML comme &euro; pour le symbole '€' n'existent pas en XML. La seule façon d'inclure ce caractère est d'utiliser les notations &#point de code décimal; ou &#xpoint de code hexadécimal;. Il est cependant possible de définir ces propres entités (cf. ci-dessous).

3.5.1.3. Entités internes

La valeur d'une entité interne est le fragment de document associé à celle-ci lors de sa déclaration. Cette valeur peut contenir des caractères ainsi que des éléments avec leurs balises. Lorsqu'elle contient des éléments, le fragment doit être bien formé [Section 2.7.1]. À toute balise ouvrante doit correspondre une balise fermante et l'imbrication des balises doit être correcte. Quelques exemples d'entités internes sons donnés ci-dessous. Le dernier exemple utilise des apostrophes ''' pour délimiter le fragment de document qui contient des guillemets '"' pour encadrer les valeurs des attributs.

<!ENTITY aka "also known as">

<!ENTITY euro "&#x20AC;">

<!ENTITY rceil '<phrase condition="html">&#x2309;</phrase>

<phrase condition="fo" role="symbolfont">&#xF8F9;</phrase>'>

Si la DTD contient les déclarations d'entités ci-dessus, Il est possible d'inclure le texte also known as en écrivant seulement &aka; ou d'inclure un symbole en écrivant &euro;. Les entités internes peuvent être référencées dans les contenus d'éléments mais aussi dans les valeurs d'attributs.

<price currency="Euro (&euro;)">30 &euro;</price>

Il est possible d'utiliser des entités dans la définition d'une autre entité pourvu que ces entités soient également définies. L'ordre de ces définitions est sans importance car les substitutions sont réalisées au moment où le document est lu par l'analyseur de l'application. Les définitions récursives sont bien sûr interdites.

<!DOCTYPE book [

<!-- Entités internes -->

<!ENTITY mci "Michel Colucci &aka; 'Coluche'">

<!ENTITY aka "also known as">

]>

<book>&mci;</book>

Il faut faire attention au fait que certaines applications ne gèrent pas ou gèrent mal les entités définies. La solution est d'ajouter à la chaîne de traitement une première étape consistant à substituer les entités par leurs valeurs pour obtenir un document intermédiaire sans entités. Le logiciel xmllint peut par exemple réaliser cette opération.

Avec l'option --noent, il écrit sur la sortie standard le document en remplaçant chaque entité par sa valeur.

DTD

3.5.1.4. Entités externes

Une entité peut désigner un fragment de document contenu dans un autre fichier. Ce mécanisme permet de répartir un même document sur plusieurs fichiers comme dans l'exemple suivant. La déclaration utilise alors le mot clé SYSTEM suivi d'une URL qui peut, simplement, être le nom d'un fichier local.

Les entités externes peuvent êtres utilisées pour scinder un document en plusieurs fichiers. Le fichier principal inclut les différentes parties en définissant une entité externe pour chacune de ces parties. Les entités sont alors utilisées pour réaliser l'inclusion comme dans l'exemple ci-dessous.

<?xml version="1.0" encoding="utf-8"?>

<!DOCTYPE book [

<!-- Entités externes -->

<!ENTITY chapter1 SYSTEM "chapter1.xml">

<!ENTITY chapter2 SYSTEM "chapter2.xml">

]>

<book>

<!-- Inclusion du fichier chapter1.xml -->

&chapter1;

<!-- Inclusion du fichier chapter2.xml -->

&chapter2;

</book>

Chacun des fichiers contenant une entité externe peut avoir une entête [Section 2.6.1]. Celle-ci permet par exemple de déclarer un encodage des caractères différents du fichier principal. Ce mécanisme pour répartir un document en plusieurs fichiers est à abandonner au profit de XInclude [Section 2.9] qui est plus pratique.

3.5.2. Entités paramètres

Les entités paramètres sont des entités qui peuvent uniquement être utilisées à l'intérieur de la DTD. La terminologie est historique et provient de SGML. Ces entités ont le même rôle que les entités générales. Elles sont surtout utilisées pour apporter de la modularité aux DTD. La déclaration d'une entité paramètre prend une des trois formes suivantes où name est le nom de l'entité, fragment est un fragment de document, fpi et url sont un FPI et une URL.

<!ENTITY % name "fragment">

<!ENTITY % name SYSTEM "url">

<!ENTITY % name PUBLIC "fpi" "url">

La seule différence avec la déclaration d'une entité générale est la présence du caractère '%' entre le mot clé ENTITY et le nom de l'entité déclarée. Comme pour les entités générales, l'entité est dite interne lorsqu'elle est déclarée avec la première syntaxe. Elle est dite externe lorsqu'elle est déclarée avec une des deux dernières syntaxes. Les règles pour l'utilisation des apostrophes ''' et des guillemets '"' sont identiques à celles pour les valeurs d'attributs [Section 2.7.3] ou les entités générales [Section 3.5.1].

L'entité name ainsi déclarée peut être référencée, c'est-à-dire utilisée, par %name; où le nom de l'entité est encadré les caractères '%' et ';'. Les entités paramètres peuvent uniquement être utilisée au sein de la DTD.

Lorsque l'entité est interne, elle peut être utilisée dans les déclarations d'éléments, d'attributs et d'autres entités.

Cette utilisation est limitée à la partie externe de la DTD. Lorsque l'entité est externe, elle est utilisée en dehors des déclarations pour inclure des déclarations provenant du document référencé par l'entité. L'exemple suivant définit deux entités paramètres idatt et langatt permettant de déclarer des attributs id et xml:lang facilement.

<!-- Déclaration de deux entités paramètres -->

<!ENTITY % idatt "id ID #REQUIRED">

<!ENTITY % langatt "xml:lang NMTOKEN 'fr'">

<!-- Utilisation des deux entités paramètres -->

<!ATTLIST chapter %idatt; %langatt;>

DTD

<!ATTLIST section %langatt;>

Les entités paramètres ajoutent de la modularité qui est surtout nécessaire dans l'écriture de DTD de grande taille. Dans l'exemple précédent, l'attribut id pourrait être remplacé partout par un attribut xml:id en changeant uniquement la définition de l'entité paramètre idatt. Un autre exemple d'utilisation des entités paramètres est donné avec les DTD mixtes [Section 3.2.3]. Les entités externes permettent d'inclure une partie de DTD provenant d'un document externe comme dans l'exemple suivant.

<!-- Entité paramètre pour inclure la DTD principale -->

<!ENTITY % main SYSTEM "main.dtd">

<!-- Inclusion du fichier main.dtd -->

%main;