Manuel INF 6540 - Téluq
Transcription
Manuel INF 6540 - Téluq
Manuel INF 6540 Daniel Lemire, professeur responsable Kamel Aouiche, auxiliaire de recherche Lucie Moulet, auxiliaire de recherche Jean-François Savard, concepteur associé Renée Dumas, spécialiste en communication écrite Montréal, 4 avril 2009 Sommaire Sommaire iii Guide d’étude Introduction . . . . . . . . . . . . . . . . . . . . . . . Objectifs . . . . . . . . . . . . . . . . . . . . . . . . . Contenu . . . . . . . . . . . . . . . . . . . . . . . . . Problématique . . . . . . . . . . . . . . . . . . . . . Découplement des informations . . . . . . . . XML et interopérabilité . . . . . . . . . . . . Flexibilité et évolution des schémas de données Les modules du cours . . . . . . . . . . . . . . . . . . Caractéristiques médiatiques . . . . . . . . . . . . . . Encadrement . . . . . . . . . . . . . . . . . . . . . . L’évaluation . . . . . . . . . . . . . . . . . . . . . . . Les travaux notés . . . . . . . . . . . . . . . Examen en salle . . . . . . . . . . . . . . . . Gestion du temps et pondération . . . . . . . . . . . . Version PDF du cours . . . . . . . . . . . . . . . . . . Remerciements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1 1 2 2 3 3 4 5 6 6 7 7 8 8 10 11 Module 1 : Introduction à XML 1.1 Aperçu . . . . . . . . . . . . . . . . . . . . . . . . . . 1.1.1 Objectifs . . . . . . . . . . . . . . . . . . . . . 1.1.2 Qu’est-ce que le XML? . . . . . . . . . . . . . . 1.1.3 Démarche . . . . . . . . . . . . . . . . . . . . . 1.2 Installation de Mozilla Firefox . . . . . . . . . . . . . . 1.2.1 Objectif . . . . . . . . . . . . . . . . . . . . . . 1.2.2 Activité . . . . . . . . . . . . . . . . . . . . . . 1.2.3 Installation de polices de caractères optionnelles 1.2.4 Avertissement . . . . . . . . . . . . . . . . . . . 1.2.5 Autres navigateurs . . . . . . . . . . . . . . . . 1.2.6 Retour . . . . . . . . . . . . . . . . . . . . . . . 1.3 Création de documents XML . . . . . . . . . . . . . . . 1.3.1 Objectif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 13 13 13 14 15 15 15 16 16 16 16 16 16 iii iv 1.3.2 1.4 1.5 1.6 Activité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Autres éditeurs pour le XML . . . . . . . . . . . . . . . . . . 1.3.3 Retour . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Introduction à XML . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.4.1 Objectif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.4.2 Activité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.4.3 Quelques notions du XML . . . . . . . . . . . . . . . . . . . 1.4.4 La philosophie du XML . . . . . . . . . . . . . . . . . . . . 1.4.5 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . Principes de XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.5.1 Objectif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.5.2 Activité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.5.3 Quelques principes et notions importantes du XML . . . . . . 1.5.4 Points importants dans la syntaxe de base . . . . . . . . . . . 1.5.5 Dans l’ordre ou dans le désordre . . . . . . . . . . . . . . . . 1.5.6 Appels d’entités . . . . . . . . . . . . . . . . . . . . . . . . 1.5.7 Les commentaires . . . . . . . . . . . . . . . . . . . . . . . 1.5.8 Les instructions de traitement . . . . . . . . . . . . . . . . . 1.5.9 Jeux de caractères . . . . . . . . . . . . . . . . . . . . . . . 1.5.10 La déclaration XML . . . . . . . . . . . . . . . . . . . . . . 1.5.11 Les espaces . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.5.12 Les fins de ligne . . . . . . . . . . . . . . . . . . . . . . . . 1.5.13 Les hyperliens . . . . . . . . . . . . . . . . . . . . . . . . . 1.5.14 Documents bien formés . . . . . . . . . . . . . . . . . . . . Définition de type de document . . . . . . . . . . . . . . . . . . . . . 1.6.1 Objectif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.6.2 Activité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.6.3 Document XML valable . . . . . . . . . . . . . . . . . . . . 1.6.4 Normes de définition de type de document . . . . . . . . . . . 1.6.5 Documents valables utilisant la norme DTD . . . . . . . . . . 1.6.6 La syntaxe des documents DTD . . . . . . . . . . . . . . . . 1.6.7 Exemple supplémentaire . . . . . . . . . . . . . . . . . . . . 1.6.8 Les attributs . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.6.9 Les entités . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.6.10 DTD interne et externe . . . . . . . . . . . . . . . . . . . . . 1.6.11 Les entités paramètres . . . . . . . . . . . . . . . . . . . . . 1.6.12 Commentaires dans les fichiers DTD . . . . . . . . . . . . . 1.6.13 Une comparaison entre Relax NG et DTD . . . . . . . . . . . 1.6.14 Une approche plus modulaire . . . . . . . . . . . . . . . . . 1.6.15 Définir l’élément-racine . . . . . . . . . . . . . . . . . . . . 1.6.16 Définir le type de contenu en Relax NG . . . . . . . . . . . . 1.6.17 Est-ce qu’il existe un outil pour passer d’un format à l’autre (DTD, Relax NG, XML Schema)? . . . . . . . . . . . . . . . 1.6.18 Est-ce qu’un document DTD est un document XML? . . . . . 1.6.19 Pourquoi est-ce qu’il n’est pas suffisant d’utiliser des documents bien formés? À quoi sert la validation? . . . . . . . . . 16 18 18 19 19 19 19 21 22 22 22 23 23 25 25 25 26 27 27 28 29 30 30 30 31 31 31 31 32 34 35 37 37 39 40 40 41 41 45 46 47 47 48 48 CC BY-NC-SA v 1.7 1.8 1.9 1.6.20 Est-ce vraiment nécessaire d’avoir des documents valables? Est-ce que je dois vraiment toujours travailler avec des fichiers DTD, XML Schema ou Relax NG? . . . . . . . . . . . . . . . 1.6.21 Livres de référence . . . . . . . . . . . . . . . . . . . . . . . La validation des documents XML . . . . . . . . . . . . . . . . . . . 1.7.1 Objectif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.7.2 Activité de validation . . . . . . . . . . . . . . . . . . . . . . Procédure pour valider des documents XML . . . . . . . . . Vérification de la procédure . . . . . . . . . . . . . . . . . . 1.7.3 Retour . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Espaces de noms . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.8.1 Objectif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.8.2 Activité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.8.3 Les vocabulaires XML . . . . . . . . . . . . . . . . . . . . . 1.8.4 Les identificateurs de ressources uniformes (URI) . . . . . . . 1.8.5 Les espaces de noms . . . . . . . . . . . . . . . . . . . . . . 1.8.6 Les DTD et les espaces de noms . . . . . . . . . . . . . . . . 1.8.7 Déclaration de l’espace de noms . . . . . . . . . . . . . . . . 1.8.8 Les déclarations croisées . . . . . . . . . . . . . . . . . . . . 1.8.9 Le préfixe par défaut . . . . . . . . . . . . . . . . . . . . . . 1.8.10 Rappel des notions formelles . . . . . . . . . . . . . . . . . . 1.8.11 Les espaces de noms et Relax NG . . . . . . . . . . . . . . . 1.8.12 Le préfixe « xml » . . . . . . . . . . . . . . . . . . . . . . . 1.8.13 Rappel : des espaces de noms pour les attributs? . . . . . . . 1.8.14 En résumé, qu’est-ce que les espaces de noms? . . . . . . . . Travail noté 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.9.1 Objectifs et pondération . . . . . . . . . . . . . . . . . . . . 1.9.2 Consignes . . . . . . . . . . . . . . . . . . . . . . . . . . . . Question 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . Question 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . Question 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . Question 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . Question 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . Question 6 . . . . . . . . . . . . . . . . . . . . . . . . . . . Question 7 . . . . . . . . . . . . . . . . . . . . . . . . . . . Question 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . Question 9 . . . . . . . . . . . . . . . . . . . . . . . . . . . Question 10 . . . . . . . . . . . . . . . . . . . . . . . . . . . Question 11 . . . . . . . . . . . . . . . . . . . . . . . . . . . Module 2 : XML en tant que syntaxe pour les documents 2.1 Aperçu . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1.1 Objectifs . . . . . . . . . . . . . . . . . . . . 2.1.2 Démarche . . . . . . . . . . . . . . . . . . . . 2.2 Introduction au XHTML . . . . . . . . . . . . . . . . 2.2.1 Objectif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 48 49 49 49 49 53 54 54 54 54 54 55 55 55 56 59 59 60 61 61 62 62 62 62 62 63 63 64 65 66 66 67 67 68 68 69 71 71 71 71 72 72 CC BY-NC-SA vi 2.3 2.4 2.5 2.6 2.2.2 Activité . . . . . . . . . . . . . . . . . . . . . . . . 2.2.3 Qu’est-ce que le XHTML? . . . . . . . . . . . . . . 2.2.4 La structure du document XHTML : head et body . . 2.2.5 Les paragraphes en HTML . . . . . . . . . . . . . . 2.2.6 Les listes en HTML . . . . . . . . . . . . . . . . . 2.2.7 Les tableaux en HTML . . . . . . . . . . . . . . . . 2.2.8 Les caractères italiques et gras . . . . . . . . . . . . 2.2.9 Les listes de définitions . . . . . . . . . . . . . . . . 2.2.10 Les lignes horizontales . . . . . . . . . . . . . . . . 2.2.11 Les images . . . . . . . . . . . . . . . . . . . . . . 2.2.12 Les hyperliens . . . . . . . . . . . . . . . . . . . . 2.2.13 Les abbréviations . . . . . . . . . . . . . . . . . . . 2.2.14 Les adresses . . . . . . . . . . . . . . . . . . . . . 2.2.15 Les indices et exposants . . . . . . . . . . . . . . . 2.2.16 Le code et les exemples . . . . . . . . . . . . . . . 2.2.17 Les citations . . . . . . . . . . . . . . . . . . . . . 2.2.18 Les révisions . . . . . . . . . . . . . . . . . . . . . 2.2.19 La langue . . . . . . . . . . . . . . . . . . . . . . . 2.2.20 Les commentaires . . . . . . . . . . . . . . . . . . 2.2.21 Séparation du contenu et de la présentation . . . . . 2.2.22 SVG . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2.23 MathML . . . . . . . . . . . . . . . . . . . . . . . 2.2.24 Convertir du HTML mal formé . . . . . . . . . . . . 2.2.25 Spécification Relax NG . . . . . . . . . . . . . . . . 2.2.26 HTML 5 . . . . . . . . . . . . . . . . . . . . . . . 2.2.27 Conclusion . . . . . . . . . . . . . . . . . . . . . . 2.2.28 Livres de référence . . . . . . . . . . . . . . . . . . 2.2.29 Activité d’autoévaluation . . . . . . . . . . . . . . . XML comme format de documents . . . . . . . . . . . . . . 2.3.1 Objectif . . . . . . . . . . . . . . . . . . . . . . . 2.3.2 Activité . . . . . . . . . . . . . . . . . . . . . . . . 2.3.3 Le SGML (Standardized General Markup Language) 2.3.4 Le XML comme format de documents . . . . . . . . 2.3.5 Le format DocBook . . . . . . . . . . . . . . . . . 2.3.6 L’ODF (Open Document Format) . . . . . . . . . . XML sur le web . . . . . . . . . . . . . . . . . . . . . . . . 2.4.1 Objectif . . . . . . . . . . . . . . . . . . . . . . . 2.4.2 Activité . . . . . . . . . . . . . . . . . . . . . . . . 2.4.3 Le XHTML et le web . . . . . . . . . . . . . . . . Travail noté 2 . . . . . . . . . . . . . . . . . . . . . . . . . 2.5.1 Objectifs et pondération . . . . . . . . . . . . . . . 2.5.2 Consignes . . . . . . . . . . . . . . . . . . . . . . . En cas de panne . . . . . . . . . . . . . . . . . . . . Pistes de discussion . . . . . . . . . . . . . . . . . . 2.5.3 Critères de correction et de notation . . . . . . . . . Travail noté 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 72 74 74 76 77 79 79 80 80 81 81 81 82 82 82 82 82 83 83 83 85 85 85 92 93 93 94 94 94 94 94 95 96 101 102 102 102 102 104 104 105 105 106 106 107 CC BY-NC-SA vii 2.6.1 2.6.2 2.6.3 Objectifs, pondération et critères de correction Description du travail . . . . . . . . . . . . . . Consignes . . . . . . . . . . . . . . . . . . . Annexe 1. Document XSLT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107 . 107 . 108 . 110 Module 3 : Technologies XML 3.1 Aperçu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1.1 Objectifs . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1.2 Démarche . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2 XSLT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2.1 Objectif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2.2 Activité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2.3 Un regard critique . . . . . . . . . . . . . . . . . . . . . . . 3.2.4 Les machines de Turing et la technologie XML . . . . . . . . 3.2.5 Qu’est-ce que le XSLT . . . . . . . . . . . . . . . . . . . . . 3.2.6 Les langages déclaratifs . . . . . . . . . . . . . . . . . . . . 3.2.7 Les fichiers XSLT . . . . . . . . . . . . . . . . . . . . . . . 3.2.8 « Éléments xsl:template » . . . . . . . . . . . . . . . . . . . 3.2.9 « Éléments xsl:value-of » . . . . . . . . . . . . . . . . . . . . 3.2.10 Arithmétique en XPath . . . . . . . . . . . . . . . . . . . . . 3.2.11 Manipulations des chaînes de caractères en XPath . . . . . . . 3.2.12 Chemins XPath plus sophistiqués . . . . . . . . . . . . . . . 3.2.13 Modularité avec les éléments « xsl:apply-templates » . . . . . 3.2.14 Chemins XPath pour la sélection des attributs . . . . . . . . . 3.2.15 Expression XPath « . » . . . . . . . . . . . . . . . . . . . . . 3.2.16 Spécifier les valeurs d’attributs . . . . . . . . . . . . . . . . . 3.2.17 Expression XPath « .. » . . . . . . . . . . . . . . . . . . . . . 3.2.18 Expression XPath « // » . . . . . . . . . . . . . . . . . . . . 3.2.19 Expression XPath « * » . . . . . . . . . . . . . . . . . . . . 3.2.20 Expression XPath avec « | » . . . . . . . . . . . . . . . . . . 3.2.21 Expression XPath pour le nom d’un élément . . . . . . . . . 3.2.22 Notion de nœuds XSLT . . . . . . . . . . . . . . . . . . . . . 3.2.23 Expressions XPath pour compter et additionner les éléments . 3.2.24 Utilisation de l’attribut « mode » . . . . . . . . . . . . . . . . 3.2.25 Fonction « generate-id » . . . . . . . . . . . . . . . . . . . . 3.2.26 Utilisation des tests . . . . . . . . . . . . . . . . . . . . . . . 3.2.27 Tester le contenu des chaînes de caractères . . . . . . . . . . 3.2.28 Accès aux éléments d’un ensemble d’éléments . . . . . . . . 3.2.29 Utiliser XSLT comme base de données et éléments « for-each » 3.2.30 Obtenir l’aggrégation avec la fonction « generate-id » . . . . . 3.2.31 Un peu plus de performance avec la function XSLT « key » . 3.2.32 Les variables . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2.33 Les paramètres . . . . . . . . . . . . . . . . . . . . . . . . . 3.2.34 Générer un commentaire . . . . . . . . . . . . . . . . . . . . 3.2.35 Créer des éléments dynamiquement avec « xsl:element » . . . 3.2.36 Copier des nœuds avec « xsl:copy » et « xsl:copy-of » . . . . 113 113 113 113 114 114 114 114 114 115 116 116 118 119 120 121 122 124 127 129 130 130 131 131 131 132 132 134 135 137 138 139 140 141 144 148 149 150 152 152 153 CC BY-NC-SA viii 3.3 3.2.37 3.2.38 3.2.39 3.2.40 3.2.41 3.2.42 3.2.43 3.2.44 3.2.45 3.2.46 3.2.47 3.2.48 3.2.49 3.2.50 3.2.51 CSS . 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.3.7 3.3.8 3.3.9 3.3.10 3.3.11 3.3.12 3.3.13 3.3.14 3.3.15 3.3.16 3.3.17 3.3.18 3.3.19 3.3.20 3.3.21 3.3.22 3.3.23 3.3.24 3.3.25 3.3.26 3.3.27 3.3.28 3.3.29 3.3.30 Union, intersection et différence en XSLT . . . . . . . Espaces de noms . . . . . . . . . . . . . . . . . . . . Les axes . . . . . . . . . . . . . . . . . . . . . . . . . L’étude d’un exemple: docbook.xslt . . . . . . . . . . Activité suggérée . . . . . . . . . . . . . . . . . . . . Autres moteurs XSLT . . . . . . . . . . . . . . . . . Pour voir le résultat de la transformation XSLT . . . . SVG et XSLT . . . . . . . . . . . . . . . . . . . . . . XPath, XPointer et XLink . . . . . . . . . . . . . . . XPath 2.0 . . . . . . . . . . . . . . . . . . . . . . . . XLT 2.0 . . . . . . . . . . . . . . . . . . . . . . . . . XQuery . . . . . . . . . . . . . . . . . . . . . . . . . XPath versus XSLT . . . . . . . . . . . . . . . . . . . En terminant . . . . . . . . . . . . . . . . . . . . . . Livres de référence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Objectif . . . . . . . . . . . . . . . . . . . . . . . . . Activité . . . . . . . . . . . . . . . . . . . . . . . . . Qu’est-ce que les CSS . . . . . . . . . . . . . . . . . Point de vue critique . . . . . . . . . . . . . . . . . . Notions de base . . . . . . . . . . . . . . . . . . . . . Contenu en ligne ou en bloc ? . . . . . . . . . . . . . Centrer un élément . . . . . . . . . . . . . . . . . . . Les commentaires . . . . . . . . . . . . . . . . . . . Sélectionner le premier caractère ou la première ligne . Ajouter du contenu avant et après un élément . . . . . Qu’est-ce qu’un pseudo-élément? . . . . . . . . . . . Sélecteurs d’intéraction . . . . . . . . . . . . . . . . . Règles par défaut . . . . . . . . . . . . . . . . . . . . L’astérisque . . . . . . . . . . . . . . . . . . . . . . . Sélection sur la base des attributs . . . . . . . . . . . Les espaces de noms . . . . . . . . . . . . . . . . . . Sélection de la langue . . . . . . . . . . . . . . . . . Sélection de plusieurs éléments . . . . . . . . . . . . Sélection sur la base de la relation entre les éléments . Sélection d’élément par valeur ID . . . . . . . . . . . Mais que se passe-t-il en cas de conflit? . . . . . . . . Le modèle de boîte CSS . . . . . . . . . . . . . . . . Quand le contenu excède le contenant . . . . . . . . . Encodage des caractères . . . . . . . . . . . . . . . . Différentes règles pour différents média . . . . . . . . Inclure d’autres fichiers CSS . . . . . . . . . . . . . . Indentation de la première ligne d’un paragraphe . . . Modifier la casse du texte . . . . . . . . . . . . . . . Autres variantes des polices . . . . . . . . . . . . . . Ajouter des compteurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154 155 156 157 160 160 160 161 161 162 163 163 167 167 167 168 168 168 168 168 169 171 172 172 172 172 173 173 173 175 175 176 176 176 177 178 179 181 183 183 183 184 184 184 184 185 CC BY-NC-SA ix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185 186 187 188 188 188 188 188 189 189 191 191 192 Module 4 : Traitement du XML en Java 4.1 Aperçu . . . . . . . . . . . . . . . . . . . . . 4.1.1 Objectifs . . . . . . . . . . . . . . . 4.1.2 Démarche . . . . . . . . . . . . . . . 4.2 Modèles de programmation . . . . . . . . . . 4.2.1 Objectif . . . . . . . . . . . . . . . . 4.2.2 Activité . . . . . . . . . . . . . . . . 4.2.3 Traitement du XML comme du texte . 4.2.4 Traitement événementiel . . . . . . . 4.2.5 Traitement avec itérateurs . . . . . . 4.2.6 Traitement avec modèle en arbre . . . 4.2.7 Transformations . . . . . . . . . . . 4.2.8 XPath . . . . . . . . . . . . . . . . . 4.2.9 XML comme extension d’un langage 4.2.10 Traitement par abstraction . . . . . . 4.2.11 Sérialisation XML . . . . . . . . . . 4.2.12 Services web . . . . . . . . . . . . . 4.3 Rappel sur la programmation Java . . . . . . 4.3.1 Objectif . . . . . . . . . . . . . . . . 4.3.2 Activité . . . . . . . . . . . . . . . . 4.3.3 Définitions . . . . . . . . . . . . . . Notion d’objet . . . . . . . . . . . . Notion de classe . . . . . . . . . . . Notion de méthode . . . . . . . . . . Notion d’interface . . . . . . . . . . Notion d’héritage . . . . . . . . . . . Notion d’encapsulation . . . . . . . . 4.3.4 Exemples . . . . . . . . . . . . . . . 4.3.5 Exemples avancés . . . . . . . . . . 4.3.6 Lecture de fichiers . . . . . . . . . . 4.3.7 Astuces . . . . . . . . . . . . . . . . 4.3.8 Retour sur l’activité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193 193 193 194 194 194 194 195 196 199 200 201 202 202 203 203 205 209 209 210 210 210 210 210 210 211 211 211 212 212 213 213 3.4 3.3.31 Traitement des retours de chariot 3.3.32 Des nouveautés en CSS 3 . . . 3.3.33 Optimisation des fichiers CSS . 3.3.34 En terminant . . . . . . . . . . 3.3.35 Livres de référence . . . . . . . Travail noté 4 . . . . . . . . . . . . . . 3.4.1 Objectifs et pondération . . . . 3.4.2 Consignes . . . . . . . . . . . . 3.4.3 Exercice 1 . . . . . . . . . . . 3.4.4 Exercice 2 . . . . . . . . . . . . 3.4.5 Exercice 3 . . . . . . . . . . . . 3.4.6 Exercice 4 . . . . . . . . . . . . 3.4.7 Exercice 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . CC BY-NC-SA x 4.4 Tutoriel sur DOM . . . . . . . . . . . . . . . . . . . 4.4.1 Objectifs . . . . . . . . . . . . . . . . . . . 4.4.2 Activité . . . . . . . . . . . . . . . . . . . . 4.4.3 Le tutoriel pour se familiariser avec le DOM Introduction . . . . . . . . . . . . . . . . . 4.4.4 Notions de base . . . . . . . . . . . . . . . . 4.4.5 Point de vue critique . . . . . . . . . . . . . 4.4.6 Un document XML . . . . . . . . . . . . . . 4.4.7 Charger un document XML en Java . . . . . 4.4.8 Accès à l’élément-racine . . . . . . . . . . . 4.4.9 L’interface « Node » . . . . . . . . . . . . . 4.4.10 Création de documents . . . . . . . . . . . . 4.4.11 Modifier un « Document » . . . . . . . . . . 4.4.12 Les espaces de noms . . . . . . . . . . . . . 4.4.13 Deux problèmes avec solution . . . . . . . . Problème 1 . . . . . . . . . . . . . . . . . . Solution du problème 1 . . . . . . . . . . . . Problème 2 . . . . . . . . . . . . . . . . . . Solution du problème 2 . . . . . . . . . . . . 4.4.14 DOM et ECMAScript . . . . . . . . . . . . 4.4.15 Asynchronous JavaScript And XML (AJAX) 4.4.16 DOM et autres langages . . . . . . . . . . . 4.4.17 Conclusion . . . . . . . . . . . . . . . . . . 4.4.18 Livres de référence . . . . . . . . . . . . . . DOM . . . . . . . . . . . . . . . . . . . . . . . . . 4.5.1 Objectif . . . . . . . . . . . . . . . . . . . . 4.5.2 Activité . . . . . . . . . . . . . . . . . . . . Travail noté 5 . . . . . . . . . . . . . . . . . . . . . 4.6.1 Objectifs et pondération . . . . . . . . . . . 4.6.2 Consignes générales . . . . . . . . . . . . . 4.6.3 Exercice 1 . . . . . . . . . . . . . . . . . . . 4.6.4 Exercice 2 . . . . . . . . . . . . . . . . . . . 4.6.5 Exercice 3 . . . . . . . . . . . . . . . . . . . 4.6.6 Exercice 4 . . . . . . . . . . . . . . . . . . . 4.6.7 Exercice 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213 213 213 213 213 214 214 214 215 215 216 221 225 226 228 228 228 229 229 231 232 237 237 237 238 238 238 238 238 239 240 241 242 243 244 Module 5 : Resource Description Framework (RDF) 5.1 Aperçu . . . . . . . . . . . . . . . . . . . . . . . . . 5.1.1 Objectifs . . . . . . . . . . . . . . . . . . . 5.1.2 Représentation des connaissances et graphes 5.1.3 Démarche . . . . . . . . . . . . . . . . . . 5.1.4 Préparation à l’examen . . . . . . . . . . . 5.1.5 Évaluation du cours . . . . . . . . . . . . . 5.2 Introduction au RDF . . . . . . . . . . . . . . . . . 5.2.1 Introduction . . . . . . . . . . . . . . . . . . 5.2.2 Point de vue critique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245 245 245 245 246 247 247 247 247 247 4.5 4.6 CC BY-NC-SA xi 5.3 5.4 5.2.3 Notions de base . . . . . . . . . . . . . . . . . 5.2.4 Le RDF en XML . . . . . . . . . . . . . . . . 5.2.5 Les classes en RDF . . . . . . . . . . . . . . . 5.2.6 Et s’il n’y a pas de symbole « # » dans l’URI? . 5.2.7 Des objets qui sont eux-mêmes des sujets . . . 5.2.8 Les contenants en RDF . . . . . . . . . . . . . 5.2.9 RDFa . . . . . . . . . . . . . . . . . . . . . . 5.2.10 Conclusion . . . . . . . . . . . . . . . . . . . Le RDF par l’exemple . . . . . . . . . . . . . . . . . 5.3.1 Introduction . . . . . . . . . . . . . . . . . . . 5.3.2 Un exemple : Dublin Core . . . . . . . . . . . 5.3.3 Un exemple : Creative Commons . . . . . . . 5.3.4 Un exemple : FOAF . . . . . . . . . . . . . . 5.3.5 Un exemple : RSS/RDF . . . . . . . . . . . . . 5.3.6 Conclusion . . . . . . . . . . . . . . . . . . . Travail noté 6 . . . . . . . . . . . . . . . . . . . . . . 5.4.1 Objectifs et pondération . . . . . . . . . . . . 5.4.2 Consignes . . . . . . . . . . . . . . . . . . . . 5.4.3 Exercice 1 . . . . . . . . . . . . . . . . . . . . 5.4.4 Exercice 2 . . . . . . . . . . . . . . . . . . . . 5.4.5 Exercice 3 . . . . . . . . . . . . . . . . . . . . 5.4.6 Exercice 4 . . . . . . . . . . . . . . . . . . . . 5.4.7 Exercice 5 . . . . . . . . . . . . . . . . . . . . 5.4.8 Exercice 6 . . . . . . . . . . . . . . . . . . . . Avant de réaliser l’exercice... . . . . . . . . . Exercice à réaliser... . . . . . . . . . . . . . . 5.4.9 Exercice 7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Annexe A : Glossaire Annexe B : Webographie XML 1 Blogues . . . . . . . . . . . . . . . . . . . . . . . 2 Cours en ligne, en français . . . . . . . . . . . . . 3 Cours en ligne, en anglais . . . . . . . . . . . . . . 4 Liens généraux, en français . . . . . . . . . . . . . 5 Articles, en français . . . . . . . . . . . . . . . . . 6 Articles, en anglais . . . . . . . . . . . . . . . . . 7 Références tirées du site Wikipedia (anglais) . . . . 7.1 Spécification XML . . . . . . . . . . . . . 7.2 Software . . . . . . . . . . . . . . . . . . 7.3 Ressources pour les développeurs . . . . . 8 Liens vers des livres portant sur le XML, en anglais 248 252 256 257 258 261 263 263 263 263 264 268 272 274 276 277 277 277 278 278 278 279 279 279 279 281 282 283 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287 287 287 287 287 288 288 288 288 288 288 289 Annexe C : Pense-bête DTD 291 Annexe D : Pense-bête HTML 293 CC BY-NC-SA xii Annexe E : Pense-bête XSLT Bibliographie 295 299 CC BY-NC-SA Guide d’étude Introduction Bienvenue dans le cours INF 6450 Gestion de l’information avec XML. Mon nom est Daniel Lemire et je suis le professeur de ce cours. J’anime un blogue sur le XML à l’adresse http://www.daniel-lemire.com/ blogue/category/xml/. Avertissement: le site web du cours utilise une technique HTML qui rend l’utilisation du bouton « Reculer d’une page » hasardeuse. Ce document contient toutes les informations utiles à votre démarche dans le cours. Je vous suggère, avant de commencer l’étude du premier module, de prendre connaissance des objectifs du cours, de son contenu, de sa problématique, de son organisation en modules, des caractéristiques médiatiques de son environnement, ainsi que des propositions de répartition de votre temps d’étude pendant les quinze semaines du cours. Normalement, vous étudierez les modules de façon séquentielle; des indications plus précises sont fournies dans chaque module quant aux liens entre les différentes activités. L’installation du navigateur Firefox est obligatoire pour suivre ce cours; c’est d’ailleurs la première activité du module 1. Objectifs Le but de ce cours est de vous donner tous les outils nécessaires pour utiliser le XML dans un projet en technologie de l’information, que ce soit un projet de développement logiciel, un projet scientifique, ou dans le cadre d’un système d’informations. Il est aussi une préparation utile pour des travaux en gestion des connaissances, recherche d’informations, bibliothéconomie, e-Learning, génie logiciel, web sémantique, etc. Les objectifs du cours sont : – Utiliser un « vocabulaire » ou une application XML pour présenter des informations en format XML. 1 Guide d’étude 2 – Déterminer si un document XML est bien formé ou valable. – Apprécier les coûts de développement de solutions XML au sein d’une organisation. – Appliquer la méthodologie orientée objet pour l’utilisation, la fusion et le filtrage des fichiers XML. – Produire et interpréter des fichiers XML : des fichiers les plus simples aux fichiers RDF. – Utiliser des transformations XSLT et des instructions CSS. – Traduire, au sein de son organisation, sa compréhension du XML dans la gestion des informations. – Interpréter un fichier RDF comme un tableau sujet/verbe/objet. Contenu Dans ce cours, nous traiterons des points suivants : – Historique, raisons qui ont entraîné la création du XML, comparaison avec HTML et SGML – Le document XML : syntaxe, éléments, attributs et entités – Documents bien formés – Documents valables : Document Type Definitions (DTD), XML Schema, Relax NG, Schematron et Examplotron – Vocabulaires et espaces de noms – Le XML comme format de document: XHTML, SVG, MathML, Open Document Format et DocBook. – Modélisation de l’information en XML – XML, XSLT, XPath, XLink, XPointer, XQuery, CSS – Utilisation du XML à partir de langages orientés objets (Java, JavaScript, C++) – Modèle objet XML (DOM) – Asynchronous JavaScript And XML (AJAX) – Filtrage, fusion et extraction du XML en Java – Métadonnées en XML : Resource Description Framework (RDF), Dublin Core, Creative Commons, FOAF, RSS 1.0, web sémantique. Le cours ne traite pas en profondeur des technologies propriétaires telles que celles d’Oracle ou de Microsoft. Le cours n’en demeure pas moins axée sur la pratique : tous les concepts introduits dans le cours sont mis en application. Parce que le cours se veut une préparation à l’utilisation du XML dans des projets concrets, les avantages et les inconvénients des diverses techniques sont présentés. Problématique La gestion des connaissances se fait de plus en plus en utilisant la technologie du web, qui se tourne elle-même vers les données semi-structurées et la syntaxe XML, en CC BY-NC-SA Problématique 3 particulier. Le XML (Extensible Markup Language) est la norme dans l’échange des données sur le web et au sein des organisations, tout en étant un des piliers du web sémantique. Les applications et outils supportant le XML, que ce soit pour l’analyse syntaxique, le filtrage ou autres activités, sont maintenant très sophistiqués, nombreux et s’appliquent à des domaines variés. Pour s’en convaincre, il suffit de voir la liste des acronymes et les sujets auxquels ils correspondent : OWL (ontologies), RDF (description des ressources), XSL (transformations et présentation), RuleML (logique), etc. Dans une organisation, le XML joue un rôle sur au moins trois plans : 1. Découplement des informations; 2. Interopérabilité; 3. Flexibilité et évolution des schémas de données. Découplement des informations Dans la gestion des connaissances, le XML joue souvent un rôle dans le découplement des informations : métadonnées versus données, présentation versus contenu, implémentation versus logique, etc. L’ubiquité du XML et des outils le supportant permet, par exemple, de découpler de façon pratique le système d’exploitation et le logiciel de traitement de texte utilisé : les fichiers Open Office et les nouveaux fichiers Microsoft Office sont en format XML, permettant ainsi, en principe, à n’importe quelle plateforme logicielle d’aller chercher le contenu, le texte. Cette interopérabilité n’était pas possible avec le format binaire « traditionnel » que Microsoft utilisait dans les années 90. Le nouveau format utilisé par Microsoft Word distingue nettement la présentation du contenu. De la même manière, le format XHTML permet de laisser le contenu textuel semi-structuré dans le fichier lui-même et de placer la présentation dans un fichier CSS. D’autre part, tout fichier XHTML peut être facilement traité par un analyseur de syntaxe XML générique, peu importe la plateforme avec laquelle il a été produit. Au contraire, le HTML « traditionnel » exige des analyseurs de syntaxe spécifiques au HTML et de conception très robuste. XML et interopérabilité Pour une organisation, le fait de stocker, ou du moins de pouvoir transformer, les informations et les connaissances en XML rend beaucoup plus facile qu’auparavant le partage de ces mêmes informations et connaissances. En principe, n’importe qui peut traiter les fichiers XML provenant de n’importe quelle organisation en utilisant un logiciel générique. Dans une certaine mesure, on se met à l’abri du blocage de la part d’un fournisseur (vendor locking), ce qui a tant nui à plusieurs organisations dans le passé. Par exemple, c’était le cas d’une entreprise qui utilisait, pour une fonction stratégique, un logiciel conçu par une société qui devait fermer ou qui refusait de fournir une fonction particulière pourtant nécessaire. Si les informations sont en format XML, il est possible, du moins en théorie, pour une organisation d’extraire avec précision CC BY-NC-SA Guide d’étude 4 l’information et de la traiter; il lui suffit d’utiliser n’importe quel analyseur de syntaxe XML et de comprendre l’application XML utilisée. Pensons à une entreprise distribuée qui, pour collaborer, doit non seulement s’entendre sur une ontologie commune entre ses différentes constituantes, mais aussi définir un protocole d’échange des informations et connaissances. Comme le XML s’est imposé en tant que norme, le problème est simplifié : il suffit maintenant de « seulement » s’entendre sur un vocabulaire. Le XML fournit non seulement la syntaxe, mais aussi les outils nécessaires pour vérifier qui respecte ou ne respecte pas la syntaxe. Les outils pour modifier, traiter, fusionner le XML ne sont plus spécifiques aux besoins d’une entreprise ou d’un type d’entreprise : tous partagent les mêmes outils de base, car tous utilisent la même syntaxe. Les problèmes d’intégration sont donc plus faciles à résoudre et on passe moins de temps à faire de la rétro-ingénierie (reverse-engineering). Il faut évidemment toujours bien documenter et comprendre les vocabulaires, mais un lot de problèmes purement techniques sont balayés. Pensons également aux projets récents portant sur les objets d’apprentissage sur lesquels travaille la Télé-université. La plupart de ces projets sont constitués en réseaux : on désire échanger des objets d’apprentissage entre des individus qui ne se rencontrent jamais. Ainsi, en utilisant, par exemple, l’application XML IEEE LOM pour décrire aux clients potentiels nos objets, nous savons que le récipiendaire, peu importe sa plateforme logicielle, pourra au minimum traiter la syntaxe. Le XML n’est donc pas un progrès ou une nouveauté technologique : la théorie de la syntaxe des fichiers textes est un sujet bien développé. Le XML s’impose davantage comme progrès social : le web a amené les gens à s’entendre une fois pour toute sur une syntaxe suffisamment simple et universelle pour les documents semi-structurés. Le cours INF 6450 Gestion de l’information avec XML ne porte donc pas uniquement sur la technologie elle-même; il envisage plutôt le XML comme une norme, mais aussi comme un ensemble de normes, incluant RDF, qui ont toutes en commun d’avoir un lien fort avec le web et la gestion de l’information et des connaissances. Flexibilité et évolution des schémas de données Un autre rôle du XML dans l’organisation : se substituer aux modèles relationnels dans lesquels on impose des champs de données fixes. Par exemple, on décrit chaque étudiant par un numéro de matricule, un nom et une date de naissance; on peut aussi associer l’étudiant à une liste de cours suivis. Bien que le modèle relationnel puisse sembler très flexible, il n’est pas toujours idéal : le web n’est pas une base de données relationnelles et, en fait, ce n’est pas du tout une base de données. S’il fallait convertir les pages web HTML en un schéma de base de données relationnelles, on constaterait rapidement qu’il s’agit d’un travail fastidieux, voire impossible. D’un autre côté, les pages web, les documents Microsoft Word et d’autres formes de données non structurées possèdent aussi leurs inconvénients. Supposons que j’accède au bottin de la Téluq par le web. En principe, je peux écrire un programme qui va automatiquement chercher le numéro de téléphone de « Richard Hotte ». En pratique CC BY-NC-SA Les modules du cours 5 cependant, comme le HTML est avant tout un format de présentation de l’information, cette approche est fragile et peu pratique : les machines ont tout simplement beaucoup de mal à extraire de l’information précise à partir de documents non structurés, contrairement aux êtres humains qui peuvent très bien reconnaître que telle page web présente bel et bien le numéro de téléphone de « Richard Hotte ». Ainsi, le XML se situe un peu entre les bases de données et les formats sans sémantique : on parle d’information semi-structurée. On garde une grande partie de la flexibilité qui a permis au web de devenir l’outil unique de gestion de l’information que l’on connaît. En même temps, on permet aux systèmes informatiques d’interagir avec toute cette information de façon automatique. De plus, avec le XML, il n’est pas du tout problématique de concevoir des schémas d’information ou de les réutiliser. En somme, le XML représente un compromis à la fois sémantique et flexible. Les modules du cours Le cours comporte 5 modules. Le premier module introduit au XML proprement dit : sa syntaxe et ses capacités de modélisation. Le module 2 porte sur le XML en tant que format pour les documents; on y présente la notion de séparation du contenu et de la présentation. Les modules 3, 4 et 5 portent respectivement sur l’ensemble de ce que l’on nomme parfois les « technologies XML » incluant XSLT, CSS, etc., sur le traitement du XML en utilisant un langage de programmation comme Java et, finalement, sur le RDF en tant que langage pour la description des ressources. Pour chaque module, nous avons rédigé des textes d’appoint et préparé des questionnaires d’autoévaluation qui vous permettront de vérifier votre maîtrise du contenu, au fur et à mesure de votre apprentissage. En outre, pour nous permettre de vous évaluer, vous réaliserez un travail noté par module. Il est préférable de procéder à l’étude des modules de façon séquentielle : en effet, il faut d’abord savoir interpréter la syntaxe XML avant de pouvoir aborder le XML comme format pour les documents. En outre, il faut une connaissance du XML comme format de document pour comprendre l’utilité des « technologies XML » et faire du traitement en Java. Finalement, le RDF exige une maîtrise suffisante de l’ensemble du XML, parce que la syntaxe peut sembler rébarbative à quelqu’un peu expérimenté. Il est cependant possible d’aborder les modules 3 et 4 de front. En résumé, le cours comporte les cinq modules suivants : – Module 1 : Introduction à XML (extensibilité, DTD, Relax NG, XML Schema, espaces de noms) – Module 2 : XML en tant que syntaxe pour les documents (XHTML, SVG, MathML, DocBook, ODF) – Module 3 : Technologies XML (XSLT, CSS, XPath, XQuery, XLink) – Module 4 : Traitement du XML en Java (DOM, SAX, Itérateurs, Sérialisation, AJAX, Services web) CC BY-NC-SA Guide d’étude 6 – Module 5 : Resource Description Framework (RDF) (Dublin Core, Creative Commons, FOAF, RSS 1.0, Atom) Caractéristiques médiatiques L’environnement du cours est un site web réalisé entièrement en XML. Les figures sont en SVG (un format XML couvert dans le cours). Vous pouvez faire vos lectures (textes, consignes, etc.) sur le site, mais aussi en utilisant un document imprimé, (Manuel INF 6450) généré à partir du site web par une transformation XSLT (sujet couvert dans le cadre du cours). Le cours contient de nombreux exemples de code en XML et Java : vous devriez être capable, à la fin du cours, de lire sans mal du XML en ligne, sans coloration syntaxique. Tous les modules comprennent des activités d’autoévaluation sous la forme de questionnaires (rédigés eux-même en XML) visant à vérifier la compréhension de vos lectures; vous répondrez à ces questionnaires sur le site, en ligne, car leur efficacité est optimisée par les possibilités du web. Un va-et-vient entre lectures et questionnaires d’autoévaluation s’imposera, mais à votre rythme. En outre, sur le site web, se trouvent la documentation touchant l’installation et l’utilisation du logiciel Firefox nécessaire au cours, diverses activités de création et de validation de documents XML, les consignes pour les travaux notés, les pense-bêtes qui, comme leur nom l’indique, vous seront utiles à différents moments. Vous y avez accès par des hyperliens dans la colonne de gauche de la page-écran, et ce pour chaque module. Les étudiants qui désirent un livre de référence pour ce cours peuvent acheter « XML en concentré : Manuel de référence » d’Elliotte Rusty Harold, W-Scott Means, Philippe Ensarguet (traducteur), Frédéric Laurent (traducteur) chez O’Reilly paru le 21 avril 2005 (ISBN : 2841773531). En outre, un des auteurs de ce livre de référence, Elliotte Rusty Harold a une page d’actualité sur le XML: Cafe con Leche XML News and Resources. Par ailleurs, nous avons préparé une feuille de route qui donne un aperçu de la démarche, un glossaire définissant quelques termes importants du cours et une webographie contenant plusieurs liens en français et en anglais. Ils sont accessibles en tout temps à partir des modules, par des boutons placés dans la partie supérieure de la pageécran. Encadrement L’encadrement, assuré par une personne tutrice que vous assigne l’Université, se fait par courriel. Ainsi, toutes vos interrogations sur le cours ou sur l’environnement d’apprentissage doivent lui être adressées par courriel; celle-ci y répondra dans les plus CC BY-NC-SA L’évaluation 7 brefs délais. Par ailleurs, nous vous demandons d’inscrire « [INF6450] » dans l’objet de tous vos messages. En ce qui concerne les travaux notés que vous transmettrez également par courriel à votre personne tutrice pour qu’elle les corrige, vous devrez en plus indiquer, dans l’objet du message, le numéro du travail, par exemple « [INF6450][TRAVAIL5] »; dans le message de transmission, vous indiquerez également votre nom, votre numéro d’étudiant (8 chiffres), la date de remise de votre travail et le nom de votre personne tutrice. Des consignes précises sont fournies dans chaque travail noté. L’évaluation Pour évaluer vos apprentissages dans ce cours, nous avons préparé 6 travaux notés et un examen en salle. Le tableau qui suit les présente sommairement. Activités notées Modules Pondération Travail noté 1 (question- Module 1 10 % naire) Travail noté 2 (discussion Modules 2-5 5% et compte rendu) Travail noté 3 (rédaction) Module 2 10 % Travail noté 4 (program- Module 3 10 % mation) Travail noté 5 (program- Module 4 15 % mation) Travail noté 6 (program- Module 5 10 % mation) Examen en salle Modules 1-5 40 % Total 100 % Les travaux notés Les travaux notés 1, 3, 4, 5 et 6 sont associés à un module et vérifient l’atteinte des objectifs de ce module. Le travail noté 1 prend la forme d’un questionnaire, le travail noté 3 consiste à rédiger un document en XML; les travaux notés 4, 5 et 6 comportent des exercices qui exigent de la programmation. Je vous recommande de réaliser ces travaux notés après avoir effectué les lectures et les activités d’autoévaluation du module en question. Il n’est pas nécessaire de faire les travaux dans l’ordre qu’ils apparaissent dans le cours; en effet, le travail noté 3 peut être fait après les autres travaux, par exemple. Cependant, le travail noté 1 doit être fait avant les autres et le travail noté 6, après les travaux notés 4 et 5. Quant au travail noté 2, la discussion dans le forum du cours, il peut commencer dès le début du module 2 et vous avez toute la durée du cours pour le réaliser. Avant de commencer cette activité, nous vous suggérons fortement d’avoir terminé l’étude du CC BY-NC-SA Guide d’étude 8 module 1, car il faut bien comprendre les définitions et concepts de base du XML. Notez que l’évaluation du travail 2 porte sur le compte rendu que vous rédigerez à la suite de votre participation dans le forum. Tous les travaux doivent être transmis à la personne tutrice par courriel. Examen en salle L’examen en salle compte pour 40 % de la note du cours. Il s’agit d’un examen de 3 heures comportant 5 questions, lesquels portent sur le contenu couvert par les travaux 1, 3, 4, 5 et 6. Un examen factice est disponible dans le dernier module pour vous permettre de vérifier si vous êtes prêt. La correction de l’examen est rigoureuse : vous devez décrire le comportement exact des programmes et pouvoir répondre aux questions de façon aussi précise que durant les travaux. Il est important d’avoir lu tous les textes et d’avoir fait toutes les activités d’autoévaluation du cours pour réussir l’examen. Aucune documentation n’est permise durant l’examen. Vers la douzième semaine du cours, l’Université vous informera de la date, de l’heure et de l’endroit de passation de l’examen. Gestion du temps et pondération Dans le tableau qui suit, nous indiquons le temps à prévoir pour chaque activité, ainsi que la pondération associée à chacune. Le temps consacré à la lecture inclut la lecture des textes conçus pour le cours. L’ordre dans lequel les activités sont présentées est l’ordre suggéré. Activités Temps suggéré Pondération Introduction au cours 2 heures Aucune Lectures et question- 15 heures Aucune naires du module 1 (incluant l’installation logicielle) Travail noté 1 (question- 5 heures 10 % naire) Lectures et question- 10 heures Aucune naires du module 2 Travail noté 2 (discussion 5 heures 5% dans le forum et compte rendu) Travail noté 3 (rédaction) 15 heures 10 % Lectures et question- 10 heures Aucune naires du module 3 (incluant la programmation XSLT et CSS) CC BY-NC-SA Gestion du temps et pondération Activités Travail noté 4 (programmation) Lectures et questionnaires du module 4 (incluant la programmation Java) Travail noté 5 (programmation) Lectures et questionnaires du module 5 Travail noté 6 (programmation) Examen Total 9 Temps suggéré 20 heures Pondération 10 % 10 heures Aucune 20 heures 15 % 5 heures Aucune 15 heures 10 % 3 heures 135 heures 40 % 100 % Un deuxième tableau répartit les activités selon les semaines, en comptant une moyenne de 9 heures de travail par semaine, pendant 15 semaines. La participation au forum s’étale sur plusieurs semaines (environ les deux tiers du cours). Semaine Activités 1 Présentation du cours, lectures et questionnaires (module 1) 2 Lectures et questionnaires (module 1) 3 Travail noté 1, lectures et questionnaires (module 2) 4 Lectures et questionnaires (module 2), travail noté 2: forum 5 Travail noté 3 6 Forum, travail noté 3, lectures et questionnaires (module 3) 7 Forum, lectures et questionnaires (module 3) 8 Forum, travail noté 4 9 Forum, travail noté 4 10 Forum, travail noté 4, lectures et questionnaires (module 4) 11 Forum, lectures et questionnaires (module 4), travail noté 5 12 Forum, travail noté 5 13 Forum, travail noté 5, lectures et questionnaires (module 5) 14 Forum, lectures et questionnaires (module 5), travail noté 6 15 Forum, travail noté 6 CC BY-NC-SA Guide d’étude Semaine 10 Activités Examen en salle À partir du tableau précédent, nous vous proposons un tableau semaine/module. Un « X » indique que des activités du module en question sont prévues pour une semaine donnée. L’astérisque signifie que vous devriez terminer le travail noté prévu pour ce module durant la semaine marquée. Semaine Module 1 Module 2 Module 3 Module 4 Module 5 1 X 2 X 3 X* X 4 X 5 X 6 X* X 7 X 8 X 9 X 10 X* X 11 X 12 X 13 X* X 14 X 15 * Forum X* Version PDF du cours Le cours est non seulement disponible en XML sur le web, mais aussi en format PDF. En effet, un des avantages de la séparation du contenu et de sa présentation, tel qu’on l’enseigne dans le cours, c’est qu’on peut ensuite présenter l’information selon plusieurs formats. Dans ce cours, nous avons utilisé XSLT pour transformer le XML en PDF. La version papier que vous avez reçue, intitulée Manuel INF 6450 (version pdf), est une version pdf écourtée du cours; elle comprend le guide d’étude qui présente le cours, le contenu de chaque module et le travail noté qui lui est associé, ainsi que le glossaire, la webographie et les trois pense-bêtes, mais pas les questionnaires d’autoévaluation; ce manuel compte plus de 200 pages. Vous pouvez y accéder par le lien qui suit : – Manuel INF 6450 (1,2 Mo). Vous pouvez aussi accéder au manuel complet du cours par ce lien : – Manuel INF 6450 complet (1,6 Mo). CC BY-NC-SA Remerciements 11 Remerciements Le cours INF 6450 Gestion de l’information avec XML a été conçu par le professeur Daniel Lemire avec la collaboration de Kamel Aouiche, assistant de recherche, de Lucie Moulet, assistante de recherche, et du concepteur associé Jean-François Savard. Le professeur Lemire les remercie vivement; il remercie également les professeurs Koné Mamadou Tadiou (Université Laval), Richard Hotte (UQAM) et Marc Couture (UQAM), ainsi que le spécialiste en sciences de l’éducation Robert Ippersiel, qui ont effectué une lecture critique de la documentation du cours. Un des étudiants du cours, monsieur Dosseh Abiassi, a signalé plusieurs pages de coquilles. En outre, le professeur remercie chaleureusement Renée Dumas, spécialiste en communication écrite, pour son apport à la qualité linguistique du cours, pour son sens pédagogique de la communication et pour sa complicité dans cette aventure. Il remercie également l’équipe de production multimédia, dirigée par Jean-Charles Dormeux, pour leur sollicitude et leur professionnalisme. CC BY-NC-SA Module 1 : Introduction à XML 1.1 1.1.1 Aperçu Objectifs À la fin de ce module, vous devriez avoir une bonne idée de ce qu’est le XML et pouvoir facilement lire et écrire du XML simple. Les objectifs spécifiques du module sont : – Utiliser un vocabulaire ou une application XML pour présenter des informations en format XML; – Déterminer si un document XML est bien formé ou valable; – Interpréter des fichiers XML utilisant des espaces de noms. Avant d’entreprendre votre démarche dans ce module, nous vous invitons à lire le texte qui suit pour avoir un aperçu de ce qu’est le XML. 1.1.2 Qu’est-ce que le XML? Le XML ou Extensible Markup Language est une syntaxe générique utilisée pour formater des données avec des balises simples et lisibles. Par exemple, pour décrire un étudiant, une syntaxe XML possible serait : <étudiant> <nom>Tremblay</nom> <prénom>Jean</prénom> <matricule>849490234</matricule> </étudiant> Par la suite, si nous désirions décrire l’ensemble des étudiants inscrits à un cours, nous pourrions utiliser la syntaxe suivante : <cours> <nom>Introduction au traitement de texte</nom> 13 Module 1 : Introduction à XML 14 <université>Téluq</université> <inscriptions> <étudiant> <nom>Tremblay</nom> <prénom>Jean</prénom> <matricule>849490234</matricule> </étudiant> <étudiant> <nom>Hotte</nom> <prénom>Richard</prénom> <matricule>8443444</matricule> </étudiant> </inscriptions> </cours> Dans ces exemples, observez la présence de texte entre les signes < et > : il s’agit de balises. Une balise marque le début ou la fin d’un élément. La balise <cours> marque le début de l’élément « cours », alors que la balise </cours> en marque la fin. Notez qu’un élément peut contenir d’autres éléments, et ainsi de suite. Cette nouvelle syntaxe a émergé dans les années 90, avec le développement du web. Depuis, le XML est devenu très courant dans l’industrie informatique et fait partie des notions de base que les informaticiens doivent maîtriser, au même titre que les bases de données ou la programmation orientée objet. Elle est caractérisée par la simplicité d’abord : le HTML et le XML ont un parent commun, le SGML qui était complexe et difficile à maîtriser; on a donc voulu « réparer » le SGML, en proposant des solutions plus simples. Entre autres choses, le web a permis d’observer que les technologies simples pouvaient être très puissantes; c’est ce qui en a fait toute la force : une technologie accessible, ouverte et avec un minimum de complexité. D’ailleurs, l’inventeur du web, Tim Berners-Lee a rapidement adopté le XML et en propose, depuis, une nouvelle vision qui repose entièrement sur le XML : le web sémantique. La prémisse étant que, si l’on sépare le contenu de la présentation, le web n’en sera que plus riche. En effet, on observe que les formats qui confondent la présentation et le contenu, tels que Microsoft Word ou le HTML, limitent la capacité de nos logiciels. Par exemple, il peut être difficile pour un logiciel de trouver automatiquement la deuxième section d’un texte placé sur le web et de la reformater automatiquement, pour qu’on puisse l’inclure dans un rapport annuel. 1.1.3 Démarche Vous devez étudier et maîtriser le contenu de ce module avant de passer aux autres, car il est de base : il définit ce qu’est le XML et vous permet d’apprendre sa terminologie propre. Selon les sections de ce module, lisez les textes proposés, faites les activités suggérées, répondez aux questionnaires d’autoévaluation. Lorsque vous maîtrisez le CC BY-NC-SA Installation de Mozilla Firefox 15 contenu du module, réalisez la première activité d’application, le travail noté 1, avant de passer au module suivant. Nous vous suggérons d’étudier le module dans l’ordre suivant : – – – – – – – Installation de Mozilla Firefox Création de documents XML, avec un éditeur de texte Introduction à XML Principes de XML Définition de type de document (DTD), Relax NG et XML Schema Validation des documents XML Espaces de noms Le pense-bête présente quelques symboles importants sur les DTD et leur signification; dans la version imprimée du cours, il se trouve en annexe. 1.2 1.2.1 Installation de Mozilla Firefox Objectif Installer le logiciel Firefox; l’utiliser pour naviguer dans le web ou ouvrir des documents sur votre ordinateur. 1.2.2 Activité Si le système d’exploitation de votre ordinateur est Windows, vous utilisez sans doute Internet Explorer (IE), le navigateur internet fourni d’office avec ce système. Malheureusement, ce navigateur ne supporte pas pleinement le XML et XHTML et, pour ce cours, étant donné qu’une partie du contenu est en XML et XHTML, il est nécessaire d’utiliser un navigateur qui le supporte parfaitement. Nous vous demandons de télécharger un autre navigateur, soit Mozilla Firefox, dont le téléchargement est gratuit. Pour la version française de Mozilla Firefox, rendez-vous à l’adresse http://frenchmozilla.sourceforge.net/firefox/; lisez les informations, sélectionnez le fichier correspondant à votre système d’exploitation et téléchargez-le; lancez ensuite la procédure d’installation et suivez bien les directives données. Sous Windows, il est possible que vous deviez faire redémarrer votre ordinateur après l’installation. Il est nécessaire d’avoir Firefox 2.0 ou mieux pour suivre ce cours: vous pouvez vérifier la version que vous avez en tapant « about: » dans la boîte de saisie des URL. Quand l’installation sera terminée, vérifiez que vous pouvez utiliser Firefox pour naviguer dans le web avant de poursuivre le cours. CC BY-NC-SA Module 1 : Introduction à XML 1.2.3 16 Installation de polices de caractères optionnelles Il se peut que votre navigateur vous avertisse de l’absence de certaines polices optionnelles la première fois que vous chargez une page contenant du MathML. Vous pouvez ignorer ces avertissements. Si vous le désirez, afin d’éviter ces avertissements, vous pouvez installer des polices de caractères supplémentaires qui sont sur le site du projet MathML de la fondation Mozilla. Ce n’est pas nécessaire dans le cadre de ce cours. 1.2.4 Avertissement Firefox est constamment mis à jour par son équipe de développement. Il est possible que vous constatiez parfois des différences entre ce qui est annoncé dans le cours et le comportement de votre version de Firefox. 1.2.5 Autres navigateurs Outre Firefox, les navigateurs Opera et Camino sont aussi compatibles avec les normes XML utilisées dans ce cours. Cependant, pour les fins des activités notées utilisant le navigateur et certaines fonctions du site web, il est nécessaire d’utiliser Firefox. 1.2.6 Retour Avez-vous pu installer Firefox et naviguer dans le web? Si oui, passez aux prochaines activités, sinon contactez votre personne tutrice ou cherchez encore un peu. 1.3 1.3.1 Création de documents XML Objectif Créer des documents XML et les ouvrir avec le navigateur Firefox. 1.3.2 Activité Il est facile de créer des documents XML sous Windows; il faut d’abord ouvrir un éditeur de texte. Tout éditeur de texte ferait l’affaire, mais avec Windows, Microsoft fournit par défaut Bloc-notes (NotePad). Pour ouvrir le Bloc-notes, il suffit d’aller dans le menu « Démarrer », sous « Accessoires », et de cliquer sur l’icône du Bloc-notes. Si vous utilisez un autre système d’exploitation que Windows, une petite recherche vous permettra de trouver rapidement un éditeur de texte déjà installé sur votre machine. Vous n’avez plus qu’à taper du code XML. Comme exercice, tapez le texte suivant : CC BY-NC-SA Création de documents XML 17 <premier> Ceci est mon premier document XML. </premier> Enregistrez-le ensuite sous le nom « premier.xml ». Malheureusement, le Bloc-notes a la fâcheuse habitude de toujours ajouter l’extension « .txt » à la fin des noms de fichiers. Donc, à chaque enregistrement, vous devrez sélectionner « Tous » dans la liste déroulante de « Type » de fichier, comme le montre la figure qui suit. Bloc-note opte par défaut pour le jeu de caractères (ou codage) ANSI ce qui, pour les fins de ce cours, correspond au jeu de caractères ISO-8859-1. Sous Windows XP ou mieux, on peut aussi sélectionner le jeu de caractères UTF-8. Ouvrez maintenant le fichier « premier.xml » dans Firefox, un navigateur qui sait reconnaître le XML; vous verrez alors apparaître votre document XML tel que vous l’avez tapé. Si vous avez fait une faute de syntaxe XML, Firefox vous l’indiquera. Le XML ressemble beaucoup au code HTML avec lequel sont créées les pages web. Nous reviendrons plus tard sur le HTML, après avoir étudié plus à fond le XML. Le module 2 comporte une activité d’introduction au HTML. Pour l’instant, retenez seulement qu’il est possible d’écrire le HTML comme du XML bien formé. L’exemple qui suit est un document HTML qui est aussi du XML bien formé. <html> <body> Bonjour </body> </html> CC BY-NC-SA Module 1 : Introduction à XML 18 Comme exercice facultatif, recopiez le texte précédent commençant par <html> et se terminant par </html> dans un fichier, en utilisant un éditeur de texte comme le Blocnotes, que l’on trouve dans les accessoires de Windows. Enregistrez le fichier sous le nom « test.html »; n’oubliez pas de sélectionner « Tous » dans la liste déroulante de « Type » de fichier, dans la boîte de dialogue d’enregistrement. Ensuite, ouvrez votre fichier avec le navigateur Firefox; vous devriez voir le texte « Bonjour » s’afficher. Ces quelques exemples montrent comment il est simple d’utiliser et de créer des fichiers XML. Le XML permet toutefois de faire beaucoup plus, comme d’échanger des messages entre des applications ou de décrire à un ordinateur le contenu d’un document. De la même façon, en utilisant le Bloc-notes, on peut créer des documents DTD (chapitre 3 du module 1). Nous verrons que les documents DTD sont aussi des fichiers au format texte servant à spécifier, dans une certaine mesure, ce qui est permis et ce qui ne l’est pas dans un document XML. Autres éditeurs pour le XML Un produit commercial très recherché pour l’édition du XML est XMLSpy, en anglais seulement. C’est probablement l’éditeur XML le plus puissant sur le marché; il en existe une version d’essai gratuite. Un autre excellent éditeur pour le XML, gratuit et en anglais seulement, est jEdit. Comme cet éditeur est un programme Java, il faut installer une machine virtuelle Java au préalable, tel le SDK J2SE. En outre, on peut ajouter à jEdit le plugiciel XML qui permet de naviguer dans les documents XML et d’en assurer la validité. Le plugiciel XSLT permet aussi de tester des documents XSLT et des expressions XPath (module 3 du cours). Finalement, pour Windows seulement, Cooktop est un éditeur XML gratuit créé par Victor Pavlov. Il permet d’éditer des fichiers XML, DTD, et XSLT, en plus de manipuler des expressions XPath. Sous MacOS, l’éditeur gratuit Smultron est recommandé. 1.3.3 Retour Avez-vous pu créer un document XML avec l’extension XML? Est-ce qu’il s’est ouvert dans Firefox sans erreur? Si oui, passez aux autres activités, sinon contactez votre personne tutrice ou cherchez encore un peu. CC BY-NC-SA Introduction à XML 19 F IG . .1 – Tim Bray en mai 2007 (photographie par Lou Springer). 1.4 1.4.1 Introduction à XML Objectif Connaître les notions de base du XML. 1.4.2 Activité Lisez le texte qui suit, puis répondez au questionnaire d’autoévaluation. Ce texte place la technologie XML dans son contexte. 1.4.3 Quelques notions du XML Le XML est un « métalangage » permettant d’échanger de l’information, principalement sur le web. Il a été conçu par Tim Bray, Jon Bosak et de nombreux autres collaborateurs, entre 1996 et 1999. On dit que c’est un « métalangage » parce qu’il est une façon pratique de créer de nouveaux langages pour échanger des informations, mais qu’il ne constitue pas un langage en soi. Le XML n’essaie pas, par lui-même, de résoudre tous les problèmes : il fournit par contre les outils nécessaires pour que, dans tous les domaines, des individus puissent résoudre leurs problèmes. Ainsi, on dit que le XML est « extensible » (peut être étendu) et que c’est un métalangage : les deux affirmations vont dans le même sens et notent la capacité du XML à s’adapter à des besoins différents. I looked at it and I saw that the markup said what the information is, not what it looks like. Why isn’t everything this way ? I still basically am asking that question. (Tim Bray) Un document XML est essentiellement du texte contenant des balises. Une balise est un segment de texte commençant par < et se terminant par >, comme <personne>. Voici un exemple simple de document XML : CC BY-NC-SA Module 1 : Introduction à XML 20 <personne> <nom>Jean</nom> <age>42</age> </personne> Le XML est très présent sur le web et les documents XML peuvent être affichés par certains navigateurs récents, comme Internet Explorer et Firefox. On échange aussi le XML entre des logiciels et des serveurs sur le web, et le XML est de plus en plus utilisé en bureautique, comme format pour les traitements de texte par exemple. Comme un document XML est avant tout du texte, il n’est pas avantageux d’utiliser le XML pour stocker des informations de type multimédia (vidéo, musique); le champ d’application du XML demeure toutefois très vaste. Le XML définit une grammaire stricte et relativement simple de manière que les outils XML génériques puissent traiter tous les documents XML, peu importe leur domaine d’application. On dit d’un document qui respecte cette grammaire qu’il est bien formé. Ainsi, il n’est pas nécessaire d’utiliser des outils coûteux et propriétaires pour faire du XML. L’application la plus commune du XML correspond au scénario suivant. Un groupe de personnes travaillant dans un domaine particulier, disons l’industrie de la construction, ont besoin d’échanger des informations, par exemple le prix et la description des matériaux. Elles doivent s’entendre sur un format informatique commun de manière que tous les logiciels, écrits ou utilisés par les différents participants, puissent communiquer entre eux, sans problème. L’information pourra ainsi être transmise sans intervention humaine. Concrètement, on utilise le XML dans le contexte d’une application XML. Une application XML est un jeu de balises et son utilisation dans un domaine particulier, par exemple la musique ou la cuisine. On peut définir un jeu de balises et, dans une certaine mesure, son utilisation en se servant d’un document DTD, Relax NG ou XML Schema (sujets que nous étudierons plus tard dans le cours). Dans un sens, une application XML forme un langage. On dit d’un document XML qui respecte les normes d’une application XML donnée qu’il est valable : un document valable est bien formé. En théorie, on pourrait penser que l’importance du XML est mineure. En effet, n’est-il pas facile de s’entendre sur des formats communs? L’expérience montre que ce n’est pas si facile. D’abord, définir avec rigueur un format de données est complexe. D’autre part, le développement de logiciels particuliers à chaque format est coûteux : avec un métalangage comme XML, on peut réutiliser souvent les mêmes librairies logicielles. Finalement, l’individu qui acquiert une expérience avec XML dans le contexte de l’industrie de la construction pourra facilement réutiliser cette expertise dans le domaine de la mode, par exemple. Il est plus facile de trouver des experts en XML que des experts dans un format de données, format particulier à un domaine pointu. Le XML n’est pas un langage de programmation bien qu’on puisse l’utiliser avec des langages comme Java (module 4). On se sert par contre de plus en plus du XML pour CC BY-NC-SA Introduction à XML 21 les fichiers de configuration des logiciels. Par exemple, il est probable que, si vous utilisez un serveur web dans votre entreprise, ce serveur ait des fichiers de configuration en XML. Un document XML ne fait rien : ce n’est qu’une source passive d’informations, comme n’importe quel document, comme des pages web. 1.4.4 La philosophie du XML Le XML met à profit un principe essentiel à l’architecture du web : be conservative in what you do, be liberal in what you accept from others (soyez strict dans ce que vous produisez, mais généreux dans ce que vous acceptez). En d’autres mots, le XML fonctionne parce que les gens tentent le plus possible de produire du XML de qualité (bien formé et valable), mais ils acceptent que les autres fassent des entorses aux règles. C’est, en partie, ce qu’on entend lorsqu’on dit que le XML est « extensible ». Cette règle est parfois appelée la loi de Postel parce qu’elle fut rédigée par Jon Postel dans la spécification RFC 793. Par exemple, supposons que vous écriviez un logiciel qui s’attend à recevoir des commandes ayant la forme suivante. <commande> <produit>papier</produit> <quantite>2</quantite> </commande> Supposons maintenant que le logiciel qui émet les commandes est mis à jour et qu’il vous transmet dorénavant les commandes sous le format suivant. <commande> <produit>papier</produit> <quantite>2</quantite> <emballage>oui</emballage> </commande> Selon les principes du XML, votre logiciel doit continuer à fonctionner, il doit ignorer le nouvel élément qu’il ne connaît pas. En d’autres mots, votre logiciel doit être généreux et ne pas exiger une conformité parfaite. Tant qu’il dispose des informations dont il a besoin, votre logiciel doit continuer à fonctionner. C’est ce principe fondateur qui permet à des millions de personnes d’utiliser le XML pour s’échanger des données sans le moindre arbitrage. Plus généralement, les technologies XML tentent de fonctionner le plus correctement possible même si les données ne correspondent pas à ce qu’on attendait. Plus généralement, le XML respecte plusieurs principes fondamentaux qui lui accorde plusieurs bénéfices. – Il est facile d’entretenir et modifier au fil du temps une application basée sur XML. CC BY-NC-SA Module 1 : Introduction à XML 22 – Le XML est modulaire : on peut décomposer les applications en plusieurs fichiers, on peut traiter séparément différents morceaux d’un même document XML. – Les spécifications XML minimisent la redondance sans la réduire à néant : il y a plusieurs façons de faire une même chose en XML, mais ce nombre est généralement limité. On a souvent le choix entre plusieurs stratégies, mais pas un trop grand nombre. – Les technologies XML tiennent compte des personnes ayant des handicaps, notamment parce que plusieurs modes de présentation sont possibles. – Le XML ne dépend pas d’une plate-forme particulière : que vous utilisiez Linux, Mac OS ou Windows, vous pouvez travailler avec le XML. – Le XML est international : le XML supporte toutes les langues, pas seulement l’anglais. – Le XML est extensible : on peut facilement faire évoluer les formats sans avoir à réécrire tous nos logiciels. – Il est facile d’apprendre le XML. – Il est facile pour un humain de lire du XML. – Le XML est efficace : un ordinateur peu puissant peut traiter du XML rapidement. – Le XML est un format textuel. – Le XML est simple. – Le XML assure la pérennité des informations. – Le XML permet l’interopérabilité des systèmes. – Un document XML peut être réutilisé facilement à plusieurs fins. – Le XML est stable : les spécifications ne changent pas trop souvent. – Le XML est universel : c’est un métalangage qui s’applique à un grand nombre de problèmes. 1.4.5 Conclusion Le XML n’est pas une nouveauté scientifique. Le XML représente, par contre, un pas en avant parce que c’est un des rares méta-langages universel. Le XML est aussi fondé sur des principes importants comme la pérennité, la simplicité, etc. qui ne sont pas toujours présents en technologie de l’information. 1.5 1.5.1 Principes de XML Objectif Découvrir les grands principes du XML CC BY-NC-SA Principes de XML 1.5.2 23 Activité Lisez le texte qui suit, puis répondez au questionnaire d’autoévaluation. Ce texte porte sur la syntaxe de base du XML. Les notions importantes sont la balise, l’élément, l’élément-racine et l’attribut. 1.5.3 Quelques principes et notions importantes du XML Rappelons qu’une balise est un segment de texte commençant par < et se terminant par >. Par exemple, <lavie> est une balise qui marque le début de l’élément vie. Une balise commençant par </, comme </lavie>, est une balise de fin; dans cet exemple, elle termine l’élément lavie. Le nom XML de la balise est le texte suivant le symbole < (ou </ pour une balise de fin) et pouvant contenir n’importe quelle lettre ou chiffre (a, b,... 0, 1, 2,...) ou les trois symboles de ponctuation, soit la marque de soulignement ( _ ), le trait d’union ( - ) ou le point (. ); un nom XML ne peut contenir d’autres symboles de ponctuation, ni un espace. En outre, il ne peut pas commencer par un chiffre, un trait d’union ou un point. Par exemple, le nom XML de la balise <lavie> est « lavie », alors que la balise <7lavie> ne serait pas autorisée. On réserve les noms débutant par xml, Xml, xMl, xmL, XMl, xML,Xml et XML pour les spécifications XML. Ainsi, la balise <xmldanslavie> est à éviter. Pour les balises de début, aussi dites d’ouverture, on peut ajouter un attribut au nom XML de la balise. Un attribut porte un nom XML qui doit respecter les mêmes règles que les noms XML des balises; il est suivi du symbole « = » et d’une valeur placée entre guillemets ou apostrophes. Par exemple, la balise <lavie age="5"> indique que l’élément la vie a un attribut (age="5") qui a comme nom XML « age » et comme valeur « 5 ». Une balise peut avoir plusieurs attributs, comme <lavie age="5" sexe="M">, mais ils doivent tous porter des noms XML différents : <lavie age="5" age="7"> n’est pas autorisée. Par convention, on réserve l’attribut « xml:lang » à la spécification de la langue dans laquelle le texte est écrit. Cette spécification est optionnelle et assez rarement utilisée. Si on veut indiquer que le contenu d’un élément est en français, on fera comme dans cet exemple : « <explication xml:lang="fr">J’avais besoin d’une voiture.</explication> ». On peut ajouter au code de la langue, un code de région comme dans « fr-CA » ou « en-US ». Le code de la langue et le code de la région doivent être séparés par un tiret. Les codes de langue ou de région qui peuvent être utilisées sont disponibles à l’URL http://www.iana.org/assignments/language-subtag-registry. Un élément est l’ensemble du texte borné par deux balises ayant le même nom XML, comme <lavie> et </lavie>. On dit que l’élément <lavie></lavie> a pour nom XML « lavie ». L’élément hérite des attributs de sa balise de départ : l’élément <lavie age="5"></lavie> a l’attribut « age="5" ». Il est à noter que la casse est significative en XML : les balises <A> et <a> n’ont pas le même nom XML. Dans le cas particulier où l’élément est vide (sans contenu), on peut remplacer <lavie></lavie> par CC BY-NC-SA Module 1 : Introduction à XML 24 <lavie/> pour abréger. Un élément peut contenir d’autres éléments, comme dans <lavie><a></a></lavie>, ou du texte, ou du texte et des éléments comme <lavie>fd<a>fsd</a>fd</lavie>. Si un élément contient d’autres éléments, il doit aussi contenir, entre ses balises de début et de fin, les balises de début et de fin de chaque élément. Notez, de plus, que deux éléments ne peuvent se chevaucher, comme <b><a></b></a>; avant de passer à un autre élément, il faut terminer le premier avec sa balise de fin. L’exemple précédent est du XML mal formé! Pour bien comprendre, illustrons notre propos par un exemple. Un document XML prend la forme suivante : <racine> <element1>http://www.google.com</element1> <element2>Un moteur de recherche</element2> </racine> Dans ce document, il y a trois éléments. Tout d’abord, il y a l’élément-racine qui comprend tout ce qui est entre les balises <racine> et </racine>. La première balise marque le début de l’élément-racine. Tout document XML bien formé doit avoir un élémentracine et un seul élément-racine. Tous les autres éléments doivent être contenus dans cet élément-racine. Dans notre exemple, cet élément a deux sous-éléments : <element1>http://www.google.com</element1> et <element2>Un moteur de recherche</element2> On peut ajouter un attribut à un des éléments de la façon suivante : <racine date="aujourd’hui"> et </racine> Le texte date="aujourd’hui" est un attribut de l’élément-racine avec pour nom « date » et comme valeur d’attribut « aujourd’hui ». Tout le texte qui ne se trouve pas dans une balise, mais qui se trouve dans l’élémentracine se décompose en nœuds de texte. Par exemple, le document suivant contient un élément contenant un nœud de texte. <racine>mon texte</racine> CC BY-NC-SA Principes de XML 1.5.4 25 Points importants dans la syntaxe de base Un document XML ne doit avoir qu’un et un seul élément appelé « élément-racine », qui doit contenir tous les autres éléments. Il faut correctement ouvrir et fermer les éléments en séquence, ainsi <a><b></a></b> n’a aucun sens en XML, il faut plutôt écrire <a><b></b></a> ou alors <a></a><b></b>. Les éléments peuvent eux aussi avoir des attributs, par exemple <a att="test"></a>, mais il faut obligatoirement mettre la valeur de l’attribut entre guillemets (") ou apostrophes (’). 1.5.5 Dans l’ordre ou dans le désordre Dans un document XML, l’ordre dans lequel les éléments sont présentés importe. Par exemple, les deux documents XML suivants ne sont pas équivalents. <racine> <element1>http://www.google.com</element1> <element2>Un moteur de recherche</element2> </racine> <racine> <element2>Un moteur de recherche</element2> <element1>http://www.google.com</element1> </racine> Par contre, l’ordre dans lequel les attributs sont présentés est sans importance. Les deux documents XML suivants sont donc équivalents. <racine attr1="test" attr2="retest"></racine> <racine attr2="retest" attr1="test" ></racine> 1.5.6 Appels d’entités Un élément peut contenir du texte, mais ne peut contenir le symbole <, comme dans l’exemple <a><</a>, parce que cela mène à de la confusion. On ne peut non plus y trouver le symbole & ou la séquence « ]]> ». Que faire alors s’il faut utiliser le caractère < dans un texte mathématique, par exemple? Il faut utiliser un appel d’entité. Un appel d’entité est un bout de texte qui commence par une esperluette ( & ) et se termine par un CC BY-NC-SA Module 1 : Introduction à XML 26 point-virgule ( ; ). Nous verrons plus tard que nous pouvons définir nos propres appels d’entités; les appels d’entités suivants font partie de la définition du XML : appel d’entité résultat < < & & > > " " ' ’ Ainsi, si le nom de votre compagnie est John&Smith, vous ne devrez pas utiliser un élément comme ceci <nom>John&Smith</nom>; il vous faudra plutôt utiliser <nom>John&Smith</nom>. Le texte « ]]> » s’écrit « ]]> ». On utilise aussi les appels d’entités pour noter les valeurs des attributs. Supposons que la valeur d’un attribut est un guillemet suivi d’une apostrophe ("’). Les deux choix possibles <nom att="’""> et <nom att=”"’> ne sont pas valables. Dans ce cas, il faudra écrire <nom att="’"">, <nom att=’'"’>, <nom att="'""> ou <nom att=’'"’>. Prenez le temps de mémoriser ces appels d’entités et retenez bien dans quel cas on peut être obligé de les utiliser. Il arrive parfois qu’il soit trop lourd d’utiliser des appels d’entités, et on peut alors utiliser un segment « CDATA ». Un tel segment débute par « <![CDATA[ » et se termine par « ]]> ». Tout le texte au sein du segment est rendu verbatim. Ainsi, le texte « <![CDATA[<monelement />]]> » est équivalent à « <monelement /> ». 1.5.7 Les commentaires Dans un document XML, on peut ajouter un commentaire qui est normalement destiné à être lu par un humain. Par exemple, dans un fichier de configuration XML, les commentaires pourraient être utilisés pour expliquer la signification des différents éléments pour qu’un humain puisse faire des modifications au besoin. Un commentaire commence par <!-- et se termine par --> et ne doit pas contenir deux tirets de suite (--) entre ces deux bornes, il ne doit pas se terminer par un tiret, mais peut contenir n’importe quel autre texte. Un commentaire peut apparaître avant ou après l’élément-racine, dans un élément, entre deux éléments, etc. Cependant, un commentaire ne peut pas apparaître au sein d’une balise, comme <a <!--ceci est la balise a-->>. C’est du XML mal formé! CC BY-NC-SA Principes de XML 1.5.8 27 Les instructions de traitement En pratique, il serait parfois utile d’appeler des fonctions externes (ou programmes) à partir du XML. Par exemple, vous pourriez avoir un programme « cout » qui donne le prix d’un produit à partir de son numéro de série : pourquoi ne pas appeler ce programme directement du XML? Le XML ne permet pas de le faire : le XML n’est qu’un métalangage pour produire des documents. Par contre, en XML, on peut utiliser des instructions de traitement. L’instruction de traitement ne fait rien en soi, mais peut indiquer à vos programmes comment trouver un certain résultat. L’exemple suivant décrit un produit portant le numéro de série 423890 et dont le prix pourrait être déterminé par une application appelée « cout ». <produit> <serie>423890</serie> <valeur><?cout 423890?></valeur> </produit> La syntaxe d’une telle instruction de traitement est simple. L’instruction débute par <? et se termine par ?>; immédiatement après <?, un nom XML valable doit apparaître (tous les noms XML valables sont autorisés à l’exception de xml, Xml, XMl, XML, XmL, xMl, xML et xmL). Rappelons que, comme pour n’importe quel contenu textuel XML, il faut faire des appels d’entités pour < et &. Une instruction de traitement n’est pas une balise ou un élément. Notez que le langage informatique PHP utilise les instructions de traitement avec comme nom « php ». Voyons l’exemple suivant : <produit> <serie>423890</serie> <?php echo "test" ?> </produit> Tout comme les commentaires, on peut mettre les instructions de traitement partout dans un document XML, sauf à l’intérieur d’une balise. 1.5.9 Jeux de caractères Historiquement, on a longtemps représenté les caractères en utilisant des octets (8 bits). Aux États-Unis, on utilisait la norme ASCII qui utilisait les sept premiers bits de chaque octet. Avec le temps, les normes ISO se sont imposées. En français, on utilise souvent le jeu de caractères « ISO-8859-1 ». L’outil Bloc-note de Microsoft utilise par défaut un jeu de caractères qui est très similaire à ISO-8859-1 (qu’ils nomment parfois ANSI). Malheureusement, n’utiliser que 8 bits pour représenter les caractères signifie qu’il est CC BY-NC-SA Module 1 : Introduction à XML 28 impossible de tenir compte des langues asiatiques, par exemple, et qu’on ne peut mélanger un texte français avec de l’arabe. Pour cette raison, en 1991, la norme Unicode fut proposée. La norme Unicode est de plus en plus utilisée et elle est popularisée en partie par son utilisation dans le XML. En effet, par défaut, un document XML utilise Unicode (spécifiquement UTF-8 ou UTF-16) et ce sont les seuls jeux de caractères qu’un processeur XML est requis de connaître. L’avantage principal d’Unicode est sa richesse : la version 5.0 du format Unicode permet de représenter 99 000 caractères différents incluant les caractères Klingon de Star Trek. En comparaison, le jeu de caractères ISO-8859-1 permet de représenter moins de 255 caractères (8 bits). La plupart des logiciels récents supportent la norme Unicode. D’ailleurs, depuis le tout début, une chaîne de caractères en Java est représentée en utilisant la norme Unicode. Par contre, il restera toujours des logiciels utilisant les jeux de caractères ISO. 1.5.10 La déclaration XML La déclaration XML ressemble à s’y méprendre à une instruction de traitement et prend la forme <?xml ... ?>. Une déclaration XML n’est pas une balise ou un élément. Le contenu d’une déclaration XML comporte généralement au maximum trois attributs : version="...", encoding="..." et standalone="...". La version 1.0 du XML est la plus utilisée; bien que la version 1.1 existe, elle est fort peu utilisée. Selon l’un des inventeurs du XML, Tim Bray, il est peu probable qu’il y ait une version 2.0 du XML . Je ne pense pas qu’il y aura de XML 2.0. Les obstacles politiques seraient effrayants - tout le monde voudra sa part du gâteau -, et la base installée de logiciels qui reconnaissent XML comprend aujourd’hui à peu près tous les ordinateurs liés à Internet, donc une transition me semblerait trop onéreuse. (Interview de Tim Bray, JDN Développeurs, 29 janvier 2007) On utilise souvent une déclaration XML avec « encoding="ISO-8859-1" » pour pouvoir utiliser les accents dans le document : les jeux de caractères Unicode ne sont pas toujours supporté par plusieurs outils logiciels n’ayant pas été mis à jour au vingt-et-unième siècle; l’utilisation des accents en français sans la déclaration « encoding="ISO-8859-1" » peut alors entraîner des problèmes. L’attribut « standalone » prend la valeur yes ou no, selon que l’on veut que la DTD externe soit lue ou non. Nous traiterons des DTD, plus tard. Dans ce cours, nous supposons que vous utilisez un éditeur de texte qui ne supporte pas les normes UTF-8 et UTF-16. En conséquence, le document XML suivant ne serait pas bien formé, car il utilise des accents : <étudiant> Jean </étudiant> CC BY-NC-SA Principes de XML 29 Par contre, le document XML qui suit est bien formé : <?xml version="1.0" encoding="ISO-8859-1"?> <étudiant> Jean </étudiant> La déclaration XML doit obligatoirement être au tout début du document ou être carrément absente : même un espace n’est pas permis. 1.5.11 Les espaces En XML, les espaces entre les éléments comptent, qu’il s’agisse d’un retour de charriot, d’une tabulation ou d’un simple espace. Ainsi, le document suivant se décompose en 7 parties ou nœuds : un élément-racine nommé html qui contient d’abord un nœud de texte (le retour de charriot) suivi d’un élément produit contenant le nœud de texte « 1 », suivi d’un autre nœud de texte (le retour de charriot), suivi d’un élément serie (vide), suivi d’un troisième nœud de texte (le retour de charriot). <html> <produit>1</produit> <serie /> </html> Par contre ce document ne contient que 4 nœuds (3 éléments et 1 nœud de texte) : <html><produit>1</produit><serie /></html> En effet, comme il n’y a pas d’espace ou de retour de charriot entre les balises, il n’y a qu’un seul nœud de texte. Si on omet les attributs, les nœuds débutent et se terminent généralement avec les balises. On peut indiquer que les espaces entre les éléments sont significatifs avec l’attribut xml:space qui peut prendre la valeur default ou la valeur preserve. Dans cet exemple, on souhaite indiquer que les espaces sont significatifs : <html xml:space="preserve"> <produit>1</produit> <serie /> </html> CC BY-NC-SA Module 1 : Introduction à XML 1.5.12 30 Les fins de ligne Les fichiers de texte sont souvent organisés en lignes. Selon le système d’exploitation, il y a plusieurs façon de représenter une fin de ligne. Les systèmes d’exploitation Microsoft utilisent deux caractères (« retour de charriot » et « nouvelle ligne ») à la fin de chaque ligne. Les autres système utilisent généralement un seul caractère (« nouvelle ligne »). Les processeurs XML sont requis de normaliser la situation et de remplacer les deux caractères utilisés par les systèmes Microsoft par un seul caractère lors de la lecture du fichier. Ainsi, peu importe comment l’on note les fins de ligne, un processeur XML ne vera qu’un caractère « nouvelle ligne ». 1.5.13 Les hyperliens Il arrive fréquemment qu’on utilise des hyperliens dans les documents XML. On distingue deux types d’hyperliens : les hyperliens contenant une adresse absolue (telle que http://domaine.ca/pong.png) et les hyperliens contenant des adresses relatives (pong.png). On reconnaît les adresses relatives parce qu’elles ne débutent pas par un protocole tel que http ou ftp. Pour compléter les adresses relatives et les transformer en adresses absolues, on utilise fréquemment l’adresse du document. Ainsi, si le document suivant se trouve à l’adresse http://domaine.ca/fichier.xml, alors un logiciel pourra charger une image située à l’adresse http://domaine.ca/pong.png : <racine> adresse relative: <image lien="pong.png" /> </racine> Le XML permet de spécifier un attribut xml:base qui sert à interpréter les adresses relatives remplaçeant l’adresse du document. Le document suivant pointe vers une image à l’adresse http://domaine.ca/image/pong.png : <racine xml:base="http://domaine.ca/" > <p xml:base="image/"> <image lien="pong.png" /> </p> </racine> 1.5.14 Documents bien formés Un document XML qui respecte ces règles de base est dit « bien formé ». Pour éviter la confusion, il ne faut pas utiliser des synonymes comme « correct ». La terminologie utilisée peut sembler très aride. Cependant, la rigueur qu’exige le XML est aussi garante de la cohérence. Comme tous les termes sont bien définis, il est plus CC BY-NC-SA Définition de type de document 31 facile de s’entendre entre experts. Comme le XML est surtout utilisé pour la communication entre les logiciels, la rigueur évitera plus tard les bogues et les incompréhensions. Pouvoir reconnaître un document XML bien formé ou comprendre pourquoi un document n’est pas bien formé, permet de s’assurer qu’un logiciel pourra traiter les informations, et qu’on saura quoi faire en cas de problème. 1.6 1.6.1 Définition de type de document Objectif Comprendre la notion de type de document et son rôle dans la définition de document valable. 1.6.2 Activité Lisez le texte qui suit, puis répondez au questionnaire d’autoévaluation. Ce texte traite des définitions de type de document (DTD) qui servent à définir les documents XML valables. 1.6.3 Document XML valable Nous avons vu ce qu’était un document XML bien formé : un seul élément-racine, les éléments ne se chevauchent pas, les noms XML ne commencent pas par un chiffre, et ainsi de suite. De plus, un document XML bien formé peut contenir n’importe quel élément et dans n’importe quel ordre, et tous les éléments peuvent contenir des attributs, et peu importe ceux-ci. En pratique, il est souvent suffisant pour les documents XML d’être bien formés, mais il arrive qu’on veuille imposer des contraintes supplémentaires aux éléments et attributs pouvant être utilisés. Par exemple, un élément « étudiant » pourrait posséder un numéro d’étudiant, mais pas l’inverse : un élément « numéro d’étudiant » ne pouvant contenir qu’un numéro et pas d’autres éléments. On peut aussi vouloir contraindre le contenu d’un document XML pour des raisons d’interopérabilité. Par exemple, si un groupe d’experts s’entendent sur un format XML pour un type de données, il est utile de pouvoir vérifier si un fichier XML donné correspond bien à ce sur quoi on s’est entendu. Un document XML qui est bien formé et qui respecte les contraintes définissant son type de document est dit valable (ou valide). En d’autres mots, un document XML qui est bien formé et qui, en plus, satisfait aux contraintes dictant quels éléments et attributs peuvent être utilisés, et dans quel ordre et avec quel contenu, est dit valable. CC BY-NC-SA Module 1 : Introduction à XML 1.6.4 32 Normes de définition de type de document Il y a plusieurs façons de définir des types de documents XML. L’approche la plus répandue, la plus ancienne et la plus simple, est la norme de définition de type de document (DTD). C’est la seule approche présentée dans ce cours. Les deux autres possibilités émergentes les plus répandues sont XML Schema et Relax NG. On fait généralement deux reproches à l’approche DTD : un document DTD n’est pas du XML et la norme n’est pas assez riche pour spécifier le contenu des documents XML avec finesse. En effet, L’approche DTD ne permet pas de déclarer qu’un contenu textuel doit être une date ou un nombre, et il n’y a pas de support pour les espaces de noms, sujet que nous traiterons plus loin dans ce module. D’un autre côté, la norme DTD est très répandue et tous les logiciels qui supportent XML supportent maintenant cette norme, incluant Java et Firefox. Les nouveaux formats comme XHTML 2.0 sont toujours publiés avec une spécification DTD. Les autres possibilités, comme XML Schema, Relax NG, Schematron et Examplotron, sont moins bien supportées. La norme XML Schema permet de définir avec une grande finesse des types de données comme une date ou un code de langue (« fr », « en »). Cette norme est très utile si on veut spécifier avec beaucoup de détail le format de nos documents XML. Comme vous pouvez le constater dans l’exemple suivant, la norme XML Schema permet non seulement de spécifier le nom des éléments et des attributs (« shipTo », « billTo », « comment », « items », « orderDate »), mais aussi leur type (« xsd:string », « xsd:decimal », « xsd:date »). <xsd:complexType name="PurchaseOrderType"> <xsd:sequence> <xsd:element name="shipTo" type="USAddress"/> <xsd:element name="billTo" type="USAddress"/> <xsd:element ref="comment" minOccurs="0"/> <xsd:element name="items" type="Items"/> </xsd:sequence> <xsd:attribute name="orderDate" type="xsd:date"/> </xsd:complexType> <xsd:complexType name="USAddress" > <xsd:sequence> <xsd:element name="name" type="xsd:string"/> <xsd:element name="street" type="xsd:string"/> <xsd:element name="city" type="xsd:string"/> <xsd:element name="state" type="xsd:string"/> <xsd:element name="zip" type="xsd:decimal"/> </xsd:sequence> <xsd:attribute name="country" type="xsd:NMTOKEN" fixed="US"/> </xsd:complexType> CC BY-NC-SA Définition de type de document 33 La norme XML Schema est supportée en Java depuis la version 1.5. Il n’est pas nécessaire d’utiliser une librairie spécialisée.Elle est cependant sujette à des critiques très sévères de la part des experts en XML tels que Tim Bray (co-inventeur du XML) qui écrivait en novembre 2006 sur son blogue : Everybody who actually touches the technology has known the truth for years, and it’s time to stop sweeping it under the rug. W3C XML Schemas (XSD) suck. They are hard to read, hard to write, hard to understand, have interoperability problems, and are unable to describe lots of things you want to do all the time in XML. Schemas based on Relax NG, also known as ISO Standard 19757, are easy to write, easy to read, are backed by a rigorous formalism for interoperability, and can describe immensely more different XML constructs. En somme, XML Schema est trop difficile à utiliser et à comprendre. Tim Bray, ainsi que de nombreux autres experts, préconisent plutôt l’utilisation de Relax NG. Cette norme, comme XML Schema, possède plusieurs avantages sur la norme DTD : elle permet de spécifier des types de données (comme une date ou un nombre), supporte les espaces de noms, etc. De plus, la norme Relax NG est plus élégante techniquement et parfois plus simple que la norme XML Schema. Des formats importants comme l’Open Document Format, DocBook (format XML), TEI, XHTML 2.0 et Atom sont définis par RelaxNG plutôt que par XML Schema. (Une définition XML Schema sera sans doute produite pour le format XHTML 2.0.) Relax NG dispose aussi d’une syntaxe « compacte », qui n’est pas en XML contrairement au format par défaut de Relax NG, et que nous allons utiliser dans nos exemples. Voici un exemple de Relax NG : element addressBook { element card { element name { text }, element email { text } }* } Cet exemple spécifie que le document XML doit avoir comme élément racine un élément « addressBook », contenant zéro ou plus éléments « card ». Un élément « card » doit obligatoirement contenir un élément « name » suivi d’un élément « email ». On trouve facilement des tutoriels de qualité sur Relax NG. L’un meilleur tutoriel est en anglais à l’adresse http://relaxng.org/compact-tutorial-20030326.html. Tout en étant plus élégante que la norme DTD, le format Relax NG est plus limitée que XML Schema puisqu’il ne permet que quatre types de contraintes sur le nombre d’occurences d’un élément (zeroOrMore comme dans notre exemple, optional, un nombre précis (comme une seule fois) et oneOrMore) alors que le XML Schema permet des contraintes beaucoup plus spécifiques. Cependant, la richesse de la norme XML Schema a un coût : il s’agit d’une norme beaucoup plus difficile à utiliser et à apprendre en pratique. CC BY-NC-SA Module 1 : Introduction à XML 34 On peut valider un document XML par rapport à une définition RelaxNG avec la librairie Jing (http://www.thaiopensource.com/relaxng/jing.html). On peut passer automatiquement d’un document DTD à un document XML Schema ou Relax NG avec un outil comme NekoDTD (http://people.apache.org/ andyc/neko/doc/ dtd/conversions.html). En somme, la norme DTD n’est sans doute pas ce qui se fait de mieux, mais c’est de loin la norme la plus utilisée historiquement, et c’est celle que nous allons étudier en détail. Pour certaines applications, la norme DTD demeure supérieure aux alternatives mentionnées précédemment: la définition d’entités n’est pas possible en XML Schema ou Relax NG, par exemple. Si vous maîtrisez la norme DTD, vous n’aurez aucun mal à utiliser une autre norme comme Relax NG puisque les principes essentiels sont les mêmes. Notez que la webographie contient quelques liens vers les normes XML Schema et Relax NG. 1.6.5 Documents valables utilisant la norme DTD Un document valable commence par une déclaration XML, comme celle qui suit : <?xml version="1.0" encoding="ISO-8859-1" standalone="no" ?> Elle est suivie d’une déclaration de type de document sous la forme <!DOCTYPE ... SYSTEM ... > , où l’on remplace les premiers trois points par le nom XML de l’élément-racine que le document doit avoir, et les deuxièmes trois points par une URL vers le document DTD. L’URL peut être absolue, comme « http://www.google.com/mydtd.dtd », ou locale, comme « madtd.dtd » ou « ../dtd/madtd.dtd ». Dans le second cas, il faut que le fichier DTD soit sur le disque, à l’endroit indiqué par rapport au fichier XML. Ainsi, dans l’exemple « ../dtd/madtd.dtd », il faudrait que le fichier « madtd.dtd » soit dans le répertoire « dtd », voisin du répertoire où se trouve le fichier XML. Ainsi, immédiatement après la déclaration XML, on pourrait avoir le texte suivant : <!DOCTYPE baliseracine SYSTEM "http://www.mondomain.com/madtd.dtd"> où « baliseracine » est le nom de l’élément-racine du document, alors que le chemin « http://www.mondomain.com/madtd.dtd » nous dit où trouver le document DTD. Rappelons que l’attribut « encoding » nous donne le jeu des caractères. On choisit souvent « ISO-8859-1 », mais par défaut, XML utilise un jeu de caractères Unicode (UTF-8). Si le contenu est en français (avec les accents), il est essentiel que le fichier soit enregistré avec le jeu de caractères déclaré sinon on pourra constater des messages d’erreurs ou des accents manquants. L’attribut « standalone » permet au logiciel de décider, s’il est nécessaire, d’aller chercher la DTD externe avant de lire le fichier XML, même si, très souvent, un logiciel tel Mozilla Firefox ignore la consigne et ne va pas CC BY-NC-SA Définition de type de document 35 chercher la DTD externe. En gros, s’il y a une DTD externe, on utilisera l’attribut « standalone="no" », autrement on utilise « standalone="yes" ». 1.6.6 La syntaxe des documents DTD Les documents DTD contiennent des instructions de la forme <!ELEMENT ... >. Bien que celle-ci ait l’apparence d’une balise XML, ce n’est pas du XML. Dans une instruction, on met d’abord un nom XML qui correspond à un nom d’élément : par exemple, l’instruction « <!ELEMENT montant ... > » définira ce qui peut être contenu dans un élément de nom « montant ». Tout ce qui suit le nom de l’élément dicte ce que l’élément peut contenir. Le plus souvent, on place la description du contenu entre parenthèses (« <!ELEMENT montant (quelque chose) > »), sauf pour les cas particuliers (« ANY » et « EMPTY ») définis plus loin. De façon courante, on définit le contenu d’un élément par une liste de noms XML, correspondant à des noms d’élément et séparés par des virgules. Par exemple, l’instruction « <!ELEMENT montant (devise,valeur) > » nous informe qu’un élément « montant » doit contenir un élément « devise » suivi d’un élément « valeur ». Notons que l’ordre des éléments importe et que les instructions « <!ELEMENT montant (devise,valeur) > » et « <!ELEMENT montant (valeur,devise) > » ne sont pas équivalentes. Bien qu’on ne puisse exprimer toutes les possibilités, la syntaxe DTD permet tout de même de spécifier un grand nombre de règles. Par exemple, le symbole « ? » permet de spécifier qu’un élément peut être présent ou non (élément optionnel). Ainsi, l’instruction « <!ELEMENT montant (devise?,valeur) > » signifie que l’élément « montant » peut contenir un élément « devise » (ou non) et doit contenir un élément « valeur ». Si jamais l’élément « devise » apparaît, il doit apparaître avant l’élément « valeur ». Si jamais on veut qu’un élément soit optionnel et que, s’il apparaît, il puisse apparaître plus d’une fois, on utilise le symbole « * ». Ainsi, l’instruction « <!ELEMENT montant (devise*,valeur) > » signifie qu’on peut avoir zéro, un ou plusieurs éléments « devise », puis un élément « valeur ». De la même façon, le symbole « + » est utilisé pour spécifier qu’un élément doit être présent, mais peut apparaître plus d’une fois. Au lieu d’utiliser la virgule, on peut utiliser le symbole « | » pour spécifier qu’un élément ou un autre peut apparaître. Ainsi, l’instruction « <!ELEMENT montant (devise|valeur) > » signifie que l’élément « montant » peut contenir soit l’élément « devise », soit l’élément « valeur » (l’un ou l’autre, mais pas les deux ou aucun des deux). Finalement, on peut combiner le tout; par exemple, l’instruction « <!ELEMENT montant (devise+|valeur*) > » signifie que l’élément « montant » peut contenir au moins un élément « devise » (et rien d’autre) ou alors, aucun, 1 ou plusieurs éléments « valeur ». Si jamais on veut qu’un élément puisse contenir du texte, on utilise le terme technique « #PCDATA » dans l’instruction DTD. Par exemple, l’instruction « <!ELEMENT montant (#PCDATA) > » signifie que l’élément « montant » contient du texte et seulement du texte (pas d’éléments). Supposons maintenant qu’on veut permettre du contenu mixte, comme dans l’exemple qui suit : <mixte> CC BY-NC-SA Module 1 : Introduction à XML 36 Ceci est du contenu <important>mixte</important> parce qu’il s’agit de mélange de texte et de <important>balises</important>. </mixte> On pourrait penser que l’instruction « <!ELEMENT mixte (#PCDATA|important) > » permettra du texte ou des éléments « important », et c’est vrai; mais elle permet l’un (juste du texte) ou l’autre (juste un élément « important »), mais pas un mélange des deux. Pour pouvoir obtenir le résultat désiré, soit un mélange d’éléments « important » et de texte, il faut permettre la répétition du choix, comme dans l’instruction « <!ELEMENT mixte (#PCDATA|important)* > ». Il s’agit de la seule façon de spécifier qu’on permet un mélange de texte et d’éléments (contenu mixte). Voyons un autre exemple de contenu mixte. Considérons l’instruction « <!ELEMENT montant (#PCDATA|devise)* > ». Ce qu’elle signifie exactement, c’est que les éléments « montant » peuvent contenir un mélange de texte et des éléments « devise », comme l’exemple qui suit : <montant> Le montant est spécifié en <devise>dollars</devise>. </montant> On peut aussi utiliser « ANY » pour spécifier qu’un élément peut contenir n’importe quoi (n’importe quelle séquence d’éléments déclarés dans la DTD et du texte) ou « EMPTY » pour spécifier qu’un élément doit être vide (sans même un seul espace). C’est le seul cas où l’on n’utilise pas de parenthèses lors de la définition du contenu, comme dans ces exemples : <!ELEMENT question ANY> et <!ELEMENT question EMPTY>. Un document DTD prendra donc la forme d’un fichier en format texte contenant une suite d’instructions comme : <!ELEMENT <!ELEMENT <!ELEMENT <!ELEMENT <!ELEMENT <!ELEMENT <!ELEMENT <!ELEMENT <!ELEMENT <!ELEMENT problemset (title?,recall?,item*)*> recall (#PCDATA | section | codexml )*> item (question, choice+)> choice (response, feedback)> question (#PCDATA)> response (#PCDATA)> feedback (#PCDATA)> codexml (#PCDATA)> title (#PCDATA)> section (#PCDATA)> Notez qu’on écrit rarement de nouvelles DTD : dans un domaine particulier, il existera souvent des DTD déjà utilisées; sinon, on fera l’effort de les créer, mais qu’une seule fois. L’important demeure toutefois de pouvoir lire et comprendre les DTD. CC BY-NC-SA Définition de type de document 1.6.7 37 Exemple supplémentaire Pour s’assurer de bien comprendre, voyons un autre exemple : <!ELEMENT <!ELEMENT <!ELEMENT <!ELEMENT lettre (#PCDATA | personne)*> personne (age, nom)> age (#PCDATA)> nom (#PCDATA) > Cette DTD nous spécifie que l’élément « lettre » contient du mélange de texte et d’éléments « personne » (contenu mixte), alors que l’élément « personne » doit contenir un élément « age », suivi d’un élément « nom ». Par exemple, ce document XML serait valable : <?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE lettre [ <!ELEMENT lettre (#PCDATA | personne)*> <!ELEMENT personne (age, nom)> <!ELEMENT age (#PCDATA)> <!ELEMENT nom (#PCDATA) > ]> <lettre> Ceci est une lettre pour <personne><age>51</age><nom>Jean</nom></personne>. </lettre> Assurez-vous de bien comprendre pourquoi ce document est valable avant de continuer. 1.6.8 Les attributs Par défaut, aucun élément n’est autorisé à avoir un attribut. Pour permettre d’ajouter un attribut à un élément, il faut une instruction de la forme <!ATTLIST recipiendaire age ...> qui spécifie que l’élément recipiendaire peut avoir un attribut « age ». On permet généralement aux valeurs d’attribut de contenir n’importe quel texte, ce qu’on représente par « CDATA ». Hormis le contenu, il existe deux types d’attributs : les attributs obligatoires (« #REQUIRED ») et les attributs optionnels (« #IMPLIED »). Par exemple, l’instruction « <!ATTLIST recipiendaire age CDATA #IMPLIED> » signifie qu’on peut (ou pas) accorder à un élément « recipiendaire » un attribut nommé « age » pouvant contenir n’importe quel texte. Si l’on désire que l’attribut soit obligatoire, on utilise une instruction comme « <!ATTLIST recipiendaire age CDATA #REQUIRED> ». Si l’on veut permettre à un élément d’avoir plusieurs attributs, on peut le faire en utilisant plusieurs instructions comme dans « <!ATTLIST recipiendaire age CDATA #REQUIRED> <!ATTLIST recipiendaire nom CDATA #REQUIRED> »; on peut aussi combiner les instructions dans une seule : « <!ATTLIST recipiendaire age CDATA CC BY-NC-SA Module 1 : Introduction à XML 38 #REQUIRED nom CDATA #REQUIRED> ». Cependant, il n’est pas possible de spécifier l’ordre dans lequel les attributs doivent apparaître, les instructions « <!ATTLIST recipiendaire age CDATA #REQUIRED nom CDATA #REQUIRED> » et « <!ATTLIST nom CDATA #REQUIRED recipiendaire age CDATA #REQUIRED> » sont équivalentes. L’attribut « xml:lang » utilisé pour définir la langue d’un texte, peut être déclaré comme ceci : « <!ATTLIST monelement xml:lang CDATA #IMPLIED> ». L’attribut xml:space peut être déclaré comme ceci : « <!ATTLIST monelement xml:space (default|preserve) #IMPLIED> ». On peut également spécifier qu’un élément donné a toujours un attribut donné (indiqué ou non dans le XML) comme ceci : « <!ATTLIST recipiendaire age CDATA #FIXED "40 ans"> ». Dans ce dernier exemple, tous les éléments « recipiendaire » ont l’attribut « age="40 ans" », même si on omet de l’indiquer dans la balise de départ de l’élément « recipiendaire ». Plus simplement, on peut spécifier une valeur par défaut qui ne prendra effet que si l’on n’a pas explicitement indiqué l’attribut. Par exemple, l’instruction « <!ATTLIST recipiendaire age CDATA "40 ans"> » signifie que l’élément « recipiendaire » aura l’attribut « age="40 ans" », à moins qu’on ne spécifie autre chose dans le XML. Il peut être utile de donner une liste de valeurs que pourra prendre un attribut. Par exemple, une pièce de monnaie est soit sur « face », soit sur « pile » : il n’y a que deux choix. Si la liste de choix est composée de textes sans espace ou ponctuation, sauf la barre du soulignement ( _ ), le trait d’union ( - ) et le point ( . ), alors on peut faire une énumération comme dans l’exemple suivant : « <!ATTLIST piece position (face|pile) #REQUIRED> ». On peut aussi spécifier une valeur par défaut, si l’on suppose, jusqu’à preuve du contraire, que la pièce est dans la position « face », comme ceci « <!ATTLIST piece position (face|pile) "face"> » On peut également spécifier qu’un attribut servira à identifier un élément de façon unique. Pour ce faire, on utilise une instruction comme « <!ATTLIST recipiendaire code ID> ». Il n’est pas possible, pour deux attributs de type ID, d’avoir la même valeur dans un même document XML. En somme, si l’on donne une valeur « ID », elle devrait correspondre de façon unique à un élément et un seul. Un attribut de type « ID » doit avoir comme valeur un « nom XML », c’est-à-dire un texte sans espace ou ponctuation, sauf la barre du soulignement ( _ ), le trait d’union ( - ) et le point ( . ), et qui ne commence pas par un chiffre, un trait d’union ou un point. On peut faire référence aux attributs de type « ID » avec des attributs de type « IDREF ». La valeur d’un attribut « IDREF » doit non seulement être un nom XML, mais doit aussi avoir un attribut de type « ID » qui possède cette même valeur quelque part dans le document XML. Par exemple, si on a l’instruction « <!ATTLIST recipiendaire code ID> », on pourra ensuite faire référence à l’élément ayant une valeur d’attribut « code » particulière, avec une instruction comme « <!ATTLIST mauvaispayeur code IDREF> ». Dans ce contexte, le document XML qui suit n’est pas valable : CC BY-NC-SA Définition de type de document 39 <mondocument> <recipiendaire code="s765" /> <recipiendaire code="s766" /> <mauvaispayeur code="s894" /> </mondocument> Par contre, l’exemple qui suit est valable : <mondocument> <recipiendaire code="s765" /> <recipiendaire code="s766" /> <mauvaispayeur code="s765" /> </mondocument> Il existe d’autres types d’attributs, mais ils sont peu utilisés. 1.6.9 Les entités Vous vous rappelez sans doute que le XML définit quelques entités par défaut, « < », par exemple. On peut toutefois définir ses propres entités avec une instruction DTD comme celle-ci : <!ENTITY monentite "Introduction à XML"> La signification de ce dernier exemple, c’est que partout où « &monentite; » apparaît dans un document, il sera remplacé par le texte « Introduction à XML ». Ce remplacement s’applique aussi aux valeurs par défaut des attributs de la DTD. On peut mettre des éléments et des attributs dans une entité comme dans cet exemple : <!ENTITY monentite "<p titre=’x’>mon paragraphe</p>"> Il n’est cependant pas permis de ne mettre qu’une partie d’un élément comme ceci : <!ENTITY monentite "<p>mon paragraphe"> Une entité peut faire appel à une autre entité : <!ENTITY montexte "La vie."> <!ENTITY monentite "<p>&montexte;</p>"> Une entité ne peut cependant pas faire appel à elle même de manière récursive, directement ou indirectement. Cet exemple n’est donc pas valable : CC BY-NC-SA Module 1 : Introduction à XML 40 <!ENTITY montexte "La vie. &monentite;"> <!ENTITY monentite "<p>&montexte;</p>"> 1.6.10 DTD interne et externe Normalement, on fait référence à un document DTD à l’aide d’une URL, c’est ce qu’on appelle la DTD externe. Mais il est possible d’ajouter ses propres instructions DTD directement dans le document XML, en ajoutant une DTD interne qui est lue avant la DTD externe. Prenons l’exemple suivant, soit un document XML qui débute par : <?xml version="1.0" encoding="ISO-8859-1" standalone="no"?> <!DOCTYPE problemset SYSTEM "../dtd/quiz.dtd"[ <!ELEMENT question #PCDATA> ]> Dans ce cas, tout ce passe comme si on ajoutait la ligne « <!ELEMENT question #PCDATA> » à la DTD externe. Normalement, il ne devrait jamais y avoir de conflit entre les deux DTD (interne et externe); on ne peut pas redéfinir un élément, mais on peut y définir des éléments! Par contre, les entités peuvent être redéfinies et la définition trouvée dans le DTD interne l’emporte. On peut même omettre complètement la DTD externe comme dans l’exemple suivant : <?xml version="1.0" encoding="ISO-8859-1" standalone="yes" ?> <!DOCTYPE jeu [ <!ELEMENT jeu (nom,(age|niveau))> <!ELEMENT nom (#PCDATA)> <!ELEMENT age (#PCDATA)> <!ELEMENT niveau (#PCDATA)> ]> 1.6.11 Les entités paramètres On peut aussi définir des entités particulières qui ne s’appliquent que dans le contexte de la DTD, et non pas dans le document XML. Pour ces entités, au lieu d’utiliser l’esperluette ( & ), on utilise plutôt le symbole du pourcentage ( % ). Ainsi, l’instruction suivante : <!ENTITY % monentite "#PCDATA|age*"> CC BY-NC-SA Définition de type de document 41 signifie que partout, dans la DTD externe, où se trouve le texte « %monentite; », il sera remplacé par « #PCDATA|age* »; on appelle ces entités des « entités paramètres ». On peut définir une entité paramètre dans la DTD interne, mais on ne peut pas l’y utiliser; elle doit être utilisée dans la DTD externe. Si l’entité paramètre « %monentite; » est définie, à la fois dans la DTD interne et dans la DTD externe, la DTD interne a préséance. En somme, les entités paramètres ne s’appliquent que dans la DTD externe; elles ne s’appliquent ni dans le document XML, ni dans le DTD interne, soit la partie de la DTD définie dans le document XML. 1.6.12 Commentaires dans les fichiers DTD Pour rendre un fichier DTD plus compréhensible, on peut ajouter des commentaires. La syntaxe est la même que pour les fichiers XML comme le montre l’exemple suivant. <!-- Un élément lettre contient des éléments personne et du texte --> <!ELEMENT lettre (#PCDATA | personne)*> <!-- Un élément personne contient un élément age et un élément nom --> <!ELEMENT personne (age, nom)> <!ELEMENT age (#PCDATA)> <!ELEMENT nom (#PCDATA) > Les commentaires dans les fichiers Relax NG non-textuel sont obtenus en débutant une ligne par le symbole « # » comme dans cet exemple. element addressBook { # les éléments addressBook contiennent 0, 1, ou plusieurs # éléments card element card { # les éléments card contiennent un élément # name et un élément email element name { text }, element email { text } }* } 1.6.13 Une comparaison entre Relax NG et DTD Une fois qu’on connaît bien le format DTD, il est facile d’apprendre Relax NG. Prenons d’abord un de nos exemples de fichier DTD. <!ELEMENT <!ELEMENT <!ELEMENT <!ELEMENT lettre (#PCDATA | personne)*> personne (age, nom)> age (#PCDATA)> nom (#PCDATA) > CC BY-NC-SA Module 1 : Introduction à XML 42 Une étude attentive vous permettra de constater que ce fichier est très similaire au fichier Relax NG suivant, qui lui est essentiellement équivalent. element lettre { # un élément lettre contient # du texte et des éléments # personne (text | element personne { # un élément personne # contient un élément age # suivi d’un élément nom element age {text}, element nom {text}, } )* } Pour bien comprendre, prenons un autre exemple, plus complexe cette fois-ci. Voici un autre fichier DTD discuté précédemment. <!ELEMENT <!ELEMENT <!ELEMENT <!ELEMENT <!ELEMENT <!ELEMENT <!ELEMENT <!ELEMENT <!ELEMENT <!ELEMENT problemset (title?,recall?,item*)*> recall (#PCDATA | section | codexml )*> item (question, choice+)> choice (response, feedback)> question (#PCDATA)> response (#PCDATA)> feedback (#PCDATA)> codexml (#PCDATA)> title (#PCDATA)> section (#PCDATA)> Voici l’équivalent en Relax NG. Si vous l’étudiez avec soin, vous verrez qu’encore une fois, le format Relax NG est très similaire au format DTD. element problemset { ( element title { text } ?, element recall { ( text | element section {text} | element codexml {text}) * } ?, element item { element question {text}, CC BY-NC-SA Définition de type de document 43 element choice { element response { text}, element feedback {text} }+ } * )* } Prenons maintenant un exemple de fichier DTD contenant un attribut. <!ELEMENT lettre (#PCDATA|personne)*> <!ELEMENT personne (age,nom,estunhomme?)> <!ATTLIST personne nas CDATA #IMPLIED> <!ELEMENT age (#PCDATA)> <!ELEMENT nom (#PCDATA)> <!ELEMENT estunhomme EMPTY> L’équivalent Relax NG est, encore une fois, assez compréhensible comme vous pourrez le constater, l’instruction ATTLIST étant remplacée par l’instruction « attribute ». element lettre { # un élément lettre contient # du texte et des éléments # personne (text | element personne { # une élément personne # contient un élément age # suivi d’un élément nom # et, optionnellement, d’un # élément estunhomme qui est # obligatoirement vide, # l’élément personne peut aussi # avoir un attribut nas attribute nas {text}?, element age {text}, element nom {text}, element estunhomme {empty}? } )* } Lorsqu’on utilise l’instruction attribute, la présence de l’attribut est requise à moins d’ajouter le point d’interrogation (« ? ») à la suite de l’instruction. CC BY-NC-SA Module 1 : Introduction à XML 44 Le format Relax NG permet aussi de définir des motifs qui peuvent être réutilisés. Prenons ce fichier DTD simple. <!ELEMENT carte (page)> <!ELEMENT page (carte)> L’équivalent en Relax NG donne ceci. carte = element carte { page } page = element page { carte } Le format Relax NG a cependant plusieurs avantages. Par exemple, l’esperluette (&) permet de spécifier que des éléments puissent être inclus dans n’importe quel ordre. Il n’y a pas d’équivalent en DTD. Considérons l’exemple suivant. element addressBook { element card { element name { text } & element email { text } }* } On peut alors permettre le XML suivant. Il n’est pas possible de spécifier le contenu de l’élément card avec une instruction DTD similaire. <addressBook> <card><name>Jean</name><email>l@c</email></card> <card><email>l@c</email><name>Jean</name></card> </addressBook> Supposons maintenant qu’un élément puisse avoir soit l’attribut nas, soit à la fois les attributs nas1 et nas2. Alors qu’il n’est pas possible de représenter cette condition en DTD, c’est une chose facile en Relax NG. element homme { ( attribute nas {text} | ( attribute nas1 {text}, attribute nas2 {text} ) ) } Vous êtes invité à poursuivre vos lectures sur le format Relax NG en faisant des recherches sur le web. CC BY-NC-SA Définition de type de document 1.6.14 45 Une approche plus modulaire En pratique, les fichiers DTD et Relax NG peuvent devenir complexes. On souhaite donc souvent les diviser en plusieurs fichiers plus petits. Par exemple, pour une spécification portant des ventes et achats de biens, on pourra avoir un fichier portant sur la description des biens, un fichier portant sur la description des acheteurs, et ainsi de suite. Une approche modulaire, avec de petits fichiers, a aussi l’avantage qu’on peut réutiliser les fichiers dans plus d’une spécification. À titre d’exemple, reprenons le fichier DTD portant sur la définition de l’élément « problemset ». Au lieu de définir tout d’un seul coup, on peut commencer par un fichier DTD qui ne définit que l’élément « choice » : <!ELEMENT choice (response, feedback)> <!ELEMENT feedback (#PCDATA)> <!ELEMENT response (#PCDATA)> Pour les fins de notre exemple, supposons que ce dernier fichier porte le nom de « choice.dtd » et se trouve à l’adresse « http://www.mondomaine.com/choice.dtd ». On pourra alors en importer le contenu dans un autre fichier externe avec une « entité paramètre externe ». À la différence d’une entité paramètre usuelle, une entité paramètre externe pointe vers un autre document que le logiciel devra traiter. On définit l’entité paramètre externe avec l’instruction « SYSTEM » suivie d’une adresse web comme dans cet exemple : <!ENTITY % monentite SYSTEM "http://www.mondomaine.com/choice.dtd"> Pour inclure le contenu du fichier externe (« choice.dtd » dans notre exemple), il suffit tout simplement de faire appel à l’entité comme ceci : <!ENTITY % monentite SYSTEM "http://www.mondomaine.com/choice.dtd"> %monentite; Dans ce cas, tout se déroule comme si le contenu du fichier « choice.dtd » était inséré à l’endroit où se trouve l’appel (« %monentite; »). On peut définir l’élément « problemset » à l’aide du fichier DTD suivant : <!ENTITY % monentite SYSTEM "http://www.mondomaine.com/choice.dtd"> %monentite; <!ELEMENT problemset (title?,recall?,item*)*> <!ELEMENT recall (#PCDATA | section | codexml )*> <!ELEMENT item (question, choice+)> <!ELEMENT question (#PCDATA)> <!ELEMENT codexml (#PCDATA)> <!ELEMENT title (#PCDATA)> <!ELEMENT section (#PCDATA)> CC BY-NC-SA Module 1 : Introduction à XML 46 On peut obtenir le même résultat avec Relax NG, un peu plus simplement avec l’utilisation de l’instruction « include ». Créons d’abord un fichier « choice.rnc » avec le contenu suivant : choiceele = element choice { element response { text}, element feedback {text} } On peut alors réutiliser le motif « choiceele » dans n’importe quel autre fichier Relax NG comme le montre cet exemple : include "choice.rnc" element problemset { ( element title { text } ?, element recall { ( text | element section {text} | element codexml {text}) * } ?, element item { element question {text}, choiceele+ } * )* } En bref, il est facile de diviser des spécifications Relax NG ou DTD en plusieurs fichiers plus petits, plus faciles à éditer, et qui peuvent être plus facilement réutilisés. 1.6.15 Définir l’élément-racine Avec une DTD, il n’est pas possible de définir l’élément-racine. Celui-ci est déclaré par l’instruction DOCTYPE qui se trouve dans le document XML. Avec Relax NG, on peut non seulement spécifier l’élément-racine avec le mot-clef start, mais on peut aussi permettre une certaine flexibilité. Par exemple, l’instruction « start = problemset | choice » placée dans un fichier Relax NG, nous indique qu’on peut utilisé l’élément problemset ou l’élément choice comme élément-racine. CC BY-NC-SA Définition de type de document 1.6.16 47 Définir le type de contenu en Relax NG Dans tous nos exemples de Relax NG, nous n’avons prévu que du contenu textuel (text) ou des éléments vides (empty). Relax NG permet de spécifier le contenu d’un élément ou d’un attribut d’une manière très fine. Il emprunte ici la spécification mise au point par XML Schema. En particulier, on peut spécifier un contenu textuel à l’aide d’une expression régulière. Voici quelques exemples. Type Explication Exemple xsd:date Une date formattée avec 2001-01-01 ou 1999-12la convention YYYY- 30 MM-DD xsd:dateTime Un moment spécifique à 2000-12-31T03:32:00 la seconde près xsd:string pattern = Une chaîne de caractères maison "[ˆ:]+" contenant au moins un caractère, à l’exclusion du symbole : xsd:string pattern = Deux chaînes de carac- 01/01 ".+/.+" tères séparée par un caractère / xsd:string pattern = Deux chaînes de carac- [email protected] ".+@.+" tères séparée par un caractère @ "text" | "html" text ou html text xsd:string min- Une chaîne caractères fai- monmotdepasse Length="7" max- sant entre 7 et 25 caracLength="25" tères xsd:decimal minExclu- Un nombre entre 0 et 10 5 sive="0.0" maxInclusive="10.0" xsd:decimal fractionDi- Un nombre n’ayant pas 5.001 gits="3" plus de 3 chiffres après la virgule (le point) On déclare ensuite le contenu d’un élément ou d’un attribut comme ceci : element madate xsd:date. 1.6.17 Est-ce qu’il existe un outil pour passer d’un format à l’autre (DTD, Relax NG, XML Schema)? Oui, le programme Java Trang (http://www.thaiopensource.com/relaxng/trang.html) permet de passer facilement d’un format à l’autre. CC BY-NC-SA Module 1 : Introduction à XML 1.6.18 48 Est-ce qu’un document DTD est un document XML? Absolument pas. Par contre, une DTD est un document textuel. Les fichiers XML Schema sont par contre toujours en XML, alors que les fichiers Relax NG sont parfois en XML, parfois en simple format textuel comme dans nos exemples. 1.6.19 Pourquoi est-ce qu’il n’est pas suffisant d’utiliser des documents bien formés? À quoi sert la validation? Les documents XML sont faits pour être échangés et assurer la pérennité des informations. Si plusieurs individus ou plusieurs institutions s’entendent sur une DTD commune, il sera beaucoup plus facile d’échanger de l’information. 1.6.20 Est-ce vraiment nécessaire d’avoir des documents valables? Est-ce que je dois vraiment toujours travailler avec des fichiers DTD, XML Schema ou Relax NG? En pratique, la validation n’est pas essentielle et une application logicielle ne devrait pas exiger des documents valables. Si vous concevez une application, la règle implicite est que toute balise ou attribut non prévue devrait être ignorée. Un navigateur qui sait lire et afficher du XML devrait pouvoir lire tout XML bien formé, même s’il n’est pas valable. Si vous inventez une nouvelle balise XHTML, le navigateur devrait tout simplement ne pas en tenir compte. Les concepteurs du XML n’ont pas inscrit la nécessité d’être valable à même la définition du XML et c’est un choix qui n’a jamais été remis en question par l’organisme de normalisation W3C. Il arrive, par exemple, qu’il soit inutilement complexe d’exiger que les documents soient bien formés. Si on se contraint à des documents bien formés, on peut même en arriver à des solutions qui sont techniquement inférieures. Pour quelques exemples, voir l’article (en anglais) « Must Ignore vs. Microformats » d’Elliotte Rusty Harold à l’adresse http://cafe.elharo.com/xml/must-ignore-vs-microformats/. Consultez le pense-bête DTD pour avoir une vue d’ensemble et pour réviser. 1.6.21 Livres de référence – Eric van der Vlist, Relax NG, O’Reilly Media, 2003, 486 pages. – Priscilla Walmsley, Definitive XML Schema, Prentice Hall Trade, 2001. CC BY-NC-SA La validation des documents XML 1.7 1.7.1 49 La validation des documents XML Objectif Valider des documents XML. 1.7.2 Activité de validation On peut facilement vérifier si un document XML est « bien formé ». Il suffit de lui donner l’extension « .xml » (ou « .xhtml ») et de l’ouvrir dans Mozilla Firefox, par exemple. Pour effectuer une telle vérification, il existe aussi des services en ligne, dont celui de la Brown University. Cependant, il arrive qu’on veuille vérifier que le document est non seulement bien formé, mais aussi valable par rapport à des documents DTD locaux. Apprenons donc à valider des documents XML, en exécutant les directives qui suivent, car cela vous sera très utile dans vos travaux en XML. La procédure que nous proposons suppose que vous connaissez bien les éléments de base d’un système d’exploitation, comme l’utilisation de la ligne de commande et l’exécution de programmes. Nous ne donnons la procédure que pour Windows, mais elle est très similaire sous MacOS ou Linux. Procédure pour valider des documents XML Avant de procéder à la validation, préparons notre environnement. Allez dans un répertoire, par exemple « C:\XML », et créez le fichier « monfichier.dtd » avec le contenu suivant, en utilisant le bloc-notes : <!ELEMENT etudiant (numero,age)> <!ELEMENT numero (#PCDATA)> <!ELEMENT age (#PCDATA) > Puis, créez un document appelé « mauvais.xml » avec le contenu suivant, toujours à l’aide du bloc-notes : <?xml version="1.0" encoding="ISO-8859-1" standalone="no"?> <!DOCTYPE etudiant SYSTEM "monfichier.dtd"> <etudiant><age>12</age></etudiant> Il est important que les deux fichiers soient dans le même répertoire. En effet, la ligne <!DOCTYPE etudiant SYSTEM "monfichier.dtd"> dans le fichier « mauvais.xml » indique qu’il devrait y avoir un fichier « monfichier.dtd » dans le même répertoire. Vérifions maintenant si le fichier « mauvais.xml » est valable. CC BY-NC-SA Module 1 : Introduction à XML 50 1. D’abord, vous devez disposer d’une machine virtuelle Java récente (Java 1.4 ou mieux) sur votre ordinateur, incluant le compilateur Java : « javac ». Si vous n’en avez pas, il faut effectuer un téléchargement et une installation d’une telle machine. En outre, vous devez avoir sur votre ordinateur le SDK, pas uniquement le JRE. Sur la page qui se trouve à l’adresse http://java.sun.com/j2se/1.4.2/ download.html, cliquez sur « Download J2SE SDK ». Le téléchargement peut prendre plusieurs minutes. Il suffit ensuite de lancer le fichier exécutable que vous venez d’enregistrer sur votre ordinateur pour installer le SDK. Une fois le SDK installé, vous pouvez poursuivre l’activité de vérification. 2. Placez le fichier Validateur.java dans le répertoire où se trouvent déjà vos fichiers « mauvais.xml » et « monfichier.dtd », soit dans « C:\XML ». Votre fichier « Validateur.java » devrait avoir le contenu suivant : //fichier Validateur.java import java.io.*; import org.xml.sax.*; import org.xml.sax.helpers.*; import javax.xml.parsers.*; /** * Ce programme est inspiré de Xerces-J. Il a été modifié * par Daniel Lemire pour le cours "Gestion de l’information * avec XML". * * Date de la première modification: 5 novembre 2004. * * Il suffit de compiler le programme avec * "javac Validateur.java". * On peut ensuite valider un document en faisant * "java Validateur monfichier.xml". * */ public class Validateur extends DefaultHandler { public Validateur() { } public void warning(SAXParseException ex) throws SAXException { printError("Avertissement", ex); } public void error(SAXParseException ex) throws SAXException { printError("Erreur", ex); } CC BY-NC-SA La validation des documents XML 51 public void fatalError(SAXParseException ex) throws SAXException { printError("Erreur fatale", ex); } protected void printError(String type, SAXParseException ex) { System.err.print("["); System.err.print(type); System.err.print("] "); if (ex== null) { System.out.println("!!!"); } String systemId = ex.getSystemId(); if (systemId != null) { int index = systemId.lastIndexOf(’/’); if (index != -1) systemId = systemId.substring(index + 1); System.err.print(systemId); } System.err.print(" ligne: "); System.err.println(ex.getLineNumber()); System.err.println(", colonne: "); System.err.print(ex.getColumnNumber()); System.err.print(", description: "); System.err.print(ex.getMessage()); System.err.println(); System.err.flush(); } public static void main(String argv[]) throws org.xml.sax.SAXException, javax.xml.parsers.ParserConfigurationException { Validateur counter = new Validateur(); PrintWriter out = new PrintWriter(System.out); XMLReader parser = null; parser = SAXParserFactory.newInstance().newSAXParser(). getXMLReader(); parser.setContentHandler(counter); parser.setErrorHandler(counter); parser.setFeature("http://xml.org/sax/features/validation", true); parser.setFeature("http://xml.org/sax/features/namespaces", true); try { parser.parse(argv[0]); CC BY-NC-SA Module 1 : Introduction à XML 52 } catch (SAXParseException e) { } catch (Exception e) { System.err.println("erreur: Erreur de traitement -" +e.getMessage()); } } } 3. Ensuite, lancez la machine virtuelle Java avec une ligne de commande. Pour cela, il faut ouvrir une fenêtre de commande. Sous Windows XP, dans le menu « Démarrer », cliquez sur « Exécuter »; une fenêtre s’ouvre, tapez le nom de programme « cmd » pour ouvrir une fenêtre de commande. Notez qu’avec les versions plus anciennes de Windows, comme Windows 98, il faut taper « command.com ». Une fenêtre s’ouvre alors avec un fond noir, c’est la fenêtre de commande. Vous allez pouvoir y taper des lignes de commande pour vérifier si votre document XML est valable. Les commandes de base sont : « dir » (affiche le contenu d’un répertoire), « cd » (change de répertoire), « cd .. » (répertoire parent), « mkdir » (création d’un nouveau répertoire), « copy » (copie d’un fichier), « move » (déplacement d’un fichier), et « del » (supprime un fichier). 4. Testez l’installation de votre machine virtuelle en tapant « java » suivi du retour de chariot. Vous devriez recevoir un message qui commence par : Usage: java [-options] class [args...] (to execute a class) or java -jar [-options] jarfile [args...] (to execute a jar file) ou quelque chose de similaire. Testez aussi l’installation du compilateur en tapant « javac »; vous devriez voir un message qui commence par quelque chose comme : Usage: javac <options> <source files> Si ce n’est pas le cas, nous vous conseillons de vérifier l’installation de votre machine virtuelle et de procéder à sa réinstallation au besoin. Si tout est bien installé et que ça ne fonctionne toujours pas, vous devrez indiquer le chemin pour trouver le compilateur en tapant la ligne de commande PATH=adresse_du_fichier_javac.exe Le fichier « javac.exe » se trouve dans le dossier « bin » du dossier où vous avez installé le SDK. Par défaut, ce fichier se trouve dans le « C: ». L’adresse du répertoire contenant le fichier « javac.exe » est donc « C:\j2sdk1.4.2_06\bin » ou « C:\Program Files\Java\jdk1.5.0\bin ». Si vous ne savez plus où est installé le SDK, vous pouvez faire une recherche, à partir du menu « Démarrer » de Windows. Une fois le chemin indiqué, retapez la commande « javac » et cette fois, tout devrait fonctionner. Comme il peut être lourd de modifier la variable d’environnement PATH chaque fois, il est possible de la modifier une fois pour toute : allez dans « Démarrer », choisissez « Paramètres », puis « Panneau de configuration », et ouvrez « Système », cliquez sur l’onglet « Avancé »; cliquez CC BY-NC-SA La validation des documents XML 53 ensuite sur le bouton « Variables d’environnement », sélectionnez « PATH » dans la liste des variables, cliquez sur le bouton « Modifier » et ajoutez, à la fin du contenu de la variable, « ;adresse_du_fichier_javac.exe », par exemple « ;C:\Program Files\Java\jdk1.5.0\bin ». 5. Ensuite, placez-vous dans le dossier où se trouvent votre fichier XML et sa DTD. Vous savez toujours où vous vous trouvez dans l’arborescence de votre ordinateur, puisque chaque ligne de commande commence par l’adresse où vous êtes. La commande pour se déplacer est « cd adresse ». Par exemple, si la ligne commence par « C:\Documents and Settings\lucie> », vous êtes dans le dossier de lucie. Pour aller au dossier XML qui se trouve sur le disque C, il faut taper : « cd C:\XML », puis faire le retour de chariot. Une nouvelle ligne apparaît et commence par : « C:\XML> ». Maintenant que vous êtes dans le dossier où se trouve votre fichier XML, vous pouvez vérifier s’il est valable. 6. Faites « javac Validateur.java » pour compiler le petit programme qui pourra vous servir à vérifier la validité des documents XML. Vous ne devriez pas avoir de mal avec la compilation. Par exemple, vous pourriez voir à l’écran : C:\XML>javac Validateur.java Note: Validateur.java uses or overrides a deprecated API. Note: Recompile with -deprecation for details. Vous pouvez ignorer les avertissements vous incitant à utiliser l’option « deprecation ». 7. Tapez la ligne de commande « java Validateur mauvais.xml », puis faites un retour de chariot. Il est important de respecter la casse dans les lignes de commande. Si rien de significatif ne s’affiche, votre fichier est valable, sinon, une description des erreurs s’affichera (en anglais). Si la machine virtuelle quitte avec l’erreur « java.lang.NoClassDefFoundError » alors que vous êtes bien dans le bon répertoire, faites alors « java -cp . Validateur mauvais.xml ». 8. Pour quitter, vous n’avez qu’à fermer la fenêtre de commande. Vérification de la procédure Après avoir tapé la commande « java Validateur mauvais.xml » pour vérifier si le fichier « mauvais.xml » est valable, vous devriez obtenir le message d’erreur suivant indiquant qu’il manque un élément « numero » (le message exact peut varier et il pourrait être en français) : > java Validateur mauvais.xml [Error] mauvais.xml:3:-1: Element "etudiant" does not allow "age" here. [Error] mauvais.xml:3:-1: Element "etudiant" requires additional elements. Pour vous assurer de bien comprendre, reprenez la procédure; créez un autre document appelé « bon.xml » avec le contenu suivant : CC BY-NC-SA Module 1 : Introduction à XML 54 <?xml version="1.0" encoding="ISO-8859-1" standalone="no"?> <!DOCTYPE etudiant SYSTEM "monfichier.dtd"> <etudiant><numero>1</numero><age>12</age></etudiant> Cette fois-ci, vous devriez, en vérifiant que le document est valable, obtenir le message suivant : > java Validateur bon.xml 1.7.3 Retour Est-ce que vous avez pu vérifier si les fichiers « mauvais.xml » et « bon.xml » étaient valables? Si oui, passez aux autres activités, sinon contactez la personne tutrice ou cherchez encore un peu. 1.8 1.8.1 Espaces de noms Objectif Utiliser les espaces de noms 1.8.2 Activité Lisez le texte qui suit, puis répondez au questionnaire d’autoévaluation. Ce texte traite des espaces de noms auxquels il faut faire appel quand on utilise plusieurs « vocabulaires » XML, en même temps. 1.8.3 Les vocabulaires XML Un « vocabulaire XML » est un ensemble de noms de balises et d’attributs ayant une signification donnée. Par exemple, les gens de la comptabilité au sein d’une entreprise pourraient avoir un vocabulaire XML pour décrire certaines transactions, alors que les ingénieurs pourraient avoir leur propre vocabulaire pour décrire certains processus techniques. Les deux équipes pourraient utiliser les mêmes noms d’élément, comme « échéance », mais avec des significations différentes. On dira alors que nous avons deux vocabulaires XML. Voyons un autre exemple. Imaginez que votre institution ait un vocabulaire XML pour les expéditions de marchandise et un vocabulaire XML pour la rédaction des factures. Un document XML combinant à la fois de l’information concernant une expédition et une facture devra utiliser deux vocabulaires. CC BY-NC-SA Espaces de noms 55 Un vocabulaire XML peut être associé à un document DTD; il peut aussi être associé à un espace de noms. 1.8.4 Les identificateurs de ressources uniformes (URI) Un identificateur de ressources uniformes (Uniform Resource Identifier ou URI) est une adresse Internet composée d’un nom de protocole ou « schéma », comme file, http, ftp, news, mailto, gopher, urn, suivi d’un deux-points « : », lui-même suivi d’un chemin, comme « www.mondomain.com/fichier ». Un URI ne pointe pas nécessairement vers un fichier, mais peut très bien être une adresse purement fictive ou une adresse pointant vers une application logicielle sur un serveur. Par exemple, « http://www.mondomain.com/fichier » et « mailto:[email protected] » sont des URI. Les URI ne doivent pas contenir d’accents, et la casse est significative sauf pour ce qui est du nom du protocole (HTTP versus http) et du nom de domaine (xerox.com versus XEROX.COM). Nous reviendrons sur les URI dans le module 5. 1.8.5 Les espaces de noms Un espace de noms est identifié par un URI; il y a correspondance unique entre les espaces de noms et les URI. Deux espaces de noms ayant le même URI sont identiques. Tous les utilisateurs d’un même vocabulaire XML devraient s’entendre sur un même URI. Par exemple, l’URI de l’espace de noms du XHTML est « http://www.w3.org/1999/xhtml ». L’URI agit un peu comme le numéro d’assurance sociale des vocabulaires XML. Il s’agit d’une analogie un peu étrange, voire originale, mais c’est ainsi. Évidemment, la notion d’espace de noms n’a de sens que si l’on considère plusieurs espaces de noms et, par conséquent, plusieurs vocabulaires. 1.8.6 Les DTD et les espaces de noms Avant de préciser le lien entre les DTD et les espaces de noms, il importe de comprendre que les espaces de noms furent proposés après l’adoption des DTD. Il y a donc une certaine incompatibilité entre les DTD et les espaces de noms. C’est d’ailleurs l’une des raisons pour laquelle plusieurs organismes, dont OASIS et le W3C, tentent de proposer des solutions de remplacement pour les DTD. Rappelons que l’on donne une DTD à un document, en ajoutant une déclaration de type de document, immédiatement après la déclaration XML, et dont la forme est : <!DOCTYPE balise SYSTEM "http://www.mondomain.com/madtd.dtd"> CC BY-NC-SA Module 1 : Introduction à XML 56 C’est la même chose avec les espaces de noms. Si vous avez, par exemple, un vocabulaire pour les expéditions et un vocabulaire pour les factures, définis respectivement par des DTD situées à : http://www.mondomain.com/expedition.dtd et http://www.mondomain.com/facture.dtd, vous ne pourriez pas combiner les deux vocabulaires ainsi : <!DOCTYPE balise SYSTEM "http://www.mondomain.com/expedition.dtd" "http://www.mondomain.com/facture.dtd"> Même si l’on pouvait combiner deux DTD de la sorte, cela aurait plusieurs inconvénients : quoi faire si les deux DTD définissent un élément « client », mais de façon différente? La solution est de créer un nouveau vocabulaire XML qui combine les deux et traite chaque vocabulaire comme un « espace de noms ». Dans l’exemple qui suit, nous considérons deux vocabulaires, « facture » et « expedition » qui ont les DTD suivantes : <!ELEMENT facture (montant, nom)> <!ELEMENT nom (#PCDATA)> <!ELEMENT montant (#PCDATA)> <!ELEMENT <!ELEMENT <!ELEMENT <!ELEMENT <!ELEMENT 1.8.7 expedition (nom)> nom (prenom, nomfamille, adresse)> prenom (#PCDATA)> nomfamille (#PCDATA)> adresse (#PCDATA)> Déclaration de l’espace de noms On peut utiliser le symbole « : » dans les noms XML, mais on ne l’utilise généralement qu’une seule fois dans un nom donné. Tout ce qui précède le deux-points est appelé le « préfixe ». On a vu qu’un espace de noms est identifié par un URI. À leur tour, les URI peuvent être associés à un « préfixe ». Tout attribut ou élément qui utilise un préfixe donné fait automatiquement partie de l’espace de noms identifié par l’URI. Seul l’URI identifie un espace de noms : le choix du préfixe est sans importance. Un document peut avoir un seul espace de noms, mais douze préfixes différents. CC BY-NC-SA Espaces de noms 57 On définit un « préfixe » à l’aide d’un attribut ayant comme préfixe « xmlns ». La définition du préfixe est alors valable pour l’ensemble de l’élément, y compris la balise où se situe l’attribut « xmlns: ». Ainsi, dans le document XML suivant : <?xml version="1.0" encoding="ISO-8859-1" ?> <fact:facture xmlns:fact="http://www.domaine.com/facture"> <fact:montant>10$</fact:montant> <fact:nom>Jean</fact:nom> </fact:facture> on reconnaît que l’élément « fact:facture » et tout son contenu utilisent l’espace de noms « http://www.domaine.com/facture » que nous avons décrit par une DTD plus haut. Le préfixe « fact » est ici associé à l’URI « http://www.domaine.com/facture » et tous les éléments et attributs ayant le préfixe « fact » sont considérés faire partie de l’espace de noms « http://www.domaine.com/facture ». Il est « illégal » d’utiliser un préfixe qui n’a pas été défini... Ainsi, le document suivant est bien formé, mais il ne respecte pas les conventions des espaces de noms : <?xml version="1.0" encoding="ISO-8859-1" ?> <fact:facture> <fact:montant>10$</fact:montant> <fact:nom>Jean</fact:nom> </fact:facture> Avez-vous remarqué que ces derniers documents n’ont pas de déclaration de type de document et ne peuvent donc pas être des documents XML valables? La plupart des documents XML utilisant les espaces de noms sont dans ce cas. Si jamais nous avions une déclaration de type de document, il faudrait une DTD qui contiennent les éléments « fact:facture », « fact:montant » et « fact:nom ». En d’autres mots, ce nouveau document XML ne peut utiliser la DTD facture décrite plus haut. Nous ne traiterons pas de cette approche ici, car on combine rarement les DTD de la sorte. Le choix du préfixe « fact: » est arbitraire. On peut changer le nom du préfixe, car seul l’URI identifie de façon unique l’espace de noms. Par exemple, le document XML suivant est équivalent à celui que nous venons de décrire. <?xml version="1.0" encoding="ISO-8859-1" ?> <facture:facture xmlns:facture="http://www.domaine.com/facture"> <facture:montant>10$</facture:montant> <facture:nom>Jean</facture:nom> </facture:facture> On peut aussi redéfinir un préfixe comme dans l’exemple qui suit : <?xml version="1.0" encoding="ISO-8859-1" ?> <facture:facture xmlns:facture="http://www.domaine.com/facture"> CC BY-NC-SA Module 1 : Introduction à XML 58 <facture:montant xmlns:facture="http://www.domaine.com/facture2"> 10$</facture:montant> <facture:nom>Jean</facture:nom> </facture:facture> Dans ce dernier cas, on dira que l’élément « montant » est dans l’espace de noms « http://www.domaine.com/facture2 » et non pas dans l’espace de noms « http://www.domaine.com/facture ». Tout élément et attribut, utilisant le préfixe « facture » dans l’élément « montant », seraient eux aussi dans l’espace de noms « http://www.domaine.com/facture2 ». L’endroit où apparaît la déclaration d’espace de noms est aussi sans conséquence. Par exemple, les deux documents suivants sont équivalents : <?xml version="1.0" encoding="ISO-8859-1" ?> <enveloppe xmlns:facture="http://www.domaine.com/facture"> <facture:facture > <facture:montant>10$</facture:montant> <facture:nom>Jean</facture:nom> </facture:facture> </enveloppe> <?xml version="1.0" encoding="ISO-8859-1" ?> <enveloppe> <facture:facture xmlns:facture="http://www.domaine.com/facture"> <facture:montant>10$</facture:montant> <facture:nom>Jean</facture:nom> </facture:facture> </enveloppe> On dit que deux documents sont équivalents, au sens des espaces de noms, s’ils ne diffèrent que par les préfixes d’espaces de noms et par les endroits où apparaissent les déclarations d’espaces de noms. Évidemment, avec les espaces de noms, on peut combiner plusieurs vocabulaires. Par exemple, si nous voulons décrire une commande en utilisant les vocabulaires « facture » et « expedition », on peut très bien le faire comme le montre l’exemple suivant : <?xml version="1.0" encoding="ISO-8859-1" ?> <facture xmlns:fact="http://www.domaine.com/facture"> <fact:montant>10$</fact:montant> <fact:nom>Jean</fact:nom> <exp:expedition xmlns:exp="http://www.domaine.com/expedition"> <exp:nom> <exp:prenom>Jean</exp:prenom> <exp:nomfamille>Bertrand</exp:nomfamille> CC BY-NC-SA Espaces de noms 59 <exp:adresse>1040, rue Jean</exp:adresse> </exp:nom> </exp:expedition> </facture> En outre, on pourrait même combiner les espaces de noms de façon arbitraire comme le montre le prochain exemple : <?xml version="1.0" encoding="ISO-8859-1" ?> <fact:facture xmlns:fact="http://www.domaine.com/facture"> <fact:montant>10$</fact:montant> <exp:nom xmlns:exp="http://www.domaine.com/expedition"> <exp:prenom>Jean</exp:prenom> <exp:nomfamille>Bertrand</exp:nomfamille> <exp:adresse>1040, rue Jean</exp:adresse> </exp:nom> </fact:facture> 1.8.8 Les déclarations croisées La déclaration d’espace de noms n’est valable qu’au sein de l’élément. Pour déterminer l’espace de nom auquel appartient un élément, il ne suffit donc pas de remonter et de s’arrêter à la première déclaration que l’on trouve. Voyez si vous pouvez voir pourquoi l’espace de nom de l’élément « fact:montant » dans l’exemple suivant est « http://www.domaine.com/facture » et non « http://www.domaine.com/facture2 ». <?xml version="1.0" encoding="ISO-8859-1" ?> <fact:facture xmlns:fact="http://www.domaine.com/facture"> <fact:facture xmlns:fact="http://www.domaine.com/facture2"> </fact:facture> <fact:montant /> </fact:facture> 1.8.9 Le préfixe par défaut On peut utiliser le préfixe par défaut, c’est-à-dire ne pas mettre de préfixe du tout. L’utilisation du préfixe par défaut est optionnelle dans un document XML. Comme tout autre préfixe, le préfixe par défaut peut être réutilisé, redéfini plusieurs fois dans un même document. Voici un exemple de préfixe par défaut : <?xml version="1.0" encoding="ISO-8859-1" ?> <fact:facture xmlns:fact="http://www.domaine.com/facture"> <fact:montant>10$</fact:montant> CC BY-NC-SA Module 1 : Introduction à XML 60 <nom xmlns="http://www.domaine.com/expedition"> <prenom>Jean</prenom> <nomfamille>Bertrand</nomfamille> <adresse>1040, rue Jean</adresse> </nom> </fact:facture> Notons cependant que le préfixe par défaut ne s’utilise que pour les éléments : les attributs sans préfixe ne sont dans aucun espace de noms, et cela sans exception. 1.8.10 Rappel des notions formelles La définition d’un préfixe d’espace de noms inclut l’élément où le préfixe est défini et tout son contenu, et rien d’autre. Le document qui suit fait une utilisation incorrecte des espaces de noms : <?xml version="1.0" encoding="ISO-8859-1" ?> <expedition> <fact:facture xmlns:fact="http://www.domaine.com/facture"> </fact:facture> <fact:nom></fact:nom> </expedition> parce que le préfixe « fact » n’est défini qu’au sein de l’élément « facture ». Bien que cela ne soit pas recommandable, il est possible de redéfinir les préfixes d’espace de noms. C’est simple si l’on se rappelle que la définition d’un préfixe inclut l’élément où la définition est faite. Ainsi, dans l’exemple : <?xml version="1.0" encoding="ISO-8859-1" ?> <expedition> <fact:facture xmlns:fact="http://www.domaine.com/facture"> <fact:nom xmlns:fact="http://www.domaine.com/nom"></fact:nom> </fact:facture> </expedition> l’élément « nom » appartient à l’espace de noms « http://www.domaine.com/nom » et non à l’espace de noms « http://www.domaine.com/facture ». Par convention, on doit toujours accorder à un préfixe d’espace de noms un URI et il serait incorrect d’écrire <fact:facture /> au lieu de <fact:facture xmlns:fact="http://www.domaine.com/facture"> dans l’exemple précédent. CC BY-NC-SA Espaces de noms 1.8.11 61 Les espaces de noms et Relax NG Alors que les DTD ne permettent pas de traiter les espaces de noms, les spécifications Relax NG et XML Schema le permettent. L’utilisation des espaces de noms en Relax NG est particulièrement simple comme le montre cet exemple. namespace fact = "http://www.domaine.com/facture" namespace fact2 = "http://www.domaine.com/facture2" element fact:facture { element fact:nom {text}, element fact:montant {text}, element fact2:id {text} }* } Le document XML suivant sera alors valable. <?xml version="1.0" encoding="ISO-8859-1" ?> <f:facture xmlns:f="http://www.domaine.com/facture"> <f:nom>Daniel</f:nom> <f:montant>10,80$</f:montant> <f2:id xmlns:f2="http://www.domaine.com/facture2">10,80$</f2:id> </f:facture> Par défaut, il n’y a pas d’espace de noms lorsqu’un préfixe n’est pas utilisé, mais on peut définir l’espace de noms par défaut comme ceci : namespace fact = "http://www.domaine.com/facture" default namespace = "http://www.domaine.com/facture2" element fact:facture { element fact:nom {text}, element fact:montant {text}, element id {text} }* } Les deux exemples précédents de Relax NG sont d’ailleurs équivalents. 1.8.12 Le préfixe « xml » Par convention, le préfixe « xml » est réservé à des applications telles que la déclaration de la langue utilisée (« xml:lang ») ou le traitement des espaces CC BY-NC-SA Module 1 : Introduction à XML 62 (« xml:space »). Il n’est pas nécessaire d’y associer explicitement un URI : l’URI « http://www.w3.org/XML/1998/namespace » y est automatiquement associé. 1.8.13 Rappel : des espaces de noms pour les attributs? Les choses se corsent un peu quand on considère les attributs. Alors qu’un élément sans préfixe tombe dans l’espace de noms par défaut si celui-ci a été défini par un attribut « xmlns="..." », ce n’est pas le cas pour les attributs. Un attribut sans préfixe n’est dans aucun espace de noms; pour y être, un attribut doit être muni d’un préfixe. 1.8.14 En résumé, qu’est-ce que les espaces de noms? Une DTD définit un ensemble fixe d’éléments, ensemble qui ne peut être recombiné avec d’autres DTD; c’est un instrument rigide. Par contre, les espaces de noms permettent de recombiner des éléments provenant de différentes applications; ils permettent donc une grande flexibilité. Alors que la DTD définit des éléments et comment les utiliser ensemble, les espaces de noms ne permettent d’établir qu’un lien entre un élément et un URI, mais sans indiquer les contraintes d’utilisation. 1.9 1.9.1 Travail noté 1 Objectifs et pondération Ce travail compte pour 10 % de la note globale du cours. Ce travail contribue à l’évaluation des objectifs suivants : – Utiliser un « vocabulaire » ou une application XML avec vocabulaire XML pour présenter des informations dans le format XML. – Déterminer si un document XML est bien formé ou valable. – Interpréter des fichiers XML utilisant des espaces de noms. Les sept premières questions du travail valent 2,5 points chacune, la huitième vaut 3,5 points; la neuvième question vaut 9 points, la dixième et la onzième valent 5 points chacune. Ce premier travail noté permet d’obtenir 40 points et compte pour 10 % de la note globale. 1.9.2 Consignes Il est recommandé d’avoir terminé les activités d’autoévaluation du premier module avant de faire le travail noté. CC BY-NC-SA Travail noté 1 63 Vous devez remettre à la personne tutrice, par courriel et en fichier attaché, un document (Word 97/2000/XP, ODF, PDF, RTF ou en format texte) clairement identifié à votre nom. Indiquez également votre numéro d’étudiant (8 chiffres), la date du travail, le nom de la personne tutrice, avec les mentions « Travail noté 1 » et « INF 6450 ». Ne transmettez pas vos solutions en plusieurs fichiers. Ne transmettez pas une archive compressée (zip ou autre). Il s’agit d’un travail personnel et vous ne devez pas partager vos réponses. L’objet de votre courriel doit commencer par « [INF6450][TRAVAIL1] »; dans le message, indiquez votre nom, votre numéro d’étudiant (8 chiffres), la date de remise de votre travail et le nom de votre personne tutrice, ainsi que les mentions « Travail noté 1 » et « INF 6450 ». Lorsque le contenu d’un document XML fait partie d’une question, vous devez supposer que le document débute avec le premier caractère et se termine avec le dernier : il n’y a pas d’espace ou de retour de chariot, ni au début ni à la fin des fichiers XML, mais tous les autres espaces ou retours de chariot comptent. Vous devez également supposer que les documents ne sont pas enregistrés avec la norme UTF-8 ou UTF-16, mais plutôt avec un outil banal comme le Bloc-notes qui sélectionne par défaut un jeu de caractères similaire à ISO-8859-1. Bon travail! Question 1 Soit le document XML suivant : <conf xml:space="preserve"> <unite groupe="universite" temps="1086585433" maison="Jean" > Davantage l’an prochain. </unite> <maison/> </conf> 1. Quel est le nom de l’élément-racine ? 2. Combien d’éléments compte ce document ? 3. Combien y a-t-il de balises dans ce document ? 4. Combien y a-t-il de nœuds de texte dans ce document ? 5. Combien d’attributs trouve-t-on dans ce document ? Question 2 Soit le document XML suivant : CC BY-NC-SA Module 1 : Introduction à XML 64 <?xml version="1.0" encoding="ISO-8859-1" standalone="no" ?> <!DOCTYPE _ [ <!ENTITY % administration "Jeanne Perron" > <!ENTITY administration "Jean Boudin"> <!ELEMENT _ (president,comptable,adjoint)*> <!ELEMENT president (#PCDATA)> <!ELEMENT comptable (#PCDATA)> <!ELEMENT adjoint (#PCDATA)> ]> <_> <president>&administration;</president> <comptable>&administration;</comptable> <adjoint>Marion Lepage</adjoint> </_> 1. 2. 3. 4. 5. Quel est le nom de l’élément-racine ? Quel est le contenu de l’élément « president » ? Quel est le contenu de l’élément « comptable » ? Est-ce qu’on pourrait omettre l’élément « adjoint » ? Combien d’éléments « president » peut contenir l’élément-racine ? Question 3 Soit le document XML suivant : <?xml version="1.0"?> <recherche xmlns="http://www.google.com/" xmlns:yahoo="http://www.yahoo.com/"> <mots-clefs xmlns="http://www.yahoo.com/">fraise, orange</mots-clefs> <yahoo:mot xmlns:yahoo2="http://www.yahoo.com/"><nombre>3</nombre> </yahoo:mot> </recherche> 1. À quel espace de noms, identifié par son URI, est-ce que l’élément « mots-clefs » appartient? 2. À quel espace de noms, identifié par son URI, est-ce que l’élément « recherche » appartient? 3. À quel espace de noms, identifié par son URI, est-ce que l’élément « yahoo:mot » appartient? 4. À quel espace de noms, identifié par son URI, est-ce que l’élément « nombre » appartient? 5. Combien y a-t-il d’espaces de noms dans ce document? CC BY-NC-SA Travail noté 1 65 Question 4 En utilisant un navigateur comme Mozilla Firefox, il est possible de déterminer si un document XML est bien formé. Dans cette question, nous vous demandons d’expliquer pourquoi les cinq documents présentés ci-dessous ne sont pas bien formés. Notez qu’on ne vous demande pas seulement d’indiquer où se trouve le problème ou de rapporter le message d’erreur qu’un outil vous donnerait. Expliquez clairement pourquoi les documents XML suivants ne sont pas bien formés. 1. (Indice. Si Mozilla donne l’erreur suivante « XML Parsing Error: illegal parameter entity reference », expliquez ce que cela signifie!) <?xml version="1.0" encoding="ISO-8859-1" standalone="no" ?> <!DOCTYPE compagnie [ <!ENTITY % administration "(president,comptable,adjoint)" > <!ELEMENT compagnie ( %administration;*)> <!ENTITY administration "Jean Boudin"> <!ELEMENT president (#PCDATA)> <!ELEMENT comptable (#PCDATA)> <!ELEMENT adjoint (#PCDATA)> ]> <compagnie> <president>&administration;</president> <comptable>&administration;</comptable> <adjoint>Marion Lepage</adjoint> </compagnie> 2. <?xml version="1.0" ?> <cours> <professeur>Éric Beaudin</professeur> <trimestre>automne</trimestre> <titre>Introduction aux affaires</titre> </cours> 3. <client> <nom>AWS Inc.</nom> <type>SMS5SB11</type> <province>QC</province> <site>http://domaine.com/cgi-bin/script.pl?box=sms5sb11&option=B</site> </client> 4. <?xml version="1.0" encoding="ISO-8859-1" <maison cout$="125000"> <adresse>124, rue Rochond</adresse> </maison> ?> 5. <?xml version="1.0" encoding="ISO-8859-1" ?> CC BY-NC-SA Module 1 : Introduction à XML 66 <personne> <prenom>Jean</prenom> </personne> <personne> <prenom>Jeanne</prenom> </personne> Question 5 Trouvez les 5 erreurs de validation du document suivant : <?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?> <!DOCTYPE université [ <!ELEMENT université (faculté*,description*)*> <!ELEMENT faculté (département*)> <!ELEMENT département EMPTY> <!ATTLIST département nom CDATA #REQUIRED xmlnote (vide|plein) "plein"> <!ATTLIST université téléphone ID #REQUIRED> ]> <université téléphone="514-4321" xml:lang="fr"> <description>La plus grande.</description> <faculté nom="sciences"> <département nom="mathématiques"> </département> <département nom="sociologie" xmlnote="vide"/> </faculté> </université> Question 6 Soit le document DTD suivant : <!ELEMENT cours (module*) > <!ELEMENT module (#PCDATA) > <!ATTLIST module nom CDATA #REQUIRED optionnel (vrai|faux) "faux"> Il est situé à l’adresse « cours.dtd ». Écrivez un document XML pour décrire un cours de 3 modules qui s’intitulent respectivement : « 1. La vie sous-marine », « 2. La vie extraterrestre » et « 3. La vie supraterrestre ». Seul le troisième module est optionnel. Votre document XML doit être valable. CC BY-NC-SA Travail noté 1 67 Question 7 Un document XML « normalisé » est tel que seul l’élément-racine contient des déclarations d’espace de noms. Écrivez un document XML qui soit équivalent à celui qui suit, au sens des espaces de noms : seul l’élément-racine contiendra des déclarations d’espace de noms. <?xml version="1.0" encoding="ISO-8859-1" ?> <lettre xmlns="http://macompagnie.com/expedition"> <recipiendaire> Jeanne Rigault </recipiendaire> <facture xmlns="http://macompagnie.com/comptabilite"> <recipiendaire> Jean Perron </recipiendaire> <expediteur> MaCompagnie.com </expediteur> <montant xml:space="preserve"> 850$ </montant> </facture> <expediteur> Daniel Legault </expediteur> </lettre> Question 8 Même question. <?xml version="1.0" encoding="ISO-8859-1" ?> <a xmlns="http://www.a.b/a" x="a"> <b xmlns="http://www.a.b/b" x="a"> <c xmlns="http://www.a.b/c" x="a"> <d x="a"/> </c> </b> </a> CC BY-NC-SA Module 1 : Introduction à XML 68 Question 9 Produisez un document XML contenant une DTD interne codifiant les spécifications suivantes; dans le cas où les DTD ne permettent pas de codifier une spécification, vous devez l’ignorer. Nous voulons représenter un annuaire (élément nommé « annuaire ») contenant aucun, une seule ou plusieurs personnes (élément nommé « personne »). L’élément « annuaire » peut avoir un attribut nommé « titre ». Les éléments « personne » sont constitués, dans l’ordre, d’un élément « nom » contenant du texte, d’un élément « prenom » contenant du texte, d’un ou plusieurs éléments « courriel » contenant du texte, d’un élément optionnel « commentaire » contenant du texte, et de un ou plusieurs éléments « ami » devant être vide, soit sans aucun contenu. Les éléments « personne » ont deux attributs, un attribut « type » qui peut prendre les valeurs « étudiant », « professeur », « tuteur » et « cadre » avec « étudiant » comme valeur par défaut, et un attribut obligatoire « nas » qui doit servir d’identifiant unique. Les éléments « ami » ont un attribut « nas » qui doit correspondre à la valeur d’attribut « nas » d’un des éléments « personne ». Question 10 Un document DTD a été proposé par John Shipman pour présenter des recettes de cuisine (« recipe » est « recette » en anglais, alors qu’on pourrait traduire librement « subrecipe » par « sous-recette » et « narrative » par « description textuelle », puis « time » par « durée », comme dans « temps de cuisson ») : <!ENTITY % narrative "(ingredients | para)+"> <!ELEMENT recipe (title, author?, (subrecipe+ | section+ | %narrative;))> <!ELEMENT subrecipe (title?, (section+ | %narrative;))> <!ELEMENT title (#PCDATA)> <!ATTLIST title original CDATA #IMPLIED > <!ELEMENT section %narrative;> <!ATTLIST section title CDATA #IMPLIED > <!ELEMENT author (#PCDATA)> <!ATTLIST author source CDATA #IMPLIED > <!ELEMENT para (#PCDATA|time)* > <!ATTLIST para title CDATA #IMPLIED > CC BY-NC-SA Travail noté 1 69 <!ELEMENT time (#PCDATA)> <!ELEMENT ingredients (item+)> <!ELEMENT item (#PCDATA)> Supposons que cette DTD est disponible à l’URL http://infohost.nmt.edu/tcc/help/xml/recipes/recipe.dtd Sur la base de cette DTD, produisez un document XML valable pour présenter une recette de votre choix. Il n’est essentiel qu’il s’agisse d’une vraie recette. Votre document XML doit utiliser tous les éléments et attributs définis par le document DTD. Vous devrez peut-être imaginer une recette un peu compliquée! Votre document doit avoir une déclaration XML et utiliser au moins un accent. Question 11 Quel est l’équivalent en DTD du fichier Relax NG suivant ? carte = element carte { attribute courriel { text }, text } page = element page { text } livre = element livre { (carte | page?) } CC BY-NC-SA Module 2 : XML en tant que syntaxe pour les documents 2.1 2.1.1 Aperçu Objectifs À la fin de ce module, vous devriez avoir approfondi votre compréhension du XML à l’aide d’exemples et mieux voir le rôle qu’il peut jouer dans votre organisation. En effet, il n’est pas suffisant de savoir ce qu’est le XML en tant que métalangage, il faut également comprendre d’où il vient et quel rôle il joue dans son domaine de prédilection : le web. L’objectif spécifique du module est : – Traduire, au sein de son organisation, sa compréhension du XML dans la gestion des informations. Pour atteindre cet objectif, nous vous proposons deux activités notées, soit une discussion de groupe sur le marquage sémantique et la rédaction d’un texte en utilisant le XML. Les lectures et les activités d’autoévaluation de ce module servent à alimenter et à préparer les activités notées. 2.1.2 Démarche Vous devez effectuer les lectures de ce module avant de passer aux modules suivants. Nous vous invitons à procéder à l’étude de ce module dans l’ordre suivant : – Introduction au XHTML, MathML et SVG – XML comme format de documents (SGML, DocBook, ODF) – XML sur le web S’il y a lieu, vérifiez vos connaissances en répondant au questionnaire d’autoévaluation. 71 Module 2 : XML en tant que syntaxe pour les documents 72 Par ailleurs, à partir du moment où vous commencez l’étude du module 2, vous pouvez entreprendre le travail noté 2, soit l’activité de discussion en groupe dans le forum, laquelle peut s’étendre sur tout le cours (participation au forum). Vous pouvez toutefois commencer cette discussion (travail noté 2) plus tard dans le cours. Par contre, le module se termine par le travail noté 3, soit la rédaction d’un texte avec XML, que vous devez réaliser avant de passer au module suivant. Le pense-bête offre un rappel du HTML; dans la version imprimée du cours, il se trouve en annexe. 2.2 2.2.1 Introduction au XHTML Objectif Connaître les notions de base du XHTML. 2.2.2 Activité Lisez le texte qui suit, avant de lire les deux autres suggérés dans ce module. C’est un impératif pour bien progresser dans votre apprentissage du XML. 2.2.3 Qu’est-ce que le XHTML? Le HTML a été inventé par Tim Berners-Lee, alors qu’il travaillait pour le centre de recherche CERN en Suisse. L’intention de Berners-Lee était de proposer un système révolutionnaire de gestion de l’information qu’il appela World Wide Web. Comme pièce maîtresse de son architecture, il avait besoin d’un format de documents qu’il appela HTML (HyperText Markup Language). La première page web, dont l’adresse était http://nxoc01.cern.ch/hypertext/WWW/TheProject.html, vit le jour en 1990. Le HTML est un langage à base de balises, un peu comme une application XML. En fait, il existe une application XML appelée XHTML, qui est à la fois du HTML et du XML. Le document que vous lisez en ce moment en est un exemple. En effet, le document que vous lisez est à la fois du XML bien formé et valable, mais aussi du HTML. Rappelons qu’une « application XML » est un ensemble de balises et d’attributs, c’està-dire un vocabulaire XML, avec des conventions d’usage dont certaines peuvent être représentées par un document DTD. La très grande majorité des documents sur le web sont écrits en HTML et, de plus en plus, en XHTML. Une des raisons principales de l’utilisation du XHTML, c’est que les outils qui traitent le XML peuvent aussi traiter du XHTML puisque ce dernier est aussi du XML. Il est donc possible, dans une organisation, de combiner le contenu CC BY-NC-SA Introduction au XHTML 73 web (HTML) avec le stockage des informations en XML. Comme nous le verrons plus tard dans le cours (module 3, section portant sur le XSLT), on peut même transformer automatiquement le XML en XHTML. Si on dit « HTML » tout court, ce n’est pas nécessairement du XML et il se peut que les outils conçus pour le XML ne puissent être utilisés pour le traiter. Cependant, si on dit « XHTML », alors il s’agit à la fois de HTML et de XML et on peut utiliser les outils destinés au XML pour en traiter le contenu. Voici quelques différences entre le HTML et le XHTML : Les serveurs web distinguent le contenu en fournissant aux navigateurs différents codes MIME (Multipurpose Internet Mail Extensions), alors que le HTML a le code MIME « text/html », on utilise le code MIME « application/xml » ou « application/xhtml+xml » pour le XHTML. Avec le serveur web Apache, on obtient le résultat désiré en ajoutant un fichier « .htaccess », dans le même répertoire que nos fichiers XHTML, contenant la ligne « AddType application/xml .xhtml ». – En HTML traditionnel, on n’a pas à fermer les éléments. Ainsi, le code suivant « <p><i>texte</p> » est acceptable en HTML, mais en XHTML, il faut écrire « <p><i>texte</i></p> ». – Les valeurs d’attributs en HTML n’ont pas à être entre des guillemets ou apostrophes. Ainsi, le code « <table border=0> » est acceptable en HTML, mais en XHTML, il faut écrire « <table border="0"> ». – En HTML, la casse des noms est sans importance. Ainsi, on peut remplacer « <p> » par « <P> », alors que ce n’est pas permis en XHTML. Dans ce cours, nous nous intéresserons surtout au XHTML. Un document XHTML prend la forme suivante : <?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Titre de mon document</title> </head> <body> Voici mon document. </body> </html> On reconnaît d’abord la déclaration XML qui n’a rien de particulier : <?xml version="1.0" encoding="ISO-8859-1" ?>. Comme pour tout document XML, on peut omettre la déclaration XML d’un document XHTML, mais si nous voulons écrire en français avec des lettres accentuées, il est nettement préférable d’avoir la déclaration XML de notre exemple. CC BY-NC-SA Module 2 : XML en tant que syntaxe pour les documents 74 On reconnaît ensuite la déclaration de type de document : <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1strict.dtd">. Observez qu’elle apparaît sur deux lignes, que c’est souvent le cas, mais que c’est un choix purement esthétique. La déclaration de type de document est un peu particulière : il s’agit d’une déclaration utilisant un identifiant public. On doit utiliser un tel identifiant quand on veut signifier qu’il s’agit d’une application XML commune; on évite ainsi que des milliers de personnes aillent chercher des documents DTD à l’adresse « http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd ». On s’attend qu’un logiciel qui dépend d’une application XML commune n’ait pas besoin d’aller chercher les documents DTD, chaque fois que le document XML est lu. Un navigateur comme Firefox ne tient pas compte de la DTD externe, on peut donc omettre la déclaration DOCTYPE sans problème. Le reste du document est simplement un élément-racine « html » contenant deux éléments : un élément head et un élément body. L’élément head doit contenir un élément title, alors que l’élément body peut être vide, mais peut aussi posséder du contenu XML mixte (texte et diverses balises XHTML). L’espace de nom ayant l’URI « http://www.w3.org/1999/xhtml » est utilisé. Si vous copiez le texte qui précède dans un éditeur de texte comme Bloc-notes et que vous enregistrez le fichier sous un nom comme « test.xhtml », vous devriez être capable d’ouvrir le fichier dans votre navigateur et de voir le texte « Voici mon document. » s’afficher à l’écran. Les documents HTML sont tous des documents en format texte et l’extension du fichier est arbitraire : on utilise tout aussi bien « .htm » que « .html », « .xhtml » ou même « .xml ». L’avantage de l’extension « .xhtml » est d’informer le navigateur qu’il s’agit d’un document XHTML, donc un document HTML et un document XML. 2.2.4 La structure du document XHTML : head et body Comme nous le disions, l’élément-racine d’un document XHTML est nommé « html ». Cet élément contient deux et exactement deux sous-éléments : head et body. L’élément head n’est pas affiché directement dans le navigateur et contient des métadonnées, c’est-à-dire une description du contenu. Un élément head doit au minimum contenir un élément title qui donne le titre du document XHTML. Par la suite, l’élément body contient un ensemble de balises et du texte (contenu mixte) qui sera affiché directement dans le navigateur. 2.2.5 Les paragraphes en HTML L’élément body contient des balises et du texte. Les retours de ligne sont traités comme des espaces normaux. Ainsi, les deux documents suivants seront affichés de la même manière par un navigateur. <?xml version="1.0" encoding="ISO-8859-1" ?> CC BY-NC-SA Introduction au XHTML 75 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Titre de mon document</title> </head> <body> Voici mon document. Voici ma vie. Voici mon chat. </body> </html> <?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Titre de mon document</title> </head> <body> Voici mon document. Voici ma vie. Voici mon chat. </body> </html> La question qui se pose alors est : Comment faire des paragraphes? En effet, dans les deux documents plus haut, le texte s’affichera sur une seule ligne (vous pouvez le tester!). La solution consiste à utiliser l’élément « p » pour « paragraphe ». Pour avoir trois paragraphes, on remplace le document HTML précédent par celui qui suit. Observez que chaque balise « p » ouverte doit être fermée. <?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Titre de mon document</title> </head> <body> <p>Voici mon document.</p> <p>Voici ma vie.</p> <p>Voici mon chat.</p> </body> CC BY-NC-SA Module 2 : XML en tant que syntaxe pour les documents 76 </html> 2.2.6 Les listes en HTML Supposons que l’on veuille faire une liste, comme ceci : – Premier point : le chat est noir. – Second point : le chat est blanc. – Dernier point : le chat est marron. On peut obtenir ce résultat avec un élément « ul » pour unordered list (liste sans ordre), contenant des éléments « li ». Observez que chaque balise « li » ouverte doit être fermée. <?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Titre de mon document</title> </head> <body> <ul> <li>Premier point: le chat est noir.</li> <li>Second point: le chat est blanc.</li> <li>Dernier point: le chat est marron.</li> </ul> </body> </html> Supposons maintenant que nous voulions une liste avec un compteur : 1. Le chat est noir. 2. Le chat est blanc. 3. Le chat est marron. Il suffit alors de remplacer l’élément « ul » par l’élément « ol » pour ordered list (liste ordonnée) : <?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Titre de mon document</title> </head> <body> CC BY-NC-SA Introduction au XHTML 77 <ol> <li>Le chat est noir.</li> <li>Le chat est blanc.</li> <li>Le chat est marron.</li> </ol> </body> </html> 2.2.7 Les tableaux en HTML Supposons maintenant que nous voulions produire un tableau. On peut l’obtenir à l’aide d’un élément « table ». Cet élément contiendra plusieurs éléments « tr » (éléments correspondant à une ligne) qui eux-mêmes contiennent des éléments « td » (éléments correspondant à une cellule). Ainsi, pour obtenir un tableau comme celui-ci : Nom Valeur Mustang 50 $ Ferrari 500 $ On utilise le code suivant : <?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Titre de mon document</title> </head> <body> <table> <tr> <td>Nom</td> <td>Valeur</td> </tr> <tr> <td>Mustang</td> <td>50 $</td> </tr> <tr> <td>Ferrari</td> <td>500 $</td> </tr> </table> </body> </html> CC BY-NC-SA Module 2 : XML en tant que syntaxe pour les documents 78 Supposons maintenant que l’on veuille un tableau avec des lignes pour marquer et diviser les cellules. Il suffit alors d’utiliser l’attribut « border ». Sa valeur numérique représente l’épaisseur en pixels de la bordure. Ainsi, pour obtenir ce résultat : Nom Valeur Mustang 50 $ Ferrari 500 $ On utilisera le code XHTML suivant : <?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Titre de mon document</title> </head> <body> <table border="1"> <tr> <td>Nom</td> <td>Valeur</td> </tr> <tr> <td>Mustang</td> <td>50 $</td> </tr> <tr> <td>Ferrari</td> <td>500 $</td> </tr> </table> </body> </html> Tous les tableaux ne sont pas si simples. On peut faire en sorte qu’une même cellule occupe deux colonnes (<td colspan="2">) ou deux rangées (<td rowspan="2">). Aussi, souvent, on utilise l’élément « th » au lieu de l’élément « td » pour désigner la première rangée d’un tableau lorsque celle-ci forme l’entête descriptive du tableau. Il est aussi possible d’utiliser un élément « caption » au sein d’un tableau pour noter le titre du tableau : <?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Titre de mon document</title> CC BY-NC-SA Introduction au XHTML 79 </head> <body> <table border="1"> <caption>Valeur de différents véhicule</caption> <tr> <th>Nom</th> <th>Valeur</th> </tr> <tr> <td>Mustang</td> <td>50 $</td> </tr> <tr> <td>Ferrari</td> <td>500 $</td> </tr> </table> </body> </html> 2.2.8 Les caractères italiques et gras On peut très facilement utiliser des effets de polices de caractères en HTML. Pour obtenir des caractères en italique, par exemple maman, il suffit d’utiliser un élément « i » comme ceci : <i>maman</i>. Pour des caractères en gras, comme maman, il suffit d’utiliser un élément « b » comme ceci : <b>maman</b>. On peut également combiner les deux, comme maman, en écrivant <i><b>maman</b></i> ou bien <b><i>maman</i></b>. Il est cependant préférable d’utiliser « em » (emphase) au lieu de « i » et « strong » (fort) au lieu de « b » : le navigateur choisira alors de rendre le texte dans un élément « em » avec un italique ou une autre technique appropriée, et de rendre le texte dans un élément « strong » en caractères gras ou une autre technique appropriée. On évite ainsi de confondre la présentation (italique ou gras) et la sémantique (emphase ou point fort). Dans le cas où un terme est défini, vous devriez utiliser un élément « dfn » (définition) comme dans cet exemple: « La <dfn>mort</dfn> est la fin de la vie ». La plupart des navigateurs afficheront alors le mot « mort » en caratères italiques. 2.2.9 Les listes de définitions Supposons que nous voulions une liste de définitions comme celle qui suit : Voiture Véhicule sur roues. Chat Bête sauvage qui se nourrit de lait. CC BY-NC-SA Module 2 : XML en tant que syntaxe pour les documents 80 Éléphant Bête sauvage de couleur rose. On obtient ce résultat en XHTML avec un élément « dl » pour definition list contenant une série d’éléments « dt » et « dd » en paire, où l’élément « dt » fournit le terme à définir et l’élément « dd » sa définition. <?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Titre de mon document</title> </head> <body> <dl> <dt>Voiture</dt> <dd>Véhicule sur roues. </dd> <dt>Chat</dt> <dd>Bête sauvage qui se nourrit de lait. </dd> <dt>Éléphant</dt> <dd>Bête sauvage de couleur rose. </dd> </dl> </body> </html> 2.2.10 Les lignes horizontales Pour obtenir une ligne horizontale, on utilise l’élément « hr » qui doit être vide. On doit donc écrire <hr></hr> ou plus simplement <hr />. Voici une ligne horizontale : 2.2.11 Les images Au moment d’écrire ces lignes, on trouve un logo de l’UQÀM à l’URL http://www.uqam.ca/img/logo/logo.jpg. Pour insérer une image dans un document HTML, il suffit d’utiliser une balise « img » avec comme attribut « src » pour source, soit l’URL. Par exemple, le code <img src="http://www.uqam.ca/img/logo/logo.jpg"></img> ou <img src="http://www.uqam.ca/img/logo/logo.jpg" /> CC BY-NC-SA Introduction au XHTML 81 permettra d’insérer le logo de l’UQÀM dans un document. Il est préférable de prévoir que l’image pourrait ne pas être trouvée ou affichée en ajoutant un attribut « alt » qui contient du texte décrivant le contenu de l’image; si l’image n’est pas disponible, le texte contenu dans l’attribut « alt » s’affichera. Le résultat final prend la forme <img src="http://www.uqam.ca/img/logo/logo.jpg" alt="logo de l’UQÀM" /> ce qui donne : 2.2.12 Les hyperliens Pour inclure un hyperlien, comme dans l’exemple de la page de l’UQÀM [lien vers http://www.uqam.ca/], il suffit d’utiliser la syntaxe « <a href="http://www.uqam.ca/">page de l’UQÀM</a> ». On peut également ajouter des marqueurs dans une page web en utilisant la syntaxe « <a name="point1">Premier point de mon document</a> ». Contrairement à la syntaxe « <a href="..."> », l’attribut « name » n’ajoute pas un hyperlien, mais un marqueur généralement invisible dans la page. Par exemple, si la page contient plusieurs sections, on peut ajouter un marqueur au début de chaque section. On pourra alors faire des liens non seulement vers le document, mais aussi vers la section marquée dans le document. Ainsi, l’hyperlien « <a href="pageweb.html#point1">aller vers le premier point du document pageweb.html</a> » mènera l’utilisateur dans le document « pageweb.html », précisément au marqueur du « point 1 », s’il existe, évidemment. 2.2.13 Les abbréviations On utilise parfois des abbréviations dans une page web tel que « etc. » ou « no ». On peut indiquer au navigateur qu’il s’agit d’une abbréviation avec un élément abbr comme ceci : « <abbr>no</abbr> ». Il est parfois utile d’utiliser l’attribut « title » pour décrire l’abbréviation en question comme dans ceci : « <abbr title="numéro">no</abbr> ». De la même façon, on peut noter les acronymes avec un élément « acronym » comme ceci : « <acronym title="Organisation du traité de l’Atlantique Nord">OTAN</acronym> ». 2.2.14 Les adresses Il est fréquent qu’une page web contienne un adresse. Le XHTML nous permet d’indiquer au navigateur qu’il s’agit bien d’une adresse avec l’élément « address », comme ceci : « <address> Daniel Lemire<br /> 100, rue Sherbrooke </address> ». Ici, l’élément « br » sert à noter un retour de charriot. CC BY-NC-SA Module 2 : XML en tant que syntaxe pour les documents 2.2.15 82 Les indices et exposants Dans un texte, il arrive qu’on veuille utiliser des exposants et des indices. Les éléments « sup » et « sub » servent à cette fonction. Par exemple, « premier » peut s’écrit « 1er ». Il n’est malheureusement pas possible de noter automatiquement des notes en bas de page en HTML ou XHTML. 2.2.16 Le code et les exemples Il y a plusieurs éléments permettant de traiter de la programmation informatique ou des mathématiques. Le code informatique peut s’écrire dans un élément « code ». Le texte saisi à l’écran par un utilisateur peut s’écrire dans un élément « kbd ». Les exemples de sortie à l’écran peuvent s’écrire dans un élément « samp » (pour sample) et les variables peuvent s’écrire dans un élément « var ». Voici un exemple : « <p>La valeur de la variable <var>i</var> est obtenue avec ce code:</p><code>int i = 1; i+=1</code><p>On s’attend à ce que l’utilisateur tape <kbd>Yes</kbd> pour oui. Voici un exemple de résultat: <samp>Error!</samp>.</p> ». 2.2.17 Les citations Pour citer quelqu’un, on peut utiliser un élément « q » lorsqu’il s’agit d’un courte citation au sein d’un paragraphe ou élément « blockquote » lorsque la citation doit former un court paragraphe. Plusieurs navigateur mettent automatiquement le contenu de l’élément « q » entre guillemets et le contenu de l’élément « blockquote » en retrait. Voici un exemple : « <p> Jean a dit: <q>mon cher!</q>. Par la suite, je lui ai lu ce texte fatidique.</p><blockquote><p>Oh! Comme la mer a merée! Oh! Comme j’ai jéjé!</p></blockquote> ». 2.2.18 Les révisions Les éléments del et ins permettent de noter un retrait et un ajout, respectivement, comme dans cet exemple: « J’ai <del>marié</del><ins>épousé</ins> ta mère ». Le navigateur se chargera d’afficher les retraits et les ajouts de manière compréhensible. 2.2.19 La langue Le XHTML respecte la spécification XML voulant qu’on indique la langue dans laquelle est écrite un texte avec l’attribute « xml:lang ». Cet attribut est optionnel, mais peut s’avérer pratique. Dans le cas où un texte en langue étrangère est présent dans un paragraphe, on peut utiliser l’élément « span » pour en indiquer la CC BY-NC-SA Introduction au XHTML 83 langue. Voici un exemple : « <p xml:lang="fr-CA">Jean aime les <span xml:lang="enUS">computers</span></p> ». L’élément « span » ne sert qu’à nous permettre de sélectionner un texte au sein d’un autre élément. 2.2.20 Les commentaires Ajouter des commentaires en XHTML est facile. Les commentaires du XML s’appliquent: il suffit de débuter le commentaire par <!-- et de le terminer par -->. Il n’est pas permis d’inclure au sein d’un commentaire deux tirets (--) ni de terminer un commentaire par un tiret. 2.2.21 Séparation du contenu et de la présentation Avec le XHTML, on peut contrôler en partie l’apparence du texte, en utilisant des italiques ou en plaçant des bordures dans nos tableaux. Ce contrôle est cependant limité : on ne peut pas ajuster l’indentation des paragraphes et on ne peut que difficilement ajuster les marges de la page. Nous verrons au module 3, dans la section sur le CSS, qu’il existe une façon élégante d’y arriver. 2.2.22 SVG On utilise de plus en plus la norme Scalar Vector Graphics (SVG) pour dessiner des figures en utilisant le XML. Le fichier suivant représente un rond jaune avec le texte « INF 6450 » au centre et deux lignes par dessus formant un X (notez les éléments « rect », « circle », « text » et « line »). Vous pouvez l’enregistrer sur votre disque et l’ouvrir avec Firefox (version 2.0 ou mieux). Vous pouvez déjà utiliser le format SVG avec plusieurs logiciels de bureautique ou tout simplement insérer un élément « svg » dans un document XHTML. Voici le code d’une image SVG. <?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg width="300" height="300" version="1.1" xmlns="http://www.w3.org/2000/svg"> <rect x="0" y="0" width="300" height="300" stroke="black" fill="red"/> <circle cx="150" cy="150" r="150" stroke="black" fill="yellow"/> <text x="150" y="150" style="text-anchor: middle">INF 6450</text> <line x1="0" y1="0" x2="300" y2="300" CC BY-NC-SA Module 2 : XML en tant que syntaxe pour les documents 84 style="stroke:rgb(99,99,99);"/> <line x1="300" y1="0" x2="0" y2="300" style="stroke:rgb(99,99,99);"/> </svg> Voici le rendu de l’image par votre navigateur. La signification des divers éléments devraient être claire. L’élément « svg » définit la planche à dessin avec sa largeur et sa hauteur. L’élément « rect » trace un rectangle à partir de deux coins opposés (0,0 et 300,300 dans notre exemple) . L’élément « circle » trace un cercle avec un centre et un rayon donnés. L’élément line trace une ligne d’un point à un autre. L’élément text inclut du texte à la position donnée. Il est aussi possible de tracer des ellipses et des formes arbitraires. Il est même possible d’animer du SVG. Il est facile d’apprendre le SVG par l’exemple si vous avez des notions de graphisme. Le site suivant comprend plusieurs exemples instructifs : http://www.w3schools.com/ svg/svg_examples.asp. Vous pouvez aussi utiliser un logiciel de graphisme gratuit comme Inkscape (disponible sur les plate-formes Apple, Windows et Linux, voir http:/ CC BY-NC-SA Introduction au XHTML 85 /www.inkscape.org/). Le site mozilla.org comprend une description complète du SVG (http://developer.mozilla.org/en/docs/SVG) tel qu’il est utilisé dans Firefox. 2.2.23 MathML De la même façon qu’on peut représenter des graphiques en XML, on peut aussi représenter des formules mathématiques (supporté par Firefox 1.0 ou mieux). La syntaxe MathML est complexe et nécessite une bonne maîtrise de la typographique mathématique. Les éléments de bases d’une équation MathML sont « mi » (pour les variables ou fonctions), « mn » (pour les nombres) et « mo » (pour les opérateurs). D’autres éléments viennent s’ajouter comme « msup » (mise en exposant). On peut insérer un élément « math » directement dans un fichier XHTML. Il arrive malheureusement que des polices de caractères manquantes empêchent l’affichage correcte de la formule. Voici la formule « x2 +x+2 » en MathML. <math xmlns="http://www.w3.org/1998/Math/MathML"> <msup><mi>x</mi><mn>2</mn></msup> <mo>+</mo> <mi>x</mi> <mo>+</mo><mn>2</mn></math> x2 + x + 2 Vous pouvez utiliser des outils en ligne tel que itex2MML pour écrire vos équations. 2.2.24 Convertir du HTML mal formé Dans une organisation, il est fréquent d’avoir à composer avec des sites web qui ne respectent pas les normes les plus élémentaires. Réécrire le HTML en XHTML peut sembler une tâche très ardue. Heureusement, il existe des outils gratuits pour corriger du HTML mal formé et générer automatiquement un XHTML valable, comme par exemple HTMLTidy (http://tidy.sourceforge.net/). Le W3C rend aussi disponible un outil de vérification en ligne des sites web pour s’assurer de leur conformité avec les normes (http://validator.w3.org/). Vous pourrez facilement constater que plusieurs pages à l’UQÀM ne sont pas du HTML valable, y compris certaines pages web de ce cours ! 2.2.25 Spécification Relax NG Il existe des définitions de type de document officielle pour le XHML, mais elles sont longues et peu lisible. Sean B. Palmer a écrit une spécification Relax NG pour un sousensemble du XHTML que je reproduis ici avec permission. Je vous invite à vérifier que vous pouvez en comprendre l’essentiel. CC BY-NC-SA Module 2 : XML en tant que syntaxe pour les documents 86 default namespace html = "http://www.w3.org/1999/xhtml" # Common Attributes Core.attrs = attribute attribute attribute attribute id { xsd:ID }?, class { text }?, style { text }?, title { text }? I18n.attrs = attribute xml:lang { text }?, attribute dir { "ltr" | "rtl" }? Main.attrs = Core.attrs, I18n.attrs, attribute onclick { text }? # Content Models BlockMinusForm = (address | blockquote | del | div.elem | dl | h1 | h2 | h3 | hr | ins | ol | p | pre | script | table | ul)* Block = (BlockMinusForm | form)* InlineMinusMedia = (a | abbr | br | cite | code | del | em | input | ins | label | script | span | strong | sub | sup | textarea | text)* Inline = (InlineMinusMedia | img | object)* Flow = (Block | Inline)* # Elements start = html html = element html { I18n.attrs, head, body } head = element head { I18n.attrs, attribute profile { text }?, title, base?, (script* & style* & meta* & link*) } CC BY-NC-SA Introduction au XHTML 87 title = element title { I18n.attrs, text } base = element base { attribute href { text }, empty } meta = element meta { I18n.attrs, attribute content { text }?, attribute name { text }?, empty } link = element link { Main.attrs, attribute href { text }?, attribute rel { text }?, attribute type { text }?, empty } style = element style { I18n.attrs, attribute type { text }, attribute title { text }?, text } script = element script { attribute type { text }, attribute src { text }?, text } body = element body { Main.attrs, attribute onload { text }?, Block } div.elem = element div { CC BY-NC-SA Module 2 : XML en tant que syntaxe pour les documents 88 Main.attrs, Flow } p = element p { Main.attrs, Inline } h1 = element h1 { Main.attrs, Inline } h2 = element h2 { Main.attrs, Inline } h3 = element h3 { Main.attrs, Inline } ul = element ul { Main.attrs, li+ } ol = element ol { Main.attrs, li+ } li = element li { Main.attrs, Flow } dl = element dl { Main.attrs, (dt, dd+)+ } dt = element dt { Main.attrs, CC BY-NC-SA Introduction au XHTML 89 Inline } dd = element dd { Main.attrs, Flow } address = element address { Main.attrs, Inline } hr = element hr { Main.attrs, empty } pre = element pre { Main.attrs, InlineMinusMedia } blockquote = element blockquote { Main.attrs, attribute cite { text }?, Block } ins = element ins { Main.attrs, attribute cite { text }?, Flow } del = element del { Main.attrs, attribute cite { text }?, Flow } a = element a { Main.attrs, attribute href { text }?, attribute rel { text }?, (text & img* & span*) CC BY-NC-SA Module 2 : XML en tant que syntaxe pour les documents 90 } span = element span { Main.attrs, Inline } br = element br { Core.attrs, empty } em = element em { Main.attrs, Inline } strong = element strong { Main.attrs, Inline } code = element code { Main.attrs, Inline } cite = element cite { Main.attrs, Inline } abbr = element abbr { Main.attrs, Inline } sub = element sub { Main.attrs, Inline } sup = element sup { Main.attrs, Inline } CC BY-NC-SA Introduction au XHTML 91 object = element object { Main.attrs, attribute data { text }?, attribute type { text }?, Flow } img = element img { Main.attrs, attribute alt { text }, attribute src { text }, attribute height { text }?, attribute width { text }?, empty } form = element form { Main.attrs, attribute action { text }, attribute method { text }?, BlockMinusForm } label = element label { Main.attrs } input = element input { Main.attrs, attribute type { "text" | "submit" | "hidden" }, attribute name { text }?, attribute size { text }?, attribute value { text }?, empty } textarea = element textarea { Main.attrs, attribute cols { text }, attribute rows { text }, attribute name { text }?, text } table = element table { CC BY-NC-SA Module 2 : XML en tant que syntaxe pour les documents 92 Main.attrs, caption?, tr+ } caption = element caption { Main.attrs, Inline } tr = element tr { Main.attrs, (th | td)+ } th = element th { Main.attrs, Flow } td = element td { Main.attrs, Flow } 2.2.26 HTML 5 Une nouvelle spécification du XHTML et du HTML appelée HTML 5 est en préparation. Elle est compatible avec les syntaxes HTML 4 et XHTML qu’elle vise à remplacer. Un document HTML 5 peut prendre la forme d’un document XML ou d’un document HTML. La déclaration doctype n’est utilisée que dans le cas où le document n’est pas un document XML et a été grandement simplifiée : il suffit d’inclure la ligne <!DOCTYPE html> au début du fichier. Voici un exemple de document HTML 5 : <!doctype html> <html> <head> <meta charset="UTF-8"> <title>Ceci est un exemple</title> </head> <body> <p>Voici un paragraphe.</p> </body> </html> Un document HTML 5 en XML ne nécessite pas de déclaration doctype : CC BY-NC-SA Introduction au XHTML 93 <?xml version="1.0" encoding="UTF-8"?> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Ceci est un exemple</title> </head> <body> <p>Voici un paragraphe.</p> </body> </html> En HTML 5, on n’utilise plus les éléments acronym et plusieurs autres éléments moins utiles (basefont, big, center, s, strike, tt, u, frame, frameset, noframe, applet, isindex, dir). Plusieurs nouveaux éléments ont été ajoutés notamment les éléments section et article. On peut aussi ajouter une figure à un document avec une légende: <figure> <img src="image.png" /> <legend>Exemple d’image</legend> </figure> Les éléments canvas, video et audio sont aussi ajoutés : le HTML devient pleinement multimédia. 2.2.27 Conclusion Le XHTML est un vocabulaire XML. Vous pouvez en consulter la DTD en ligne, à l’adresse http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd; il ne s’agit pas d’une DTD facile à lire, mais elle est néanmoins disponible. Notez qu’il existe de très bons livres de référence pour approfondir le XHTML, mais pour ce cours, il suffit de connaître les quelques balises présentées dans ce document. Un des avantages importants du XHTML sur des pages web traditionnelles (souvent mal formées) est qu’on peut facilement traiter des pages XHTML avec des outils destinés au XML. Par exemple, à partir des pages XHTML et XML de ce cours, j’ai pu créer automatiquement une version PDF du cours. En somme, on peut plus facilement extraire et traiter l’information d’une page XHTML que l’on peut le faire d’une page HTML mal formée. Pour avoir une vue d’ensemble des notions étudiées, consultez le pense-bête sur le HTML. 2.2.28 Livres de référence – Jennifer Robbins, HTML and XHTML Pocket Reference, O’Reilly Media, 2006, 97 pages. CC BY-NC-SA Module 2 : XML en tant que syntaxe pour les documents 94 – Jean Engels, XHTML et css : cours et exercices, Eyrolles, 2006. 2.2.29 Activité d’autoévaluation Afin de vous assurez d’avoir bien compris les notions présentées dans cette leçon, vous devez créer un document XHTML valable, utilisant les différents éléments que nous avons étudiés. Afin que votre navigateur reconnaisse le document comme étant du XHTML, vous devriez utiliser l’extension « xthml ». Si vous déposez le fichier sur un serveur web Apache, il peut être nécessaire de créer aussi un fichier « .htaccess » et de le déposer dans le même répertoire que votre fichier XHTML afin que le serveur puisse reconnaître les fichiers XHTML. Votre fichier « .htaccess » pourrait avoir le contenu suivant : DirectoryIndex index.xhtml index.html index.php index.pl index.cgi AddType application/xml .xhtml 2.3 2.3.1 XML comme format de documents Objectif Comprendre le XML comme format de documents. 2.3.2 Activité Après avoir lu Introduction au XHTML, lisez le texte qui suit, puis répondez au questionnaire d’autoévaluation. Ce texte porte sur plusieurs formats de documents avec balises. D’abord, il y a le HTML que nous avons présenté, qui est un format de documents pour le web; et comme nous l’avons vu, il existe une version XML du HTML, appelée XHTML, qui est à la fois du XML et du HTML. 2.3.3 Le SGML (Standardized General Markup Language) En 1969, Charles Goldfarb, Edward Mosher et Raymond Lorie ont inventé le GML (Generalized Markup Language). Chercheurs chez IBM, ils voulaient faciliter l’échange d’informations entre les outils d’édition, de formatage et de recherche de documents. Le GML possédait déjà un concept de « type de documents » similaire aux documents DTD modernes. Chez IBM, le GML a été utilisé pour la production d’environ 90 % des documents électroniques. CC BY-NC-SA XML comme format de documents 95 En 1978, l’American National Standards Institute (ANSI) a travaillé sur un projet de langage de description de textes, basé sur le GML; le projet s’est terminé en 1985 par la normalisation du SGML. Le centre de recherche CERN a été l’une des premières institutions, outre IBM, à mettre au point des outils pour le SGML. On dit souvent que le SGML est l’ancêtre du XML, dans la mesure où les créateurs du XML connaissaient le SGML et voulaient faire mieux. Le HTML est aussi fortement inspiré du SGML et existait au moment où le XML a été proposé. Il n’est donc pas surprenant que le XML et le HTML se ressemblent et puissent même se retrouver dans un seul format, le XHTML. La principale difficulté avec le SGML est sa complexité. On considère généralement que partout où le SGML était utilisé, il est maintenant préférable d’utiliser le XML. Comme les deux normes sont similaires, on migre souvent du SGML au XML. Quoiqu’il y ait de petits ennuis de conversion, le passage au XML permet de traiter les nouveaux documents avec les nombreux outils XML et de suivre la tendance. Le SGML n’est pas très différent du XHTML. Par exemple, les paragraphes sont spécifiés avec des éléments « para » de la même façon qu’ils sont spécifiés avec des éléments « p » en XHTML. 2.3.4 Le XML comme format de documents Notons que le SGML, le HTML et le XML sont avant tout des formats de documents. On utilise maintenant le XML comme outil de programmation pour stocker et pour échanger des informations entre les logiciels; toutefois, l’objectif des créateurs du XML n’était que de créer un format de documents simple et pratique. Pour les documents, un des avantages des nombreux formats basés sur le XML ou le SGML est qu’ils « décrivent l’information » au lieu de la présenter. Par la suite, il est facile de publier ou transformer un document XML en document PDF, HTML ou autre, selon les besoins. La séparation du contenu et de sa présentation est un facteur de productivité important parce qu’on simplifie la tâche de l’écriture, la ramenant au contenu seulement. La séparation du contenu et de sa présentation existe, en partie, dans le XHTML. Par exemple, quand on ajoute un élément de paragraphe « p », on fait un choix qui s’appuie sur la logique du texte, non sur son apparence. Quant aux choix des polices, de l’espace entre les lignes, de l’espace entre les paragraphes ou des couleurs, ils ne sont généralement pas pris en compte par le XHTML. Mais tout n’est pas parfait; l’utilisation de balises pour appeler de l’italique, soit « i » en XHTML, ne nous assure pas une séparation complète entre la présentation et le contenu. Par exemple, il serait plus « logique » d’indiquer qu’un mot appartient à une langue étrangère et qu’il apparaisse dès lors en italique. Ainsi, au lieu d’écrire « La vie est <i>cool</i>. », on aimerait écrire « La vie est <anglais>cool</anglais>. » ou quelque chose de similaire. Le XHTML constitue donc un compromis entre une séparation complète du contenu et de sa présentation, et l’absence de séparation. CC BY-NC-SA Module 2 : XML en tant que syntaxe pour les documents 96 Comme nous le verrons dans le troisième module, la façon la plus naturelle de dicter la présentation d’un document XHTML est d’utiliser un ou plusieurs fichiers CSS. En plaçant les instructions de formatage dans des fichiers CSS, distincts des fichiers XHTML, on obtient une bonne séparation du contenu et de sa présentation. Cette approche a un grand avantage : si on doit changer l’apparence d’un site web, on peut se contenter d’éditer quelques fichiers CSS au lieu de modifier le contenu lui-même qui se trouve dans plusieurs fichiers XHTML. Par exemple, si on veut que le texte contenu dans les tableaux soit en caractères gras et que le texte des listes apparaisse en rouge, on utilisera les instructions CSS suivantes : td {font-weight:bold;} li {color:red;} Le XML est aussi très utile pour aider à l’autodescription des informations. Par exemple, si dans un texte vous mettez tous les termes techniques en italique, il est possible que vous puissiez plus tard faire une recherche dans votre document pour tous les termes techniques. Toutefois, quelqu’un qui ne connaîtrait pas votre convention pourrait avoir beaucoup de mal à faire la même recherche. Par contre, si vous utilisez un élément particulier pour les termes techniques comme les balises <technique></technique>, il devient beaucoup plus facile à quelqu’un d’autre de s’y retrouver dans votre document. On pourrait objecter que l’ajout de nombreuses balises alourdira le texte qui occupera alors trop de place sur le disque; l’expérience montre que la pérennité des documents doit presque toujours être privilégiée par rapport à l’utilisation de l’espace disque. En outre, le XML est un format ouvert : on peut utiliser une multitude d’outils différents pour manipuler les documents XML; nous ne sommes pas limités à des produits spécifiques à une compagnie ou institution donnée. Le XML a donc l’avantage sur plusieurs autres formats quant à sa pérennité. 2.3.5 Le format DocBook Développé à partir de 1991, le format DocBook est un format de documents souvent utilisé pour la documentation technique. Le format DocBook est une application SGML qui devient une application XML. Il existe de nombreux outils permettant de transformer un document DocBook en document HTML ou PDF. Le format DocBook possède de nombreux avantages pour la rédaction de documents techniques parce qu’il assure une grande séparation entre le contenu et sa présentation : il ne permet que des balises ayant trait à la logique du texte; par exemple, il n’est pas possible de spécifier une police de caractères en DocBook. L’auteur peut alors concentrer son attention sur le contenu du document, sans perdre de temps avec le formatage, qui est une étape ultérieure. La séparation du contenu et de sa présentation permet aussi que plusieurs personnes puissent travailler sur un même projet de documentation tout en assurant une présentation uniforme, parce que DocBook ne comprend pas d’instructions de formatage. CC BY-NC-SA XML comme format de documents 97 Malheureusement, comme les autres formats hérités du SGML, plusieurs documents en format DocBook sont du SGML et non du XML; on ne peut donc pas utiliser les outils XML pour tous les documents DocBook. Par contre, la situation est en train de changer; il devient plus facile de déterminer si un document est bel et bien un document XML : la déclaration XML placée au début d’un document DocBook nous l’indique. Le format DocBook est fréquemment utilisé dans les projets de logiciels libres et « open source », ainsi que par certaines grandes sociétés, comme IBM. En général, les avantages du format DocBook sont plus visibles dans un contexte de travail d’équipe. La création d’un document DocBook simple n’est pas très difficile. Tout d’abord, bien qu’elle puisse varier selon les versions, la déclaration de type de document d’un document DocBook ressemble à ceci : <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4CR2//EN" "http://www.oasis-open.org/docbook/xml/4.4CR2/docbookx.dtd"> Dans ce cas, on voit que le document DTD se trouve à l’adresse : http://www.oasis-open.org/docbook/xml/4.4CR2/docbookx.dtd Il faut cependant noter qu’il s’agit d’un document DTD qui dépend d’autres documents DTD et que la lecture d’un tel type de document DTD n’est pas très facile. L’élément-racine d’un document DocBook peut varier, mais les deux principales structures sont « book » (livre) et « article »; notez que l’on peut commencer par l’une ou l’autre : <?xml version="1.0" encoding=’ISO-8859-1’ standalone="no"?> <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4CR2//EN" "http://www.oasis-open.org/docbook/xml/4.4CR2/docbookx.dtd"> <book> (...) </book> <?xml version="1.0" encoding=’ISO-8859-1’ standalone="no"?> <!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.4CR2//EN" "http://www.oasis-open.org/docbook/xml/4.4CR2/docbookx.dtd"> <article> (...) </article> Ensuite, on doit ajouter un élément « bookinfo » ou « articleinfo », selon que le document est un livre ou un article. Le plus souvent, les éléments en question contiennent un élément « title » contenant le titre, ainsi qu’un élément « author » qui contiendra les éléments « firstname » (prénom) et « surname » (nom de famille). On peut aussi ajouter un élément « copyright » (droit d’auteur) qui contiendra un élément « year » (année) CC BY-NC-SA Module 2 : XML en tant que syntaxe pour les documents 98 et un élément « holder » (titulaire). Voici quelques structures courantes de documents DocBook : <?xml version="1.0" encoding=’ISO-8859-1’ standalone="no"?> <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4CR2//EN" "http://www.oasis-open.org/docbook/xml/4.4CR2/docbookx.dtd"> <book> <bookinfo> <title>Notre documentation</title> <author> <firstname>Alexis</firstname> <surname>Letrotteur</surname> </author> <copyright><year>2004</year><holder>Bell Canada</holder></copyright> </bookinfo> (...) </book> <?xml version="1.0" encoding=’ISO-8859-1’ standalone="no"?> <!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.4CR2//EN" "http://www.oasis-open.org/docbook/xml/4.4CR2/docbookx.dtd"> <article> <articleinfo> <title>Le sens de la vie</title> <author> <firstname>Gilles</firstname> <surname>Proulx</surname> </author> <copyright><year>2004</year> <holder>Gouvernement du Canada</holder> </copyright> </articleinfo> (...) </article> L’élément de base d’un document DocBook est l’élément « para » qui note la présence d’un paragraphe. Dans le cas d’un livre, on va le plus souvent faire suivre l’élément « bookinfo » d’éléments « chapter » (chapitre), qui eux-mêmes peuvent contenir des éléments « section », comme dans l’exemple qui suit : <?xml version="1.0" encoding=’ISO-8859-1’ standalone="no"?> <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4CR2//EN" "http://www.oasis-open.org/docbook/xml/4.4CR2/docbookx.dtd"> <book> <bookinfo> <title>Notre documentation</title> CC BY-NC-SA XML comme format de documents 99 <author> <firstname>Alexis</firstname> <surname>Letrotteur</surname> </author> <copyright><year>2004</year><holder>Bell Canada</holder></copyright> </bookinfo> <chapter> <title>Premier chapitre</title> <section> <title>Première section du premier chapitre</title> <para>Mettre ici le premier paragraphe de la première section.</para> </section> </chapter> </book> Observez que tous les éléments « chapter », ainsi que tous les éléments « section » débutent par un élément « title » : c’est souvent suffisant. Il n’est pas permis de commencer un élément « section » ou « chapter » directement par un élément « para ». Par contre, on pourrait omettre d’avoir des sections dans nos chapitres, comme dans l’exemple qui suit : <?xml version="1.0" encoding=’ISO-8859-1’ standalone="no"?> <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4CR2//EN" "http://www.oasis-open.org/docbook/xml/4.4CR2/docbookx.dtd"> <book> <bookinfo> <title>Notre documentation</title> <author> <firstname>Alexis</firstname> <surname>Letrotteur</surname> </author> <copyright><year>2004</year><holder>Bell Canada</holder></copyright> </bookinfo> <chapter> <title>Premier chapitre</title> <para>Mettre ici le premier paragraphe du premier chapitre.</para> </chapter> </book> Dans le cas d’un simple article, nous n’utiliserons pas les éléments « chapitre » et il suffit, le plus souvent, d’utiliser des éléments « section », comme dans l’exemple qui suit : <?xml version="1.0" encoding=’ISO-8859-1’ standalone="no"?> <!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.4CR2//EN" "http://www.oasis-open.org/docbook/xml/4.4CR2/docbookx.dtd"> CC BY-NC-SA Module 2 : XML en tant que syntaxe pour les documents 100 <article> <articleinfo> <title>Notre documentation</title> <author> <firstname>Alexis</firstname> <surname>Letrotteur</surname> </author> <copyright><year>2004</year><holder>Bell Canada</holder></copyright> </articleinfo> <section> <title>Première section de l’article</title> <para>Mettre ici le premier paragraphe de la première section.</para> </section> <section> <title>Deuxième section de l’article</title> <para>Mettre ici le premier paragraphe de la seconde section.</para> </section> </article> On pourrait aussi utiliser les éléments « sect1 », « sect2 », « setc3 » et ainsi de suite, pour obtenir les notions de section, sous-section, sous-sous-section et ainsi de suite. Comme le format DocBook est destiné à la documentation technique, il existe plusieurs balises pour décrire le code informatique. L’élément le plus simple est l’élément « programlisting ». Ainsi, pour ajouter un petit programme Java dans un document DocBook, on utilisera l’élément suivant : <programlisting> public static void main(String[] arg) { System.out.println("Allo!"); } </programlisting> On peut également placer un élément « programlisting » dans les éléments « section », « chapter », « para », etc. Tout comme en HTML, on peut créer des listes avec les éléments « itemizedlist » (liste non ordonnée, équivalent de « ul » en HTML) et « orderedlist » (liste ordonnée, équivalent de « ol » en HTML). Une liste est constituée d’éléments « listitem » qui ne peuvent contenir directement du texte : on met généralement des éléments « para » dans les éléments « listitem ». Par contre, les éléments « listitem » ne peuvent apparaître hors des éléments « itemizedlist » et « orderedlist ». En outre, on place les listes dans les éléments « chapter », « section », etc. Voici quelques exemples : <itemizedlist> <listitem> <para>un triangle</para> CC BY-NC-SA XML sur le web 101 </listitem> <listitem> <para>un losange</para> </listitem> </itemizedlist> <orderedlist> <listitem> <para>Premier élément (numéro 1)</para> </listitem> <listitem> <para>Second élément (numéro 2)</para> </listitem> </orderedlist> Le format DocBook est supporté par certains traitement de textes comme OpenOffice qui est disponible gratuitement. 2.3.6 L’ODF (Open Document Format) Historiquement, les formats de bureautiques ont été propriétaires, que ce soit le format WordPerfect ou le format Microsoft Word. Pour une institution, cela pose le problème de la pérennité des documents : qu’est-ce qui se produit si la compagnie qui propose un format décide de ne plus supporter un ancien format, parce qu’elle fait faillite ou change sa stratégie commerciale ? Qu’est-ce qui se produit si elle décide d’augmenter le coût de ses produits ? L’Open Document Format (ODF) est une norme XML adoptée en mai 2005 par OASIS et est devenu une norme ISO (ISO 26300.2006) le 30 novembre 2006. Le format ODF est un format XML que tout le monde peut utiliser librement. Nous allons voir différentes techniques dans ce cours qui permettent de manipuler des documents XML et elles s’appliquent au format ODF. Le format ODF n’est pas très différent des nouveaux formats Open XML utilisés par Microsoft Office, mais au lieu de n’être soutenu que par une seule compagnie, ODF provient d’une entente entre plusieurs grandes sociétés : Adobe Systems, IBM, Intel, Novell et Sun Microsystems. Dans les deux cas (ODF et Open XML), les fichiers XML sont mis dans une archive compressée et nous avons accès à la sémantique des balises XML. Le logiciel OpenOffice utilise le format ODF et a les avantages d’être gratuit et disponible pour une variété de systèmes (Apple, Linux, Microsoft, etc.). Il est aussi possible de créer des documents ODF à partir de Microsoft Office 2007 à l’aide d’une composante logicielle supplémentaire (Open XML Translator). Dans le cadre de ce cours, vous pouvez remettre vos travaux dans le format ODF. CC BY-NC-SA Module 2 : XML en tant que syntaxe pour les documents 2.4 2.4.1 102 XML sur le web Objectif Comprendre le XHTML pour publier des documents sur le web. 2.4.2 Activité Lisez le texte qui suit, puis répondez au questionnaire d’autoévaluation. 2.4.3 Le XHTML et le web Rappelons d’abord que le XHTML est un format hybride : il tient à la fois du HTML et du XML. Nous allons étudier ce format, examiner son importance et son rôle pour la publication de documents sur le web. Produire du XHTML est une des principales façons de publier du XML sur le web. Le XHTML en question peut être produit à la main avec un éditeur de texte : dans ce cas, il faudra s’assurer qu’il est bien formé. Avec un navigateur comme Mozilla Firefox, on peut s’en assurer en l’enregistrant avec un nom portant l’extension « .xhtml », comme « mon_fichier.xhtml », et en l’ouvrant avec le navigateur. On peut aussi produire du XHTML en « transformant un fichier XML », ce que nous verrons dans le prochain module. Finalement, on utilise aussi beaucoup de XML sur le web sans passer par le XHTML, soit en utilisant la technologie CSS, que nous étudierons dans le prochain module, soit en destinant le XML aux machines. L’avantage du XHTML est de pouvoir bénéficier de toute la puissance du XML, de toutes les astuces et outils que l’on connaît en XML, tout en conservant le format HTML qui s’est montré utile au fil des ans. On peut se demander alors pourquoi le HTML ne suffit pas. Après tout, le web s’est fait avec le HTML et ça fonctionne bien. L’embarras avec le HTML, c’est qu’il permet de faire des choses que les machines ne savent pas bien traiter. Par exemple, prenons le document HTML typique suivant : <html> <body> <p>Voici mon <i>document. <p><b>Il est beau, non? </body> </html> Cet exemple n’est pas un document XML valable! On voit bien qu’il s’agit d’un document avec deux paragraphes (balises « p »), dont une partie est en caractères gras CC BY-NC-SA XML sur le web 103 (balise « b ») et une autre en italique (« i »). On peut toutefois se demander, à juste titre, si la phrase « Il est beau, non? » est en italique ou pas. Il y a deux façons de rendre ce document HTML en XHTML : <?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>le titre est obligatoire en XHTML</title> </head> <body> <p>Voici mon <i>document</i>.</p> <p><b>Il est beau, non?</b></p> </body> </html> ou encore <?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" > <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>le titre est obligatoire en XHTML</title> </head> <body> <p>Voici mon <i>document.</i></p> <p><i><b>Il est beau, non?</b></i></p> </body> </html> On constate aisément que le XHTML ne tolère pas les ambiguïtés qui rendent le HTML difficile à traiter par les machines. C’est un avantage de taille, car il existe plusieurs outils gratuits pour traiter le XML et qui peuvent être utilisés avec le XHTML, alors que les outils pour traiter le HTML sont plus difficiles à développer et, en général, plus capricieux parce qu’ils doivent traiter des ambiguïtés. Le XHTML permet aussi de faire des choses qui n’existent pas en HTML. Par exemple, on peut utiliser des appels d’entités. Supposons que le nom d’un auteur ou le titre de son livre apparaissent à plusieurs reprises dans un document. La redondance de l’information peut être une source d’erreur : si on change le titre du livre à un endroit, il faut le changer partout. Avec le XHTML, on peut déclarer les entités suivantes : <!ENTITY titre "Le père de tous les documents"> CC BY-NC-SA Module 2 : XML en tant que syntaxe pour les documents <!ENTITY monnom 104 "Daniel Lemire"> Ensuite, on pourra avoir le document suivant : <?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" [ <!ENTITY titre "Le père de tous les documents"> <!ENTITY monnom "Daniel Lemire"> ]> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>&titre;</title> </head> <body> <p>Le titre de ce livre est: &titre;. L’auteur est &monnom;.</p> <p>Copyright 2010, par &monnom;.</p> </body> </html> Le résultat à l’écran, dans un navigateur qui comprend le XHTML, sera : Le titre de ce livre est: Le père de tous les documents. L’auteur est Daniel Lemire. Copyright 2010, par Daniel Lemire. 2.5 2.5.1 Travail noté 2 Objectifs et pondération Ce travail compte pour 5 % de la note globale du cours. Il contribue à l’évaluation de l’objectif suivant : – Traduire, au sein de son organisation, sa compréhension du XML dans la gestion des informations. Ce travail consiste à discuter d’un sujet avec les autres étudiants du cours et à réunir vos textes dans un compte rendu. CC BY-NC-SA Travail noté 2 2.5.2 105 Consignes Avant d’entreprendre ce travail noté, il est recommandé d’avoir terminé les activités d’autoévaluation du module 1 et d’avoir commencé l’étude du module 2. Vous avez jusqu’à la fin du cours pour réaliser ce travail. Vous devez contribuer au forum de façon originale et substantielle. 1. Choisissez un sujet qui vous intéresse; quelques pistes de discussion vous sont suggérées plus loin. 2. Effectuez des recherches sur le web, prenez des notes. 3. Inscrivez-vous sur Facebook si ce n’est pas déjà fait (http://fr-fr.facebook.com/). Facebook est un site de réseautage social. L’inscription sur Facebook est gratuite et elle ne prend que quelques minutes. Par contre, n’allez pas demander de l’aide aux services de l’Université pour vous brancher à Facebook : demandez plutôt à votre tuteur de vous aider. 4. Accédez au groupe du cours « INF 6450 » à l’adresse http://www.facebook.com/ group.php?gid=57220667716. Vous trouverez au sein de la page du groupe un forum de discussion. 5. Rédigez votre intervention de façon claire et précise afin d’inciter les lecteurs à vous lire et à commenter; prenez soin de préciser vos références. 6. Lisez les messages de vos collègues et échangez. Répondez à vos interlocuteurs et réagissez à leur contribution. 7. Quand vous jugerez votre participation suffisante, que aurez terminé votre discussion, réunissez les textes que vous avez produits. 8. Rédigez un compte rendu de votre participation (Word 97/2000/XP, ODF, PDF, RTF ou au format texte) qui doit contenir une copie des textes que vous avez produits dans le forum ou blogue. 9. Transmettez à votre personne tutrice, par courriel, votre compte rendu clairement identifié à votre nom, en le joignant au message en fichier attaché. L’objet de votre courriel doit commencer par « [INF6450][TRAVAIL2] »; dans le message, indiquez votre nom, votre numéro d’étudiant (8 chiffres), la date de remise de votre travail et le nom de votre personne tutrice, ainsi que les mentions « Travail noté 2 » et « INF 6450 ». Ne transmettez pas plusieurs fichiers. Ne transmettez pas une archive compressée (zip ou autre). En cas de panne Il peut arriver que vous ne puissiez vous brancher au groupe Facebook du cours. En effet, Facebook peut tomber en panne, vous refuser l’accès ou même cessez d’exister. Comme alternative, vous pouvez aussi commenter sur le blogue du cours. CC BY-NC-SA Module 2 : XML en tant que syntaxe pour les documents 106 Pistes de discussion Bien que votre contribution doive être originale et que nous vous invitions fortement à faire une recherche préalable sur le web pour nourrir vos discussions, vous pouvez utiliser les pistes suivantes : – Le blogue du cours à http://www.daniel-lemire.com/blogue/category/xml/ est régulièrement mis à jour. – Le Security Assertion Markup Language (SAML) doit permettre d’identifier et d’autoriser les utilisateurs sur plusieurs sites en ne leur demandant qu’une seule fois leur mot de passe. – La langage RuleML permet d’écrire des règles formelles en XML et de les échanger entre divers sites. – Les versions récentes de Microsoft Office utilisent de façon agressive le XML comme format de documents. On trouve sur le web plusieurs articles traitant de cette question, dont un article sur les conséquences de l’utilisation de XML par Microsoft pour les logiciels antivirus et un article sur les conséquences légales des choix faits par Microsoft. – Le clone gratuit de Microsoft Office, OpenOffice (voir openoffice.org) utilise lui aussi un format XML pour ses documents. De plus, il est possible de trouver sur le web plusieurs articles portant sur l’utilisation du XML faite par OpenOffice. – Le jeu vidéo très populaire World of Warcraft offre un outil à base de XML permettant de modifier l’interface du jeu. – Le W3C a récemment publié les spécifications de VoiceXML 2.0 avec une annonce en français; de plus, le magazine Silicon a publié un article sur le sujet. En principe, VoiceXML devrait permettre de créer des systèmes contrôlés par la parole : par exemple, un outil de gestion de l’inventaire par téléphone qui permettrait de demander un rapport des stocks à partir d’un numéro de série. – On a appris récemment que le gouvernement américain rend disponibles les données météorologiques au format XML. 2.5.3 Critères de correction et de notation L’évaluation porte sur l’originalité de votre propos, sur l’ampleur de la recherche sousjacente à votre discussion et sur la qualité des textes que vous proposez. – Originalité : Est-ce que votre contribution diffère de ce qu’on trouve déjà dans le forum ou sur le blogue? (30 %) – Contenu et recherche : Est-ce que votre contribution démontre une recherche substantielle sur le sujet? Est-ce que vous avez donné 3 ou 4 références (comme des URL) pertinentes et originales? (60 %) – Présentation : Est-ce que votre contribution est faite de textes lisibles, clairs, cohérents, écrits dans un français correct? (10 %) CC BY-NC-SA Travail noté 3 2.6 2.6.1 107 Travail noté 3 Objectifs, pondération et critères de correction Ce travail compte pour 10 % de la note globale du cours. Il contribue à l’évaluation des objectifs suivants : – Utiliser un « vocabulaire » ou une application XML pour présenter des informations en format XML. – Déterminer si un document XML est bien formé ou valable. – Traduire, au sein de son organisation, sa compréhension du XML dans la gestion des informations. Votre travail sera noté en utilisant les critères suivants : – – – – – votre capacité à créer un document DocBook valable et bien formé (30 %), votre utilisation des balises requises (15 %), l’utilisation d’une instruction spéciale (XSLT) (5 %) production d’un document XHTML valable selon les consignes (20 %). le contenu de votre texte (clarté, cohérence, qualité du français) (30 %). Il est recommandé d’avoir terminé les activités d’autoévaluation des modules 1 et 2 avant d’entreprendre ce travail noté. Pour réaliser ce travail, vous devez utiliser la technologie XSLT (sans nécessairement la maîtriser); vous pouvez également commencer les autres modules avant de le terminer si vous jugez que votre connaissance du XML n’est pas encore suffisante. Vous avez jusqu’à la fin du cours pour réaliser ce travail. 2.6.2 Description du travail En respectant les consignes spécifiques qui suivent, vous rédigerez un texte qui répondra à la question suivante : « Pourquoi est-ce que je devrais utiliser XML dans mon projet? ». Vous fournirez au minimum 6 bonnes raisons justifiant l’utilisation de XML au sein d’un projet stratégique. Votre texte, que vous nommerez « INF6450travail3_votrenom.xml », sera un document DocBook d’au moins 2000 mots (environ 130 lignes), comptant au moins deux « chapitres » (éléments « chapter »), chacun comptant au minimum 2 sections. En outre, vous devez produire un document XHTML valable qui résume brièvement vos 6 arguments. Le document XHTML doit être nommé « INF6450travail3_votrenom.xhtml » et doit être du XHTML valable. Votre document doit utiliser au moins un élément « acronym », un élément « samp », et un élément « blockquote ». Transmettez les deux documents à votre tuteur par courriel en tant que fichiers attachés. L’objet de votre courriel doit commencer par « [INF6450][TRAVAIL3] »; dans le message, indiquez votre nom, votre numéro d’étudiant (8 chiffres), la date de CC BY-NC-SA Module 2 : XML en tant que syntaxe pour les documents 108 remise de votre travail et le nom de votre personne tutrice, ainsi que les mentions « Travail noté 3 » et « INF 6450 ». Ne transmettez pas une archive compressée (zip ou autre). Ce travail de rédaction est personnel et votre texte doit être original. Rappelons que lorsqu’on vous donne le contenu d’un document XML, vous devez supposer que le document débute avec le premier caractère et se termine avec le dernier. 2.6.3 Consignes 1. Un document DocBook débute normalement par la définition de type de document (DTD) : <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4CR2//EN" "http://www.oasis-open.org/docbook/xml/4.4CR2/docbookx.dtd"> Cependant, il suffit de visiter l’URL http://www.oasis-open.org/docbook/xml/4.4CR2/docbookx.dtd pour se rendre compte que le document DTD de DocBook n’est pas trivial : il comporte un grand nombre d’éléments dont nous n’avons pas besoin. En particulier, DocBook a plusieurs balises pour la description du code source informatique. Utilisez donc un document DTD nommé « simpledocbook.dtd », une version grandement simplifiée de DocBook et ayant le contenu suivant : <!ELEMENT book (bookinfo,chapter*)> <!ELEMENT chapter (title,section*)> <!ELEMENT title (#PCDATA)> <!ELEMENT bookinfo (title,author,copyright)> <!ELEMENT author (firstname,surname)> <!ELEMENT copyright (year,holder)> <!ENTITY % divers "para|programlisting|itemizedlist|orderedlist"> <!ELEMENT section (title,(%divers;)+)> <!ELEMENT para (#PCDATA)> <!ELEMENT programlisting (#PCDATA)> <!ELEMENT holder (#PCDATA)> <!ELEMENT surname (#PCDATA)> <!ELEMENT firstname (#PCDATA)> <!ELEMENT year (#PCDATA)> <!ELEMENT itemizedlist (listitem+)> <!ELEMENT orderedlist (listitem+)> <!ELEMENT listitem (%divers;)+> 2. Placez ce document DTD dans le même répertoire que votre document XML. CC BY-NC-SA Travail noté 3 109 3. Rédigez le texte de votre document DocBook en utilisant au moins une fois tous les éléments de cette DTD, y compris « programlisting » et « listitem ». Votre déclaration de type de document doit être : <!DOCTYPE book SYSTEM "simpledocbook.dtd"> Même si, à strictement parler, un élément « programlisting » doit contenir le texte d’un programme, aux fins de ce travail noté, vous pouvez utiliser du XML dans cet élément. Note. Votre document ne sera pas un véritable document DocBook, car il n’aura pas une déclaration normale de type de document. Cependant, il vous serait possible de remplacer la déclaration de type de document par une déclaration normale et vous auriez alors un véritable document DocBook. 4. Un document DocBook ne contient pas les informations de formatage et, en général, n’est pas très lisible. Pour permettre une lecture plus aisée du document, utilisez le document XSLT qui se trouve à l’annexe 1, plus loin. Copiez le document en question et enregistrez-le sous le nom « docbook.xml », dans le même répertoire que votre document XML. Le XSLT permet de transformer le document DocBook en HTML. On ne vous demande pas de comprendre le XSLT, car le sujet sera étudié dans le prochain module. 5. Pour l’instant, ajoutez simplement l’instruction suivante dans votre document XML, immédiatement après la déclaration XML <?xml-stylesheet href="docbook.xml" type="application/xml"?> 6. Ensuite, une fois votre document XML terminé, ouvrez-le dans Firefox; vous devriez voir votre document nouvellement formaté. Assurez-vous que le document « docbook.xml » de l’annexe 1 est bien dans le même répertoire que votre document DocBook. Constatez alors comment votre document XML est présenté de façon totalement différente de son allure originale. C’est un résultat de la division entre le contenu et sa présentation : le fichier XSLT s’occupe ici de la présentation, alors que votre texte XML ne comporte que le contenu. Par exemple, la version formatée dispose d’une table des matières qui se génère automatiquement, alors que le document XML n’a aucune notion de table des matières. 7. La production du document XHTML se fait de manière similaire, mais sans l’utilisation d’un document XSLT. Pour tester la validité de votre document, vous pouvez utiliser l’outil de validation du W3C disponible à l’adresse « http://validator.w3.org/ » (voir « Validate by File Upload »). 8. Transmettez à votre personne tutrice, par courriel, vos documents XML clairement identifiés à votre nom, en les joignant au message. Vous devez transmettre deux documents XML : un document DocBook et son résumé en XHTML. Dans la zone « Objet », inscrivez le sigle du cours et le numéro du travail (INF 6450 Travail noté 3) dans le message, indiquez votre nom, votre numéro d’étudiant (8 chiffres), la date de remise de votre travail et le nom de votre personne tutrice, ainsi que les mentions « INF 6450 » et « Travail noté 3 ». CC BY-NC-SA Module 2 : XML en tant que syntaxe pour les documents 110 Annexe 1. Document XSLT Le document XSLT suivant servira à convertir votre document DocBook en HTML. C’est là un avantage du format DocBook : on peut facilement le convertir en d’autres formats. Nous étudierons le XSLT dans le troisième module. <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html" indent="yes" encoding="ISO-8859-1" /> <xsl:template match="book"> <html> <head><xsl:apply-templates select="bookinfo"/></head> <body><h1><xsl:value-of select="bookinfo/title" /></h1> <p style="text-indent:1em;"> <xsl:value-of select="bookinfo/author/firstname" /> <xsl:text> </xsl:text> <xsl:value-of select="bookinfo/author/surname" /> © <xsl:value-of select="bookinfo/copyright/year" /> </p><h2>Table des matières</h2> <ul><xsl:apply-templates select="chapter" mode="tdm"/></ul> <xsl:apply-templates select="chapter"/> </body></html> </xsl:template> <xsl:template match="bookinfo"> <title><xsl:value-of select="title" /> par <xsl:value-of select="author/firstname" /><xsl:text> </xsl:text><xsl:value-of select="author/surname" /> </title> </xsl:template> <xsl:template match="chapter" mode="tdm"> <li><a href="#{generate-id(.)}"> <xsl:number format="digit" lang="fr" count="chapter"/>. <xsl:value-of select="title" /></a></li> <ul><xsl:apply-templates select="section" mode="tdm"/></ul> </xsl:template> <xsl:template match="section" mode="tdm"> <li><a href="#{generate-id(.)}"> <xsl:number format="digit" lang="fr" count="chapter"/>.<xsl:number format="digit" lang="fr" count="section"/> <xsl:text> </xsl:text> <xsl:value-of select="title" /></a></li> </xsl:template> <xsl:template match="chapter"> <h2><a name="{generate-id(.)}" >Chapitre CC BY-NC-SA Travail noté 3 111 <xsl:number format="digit" lang="fr" count="chapter"/>.<xsl:text> </xsl:text> <xsl:value-of select="title" /></a></h2> <div style="margin-left:1em"> <xsl:apply-templates select="section"/> </div> </xsl:template> <xsl:template match="section"> <h3><a name="{generate-id(.)}"> <xsl:number format="digit" lang="fr" count="chapter"/>.<xsl:number format="digit" lang="fr" count="section"/> <xsl:text> </xsl:text> <xsl:value-of select="title" /></a></h3> <div style="margin-left:1em"> <xsl:apply-templates/> </div> </xsl:template> <xsl:template match="itemizedlist"> <ul style="margin-left:1em"><xsl:apply-templates /></ul> </xsl:template> <xsl:template match="orderedlist"> <ol style="margin-left:1em"><xsl:apply-templates /></ol> </xsl:template> <xsl:template match="listitem"> <li style="text-indent:0.5em"><xsl:apply-templates /></li> </xsl:template> <xsl:template match="programlisting"> <pre style="color:blue;background-color:rgb(200,200,200); margin-left:1em"> <code> <xsl:apply-templates /> </code></pre> </xsl:template> <xsl:template match="para"> <xsl:choose> <xsl:when test="name(..) = ’listitem’"> <xsl:apply-templates /></xsl:when> <xsl:otherwise><p><xsl:apply-templates /></p> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="title" /> </xsl:stylesheet> CC BY-NC-SA Module 3 : Technologies XML 3.1 3.1.1 Aperçu Objectifs Nous avons vu que le XML permet de stocker et d’échanger des informations et que certaines formes de XML, comme le XHTML, s’affichent de façon lisible dans un navigateur. Cependant, dans une organisation, il faut souvent pouvoir afficher de façon lisible du XML qui n’est pas nécessairement compris par un navigateur. Dans ce module, nous présentons deux technologies importantes qui solutionnent cette situation : XSLT et CSS. Nous verrons aussi que le XSLT permet de transformer automatiquement le XML en d’autres formats, ce qui peut être très utile. L’objectif spécifique du module est : – Interpréter des fichiers XML utilisant des espaces de noms, des transformations XSLT ou des instructions CSS. Une activité, le travail noté 4, nous permettra d’évaluer votre atteinte de cet objectif. 3.1.2 Démarche Il n’est pas nécessaire de terminer l’étude de ce module avant de passer aux autres modules du cours. Nous vous invitons à procéder à l’étude de ce module dans l’ordre suivant : – XSLT, XPath, XQuery, XPointer et XLink – CSS Lisez les textes et vérifiez vos connaissances en répondant aux deux questionnaires d’autoévaluation; réalisez ensuite le travail noté 4 qui prend la forme d’un questionnaire portant sur XSLT et CSS. 113 Module 3 : Technologies XML 114 Le pense-bête pour le XSLT, en annexe dans la version imprimée du cours, rassemble les principaux éléments du XSLT et précise leur fonction. 3.2 3.2.1 XSLT Objectif Comprendre le XSLT comme application XML pour transformer les documents, grâce aux feuilles de style. 3.2.2 Activité Lisez le texte qui suit, puis répondez au questionnaire d’autoévaluation. Ce texte porte sur le langage XSL (Extensible Stylesheet Language), mais en particulier sur les XSL Transformations (XSLT). On traitera également des chemins XPath et de XQuery. 3.2.3 Un regard critique Le XML n’est pas un langage de programmation. Néanmoins, on peut utiliser le XML pour définir un langage comme le XSL. Est-ce que c’est une bonne idée ? Plusieurs auteurs, dont Alan Holub, croient que le XML est une syntaxe trop lourde pour la programmation. XML is perhaps the worst programming language ever conceived. I’m not talking about XML as a data-description language, which was its original design. I’m talking about perverting XML for programming applications. It’s inappropriate to use XML as a scripting language (...). These sorts of XML "programs" are unreadable, unmaintainable, an order of magnitude larger than necessary, and audaciously inefficient at runtime. (Alan Holub, Software Development Times, September 2006) Personnellement, je trouve que le XSLT est amusant et utile. Il est utilisé par des millions de sites web et on ne peut prétendre être un expert en XML sans une bonne maîtrise du XSLT. 3.2.4 Les machines de Turing et la technologie XML Une machine de Turing est un modèle abstrait qui sert à représenter les ordinateurs. La thèse de Church-Turing affirme que tout traitement d’information peut être accompli par une machine de Turing. On accepte généralement cette hypothèse comme étant CC BY-NC-SA XSLT 115 vraie en informatique. Un langage de programmation est Turing-complet s’il peut effectuer tous les calculs qu’une machine de Turing peut faire. Le Java, le XSLT et XQuery sont des langages qui sont Turing-complet. Tous les langages informatiques ne sont pas Turing-complet : CSS ne l’est pas. 3.2.5 Qu’est-ce que le XSLT La première version du langage XSLT (Extensible Stylesheet Language Transformation) a été publiée en 1997 et elle est devenue une recommandation W3C en 1999. Elle fait partie du XSL (Extensible Stylesheet Language) qui comprend une seconde composante, les XSL-FO (Extensible Stylesheet Language Formatting Objects). La technologie XSL tire son origine du besoin d’un langage simple, mais suffisamment puissant pour pouvoir contrôler finement l’affichage du XML. On utilise beaucoup le XSLT sur le web et au sein des systèmes d’information, alors que le XSL-FO est davantage utile pour les applications de mise en page spécialisées. Dans ce cours, nous nous soucierons seulement du XSLT, dont l’utilité dépasse de loin les problèmes de présentation. L’objectif poursuivi par le XSLT est de transformer les documents XML en d’autres documents. Par exemple, supposons que vous ayez le document suivant : <?xml version="1.0" encoding="ISO-8859-1" ?> <facture> <montant>10.10</montant> <personne>Jean Rochond</personne> <raison>Achat d’ordinateur</raison> </facture> et que vous vouliez transformer ce type de document XML en document HTML qui aurait la forme suivante : <html> <head> <title>Facture de Jean Rochond</title> </head> <body><p>Ceci est une facture pour Jean Rochond de 10.10$ pour: Achat d’ordinateur.</p></body> </html> Si votre entreprise utilise du XML et que vous désirez envoyer des factures par courriel, vous pourriez envoyer le document HTML au lieu du document XML. De cette manière, le client pourrait consulter sa facture sans avoir à comprendre le XML. On pourrait bien sûr écrire un programme en Java qui effectuerait cette opération, mais la conception d’un programme Java prend du temps et on cherche parfois une solution plus économique, plus rapide. Avec l’exemple que nous venons de voir, on pourrait CC BY-NC-SA Module 3 : Technologies XML 116 automatiser la transformation de XML en HTML en moins d’une quinzaine de minutes. Pour obtenir le résultat désiré, il faut utiliser un petit fichier XSLT. 3.2.6 Les langages déclaratifs Un langage comme Java est orienté objet et procédural. Ce n’est pas, par contre, un langage déclaratif et on dit donc qu’il est impératif. Les langages déclaratifs sont des langages qui définissent le problème au lieu d’en définir la solution. On les reconnaît souvent parce qu’ils énoncent des règles au lieu d’énoncer des procédures. Le langage Prolog est un exemple de langage déclaratif parce que le programmeur ne fait que saisir des relations sans définir comment l’ordinateur doit combiner ses relations: pere(X,Y) :- parent(X,Y),homme(X). freresoeur(X,Y) :- parent(Z,X), parent(Z,Y). Le SQL est aussi déclaratif parce qu’on spécifie à l’ordinateur quelles informations on veut sans pour autant spécifier comment l’information doit être trouvée: SELECT age FROM table WHERE age > 25; Le XSLT et XQuery sont des exemples plus récents de langages déclaratifs. On affirme souvent que les langages déclaratifs sont plus lents que les langages impératifs parce que le logiciel doit lui-même trouver la meilleure stratégie pour évaluer le programme sans recevoir beaucoup d’indices de la part de l’humain. Le contraire peut aussi être vrai: comme le logiciel peut optimiser à sa guise l’exécution du programme étant donné l’absence de structure imposée par l’humain, il est possible pour un langage déclaratif de surpasser en vitesse un langage impératif. En pratique, personne ne se plaint vraiment de la lenteur relative du XSLT, de SQL ou de Prolog. Cependant, pour le programmeur habitué à la programmation impérative, la programmation déclarative peut être source de confusion. Avec l’expérience, on se rend compte que, pour bien des problèmes, la programmation déclarative est préférable surtout lorsqu’on ne veut pas se soucier des détails techniques comme la façon dont le fichier XML est lu et comment il est stocké en mémoire. Le XSLT (et XQuery) peut aussi être considéré comme un langage fonctionnel (voir FXSL ou The Functional Programming Language XSLT - A proof through examples par Dimitre Navatchev) au même titre que APL, Lisp, Haskell, Maple, Mathematica, Ocaml ou Scheme. 3.2.7 Les fichiers XSLT Le fichier XSLT contient des règles qu’un « processeur XSLT » applique aux fichiers XML pour les transformer. Heureusement, si vous utilisez Firefox, vous avez déjà un CC BY-NC-SA XSLT 117 processeur XSLT moderne à même votre navigateur. Lors de l’ouverture d’un document XML, Firefox tente automatiquement de trouver et d’exécuter un document XSLT pour transformer le document XML. Un processeur XSLT va parcourir tous les éléments de votre document en commençant par l’élément-racine et, à chaque fois, il va tenter d’appliquer une règle. Commençons par créer le fichier XSLT suivant qu’on enregistrera sur le disque comme étant « xslt.xml » : <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> </xsl:stylesheet> Ce fichier ne contient aucune « règle » et constitue le document XSLT de base. Nous vous suggérons de faire l’exercice de création de ce document avec Bloc-notes, par exemple. Un fichier XSLT est un document XML bien formé, utilisant l’espace de noms « http://www.w3.org/1999/XSL/Transform » et ayant pour élément-racine stylesheet (ou transform), lequel a lui-même un attribut « version ». On ne discute ici que de la première version de XSLT (1.0); on utilise donc 1.0 comme valeur d’attribut pour version. Prenons maintenant le fichier XML que nous avions auparavant; modifions-le un peu en le faisant pointer vers le fichier XSLT nouvellement créé : <?xml version="1.0" encoding="ISO-8859-1" ?> <?xml-stylesheet href="xslt.xml" type="application/xml"?> <facture> <montant>10.10</montant> <personne>Jean Rochond</personne> <raison>Achat d’ordinateur</raison> </facture> On ajoute donc la ligne : « <?xml-stylesheet href="xslt.xml" type="application/xml"?> ». Cette ligne indique au navigateur, ou à un autre logiciel, que le document XML peut être transformé par le fichier XSLT nommé « xslt.xml ». Le chemin peut être relatif ou absolu : on pourrait donc aussi avoir une ligne comme : «<?xml-stylesheet href="http://www.mondomaine.com/xslt.xml" type="application/xml"?>» si l’URL « http://www.mondomaine.com/xslt.xml » pointe vers un fichier XSLT. CC BY-NC-SA Module 3 : Technologies XML 118 Il suffit d’enregistrer ce nouveau document XML dans le même répertoire que le fichier « xslt.xml », disons avec le nom « test.xml », puis d’ouvrir le fichier « test.xml » dans Firefox. Normalement, on ne devrait rien voir à l’écran (une page vide), car le document XSLT utilisé est vide de toute instruction et le résultat ne sera pas du HTML. Le résultat peut cependant varier selon le navigateur utilisé, car votre navigateur pourrait afficher le texte, même s’il ne s’agit pas de HTML : dans ce cas, vous ne verriez que le texte contenu dans le document XML, les balises en moins. Vous pouvez tester vos scripts XSLT en ligne directement sur la page web http://www.daniel-lemire.com/ blogue/xsltprocessor.html. Avec ce dernier outil, écrit en ECMAScript, il n’est pas nécessaire d’avoir une instruction xml-stylesheet : on peut traiter n’importe quel fichier XML avec n’importe quelle transformation XSLT. En ce sens, on peut programmer en XSLT sans jamais utiliser l’instruction xml-stylesheet. 3.2.8 « Éléments xsl:template » Modifions maintenant le fichier « xslt.xml » de façon à rendre l’expérience plus intéressante. Tout d’abord, traitons tous les éléments « facture » du document XML. Pour obtenir le résultat, il faut placer un élément « <xsl:template match="facture"> » dans l’élément-racine du document XSLT comme ceci : <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="facture"> On doit mettre quelque chose ici!!! </xsl:template> </xsl:stylesheet> Il faut voir l’élément « xsl:template » comme une règle qui dit : à chaque fois qu’on rencontre un élément qui s’appelle « facture », faisons ceci. Le modèle est inclus dans l’élément « xsl:template ». Dans l’exemple de document XSLT que nous venons de voir, le processeur XSLT remplacerait tous les éléments « facture » qu’il rencontre par le texte « On doit mettre quelque chose ici!!! », ce qui donnerait comme résultat le fichier suivant (le résultat exact peut varier un peu selon le processeur XSLT) : <?xml version="1.0" encoding="ISO-8859-1" ?> On doit mettre quelque chose ici!!! Malheureusement, ce n’est pas du HTML valable et Firefox devrait n’afficher qu’un écran vide si vous tentez d’ouvrir le fichier « test.xml » avec un lien vers un tel fichier XSLT. Nous allons donc modifier le fichier XSLT, en ajoutant des balises, comme ceci : <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" CC BY-NC-SA XSLT 119 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="facture"> <html><body>On doit mettre quelque chose ici!!!</body></html> </xsl:template> </xsl:stylesheet> Cette fois, si vous ouvrez le document « test.xml », vous devriez voir le texte « On doit mettre quelque chose ici!!! » s’afficher dans votre navigateur. Faites l’expérience. Dans les exemples que nous allons proposer, nous omettons les éléments « html » et « body » par souci de simplicité. La présence de ces éléments n’est pas nécessaire et n’est utile que pour afficher le résultat dans un navigateur. À vous de les ajouter si vous désirez afficher le résultat. Pour résumer, chaque fois que le processeur XSLT rencontre un élément « facture », il applique le modèle qui se trouve dans l’élément « <xsl:template match="facture"> ». Notez que si l’élément « facture » contient lui-même des éléments, ils ne sont pas automatiquement visités par le processeur XSLT. Ce dernier considère que dès qu’un modèle est appliqué à un élément, il peut alors parcourir le reste du document sans se soucier du contenu de cet élément qui est maintenant « couvert ». 3.2.9 « Éléments xsl:value-of » Jusqu’à présent, le résultat n’est pas très fascinant parce que les éléments « xsl:template » ont été utilisés comme des outils pour faire du « Rechercher/Remplacer ». Le contenu de l’élément « facture » n’est pas traité, on le remplace bêtement par autre chose. Nous pouvons traiter le contenu d’un élément à l’aide d’un élément « xsl:value-of » avec la syntaxe <xsl:value-of select="..." />. La valeur de l’élément « select » est un chemin (appelé expression XPath) : les chemins les plus simples sont constitués du nom d’un sous-élément. Par exemple, si le processeur traite un élément « facture » qui contient un élément « montant », alors l’élément <xsl:value-of select="montant" /> nous donne le contenu de l’élément « montant ». C’est ainsi que nous pouvons trouver le nom de la personne devant recevoir une facture, en utilisant <xsl:value-of select="personne" />. Voyons maintenant un exemple plus complexe de fichier XSLT : <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="facture"> <html> <head> <title>Facture de <xsl:value-of select="personne" /></title> CC BY-NC-SA Module 3 : Technologies XML 120 </head> <body> <p>Ceci est une facture pour <xsl:value-of select="personne" /> de <xsl:value-of select="montant" />$ pour: <xsl:value-of select="raison" />.</p> </body> </html> </xsl:template> </xsl:stylesheet> Si vous modifiez le fichier « xslt.xml » et que vous ouvrez le fichier « test.xml » dans un navigateur supportant le XSLT (comme Firefox), vous devriez voir s’afficher à l’écran la ligne « Ceci est une facture pour Jean Rochond de 10.10$ pour: Achat d’ordinateur. ». Il faut avouer que c’est déjà beaucoup plus intéressant comme application! Ce qui se passe, c’est que le nouveau document XSLT transforme notre document XML en un document HTML : <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Facture de Jean Rochond</title> </head> <body><p>Ceci est une facture pour Jean Rochond de 10.10$ pour: Achat d’ordinateur.</p></body> </html> Pour résumer, nous pouvons aller chercher le contenu textuel d’une expression XPath avec une instruction comme « <xsl:value-of select="..." /> » où « ... » est une expression XPath comme le nom de l’élément. 3.2.10 Arithmétique en XPath Nous pouvons aussi nous servir des expressions XPath pour faire du calcul simple. Par exemple, les trois expressions suivantes donneront 2, 2 et 2.5 respectivement : <xsl:value-of select="1+1" /> <xsl:value-of select="2*1" /> <xsl:value-of select="5 div 2" /> Il arrive qu’on doive calculer une somme de nombres. Par exemple, supposons qu’un facture comporte une liste de montants. <?xml version="1.0" encoding="ISO-8859-1" ?> <?xml-stylesheet href="xslt.xml" CC BY-NC-SA XSLT 121 type="application/xml"?> <facture> <montant>10.10</montant> <montant>20.10</montant> <montant>40.10</montant> </facture> La fonction XPath « sum » nous permet de calculer la somme des montants sans effort comme dans cet exemple : <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="facture"> <html> <body> <xsl:value-of select="sum(montant)" /> </body> </html> </xsl:template> </xsl:stylesheet> Comme en Java, on a aussi les fonctions « floor », « ceiling », « mod » et « round ». On peut aussi utiliser les paranthèses dans toutes expressions XPath : « (5 + 2) div 2 ». 3.2.11 Manipulations des chaînes de caractères en XPath Outre les fonctions arithmétiques, on peut aussi manipuler les chaînes de caractères en XPath. La fonction la plus simple est « string-length ». Elle calcule la longueur d’une chaîne. Une autre fonction simple est « normalize-space » qui élimine tous les espaces au début et à la fin d’une chaîne en plus de remplacer les espaces répétés par un espace simple. La fonction « translate » permet de remplacer des caractères. Par exemple, pour remplacer les é par des e et les à par des a, on pourrait utiliser l’instruction suivante « translate("à la vérité","éà","ea") » qui renvoie « a la verite ». On peut extraire des sous-chaînes de caractères de diverses manières : la fonction « substring » permet d’extraire une sous-chaîne lorsqu’on en connaît sa position et sa longueur, la fonction « substring-after » permet d’aller chercher un suffixe, la fonction « substring-before » permet d’aller chercher un préfixe. Par exemple, « substring("la vie est belle",3,7) » renvoie « vie est », « substring-after("la vie est belle","est") » renvoie « belle » alors que « substring-before("la vie est belle","est") » renvoie « la vie » On peut aussi additionner deux chaînes de caractères pour en faire une seule avec la fonction « concat ». L’expression « concat("a","b") » a comme valeur "ab". CC BY-NC-SA Module 3 : Technologies XML 122 On peut tester une chaîne pour la présence d’une sous-chaîne avec la fonction XPath « contains ». L’expression « contains("abc","bc") » est vraie parce que "bc" est une sous-chaîne de "abc", alors que l’expression « contains("abc","bz") » est fausse. 3.2.12 Chemins XPath plus sophistiqués Supposons maintenant que nous devions traiter un document XML un peu plus complexe, comme celui qui suit : <?xml version="1.0" encoding="ISO-8859-1" ?> <?xml-stylesheet href="xslt.xml" type="application/xml"?> <facture> <montant>10.10</montant> <personne> <sexe>M</sexe> <nom>Rochond</nom> <prenom>Jean</prenom> </personne> <raison>Achat d’ordinateur</raison> </facture> Observez que l’élément « personne » contient maintenant trois sous-éléments : sexe, nom et prenom. Quand on demande au XSLT d’inclure le contenu d’un élément, à l’aide d’une instruction « xsl:value-of », il retire d’abord toutes les balises. Il garde les espaces entre les éléments, le texte, et les retours de chariot; seules les balises sont retirées. En somme, le résultat de l’instruction « xsl:value-of » appliqué à un élément est son contenu textuel. Précisons que dans le cas où on sélectionne non pas un élément, mais plusieurs, l’instruction value-of ne s’applique qu’au premier élément rencontré. Ainsi, si nous utilisions le fichier XSLT précédent destiné à des éléments « personne » ne contenant que du texte, nous obtiendrions à l’écran, dans Firefox, le texte « Ceci est une facture pour M Rochond Jean de 10.10$ pour: Achat d’ordinateur. ». Pourquoi ce résultat? Parce qu’à l’endroit où se trouve <xsl:value-of select="personne" /> s’insère le contenu de l’élément, sans le balisage, ce qui fait que seul le contenu des souséléments, dans l’ordre, est affiché. De façon concrète, le fichier XML est transformé en contenu HTML : <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Facture de M Rochond Jean </title> CC BY-NC-SA XSLT 123 </head> <body><p>Ceci est une facture pour M Rochond Jean de 10.10$ pour: Achat d’ordinateur.</p> </body> Par ailleurs, nous pouvons modifier le fichier XSLT pour aller chercher le contenu respectif des sous-éléments « prenom » et « nom ». Pour ce faire, il suffit de remplacer « select="personne" » par « select="personne/prenom" » et « select="personne/nom" », car la valeur de l’attribut « select » se comporte un peu comme dans les adresses web : le symbole « / » entre deux noms d’élément signifie « sous-élément ». Nous pourrons alors utiliser le fichier XSLT suivant : <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="facture"> <html> <head> <title>Facture de <xsl:value-of select="personne" /></title> </head> <body> <p>Ceci est une facture pour <xsl:value-of select="personne/prenom" /> <xsl:value-of select="personne/nom" /> de <xsl:value-of select="montant" />$ pour: <xsl:value-of select="raison" />.</p> </body> </html> </xsl:template> </xsl:stylesheet> Si nous testons ce nouveau fichier XSLT dans Firefox, nous constaterons que le résultat est presque correct : cette fois-ci, le fichier « test.xml » s’affiche comme « Ceci est une facture pour JeanRochond de 10.10$ pour: Achat d’ordinateur. ». Notez qu’il manque un espace entre Jean et Rochond. Cela se produit parce que dans un document XSLT, on ignore les espaces entre les éléments (dans le cas où il n’y a que des espaces entre les deux éléments) : pour obtenir un espace, il faut en marquer la présence en insérant un élément « xsl:text » comme ceci : <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="facture"> <html> CC BY-NC-SA Module 3 : Technologies XML 124 <head> <title>Facture de <xsl:value-of select="personne" /></title> </head> <body> <p>Ceci est une facture pour <xsl:value-of select="personne/prenom" /> <xsl:text> </xsl:text> <xsl:value-of select="personne/nom" /> de <xsl:value-of select="montant" />$ pour: <xsl:value-of select="raison" />.</p> </body> </html> </xsl:template> </xsl:stylesheet> En effet, alors que les espaces entre les éléments sont ignorés, l’espace dans un élément « xsl:text » sera pris en compte. Attention à la confusion : les espaces entre les éléments sont ignorés dans le fichier XSLT, mais pas dans le fichier XML qui est traité! Nous constatons que les chemins XPath peuvent contenir non seulement le nom d’un élément, mais aussi le nom d’un sous-élément, comme « personne/prenom ». Cela peut nous permettre de construire des modèles complexes qui peuvent aller extraire des valeurs contenues dans des sous-éléments. 3.2.13 Modularité avec les éléments « xsl:apply-templates » Notre fichier « xslt.xml » se complexifie et devient plus difficile à comprendre. Tout est dans un seul modèle, le modèle facture. Pour simuler un problème probable, imaginons que notre XML est plus complexe et prend la forme : <?xml version="1.0" encoding="ISO-8859-1" ?> <?xml-stylesheet href="xslt.xml" type="application/xml"?> <facture> <montant>10.10</montant> <recipiendaire> <personne> <sexe>M</sexe> <nom>Rochond</nom> <prenom>Jean</prenom> </personne> </recipiendaire> <commercant> <personne> <sexe>F</sexe> <nom>Ladouce</nom> <prenom>Jeanne</prenom> CC BY-NC-SA XSLT 125 </personne> </commercant> <raison>Achat d’ordinateur</raison> </facture> Dans ce nouveau document XML, se trouvent deux éléments « personne ». Il serait bête, dans le document XSLT, de répéter le travail chaque fois qu’on veut afficher un élément « personne ». Regardons ce que cela pourrait donner en pratique : <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="facture"> <html> <head> <title>Facture de <xsl:value-of select="personne" /></title> </head> <body> <p>Ceci est une facture pour <xsl:value-of select="recipiendaire/personne/prenom" /> <xsl:text> </xsl:text> <xsl:value-of select="recipiendaire/personne/nom" /> de <xsl:value-of select="montant" />$ pour: <xsl:value-of select="raison" />.</p> <p>Votre commerçant: <xsl:value-of select="commercant/personne/prenom" /> <xsl:text> </xsl:text> <xsl:value-of select="commercant/personne/nom" /> </p> </body> </html> </xsl:template> </xsl:stylesheet> Observez comment on répète le texte suivant à deux reprises : <xsl:value-of select="recipiendaire/personne/prenom" /> <xsl:text> </xsl:text> <xsl:value-of select="recipiendaire/personne/nom" /> Voici une autre solution, plus élégante, qui donne le même résultat : <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- d’abord un modèle pour les éléments facture --> CC BY-NC-SA Module 3 : Technologies XML 126 <xsl:template match="facture"> <html> <head> <title>Facture de <xsl:value-of select="recipiendaire/personne" /></title> </head> <body> <p>Ceci est une facture pour <xsl:apply-templates select="recipiendaire" /> de <xsl:value-of select="montant" />$ pour: <xsl:value-of select="raison" />.</p> <p>Votre commerçant: <xsl:apply-templates select="commercant" /> </p> </body> </html> </xsl:template> <!-- le modèle pour les éléments facture utilise un modèle pour les éléments personne --> <xsl:template match="personne"> <xsl:value-of select="prenom" /> <xsl:text> </xsl:text> <xsl:value-of select="nom" /> </xsl:template> </xsl:stylesheet> Quelques éléments « xsl:value-of » ont été remplacés par des éléments « xsl:applytemplates ». Un élément « xsl:apply-templates » prend le contenu et, au lieu d’insérer le contenu textuel comme le fait « xsl:value-of » à l’endroit prévu, il insère plutôt le résultat obtenu par l’application de modèles (éléments « xsl:template »). Ainsi, dans l’exemple que nous venons de voir, chaque fois que le processeur XSLT rencontre l’instruction « <xsl:apply-templates select="recipiendaire" /> », il prend l’élément « recipiendaire » et essaie d’appliquer ses modèles. Comme il n’a pas de modèle pour les éléments « recipiendaire », il explore le contenu de l’élément et y trouve immédiatement un élément « personne ». Puisqu’il dispose d’un modèle pour ce type d’élément, il va l’appliquer. Par ailleurs, comme les éléments « recipiendaire » et « commercant » ne contiennent qu’un élément « personne », c’est donc le modèle défini pour les éléments « personne » qui s’appliquera dans les deux cas. Normalement, les éléments « xsl:apply-templates » sont utilisés au sein des éléments « xsl:template ». On peut aussi les utiliser au sein d’autres éléments que nous discuterons prochainement, « xsl:param » et « xsl:variable ». Notre fichier « xslt.xml » est maintenant plus modulaire, parce qu’il contient deux modèles (éléments « xsl:template »). En résumé, il est souvent préférable d’utiliser un élément « xsl:apply-templates » qu’un élément « xsl:value-of » quand la complexité du modèle augmente; ceci permet d’assurer la modularité et de garder la simplicité du document XSLT. CC BY-NC-SA XSLT 127 Par défaut, l’instruction apply-templates traite les documents dans l’ordre où ils se présentent dans le document original. On peut forcer le XSLT à trier les éléments avant de le traiter avec l’instruction xsl:sort. Dans notre exemple, on peut remplacer l’élément <xsl:apply-templates select="recipiendaire" /> par cet élément si on veut que les individus soient triés par leur nom de famille. <xsl:apply-templates match="étudiant" > <xsl:sort select="personne/nom" order="ascending" data-type="text" /> </xsl:apply-templates> Si on souhaite un tri sur la valeur numérique d’une expression, on remplacera datatype="text" par data-type="number". On peut aussi importer un autre fichier XSLT avec l’instruction xsl:import. Celle-ci doit apparaître au tout début du fichier XSLT comme premier sous-élément de l’élément xsl:stylesheet comme dans cet exemple : <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:import href="mesregles.xsl"/> <xsl:template match="facture"> <html> <head> <title>Facture de <xsl:value-of select="personne" /></title> </head> </xsl:template> </xsl:stylesheet> En cas de conflit entre les règles de fichier XSLT principal et celles du fichier importé, les règles du fichier XSLT principal l’emporte. 3.2.14 Chemins XPath pour la sélection des attributs Maintenant que nous avons un document XSLT modulaire, il est plus facile de l’enrichir. Supposons que le document XML contienne des attributs... Le numéro d’assurance sociale des individus peut être indiqué par des attributs « nas », en utilisant le symbole « @ » dans l’expression XPath, comme dans l’exemple qui suit : <?xml version="1.0" encoding="ISO-8859-1" ?> <?xml-stylesheet href="xslt.xml" type="application/xml"?> <facture> <montant>10.10</montant> <recipiendaire> <personne nas="423432432"> <sexe>M</sexe> CC BY-NC-SA Module 3 : Technologies XML 128 <nom>Rochond</nom> <prenom>Jean</prenom> </personne> </recipiendaire> <commercant> <personne nas="432444333"> <sexe>F</sexe> <nom>Ladouce</nom> <prenom>Jeanne</prenom> </personne> </commercant> <raison>Achat d’ordinateur</raison> </facture> En outre, si nous voulons afficher le numéro d’assurance sociale de l’individu entre parenthèses, nous pourrons utiliser le fichier « xslt.xml » suivant : <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="facture"> <html> <head> <title>Facture de <xsl:value-of select="personne" /></title> </head> <body> <p>Ceci est une facture pour <xsl:apply-templates select="recipiendaire" /> de <xsl:value-of select="montant" />$ pour: <xsl:value-of select="raison" />.</p> <p>Votre commerçant: <xsl:apply-templates select="commercant" /> </p> </body> </html> </xsl:template> <xsl:template match="personne"> <xsl:value-of select="prenom" /> <xsl:text> </xsl:text> <xsl:value-of select="nom" /> ( <xsl:value-of select="@nas" /> ) </xsl:template> </xsl:stylesheet> CC BY-NC-SA XSLT 129 Notez que le chemin XPath « <xsl:value-of select="@nas" /> » ne donne pas le contenu de l’élément « nas », mais plutôt la valeur de l’attribut ayant pour nom « nas ». 3.2.15 Expression XPath « . » Supposons que, dans un modèle, nous voulions obtenir non pas la valeur d’un attribut ou d’un sous-élément, mais la valeur de l’élément lui-même. On obtient ce résultat avec l’expression XPath « . » (un point). Par exemple, nous pourrions définir le modèle suivant : <xsl:template match="prenom"> <xsl:value-of select="." /> </xsl:template> Dans l’expression « select="." », le point représente l’élément courant, c’est-à-dire l’élément « prenom ». Donc, l’élément « <xsl:value-of select="." /> » donne le contenu de l’élément « courant ». Nous pourrions remplacer le fichier XSLT précédent par celui qui suit et obtenir les mêmes résultats : <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="facture"> <html> <head> <title>Facture de <xsl:value-of select="personne" /></title> </head> <body> <p>Ceci est une facture pour <xsl:apply-templates select="recipiendaire" /> de <xsl:value-of select="montant" />$ pour: <xsl:value-of select="raison" />.</p> <p>Votre commerçant: <xsl:apply-templates select="commercant" /> </p> </body> </html> </xsl:template> <xsl:template match="personne"> <xsl:apply-templates select="prenom" /> <xsl:text> </xsl:text> <xsl:value-of select="nom" /> ( <xsl:value-of select="@nas" /> ) </xsl:template> <xsl:template match="prenom"> CC BY-NC-SA Module 3 : Technologies XML 130 <xsl:value-of select="." /> </xsl:template> </xsl:stylesheet> Nous pourrions objecter que les instructions « <xsl:apply-templates select="recipiendaire" /> » et « <xsl:apply-templates select="commercant" /> » sont étranges puisqu’il n’y a pas de modèle « recipiendaire » ou « commercant ». Cependant, la règle par défaut qui s’applique aux éléments est d’appliquer les modèles à leurs sous-éléments et ainsi de suite. 3.2.16 Spécifier les valeurs d’attributs Nous savons maintenant comment aller chercher la valeur d’un attribut en utilisant une expression XPath contenant le symbole « @ ». Cependant, qu’en est-il de la spécification des valeurs d’attributs? Supposons le document suivant : <facture> <montant>10.10</montant> </facture> Nous voulons le simplifier pour n’avoir que : <facture montant="10.10" /> Nous pouvons obtenir ce résultat en utilisant les accolades, pour indiquer une valeur XPath comme valeur d’attribut, de la façon suivante : <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="facture"> <facture montant="{montant}" /> </xsl:template> </xsl:stylesheet> <section>Expression XPath «.»</section> 3.2.17 Expression XPath « .. » L’expression « select=".." » (deux points successifs) peut être utilisée pour représenter l’élément dans lequel se trouve l’élément courant. Ainsi, dans le modèle suivant CC BY-NC-SA XSLT 131 <xsl:template match="prenom"> <xsl:value-of select=".." /> </xsl:template> l’instruction « <xsl:value-of select=".." /> » donne la valeur (texte contenu dans l’élément sans les balises) de l’élément « personne » dans lequel est contenu l’élément « prenom ». Nous pouvons aller chercher le parent du parent avec l’instruction <xsl:value-of select="../.." />. Lorsque l’élément courant est l’élément-racine, l’expression « .. » (deux points successifs) ne devrait pas être utilisée. 3.2.18 Expression XPath « // » Parfois, il est avantageux de sélectionner par nom tous les éléments qui sont dans l’élément courant ou dans un sous-élément; nous pouvons obtenir ce résultat avec l’expression XPath « // » (deux barres obliques). L’expression XPath « //prenom » sélectionne tous les éléments prenom incluant ceux qui seraient contenus dans un élément nom, par exemple. L’instruction <xsl:value-of select="//personne" /> donnera donc le contenu textuel du premier élément personne recontré dans le document. 3.2.19 Expression XPath « * » Parfois, il est avantageux de sélectionner tous les éléments qui sont dans l’élément courant; nous pouvons obtenir ce résultat avec l’expression XPath « * » (astérisque). Par exemple, le modèle qui suit s’applique à tous les éléments : <xsl:template match="*"> Ceci est un élément. </xsl:template> Une expression avec « @* » sélectionne tous les attributs contenus dans un élément. Dans certains cas, plus d’un modèle s’applique à un élément donné : en cas de doute, le processeur applique le modèle le plus « spécifique »; le modèle pour « * » ne s’applique que s’il n’existe aucun autre modèle. De la même façon, nous pouvons indiquer au processeur XSLT d’appliquer les règles à tous les éléments, en utilisant la syntaxe <xsl:apply-templates select="*" />. 3.2.20 Expression XPath avec « | » Parfois, nous voulons sélectionner plusieurs noms d’éléments; nous pouvons obtenir ce résultat avec le symbole « | » (barre verticale) qui signifie « union ». Par exemple, le CC BY-NC-SA Module 3 : Technologies XML 132 modèle qui suit s’applique à tous les éléments « facture » et « montant », et seulement à ces éléments : <xsl:template match="facture|montant"> Ceci est un élément facture ou montant. </xsl:template> 3.2.21 Expression XPath pour le nom d’un élément Supposons que nous voulions afficher uniquement les noms des éléments (sans leur contenu). Nous pouvons obtenir ce résultat avec la fonction XPath « name » qui donne le nom de l’élément. La fonction name inclut le préfixe de l’espace de noms. Si on souhaite le nom de l’élément sans le préfixe, on peut utiliser la fonction « local-name ». La fonction « namespace-uri » donne l’URI de l’espace de noms de l’élément. Ainsi, le document XSLT suivant permet d’afficher tous les noms des éléments XML, sans le contenu textuel de ces éléments. <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="*"> <xsl:value-of select="name(.)" /> <xsl:apply-templates select="*" /> </xsl:template> </xsl:stylesheet> Nous pourrions aussi vouloir afficher non seulement le nom de l’élément courant, mais aussi le nom de l’élément-parent, ce qu’on peut faire avec le document XSLT suivant : <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="*"> <xsl:value-of select="name(..)" /> / <xsl:value-of select="name(.)" /> <xsl:apply-templates select="*" /> </xsl:template> </xsl:stylesheet> 3.2.22 Notion de nœuds XSLT Un processeur XSLT traite un fichier XML en partant du début et en appliquant ses règles au fur et à mesure qu’il rencontre des éléments. Rappelons que si le processeur CC BY-NC-SA XSLT 133 XSLT rencontre un élément pour lequel il n’a aucune règle (modèle), il visite tous les sous-éléments et applique le modèle par défaut, soit reproduire le texte quand il en rencontre, en omettant les balises. Une autre façon de décrire ce comportement est de dire que le XSLT utilise un modèle de fichiers XML « en arbre de nœuds ». Imaginons un arbre où, à la racine, se trouve un nœud spécial représentant le document dans son ensemble. Avec XPath, nous pouvons pointer directement sur le nœud-racine (le document lui-même) en utilisant la barre oblique « / » que nous plaçons au début de l’expression XPath, comme dans « <xsl:value-of select="/" /> ». Dans ce cas, « <xsl:value-of select="/jean" /> » donne la valeur de l’élément-racine, si celui-ci se nomme « jean ». Le nœud-racine contient lui-même l’élément-racine. Chaque élément et chaque élément de texte sont aussi des nœuds dans ce modèle d’arbre XSLT. Alors que les nœuds de texte ne peuvent pas contenir d’autres nœuds, les nœuds d’élément peuvent contenir plusieurs autres nœuds dont d’autres nœuds d’élément et de texte. Ainsi, par défaut, le processeur XSLT qui atteint un élément visite tous les éléments et les nœuds de texte qu’il contient. Un nœud de texte rencontré est simplement recopié, par défaut, alors que pour les éléments, on visite également leur contenu. C’est ce qui explique que, par défaut, s’il n’y a aucune règle dans le document XSLT, un document XML est recopié sans les balises. D’autres nœuds existent comme les nœuds de commentaire, les nœuds d’instructions de traitement et les nœuds d’espaces de noms, mais ils sont moins importants que le nœud du document (nœud-racine), les nœuds d’attribut, les nœuds de texte ou les nœuds d’élément. Dans le modèle d’arbre, les nœuds d’espaces de noms et les nœuds d’attribut sont attachés à l’élément, mais ne sont pas un enfant (« child »). Nous avons déjà vu que « * » et « @* » permettaient de sélectionner les sous-éléments et attributs d’un élément. On peut sélectionner les nœuds de texte avec la fonction XPath « text() ». Notons aussi que l’élément « <xsl:apply-templates/> » signifie que les modèles s’appliquent à tous les nœuds contenus dans le nœud courant. Les règles par défaut qui s’appliquent en XSLT sont : <xsl:template match="*|/"> <xsl:apply-templates/> </xsl:template> <xsl:template match="text()|@*"> <xsl:value-of select="."/> </xsl:template> <xslt:template match="processing-instruction()|comment()" /> En résumé, un processeur XSLT représente un document XML comme un arbre et tente de le visiter de la racine vers les feuilles. Lorsqu’il rencontre un modèle pour un CC BY-NC-SA Module 3 : Technologies XML 134 nœud, il l’applique et ne poursuit pas automatiquement la visite des nœuds qui y sont contenus, à moins de rencontrer un élément « xsl:apply-templates ». 3.2.23 Expressions XPath pour compter et additionner les éléments Avec XSLT et XPath, on peut faire un certain nombre d’opérations, comme compter les éléments. La fonction XPath « count » compte le nombre de nœuds (éléments) sélectionnés. Soit le document XML suivant : <facture> <montant>10.10</montant> <montant>20.10</montant> </facture> Supposons qu’on veuille calculer automatiquement le nombre d’éléments « montant » pour obtenir quelque chose comme ceci : <facture nombre="2" /> Il suffit simplement d’utiliser la fonction « count », comme dans l’exemple de document XSLT qui suit : <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="facture"> <facture nombre="{count(montant)}" /> </xsl:template> </xsl:stylesheet> Supposons maintenant qu’on veuille numéroter les montants pour bien indiquer quel montant apparaît en premier, quel montant apparaît en deuxième, et ainsi de suite. Pour ce faire, il n’y a pas d’expression XPath appropriée, mais nous pouvons obtenir le résultat désiré à l’aide de l’élément XSLT « xsl:number » et son attribut « count ». En effet, le document XSLT qui suit : <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="facture"> <xsl:apply-templates select="montant" /> </xsl:template> <xsl:template match="montant"> CC BY-NC-SA XSLT 135 Montant numero <xsl:number count="montant" /> est <xsl:value-of select="." />. </xsl:template> </xsl:stylesheet> permet d’obtenir le résultat suivant : Montant numero 1 est 10.10. Montant numero 2 est 20.10. L’élément « xsl:number » avec l’attribut « count » permet de numéroter des éléments sur la base de leur nom, que l’on utilise comme valeur de l’attribut « count ». On peut aussi additionner des nombres avec la fonction XPath « sum ». L’exemple suivant fera la somme des valeurs numériques contenues dans les éléments « montant » (10.10 et 20.10). <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="facture"> <xsl:value-of select="sum(montant)" /> </xsl:template> </xsl:stylesheet> 3.2.24 Utilisation de l’attribut « mode » Il arrive que nous voulions définir plus d’un modèle pour un élément donné. Nous pouvons ajouter des modèles en utilisant l’attribut « mode » qui s’applique aux éléments « xsl:apply-templates » et « xsl:template ». La règle est très simple : si votre élément « xsl:apply-templates » a une valeur d’attribut pour « mode », alors seuls les éléments « xsl:template » ayant la même valeur d’attribut pour « mode » s’appliquent. On utilise souvent l’attribut « mode » pour faire des tables des matières. Prenons, par exemple, la liste de cours suivants : <?xml version="1.0" encoding="ISO-8859-1" ?> <universite> <cours><nom>INF 102 Introduction avancée</nom> <description>Un cours d’introduction à l’informatique pour futurs ingénieurs.</description></cours> <cours><nom>INF 101 Introduction</nom> <description>Un cours d’introduction à l’informatique pour les étudiants en éducation.</description></cours> <cours><nom>INF 103 Java</nom> CC BY-NC-SA Module 3 : Technologies XML 136 <description>Un cours d’introduction au Java</description></cours> </universite> Nous pourrions vouloir que s’affiche d’abord seulement la liste des noms de cours et que cette dernière soit suivie d’une liste détaillée comprenant le nom et la description du cours : La liste des cours en bref: – INF 102 Introduction avancée – INF 101 Introduction – INF 103 Java La liste détaillée des cours: – INF 102 Introduction avancée: Un cours d’introduction à l’informatique pour futurs ingénieurs. – INF 101 Introduction: Un cours d’introduction à l’informatique pour les étudiants en éducation. – INF 103 Java: Un cours d’introduction au Java Nous pouvons obtenir ce résultat avec le document XSLT suivant qui utilise l’attribut « mode » : <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="universite"> <html><body> <p>La liste des cours en bref:</p> <ul> <xsl:apply-templates select="cours" mode="initial" /> </ul> <p>La liste détaillée des cours:</p> <ul> <xsl:apply-templates select="cours" mode="complet" /> </ul> </body></html> </xsl:template> <xsl:template match="cours" mode="initial"> <li><xsl:value-of select="nom" /></li> </xsl:template> <xsl:template match="cours" mode="complet"> <li><xsl:value-of select="nom" /> : <xsl:value-of select="description" /></li> </xsl:template> CC BY-NC-SA XSLT 137 </xsl:stylesheet> 3.2.25 Fonction « generate-id » La fonction XSLT « generate-id » génère un « nom » unique pour chaque élément d’un document XML. Ce nom sera toujours le même pour un même élément, même si nous le rencontrons à plusieurs reprises. Si nous reprenons la liste des cours de l’exemple précédent sur l’utilisation de l’attribut « mode », nous pourrions générer un identifiant unique pour chaque cours et l’afficher comme dans l’exemple de document XSLT qui suit : <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="universite"> <html><body> <p>La liste des cours en bref :</p> <ul> <xsl:apply-templates select="cours" mode="initial" /> </ul> <p>La liste détaillée des cours :</p> <ul> <xsl:apply-templates select="cours" mode="complet" /> </ul> </body></html> </xsl:template> <xsl:template match="cours" mode="initial"> <li><xsl:value-of select="nom" /> (identifiant: <xsl:value-of select="generate-id(.)" />)</li> </xsl:template> <xsl:template match="cours" mode="complet"> <li><xsl:value-of select="nom" /> : <xsl:value-of select="description" /> (identifiant: <xsl:value-of select="generate-id(.)" />)</li> </xsl:template> </xsl:stylesheet> Nous pourrions alors obtenir un résultat comme celui-ci : La liste des cours en bref: – INF 102 Introduction avancée (identifiant: id2243749) – INF 101 Introduction (identifiant: id2243760) – INF 103 Java (identifiant: id2243686) CC BY-NC-SA Module 3 : Technologies XML 138 La liste détaillée des cours: – INF 102 Introduction avancée: Un cours d’introduction à l’informatique pour futurs ingénieurs. (identifiant: id2243749) – INF 101 Introduction: Un cours d’introduction à l’informatique pour les étudiants en éducation. (identifiant: id2243760) – INF 103 Java: Un cours d’introduction au Java (identifiant: id2243686) Les valeurs exactes que prennent les identifiants sont sans importance, mais il importe que ce soit toujours la même valeur pour un même élément. Par exemple, le cours sur Java obtient toujours l’identifiant « id2243686 » dans notre exemple. 3.2.26 Utilisation des tests Nous pouvons tester des conditions à l’aide d’expressions XPath contenant les symboles « < », « = », « != », « or », « and », « > », « >= », « <= ». Nous utilisons les tests en XSLT avec les éléments « xsl:choose » et « xsl:if ». Par exemple, faire quelque chose de particulier, si le nom de l’élément courant est « montant ». <xsl:template match="*"> <xsl:if test="name(.) = ’montant’"> Il s’agit d’un élément nommé «montant». </xsl:if> </xsl:template> La syntaxe de l’élément « xsl:if » est très simple; si la valeur de l’expression XPath contenue dans l’attribut « test » est vraie, le contenu de l’élément « xsl:if » s’applique, sinon, on l’omet. Notez qu’il n’y a pas d’élément « xsl:else » Nous pouvons aussi traiter plusieurs tests dans un seul élément « xsl:choose » comme ceci : <xsl:template match="*"> <xsl:choose> <xsl:when test="name(.)=’montant’"> Il y a une balise "montant" </xsl:when> <xsl:when test="name(.)=’facture’"> J’ai trouvé une "facture" </xsl:when> <xsl:otherwise> Je ne connais pas cet élément </xsl:otherwise> </xsl:choose> </xsl:template> CC BY-NC-SA XSLT 139 On peut aussi combiner plusieurs tests avec les opérateurs logiques and, or et not comme le montre le prochain exemple. <xsl:template match="*"> <xsl:choose> <xsl:when test="name(.)=’montant’ or name(.)=’facture’"> Il y a une balise "montant" ou une balise "facture" </xsl:when> <xsl:when test="not(name(.)=’argent’)"> Ce n’est ni montant, ni facture, ni argent. </xsl:when> <xsl:otherwise> Je ne connais pas cet élément. </xsl:otherwise> </xsl:choose> </xsl:template> On peut aussi tester la langue d’un élément avec la fonction XPath « lang ». L’expression « count(//p[lang(’en’)]) » compte le nombre d’élément « p » ayant été déclaré comme contenant du texte en langue anglaise. Observez qu’un élément « xsl:choose » contient plusieurs éléments « xsl:when » qui sont testés tour à tour, jusqu’à ce qu’une condition soit vraie; l’élément « xsl:otherwise » est présent pour l’éventualité où tous les tests échouent. Tous les tests sont réalisés en séquence et dès qu’une condition est vraie, les tests s’arrêtent et le contenu de l’élément « xsl:when » est évalué. En XSLT, il ne faut pas abuser des tests; il est préférable d’utiliser des éléments « xsl:template » qui sont plus modulaires. 3.2.27 Tester le contenu des chaînes de caractères Nous avons vu comment comparer le nom ou le contenu d’un élément avec une chaîne de caractères donnée, mais il arrive qu’on veuille faire des comparaisons plus fine. Heureusement, il existe des fonctions XPath permettant d’analyser le contenu des chaînes. Par exemple, « starts-with("a",@toto) » renvoie la valeur vraie si et seulement si la valeur de l’attribut « toto » débute avec la lettre « a ». L’expression « endswith("a",@toto) » est vraie si et seulement si la valeur de l’attribut « toto » se termine avec la lettre « a ». De la même façon, « contains("abc",@toto) » renvoie la valeur vraie si et seulement si la valeur de l’attribut « toto » contient la chaîne « abc » (comme dans « j’ai un abc »). CC BY-NC-SA Module 3 : Technologies XML 3.2.28 140 Accès aux éléments d’un ensemble d’éléments Avec XSLT, nous pouvons traiter du XML un peu comme nous traitons un tableau en Java ou en C/C++. Par exemple, supposons que nous ayons une liste de clients avec leur numéro de téléphone, comme ceci : <?xml version="1.0" encoding="ISO-8859-1" ?> <listedeclients> <client telephone="543-5454"><nom>Jacques</nom></client> <client telephone="545-5455"><nom>Sylvain</nom></client> <client telephone="443-4456"><nom>Claude</nom></client> <client telephone="533-3445"><nom>Yvon</nom></client> </listedeclients> Notez que l’expression XPath « /listedeclients/client » est en fait une séquence (ensemble ordonné) d’éléments. Ainsi, « /listedeclients/client[2] » représente le deuxième (et non le troisième!) élément « client », celui dont le nom est « Sylvain ». Maintenant, si nous voulons obtenir le numéro de téléphone du deuxième client de la liste, il faut d’abord ajouter le symbole « / » (barre oblique) pour indiquer qu’on cherche un sous-nœud de l’élément en question, suivi de « @telephone » pour désigner l’attribut « telephone ». Le document XSLT suivant nous donnerait le numéro de téléphone désiré : <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="listedeclients"> <xsl:value-of select="/listedeclients/client[2]/@telephone" /> </xsl:template> </xsl:stylesheet> Ou, plus simplement : <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="listedeclients"> <xsl:value-of select="client[2]/@telephone" /> </xsl:template> </xsl:stylesheet> Notez que l’expression « /listedeclients/client[0] » n’est pas valable, car la numérotation des éléments d’une séquence débute à 1 en XSLT, contrairement à Java et à C/C++. CC BY-NC-SA XSLT 141 Notez aussi qu’on aurait pu obtenir le même résultat avec l’expression XPath « (/listedeclients/client/@telephone)[2] », car « /listedeclients/client/@telephone » est aussi une séquence (mais une séquence d’attributs). Nous devons toutefois ajouter une parenthèse pour marquer la priorité des opérations. En effet, la syntaxe « a/b[2] » signifie : deuxième nœud de type « b » dans les nœuds de type « b ». Comme il ne peut y avoir qu’un seul attribut d’un type donné dans un élément, la syntaxe « a/@b[2] » donnera toujours un ensemble vide. D’un autre côté, la syntaxe « (a/b)[2] » signifie : deuxième nœud de type « b » dans la séquence des nœuds de type « b » contenus dans les nœuds de type « a ». De la même manière, « //b[2] » donne la liste de tous les éléments b « b » dans le document apparaissant deuxième dans la liste des éléments contenus dans un autre élément, alors que « (//b)[2] » est le deuxième élément « b » rencontré dans tout le document. Vous croyez avoir bien compris ? Quelle est la différence entre « (b)[2] » et « b[2] » ? Quelle est la différence entre « (b[2])/a » et « b[2]/a » ? 3.2.29 Utiliser XSLT comme base de données et éléments « foreach » L’exemple de la liste des clients avec leur numéro de téléphone nous permet de faire plus. Nous pouvons y utiliser XSLT comme « moteur (primitif) de base de données », en cherchant les éléments selon leur contenu. L’expression XPath « /listedeclients/client[nom=’Sylvain’] » nous donnera les éléments pour lesquels le contenu du sous-élément « nom » est « Sylvain ». L’expression plus complète « /listedeclients/client[nom=’Sylvain’]/@telephone » pointera directement sur l’attribut « telephone » dont la valeur est « 545-5455 ». D’un autre côté, l’expression XPath « /listedeclients/client[@telephone=’533-3445’]/nom », nous donnera l’élément « nom » contenant le nom du client ayant le numéro de téléphone indiqué. L’absence du symbole « = » dans le crochets indique qu’il s’agit d’un test d’existence. Ainsi, « /listedeclients/client[nom] » donne les éléments « client » qui ont un sousélément « nom ». De la même façon, « /listedeclients/client[@telephone] » donne les éléments « client » qui ont un attribut « telephone ». Supposons maintenant que nous soyons devant un fichier XML comme celui-ci : <?xml version="1.0" encoding="ISO-8859-1" ?> <listes> <vendeur nom="Jean"> <client telephone="543-5454"><nom>Jacques</nom></client> <client telephone="545-5455"><nom>Sylvain</nom></client> <client telephone="443-4456"><nom>Claude</nom></client> <client telephone="533-3445"><nom>Yvon</nom></client> </vendeur> <vendeur nom="Raymond"> <client telephone="432-2145"><nom>Arthur</nom></client> CC BY-NC-SA Module 3 : Technologies XML 142 <client telephone="545-5456"><nom>Sylvain</nom></client> <client telephone="443-4556"><nom>Claudette</nom></client> <client telephone="533-3445"><nom>Yvon</nom></client> </vendeur> </listes> Il est maintenant plus fastidieux de trouver le numéro de téléphone d’un certain client, car il faut visiter tous les vendeurs. De plus, chaque vendeur peut avoir un numéro de téléphone (possiblement différent) pour chaque client. Comme nous allons le voir, le XSLT permet de gérer assez facilement ces situations. Tout d’abord, l’expression « //client » donne une séquence de tous les éléments « client » dans le nœud courant. Avec l’expression XPath « //client[nom=’Sylvain’] », nous pouvons obtenir la séquence de tous les éléments « client » ayant pour nom « Sylvain ». Dans ce cas précis, il y a plus d’un élément dans la réponse. Pour visiter l’ensemble des éléments dans la séquence, il suffit d’utiliser l’élément « xsl:for-each » comme ceci : <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <html><body>Numéros de téléphone pour Sylvain: <ul> <xsl:for-each select="//client[nom=’Sylvain’]/@telephone" > <li><xsl:value-of select="." /></li> </xsl:for-each> </ul> </body></html> </xsl:template> </xsl:stylesheet> Le résultat de l’application de ce fichier XSLT au fichier XML contenant les numéros de téléphone sera : <html><body>Numéros de téléphone pour Sylvain: <ul> <li>545-5455</li> <li>545-5456</li> </ul> </body></html> CC BY-NC-SA XSLT 143 Dans une telle boucle, il peut être utile de savoir quel est le numéro du nœud courant. On obtient ce numéro avec la fonction XSLT « position() » qui a la valeur 1 quand il s’agit du premier nœud et la valeur « last() » quand il s’agit du dernier nœud. On peut aussi utiliser une instruction xsl:sort au sein d’un élément for-each. Supposons maintenant que nous voulions compter le nombre de fois qu’un client est dans la base de données. Un modèle XSLT comme celui qui suit semble une bonne piste : <xsl:template match="client"> <li><xsl:value-of select="count(//client[nom=./nom])" /></li> </xsl:template> Malheureusement, entre les crochets (partie conditionnelle de l’expression XPath), le symbole « . » ne représente plus l’élément « client » XSLT courant, mais bien chacun des éléments « client » du document tour à tour : la condition « nom=./nom » est ici toujours satisfaite. Heureusement, il existe une fonction XSLT, appelée « current() », qui représente toujours l’élément XSLT courant. Donc, si nous voulons parcourir tout le document et trouver combien de fois chaque client est dans la liste, nous pourrions utiliser le document XSLT suivant : <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="listes"> <html><body><ul> <xsl:apply-templates match="*" /> </ul></body></html> </xsl:template> <xsl:template match="vendeur"> <li><p>Nom du vendeur: <xsl:value-of select="@nom" /></p> <ul><xsl:apply-templates match="*" /></ul></li> </xsl:template> <xsl:template match="client"> <li><xsl:value-of select="nom" />: <xsl:value-of select="count(//client[nom=current()/nom])" /></li> </xsl:template> </xsl:stylesheet> Le résultat de la transformation sera alors : CC BY-NC-SA Module 3 : Technologies XML 144 <html><body><ul> <li> <p>Nom du vendeur: Jean</p> <ul> <li>Jacques: 1</li> <li>Sylvain: 2</li> <li>Claude: 1</li> <li>Yvon: 2</li> </ul> </li> <li> <p>Nom du vendeur: Raymond</p> <ul> <li>Arthur: 1</li> <li>Sylvain: 2</li> <li>Claudette: 1</li> <li>Yvon: 2</li> </ul> </li> </ul></body></html> Nous verrons dans la section suivante comment faire pour ne présenter chaque client qu’une seule fois. 3.2.30 Obtenir l’aggrégation avec la fonction « generate-id » Supposons qu’on veuille calculer le total des éléments « quantite », mais en faisant l’aggrégation pour chaque valeur de l’attribut « type » dans l’exemple suivant. <?xml version="1.0" encoding="ISO-8859-1"?> <?xml-stylesheet href="produits.xsl" type="text/xsl" ?> <produits> <france> <quantite type="bain">53</quantite> <quantite type="chambre">12</quantite> </france> CC BY-NC-SA XSLT 145 <canada> <quantite type="bain">14</quantite> <quantite type="chambre">12</quantite> </canada> </produits> On pourrait tenter de résoudre ce problème avec une expression XPath de la forme « sum(//quantite[@type=current()/@type]) ». Malheureusement, on risque alors de calculer plusieurs fois la même somme. Par exemple, tentez d’appliquer la transformation suivante : <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="produits"> <html> <body> <xsl:apply-templates select="*" /> </body> </html> </xsl:template> <xsl:template match="quantite"> <p> <xsl:value-of select="@type" /> - <xsl:value-of select="sum(//quantite[@type=current()/@type])" /> </p> </xsl:template> </xsl:stylesheet> Vous obtiendrez alors le résultat suivant : <html><body> <p>bain - 67</p> <p>chambre - 24</p> <p>bain - 67</p> <p>chambre - 24</p> </body></html> Pour calculer la somme qu’une seule fois pour chaque valeur de l’attribut type, on pourrait ne faire le calcul que la première fois qu’on rencontre une valeur d’attribut CC BY-NC-SA Module 3 : Technologies XML 146 donnée. L’expression XPath « //quantite[@type=x] » représente l’ensemble des éléments quantite ayant un attribut de valeur x. L’expression « //quantite[@type=x][1] » nous donne le premier élément de ce type rencontré. On pourrait penser que l’expression XPath « //quantite[@type=x][1]=current() » permet de déterminer si le nœud courant est le premier. Malheureusement, cette expression XPath vérifie plutôt si les deux éléments ont le même contenu. Comme nous avons deux éléments quantite ayant le même contenu dans notre exemple, cette solution ne suffit pas. La fonction generate-id quant à elle associe un identifiant unique à chaque nœud d’un document XML et permet donc de distinguer les éléments entre eux même lorsqu’ils ont le même contenu. L’expression « //quantite[@type=current()/@type]) » donne la séquence de tous les éléments quantite ayant un attribut type de même valeur que l’élément courant, alors que « (//quantite[@type=current()/@type])[1] » sélectionne le premier de cette liste. On peut vérifier si l’élément « quantite » est le premier du document ayant un certain type avec la fonction « generateid » et l’expression « generate-id((//quantite[@type=current()/@type])[1]) = generateid(.) ». On peut aussi vérifier que c’est le dernier avec l’expression « generateid((//quantite[@type=current()/@type])[last()]) = generate-id(.) ». En utilisant cette astuce, on peut obtenir l’aggrégation souhaitée avec le programme XSLT suivant où l’on fait la somme seulement pour le premier élément rencontré ayant un certain type : <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="produits"> <html> <body> <xsl:apply-templates select="*" /> </body> </html> </xsl:template> <xsl:template match="quantite"> <xsl:if test="generate-id((//quantite[@type=current()/@type])[1]) = generate-id(.)" > <p> <xsl:value-of select="@type" /> - <xsl:value-of select="sum(//quantite[@type=current()/@type])" /> </p> </xsl:if> </xsl:template> </xsl:stylesheet> On peut appliquer cette technique à notre exemple de la section précédente avec les vendeurs et les clients. La transformation suivante permet de ne calculer la fréquence de chaque client qu’une seule fois. CC BY-NC-SA XSLT 147 <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="listes"> <html><body><ul> <xsl:apply-templates match="*" /> </ul></body></html> </xsl:template> <xsl:template match="vendeur"> <xsl:apply-templates match="*" /> </xsl:template> <xsl:template match="client"> <xsl:if test="generate-id(.)=generate-id(//client[nom=current()/nom][1])"> <li><xsl:value-of select="nom" />: <xsl:value-of select="count(//client[nom=current()/nom])" /></li> </xsl:if> </xsl:template> </xsl:stylesheet> Le résultat de cette transformation donne une liste désordonnée de clients : <html><body><ul> <li>Jacques: 1</li> <li>Sylvain: 2</li> <li>Claude: 1</li> <li>Yvon: 2</li> <li>Arthur: 1</li> <li>Claudette: 1</li> </ul></body></html> On peut trier le nom des clients en utilisant un élément xsl:sort : <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> CC BY-NC-SA Module 3 : Technologies XML 148 <xsl:template match="listes"> <html><body><ul> <xsl:for-each select="//client" > <xsl:sort select="nom" order="ascending" data-type="text" /> <xsl:if test="generate-id(.)=generate-id(//client[nom=current()/nom][1])"> <li><xsl:value-of select="nom" />: <xsl:value-of select="count(//client[nom=current()/nom])" /></li> </xsl:if> </xsl:for-each> </ul></body></html> </xsl:template> </xsl:stylesheet> 3.2.31 Un peu plus de performance avec la function XSLT « key » Le problème avec l’utilisation d’expressions XPath telles que //client[nom=current()/nom] est qu’elles peuvent s’avérer coûteuses en temps de calcul si on les utilisent à répétition. Afin d’accélérer les choses et simplifier un peu nos programmes, on peut créer un tableau associatif avec l’élément xsl:key et sa fonction correspondante key. Un tableau associatif est simplement une structure de donnée qui associe à chaque clef ou au plusieurs valeurs. Puisque ce tableau est construit une seule fois lorsque le processeur rencontre l’élément xsl:key, le processeur XSLT n’a pas à visiter les nœuds du document plusieurs fois. L’élément xsl:key comprend trois attributs incluant le nom du tableau associative (name), les clefs à inclure (use) et les nœuds à traiter (match). L’instruction <xsl:key name="montableau" match="client" use="nom"/> va créer un tableau associatif s’appelant montableau et qui associe à chaque valeur client/nom l’élément nom correspondant. La fonction key quant à elle prend deux paramètres incluant le nom du tableau et la valeur de la clef. À titre d’exemple, la transformation suivante permet de calculer la fréquence de chaque client comme à la question précédente, mais en utilisant un tableau associatif : <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:key name="montableau" match="client" use="nom"/> <xsl:template match="listes"> <html><body><ul> <xsl:for-each select="//client" > <xsl:sort select="nom" order="ascending" data-type="text" /> <xsl:if test="generate-id(.)=generate-id(key(’montableau’,nom)[1])"> <li><xsl:value-of select="nom" />: <xsl:value-of select="count(//client[nom=current()/nom])" /></li> </xsl:if> </xsl:for-each> CC BY-NC-SA XSLT 149 </ul></body></html> </xsl:template> </xsl:stylesheet> 3.2.32 Les variables Il est possible, en XSLT, de définir des variables, mais elles sont « immutables » (« dont la valeur ne peut être modifiée »). On peut se demander, à juste titre, si les mots variables et immutables vont bien ensemble, mais c’est ainsi que les inventeurs du XSLT se sont exprimés. Pour définir une variable nommée « test », on utilise l’élément « <xsl:variable name="test" select="xxx" /> ». La variable contiendra alors le résultat de l’expression XPath contenue dans l’attribut « select ». L’exemple suivant peut être utilisé pour afficher le contenu de tous les éléments « produit » immédiatement contenus dans l’élément racine. <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:variable name="test" select="/" /> <xsl:template match="$test/produit"> <xsl:value-of select="*" /> </xsl:template> </xsl:stylesheet> On peut aussi définir la valeur de la variable en omettant l’attribut « select » et en ajoutant du contenu à l’élément « xsl:variable ». Ce contenu pourrait comprendre du XSLT. <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:variable name="test" > <produit>x</produit> </xsl:variable> <xsl:template match="$test/produit"> <xsl:value-of select="*" /> </xsl:template> </xsl:stylesheet> On peut déclarer la variable localement au sein d’un élément template : <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> CC BY-NC-SA Module 3 : Technologies XML 150 <xsl:template match="/"> <xsl:variable name="test" > <produit>x</produit> </xsl:variable> <xsl:value-of select="$test" /> </xsl:template> </xsl:stylesheet> 3.2.33 Les paramètres Un fichier XSLT peut être utilisé comme un programme dans la mesure où on peut lui passer des paramètres. Rappelons qu’on appelle un fichier XSLT « xslt.xml » à partir d’un fichier XML qu’on veut transformer de cette manière : <?xml version="1.0" encoding="ISO-8859-1" ?> <?xml-stylesheet href="xslt.xml" type="application/xml"?> <facture> <montant>10.10</montant> <personne>Jean Rochond</personne> <raison>Achat d’ordinateur</raison> </facture> On peut enrichir cet appel avec les instructions « xslt-param » comme dans cet exemple. <?xml version="1.0" encoding="ISO-8859-1" ?> <?xslt-param name="couleur" value="blue"?> <?xslt-param name="taille" value="2"?> <?xml-stylesheet href="xslt.xml" type="application/xml"?> <facture> <montant>10.10</montant> <personne>Jean Rochond</personne> <raison>Achat d’ordinateur</raison> </facture> Selon votre processeur XSLT, il peut y avoir d’autres façons de passer des paramètres à une feuille de style XSLT. On reçoit alors les paramètres avec un élément « xsl:param ». L’attribut « select » est utilisé pour spécifier une valeur par défaut. <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> CC BY-NC-SA XSLT 151 <xsl:param name="couleur" select="red"> <xsl:param name="taille" select="1"> <xsl:template match="facture"> <html> <head> <title>Facture de <xsl:value-of select="personne" /></title> </head> <body> <p style="color:{$couleur}; font-size:{$taille}em">Ceci est une facture pour <xsl:value-of select="personne" /> de <xsl:value-of select="montant" />$ pour: <xsl:value-of select="raison" />.</p> </body> </html> </xsl:template> </xsl:stylesheet> On peut aussi passer des paramètres aux éléments « xsl:template » avec les éléments « xsl:call-template » comme dans cet exemple qui est une façon équivalente, mais plus compliquée, de formater notre document XML de type « facture » . <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template name="facture"> <xsl:call-template name="monmotif"> <xsl:with-param name="title" select="."/> </xsl:call-template> </xsl:template> <xsl:template name="monmotif"> <xsl:param name="contenu" /> <html> <head> <title>Facture de <xsl:value-of select="$contenu/personne" /></title> </head> <body> <p>Ceci est une facture pour <xsl:value-of select="$contenu/personne" /> de <xsl:value-of select="$contenu/montant" />$ pour: <xsl:value-of select="$contenu/raison" />.</p> </body> </html> CC BY-NC-SA Module 3 : Technologies XML 152 </xsl:template> </xsl:stylesheet> On peut aussi charger des documents distants avec la fonction XSLT « document » , cette instruction donne une copie du document situé à l’adresse @href : <xsl:copy-of select="document(@href)"/>. (L’élément « xsl:copy-of » sert ici à faire une copies des nœuds contenus dans le document distant.) Elle est cependant sujette à des contraintes de sécurité lorsqu’on l’utilise dans un navigateur : il n’est pas permis de charger des documents provenant d’autres serveurs que le serveur d’origine. 3.2.34 Générer un commentaire Il arrive qu’on veuille produire un commentaire dans la sortie XML. Rien de plus simple ! Il suffit d’utiliser l’instruction xsl:comment comme dans cet exemple : <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:comment>Ceci est un commentaire.</xsl:comment> </xsl:stylesheet> Le résultat devrait ressembler à ceci : <?xml version="1.0" encoding="ISO-8859-1"?> <!--Ceci est un commentaire.--> 3.2.35 Créer des éléments dynamiquement avec « xsl:element » Il est parfois utile de créer dynamiquement un élément avec « xsl:element » et de créer des attributs avec « xsl:attribute ». Dans l’exemple suivant, on va créer un élément dont le nom nous est fourni par un paramètre. <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:param name="ele" select="p"> <xsl:template match="/"> <xsl:element name="{$ele}" namespace="http://mondom.com/" > <xsl:attribute name="couleur" namespace="http://mondom.com/"> bleu </xsl:attribute> CC BY-NC-SA XSLT 153 </xsl:element> </xsl:template> </xsl:stylesheet> 3.2.36 Copier des nœuds avec « xsl:copy » et « xsl:copy-of » Il est parfois nécessaire de dire au XSLT qu’on souhaite tout simplement recopier le nœud courant dans le document sortant. L’élément « xsl:copy » copie l’élément (seul, sans ses attributs mais avec son espace de noms) alors que l’élément « xsl:copy-of » permet de copier un élément ainsi que tous les nœuds qu’il contient. XSLT ne transforme pas les nœuds ainsi copiés, ils sont insérés dans le résultat directement. Par exemple, ce document XSLT va créer une copie intégrale du document: <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="xml" version="1.0" indent="yes" encoding="ISO-8859-1"/> <xsl:template match="/"> <xsl:copy-of select="." /> </xsl:template> </xsl:stylesheet> Dans le cas où l’on sélectionne plus d’un élément, notamment avec une expression du type nom|prenom, tous les éléments sont copiés l’un après l’autre. Ce comportement diffère de l’instruction value-of qui n’extrait le contenu textuel que du premier élément rencontré. Par contre, si on ne souhaite qu’un document XML qui contient le même élémentracine, mais sans le contenu de l’élément racine, on utilisera plutôt un élément « xsl:copy », comme ceci : <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="xml" version="1.0" indent="yes" encoding="ISO-8859-1"/> <xsl:template match="/*"> <xsl:copy/> </xsl:template> </xsl:stylesheet> Naturellement, on peut même définir le contenu de l’élément copié à l’aide d’un modèle : CC BY-NC-SA Module 3 : Technologies XML 154 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="xml" version="1.0" indent="yes" encoding="ISO-8859-1"/> <xsl:template match="/*"> <xsl:copy > <a>x</a> </xsl:copy> </xsl:template> </xsl:stylesheet> Si on souhaite ne copier qu’une partie du contenu de l’élément ainsi reproduit, par exemple ses attributs, on peut utiliser copy-of : <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="xml" version="1.0" indent="yes" encoding="ISO-8859-1"/> <xsl:template match="/*"> <xsl:copy > <xsl:copy-of select="@*"/> <a>x</a> </xsl:copy> </xsl:template> </xsl:stylesheet> 3.2.37 Union, intersection et différence en XSLT Nous avons vu que le symbole « | » nous permet d’obtenir l’union de deux expressions XPath. Prenons l’exemple de ce document : <x> <a s="1" <b s="1" <c s="0" <d s="0" </x> t="0" t="1" t="1" t="0" /> /> /> /> L’expression « //*[@s="1"] » représente les éléments a et b, l’expression « //*[@t="1"] » représente les éléments b et c, alors que l’expression « //*[@s="1"]|//*[@t="1"] » représente les éléments a,b,c (une union de « //*[@s="1"] » et « //*[@t="1"] »). CC BY-NC-SA XSLT 155 Supposons maintenant que nous désirions obtenir les éléments qui satisfont « @s="1" » et « @t="1" » : on veut calculer l’intersection entre « //*[@s="1"] » et « //*[@t="1"] ». On pourrait, bien sûr, obtenir ce résultat avec « //*[@s="1" and @t="1"] », mais il existe une autre façon de le faire qui est d’application plus générale. Supposons que les résultats des expressions « //*[@s="1"] » et « //*[@t="1"] » sont déjà stockés dans les variables a1 et a2 respectivement. Alors l’expression « $a1[count(.|$a2)=count($a2)] » sélectionne l’élément b (ou « //*[@s="1" and @t="1"] »). Ce motif particulier calcule l’intersection entre le contenu des variables a1 et a2. Pour le comprendre, il suffit de réaliser que la condition « count(.|$a2)=count($a2) » n’est vraie que pour les nœuds appartenant déjà à l’ensemble a2. Supposons maintenant que l’on souhaite trouver les éléments qui satisfont « @s="1" » mais pas « @s="1" », c’est-à-dire l’élément a. En fait, on souhaite calculer la différence entre deux ensembles (« //*[@s="1"] » et « //*[@t="1"] »). On pourrait obtenir ce résultat avec l’expression « //*[@s="1" and not(@t="1")] », mais encore une fois, il existe un motif plus général: « $a1[count(.|$a2)!=count($a2)] » ou « //*[@s="1"][count(.|//*[@t="1"])!=count(//*[@t="1"])] ». Pour comprendre cette expression, il suffit de réaliser que si et seulement si un nœud x n’appartient pas à a2, alors l’expression « count(x|$a2)!=count($a2) » sera vraie. 3.2.38 Espaces de noms Les espaces de noms sont supportés et ne posent pas de problème. Il suffit de définir les préfixes, comme on le fait habituellement. Par exemple, considérons le code XML suivant : <?xml version="1.0" encoding="ISO-8859-1" ?> <?xml-stylesheet href="class2.xsl" type="text/xsl" ?> <université> <étudiant> <n:nom xmlns:n="http://www.mondomaine.com/">Réjean Tremblay</n:nom> </étudiant> </université> Pour afficher le nom de l’étudiant, il suffira d’utiliser le document XSLT suivant : <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:n="http://www.mondomaine.com/"> <xsl:template match="université" > <html><body> <xsl:apply-templates match="étudiant/n:nom" /> </body></html> </xsl:template> CC BY-NC-SA Module 3 : Technologies XML 156 <xsl:template match="n:nom" > <p><xsl:value-of select="." /></p> </xsl:template> </xsl:stylesheet> Observons que l’attribut « match="nom" » ne s’applique pas à l’élément « nom » dans l’espace de noms « http://www.mondomaine.com/ », tel qu’il apparaît dans notre document XML : il est obligatoire d’utiliser un préfixe correspondant au bon espace de noms. Tout comme « match="*" » permet de sélectionner tous les éléments, « match="n:*" » permet de sélectionner tous les éléments qui sont dans un espace de noms donné. 3.2.39 Les axes Par défaut, l’expression XPath « nom » désigne les éléments « nom » qui sont des enfants du nœud courant. On peut aussi écrire « child::nom ». De la même manière, « nom[2] » ou « child::nom[2] » désigne le second enfant du nœud courant. Il est possible de changer ce comportement en choisissant un axe différent. – « child » : il s’agit de l’axe par défaut, « child::nom[3] » désigne le troisième élément « nom » enfant du nœud courant. – « parent » : l’axe « parent » est pratiquement inutile, « parent::nom » désigne l’élément parent si celui-ci se nomme « nom ». En général, il est plus simple d’utiliser la syntaxe « .. » qui est équivalente à « parent::node() ». – « attribute » : la syntaxe « attribute:: » n’est pas utilisée, on préfère la notation « @nom » qui signifie la même chose que « attribute::nom ». – « ancestor » : la syntaxe « ancestor::nom » désigne les éléments de nom « nom » dans lesquels le nœud courant est contenu. On peut tester si le nœud courant est contenu dans un paragraphe avec la syntaxe <xsl:if test="ancestor::paragraphe">...</xsl:if>. – « ancestor-or-self » : idem que l’axe ancestor exception faite que l’on inclut le nœud courant, on pourrait donc tester si nœud courant est contenu dans un paragraphe ou s’il est lui-même un paragraphe avec la syntaxe <xsl:if test="ancestor-orself::paragraphe">...</xsl:if>. – « preceding-sibling » : cet axe consulte en séquence les frères du nœud courant, c’est-à-dire les nœud ayant le même parent, qui apparaissent avant le nœud courant. Par exemple, « preceding-sibling::nom[2] » cherche le second élément-frère apparaissant avant le nœud courant. – « following-sibling » : voir l’axe « preceding-sibling », mais à l’envers (après le nœud courant). – « preceding » : cet axe est similaire à « preceding-sibling », mais on traverse tous les nœuds qui se sont terminés avant nœud courant. Par exemple, « preceding::nom[2] » cherche le second élément apparaissant avant le nœud courant, même s’il n’a pas le même parent. CC BY-NC-SA XSLT 157 – « following » : voir l’axe « preceding », mais à l’envers. – « descendant » : voir l’axe « ancestor », mais à l’envers. – « descendant-or-self » : voir l’axe « ancestor-or-self », mais à l’envers. 3.2.40 L’étude d’un exemple: docbook.xslt Lors du travail 3, je vous ai demandé d’utiliser un fichier XSLT appelé docbook.xslt qui transforme des documents DocBook simple en HTML. Vous êtes maintenant en mesure d’analyser et de comprendre cet exemple. Nous allons passer en revue brièvement les éléments « xsl:template » qu’il contient. Le premier élément « xsl:template » sert à capturer l’élément « book ». Comme il s’agit de l’élément-racine, on en profite pour produire les éléments « html », « head » et « body ». Le contenu de l’élément « head » sera rempli par l’élément « xsl:template » traitant l’élément DocBook « bookinfo ». On affiche immédiatement le prénom et le nom de l’auteur à l’aide des expressions XPath « bookinfo/author/firstname » et « bookinfo/author/surname ». Notez l’utilisation de l’élément <xsl:text> </xsl:text> pour produire un espace entre le nom et le prénom. En effet, sans cet élément, il n’y aurait pas d’espace puisque les espaces et retours de charriot sont ignorés dans les fichiers XSLT. Le reste du document est produit avec les deux éléments « xsl:template » traitant les éléments « chapter » : on utilise le l’attribut mode « tdm » pour produire la table des matières, et le reste du document est produit avec le traitement des éléments « chapter » par défaut (sans attribut mode). <xsl:template match="book"> <html> <head><xsl:apply-templates select="bookinfo"/></head> <body><h1><xsl:value-of select="bookinfo/title" /></h1> <p style="text-indent:1em;"> <xsl:value-of select="bookinfo/author/firstname" /> <xsl:text> </xsl:text> <xsl:value-of select="bookinfo/author/surname" /> © <xsl:value-of select="bookinfo/copyright/year" /> </p><h2>Table des matières</h2> <ul><xsl:apply-templates select="chapter" mode="tdm"/></ul> <xsl:apply-templates select="chapter"/> </body></html> </xsl:template> L’élément « xsl:template » traitant l’élément DocBook « bookinfo » est simple : l’expression XPath « title » permet de trouver le titre du document puisqu’un élément « title » doit être présent dans tout élément DocBook « bookinfo ». Comme on l’a fait précédemment, on trouve le prénom et le nom de l’auteur, mais cette fois-ci, avec les expressions XPath « author/firstname » et « author/surname » puisque nous sommes maintenant au sein d’un élément « bookinfo ». <xsl:template match="bookinfo"> CC BY-NC-SA Module 3 : Technologies XML 158 <title><xsl:value-of select="title" /> par <xsl:value-of select="author/firstname" /><xsl:text> </xsl:text><xsl:value-of select="author/surname" /> </title> </xsl:template> Les élément « xsl:template » avec attribut mode génèrent la table des matières. Les éléments « xsl:number » permettent de numéroter automatiquement les chapitres et sections. Afin de générer des hyperliens permettant de naviguer dans le document à partir de la table des matières, on utilise des fragments générés à partir de la fonction XSLT « generate-id ». Lorsque nous générons le contenu du document lui-même, on utilise à nouveau la fonction XSLT « generate-id » pour placer des ancres dans le document au bon endroit. L’avantage de la fonction XSLT « generate-id » est qu’elle permet de générer facilement un identifiant unique pour chaque paragraphe. <xsl:template match="chapter" mode="tdm"> <li><a href="#{generate-id(.)}"> <xsl:number format="digit" lang="fr" count="chapter"/>. <xsl:value-of select="title" /></a></li> <ul><xsl:apply-templates select="section" mode="tdm"/></ul> </xsl:template> <xsl:template match="section" mode="tdm"> <li><a href="#{generate-id(.)}"> <xsl:number format="digit" lang="fr" count="chapter"/>. <xsl:number format="digit" lang="fr" count="section"/> <xsl:text> </xsl:text> <xsl:value-of select="title" /></a></li> </xsl:template> Les élément « xsl:template » sans attribut mode génèrent le document lui-même. La principale différence avec la génération de la table des matières est la présence de l’élément <xsl:apply-templates/> qui traite le contenu des éléments « section ». <xsl:template match="chapter"> <h2><a name="{generate-id(.)}" >Chapitre <xsl:number format="digit" lang="fr" count="chapter"/>.<xsl:text> </xsl:text> <xsl:value-of select="title" /></a></h2> <div style="margin-left:1em"> <xsl:apply-templates select="section"/> </div> </xsl:template> <xsl:template match="section"> <h3><a name="{generate-id(.)}"> CC BY-NC-SA XSLT 159 <xsl:number format="digit" lang="fr" count="chapter"/>. <xsl:number format="digit" lang="fr" count="section"/> <xsl:text> </xsl:text> <xsl:value-of select="title" /></a></h3> <div style="margin-left:1em"> <xsl:apply-templates/> </div> </xsl:template> Le traitement des éléments DocBook « itemizedlist », « orderedlist » et « listitem » est simple : il suffit de les convertir en éléments HTML « ul », « ol » et « li » respectivement. <xsl:template match="itemizedlist"> <ul style="margin-left:1em"><xsl:apply-templates /></ul> </xsl:template> <xsl:template match="orderedlist"> <ol style="margin-left:1em"><xsl:apply-templates /></ol> </xsl:template> </xsl:stylesheet> <xsl:template match="listitem"> <li style="text-indent:0.5em"><xsl:apply-templates /></li> </xsl:template> Les éléments DocBook « programlisting » sont convertis en éléments HTML « pre » (préformaté). <xsl:template match="programlisting"> <pre style="color:blue;background-color:rgb(200,200,200); margin-left:1em"> <code> <xsl:apply-templates /> </code></pre> </xsl:template> Les éléments DocBook « para » sont convertis en éléments HTML « p » sauf lorsqu’ils sont au sein d’un élément DocBook « listitem ». <xsl:template match="para"> <xsl:choose> <xsl:when test="name(..) = ’listitem’"> <xsl:apply-templates /></xsl:when> <xsl:otherwise><p><xsl:apply-templates /></p> </xsl:otherwise> CC BY-NC-SA Module 3 : Technologies XML 160 </xsl:choose> </xsl:template> </xsl:stylesheet> Les éléments DocBook « title » ne doivent pas être traités directement lorsqu’on les rencontre. <xsl:template match="title" /> Comme vous pouvez le constater, en décomposant un document XSLT complexe, on arrive facilement à en expliquer le fonctionnement. C’est d’ailleurs un avantage de la programmation déclarative de pouvoir être ainsi décomposée et expliquée. 3.2.41 Activité suggérée Essayez de refaire les exemples avec le moteur XSLT de Firefox. Vous devrez ajouter les éléments « html » et « body » lorsqu’ils ont été omis. Essayez également de modifier les exemples pour vous assurer d’avoir bien compris. Enfin, pour mieux comprendre le XSLT, faites quelques exercices exploratoires. Vous pouvez consulter les articles de mozilla.org sur XSLT (http://developer.mozilla.org/en/ docs/XSLT) et XPath (http://developer.mozilla.org/en/docs/XPath). Pour avoir une vue d’ensemble, consultez le pense-bête XSLT. 3.2.42 Autres moteurs XSLT Votre navigateur supporte XSLT, mais si vous désirez un moteur XSLT qui ne dépende pas d’un navigateur, je vous suggère 4Suite (http://www.4suite.org/) ou Xalan (http:// xml.apache.org/xalan-j/). Si vous avez le temps d’installer un tel moteur, vous pourrez sans doute plus rapidement faire les travaux et refaire les exemples de cette leçon, mais l’utilisation de Firefox est suffisante. 3.2.43 Pour voir le résultat de la transformation XSLT Avec Firefox .2.0 ou mieux, on peut voir le résultat de la transformation XSLT en enregistrant le fichier: il faut aller dans le menu « Fichier » puis sélectionner « Enregistrez sous ». Normalement, on pourra alors enregistrer le fichier XML en fichier HTML (si la transformation donne un fichier HTML). On peut ouvrir le fichier HTML avec un éditeur comme Bloc-note pour voir le résultat. CC BY-NC-SA XSLT 3.2.44 161 SVG et XSLT Une des applications intéressantes du XSLT est de transformer un document en image. Par exemple, étant donné les données d’une entreprise, on pourrait automatiquement générer un histogramme en SVG. 3.2.45 XPath, XPointer et XLink En présentant le XSLT, nous avons couvert les expressions XPath qui nous permettent de sélectionner des nœuds dans des documents XML. D’autres technologies XML utilisent XPath comme XLink et XPointer. XPointer est tout simplement une façon d’ajouter à un URI une expression XPath pour permettre de représenter un lien vers une partie d’un document XML. On ajoute un fragment de la forme « #xpointer(...) » à l’URI où les trois petits points sont remplacés par une expression XPath. Par exemple, si vous voulez représenter le premier élément « cours » d’un document XML, vous pouvez utiliser la syntaxe « http://x.com/doc.xml#xpointer(//cours[1]) ». Si vous omettez l’URI, par défaut, le document XML dans lequel se trouve l’expression XPointer est sélectionné. Les navigateurs ne supportent pas encore correctement XPointer. XLink est une généralisation des hyperliens du HTML pouvant être utilisé dans tous les documents XML. On utilise XLink surtout pour mettre des hyperliens dans des images SVG. L’espace de noms pour XLink est « http://www.w3.org/1999/xlink » et on l’utilise surtout avec l’attribut « href ». Dans la figure SVG suivante, le texte « INF 6450 » est un hyperlien vers l’URI « http://www.teluq.ca/inf6450 ». Voici le code de la figure. <?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg width="300" height="300" version="1.1" xmlns="http://www.w3.org/2000/svg"> <rect x="0" y="0" width="300" height="300" stroke="black" fill="red"/> <circle cx="150" cy="150" r="150" stroke="black" fill="yellow"/> <a xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.teluq.ca/inf6450"> <text x="150" y="150" style="text-anchor: middle">INF 6450</text> </a> <line x1="0" y1="0" x2="300" y2="300" style="stroke:rgb(99,99,99);"/> <line x1="300" y1="0" x2="0" y2="300" style="stroke:rgb(99,99,99);"/> CC BY-NC-SA Module 3 : Technologies XML 162 </svg> Voici le rendu de la figure dans votre navigateur avec l’hyperlien. 3.2.46 XPath 2.0 Une nouvelle version de XPath est disponible (XPath 2.0). À part quelques exceptions, tout ce qui fonctionnait en XPath 1.0, fonctionne toujours en XPath 2.0. Cependant, XPath 2.0 ajoute de nombreuses fonctions et opérateurs qui simplifient la vie du programmeur tels que empty, exists, intersect, except (pour calculer le complément), deep-equal (pour tester l’égalité entre deux séquences), index-of, reverse, subsequence, insert-before, remove, distinct-values, avg, max, min, etc. Alors que XPath 1.0 ne traite que des nombres, des chaînes de caractères, des valeurs booléennes et des ensembles de nœuds, XPath 2.0 introduit la notion de séquence et plusieurs autres types de données pour noter les notes, la durée, les entiers, les nombres à virgule flottante, etc. XPath 2.0 supporte aussi les expressions régulières avec les fonctions matches, replace, et tokenize. XPath 2.0 intègre maintenant la fonction « document » qui était une fonction XSLT. XPath 2.0 comprend maintenant un syntaxe if/then/else comme dans cet exemple : « if ( @sexe eq ’m’ ) then ’Monsieur’ else ’Madame’ ». On peut aussi utiliser des boucles : CC BY-NC-SA XSLT 163 « for $i in //etudiant return $i/note ». On peut vérifier si au moins un (some) ou tous (every) les éléments d’une séquence satisfont une condition: « every $i in //etudiant satisfies $i/note > 0 » ou « some $i in //etudiant satisfies $i/note < 100 ». En somme, XPath 2.0 permet d’effectuer plusieurs traitement qui n’étaient possible qu’avec des instructions XSLT auparavant. 3.2.47 XLT 2.0 Une nouvelle version du XSLT est disponible, nommée XLT 2.0. Elle ajoute notamment la possibilité de générer plusieurs documents plutôt qu’un seul avec l’instruction xslt:result-document. On peut aussi traiter non seulement des fichiers XML, mais aussi d’autres types de fichiers dont les fichiers CSV (comma-separated values) générés par les chiffriers électroniques et bases de données. L’instruction « xsl:analyze-string » permet de prendre appui sur les nouvelles possibilités du traitement des chaînes de caractères de XPath 2.0. L’instruction « xsl:function » permet quant à elle de définir de nouvelles fonctions qui pourront être utilisées au sein des expressions XPath. L’instruction « xsl:for-each-group » permet de visiter les nœuds par groupes : on peut ainsi visiter tous les éléments etudiant en les regroupant selon la valeur de leur attribut nom. Elliotte Rusty Harold a publié une page sur XSLT 2.0 qui présente quelques exemples. 3.2.48 XQuery XSLT peut servir pour extraire des informations d’un document XML. On peut trouver tous les noms des étudiants répondant à certains critères. Dans un sens, XSLT peut être utilisé comme langage dans le contexte des bases de données. Cependant, pour cette fin spécifique, un nouveau langage appelé XQuery a été proposé. La syntaxe du XQuery est un mélange de XPath et de SQL et ressemble davantage à ce que les spécialistes des bases de données connaissent bien. Pour tester les requêtes XQuery, Saxon est un outil pratique écrit en java. Pour utiliser Saxon, chargez d’abord le fichier saxon9.jar. Vous devez mettre votre requête XQuery dans un fichier texte (tel que « query ») et invoquez Saxon comme ceci : java -cp saxon9.jar net.sf.saxon.Query query Dans cet exemple, il faut que les fichiers saxon9.jar et query soient dans le dossier où vous lancez la commande. Le fichier query doit contenir une requête XQuery. Une requête XQuery n’est pas du XML. Pour rendre nos exemples plus concrets, supposez que le fichier qui se trouve à l’URI http://universite.com/etu.xml soit celui-ci : <liste> <etudiant> <nom>Laroche</nom> <prenom>Pierre</prenom> CC BY-NC-SA Module 3 : Technologies XML 164 <statut>inscrit</statut> <cours> <sigle>INF 6460</sigle> <note>54</note> </cours> <cours> <sigle>INF 6450</sigle> <note>44</note> </cours> </etudiant> <etudiant> <nom>Aaron</nom> <prenom>Jean</prenom> <statut>inscrit</statut> <cours> <sigle>INF 6460</sigle> <note>56</note> </cours> <cours> <sigle>INF 6450</sigle> <note>46</note> </cours> </etudiant> <etudiant> <nom>Pouf</nom> <prenom>Jean</prenom> <statut>non-inscrit</statut> </etudiant> </liste> Vous pouvez créer un fichier etu.xml sur votre disque dans le même dossier que le fichier query, et remplacer partout l’URI par le nom du fichier (tel que « etu.xml »). Parce que XQuery, tout comme XSLT 2.0, s’appuie sur XPath 2.0, il est facile de calculer la liste des cours : for $s in distinct-values(doc("etu.xml")//sigle) return $s Cette requête donnera « INF 6460 INF 6450 ». Voici un exemple de requête XQuery pour extraire d’un document XML tous les étudiants inscrits : <maliste> {let $inscription := "inscrit" for $b in doc("http://universite.com/etu.xml")/liste/etudiant where $b/statut = $inscription order by $b/nom ascending CC BY-NC-SA XSLT 165 return <etudiant> { $b/prenom } { $b/nom } </etudiant>} </maliste> Cet exemple est une requête de type FLWOR parce qu’elle ne contient que des instructions « for », « let », « where », « order by », et « return ». L’instruction « for » sert à définir une boucle, l’instruction « where » sert à poser une condition, l’instruction « order by » permet de trier le résultat, alors que l’instruction « return » définit le résultat. L’instruction « let » permet de définir une constante. Notez que XQuery utilise les accolades pour distinguer les requêtes XQuery et XPath du texte. La requête considère tous les éléments etudiant contenus dans l’élément-racine liste, pour chacun d’entre eux, elle vérifie qu’il contient un élément statut contenant le texte « inscrit », puis elle donne la liste des noms et prénoms triée selon le nom. Voici quel sera le résultat : <maliste> <etudiant> <prenom>Jean</prenom> <nom>Aaron</nom> </etudiant> <etudiant> <prenom>Pierre</prenom> <nom>Laroche</nom> </etudiant> </maliste> On peut attribuer un compteur aux nœuds : <maliste> { for $b at $pos in doc("http://universite.com/etu.xml")/liste/etudiant order by $b/nom descending return <etudiant> $pos { $b/prenom } { $b/nom } </etudiant> } </maliste> Le résultat sera alors : <maliste> <etudiant>3<prenom>Jean</prenom> <nom>Pouf</nom> </etudiant> <etudiant>1CC BY-NC-SA Module 3 : Technologies XML 166 <prenom>Pierre</prenom> <nom>Laroche</nom> </etudiant> <etudiant>2<prenom>Jean</prenom> <nom>Aaron</nom> </etudiant> </maliste> On peut combiner les requêtes FLWOR, comme dans cet exemple : <maliste> {for $e in doc("http://universite.com/etu.xml")//etudiant return <etudiant nom="{$e/nom}"> { for $v in $e/cours return <note>{number($v/note)}</note> } </etudiant> } </maliste> Cette requête va considérer chaque élément etudiant du document XML et créer une liste de notes obtenues pour cet étudiant, dans ce cas, le résultat sera : <maliste> <etudiant nom="Laroche"> <note>54</note> <note>44</note> </etudiant> <etudiant nom="Aaron"> <note>56</note> <note>46</note> </etudiant> <etudiant nom="Pouf"/> </maliste> L’expression suivante va calculer la moyenne de notes (50) : <maliste> avg( for $n in doc("http://universite.com/etu.xml")//note return $n ) </maliste> Par défaut, les documents XQuery utilisent le jeu de caractères Unicode UTF-8. On peut stipuler un jeu de caractères différent dans la déclaration XQuery optionnelle comme dans cet exemple : CC BY-NC-SA CSS 167 xquery version "1.0" encoding "utf-8"; for $s in distinct-values(doc("etu.xml")//sigle) return $s Certains moteurs de bases de données comme MonetDB ou eXist supportent les requêtes XQuery. Il y a aussi d’excellents tutoriels sur le web. Elliotte Rusty Harold nous offre une excellente page sur XQuery qui résume bien les points essentiels avec des exemples. 3.2.49 XPath versus XSLT Les expressions XPath sont très utilisées en XSLT. Apprendre le XSLT, c’est aussi apprendre XPath. Par contre, tout ce qui ressemble à une expression XPath, n’est pas nécessairement une expression XPath. Par exemple, les fonctions current, document, generate-id et key sont des fonctions XSLT qui ne sont pas disponibles en XPath, mais qui s’utilisent au sein des expressions XPath. On peut aussi utiliser les expressions XPath en Java, en ECMAScript, avec XQuery, etc. Avec XSLT 2.0, il est possible de définir ses propres fonctions qui s’utilisent au sein des expressions XPath. 3.2.50 En terminant Le langage XSLT est beaucoup plus riche que ce que nous venons de vous présenter. Nous pouvons pratiquement tout faire avec le XSLT. En fait, le XSLT est un langage complet (au sens de Turing) et, en principe, tout ce qui peut être fait comme transformation en Java, peut être fait en utilisant le XSLT. En pratique, le XSLT est particulièrement approprié si nous voulons faire des transformations simples. Il est aussi possible d’utiliser le XSLT pour résoudre automatiquement des problèmes intéressants. Supposons que vous deviez communiquer avec une institution qui utilise aussi le XML, mais avec des fichiers XML légèrement différents. Il est possible qu’une simple transformation XSLT permette de transformer les fichiers XML de l’autre institution en des fichiers similaires aux vôtres. Le XSLT peut sembler un peu déroutant, mais il faut simplement prendre de l’expérience avec ce type de programmation. 3.2.51 Livres de référence – Sal Mangano, XSLT Cookbook, O’Reilly Media, 2006, 751 pages. – Jeni Tennison, Beginning XSLT, Apress, 2004, 800 pages. CC BY-NC-SA Module 3 : Technologies XML 3.3 3.3.1 168 CSS Objectif Utiliser des transformations XSLT et des instructions CSS. 3.3.2 Activité Lisez le texte qui suit, puis répondez au questionnaire d’autoévaluation. Ce texte porte sur les CSS (Cascading StyleSheets). 3.3.3 Qu’est-ce que les CSS La norme CSS a d’abord été proposée par Håkon Lie du CERN en Suisse en 1994 (environ 4 ans après l’apparition de la première page web). Cette norme a été acceptée comme recommandation officielle du W3C deux ans plus tard, soit en 1996, et la seconde version (CSS 2.0) est devenue une recommandation du W3C l’année suivante, soit en 1997. Une troisième version est en développement. À l’origine, les instructions CSS étaient destinées uniquement à indiquer aux navigateurs comment présenter le HTML (couleurs, polices, etc.); on s’est vite rendu compte qu’on pouvait aussi l’appliquer au XML et on considère maintenant les CSS comme une technologie qui s’applique autant au HTML qu’au XML (et aussi, évidemment, au XHTML). Nous avons vu que le XSLT permettait de transformer du XML en HTML pour l’affichage dans un navigateur. En général, le XSLT permet de transformer tout document XML en un autre format (HTML, XML ou autre). Un fichier CSS est beaucoup plus limité dans la mesure où il ne transforme pas le document XML. Il permet seulement de spécifier comment le contenu du document XML sera affiché. Le fichier XSLT est un outil de transformation, alors que le fichier CSS est un outil de formatage. Un document CSS permet de rendre un document XML plus lisible. D’un autre côté, le fichier CSS permet de contrôler avec beaucoup de finesse la présentation du document XML, alors qu’il peut être difficile et fastidieux d’obtenir le même résultat en XSLT, sans utiliser les CSS. Les fichiers CSS tendent aussi à être plus simples que les fichiers XSLT; il peut donc être plus facile de les modifier et de les garder à jour. Finalement, on peut utiliser à la fois des fichiers CSS et des fichiers XSLT, en combinant les avantages des deux (présentation et transformation). 3.3.4 Point de vue critique CSS est un langage déclaratif relativement limité. Il n’est pas possible de définir des variables, des fonctions ou de faire de l’arithmétique en CSS. On peut, par contre, CC BY-NC-SA CSS 169 redéfinir à volonté des règles, ce qui peut rendre le comportement final difficile à comprendre pour un humain. Il n’est pas facile, en CSS, de détecter le navigateur utilisé alors que tous les navigateurs ne traitent pas les règles de la même façon. 3.3.5 Notions de base Pour l’essentiel, le langage CSS prend la forme d’une succession d’affirmations de la forme élément propriété: valeur; autrepropriété: valeur;. Il s’agit d’une syntaxe très simple. Supposons un document XML comme celui-ci : <?xml version="1.0" encoding="ISO-8859-1" ?> <comptearecevoir> <facture> <personne>Jean Rochond</personne> <montant>10.10</montant> <raison>Achat d’ordinateur</raison> </facture> <facture> <personne>Madeleine Bédard</personne> <montant>20.10</montant> <raison>Achat d’un crayon</raison> </facture> </comptearecevoir> Certains navigateurs affichent le XML brut sans formatage, ce qui n’est pas très accessible. D’autres navigateurs affichent le document sans les balises : Jean Rochond 10.10 Achat d’ordinateur Madeleine Bédard 20.10 Achat d’un crayon Ce document XML est difficile à lire, même sans les balises, surtout si vous n’êtes pas un expert en XML. Sans le transformer, il est possible de l’afficher avec de la couleur ou de l’italique, comme ceci : – Jean Rochond 10.10 Achat d’ordinateur – Madeleine Bédard 20.10 Achat d’un crayon CC BY-NC-SA Module 3 : Technologies XML 170 Voilà qui est nettement plus lisible! Nous pouvons obtenir ce résultat à l’aide du fichier CSS suivant : facture { display: block; margin-bottom: 30pt; } montant { color: red; } raison { display: block; font-style: italic; margin-left: 1cm; } Pour vérifier que c’est bien le cas, il suffit de créer un fichier « chap12.css » avec le contenu CSS précédent et de modifier le fichier XML en y ajouter une ligne pointant vers le fichier CSS (<?xml-stylesheet type="text/css" href="chap12.css"?>), comme ceci : <?xml version="1.0" encoding="ISO-8859-1" ?> <?xml-stylesheet type="text/css" href="chap12.css"?> <comptearecevoir> <facture> <personne>Jean Rochond</personne> <montant>10.10</montant> <raison>Achat d’ordinateur</raison> </facture> <facture> <personne>Madeleine Bédard</personne> <montant>20.10</montant> <raison>Achat d’un crayon</raison> </facture> </comptearecevoir> Si le fichier XML est dans le même répertoire que le fichier CSS, Firefox devrait vous présenter le document XML avec le montant en rouge et le commentaire (raison) en italique, comme nous l’avons présenté plus haut. Examinons maintenant les différentes instructions du fichier CSS. CC BY-NC-SA CSS 171 – L’instruction « display: block; » déclare que l’élément devrait former son propre paragraphe. L’instruction « display: none; » rend l’élément invisible. – Les instructions « margin-bottom: 30pt; » et « margin-left: 1cm; » définissent des marges en bas et à gauche de 30 points et de 1 cm respectivement. – L’instruction « color: red; » affirme que le contenu de l’élément devrait être écrit en rouge, alors que « font-style: italic; » nous dit que le texte de l’élément devrait être en italique. On pourrait aussi contrôler la couleur de fond avec un instruction comme « background-color:red ». Dans l’éventualité où nous voulons choisir une couleur très précise, et non les couleurs courantes comme « red », « green », « blue », « yellow », « white », « black », etc., nous pouvons la spécifier selon sa composition avec les couleurs de base (« red », « green , « blue ») avec une instruction comme « background-color:rgb(200,200,200); », où chaque valeur numérique est entre 0 et 255 inclusivement. 3.3.6 Contenu en ligne ou en bloc ? Par défault, les éléments s’affichent en ligne, un à la suite de l’autre. On peut contrôler comment s’affiche un élément avec la propriété « display » qui peut prendre plusieurs valeurs dont celles-ci : – « display: none »: l’élément ne doit pas s’afficher. Par exemple, l’instruction « imgdisplay: none; » fait en sorte que les images ne s’affichent plus en HTML. Il est fréquent qu’avec du ECMAScript, on cache et affiche tour à tour des éléments pour donner l’impression que la page est dynamique. – « display: inline »: l’élément s’affiche à la suite du précédent comme s’il s’agissait d’un caractère. – « display: block »: l’élément s’affiche dans un bloc distinct, comme un nouveau paragraphe, par exemple. – « display: list-item »: l’élément s’affiche comme un élément d’une liste. Voici un exemple : p { display: block } strong { display: inline } li { display: list-item } img { display: none } On peut aussi définir la propriété « float » d’un élément qui lui permet de sortir du flot normal des éléments et de se placer à gauche ou à droite. Par exemple, une image en XHTML s’affiche normalement comme un bloc. On peut forcer l’image à s’intégrer au paragraphe suivant avec l’instruction « float: right » ou « float: left ». On peut aussi utiliser la propriété « float » pour créer plusieurs colonnes de texte comme dans un journal. Je vous invite à faire différentes expériences pour mieux comprendre l’utilisation de cette instruction. CC BY-NC-SA Module 3 : Technologies XML 3.3.7 172 Centrer un élément Bien qu’on puisse changer la justification du texte avec une instruction comme « textalign: center », centrer un élément requiert plutôt une manipulation des marges avec la valeur spéciale « auto », comme dans cet exemple : p { width: 5cm; margin-left: auto; margin-right: auto;} Il aurait été sans doute préférable d’avoir une instruction dédiée pour centrer les éléments comme il s’agit d’une opération courante. 3.3.8 Les commentaires Tout comme en Java, on peut ajouter des commentaires à un fichier CSS qui sont systématiquement ignorés par la machine. Un bloc de commentaire débute par « /* » et se termine par « */ ». /* mon fichier css */ montant { color: red; /* la couleur rouge */ } 3.3.9 Sélectionner le premier caractère ou la première ligne On peut sélectionner la première ligne d’un élément s’affichant en mode « block » et le premier caractère de tout élément avec les sélecteurs « :first-line » et :« :first-letter » respectivement. Voici un exemple : p:first-line {text-transform: uppercase} p:first-letter {font-size: 200%;float: left;} 3.3.10 Ajouter du contenu avant et après un élément Avec CSS, on peut demander qu’une certaine chaîne de caractères apparaisse avant ou après un élément. Par exemple, si on veut ajouter automatiquement des guillemets avant et après un élément, on peut procéder comme ceci : blockquote:before {content:"«";} blockquote:after {content:"»";} CC BY-NC-SA CSS 173 Nous ne sommes pas limités au texte cependant. Il est possible, par exemple, d’ajouter automatiquement une image avant chaque élément comme ceci : p:before {content:url("monimage.png";} 3.3.11 Qu’est-ce qu’un pseudo-élément? Les instructions first-line, first-letter, before et after que nous venons de présenter sont les principaux exemples de pseudo-éléments. 3.3.12 Sélecteurs d’intéraction Certains sélecteurs n’agissent qu’en réponse aux comportements de l’utilisateur. Par exemple, le sélecteur « p:hover » sélectionne les éléments « p » qui sont survolés par le curseur de la souris. Il existe plusieurs sélecteurs d’intéraction dont « :link » (lien non visité), « :visited » (lien visité), « active » (l’utilisateur utilise un élément), « :focus » (l’élément est sélectionné par l’utilisateur). On peut aussi combiner les sélecteurs comme dans cet exemple : « a:hover:focus ». On appelle aussi ces sélecteurs de pseudoclasses. 3.3.13 Règles par défaut Dans le cas du HTML ou du XHTML, les navigateurs utilisent une liste de règles par défaut. Ces règles vont varier d’un navigateur à l’autre, mais voici un exemple de règles utilisées par Firefox : html, div { display: block; } body { display: block; margin: 8px; } p, dl, multicol { display: block; margin: 1em 0; } blockquote { display: block; margin: 1em 40px; CC BY-NC-SA Module 3 : Technologies XML 174 } h1 { display: block; font-size: 2em; font-weight: bold; margin: .67em 0; } h2 { display: block; font-size: 1.5em; font-weight: bold; margin: .83em 0; } pre { display: block; white-space: pre; margin: 1em 0; } b, strong { font-weight: bolder; } i, cite, em, var, dfn { font-style: italic; } u, ins { text-decoration: underline; } s, strike, del { text-decoration: line-through; } big { font-size: larger; } small { font-size: smaller; CC BY-NC-SA CSS 175 } sub { vertical-align: sub; font-size: smaller; line-height: normal; } sup { vertical-align: super; font-size: smaller; line-height: normal; } ul, menu, dir { display: block; list-style-type: disc; margin: 1em 0; } ol { display: block; list-style-type: decimal; margin: 1em 0; } li { display: list-item; } area, base, basefont, head, meta, script, style, title, noembed, param { display: none; } 3.3.14 L’astérisque L’astérisque nous permet d’appliquer une règle à tous les éléments, comme dans cet exemple : « * color:red; ». 3.3.15 Sélection sur la base des attributs Avec les CSS, en utilisant les crochets, nous pouvons sélectionner tous les éléments ayant un attribut donné. Par exemple, l’instruction « *[monattribut] color:red; » mettra CC BY-NC-SA Module 3 : Technologies XML 176 en rouge tous les éléments ayant un attribut portant le nom « monattribut ». Nous pouvons aussi, bien sûr, limiter la sélection à des éléments portant un nom donné comme dans cet exemple : « maman[monattribut] color:red; » où les éléments « maman » ayant un attribut « monattribut » seront en rouge. Finalement, nous pouvons de plus limiter la sélection à des attributs ayant une certaine valeur, comme dans « maman[monattribut="papa"] color:red; ». Il arrive fréquemment qu’une valeur d’attribut contiennent plusieurs mots, comme dans « <amerique pays="États-Unis Canada" /> ». Pour séléctionner tous les élément dont un attribut contiennent un mot particulier, on remplace « = » par « = » comme dans l’instruction « *[pays ="Canada"] color:red; » qui mettra en rouge tout élément dont l’attribut « pays » contient le mot « Canada ». Les mots doivent être séparés par des espaces. Dans l’éventualité où les mots sont séparés par des tirets, comme dans « <amerique pays="Mexique-Canada" /> », on peut obtenir le même résultat avec « |= » comme dans « *[pays|="Canada"] color:red; ». 3.3.16 Les espaces de noms Les espaces de noms ne sont pas supportés en CSS 1 ou CSS 2. Ainsi « monelement color:red; » met en rouge le contenu de tous les éléments monelement, peu importe leur espace de noms. Il est incorrect d’utiliser la syntaxe « xhtml:monelement color:red; ». 3.3.17 Sélection de la langue On a vu qu’il est possible en XML de spécifier la langue dans laquelle est écrit un texte avec l’attribut « xml:lang. ». On pourrait penser que pour mettre le texte déclaré comme étant en anglais en rouge, il suffirait de l’instruction « *[lang="fr"] color:red; », mais que se passera-t-il si on a utilisé un code de région avec la langue comme « fr-CA »? Une solution plus élégante consiste alors à utiliser la sélection sur la langue avec une instruction comme « :lang(en) color:red; ». Une alternative est d’utiliser « *[lang|="fr"] color:red; ». 3.3.18 Sélection de plusieurs éléments Supposons maintenant que nous voulions afficher en rouge tous les éléments « facture » et « maison ». Nous pouvons le faire avec deux instructions : facture { color:red;} maison { color:red;} En pratique cependant, il est préférable d’utiliser la virgule pour grouper les éléments, comme ceci : CC BY-NC-SA CSS 177 facture, maison { color:red;} Les deux instructions et cette dernière forme sont exactement équivalentes. 3.3.19 Sélection sur la base de la relation entre les éléments Supposons maintenant que nous ne voulions pas afficher tous les éléments « personne » en rouge, mais seulement les éléments « personne » contenus dans un élément « facture ». Nous obtiendrons ce résultat en plaçant les deux noms d’élément côte-à-côte (séparé par un espace). Ainsi, l’instruction « facture personne color:red; » affichera en rouge tous les éléments « personne » contenus dans un élément « facture », comme dans l’exemple qui suit : <?xml version="1.0" encoding="ISO-8859-1" ?> <?xml-stylesheet type="text/css" href="chap12.css"?> <comptearecevoir> <facture> <personne>Jean Rochond</personne> </facture> </comptearecevoir> ou dans ce deuxième exemple... <?xml version="1.0" encoding="ISO-8859-1" ?> <?xml-stylesheet type="text/css" href="chap12.css"?> <comptearecevoir> <facture> <client><personne>Jean Rochond</personne></client> </facture> </comptearecevoir> Nous pourrions vouloir que seuls les éléments immédiatement contenus dans l’élément « facture », comme dans le premier exemple, soient en rouge, et non pas ceux qui sont contenus dans des éléments eux-mêmes dans un élément « facture » (deuxième exemple). Nous pouvons obtenir ce résultat avec l’instruction « facture > personne color:red; ». En somme, la règle « a b color:red; » s’applique à l’élément « b », si l’élément « b » est contenu dans un élément « a » comme dans « <a><b></b></a> » ou « <a><c><b></b></c></a> ». Par contre, la règle « a > b color:red; » s’applique à l’élément « b », si et seulement si l’élément « b » est immédiatement contenu dans un élément « a », comme dans « <a><b></b></a> ». Elle ne s’applique toutefois pas si « b » est contenu dans un élément lui-même contenu dans « a », comme dans « <a><c><b></b></c></a> ». CC BY-NC-SA Module 3 : Technologies XML 178 Supposons maintenant, dans l’exemple suivant, que nous voulions indenter le premier paragraphe (élément « p ») suivant le titre (élément « titre ») : <?xml version="1.0" encoding="ISO-8859-1" ?> <titre>Mon histoire</titre> <p>C’est triste.</p> <p>Oui, c’est triste.</p> Ce résultat s’obtient avec l’instruction « titre + p text-indent: 0cm; ». La syntaxe « a + b ... » s’applique à l’élément « b » quand les éléments « a » et « b » sont contenus dans le même élément, et que « b » est immédiatement après « a ». Notez que la règle « a + b ... » s’applique à « b », mais ne s’applique pas à « a ». Supposons que nous désirions indenter le premier paragraphe (élément « p ») dans l’élément « section » : <?xml version="1.0" encoding="ISO-8859-1" ?> <section titre="Mon histoire" > <p>C’est triste.</p> <p>Oui, c’est triste.</p> </titre> On peut obtenir ce résultat avec la sélecteur « section > p:firstchild ... » où « :firstchild » signifie que seuls les éléments « p » étant le premier élément au sein d’un autre élément sont sélectionnés. En fait, dans cet exemple particulier, on obtiendrait aussi le résultat voulu avec le sélecteur « p:firstchild ... ». Par ailleurs, nous pouvons combiner les espaces, les « + », les virgules et les « > » dans un même sélecteur. Par exemple, « a + b, c ... » s’applique aux éléments « c » et aux éléments « b » qui suivent immédiatement un élément « a ». 3.3.20 Sélection d’élément par valeur ID Si vous avez des éléments ayant des attributs ayant une valeur de type « ID », on sait alors que leur valeur est un nom XML et qu’elle ne doit être utilisée qu’une seule fois. C’est le cas des attributs de la forme « id="xxx" » que l’on peut utiliser avec pratiquement tous les éléments XHTML. On peut sélectionner un élément basé sur la valeur d’un tel attribut en utilisant le symbole « # » : #xxx { color: red; } Dans ce cas, le contenu d’un élément comme une balise XHTML « <p id=’xxx’>test</p> » s’affichera en rouge. On peut combiner les sélecteurs « # » avec les autres règles que nous avons traitées , par exemple, le code suivant ne mettra en CC BY-NC-SA CSS 179 rouge que les éléments « i » contenus dans un élément ayant un attribut de type « ID » avec pour valeur « xxx » : #xxx i{ color: red; } 3.3.21 Mais que se passe-t-il en cas de conflit? Plusieurs instructions peuvent s’appliquer en même temps: un texte peut être en rouge et souligné. Il peut arriver cependant que deux instructions CSS se contredisent. Par exemple, un texte ne peut être à la fois en rouge et en bleu. Dans ce cas, la sélection la plus spécifique l’emporte. Ainsi, dans l’exemple qui suit... * { color: black; } montant { color: red; } montant > montant { color: yellow; } les éléments « montant » seront en rouge, sauf s’ils sont immédiatement contenus dans un autre élément « montant », auquel cas ils seront en jaune. Par ailleurs, si deux sélections de même spécificité sont rencontrées, c’est la dernière qui l’emporte. Ainsi, dans l’exemple qui suit... montant { color: red; } montant { color: black; } les éléments « montant » seront en noir. CC BY-NC-SA Module 3 : Technologies XML 180 On peut cependant forcer le navigateur à considérer une règle qui apparaît avant une autre comme ayant tout de même priorité (à spécificité égale). Il suffit d’utiliser la mention !important... montant { color: red !important; } montant { color: black; } les éléments « montant » seront en rouge. Notez que la mention !important permet souvent d’ignorer la spécificité de la règle: les règles avec cette mention l’emportent toujours sur les autres. (Si une autre règle avec la mention !important a une plus grande spécificité, elle aura bien sûr priorité.) Les règles par défaut utilisées par votre navigateur dans le cas du HTML ou du XHTML sont lues en premier. De cette manières, toutes les règles qui vous stipulez dans vos propres fichiers CSS et à même le XML ou HTML ont priorité pour une même spécificité. On peut considérer que les règles avec la mention !important sont lues en dernier dans la mesure où ils l’emportent toujours sur les autres. Calculer la spécificité des règles n’est pas une mince affaire, mais c’est pourtant nécessaire dans certains cas difficiles. La spécificité se mesure avec une valeur à 4 chiffres (a,b,c,d). Lorsqu’on compare deux spécificités (a1,b1,c1,d1) et (a2,b2,c2,d2), on utilise l’ordre lexicographique pour déterminer lequel est supérieur. Ainsi, si a1 est plus grand que a2, alors (a1,b1,c1,d1) a une plus grande spécificité que (a2,b2,c2,d2), si a1 est égal à a2, alors on compare b1 et b2, et ainsi de suite. – La première valeur (a) vaut 1 si et seulement si la règle apparaît dans le fichier XML, HTML ou XHTML dans un attribut style. Par exemple, si on a un élément paragraphe en HTML de cette forme <p style="color:red" >, alors la règle color:red aura une très grande spécificité. – La seconde valeur (b) est le nombre de sélections sur la valeur ID utilisée par la règle. Ainsi, la règle #x color:red pourra avoir une spécificité de 0,1,0,0. En pratique, la sélection par valeur ID l’emporte souvent sur les autres règles. – La troisième valeur (c) est le nombre de valeurs d’attributs utilisées par la règle (excluant l’attribut ID). Ainsi, la règle *[monattribut] color:red; pourrait avoir comme spécificité 0,0,1,0. Les pseudo-classes comptent comme des attributs. – La quatrième valeur (c) est le nombre d’éléments utilisés par la règle. Ainsi, la règle p[monattribut] color:red; pourrait avoir comme spécificité 0,0,1,1. Pour mieux comprendre, prenons un exemple concret... z[x] > a[i] {color: blue;} z z[x] a {text-decoration: underline;} CC BY-NC-SA CSS 181 z > z a , z z z + a { color: red ;} Il est plus facile de comptabiliser la spécificité si on écrit les règles individuellement (sans la virgule). Voyez si vous êtes capable de voir pourquoi les différentes règles ont les spécificités annoncées dans les commentaires... /* spécificité: 0,0,2,2 */ z[x] > a[i] {color: blue;} /* spécificité: 0,0,0,3 */ z > z a { color: red ; } /* spécificité: 0,0,0,4 */ z z z + a { color: red; } /* spécificité: 0,0,1,3 */ z z[x] a {text-decoration: underline;} Prenons maintenant un fichier XML auquel on applique les instructions CSS précédente. L’élément a dans le fichier suivant est sélectionné par les 4 règles du fichier CSS. Comment sera affiché le texte dans votre navigateur? <?xml version="1.0" encoding="ISO-8859-1" ?> <?xml-stylesheet type="text/css" href="test.css"?> <z><z x="x"> <z /> <a i="x">mon texte</a> </z> </z> Le texte apparaîtra en bleu et sera souligné. Si on ajoute une instruction avec la mention !important comme « * color: black !important; » alors on peut faire en sorte que le texte soit noir. 3.3.22 Le modèle de boîte CSS En CSS, on peut spécifier la hauteur et la largeur d’un objet à l’aide des instructions « width » et « height ». Par exemple, pour indiquer qu’un paragraphe devrait n’avoir qu’une largeur de 20 pixels, on utilise un sélecteur comme celui-ci : p{ width: 20px; } Le CSS supporte plusieurs unités de mesure outre les pixels dont les pouces (in), les centimètres (cm), pourcentage (%), etc. CC BY-NC-SA Module 3 : Technologies XML 182 On peut ensuite définir une marge (margin en anglais) autour de tout objet. La marge est une région où rien ne peut apparaître, incluant un autre objet. Mais la marge ne fait pas partie de l’objet lui-même. Ainsi, si un objet fait 10 pixels de hauteur et de largeur, et que vous définissez une marge de 10 pixels tout autour de l’objet, un espace d’une superficie de 900 pixels sera occupée sur l’écran. Voici un exemple de marge : p{ margin-top:10px; margin-bottom:10px; margin-right:10px; margin-left:10px; } Outre la marge, on peut aussi définir une région d’espacement (padding en anglais). Contrairement à la marge, la région d’espacement fait partie de l’objet dans la mesure où, si vous définissez une couleur de fond pour l’objet, la région d’espacement sera colorée, car elle fait partie de l’objet. Tout comme la marge, rien n’occupe cette région et elle n’est pas comptabilisée dans la hauteur et la largeur de l’objet. p{ padding-top:10px; padding-bottom:10px; padding-right:10px; padding-left:10px; } On peut définir une bordure (border en anglais) afin de tracer un ligne tout autour de l’objet. La bordure se place entre la région d’espacement et la marge. La bordure peut prendre différente épaisseurs (telles que thin, medium, et thick) et aussi une couleur. p{ border-color: black; border-width: medium; } Voici un diagramme qui résume les différentes définitions : CC BY-NC-SA CSS 183 Contenu ici padding−right padding−left margin−left padding−top rmargin−right margin−top hauteur de l’objet (height) bordure (border) espacement (padding): espace laissé vacant marge (margin): rien ne peut apparaître ici margin:bottom largeur de l’objet (width) 3.3.23 Quand le contenu excède le contenant Il arrive qu’une image ou qu’un texte excède la taille de l’élément dans lequel il a été placé. Par défaut, ce texte ou cet image s’affichera au-delà du cadre de sa boîte (« overflow:visible »). L’instruction « overflow:hidden » permet de faire disparaître la partie d’un texte ou d’une image qui excède la boîte, alors que l’instruction « overflow:scroll » va faire apparaître des barres de défilement pour permettre à l’utilisateur d’avoir accès à tout le contenu sans pour autant avoir un dépassement.. 3.3.24 Encodage des caractères Il peut être utile de spécifier l’encodage des caractères utilisé pour créer le document CSS. Il suffit d’inclure une instruction « @charset » au tout début du document. Voici deux exemples : @charset "UTF-8"; @charset "ISO-8859-1"; 3.3.25 Différentes règles pour différents média Il arrive qu’on veuille qu’une page s’affiche différemment selon qu’on utilise un écran, qu’on l’imprime sur papier ou qu’on utilise un téléphone cellulaire. L’instruction « @media » permet de préciser quel médium est concerné par la règle. Plusieurs média sont reconnus dont « handheld » (appareil portable comme un téléphone cellulaire), « screen » (à l’écran), « tv » (sur un téléviseur), « print » (sur papier), etc. Lorsque l’instruction « @media » n’est pas précisée, la règle s’applique tout le temps. Voici un exemple : CC BY-NC-SA Module 3 : Technologies XML 184 @media print, handheld { img { display: none } h1 {color: black } } @media screen, tv { h1 {color: blue } } 3.3.26 Inclure d’autres fichiers CSS Il arrive parfois qu’on veuille adopter une approche modulaire et créer plusieurs petits fichiers CSS. L’instruction « @import » apparaissant avant le début des règles, mais après une éventuelle instruction « @charset » permet d’inclure un ou plusieurs fichiers CSS. On peut aussi spécifier le type de médium concerné. @import "mineure.css"; @import "print-mineure.css" print; 3.3.27 Indentation de la première ligne d’un paragraphe On peut indenter la première ligne d’un paragraphe avec l’instruction « text-indent ». Par exemple, pour indenter la première ligne de tous les paragraphes par 1 cm, on peut utiliser l’instruction « text-indent: 1cm ». 3.3.28 Modifier la casse du texte L’instruction « text-transform » permet de modifier la casse du texte ce qui est particulièrement utile avec les titres. Par exemple, « text-transform: capitalize » modifie le texte de manière à ce que le premier caractère de chaque mot soit en majuscule. Les instructions « text-transform: uppercase » et « text-transform: lowercase » permettent de passer à une casse uniforme (majuscule ou minuscule). Finalement, l’instruction « text-transform: capitalize » met le premier caractère de chaque mot en majuscule. 3.3.29 Autres variantes des polices Il est possible de modifier de diverses façons les polices : « font-style:italic », « fontstyle:oblique » « font-family: sans-serif », « font-family: serif », « font-weight: bold », « font-weight: bolder », « font-weight: lighter ». On peut modifier la taille des caractères : « font-size: large », « font-size: small ». On peut ajouter des lignes sous, sur ou CC BY-NC-SA CSS 185 au dessus le texte, ou faire clignoter le texte : « text-decoration: underline », « textdecoration: overline », « text-decoration: line-through », « text-decoration: blink ». Vous pouvez aussi spécifier l’apparence que prendra le curseur avec l’attribut « cursor » qui prend la valeur « text » par défaut, et la valeur « pointer » pour les hyperliens. 3.3.30 Ajouter des compteurs On peut définir des compteurs pour, par exemple, numéroter des chapitres ou paragraphes. Ce premier exemple numérote les paragraphes (éléments « p ») contenus entre chaque élément « h1 » avec des nombres romains : p {counter-increment: par-num} h1 {counter-reset: par-num} p:before {content: counter(par-num, upper-roman) ". "} Ce second exemple numérote les éléments « h1 » avec des nombres arabes : h1 {counter-increment: h1-num} h1:before {content: counter(h1-num, decimal) ". "} Ce troisième exemple « numérote » les éléments « h1 » et « h2 » avec des lettres (a,b,c,...) : h1 {counter-reset: h2counter; counter-increment: h1counter} h2 {counter-increment: h1counter} h1:before {content: counter(h1counter, lower-latin) ". "} h2:before { content: counter(h1counter, lower-latin) "." counter(h2counter, lower-latin) ". " } 3.3.31 Traitement des retours de chariot Par défaut, le contenu textuel d’un élément est affiché sans tenir compte des retours de chariot présents dans le fichier XML, mais en insérant plutôt des retours de chariot au besoin. Avec l’instruction « white-space : pre », on force le maintient des retours de chariot là où ils sont, ce qui est très utile pour présenter du code informatique. L’instruction « white-space : nowrap » élimine toute utilisation des retours de chariot, alors que l’instruction« white-space : normal » correspond au comportement pas défaut. CC BY-NC-SA Module 3 : Technologies XML 3.3.32 186 Des nouveautés en CSS 3 La prochaine version du CSS, CSS 3, apporte de nombreuses améliorations. En particulier, elle ajoute plusieurs sélecteurs. Voici un tableau qui résume certains des sélecteurs les plus utilisés ainsi que le niveau CSS correspondant. Sélecteur Signification Niveau CSS * tout élément 2 E un élément de nom E 1 E[foo] un élément E ayant un at- 2 tribut foo E[foo="bar"] un élément E ayant un at- 2 tribut foo dont la valeur est « bar » E[foo ="bar"] un élément E ayant un at- 2 tribut foo dont la valeur contient le mot « bar » séparé par des espaces E[fooˆ="bar"] un élément E ayant un at- 3 tribut foo débute par le texte « bar » E[foo$="bar"] un élément E ayant un at- 3 tribut foo se termine par le texte « bar » E[foo*="bar"] un élément E ayant un at- 3 tribut foo dont la valeur contient le texte « bar » E[foo|="bar"] un élément E ayant un at- 2 tribut foo dont la valeur contient le mot « bar » séparé par des tirets EF un élément F contenu 1 dans un élément E E>F un élément F contenu di- 2 rectement dans un élément E E+F un élément F précédé 2 immédiatement par un élément-voisin E E F un élément F précédé par 3 un élément-voisin E Avec CSS 3, il devient donc possible, par exemple, de sélectionner tous les hyperliens ayant une adresse (attribut « href ») débutant par « http » avec le sélecteur « a[hrefˆ="http"] », ce qui pourrait être utilisé pour indiquer visuellement les liens externes. CC BY-NC-SA CSS 3.3.33 187 Optimisation des fichiers CSS Il y a plusieurs façons d’écrire un même ensemble d’instructions. Par exemple, ce fichier CSS est trop long et difficile à comprendre : montant { color: red; font-weight: bold; background:white; font-style: normal; text-align: center; } nom { color: white; background:white; font-style: normal; text-align: left; } texte { color: black; text-align: center; font-style: normal; background:white; text-align: left; } On peut le réécrire dans un format plus concis et plus clair : montant { color: red; font-weight: bold; text-align: center; } nom { color: white; text-align: left; } texte { color: black; text-align: left; } montant, nom, texte { background: white; font-style: normal; } CC BY-NC-SA Module 3 : Technologies XML 188 Il existe de nombreux outils pour optimiser les fichiers CSS dont CSSTidy qui est disponible en ligne. 3.3.34 En terminant La syntaxe CSS est beaucoup plus riche que ce que nous venons de voir. Pour plus d’information, nous vous invitons à lire le document de référence http:// www.yoyodesign.org/doc/w3c/css2/ ou les articles du site mozilla.org (http://developer.mozilla.org/en/docs/CSS). . 3.3.35 Livres de référence – David Sawyer McFarland, CSS: The Missing Manual, O’Reilly Media, 2006, 476 pages. – Charles Wyke-Smith, CSS 2, guide du designer, Pearson Education France, 2005, 268 pages. 3.4 3.4.1 Travail noté 4 Objectifs et pondération Ce travail compte pour 10 % de la note globale du cours. Il contribue à l’objectif suivant : – Utiliser des transformations XSLT et des instructions CSS. Le travail comprend cinq exercices : le premier vaut 3 points, le deuxième vaut 2 points, le troisième vaut 2 points, le quatrième vaut 2 points, et le cinquième vaut 1 point. 3.4.2 Consignes Faites les exercices et répondez aux questions en utilisant Firefox comme moteur XSLT et comme navigateur; les exercices ont été conçus en fonction de ce navigateur. Certains étudiants trouvent pratique d’utiliser l’outil de traitement en ligne disponible sur le blogue du cours (http://www.daniel-lemire.com/blogue/xsltprocessor.html). En effectuant les exercices, n’utilisez que des fonctions disponibles dans Firefox. De plus, n’utilisez pas les éléments « xsl:key » ou la fonction XPath « key » dans vos solutions. CC BY-NC-SA Travail noté 4 189 Une fois votre travail terminé, transmettez à votre personne tutrice, par courriel, un document (Word 97/2000/XP, ODF, PDF, RTF ou en format texte) en fichier attaché. L’objet de votre courriel doit commencer par « [INF6450][TRAVAIL4] »; dans le message, indiquez votre nom, votre numéro d’étudiant (8 chiffres), la date de remise de votre travail et le nom de votre personne tutrice, ainsi que les mentions « Travail noté 4 » et « INF 6450 ». Il s’agit d’un travail personnel et vous ne devez pas partager vos solutions. Bon travail! 3.4.3 Exercice 1 Étant donné le document XML suivant, rédigez le contenu du document CSS « test.css », de telle sorte que les mots « Rouge » s’affichent en rouge, les mots « Noir » s’affichent en noir, les mots « majuscule » s’affichent en majuscule et ainsi de suite. Votre document CSS doit contenir au plus 5 instructions CSS de la forme « quelque chose autre chose ». Indice : Vous pouvez utiliser « color:red », « color:olive », « color:black », « color:blue », et ainsi de suite pour fixer la couleur du texte. <?xml version="1.0" encoding="ISO-8859-1" ?> <?xml-stylesheet type="text/css" href="test.css"?> <a> <b>Rouge</b> <c><a>Olive</a> <b>Bleu</b> <a><a>Noir</a> Olive <b>Bleu</b> <a>Rouge</a> <a>Noir</a> </a></c> <b><a>Rouge</a> <b>Noir</b></b> <d>majuscule</d> </a> 3.4.4 Exercice 2 Supposons que toutes les notes des étudiants, dans différents cours, se trouvent dans le document XML suivant : <?xml version="1.0" encoding="ISO-8859-1" ?> <?xml-stylesheet href="class.xsl" type="text/xsl" ?> CC BY-NC-SA Module 3 : Technologies XML 190 <université> <étudiant><nom>Réjean Tremblay</nom> <cours sigle="INF8430" note="89" /> <cours sigle="INF1030" note="69" /> <cours sigle="INF1230" note="75" /></étudiant> <étudiant><nom>Martin Lambert</nom> <cours sigle="INF8430" note="75" /> <cours sigle="INF1030" note="72" /> <cours sigle="INF1230" note="73" /></étudiant> <étudiant><nom>Luc Alain</nom> <cours sigle="INF9430" note="39" /> <cours sigle="INF1030" note="89" /> <cours sigle="INF1230" note="79" /></étudiant> <étudiant><nom>Olive Saint-Amant</nom> <cours sigle="INF8430" note="91" /> <cours sigle="INF1230" note="99" /></étudiant> </université> À partir de ce document XML, fournissez le document XSLT « class.xsl » qui calcule les moyennes des étudiants, d’après les éléments « cours » associés aux éléments « étudiant », et qui trie les étudiants par ordre alphabétique de leur nom de famille. Votre document XSLT doit fonctionner même si on change le nom des étudiants, l’ordre des éléments et le nom des cours. En conséquence, le nom des étudiants ou le nom des cours ne peuvent apparaître dans votre document XSLT. En outre, vous ne devez pas utiliser les crochets « [ ] » dans votre solution. Indices 1. Le tableau ci-dessous devrait vous permettre de vérifier votre réponse. Étudiant Moyenne Luc Alain 69.0 Martin Lambert 73.3 Olive Saint-Amant 95.0 Réjean Tremblay 77.7 2. Vous pouvez trier les étudiants selon leur nom de famille, en remplaçant « <xsl:apply-templates match="étudiant" /> » par : <xsl:apply-templates match="étudiant" > <xsl:sort select="substring-after(nom,’ ’)" order="ascending"/> </xsl:apply-templates> 3. Vous pouvez formater les nombres à virgule flottante comme dans le tableau, en utilisant des appels de fonction XSLT tels que « format-number(10.1324, ’##.0’) ». CC BY-NC-SA Travail noté 4 3.4.5 191 Exercice 3 Utilisez le même document XML qu’à l’exercice précédent. Cette fois-ci, comptez le nombre d’étudiants dans chaque cours et calculez la moyenne par cours. Encore une fois, les noms des cours ou des étudiants ne doivent pas apparaître dans votre document XSLT. Le tableau qui suit présente le résultat. Sigle Nombre d’étudiants INF8430 3 INF1030 3 INF1230 4 INF9430 1 Moyenne du cours 85.0 76.7 81.5 39.0 Bien que cet exercice soit très similaire au précédent et que la solution soit de même longueur, vous le trouverez probablement plus difficile. Note. Si vous aviez le droit d’utiliser XSLT 2.0, la nouvelle instruction « xsl:for-eachgroup » rendrait ce problème plus facile. Mais rappelez-vous que vous devez vous limiter à XSLT 1.0. 3.4.6 Exercice 4 Supposons que vous ayiez des documents contenant exclusivement une déclaration XML, des éléments et des attributs. Il n’y a pas d’espace de noms. Vous souhaitez filtrer les documents XML de telle manière que seuls les éléments dont le nom contient la lettre a sont inclus. Naturellement, les éléments, peu importe leur nom, qui ne sont pas contenus dans un élément dont le nom contient la lettre a doivent être omis. Le document XML devra contenir une instruction xml-stylesheet, mais elle ne doit pas être reproduite dans le document sortant. Par exemple, si on prend cet exemple: <?xml version="1.0" ?> <?xml-stylesheet href="monfichier.xsl" type="text/xsl" ?> <a> <ab x="x"><b>Test</b><a>z</a></ab> <z x="x"><a>z</a></z> </a> On souhaite que le document sortant soit celui-ci: <?xml version="1.0" encoding="ISO-8859-1"?> <a> <ab x="x"><a>z</a></ab> </a> CC BY-NC-SA Module 3 : Technologies XML 192 Vous devez proposer deux documents XSLT permettant de réaliser ce filtrage. Le premier document ne devra pas contenir d’élément « xsl:element », alors que le second ne contiendra pas d’élément « xsl:copy ». 3.4.7 Exercice 5 Considérez le fichier XML de la question 2 comprenant les notes des étudiants. Écrivez une requête XQuery qui calcule la moyenne des notes de chaque cours et la présente sous cette forme : <maliste> <cours sigle="INF8430">85</cours> <cours sigle="INF1030">76.66666666666667</cours> <cours sigle="INF1230">81.5</cours> <cours sigle="INF9430">39</cours> </maliste> Vous pouvez utiliser la fonction avg qui calcule la moyenne. CC BY-NC-SA Module 4 : Traitement du XML en Java 4.1 4.1.1 Aperçu Objectifs Dans le premier module, nous avons appris ce qu’était le XML du point de vue technique. Dans le module 2, nous avons vu le rôle que jouait le XML dans l’organisation et sur le web. Le module 3 portait sur les technologies propres aux XML pour la présentation et la transformation des documents. Le module 4 porte sur le traitement du XML à partir d’un langage orienté objet, particulièrement Java. En pratique, le XML n’opère pas en vase clos. Les entreprises ont déjà des bases de données relationnelles, des logiciels spécialisés, des serveurs et ainsi de suite. Même si nous le pouvions, il serait impossible d’utiliser uniquement du XML : il faut nécessairement utiliser d’autres technologies, telle la programmation orientée objet, Java par exemple. On pourrait écrire ses propres fonctions pour traiter le XML, mais on utilise plus souvent une API. Rappelons qu’une API (Application and Programming Interface en anglais ou Interface pour la programmation d’applications en français) est un ensemble de fonctions et d’objets facilitant la programmation d’applications. Pour le traitement du XML en Java, il y a deux aspects importants à prendre en compte. Il faut d’abord bien connaître l’approche DOM (Document Object Model) qui sert de référence à toutes les API orientées objets destinées au traitement du XML. En outre, il faut acquérir suffisamment d’expérience dans ce domaine pour pouvoir juger convenablement de la quantité de travail nécessaire au développement d’une application Java utilisant le XML. Les objectifs spécifiques du module sont : – Apprécier les coûts de développement de solutions XML au sein d’une organisation. 193 Module 4 : Traitement du XML en Java 194 – Appliquer la méthodologie orientée objet pour la consommation, la fusion et le filtrage des fichiers XML. Une activité nécessitant de la programmation, le travail noté 5, nous permettra d’évaluer votre atteinte de cet objectif. 4.1.2 Démarche Avant de commencer l’étude du module 4, vous devez avoir terminé les modules 1 et 3. Il n’est toutefois pas nécessaire de terminer ce module avant de passer au module 5. Nous vous invitons à étudier ce module dans l’ordre suivant : – – – – Modèles de programmation Rappel sur la programmation Java Tutoriel sur DOM et AJAX DOM (autoévaluation) Lisez les textes et vérifiez vos connaissances en répondant aux questionnaires d’autoévaluation, s’il y a lieu; réalisez ensuite le travail noté 5 qui prend la forme d’une activité de programmation. Important.- Avant de réaliser le travail noté 5, vous devriez avoir répondu aux deux questionnaires d’autoévaluation, en maîtriser le contenu et avoir terminé l’étude du module 3. 4.2 4.2.1 Modèles de programmation Objectif Connaître des méthodologies de traitement du XML, dont l’approche DOM. 4.2.2 Activité Lisez le texte qui suit, puis répondez au questionnaire d’autoévaluation. Ce texte porte sur les modèles de programmation en XML et présente les méthodologies communes pour la programmation en vue de traiter du XML. Il conclut avec quelques problèmes communs. Il y a plusieurs façons de traiter du XML. Chaque méthode a ses avantages et ses inconvénients. Bien que ce module s’intéresse surtout à l’approche DOM, il est important de connaître l’ensemble des méthodologies possibles et d’avoir une idée des forces et faiblesses relatives de chacune. CC BY-NC-SA Modèles de programmation 4.2.3 195 Traitement du XML comme du texte Un fichier XML est d’abord un fichier texte. Comme certains langages, tel Java, savent bien traiter les fichiers en format texte, ils peuvent directement traiter le XML. En fait, du moment où nous utilisons un éditeur de texte pour écrire du XML, c’est exactement ce que nous faisons : nous utilisons, comme outil XML, un programme prévu pour traiter du texte. Par exemple, nous pouvons produire du XML à partir d’un programme Java avec des instructions comme celles qui suivent : int montant = 10; String nom= "Gérard Beauford"; System.out.println("<?xml version="1.0" ?> <facture><montant>"+montant +"</montant><nom>"+nom+"</nom></facture>"); Cependant, comment savoir si le XML produit est bien formé? Dans l’exemple précédent, le document XML affiché à l’écran avec l’instruction « System.out.println » ne sera pas du XML bien formé. Pourquoi? Il y a un accent dans le nom et la plupart des environnement de commande n’utilisent pas la norme UTF-8. En principe, il est possible d’écrire un programme Java qui génère du XML bien formé la plupart du temps; mais, une fois de temps en temps, il se produira une erreur dans le XML. Cette erreur pourrait toutefois être suffisamment sérieuse et entraîner un bogue important : Mozilla Firefox refusera d’afficher du XML qui n’est pas bien formé. Pour cette raison, il est préférable, quand cela en vaut la peine, d’utiliser des librairies ou outils dédiés au XML pour une meilleure productivité. De la même façon, lire du XML sans avoir recours à des librairies peut être difficile; par exemple, supposons qu’il faille écrire un programme Java sans utiliser des librairies capables d’extraire le nom et le montant du fichier XML suivant : <?xml version="1.0" encoding="ISO-8859-1" standalone="no"?> <facture> <montant>432</montant> <nom>Gérard Beauford</nom></facture> Un tel programme peut être relativement difficile à écrire. Nous pouvons toutefois bien y arriver avec les expressions régulières (voir le paquetage « java.util.regex » en Java), mais dans le cas de fichiers XML plus complexes, le programme risque de devenir long et fastidieux. Illustrons comment les choses peuvent se corser davantage en étudiant l’exemple suivant : <?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?> <!DOCTYPE facture [ <!ELEMENT facture (montant, nom)> <!ELEMENT montant (#PCDATA)> CC BY-NC-SA Module 4 : Traitement du XML en Java 196 <!ELEMENT nom (#PCDATA)> <!ATTLIST nom surnom CDATA "Joe"> ]> <facture><montant>432</montant><nom>Gérard Beauford</nom></facture> Supposons maintenant que vous deviez écrire un programme Java pour déterminer la valeur de l’attribut « surnom » de l’élément « nom » de ce document XML. Nous constatons qu’il faut traiter non seulement le XML, mais aussi la DTD. Et nous savons que les DTD sont le plus souvent externes, ce qui rend le problème encore plus difficile. Supporter l’ensemble des normes XML devient rapidement très fastidieux : pensons aux entités, déclarations XML, et ainsi de suite. Donc, le traitement du XML en tant que texte est une méthode qui, sans être inappropriée, a ses limites. 4.2.4 Traitement événementiel Le traitement événementiel est une approche très simple pour traiter le XML, mais qui peut être difficile pour le programmeur. En fait, une API, souvent l’API SAX, est utilisée pour lire le XML en séquence. Une alternative à SAX est XNI (Xerces Native Interface). Chaque fois qu’une nouvelle balise ou tout autre élément significatif (instruction XML, contenu XML, etc.) est rencontré, un « événement » est généré. C’est le même type de traitement qui est utilisé pour gérer l’interface graphique avec boutons, fenêtres, etc.; dans ce type de traitement toutefois, l’événement « presse le bouton » est plutôt du type « nouvel élément rencontré ». Par exemple, avec le document XML qui suit... <facture><montant>432</montant><nom>Maman</nom></facture> nous aurons les « événements » suivants (avec la librairie Sax) : 1. Début du document 2. Début d’un élément « facture » 3. Début d’un élément « montant » 4. Texte « 432 » 5. Fin d’un élément « montant » 6. Début d’un élément « nom » 7. Texte « Maman » 8. Fin d’un élément « nom » 9. Fin d’un élément « facture » 10. Fin du document CC BY-NC-SA Modèles de programmation 197 La programmation événementielle peut être plus facile et plus fiable que le traitement du XML en tant que texte parce qu’au lieu de traiter chaque caractère, nous n’avons qu’à traiter ce qui est significatif pour le XML (balises de début et de fin, texte, etc.). Par exemple, les commentaires en XML seront automatiquement reconnus par un parseur événementiel. En fait, le parseur peut parfaitement omettre de générer un événement quand un commentaire est rencontré : c’est pourquoi les commentaires ne doivent jamais contenir des informations importantes. Les valeurs d’attributs par défaut, comme « surnom » dans l’exemple précédent, peuvent être traitées automatiquement. Le traitement événementiel implique quand même beaucoup de travail de la part du programmeur, particulièrement s’il doit prendre en compte plusieurs informations dans le document. Par exemple, s’il est nécessaire de connaître le contenu de tous les éléments du document XML, il faut enregistrer toutes ces informations, car le traitement événementiel ne permet pas les retours en arrière : le fichier est lu en séquence et nous devons faire le reste. Il y a des cas où le traitement événementiel est la meilleure solution. Lorsque nous devons traiter des fichiers XML très lourds, faisant plusieurs Mo, ou que l’on travaille sur des machines avec peu de mémoire (comme un téléphone cellulaire), ce type de traitement permet de faire une utilisation judicieuse de la mémoire vive. Un cas intéressant est celui où seuls quelques éléments d’un document XML nous intéressent. Par exemple, nous cherchons la valeur des éléments « nom » : le traitement événementiel permet de parcourir tout le document, mais de ne retenir que l’information voulue. En général, nous pouvons dire que la programmation événementielle du XML est réservée à des cas particuliers, tels les documents lourds, et aux experts. L’utilisation de SAX2 est fort simple à la base comme le montre le programme MonApplicationSAX. Il suffit de créer une classe dérivée de org.xml.sax.helpers.DefaultHandler où l’on surcharge des méthodes comme « startElement », « endElement » et « characters » qui nous permettent de gérer les événements « début d’un élément », « fin d’un élément » et « nœud de texte » respectivement. On peut aussi gérer d’autres événements comme le début du document (méthode « startDocument ») et sa fin (méthode « endDocument »). Ce type de programmation orientéeobjet correspond au motif de l’observateur : on construit une classe qui est chargée de recevoir les différents événements et d’y réagir. Même les programmeurs expérimentés utilisent peu souvent ce type de motif. import java.io.*; import org.xml.sax.*; import org.xml.sax.helpers.*; /** * INF 6450 * Daniel Lemire */ public class MonApplicationSAX extends DefaultHandler { /** CC BY-NC-SA Module 4 : Traitement du XML en Java 198 * Événement correspondant au début d’un élément */ public void startElement (String uri, String name, String qName, Attributes atts) { if(uri.length()>0) System.out.println("Début de l’élément "+uri+":"+qName); else System.out.println("Début de l’élément "+name); } /** * Événement correspondant à la */ public void endElement (String if(uri.length()>0) System.out.println("Fin de else System.out.println("Fin de fin d’un élément uri, String name, String qName) l’élément "+uri+":"+qName); l’élément "+name); } /** * Ici on traite l’événement correspondant à un noeud de texte */ public void characters (char charac[], int debut, int longueur) { for (int i = debut; i < longueur+debut; ++i) System.out.print(charac[i]); System.out.println(); } /** * on traite un fichier offert en ligne de commande. * Utilisation: java MonApplicationSAX nomdufichier.xml */ public static void main (String args[]) throws Exception { XMLReader xr = XMLReaderFactory.createXMLReader(); xr.setContentHandler(new MonApplicationSAX()); xr.parse(new InputSource(new FileReader(args[0]))); } } CC BY-NC-SA { Modèles de programmation 4.2.5 199 Traitement avec itérateurs Le traitement événementiel n’est pas très intuitif. Par contre, la plupart des programmeurs Java connaissent le traitement itératif. Voici un exemple très simple de programmation avec un itérateur : import java.util.*; public class myvec { public static void main(String[] arg) { Vector<String> v= new Vector<String>(); v.add("parent"); v.add("enfant"); Iterator i = v.iterator(); while(i.hasNext()) System.out.println(i.next()); } } Au lieu de créer une classe qui attend passivement de recevoir des événements, on fait une simple boucle. La Streaming API for XML (StAX) permet de faire un peu la même chose avec du XML. Voici un exemple, observez bien la présence d’une seule boucle et l’absence de plusieurs méthodes : // ce programme nécessite l’installation d’une // librairie StAX // voir http://dev2dev.bea.com/xml/stax.html // import javax.xml.stream.*; import java.net.*; import java.io.*; public class staxex { public static void main(String[] args) { String input = args[0]; try { URL u = new URL(input); InputStream in = u.openStream(); XMLInputFactory factory = XMLInputFactory.newInstance(); XMLStreamReader parser = factory.createXMLStreamReader(in); for (int event = parser.next(); event != XMLStreamConstants.END_DOCUMENT; event = parser.next()) { switch (event) { case XMLStreamConstants.START_ELEMENT: System.out.println(parser.getLocalName()); break; case XMLStreamConstants.END_ELEMENT: CC BY-NC-SA Module 4 : Traitement du XML en Java 200 System.out.println(parser.getLocalName()); break; case XMLStreamConstants.CDATA: System.out.print(parser.getText()); break; } } parser.close(); } catch (XMLStreamException ex) { System.out.println(ex); } catch (IOException ex) { System.out.println(ex); } } } StAX est une norme Java officielle (JSR 173). La librairie open source Woodstox offre une implémentation de l’API StAX. 4.2.6 Traitement avec modèle en arbre Un document XML peut être vu comme un arbre avec un élément-racine contenant luimême des éléments, qui eux-mêmes contiennent des éléments, et ainsi de suite. Ainsi, en utilisant le traitement événementiel par exemple, une librairie peut d’abord lire le document XML et créer un modèle en arbre. Le modèle en arbre XML le plus connu et qui sert de référence est le Document Object Model (DOM). Il est facile de trouver des librairies qui supportent le DOM ou une variante. Nous traiterons du DOM dans un prochain texte. Ainsi, étant donné le document XML suivant... <?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?> <!DOCTYPE facture [ <!ELEMENT facture (montant, nom)> <!ELEMENT montant (#PCDATA)> <!ELEMENT nom (#PCDATA)> <!ATTLIST nom surnom CDATA "Joe"> ]> <facture><montant>432</montant> <nom>Gérard Beauford</nom></facture> un modèle en arbre aura comme objet-racine un objet représentant le document luimême ayant comme enfant l’élément « facture ». Cet objet aura lui-même une liste CC BY-NC-SA Modèles de programmation 201 d’enfants, c’est-à-dire deux objets représentant les éléments « montant » et « nom ». La valeur d’attribut de « surnom » se trouvera dans l’objet représentant l’élément « nom ». De façon simpliste, nous pouvons représenter le document XML précédent avec le diagramme en arbre suivant : Document - déclaration de type | facture | | montant nom (surnom="Joe") | | "432" "Gérard Beauford" La programmation avec des modèles en arbre n’est pas toujours facile. Il y a un grand nombre d’objets à manipuler (un pour chaque élément de l’arbre) et donc beaucoup d’appels de fonctions. De plus, ce type de programmation exige beaucoup de mémoire parce que, généralement, le parseur va d’abord visiter le document en entier, le transformer en objets, puis tout stocker en mémoire. D’un autre côté, ce type de programmation (avec modèle en arbre) est sans doute l’une des façons les plus conviviales de traiter de petits fichiers XML à partir d’un langage orienté-objet comme Java. Il est relativement facile d’apprendre à écrire des programmes en Java pour traiter le XML, en utilisant le DOM. De la même façon, à partir d’un modèle en arbre, nous pouvons produire un document XML. Si nous utilisons une bonne librairie, nous sommes certains que le document XML généré sera bien formé et conforme à notre intention. Il faut par contre bien comprendre que le même modèle en arbre peut correspondre à plusieurs fichiers XML différents. Dans l’exemple précédent, il est possible qu’une librairie, qui a comme paramètre l’arbre que nous avons dessiné, génère un fichier XML comme celui-ci : <?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?> <facture><montant>432</montant> <nom surnom="Joe">Gérard Beauford</nom></facture> 4.2.7 Transformations Le XSLT est une autre façon de traiter le XML par la programmation. Dans les cas les plus simples, c’est probablement le meilleur outil. Cependant, pour un traitement plus complexe, avec intégration dans un système d’information, il ne suffira généralement pas. Par exemple, le XSLT n’est pas conçu pour aller chercher des informations dans une base de données et les transformer en XML bien formé. CC BY-NC-SA Module 4 : Traitement du XML en Java 4.2.8 202 XPath Si nous devons extraire de l’information d’un document XML à partir d’un langage comme Java, il sera souvent plus simple d’utiliser une API qui supporte XPath. C’est le cas notamment du « SDK Java 1.5 ». Nous avons étudié les expressions XPath dans le module 3. Comme nous pouvons le voir avec l’exemple suivant, l’utilisation de XPath en Java requiert la création de plusieurs objets intermédiaires, ce qui n’est pas toujours très pratique. Le traitement XPath se fait sur un document chargé complètement en mémoire ce qui rend son application prohibitive sur de gros documents. Par contre, la syntaxe XPath est très expressive et peut éviter d’avoir à écrire de longs programmes Java. /* on doit toujours importer ces deux paquetages: */ import javax.xml.parsers.*; import javax.xml.xpath.*; /* on doit construire une instance du document XML */ DocumentBuilderFactory dbfact = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = dbfact.newDocumentBuilder(); /* on peut traiter directement un URL */ Document document = builder.parse("http://www.mondomaine.com/monfichier.xml"); /* on construit un objet XPath */ XPathFactory fact = XPathFactory.newInstance(); XPath xpath = fact.newXPath(); /* finalement, on peut émettre sa requête XPath sur le document */ String title = xpath.evaluate("//nom/text()", document); 4.2.9 XML comme extension d’un langage Tout comme les structures de données simples, tel que les tableaux, font souvent partie intégrante des langages de programmation, on choisit parfois d’intégrer le traitement du XML à même le langage. À titre d’exemple, EAX (ECMAScript for XML) est une norme qui définit une extension du langage ECMAScript pour le traitement du XML. Avec ce type d’intégration, on peut définir un document XML directement dans le code comme dans cet exemple. var sales = <sales vendor="John"> <item type="peas" price="4" quantity="6"/> <item type="carrot" price="3" quantity="10"/> <item type="chips" price="5" quantity="3"/> </sales>; On peut aussi traiter les documents XML comme s’ils étaient des structures de données intégrées au langage, comme dans cet exemple. CC BY-NC-SA Modèles de programmation 203 for each( var price in sales..@price ) { alert( price ); } EAX est supporté par les implémentations du ECMAScript de Firefox (JavaScript) et de Flash (ActionScript). Ce n’est pas le seul exemple d’intégration du XML à un langage. 4.2.10 Traitement par abstraction Nous pouvons utiliser des outils et des librairies qui n’exigent aucune connaissance du XML, mais qui peuvent utiliser et générer du XML. Par exemple, la plupart des bases de données relationnelles permettent d’importer et d’exporter des données en XML, sans jamais devoir manipuler le XML directement. Une entreprise pourra écrire sa propre librairie de traitement du XML dans le contexte d’une application XML spécifique. Par exemple, imaginons une application XML pour les factures; nous pourrions écrire une fonction qui prend en paramètre le montant et la personne à qui est destinée la facture, et qui génère le XML, sans que nous n’ayons même à savoir ce qu’est le XML. 4.2.11 Sérialisation XML Comme exemple de traitement par abstraction, on a la sérialisation XML des objets en Java. On définit le terme sérialisation XML comme la transformation d’un objet Java en un fichier XML de manière à ce qu’on puisse reconstuire l’objet par la suite. On peut utiliser la sérialisation pour rapidement enregistrer des informations sur le disque ou transmettre des objets vers un autre programme au travers un réseau. Par exemple, le programme Serialization.java enregistre sur le disque un fichier XML contenant la description complète d’un objet « java.lang.String ». import java.beans.*; import java.io.*; /** * INF 6450 * Daniel Lemire */ public class Serialization { /** * Écrit l’objet en XML dans le fichier spécifié * (ce qu’on appelle une "sérialisation") */ public static void ecrireObjet(Object o, File f) throws IOException CC BY-NC-SA { Module 4 : Traitement du XML en Java 204 XMLEncoder e = new XMLEncoder( new BufferedOutputStream( new FileOutputStream(f))); e.writeObject(o); e.close(); } /** * Lit un objet "sérialisé" en XML dans le fichier spécifié */ public static Object lireObjet(File f) throws IOException { XMLDecoder e = new XMLDecoder( new BufferedInputStream( new FileInputStream(f))); Object o = e.readObject(); e.close(); return o; } /** * lit un fichier et l’affiche à l’écran! */ public static void affiche(File f) throws IOException { BufferedReader br = new BufferedReader(new FileReader(f)); String ligne; while((ligne = br.readLine()) != null) { System.out.println(ligne); } br.close(); } public static void main(String[] args) throws IOException { // je crée un objet java, dans ce cas, une chaîne de carac. String o = new String("Un objet java"); // je vais enregistrer le résultat dans un fichier XML File fichier = new File("test.xml"); ecrireObjet(o,fichier); affiche(fichier); Object lu = lireObjet(fichier); // ensuite, je vérifie que l’objet lu est bien identique // à l’objet écrit assert(lu.equals(o)); } } Après l’exécution de ce programme, le contenu du fichier XML « test.xml » est : CC BY-NC-SA Modèles de programmation 205 <?xml version="1.0" encoding="UTF-8"?> <java version="1.5.0_05" class="java.beans.XMLDecoder"> <string>Un objet java</string> </java> On peut aussi utiliser la sérialisation avec ses propres objets à la condition qu’il s’agisse de « Beans » : tous les attributs de votre objet doivent être modifiés et lus par des méthodes qui débutent par « set » et « get » respectivement. Voici un exemple typique d’objet Bean qui peut facilement être sérialisé : public int x, public } public public public public } class UneClasse { y; UneClasse() { int getX() {return x;} int getY() {return y;} void setX(int i) {x=i;} void setY(int i) {y=i;} Voici un exemple de sérialisation XML de cet objet : <?xml version="1.0" encoding="UTF-8"?> <java version="1.5.0_05" class="java.beans.XMLDecoder"> <object class="UneClasse"> <void property="x"> <int>1</int> </void> <void property="y"> <int>2</int> </void> </object> </java> Il faut, bien entendu, que le programme qui lit vos objets sérialisés ait accès aux classes de vos objets. 4.2.12 Services web Bien qu’il ne s’agisse pas d’une façon de traiter du XML, les services web font partie intégrante des méthodes de programmation utilisant le XML. La définition même de ce qu’est un service web peut varier, mais pour l’essentiel, il s’agit d’un service pouvant être utilisé au sein d’application logicielle. Le service est généralement accessible sur le web et répond aux requêtes par du XML. On peut transmettre les requêtes sous diverses formes : requêtes HTTP simples (GET), transmission de documents XML, CC BY-NC-SA Module 4 : Traitement du XML en Java 206 etc. De nombreux sites web nous permettent d’utiliser des services web. Par exemple, Amazon, la librairie en ligne, vous permet d’utiliser un service web pour récupérer automatiquement les descriptions de produits. En principe, on peut combiner plusieurs services web pour composer des applications riches et originales, ou simplement pour ajouter une fonction particulière à un site web. Plusieurs protocoles peuvent être utilisés dont le Simple Object Access Protocol (SOAP) ou le Search/Retrieve via URL (SRU). On distingue généralement deux types de services web. Les services web « REST » tels que SRU se servent exclusivement du protocole HTTP et il est toujours possible de faire des requêtes en entrant simplement un URL dans un navigateur. Les services web REST font l’objet d’une spécification Java (Java Specification Request 311: Java API for RESTful Web Services). Les autres services web, dont ceux utilisant SOAP, exigent plutôt souvent que toutes les requêtes prennent la forme d’un fichier XML et ils ne tiennent pas compte particulièrement du protocole HTTP. Le protocole HTTP (RFC 2616) est relativement simple. Toutes les requêtes se font du client vers le serveur et se distinguent par un URI et une méthode. Votre navigateur fait des requêtes GET à chaque fois que vous chargez une page. La plupart des formulaires que vous utilisez sur le web emploie la méthode POST. On choisit généralement une des méthodes suivantes : Méthode Explication GET Requête visant à obtenir la ressource (par exemple, un document XML) identifié par l’URI. Il s’agit du type de requête le plus utilisé: c’est celui utilisé généralement par les navigateurs pour charger les pages web. Une telle requête ne doit pas modifier l’état de la ressource. POST Ajouter une nouvelle ressource (un document, une image, un texte) en lien avec l’URI ou annoter ou modifier une ressource existante. L’URI fourni ne sera pas l’URI de la ressource si une nouvelle ressource est créée. PUT Créer ou remplacer une ressource ayant l’URI fourni. En général, les requêtes PUT sont utilisées pour remplacer les ressources (comme un fichier XML). DELETE Supprimer une ressource (comme un document). Les méthodes GET, PUT et DELETE sont idempotentes : on peut répéter la requête autant de fois qu’on le désire, et on obtiendra le même résultat qu’une seule requête. La méthode POST, par contre, n’est pas idempotente : sa répétition pourrait entraîner la création ou la modification de ressources. La méthode GET est sécuritaire : on peut l’employer sans crainte de créer ou de modifier une ressource. CC BY-NC-SA Modèles de programmation 207 Un exemple de service web REST simple, utilisant le protocole SRU, est offert par la librairie du congrès du gouvernement américain. À l’aide d’une simple requêtre prenant la forme d’un URL, on peut demander de recevoir un fichier XML décrivant n’importe quel livre connu de la librairie. Voici un exemple de code Java fonctionnel permettant de faire une telle requête : import org.w3c.dom.*; import javax.xml.parsers.*; import javax.xml.xpath.*; public class example { public static void main(String[] args) throws Exception { String base = "http://z3950.loc.gov:7090/voyager?"; String autre = "operation=searchRetrieve&version=1.1&recordPacking=xml"; String autre2 = "&startRecord=1&maximumRecords=20&query="; String requete ="(dc.title=%22First Impressions of the New World%22) and (dc.creator all %22Trotter Isabella Strange%22)"; DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder parser = factory.newDocumentBuilder(); Document doc = parser.parse(base+autre+autre2+requete); Element racine = doc.getDocumentElement(); XPathFactory fact = XPathFactory.newInstance(); XPath xpath = fact.newXPath(); System.out.println("code: "+xpath.evaluate("//leader/text()", doc)); } } En examinant le code, on peut voir qu’on cherche de l’information sur tous les livres ayant pour titre « First Impressions of the New World » et écrits par « Trotter Isabella Strange ». Le résultat de la requête SRU est plutôt incompréhensible dans ce cas précis. Il est surtout destiné aux spécialistes en bibliothéconomie : <?xml version="1.0"?> <zs:searchRetrieveResponse xmlns:zs="http://www.loc.gov/zing/srw/"> <zs:version>1.1</zs:version><zs:numberOfRecords>1</zs:numberOfRecords> <zs:records><zs:record> <zs:recordSchema>info:srw/schema/1/marcxml-v1.1</zs:recordSchema> <zs:recordPacking>xml</zs:recordPacking><zs:recordData><record xmlns="http://www.loc.gov/MARC21/slim"> <leader>01007cam a2200265u 4500</leader> <controlfield tag="001">8662129</controlfield> <controlfield tag="005">20011206111958.0</controlfield> <controlfield tag="008">830108s1859 enkb a 000 0 eng </controlfield> CC BY-NC-SA Module 4 : Traitement du XML en Java 208 <datafield tag="035" ind1=" " ind2=" "> <subfield code="9">(DLC) 02002686</subfield> </datafield> <datafield tag="906" ind1=" " ind2=" "> <subfield code="a">0</subfield> <subfield code="b">cbc</subfield> <subfield code="c">premunv</subfield> <subfield code="d">u</subfield> <subfield code="e">ncip</subfield> <subfield code="f">19</subfield> <subfield code="g">y-gencatlg</subfield> </datafield> <datafield tag="010" ind1=" " ind2=" "> <subfield code="a"> 02002686 </subfield> </datafield> <datafield tag="040" ind1=" " ind2=" "> <subfield code="a">DLC</subfield> <subfield code="c">CarP</subfield> <subfield code="d">DLC</subfield> </datafield> <datafield tag="043" ind1=" " ind2=" "> <subfield code="a">n-cn---</subfield> <subfield code="a">n-us---</subfield> </datafield> <datafield tag="050" ind1="1" ind2="0"> <subfield code="a">E166</subfield> <subfield code="b">.T85</subfield> </datafield> <datafield tag="050" ind1="0" ind2="0"> <subfield code="a">Microfilm 32043 E</subfield> </datafield> <datafield tag="100" ind1="1" ind2=" "> <subfield code="a">[Trotter, Isabella (Strange)],</subfield> <subfield code="d">1816-1878. [from old catalog]</subfield> </datafield> <datafield tag="245" ind1="1" ind2="0"> <subfield code="a">First impressions of the New world on two travellers from the Old, in the autumn of 1858.</subfield> </datafield> <datafield tag="260" ind1=" " ind2=" "> <subfield code="a">London,</subfield> <subfield code="b">Longman, Brown, Green, Longmans, & Roberts,</subfield> <subfield code="c">1859.</subfield> </datafield> <datafield tag="300" ind1=" " ind2=" "> CC BY-NC-SA Rappel sur la programmation Java 209 <subfield code="a">xi, 308 p.</subfield> <subfield code="b">front. (fold. map)</subfield> <subfield code="c">20 cm.</subfield> </datafield> <datafield tag="583" ind1=" " ind2=" "> <subfield code="a">Replace;</subfield> <subfield code="z">LC copy replaced by preservation microfilm</subfield> <subfield code="5">DLC</subfield> </datafield> <datafield tag="651" ind1=" " ind2="0"> <subfield code="a">United States</subfield> <subfield code="x">Description and travel. [from old catalog]</subfield> </datafield> <datafield tag="651" ind1=" " ind2="0"> <subfield code="a">Canada</subfield> <subfield code="x">Description and travel. [from old catalog]</subfield> </datafield> <datafield tag="985" ind1=" " ind2=" "> <subfield code="g">pmosl</subfield> </datafield> <datafield tag="985" ind1=" " ind2=" "> <subfield code="e">mvp</subfield> <subfield code="f">zz01</subfield> </datafield> <datafield tag="991" ind1=" " ind2=" "> <subfield code="b">c-MicRR</subfield> <subfield code="h">Microfilm 32043 E</subfield> <subfield code="t">Copy 1</subfield> <subfield code="w">PREM</subfield> </datafield> </record></zs:recordData><zs:recordPosition>1</zs:recordPosition> Pour une description, des services web utilisant SOAP, vous pouvez consulter la rubrique correspondante sur wikipédia. Ils sont généralement plus complexes que les services web REST. 4.3 4.3.1 Rappel sur la programmation Java Objectif Ramener à votre mémoire les notions que vous connaissez déjà sur le langage de programmation Java. CC BY-NC-SA Module 4 : Traitement du XML en Java 4.3.2 210 Activité Lisez les définitions qui suivent, puis compilez et exécutez les programmes suggérés dans la section « Exemples ». 4.3.3 Définitions Notion d’objet Java est un langage orienté objet. Le terme « orienté objet » signifie que l’on modélise le problème en utilisant des « objets ». Les objets possèdent des données (les attributs) et des comportements (les méthodes). Dans la plupart des langages orientés objets, les objets appartiennent à une « classe » qui en définit le type. Notion de classe Une classe est un modèle pour créer des objets qui ont des caractéristiques communes. La classe comporte la structure d’un objet (ses attributs et ses méthodes). On dit qu’un objet est l’instance d’une classe et on parle d’instanciation. En Java, tous les objets sont créés à partir d’une classe. Notion de méthode Une méthode est une fonction qui peut être appliquée aux objets ou qui est appliquée par les objets. Par exemple, pour une classe « Voiture », une méthode pourrait être « Freiner » ou « Accélérer ». Notion d’interface Une interface est définie par un ensemble de méthodes et de variables à la manière d’une classe; mais, à la différence d’une classe, on ne peut l’utiliser comme modèle pour créer un objet. On dit d’une classe qui contient toutes les méthodes spécifiées par l’interface qu’elle implémente l’interface en question. En pratique, l’interface peut se traiter comme une classe : si la classe « Voiture » implémente l’interface « Vehicule », alors tous les objets instanciés à partir de « Voiture » peuvent être traités comme des objets de type « Vehicule ». Une même classe peut implémenter plusieurs interfaces. CC BY-NC-SA Rappel sur la programmation Java 211 Notion d’héritage L’héritage est un lien entre des classes. Si une classe est créée à partir d’une classe déjà existante, elle « hérite » de ses attributs et de ses méthodes. Par exemple, la classe « voiture » pourrait hériter de la classe « engin ». Notion d’encapsulation L’encapsulation consiste à protéger un objet, en empêchant l’accès à ses données par un autre moyen que les méthodes proposées. 4.3.4 Exemples Les deux exemples proposés sont très simples. Toutefois, faites-les pour vous remémorer la programmation Java. Commençons par le commencement. Créons un programme qui affichera « Bonjour ! ». Tapez le texte suivant, avec Notepad/Bloc-notes, et enregistrez-le sous le nom « bonjour.java ». public class bonjour{ public static void main (String[] args){ System.out.println("Bonjour !"); } } Pour tester ce programme, ouvrez une fenêtre de commande et placez-vous dans le dossier où vous avez enregistré le fichier « bonjour.java », puis tapez « javac bonjour.java » pour compiler le programme. N’oubliez pas d’indiquer le chemin du fichier « javac.exe »; au besoin, par exemple, tapez, dans la fenêtre de commande, « PATH=C:/j2sdk1.4.2_06/bin », suivi d’un retour du chariot. Cette commande va créer un fichier « bonjour.class » qui contient le programme compilé. Pour exécuter le programme, il suffit de taper « java bonjour ». Normalement, le texte « Bonjour ! » s’affichera. Créons maintenant un autre programme qui prend comme argument le nom d’une personne et qui affiche « Bonjour nom ! ». Il suffit de modifier le programme précédent. Nommons ce programme « bonjourbis » et le fichier « bonjourbis.java ». public class bonjourbis{ public static void main (String[] args){ String nom = new String(args[0]); System.out.println("Bonjour "+nom+" !"); } } CC BY-NC-SA Module 4 : Traitement du XML en Java 212 Pour compiler le fichier, il suffit de taper « javac bonjourbis.java ». Pour l’exécuter avec « Lucie » comme argument, il suffit d’ajouter l’argument à la fin de la ligne de commande : « java bonjourbis Lucie ». Et le texte « Bonjour Lucie ! » s’affichera. 4.3.5 Exemples avancés Supposons que Voiture et Bicyclette sont des classes qui héritent de Vehicule ou alors, des classes qui implémentent l’interface Vehicule. Supposons que vous avez un objet de type Vehicule, comment savoir s’il s’agit d’un objet de classe Voiture ou Bicyclette ? Vous pouvez tester son type avec le mot-clef « instanceof », comme ceci : public void afficheType (Vehicule v){ if(v instanceof Voiture) { System.out.println("Objet de classe Voiture!"); } else if (v instanceof Bicyclette) { System.out.println("Objet de classe Bicyclette!"); } else { System.out.println("Erreur!"); } } Supposons maintenant qu’on vous passe un objet de type Vehicule alors que vous savez très bien que c’est un objet de classe Voiture, ça peut être bien embêtant surtout si l’objet Voiture a des méthodes ou attributs que le type Vehicule n’a pas ! Vous pouvez dire à Java, explicitement, que vous voulez qu’il traite l’objet comme ayant la classe Voiture comme ceci : public void traiteType (Vehicule v){ Voiture w = (Voiture) v; (...) } Attention cependant ! Si l’objet n’est pas de la classe Voiture, une exception sera générée (ClassCastException). 4.3.6 Lecture de fichiers On peut lire un fichier au format text en Java, ligne par ligne, en utilisant la classe BufferReader du paquetage java.io. import java.io.*; (...) BufferedReader br = new BufferedReader( new InputStreamReader(new FileInputStream(nomdufichier))); String ligne; while ((ligne = br.readLine()) != null) { CC BY-NC-SA Tutoriel sur DOM 213 (...) } br.close(); 4.3.7 Astuces – La casse est importante en Java. La variable « i » n’est pas la même que la variable « I ». – Votre fichier java ne peut contenir qu’une seule classe « public » et le fichier doit avoir le même nom que cette classe. – Les instructions, dans une fonction, doivent être séparées par le point-virgule ( ; ). 4.3.8 Retour sur l’activité Est-ce que vous avez pu compiler et exécuter les programmes en java? Si oui, passez aux autres activités, sinon contactez la personne tutrice ou cherchez encore un peu. 4.4 4.4.1 Tutoriel sur DOM Objectifs – Apprendre à lire et à écrire du XML à partir de Java. – Comprendre le modèle DOM, en particulier sa structure en arbre. 4.4.2 Activité Ce tutoriel vous fournira une compréhension pratique de DOM (version 2.0) en Java. Lisez attentivement le texte qui suit et, au fur et à mesure, faites les exemples proposés. 4.4.3 Le tutoriel pour se familiariser avec le DOM Introduction Nous supposons que vous disposez d’un environnement de développement Java et que vous ferez les exemples de ce tutoriel afin de mieux comprendre. Notre objectif est avant tout de vous rendre suffisamment à l’aise avec DOM pour pouvoir l’utiliser; nous vous invitons toutefois à naviguer dans le web pour en apprendre davantage sur le sujet, au besoin. CC BY-NC-SA Module 4 : Traitement du XML en Java 214 L’API Java elle-même est disponible sur le site de Sun Microsystems. Pour pouvoir faire vos propres programmes, consultez l’API Java qui comprend tous les objets et fonctions du tutoriel. 4.4.4 Notions de base On dit qu’un modèle DOM est une structure en arbre. En informatique, un arbre est un graphe ou une structure constituée de nœuds, de façon telle que chaque nœud a un et un seul parent - ou aucun -, lequel a un seul ou plusieurs enfants. Un seul nœud est autorisé à ne pas avoir de parent, c’est le nœud-racine. Pour illustrer notre propos, nous pouvons penser à une cellule qui se divise : chaque cellule a une et une seule celluleparente, et chaque cellule peut se diviser (souvent en deux) ou mourir avant de pouvoir se diviser. On dit d’un nœud qui n’a pas d’enfant qu’il est un nœud-feuille. Comme nous allons le voir, dans un arbre DOM, tous les éléments, les déclarations XML, etc., sont représentés par un nœud. Le nœud-racine est le document lui-même qui peut contenir la déclaration XML, la déclaration de type de document et l’élémentracine, comme ses enfants. 4.4.5 Point de vue critique L’API DOM est très utilisée. Elle est supportée dans plusieurs langages, dont ECMAScript, Java, C#, C++, etc. parce qu’elle a été spécifiée avec l’Interface description language. Par contre, comme c’est un traitement du XML en arbre, les implémentations de l’API DOM consomment beaucoup de mémoire. En plus, l’API DOM fait travailler le programmeur en exigeant beaucoup de lignes de code pour faire les choses les plus simples. Il arrive aussi qu’une implémentation de l’API DOM soit beaucoup plus lente que des alternatives plus simples. Malgré tous ces défauts, le fait que l’API DOM soit si bien supportée en fait une référence incontournable. 4.4.6 Un document XML Créons d’abord un document XML, que nous nommerons « test.xml », et un répertoire pour y déposer le fichier en question, ainsi que le code Java pour ce tutoriel. <?xml version="1.0" encoding="ISO-8859-1" ?> <liste> <joueur> <nom surnom="jojo">Jean</nom> <buts>32</buts> </joueur> <joueur> <nom surnom="Ma">Marie</nom> <buts>54</buts> CC BY-NC-SA Tutoriel sur DOM 215 </joueur> </liste> 4.4.7 Charger un document XML en Java Écrivons maintenant un programme en Java qui va lire ce fichier XML. Pour ce faire, créons avec Notepad/Bloc-notes ou avec tout autre éditeur approprié, un fichier « test.java » contenant le texte suivant : import org.w3c.dom.*; import javax.xml.parsers.*; public class test { public static void main(String[] args) throws Exception { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder parser = factory.newDocumentBuilder(); Document doc = parser.parse(args[0]); } } Ensuite, compilons et exécutons le programme : javac test.java java test test.xml Si tout se passe bien, vous ne devriez rien voir s’afficher sur votre écran. En effet, les trois lignes de code Java utilisées plus haut ne font que créer l’objet « Document » qui contient, selon un modèle en arbre, notre document « test.xml ». Java utilise un traitement événementiel (SAX) pour charger le fichier. Cependant, une fois que l’objet doc a été créé, vous pourriez effacer le fichier du disque sans mal. Le traitement du document se fait entièrement en mémoire. 4.4.8 Accès à l’élément-racine Le premier élément que nous voulons consulter est l’élément-racine qui, dans notre cas, est un élément « liste ». Nous obtiendrons le résultat désiré en utilisant la méthode « getDocumentElement », comme ceci : import org.w3c.dom.*; import javax.xml.parsers.*; public class test { public static void main(String[] args) throws Exception { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); CC BY-NC-SA Module 4 : Traitement du XML en Java 216 DocumentBuilder parser = factory.newDocumentBuilder(); Document doc = parser.parse(args[0]); Element racine = doc.getDocumentElement(); } } Cet exemple n’est pas très intéressant puisque, encore une fois, rien ne s’affiche à l’écran. Par contre, nous avons maintenant un objet « racine » qui est un modèle de l’élément-racine du document XML et qui a le type d’une interface « Element ». L’interface « Element » est l’interface la plus importante en DOM. Notre nouvel objet « racine » a une méthode « getTagName() » qui permet de connaître le nom de l’élément. Par exemple, le code suivant devrait afficher le texte « liste » à l’écran. import org.w3c.dom.*; import javax.xml.parsers.*; public class test { public static void main(String[] args) throws Exception { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder parser = factory.newDocumentBuilder(); Document doc = parser.parse(args[0]); Element racine = doc.getDocumentElement(); System.out.println(racine.getTagName()); } } Voici deux des méthodes importantes de l’interface « Element » : Méthode Résultat getTagName() Donne le nom de l’élément getAttribute(String nom) Donne la valeur d’un attribut Point technique : Dans le cas où vous devez faire afficher du texte en ligne de commande sous un environnement Windows, il arrive que les accents ne passent pas. En effet, le jeu de caractère utilisé par l’outil de ligne de commande Windows est souvent Cp850. Il faut donc en informer Java en ajouter la ligne « System.setOut(new PrintStream(System.out, true, "Cp850")); » avant d’utiliser la méthode System.out. 4.4.9 L’interface « Node » Dans le modèle DOM, l’arbre est un arbre fait de nœuds ou « nodes », en anglais. Plusieurs choses sont représentées par l’interface « Node » : du texte, un élément, une instruction de traitement, une déclaration de type de document, une entité, etc. L’arbre DOM commence à la racine par le document lui-même. Les attributs peuvent être traités comme des « Node », même s’ils ne font pas partie de l’arbre DOM : un CC BY-NC-SA Tutoriel sur DOM 217 attribut est une propriété d’un élément de l’arbre. Le modèle en arbre DOM peut être décrit ainsi : un document contient des « Node », et chaque « Node » contient d’autres « Node », etc. L’interface « Node » possède deux méthodes très importantes : « getNodeName() » et « getNodeValue() ». La valeur donnée par l’une ou l’autre de ces deux méthodes dépend du type de nœud représenté. Le tableau suivant résume le comportement de ces méthodes pour différents types importants : type de nœud nom DOM valeur de getNo- valeur de getNodeName() deValue() attribut Attr nom de l’attribut valeur de l’attribut élément Element nom de l’élément null instruction de trai- ProcessingInstructioncible de l’instruc- contenu entier de tement tion l’instruction sans la cible texte Text la chaîne « #text » le texte Une autre méthode importante est « getNodeType ». Par exemple, si « e » est un nœud et que nous voulons vérifier s’il s’agit d’un élément, nous pouvons le faire comme ceci : if( e.getNodeType() == Node.ELEMENT_NODE) { System.out.println(" Ce noeud est un élément!!! "); } Demandons maintenant à DOM de nous fournir tous les sous-éléments « joueur » de l’élément-racine, comme ceci : import org.w3c.dom.*; import javax.xml.parsers.*; public class test { public static void main(String[] args) throws Exception { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder parser = factory.newDocumentBuilder(); Document doc = parser.parse(args[0]); Element racine = doc.getDocumentElement(); NodeList nl = racine.getElementsByTagName("joueur"); } } Nous avons utilisé la méthode « getElementsByTagName » qui nous permet d’obtenir la liste des sous-éléments ayant le nom XML donné. Une alternative est d’utiliser la méthode « getElementById » qui donne le seul élément ayant un attribut de type « ID » correspondant à la chaîne de caractères founie. En XHTML, par exemple, on peut ajouter un attribut nommé « id » qui a comme une valeur « ID ». Rappelons qu’un attribut a une valeur de type « ID » si elle est un nom XML et si toutes les valeurs de type CC BY-NC-SA Module 4 : Traitement du XML en Java 218 « ID » dans le document sont différentes. L’avantage sur la méthode « getElementsByTagName » est qu’on peut rapidement sélectionner un unique élément. L’interface « NodeList » est, quant à elle, très simple. Elle n’a que deux méthodes : « getLength() », qui retourne le nombre de « Node », et « item(int) », qui nous donne accès au « Node » en question. Donc, pour visiter tous les sous-éléments de l’élémentracine, nous pouvons faire comme ceci : import org.w3c.dom.*; import javax.xml.parsers.*; public class test { public static void main(String[] args) throws Exception { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder parser = factory.newDocumentBuilder(); Document doc = parser.parse(args[0]); Element racine = doc.getDocumentElement(); NodeList nl = racine.getChildNodes(); for (int i = 0; i < nl.getLength(); ++i) { Node n = nl.item(i); } } } Les deux sous-éléments « joueur » de l’élément « liste » sont visités. Parce que les deux « Node » en question sont des éléments, nous aurions très bien pu écrire : import org.w3c.dom.*; import javax.xml.parsers.*; public class test { public static void main(String[] args) throws Exception { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder parser = factory.newDocumentBuilder(); Document doc = parser.parse(args[0]); Element racine = doc.getDocumentElement(); NodeList nl = racine.getChildNodes(); for (int i = 0; i < nl.getLength(); ++i) { Element n = (Element) nl.item(i); } } } CC BY-NC-SA Tutoriel sur DOM 219 Supposons maintenant que nous voulions afficher le contenu des deux éléments « joueur ». Nous pouvons y arriver en commençant comme ceci : import org.w3c.dom.*; import javax.xml.parsers.*; public class test { public static void main(String[] args) throws Exception { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder parser = factory.newDocumentBuilder(); Document doc = parser.parse(args[0]); Element racine = doc.getDocumentElement(); NodeList nl = racine.getElementsByTagName("joueur"); for (int i = 0; i < nl.getLength(); ++i) { Element joueur = (Element) nl.item(i); NodeList listedenoms = joueur.getElementsByTagName("nom"); Element nom = (Element) listedenoms.item(0); } } } En principe, nous avons maintenant les éléments « nom » des joueurs, mais comment faire pour obtenir le contenu textuel d’un élément? Nous devons savoir que le texte est lui-même un « Node ». Il suffit donc de sélectionner le premier et seul « Node » contenu dans l’élément « nom » et d’aller en chercher la valeur (getFirstChild().getNodeValue()), comme ceci : import org.w3c.dom.*; import javax.xml.parsers.*; public class test { public static void main(String[] args) throws Exception { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder parser = factory.newDocumentBuilder(); Document doc = parser.parse(args[0]); Element racine = doc.getDocumentElement(); NodeList nl = racine.getElementsByTagName("joueur"); for (int i = 0; i < nl.getLength(); ++i) { Element joueur = (Element) nl.item(i); NodeList listedenoms = joueur.getElementsByTagName("nom"); Element nom = (Element) listedenoms.item(0); System.out.println(nom.getFirstChild().getNodeValue()); } CC BY-NC-SA Module 4 : Traitement du XML en Java 220 } } Essayez maintenant ce programme. Vous devriez voir les noms des joueurs qui s’affichent. Si vous souhaitez ajouter le nombre de buts correspondant à chaque joueur, rien de plus facile! Il suffit de répéter le code comme dans l’exemple qui suit : import org.w3c.dom.*; import javax.xml.parsers.*; public class test { public static void main(String[] args) throws Exception { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder parser = factory.newDocumentBuilder(); Document doc = parser.parse(args[0]); Element racine = doc.getDocumentElement(); NodeList nl = racine.getElementsByTagName("joueur"); for (int i = 0; i < nl.getLength(); ++i) { Element joueur = (Element) nl.item(i); NodeList listedenoms = joueur.getElementsByTagName("nom"); Element nom = (Element) listedenoms.item(0); System.out.println(nom.getFirstChild().getNodeValue()); NodeList listedebuts = joueur.getElementsByTagName("buts"); Element buts = (Element) listedebuts.item(0); System.out.println(buts.getFirstChild().getNodeValue()); } } } Dans l’éventualité ou un élément nom ne contiendrait pas de texte, la méthode getFirstChild() retourne la valeur null. Il faudrait donc cette éventualité (buts.getFirstChild()==null) afin d’éviter un plantage du programme. Vous vous rappelez sans doute que les éléments « nom » ont un attribut « surnom ». Pour aller en chercher la valeur, il suffit d’utiliser la méthode « getAttribute » comme ceci : import org.w3c.dom.*; import javax.xml.parsers.*; public class test { public static void main(String[] args) throws Exception { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder parser = factory.newDocumentBuilder(); CC BY-NC-SA Tutoriel sur DOM 221 Document doc = parser.parse(args[0]); Element racine = doc.getDocumentElement(); NodeList nl = racine.getElementsByTagName("joueur"); for (int i = 0; i < nl.getLength(); ++i) { Element joueur = (Element) nl.item(i); NodeList listedenoms = joueur.getElementsByTagName("nom"); Element nom = (Element) listedenoms.item(0); System.out.println(nom.getFirstChild().getNodeValue()); System.out.println(nom.getAttribute("surnom")); NodeList listedebuts = joueur.getElementsByTagName("buts"); Element buts = (Element) listedebuts.item(0); System.out.println(buts.getFirstChild().getNodeValue()); } } } Nous constatons que les attributs ne sont pas des « Node » et qu’ils sont donc plutôt traités comme faisant partie d’un élément. C’est logique; puisqu’un attribut ne peut contenir d’autres attributs, il ne forme donc pas un élément essentiel d’une structure en arbre, contrairement aux éléments. Et c’est tout ce qu’il nous faut pour lire complètement le fichier XML « test.xml ». Vous pouvez bien sûr créer un programme plus sophistiqué! 4.4.10 Création de documents À partir d’une structure DOM, nous pouvons créer un document XML en Java à l’aide de quelques lignes et du paquetage « javax.xml.transform » et de ses sous-paquetages. L’écriture d’une structure DOM se fait vers un objet de type « Writer ». Si nous voulons écrire dans un fichier, nous devons créer un « FileWriter » et si nous voulons afficher à l’écran, nous passerons en paramètre l’objet « System.out ». Par exemple, pour lire le document « test.xml », en faire une structure DOM et l’enregistrer, nous pouvons utiliser le programme suivant : import import import import import import org.w3c.dom.*; javax.xml.parsers.*; java.io.*; javax.xml.transform.*; javax.xml.transform.dom.*; javax.xml.transform.stream.*; public class construction { public static void main(String[] args) throws Exception { // lecture d’un document DocumentBuilderFactory factory = CC BY-NC-SA Module 4 : Traitement du XML en Java 222 DocumentBuilderFactory.newInstance(); DocumentBuilder parser = factory.newDocumentBuilder(); Document doc = parser.parse(args[0]); // écriture d’un document TransformerFactory tfact = TransformerFactory.newInstance(); Transformer transformer = tfact.newTransformer(); DOMSource source = new DOMSource(doc); FileWriter fw = new FileWriter(args[1]); StreamResult result = new StreamResult(fw); transformer.transform(source, result); } } Pour afficher à l’écran, nous aurions pu utiliser la syntaxe « new StreamResult(System.out); ». Si nous enregistrons ce code Java dans un fichier nommé « construction.java », il suffira ensuite de taper : javac construction.java java construction test.xml copy.xml Le fichier qui en résulte, « copy.xml », devrait être pratiquement identique à « test.xml ». Nous pouvons évidemment utiliser cette approche pour créer des documents XML. Nous allons maintenant créer un document XML « vide », avant de lui ajouter du contenu. Nommons le fichier du programme « construction2.java ». Nous utilisons la méthode « newDocument » : import import import import import import org.w3c.dom.*; javax.xml.parsers.*; java.io.*; javax.xml.transform.*; javax.xml.transform.dom.*; javax.xml.transform.stream.*; public class construction2 { public static void main(String[] args) throws Exception { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder parser = factory.newDocumentBuilder(); Document doc = parser.newDocument(); } } CC BY-NC-SA Tutoriel sur DOM 223 Si nous enregistrons ce document, il n’y aura que la déclaration XML. Créons maintenant un élément « liste » et ajoutons-le à notre document. Pour ce faire, nous utiliserons la méthode « createElement » de l’interface « Document » et la méthode « appendChild », comme ceci : import import import import import import org.w3c.dom.*; javax.xml.parsers.*; java.io.*; javax.xml.transform.*; javax.xml.transform.dom.*; javax.xml.transform.stream.*; public class construction2 { public static void main(String[] args) throws Exception { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder parser = factory.newDocumentBuilder(); Document doc = parser.newDocument(); Element liste = doc.createElement("liste"); doc.appendChild(liste); } } Il est important de noter qu’on ne peut créer un élément ou autre nœud sans avoir d’abord un document. Un nœud DOM contient toujours une référence au document auquel il appartient, même si on ne l’a pas encore inséré dans le document avec une fonction « appendChild ». Il est impossible de prendre un élément d’un document et de l’insérer dans un autre document : vous risquez ainsi de vous retrouver avec un document dysfonctionnel. On peut cependant copier un nœud d’un document pour l’amener dans un nouveau document avec la méthode « importNode » de l’interface « Document ». Nous pouvons donc créer un nouveau fichier avec le contenu de « test.xml », entièrement à partir de fonctions en Java. À chaque nœud, nous pouvons ajouter des enfants à l’aide de la méthode « appendChild ». Nous pouvons aussi créer des nœuds de texte à partir de la méthode « createTextNode » de l’interface « Document ». Finalement, l’interface « Element » a une méthode « setAttribute » pour créer un attribut. Comme nous utilisons souvent « ISO-8859-1 » pour l’encodage de caractères, nous vous suggérons de spécifier l’attribut « encoding » du document XML, comme ceci : TransformerFactory tfact = TransformerFactory.newInstance(); Transformer transformer = tfact.newTransformer(); transformer.setOutputProperty("encoding", "ISO-8859-1"); CC BY-NC-SA Module 4 : Traitement du XML en Java 224 Le programme suivant va créer un document « nouveaufichier.xml » équivalent au fichier « test.xml » défini plus haut. Nous appellerons le fichier « construction3.java ». import import import import import import org.w3c.dom.*; javax.xml.parsers.*; java.io.*; javax.xml.transform.*; javax.xml.transform.dom.*; javax.xml.transform.stream.*; public class construction3 { public static void main(String[] args) throws Exception { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder parser = factory.newDocumentBuilder(); Document doc = parser.newDocument(); Element liste = doc.createElement("liste"); doc.appendChild(liste); Element joueur1 = doc.createElement("joueur"); Element joueur2 = doc.createElement("joueur"); liste.appendChild(joueur1); liste.appendChild(joueur2); Element nom1 = doc.createElement("nom"); nom1.appendChild(doc.createTextNode("Jean")); Element nom2 = doc.createElement("nom"); nom2.appendChild(doc.createTextNode("Marie")); joueur1.appendChild(nom1); joueur2.appendChild(nom2); Element but1 = doc.createElement("buts"); but1.appendChild(doc.createTextNode("32")); Element but2 = doc.createElement("buts"); but2.appendChild(doc.createTextNode("54")); joueur1.appendChild(but1); joueur2.appendChild(but2); nom1.setAttribute("surnom","jojo"); nom2.setAttribute("surnom","Ma"); TransformerFactory tfact = TransformerFactory.newInstance(); Transformer transformer = tfact.newTransformer(); transformer.setOutputProperty("encoding", "ISO-8859-1"); DOMSource source = new DOMSource(doc); FileWriter fw = new FileWriter("nouveaufichier.xml"); StreamResult result = new StreamResult(fw); transformer.transform(source, result); CC BY-NC-SA Tutoriel sur DOM 225 } } Testez ce programme et modifiez-le pour explorer différentes possibilités. Il peut être utile de vérifier les fonctions disponibles dans le cadre de l’API Java. Il est intéressant d’observer qu’il est possible d’ajouter à plusieurs reprises un nœud de texte à même un élément : e.appendChild(doc.createElement("a")); e.appendChild(doc.createElement("b")); e.appendChild(doc.createElement("c")); Le contenu de l’élément, dans cet exemple, sera tout simplement le texte « abc » décomposé en 3 nœud. 4.4.11 Modifier un « Document » Nous observons que l’écriture d’un document XML se fait à partir d’un objet « Document ». Rien ne nous empêche donc de charger un document XML, de le modifier et de l’enregistrer à nouveau. Voici un tableau qui donne quelques fréquentes opérations de modification : Code Résultat e.getParentNode().removeChild(e); Permet d’éliminer un nœud e.getParentNode().replaceChild(e,f); Permet de remplacer un nœud par un autre e.setAttribute(String nom, String va- Permet de modifier un attribut leur) e.removeAttribute(String nom) Permet d’éliminer un attribut Par exemple, le programme suivant, « Modif.java », permet d’ajouter un attribut à l’élément-racine de tout document XML : import import import import import import org.w3c.dom.*; java.io.*; javax.xml.parsers.*; javax.xml.transform.*; javax.xml.transform.dom.*; javax.xml.transform.stream.*; public class Modif { public static void main(String[] args) throws Exception { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder parser = CC BY-NC-SA Module 4 : Traitement du XML en Java 226 factory.newDocumentBuilder(); Document doc = parser.parse(args[0]); Element racine = doc.getDocumentElement(); racine.setAttribute("unattribut","une valeur"); TransformerFactory tfact = TransformerFactory.newInstance(); Transformer transformer = tfact.newTransformer(); transformer.setOutputProperty("encoding", "ISO-8859-1"); DOMSource source = new DOMSource(doc); FileWriter fw = new FileWriter(args[0]); StreamResult result = new StreamResult(fw); transformer.transform(source, result); } } Il suffit de l’appeler avec la syntaxe « java Modif monfichier.xml ». 4.4.12 Les espaces de noms L’utilisation des espaces de noms est prévue en DOM (version 2.0). Par exemple, pour créer un élément appartenant à un espace de noms, il faut utiliser la syntaxe « createElementNS(String espace, String nom) », où « espace » prend la valeur de l’URI et « nom » contient le préfixe et le nom de l’élément. Cette nouvelle méthode vient remplacer le simple « createElement(String nom) ». Il existe aussi une méthode correspondante « setAttributeNS(String espace, String nom, String valeur) ». Considérons l’exemple de document XML suivant : <?xml version="1.0" encoding="ISO-8859-1"?> <md:racine xmlns:md="http://www.mondomaine.com/"> <md:element md:unattribut="sa valeur"/></md:racine> Pour le produire en DOM, il faudrait utiliser un code comme celui-ci : import import import import import import org.w3c.dom.*; java.io.*; javax.xml.parsers.*; javax.xml.transform.*; javax.xml.transform.dom.*; javax.xml.transform.stream.*; public class Espace { public static void main(String[] args) throws Exception { String uri= "http://www.mondomaine.com/"; DocumentBuilderFactory factory = CC BY-NC-SA Tutoriel sur DOM 227 DocumentBuilderFactory.newInstance(); DocumentBuilder parser = factory.newDocumentBuilder(); Document doc = parser.newDocument(); Element racine = doc.createElementNS(uri,"md:racine"); racine.setAttribute("xmlns:md",uri); doc.appendChild(racine); Element e = doc.createElementNS(uri,"md:element"); racine.appendChild(e); e.setAttributeNS(uri,"md:unattribut","sa valeur"); TransformerFactory tfact = TransformerFactory.newInstance(); Transformer transformer = tfact.newTransformer(); transformer.setOutputProperty("encoding", "ISO-8859-1"); DOMSource source = new DOMSource(doc); StreamResult result = new StreamResult(System.out); transformer.transform(source, result); } } Il faut nommer le fichier « Espace.java ». Nous pouvons aussi retrouver l’espace de noms d’un élément à l’aide de la méthode « getNamespaceURI() » de l’interface « Node ». Cependant, par défaut, la classe « DocumentBuilderFactory » ignore les espaces de noms et il faut, par conséquent, ajouter la ligne « factory.setNamespaceAware(true); ». L’exemple du code qui suit donne l’espace de noms (URI), le préfixe et le nom de l’élément (avec le préfixe) de tout fichier XML saisi dans une ligne de commande : import org.w3c.dom.*; import javax.xml.parsers.*; public class LireEspace { public static void main(String[] args) throws Exception { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); DocumentBuilder parser = factory.newDocumentBuilder(); Document doc = parser.parse(args[0]); Element racine = doc.getDocumentElement(); System.out.println(racine.getNamespaceURI()+" " +racine.getPrefix()+" "+ racine.getTagName()); } } CC BY-NC-SA Module 4 : Traitement du XML en Java 228 Il faut nommer le fichier « LireEspace.java », et l’exécuter avec la syntaxe « java LireEspace monfichier.xml ». 4.4.13 Deux problèmes avec solution Pour vous aider à maîtriser le modèle DOM, nous vous proposons deux problèmes et une solution possible pour chacun. Problème 1 Créez une classe « Arbre » (fichier « Arbre.java ») qui donne l’arbre DOM d’un document XML. Pour chaque nœud, donnez son nom et sa valeur (indices : « getNodeName », « get NodeValue »). Enfin, indentez les nœuds selon le nombre de parents qu’ils ont. Ainsi, étant donné le fichier « test.xml » suivant : <?xml version="1.0" encoding="ISO-8859-1" ?> <joueur><nom surnom="jojo">Jean</nom><buts>32</buts></joueur> La commande « java Arbre test.xml » devrait afficher à l’écran le résultat suivant : Nom: #document Valeur: null Nom: joueur Valeur: null Nom: nom Valeur: null Nom: #text Valeur: Jean Nom: buts Valeur: null Nom: #text Valeur: 32 Solution du problème 1 Voici une solution possible : import org.w3c.dom.*; import javax.xml.parsers.*; public class Arbre { public static void traite(Node node, int i) { String s= ""; for (int k = 0; k < i; ++k) s+=" "; System.out.println(s+"Nom: "+ node.getNodeName() + " Valeur: "+node.getNodeValue()); NodeList nl = node.getChildNodes(); if(nl != null) { for (int k = 0; k < nl.getLength(); ++k) { traite( nl.item(k),i+2); CC BY-NC-SA Tutoriel sur DOM 229 } } } public static void main(String[] args) throws Exception { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder parser = factory.newDocumentBuilder(); Document doc = parser.parse(args[0]); traite(doc,0); } } Problème 2 Nous pouvons utiliser un fichier XML comme archive d’une base de données primitive. Cette fois-ci, nous vous demandons d’écrire un programme qui permet de chercher, d’effacer et d’ajouter des noms dans un bottin téléphonique. Stockez les numéros dans un fichier XML nommé « bottin.xml » et ayant le contenu qui suit : <?xml version="1.0" encoding="ISO-8859-1"?> <bottin> <personne nom="Jean Réjean" téléphone="432-4421" /> <personne nom="Jules Desche" téléphone="432-4332" /> </bottin> Concevez un programme dont le code source sera contenu dans un fichier nommé « Bottin.java ». Votre programme doit posséder les trois fonctions suivantes : – « java Bottin efface "Jean Réjean" » : élimine du fichier « bottin.xml » tout élément « personne » ayant comme attribut « nom="Jean Réjean" ». – « java Bottin cherche "Jean Réjean" » : donne le numéro de téléphone correspondant au nom donné à partir du contenu du fichier « bottin.xml », et ne retourne rien si le nom donné n’est pas trouvé. – « java Bottin ajoute "Jean Réjean" 432-4421 » : fait en sorte que le nom « Jean Réjean » soit associé au seul numéro de téléphone « 432-4421 ». Vous pouvez supposer que le fichier « bottin.xml » existe et se trouve dans le même répertoire que le fichier « Bottin.java ». Vous pouvez également supposer que l’élémentracine est « bottin ». Solution du problème 2 Voici une solution possible : CC BY-NC-SA Module 4 : Traitement du XML en Java import import import import import import 230 org.w3c.dom.*; java.io.*; javax.xml.parsers.*; javax.xml.transform.*; javax.xml.transform.dom.*; javax.xml.transform.stream.*; public class Bottin { public static void main(String[] args) throws Exception { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); DocumentBuilder parser = factory.newDocumentBuilder(); Document doc = parser.parse("bottin.xml"); Element racine = doc.getDocumentElement(); NodeList nl = racine.getChildNodes(); if(args[0].equals("efface")) { for (int k = 0; k < nl.getLength(); ++k) { if(nl.item(k).getNodeType()==Node.ELEMENT_NODE) { Element e = (Element) nl.item(k); if(e.getAttribute("nom").equals(args[1])) { e.getParentNode().removeChild(e); } } } } else if (args[0].equals("cherche")) { for (int k = 0; k < nl.getLength(); ++k) { if(nl.item(k).getNodeType()==Node.ELEMENT_NODE) { Element e = (Element) nl.item(k); if(e.getAttribute("nom").equals(args[1])) { System.out.println(e.getAttribute("téléphone")); } } } } else if (args[0].equals("ajoute")) { boolean ajout = false; for (int k = 0; k < nl.getLength(); ++k) { if(nl.item(k).getNodeType()==Node.ELEMENT_NODE) { Element e = (Element) nl.item(k); if(e.getAttribute("nom").equals(args[1])) { e.setAttribute("téléphone",args[2]); ajout=true; } } } CC BY-NC-SA Tutoriel sur DOM 231 if( ! ajout) { Element p = doc.createElement("personne"); p.setAttribute("nom", args[1]); p.setAttribute("téléphone", args[2]); racine.appendChild(p); } } TransformerFactory tfact = TransformerFactory.newInstance(); Transformer transformer = tfact.newTransformer(); transformer.setOutputProperty("encoding", "ISO-8859-1"); DOMSource source = new DOMSource(doc); FileWriter fw = new FileWriter("bottin.xml"); StreamResult result = new StreamResult(fw); transformer.transform(source, result); } } 4.4.14 DOM et ECMAScript ECMAScript est un langage similaire au Java quant à sa syntaxe de base et qui s’exécute souvent dans un navigateur. Il fut inventé par Netscape en 1995 sous le nom de JavaScript. Il s’agit d’une norme de l’European Computer Manufacturers Association (ECMA) depuis 1997. L’implémentation du ECMAScript que l’on retrouve dans le navigateur Firefox se nomme toujours JavaScript, alors que Microsoft nomme son implémentation JScript. L’ECMAScript n’est pas une forme de Java, même s’ils ont une ressemblance superficielle, adoptant tous les deux une syntaxe proche du langage C. Il existe de nombreux tutoriels sur le ECMAScript incluant le tutoriel de Jean-Paul Davalan se trouvant à l’URL http://perso.wanadoo.fr/jean-paul.davalan/lang/jsc/ ou encore le tutoriel de commentcamarche.net. Le site xul.fr offre un résumé du langage, le site mozilla.org offre une description complète du langage (en anglais). Si vous ne connaissez pas le langage ECMAScript, vous devriez prendre quelques instants pour en faire un survol. Les implémentations ECMAScript supportent bien l’API DOM en général. La documentation de l’API DOM pour l’implémentation de ECMAScript de Firefox se trouve à l’adresse http://developer.mozilla.org/en/docs/Gecko_DOM_Reference. La principale différence entre DOM en ECMAScript et DOM en Java est que certaines méthodes en Java deviennent des attributs en ECMAScript (getNodeValue() devient nodeValue). ECMAScript peut donc lire et traiter des documents XML avec l’API DOM. En particulier, si ECMAScript est utilisé au sein d’une page XHTML, le script peut modifier la page dynamiquement en utilisant l’API DOM. La principale différence entre l’utilisation de DOM en Java et ECMAScript est qu’à l’exception des méthodes getAttribute, setAttribute, getAttributeNS, setAttributeNS, getAttributeNode, setAttributeNode, getAttributeNodeNS, setAttributeNodeNS, getElementsByTagName et getElementById, CC BY-NC-SA Module 4 : Traitement du XML en Java 232 toutes les méthodes dont le nom commence par « get » ou « set » sont remplacées par un attribut de l’objet (ou « property » en anglais). Au lieu d’écrire « e.getChildNodes(); », on écrit « e.childNodes; », au lieu d’écrire « e.setNodeValue("texte"); », on écrit « e.nodeValue="texte"; », et ainsi de suite. Par exemple, le script suivant va ajouter du texte lorsque la souris passera sur l’élément ayant un attribut « id=’javatest’ ».. monele=document.getElementById(’javatest’); monele.childNodes.item(0).nodeValue+=’ (passage de souris) ’; 4.4.15 Asynchronous JavaScript And XML (AJAX) Normalement, sur un site web, pour aller chercher de l’information supplémentaire sur le serveur, tel que la description d’un produit ou l’horaire d’un film, il faut charger une nouvelle page web. Cependant, si l’information en question est disponible au format XML, un script ECMAScript peut la récupérer sans forcer le chargement d’une nouvelle page ce qui donne l’impression à l’utilisateur que l’application web est rapide, car il ne voit pas de chargement de pages. Le fait de pouvoir charger un fichier XML du serveur d’origine à partir d’un script ECMAScript constitue l’essentiel d’une technique appelée Asynchronous JavaScript And XML (AJAX) (JavaScript asynchrone et XML). Notons qu’à cause du modèle de sécurité ECMAScript, le fichier XML doit être sur le même serveur et être du même nom de domaine que la page HTML. Vous avez sans doute déjà utilisé une application AJAX. Les sites de courriel en ligne comme Google Mail l’utilisent presque tous pour charger le contenu d’un message sans forcer le chargement d’une nouvelle page. Si vous connaissez l’API DOM, la programmation d’une application AJAX n’est pas bien difficile. Il vous suffit d’apprendre un peu de ECMAScript. La classe XMLHttpRequest rend AJAX facile parce qu’elle permet d’aller chercher un fichier XML sur le serveur en quelques lignes de code. Voici un exemple simple de page web comportant un script ECMAScript et chargeant du contenu XML, en l’occurence, deux des pages web du cours: <?xml version="1.0" encoding="ISO-8859-1" ?> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Exemple AJAX</title> <script language="JavaScript"> /* Cette fonction va chercher un document XML sur le serveur et appelle la fonction afficherTitre lorsque c’est fait! */ function chargeDocument(URI) { xmlhttp = new XMLHttpRequest(); CC BY-NC-SA Tutoriel sur DOM 233 xmlhttp.open("GET", URI,true); xmlhttp.onreadystatechange=function() { if (xmlhttp.readyState==4) { afficheTitre(xmlhttp.responseXML); } } xmlhttp.send(null); } /* Cette fonction est appelée lorsque le document XML est chargé */ function afficheTitre(doc) { // on récupère le contenu de l’unique élément titre titreele = doc.getElementsByTagName("title").item(0); if(titreele.firstChild != null) titre=titreele.nodeValue; else titre = ""; // on ajoute un élément au document courant // "document" est le document XHTML, à ne pas confondre avec "doc" elementp = document.createElement("p"); elementp.appendChild(document.createTextNode(titre)); body = document.getElementsByTagName("body").item(0); body.appendChild(elementp); } </script> </head> <body> <p>Vous pouvez cliquer sur les liens suivants plus d’une fois. À chaque fois, votre navigateur charge un document XHTML et en affiche le titre.</p> <ul> <li><a href="javascript:chargeDocument(’domtutoriel.xhtml’);"> Récupère et affiche le titre du document domtutoriel.xhtml.</a></li> <li><a href="javascript:chargeDocument(’travail5.xhtml’);"> Récupère et affiche le titre du document travail5.xhtml.</a></li> </ul> </body> </html> Le code ECMAScript n’est pas très long comme vous pouvez le constater. L’attribut readyState de l’objet xmlhttp nous permet de déterminer quand le document XML a CC BY-NC-SA Module 4 : Traitement du XML en Java 234 été chargé (xmlhttp.readyState==4). La propriété onreadystatechange est quant à elle appelée chaque fois que l’objet de type XMLHttpRequest change d’état. Lorsque le document XML est chargé, on peut donc appeler une fonction qui manipule le contenu de la page web (fonction afficheTitre). Voici un exemple similaire, mais qui récupère, cette fois-ci, le fichier RSS du journal le Devoir et en affiche les principales manchettes (le fichier RSS est une représentation en XML du contenu du journal). Il faut au préalable charger le fichier ledevoir.xml et le déposer dans le même répertoire que le fichier XHTML contenant le script AJAX, sur votre disque.Le fil de nouvelles du devoir se trouve normalement à l’adresse « http:// www.ledevoir.com/rss/ledevoir.xml ». <?xml version="1.0" encoding="ISO-8859-1" ?> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Exemple plus avancé en AJAX</title> <script language="JavaScript"> /* Cette fonction va chercher un document XML sur le serveur et appelle la fonction afficherTitres lorsque c’est fait! */ function chargeDocument(URI) { try { xmlhttp = new XMLHttpRequest(); xmlhttp.open("GET", URI,true); xmlhttp.onreadystatechange=function() { if (xmlhttp.readyState==4) { afficheTitres(xmlhttp.responseXML); } } xmlhttp.send(null); } catch(o) {alert(o);} } /* Cette fonction est appelé lorsque le document XML est chargé */ function afficheTitres(doc) { titres = doc.getElementsByTagName("title"); elementol = document.createElement("ol"); var longueur = titres.length; for ( k = 0; k < longueur ; ++k) { elementli = document.createElement("li"); elementli.appendChild( document.createTextNode( titres[k].firstChild.nodeValue CC BY-NC-SA Tutoriel sur DOM 235 ) ); elementol.appendChild(elementli); } body = document.getElementsByTagName("body").item(0); body.appendChild(elementol); } </script> </head> <body> <ul> <li><a href="javascript:chargeDocument(’ledevoir.xml’);">Récupère et affiche les nouvelles du devoir.</a></li> </ul> </body> </html> Finalement, si on souhaite insérer non pas seulement du texte, mais des éléments provenant d’un autre document, on peut obtenir ce résultat avec la fonction importNode : <?xml version="1.0" encoding="ISO-8859-1" ?> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Exemple AJAX avec importNode</title> <script language="JavaScript"> /* Cette fonction va chercher un document XML sur le serveur et appelle la fonction afficheListe lorsque c’est fait! */ function chargeDocument(URI) { xmlhttp = new XMLHttpRequest(); xmlhttp.open("GET", URI,true); xmlhttp.onreadystatechange=function() { if (xmlhttp.readyState==4) { afficheListe(xmlhttp.responseXML); } } xmlhttp.send(null); } /* Cette fonction est appelé lorsque le document XML est chargé */ function afficheListe(doc) { ule = doc.getElementsByTagName("ul").item(0); // on récupère l’élément ul avec tout son contenu: body = document.getElementsByTagName("body").item(0) CC BY-NC-SA Module 4 : Traitement du XML en Java 236 body.appendChild(document.importNode(ule,true)); } </script> </head> <body> <p>Vous pouvez cliquer sur les liens suivants plus d’une fois. À chaque fois, votre navigateur charge un document XHTML et en affiche une partie du contenu.</p> <ul> <li><a href="javascript:chargeDocument(’domtutoriel.xhtml’);">Récupère et affiche une liste du document domtutoriel.xhtml.</a></li> <li><a href="javascript:chargeDocument(’travail5.xhtml’);">Récupère et affiche une liste du document travail5.xhtml.</a></li> </ul> </body> </html> La classe XMLHttpRequest fait l’objet d’une spécification du W3C. La construction d’un objet XMLHttpRequest est simple (xmlhttp = new XMLHttpRequest();) et généralement suivie de l’appel xmlhttp.open qui prend de 2 à 5 paramètres dont la méthode, l’URL, une valeur booléenne stipulant si l’appel est synchrone ou asynchrone, un nom d’utilisateur et un mot de passe. Les deux derniers paramètres sont utilisés si la ressource est protégée par mot de passe. On utilise généralement des appels asynchrone, pour éviter que le navigateur ne fige en attendant la réponse du serveur. La méthode est une des méthodes définie par le protocole HTTP (RFC 2616) dont GET, PUT, POST, et DELETE. On utilise le plus souvent AJAX avec des requêtes GET. Comme les requêtes GET ne nécessitent pas la transmission d’un document, on termine la requête avec « xmlhttp.send(null); ». Puisque la requête est asynchrone (le plus souvent) on doit définir une fonction qui sera appelée lorsque la réponse arrivera du serveur (onreadystatechange). Si la réponse du serveur est un fichier XML, on peut le récupérer avec l’attribut « responseXML ». Le document responseXML s’utilise comme tout document DOM. On peut aussi manipuler le document XHTML qui a fait l’appel AJAX avec l’API DOM. En somme, si on connaît bien l’API DOM, et si on connaît un peu d’ECMAScript, il est facile de développer des applications AJAX si on cible un navigateur comme Firefox. Par contre, les navigateurs diffèrent souvent beaucoup les uns des autres et, en particulier, Internet Explorer ne respecte pas les recommandations du W3C ce qui rend le développement plus difficile. Voici quelques sites qui utilisent AJAX : CC BY-NC-SA DOM 237 – http://www.objectgraph.com/dictionary/ – http://www.google.com/webhp?complete=1&hl=en – http://maps.google.com/ Le site mozilla.org a plusieurs articles sur AJAX (en anglais). Depuis mai 2006, Google rend disponible gratuitement son Google Web Toolkit qui permet de construire des applications AJAX en Java fonctionnant avec tous les principaux navigateurs. Il existe d’autres librairies AJAX telles que Dojo, Rico, et la Yahoo! User Interface Library. Une librairie particulièrement intéressante est la librairie Prototype (http:// www.prototypejs.org/) qui est constituée d’un seul fichier ECMAScript. Malheureusement, le traitement d’un document XML en ECMAScript est parfois inutilement lourd. Pour cette raison, on remplace souvent le XML par du JavaScript Object Notation (JSON) ou par du HTML. 4.4.16 DOM et autres langages L’API DOM est supportée en C++ (voir Xerces-C), en Python (paquetage xml.dom), en Perl (voir Xerces-P), en ECMAScript, etc. C’est d’ailleurs la principale force de cette API : peu importe le contexte, il y a fort à parier que vous aurez accès à l’API DOM. Ce n’est sans doute pas la meilleure API possible, mais son ubiquité fait en sorte qu’il vaut la peine d’apprendre à la connaître. 4.4.17 Conclusion Dans ce tutoriel, nous avons appris à lire et à écrire du XML à partir du Java. Nous avons aussi appris à mieux comprendre le modèle DOM et, en particulier, sa structure en arbre. Vous devriez maintenant être en mesure de commencer à créer des applications Java, de filtrer, fusionner et modifier du XML. 4.4.18 Livres de référence – Elliotte Rusty Harold, Processing XML with Java: A Guide to SAX, DOM, JDOM, JAXP, and TrAX, Addison-Wesley Professional, 2002, 1120 pages. – Frank W. Zammetti, Practical Ajax Projects with Java Technology, Apress, 2006, 504 pages. – Brett McLaughlin, Head Rush AJAX, O’Reilly Media, 2006, 413 pages. CC BY-NC-SA Module 4 : Traitement du XML en Java 4.5 4.5.1 238 DOM Objectif Comprendre l’approche DOM. 4.5.2 Activité Lisez le texte qui suit, puis répondez au questionnaire d’autoévaluation en vous référant au tutoriel sur DOM que vous venez d’utiliser. On peut définir DOM comme un ensemble d’API (Application Program Interface) : un ensemble de fonctions et d’objets que l’on peut utiliser en Java (ou autres langages similaires) pour manipuler le XML selon un modèle en arbre. Dans ce cours, nous allons nous pencher plus particulièrement sur l’incarnation Java de DOM. Note.- Le terme DOM désigne aussi un type de modèle en arbre représentant le XML. Il y a donc deux significations au terme « DOM » : un ensemble d’API utilisant un modèle en arbre ou un certain modèle en arbre. Un des avantages de DOM est qu’il est indépendant du langage ou de la plate-forme. Ainsi, si vous connaissez DOM, vous pourrez l’utiliser dans plusieurs contextes différents. Ce qui est peut-être le plus important, c’est que les concepts propres à DOM se retrouvent dans d’autres API pour traiter le XML, qu’elles soient produites par Microsoft, Sun Microsystems ou d’autres auteurs. Dans une API DOM, tous les éléments sont immédiatement accessibles : on lit le fichier une fois et il est ensuite totalement en mémoire. La contrepartie de cet avantage est que DOM utilise beaucoup de mémoire parce qu’il doit charger la totalité des fichiers XML. Notez toutefois que, dans le contexte DOM, il serait possible, en principe, de ne pas tout charger en mémoire. Comme nous l’avons vu, l’API DOM permet de créer des documents XML, de naviguer dans des documents XML, d’ajouter, de modifier ou d’éliminer des éléments XML. 4.6 4.6.1 Travail noté 5 Objectifs et pondération Le travail noté 5, une activité de programmation Java, compte pour 15 % de la note globale du cours. Il contribue à l’atteinte des objectifs suivants : CC BY-NC-SA Travail noté 5 239 – Apprécier les coûts de développement de solutions XML au sein d’une organisation. – Appliquer la méthodologie orientée objet pour la consommation, la fusion et le filtrage des fichiers XML. Le travail comporte cinq exercices, valant respectivement 3, 4, 4, 2 et 2 points, pour un total de 15 points. 4.6.2 Consignes générales 1. Utilisez les noms des fichiers spécifiés dans chaque exercice. 2. Vous n’avez droit qu’à un seul fichier « .java » par exercice et il ne doit pas contenir plus de 500 lignes de code. Tous les problèmes peuvent être résolus en moins de 100 lignes! Rappelons qu’une « ligne » de code comprend un maximum de 80 caractères. 3. Chaque fichier doit débuter par un commentaire donnant le sigle du cours et votre nom comme ceci : /** * INF 6450 */ Travail noté 5 - Votre nom, fait avec SDK 1.5.0_06 4. Vous devriez pouvoir accéder à la version de votre SDK, en tapant « javac version » ou « java -version » dans une ligne de commande. 5. Ne traitez pas les cas d’exception, comme les fichiers qui n’existent pas ou ne peuvent être ouverts. Par contre, votre code doit produire un résultat correct dans des conditions normales. Par exemple, si on vous demande de produire du XML, il doit s’agir de XML bien formé. Si on vous demande de lire du XML, vous devez pouvoir lire tout XML qui se conforme aux spécifications décrites dans l’exercice. Vous devez utiliser l’API DOM. 6. Il est impératif que vos fichiers compilent avec le SDK (le plus récent), sans utiliser de librairies particulières. Un fichier Java qui ne compile pas ne sera pas noté. 7. Lorsque vous aurez terminé les exercices, vous devez transmettre à votre personne tutrice, par courriel, l’ensemble des fichiers avec l’extension Java comme fichiers attachés. Vous devez aussi remettre un fichier XML ainsi qu’un document (Word 97/2000/XP, ODF, PDF, RTF ou en format texte) clairement identifié à votre nom contenant l’analyse demandée à la première question du travail. L’objet de votre courriel doit commencer par « [INF6450][TRAVAIL5] »; dans le message, indiquez votre nom, votre numéro d’étudiant (8 chiffres), la date de remise de votre travail et le nom de votre personne tutrice, ainsi que les mentions « Travail noté 5 » et « INF 6450 ». Ne transmettez pas une archive compressée (zip ou autre). Il s’agit d’un travail personnel et vous ne devez pas partager vos solutions. CC BY-NC-SA Module 4 : Traitement du XML en Java 4.6.3 240 Exercice 1 Supposons une liste de transactions avec un attribut « montant » pour chaque client, comme dans le document XML suivant : <?xml version="1.0" encoding="ISO-8859-1" ?> <liste> <client nom="Jean Charles"> <transaction montant="500" /> <question>Quelle est la dernière marque?</question> <transaction montant="1200" /> </client> <client nom="Pierre Élisabeth"> <transaction montant="600" /> <transaction montant="800" /> <question>Où puis-je trouver le modèle 2002?</question> <transaction montant="2000" /> </client> </liste> Supposons que le fichier se nomme « transactions.xml ». Nous ne savons pas combien de transactions il peut y avoir par client; nous ne savons pas combien de clients nous avons; de plus, nous ne connaissons pas les noms des clients d’avance. Nous supposons que l’élément-racine est toujours « liste »; que tous les éléments « transaction » ont un attribut « montant »; que tous les éléments « transaction » sont dans des éléments « client »; que les éléments « client » sont tous dans l’élément-racine et ont tous un attribut « nom ». Nous supposons également qu’il n’y aura pas deux attributs « nom » avec la même valeur (même nom). Enfin, nous supposons que toutes les valeurs d’attribut de « montant » sont des entiers (« int » en Java). Écrivez un programme qui calcule la somme des valeurs de l’attribut « montant » pour chaque client (seuls les attributs « montant » des éléments « transaction »). Nous supposons qu’il s’agit de nombres entiers, des dollars par exemple. Le code source de votre programme sera dans un fichier nommé « Transactions.java ». Ainsi, la commande « java Transactions transactions.xml » devra donner : Nom du Somme: Nom du Somme: client: Jean Charles 1700 client: Pierre Élisabeth 3400 Comparez la solution que vous obtenez en utilisant DOM avec ce qui est possible de faire avec XSLT, en fonction du temps de développement. Donnez au moins un avantage de l’approche DOM sur l’approche XSLT et un avantage de l’approche XSLT sur DOM. Vous devez remettre une solution XSLT sous la forme d’un document XML. CC BY-NC-SA Travail noté 5 241 Vous pouvez mettre des commentaires dans votre code Java, mais la comparaison entre DOM et XSLT doit être faite dans un document à part. 4.6.4 Exercice 2 Avec XSLT, nous pouvons combiner plusieurs documents en utilisant la fonction « document » qui permet de charger plusieurs documents XML. Mais que se passe-t-il lorsque nous devons combiner plusieurs documents, dont certains ne sont pas en XML? À ce moment, l’utilisation d’un langage comme Java et de DOM peut être très avantageuse. Supposons qu’un serveur enregistre les achats effectués sur le site, dans un fichier texte, en plaçant chaque achat sur une ligne avec des informations séparées par des virgules. Le fichier se nomme « achats.txt » : Jean Charles, 3214324565, 321, 2 Yvan Richard, 5435435545, 321, 1 Yvette Gagnon, 4324324243, 1, 12 Sur chaque ligne, se trouvent le nom du client, son numéro de carte de crédit, le code du produit acheté et la quantité achetée. Nous supposons que le serveur est un logiciel commercial et qu’il n’est pas possible de le modifier pour obtenir le format des données en XML. Par ailleurs, nous avons un document XML contenant notre inventaire; le fichier se nomme « inventaire.xml ». Le voici : <?xml version="1.0" encoding="ISO-8859-1"?> <inventaire> <produit code="1" prix="432.00" quantité= "43" /> <produit code="32" prix="32.00" quantité= "100" /> <produit code="321" prix="31.00" quantité= "200" /> </inventaire> Écrivez un programme qui met à jour l’inventaire en tenant compte des achats de la journée, contenus dans le fichier « achats.txt ». Votre code source devra se trouver dans le fichier « Inventaire.java » et la commande « java Inventaire achats.txt inventaire.xml » va modifier le fichier « inventaire » pour y soustraire les produits achetés ce qui, dans le cas qui nous concerne, donnera un fichier « inventaire.xml » ayant le contenu suivant : <?xml version="1.0" encoding="ISO-8859-1"?> <inventaire> <produit code="1" prix="432.00" quantité= "31" /> <produit code="32" prix="32.00" quantité= "100" /> <produit code="321" prix="31.00" quantité= "197" /> </inventaire> CC BY-NC-SA Module 4 : Traitement du XML en Java 242 Nous pouvons supposer que le fichier « inventaire.xml » ne contient qu’un seul élément « produit » pour chaque valeur d’attribut « code ». Nous pouvons aussi supposer qu’aucun code invalide n’apparaît dans le fichier « achats.txt ». Par contre, nous ne savons pas combien de produits nous avons et combien d’achats il y aura. Évidemment, il est possible d’avoir un nombre négatif de produits dans notre inventaire. Indice.- Il est parfaitement possible d’écrire un tel programme en moins de 50 lignes. 4.6.5 Exercice 3 Il arrive que les données initiales ne soient pas en XML. Dans cet exercice, nous vous demandons de concevoir une calculatrice qui affiche ses résultats en XML (MathML pour être plus précis). Tout d’abord, pour vous convaincre qu’on peut écrire des équations en XML, transcrivez le contenu XML suivant dans un fichier nommé « math.xml » : <?xml version="1.0" encoding="ISO-8859-1"?> <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow> <mn>1</mn> <mo>+</mo> <mn>2</mn> <mo>=</mo> <mn>3.0</mn> </mrow> </math> Si vous ouvrez ce ficher dans Mozilla Firefox, vous devriez voir s’afficher le texte « 1 + 2 = 3 ». Cela signifie que Firefox reconnaît la syntaxe MathML. Vous pouvez constater que cette syntaxe n’est pas très complexe, du moins pour des exemples simples. Sachez que l’espace de noms de MathML est « http://www.w3.org/1998/Math/MathML ». Il faut utiliser comme élément-racine un élément « math », lui-même contenant un élément « mrow ». L’élément « mrow » pourra contenir un succession d’éléments « mn » (pour les nombres) et d’éléments « mo » (pour les opérateurs, comme « + », « < », « > », « - »). Si le résultat attendu est du texte, comme « vrai » ou « faux », il faut utiliser l’élément « mrow » contenant un élément « mtext » qui lui contient le texte, par exemple <mrow><mtext>vrai</mtext></mrow>). Vous devez créer un programme dont le code source se trouvera dans un fichier nommé « Calculatrice.java Votre programme doit utiliser l’API DOM. La calculatrice ne saura faire que 4 opérations : addition, soustraction et deux opérations de comparaison (< et >) dont la réponse est « vrai » ou « faux ». Ainsi, toutes les opérations se retrouvent dans la forme : 1 + 2, 1 - 2, 1 < 2 et 2 > 1. Par exemple, la commande « java Calculatrice 1.5 "<" 2 » devrait produire à l’écran (dans la fenêtre de commande) ceci : CC BY-NC-SA Travail noté 5 243 <?xml version="1.0" encoding="ISO-8859-1"?> <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow> <mn>1.5</mn> <mo><</mo> <mn>2</mn> <mo>=</mo> <mrow><mtext>vrai</mtext></mrow> </mrow> </math> Notez qu’on remplace < et > par « "<" » et « ">" » dans une ligne de commande parce que ces deux symboles ont des significations particulières et que votre environnement de commande pourrait les interpréter comme une demande de rediriger la sortie vers un fichier. D’autre part, « java Calculatrice 2 - 1 » devrait donner : <?xml version="1.0" encoding="ISO-8859-1"?> <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow> <mn>2</mn> <mo>-</mo> <mn>1</mn> <mo>=</mo> <mn>1.0</mn> </mrow> </math> 4.6.6 Exercice 4 Il est parfois pénible d’utiliser l’interface DOM quand on cherche une seule information précise. Écrivez un programme Java qui permet d’extraire le prix correspondant à l’item ayant le code de produit 321 dans un fichier XML ayant la forme suivante en utilisant une expression XPath. <?xml version="1.0" encoding="ISO-8859-1"?> <inventaire> <produit code="1" prix="432.00" quantité= "43" /> <produit code="32" prix="32.00" quantité= "100" /> <produit code="321" prix="31.00" quantité= "200" /> </inventaire> CC BY-NC-SA Module 4 : Traitement du XML en Java 4.6.7 244 Exercice 5 En utilisant AJAX, on peut rendre une page web dynamique. Malheureusement, pour des raisons de sécurité, un script dans une page web ne peut charger un fichier qui se trouve dans un domaine autre que celui d’origine. On vous demande donc de déposer le fichier ledevoir.xml (il faut suivre l’hyperlien) sur votre machine et de créer une page web AJAX capable de charger le fichier XML en question et d’afficher tant le titre des nouvelles que leur description complète. Attention, il ne faut récupérer que le contenu des éléments au sein des éléments item. Vous pouvez supposer que les titres et descriptions ne contiennent que du texte, sans éléments HTML. Si vous préférez, vous pouvez aussi utiliser le dernier fil de nouvelle du devoir, disponible à l’adresse « http:/ /www.ledevoir.com/rss/ledevoir.xml ». Si les descriptions contiennent du texte sous la forme <a href="...">, il n’est pas nécessaire de les afficher sous la forme d’hyperliens. Certains étudiants trouvent utile d’utiliser la syntaxe « try catch(e) » de l’ECMAScript (qui fonctionne comme en Java) pour traiter les erreurs. Cependant, cette syntaxe n’est pas nécessaire. CC BY-NC-SA Module 5 : Resource Description Framework (RDF) 5.1 5.1.1 Aperçu Objectifs Les graphes annotés sont un outil puissant de représentation des connaissances; en XML, on utilise certains graphes dirigés et annotés. Le module 5 porte sur le « Resource Description Framework (RDF) », une forme de représentation des connaissances; le modèle RDF est un modèle de graphe pouvant s’écrire en XML. Bien qu’il s’agisse d’une norme qui fait appel à des concepts abstraits, dans la pratique, le RDF est très utilisé. Il suffit de faire une recherche sur le web sur des sujets comme « Dublin Core, Creative Commons, FOAF, RSS 1.0 » pour constater à quel point le RDF est présent. Le résultat d’une recherche sur Google pour « Dublin Core » donne 1,2 million de pages; la recherche sur « Creative Commons » annonce 5,5 millions de pages et celle sur « FOAF » donne 1,5 million de pages. De plus, le RDF est intimement lié au XML, car très souvent des données RDF sont écrites en format XML. L’objectif spécifique du module est : – Interpréter un fichier RDF comme un tableau sujet/verbe/objet. Une activité, le travail noté 6, nous permettra d’évaluer votre atteinte de cet objectif. Avant d’entreprendre votre démarche, lisez le texte qui suit. 5.1.2 Représentation des connaissances et graphes Le cours porte sur le XML en tant qu’outil pour la gestion des connaissances. Nous avons vu, dans les modules précédents, le rôle que peut jouer le XML comme outil dans la gestion des données, qui sont une forme de connaissances de premier niveau : le 245 Module 5 : Resource Description Framework (RDF) 246 XML rend plus facile l’échange et la transformation des données. De plus, notamment dans le module 2, nous avons vu que le XML permet le marquage « sémantique » des informations; le XML s’impose donc naturellement comme outil de gestion des connaissances. En effet, prenons cet exemple de marquage sémantique : <?xml version="1.0" encoding="ISO-8859-1"?> <personne> <nomdefamille>Jean</nomdefamille> <datedenaissance>3 février 1971</datedenaissance> </personne> Ce document XML contient non seulement l’information souhaitée, mais en plus, à un niveau élémentaire, il nous permet de comprendre le sens de cette information, grâce aux noms des balises. Cependant, utiliser le nom des balises pour représenter les connaissances n’est pas toujours très pratique. Supposons que nous ayons deux documents XML semblables à celui de l’exemple précédent. Comment pouvons-nous représenter le fait que les deux personnes sont amies? Une façon plus naturelle de représenter les connaissances est d’utiliser des graphes. Un graphe est un ensemble de nœuds liés par des relations d’un nœud à un autre. Par exemple, l’ensemble des pages web forme un graphe avec la relation « contient un lien vers ». On dit que le graphe est « dirigé » si les relations sont à sens unique. Le web est un exemple de graphe dirigé : une page web peut avoir un lien vers une autre page web, qui elle-même ne contient pas un lien de retour vers la page d’origine. On dit qu’un graphe est « annoté » si les relations entre deux nœuds peuvent être de différentes natures. Par exemple, une communauté d’humains forme un graphe dirigé avec les relations « est ami avec » et « est parent avec ». Supposons que les relations « est ami avec » et « est parent avec » soient réflexives, alors le graphe d’humains est annoté, mais pas dirigé. Par contre, si nous acceptons qu’une personne puisse être l’ami de quelqu’un sans que cette personne soit son ami, alors le graphe d’humains sera annoté et dirigé. Pour des raisons pratiques, nous représentons les graphes avec des tableaux en trois colonnes. 5.1.3 Démarche Il faut avoir terminé le premier module avant de s’attaquer au module 5; en outre, il sera très utile d’avoir commencé les modules 2, 3 et 4 afin d’avoir suffisamment d’expérience avec le XML. Nous vous suggérons d’étudier, dans l’ordre, les deux textes proposés et de répondre aux questionnaires d’autoévaluation les accompagnant : – Introduction au RDF; – Le RDF par l’exemple, Dublin Core, Creative Commons, FOAF, RSS/Atom. CC BY-NC-SA Introduction au RDF 247 Le module se termine par le travail noté 6, qui prend la forme d’une activité de synthèse. Il est recommandé de répondre d’abord aux deux questionnaires d’autoévaluation avant de réaliser ce travail. 5.1.4 Préparation à l’examen Une fois les activités du module terminées, vous devrez vous préparer à l’examen. Pour vérifier si vous êtes prêt, vous pouvez télécharger l’examen factice (PDF, 79 Ko). Si vous pouvez faire cet examen sans problème, tout va bien. Pour vérifier vos réponses, consultez le corrigé (PDF, 195 Ko). 5.1.5 Évaluation du cours Lorsque vous aurez terminé le cours, répondez au questionnaire d’évaluation du cours (Microsoft Word, 163 Ko) , afin de nous aider à l’améliorer. Votre opinion et vos commentaires sont très importants pour nous. Nous vous remercions à l’avance de votre collaboration. 5.2 5.2.1 Introduction au RDF Introduction Le Resource Description Framework (RDF) est un langage pour les métadonnées sur le web, c’est-à-dire un langage pour énoncer ce que l’on sait sur quelque chose ou quelqu’un. Par exemple, le RDF est idéal pour indiquer qui est l’auteur d’un document ou quel est le titre du document. De plus, le langage RDF est prévu pour être à la fois simple (mais tout est relatif), suffisamment puissant pour « tout » décrire, et facilement utilisable par des logiciels. Dans le deuxième texte que nous proposons, Le RDF par l’exemple, nous verrons quelques applications intéressantes. Pour l’instant, nous ne présentons dans ce texte que les concepts de base. 5.2.2 Point de vue critique Le RDF demeure relativement peu utilisé dans des applications complexes, même s’il s’agit d’une idée simple et élégante. Une des raisons qui contribue sans aucun doute à ce manque de popularité du RDF, est la syntaxe RDF/XML qui n’est pas très jolie. CC BY-NC-SA Module 5 : Resource Description Framework (RDF) 5.2.3 248 Notions de base Le RDF a été normalisé en 1999 (par une recommandation W3C) et est un effort commun de plusieurs experts. Le RDF se veut suffisamment riche pour représenter de façon formelle la connaissance tout en étant simple à utiliser. Une des prémisses du format RDF est que tout peut être énoncé en utilisant des triplets : sujet, verbe et objet. Notez que certains auteurs utiliseront le terme « prédicat » au lieu du terme « verbe ». Par exemple, pour décrire « Jean », nous dirons que « Jean est un garçon » et nous décomposerons ainsi cette affirmation : <Jean><est><garçon>, ou l’afficherons dans un tableau : Sujet Verbe Objet Jean est garçon Nous ne faisons pas de la grammaire, mais bien de la représentation : le verbe n’a pas à être un verbe de la langue française ou anglaise. L’important est que le verbe soit un lien, une relation, entre une première chose (sujet) et une seconde (objet). Par exemple, si nous voulons affirmer que le titre de la page web « http://www.daniel-lemire.com/ » est « Daniel Lemire’s blog », nous pouvons le faire à l’aide du tableau suivant : Sujet Verbe Objet http://www.danieltitre Daniel Lemire’s blog lemire.com/ Ces exemples de représentation ne sont pas encore des exemples de données « RDF », car en RDF, le verbe doit être un URI. Le RDF, tout comme le XML, est fait pour être traité par des machines et les machines sont bêtes. Elles ne savent pas ce que signifie le mot « titre » dans le tableau précédent. Est-ce un titre à la Bourse, le titre d’une fonction (comme docteur) ou le titre d’une page? Pour régler ce problème, il faut utiliser des URI (Uniform Resource Identifier), c’est-à-dire des adresses fictives qui identifient une ressource Internet. Un URI contient un protocole (http, mailto, ftp, etc.), un domaine comme « fichiers.com » et un chemin comme « /mesfichiers/index.html ». Dans ce cours, nous adoptons la norme RFC2396 et nous permettons que les URI comportent le symbole du dièse ( # ), comme « ftp://fichiers.com#maman » : tout ce qui apparaît après ce symbole forme le « fragment ». Notons que les accents ne peuvent pas être utilisés dans un URI; ainsi, « http://école.com » n’est pas un URI valable. Un protocole particulier, « urn », est parfois utilisé dans les URI. Par exemple, pour identifier un livre par son code ISBN, nous pouvons utiliser l’URI « urn:ISBN:0-123-12345-1 ». La casse est significative dans un URI sauf pour le nom du protocole (HTTP ou http) et le nom du domaine (xerox.com ou XEROX.COM). Toutes les URL (Uniform Resource Locator) utilisées sur le web, comme « http://www.google.com », « mailto:[email protected] », « ftp://fichiers.com », ainsi que d’autres adresses ayant la même syntaxe, mais qui ne pointent pas nécessairement vers une ressource Internet existante, sont des exemples d’URI. Ainsi, si l’on vous donne l’URI « http://www.mydomain.com/daniel », il n’est pas certain qu’une page CC BY-NC-SA Introduction au RDF 249 web se trouve à cette adresse. Le seul but des URI est d’identifier des ressources. Le mot « ressource » a un sens très, très large : tout peut être considéré comme une ressource. Par exemple, pour identifier l’humoriste « Daniel Lemire », nous pouvons adopter l’URI « http://www.daniellemire.com/luimeme »; ce sera un bon choix si l’humoriste en question est propriétaire du nom de domaine (daniellemire.com) et compte le garder longtemps. Par ailleurs, on pourra utiliser l’URI « http://www.daniel-lemire.com/fr/ » pour identifier le professeur « Daniel Lemire » qui est responsable d’un cours portant sur le XML. Dans ce dernier exemple, l’URI est aussi un URL qui pointe vers la page personnelle du professeur. Nous voyons immédiatement l’avantage des URI : alors que l’ordinateur ne saura pas toujours faire la différence entre « Daniel Lemire » l’humoriste et « Daniel Lemire » le professeur, nous pourrons, en utilisant des URI, analyser automatiquement l’information, à la condition que tous utilisent le même URI pour représenter la même ressource. Pour distinguer les individus, nous pourrions utiliser leur numéro d’assurance sociale... Mais comme le concept de ressource est général, il faut aussi pouvoir distinguer les différentes significations que peuvent prendre le mot « titre », et ainsi de suite. La langue française (ou anglaise) permet à un mot d’avoir plusieurs sens, alors que chaque URI représente un concept et un concept seulement. Supposons maintenant que nous voulions décrire l’affirmation suivante en RDF : « Il y a une personne appelée Daniel Lemire dont l’adresse de courriel est [email protected] et qui est professeur. » Cette phrase peut être très difficile à analyser par un ordinateur. Commençons par la décomposer en affirmations simples : sujet/verbe/objet. D’abord, pour qu’il n’y ait pas de confusion, nous allons identifier l’individu s’appelant Daniel Lemire par l’URI « http://www.daniel-lemire.com/fr/ ». – http://www.daniel-lemire.com/fr/ est une personne. – http://www.daniel-lemire.com/fr/ s’appelle Daniel Lemire. – http://www.daniel-lemire.com/fr/ peut être joint par courriel à [email protected]. – http://www.daniel-lemire.com/fr/ a le titre de professeur. Rappelons ici que tous les verbes et tous les sujets doivent être identifiés par des URI. En ce qui nous concerne, il n’y a qu’un seul sujet identifié par « http://www.daniellemire.com/fr/ ». Il reste à trouver des URI pour les verbes et certains objets. Prenons d’abord la première affirmation : « http://www.daniel-lemire.com/fr/ est une personne ». Le verbe « être », dans cette phrase, associe la classe « personne » (au même sens que dans la programmation orientée objet) à la ressource « http://www.daniellemire.com/fr/ ». Nous pourrions inventer un URI ayant ce sens, mais il en existe déjà un : « http://www.w3.org/1999/02/22-rdf-syntax-ns#type ». Chaque fois que nous rencontrons cet URI, cela signifie qu’une ressource appartient à une certaine classe. Quant à l’objet « personne », il existe au moins un URI pour noter la classe « personne », soit « http://www.w3.org/2000/10/swap/pim/contact#Person ». Nous verrons que dans d’autres contextes, d’autres URI peuvent être utilisés avec un sens similaire. Finalement, l’affirmation « http://www.daniel-lemire.com/fr/ est une personne » peut s’écrire comme ceci : CC BY-NC-SA Module 5 : Resource Description Framework (RDF) Sujet http://www.daniellemire.com/ en/ Verbe http://www.w3.org/1999/ 02/22-rdf-syntax-ns#type 250 Objet http://www.w3.org/ 2000/ 10/swap/pim/ contact#Person Passons maintenant à la deuxième affirmation : « http://www.daniel-lemire.com/fr/ s’appelle Daniel Lemire ». Le verbe « s’appelle » peut être identifié par l’URI « http://www.w3.org/2000/10/swap/pim/contact#fullName ». Encore une fois, nous aurions pu inventer notre propre URI, en autant que nous utilisons toujours le même avec la même signification. L’objet, « Daniel Lemire », n’a pas de signification particulière et n’est qu’une chaîne de caractères; nous ne sommes donc pas tenus d’utiliser un URI. Cela n’est vrai que pour les objets : les sujets et les verbes doivent toujours être représentés par des URI en RDF. Nous obtenons le tableau suivant : Sujet Verbe Objet http://www.danielhttp://www.w3.org/ "Daniel Lemire" lemire.com/ en/ 2000/ 10/swap/pim/ contact#fullName Nous notons les chaînes de caractères avec les guillemets : alors que « http://www.unuri.org » est un URI, « "http://www.unuri.org" » est une chaîne de caractères. Dans l’affirmation « http://www.daniel-lemire.com/fr/ peut être joint par courriel à [email protected] », nous pouvons remplacer le verbe par « http://www.w3.org/2000/10/swap/pim/contact#mailbox ». Quant à l’objet « [email protected] », c’est une adresse de courriel; afin qu’un ordinateur puisse comprendre qu’il s’agit d’une adresse de courriel et non d’une chaîne de caractères, nous utiliserons l’URL « mailto:[email protected] » pour le représenter. Nous avons donc le tableau suivant : Sujet Verbe Objet http://www.danielhttp://www.w3.org/ mailto:[email protected]/ en/ 2000/ 10/swap/pim/ luq.uqam.ca contact#mailbox L’affirmation « http://www.daniel-lemire.com/fr/ a le titre de professeur » se traite de la même manière, de telle sorte que nous obtenons finalement le tableau suivant : Sujet Verbe Objet http://www.danielhttp://www.w3.org/1999/ http://www.w3.org/ lemire.com/ en/ 02/22-rdf-syntax-ns#type 2000/ 10/swap/pim/ contact#Person http://www.danielhttp://www.w3.org/ "Daniel Lemire" lemire.com/ en/ 2000/ 10/swap/pim/ contact#fullName CC BY-NC-SA Introduction au RDF Sujet http://www.daniellemire.com/ en/ http://www.daniellemire.com/ en/ 251 Verbe http://www.w3.org/ 2000/ 10/swap/pim/ contact#mailbox http://www.w3.org/ 2000/ 10/swap/pim/ contact#personalTitle Objet mailto:[email protected] "Professeur" Précisons qu’en RDF, l’ordre des affirmations est sans importance. Ainsi, l’ordre des rangées dans le tableau est sans importance. Ce tableau est une description formelle de notre phrase d’origine « Il y a une personne appelée Daniel Lemire dont l’adresse de courriel est [email protected] et qui est professeur. »; cette description peut être traitée par un ordinateur. Comme nous le verrons plus loin, ce tableau RDF peut s’écrire en XML de la façon suivante : <?xml version="1.0" encoding="ISO-8859-1"?> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:contact="http://www.w3.org/2000/10/swap/pim/contact#"> <contact:Person rdf:about="http://www.daniel-lemire.com/fr/"> <contact:fullName>Daniel Lemire</contact:fullName> <contact:mailbox rdf:resource="mailto:[email protected]"/> <contact:personalTitle>Professeur</contact:personalTitle> </contact:Person> </rdf:RDF> On peut aussi représenter graphiquement le tableau RDF : http://www.daniel-lemire.com/fr/ Type Person Daniel Lemire fullName mailbox personalTitle [email protected] Professeur Nous pouvons également spécifier dans quelle langue une chaîne de caractères est écrite; par exemple, le mot « professeur » n’a de sens qu’en français. Pour ce faire, nous utiliserons un attribut « xml:lang » ayant pour valeur un code ISO à deux caractères pour représenter la langue : « fr » pour français, « en » pour anglais, et ainsi de suite. Notre exemple modifié se lit comme suit : <?xml version="1.0" encoding="ISO-8859-1"?> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:contact="http://www.w3.org/2000/10/swap/pim/contact#"> <contact:Person rdf:about="http://www.daniel-lemire.com/fr/"> CC BY-NC-SA Module 5 : Resource Description Framework (RDF) 252 <contact:fullName>Daniel Lemire</contact:fullName> <contact:mailbox rdf:resource="mailto:[email protected]"/> <contact:personalTitle xml:lang="fr">Professeur</contact:personalTitle> </contact:Person> </rdf:RDF> Le choix de la langue ne constitue pas une nouvelle relation RDF, mais vient simplement annoter l’objet : dans un tableau sujet/verbe/objet, nous nous contenterons, par exemple, de remplacer « "Professeur" » par « "Professeur" (français) ». Nous pouvons résumer le RDF comme ceci : – – – – Le RDF peut être utilisé pour représenter tout objet, tant un site web qu’un individu. Le RDF peut être traité par une machine. Le RDF est composé de triplets : sujet/verbe/objet. Le sujet est toujours identifié par un URI; mais dans certains cas, on peut omettre l’URI et alors, un URI factice sera généré dynamiquement. – Le verbe est toujours identifié par un URI, sans aucune exception. – L’objet est soit un URI, soit une valeur explicite (une chaîne de caractères, par exemple). – Le RDF peut être représenté en XML. 5.2.4 Le RDF en XML Avertissement.- Tous les contenus RDF ne peuvent être représentés en XML selon la méthode que nous venons de présenter. La grande majorité du contenu RDF peut l’être, mais il y a des exceptions. Pour éviter les problèmes, nous supposerons ici que l’URI du verbe prend la forme « http://www.domaine.com/blabla/bla#vvv ». En d’autres termes, l’URI du verbe contient le symbole du dièse ( # ) et le texte après ce symbole est un nom XML valable (pouvant être utilisé comme balise). Il existe plusieurs façons de représenter le RDF en XML, mais nous n’étudierons que l’approche préconisée par le W3C, qui est l’approche la plus courante. Par ailleurs, nous n’étudierons pas toute la syntaxe RDF/XML, mais seulement ce qui est nécessaire pour comprendre la majorité du RDF qui se trouve actuellement sur le web. En règle générale, les documents XML représentant du contenu RDF n’ont pas de DTD, mais utilisent les espaces de noms. Nous commençons habituellement un document par une déclaration XML qui sera soit « <?xml version="1.0"?> », soit « <?xml version="1.0" encoding="ISO-8859-1"?> » pour permettre l’utilisation des accents français. Ensuite, viendra toujours l’élément RDF comme élément-racine. Ainsi, un des documents XML les plus simples possibles représentant du contenu RDF est : <?xml version="1.0" encoding="ISO-8859-1"?> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> </rdf:RDF> CC BY-NC-SA Introduction au RDF 253 Observez l’utilisation de l’espace de noms identifié par l’URI « http://www.w3.org/1999/02/22-rdf-syntax-ns# ». Le fait de noter l’espace de noms par les trois lettres « rdf » est sans conséquence et nous pourrions aussi écrire : <?xml version="1.0" encoding="ISO-8859-1"?> <nimportequoidautre:RDF xmlns:nimportequoidautre="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> </nimportequoidautre:RDF> L’important, c’est que l’élément-racine RDF soit dans l’espace de nom « http://www.w3.org/1999/02/22-rdf-syntax-ns# ». Supposons maintenant que nous voulions décrire l’affirmation RDF suivante : Sujet Verbe Objet http://www.danielhttp://www.w3.org/ mailto:[email protected]/fr/ 2000/ 10/swap/pim/ luq.uqam.ca contact#mailbox La première étape consiste à décomposer l’URI du verbe en deux parties : l’URI jusqu’au symbole « # » inclusivement, soit « http://www.w3.org/2000/10/swap/pim/contact# », et le reste du texte, soit « mailbox ». La première partie devient un espace de noms, et la deuxième, appelée fragment, deviendra un nom d’élément. On utilise ensuite habituellement une balise « Description » dans l’espace de noms « http://www.w3.org/1999/02/22-rdf-syntax-ns# » avec le nom d’attribut « about » comme ceci : <?xml version="1.0" encoding="ISO-8859-1"?> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/10/swap/pim/contact#" > <rdf:Description about="http://www.daniel-lemire.com/fr/"> <mailbox rdf:resource="mailto:[email protected]" /> </rdf:Description> </rdf:RDF> Dans cet exemple, le sujet est la valeur d’attribut de « about », soit « http://www.daniellemire.com/fr/ », le verbe est le nom de l’élément contenu dans l’élément « rdf:Description », ici « mailbox », auquel on ajoute en préfixe l’espace de noms auquel il appartient, soit « http://www.w3.org/2000/10/swap/pim/contact# ». L’URI de l’objet est la valeur de l’attribut « rdf:resource », soit « mailto:[email protected] ». Pour nous assurer de bien comprendre, voyons un autre exemple, quoique plus abstrait. Supposons que nous ayons le contenu RDF suivant : Sujet Verbe Objet http://domaine.com/ http://dohttp://www.objet.com/ page/ maine.com#unverbe Nous pourrions utiliser la représentation XML suivante : CC BY-NC-SA Module 5 : Resource Description Framework (RDF) 254 <?xml version="1.0" encoding="ISO-8859-1"?> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://domaine.com#" > <rdf:Description rdf:about="http://domaine.com/page/"> <unverbe rdf:resource="http://www.objet.com/" /> </rdf:Description> </rdf:RDF> Que devons-nous faire si l’objet n’est pas un URI, mais une chaîne de caractères? Dans ce cas, nous omettrons l’attribut « rdf:resource » et nous placerons notre valeur dans l’élément. Ainsi, pour représenter le contenu RDF suivant : Sujet Verbe Objet http://www.danielhttp://www.w3.org/ "Professeur" lemire.com/fr/ 2000/ 10/swap/pim/ contact#personalTitle nous pourrons utiliser le code XML qui suit : <?xml version="1.0" encoding="ISO-8859-1"?> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/10/swap/pim/contact#" > <rdf:Description rdf:about="http://www.daniel-lemire.com/fr/"> <personalTitle>Professeur</personalTitle> </rdf:Description> </rdf:RDF> Encore une fois, les conventions relatives aux espaces de noms s’appliquent et nous pourrions remplacer le XML de l’exemple précédent par celui-ci : <?xml version="1.0" encoding="ISO-8859-1"?> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:espacedenom="http://www.w3.org/2000/10/swap/pim/contact#" > <rdf:Description rdf:about="http://www.daniel-lemire.com/fr/"> <espacedenom:personalTitle>Professeur</espacedenom:personalTitle> </rdf:Description> </rdf:RDF> Donc, pour représenter l’ensemble des données RDF suivantes : Sujet Verbe Objet http://www.danielhttp://www.w3.org/ "Daniel Lemire" lemire.com/fr/ 2000/ 10/swap/pim/ contact#fullName http://www.danielhttp://www.w3.org/ mailto:[email protected]/fr/ 2000/ 10/swap/pim/ luq.uqam.ca contact#mailbox CC BY-NC-SA Introduction au RDF Sujet http://www.daniellemire.com/fr/ 255 Verbe http://www.w3.org/ 2000/ 10/swap/pim/ contact#personalTitle Objet "Professeur" nous utiliserons plusieurs éléments, les uns à la suite des autres, comme ceci : <?xml version="1.0" encoding="ISO-8859-1"?> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:espacedenom="http://www.w3.org/2000/10/swap/pim/contact#" > <rdf:Description rdf:about="http://www.daniel-lemire.com/fr/"> <espacedenom:fullName>Daniel Lemire</espacedenom:fullName> </rdf:Description> <rdf:Description rdf:about="http://www.daniel-lemire.com/fr/"> <espacedenom:mailbox rdf:resource="mailto:[email protected]" /> </rdf:Description> <rdf:Description rdf:about="http://www.daniel-lemire.com/fr/"> <espacedenom:personalTitle>Professeur</espacedenom:personalTitle> </rdf:Description> </rdf:RDF> En pratique toutefois, nous ne répétons pas l’élément « Description » avec la même valeur d’attribut « about »; nous préférons la syntaxe qui suit : <?xml version="1.0" encoding="ISO-8859-1"?> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:espacedenom="http://www.w3.org/2000/10/swap/pim/contact#" > <rdf:Description rdf:about="http://www.daniel-lemire.com/fr/"> <espacedenom:fullName>Daniel Lemire</espacedenom:fullName> <espacedenom:mailbox rdf:resource="mailto:[email protected]" /> <espacedenom:personalTitle>Professeur</espacedenom:personalTitle> </rdf:Description> </rdf:RDF> Et comme l’ordre est sans importance en RDF, nous pourrions aussi avoir le XML suivant : <?xml version="1.0" encoding="ISO-8859-1"?> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:espacedenom="http://www.w3.org/2000/10/swap/pim/contact#" > <rdf:Description rdf:about="http://www.daniel-lemire.com/fr/"> CC BY-NC-SA Module 5 : Resource Description Framework (RDF) 256 <espacedenom:personalTitle>Professeur</espacedenom:personalTitle> <espacedenom:fullName>Daniel Lemire</espacedenom:fullName> <espacedenom:mailbox rdf:resource="mailto:[email protected]" /> </rdf:Description> </rdf:RDF> 5.2.5 Les classes en RDF Jusqu’à présent, nous n’avons pas représenté en XML l’affirmation suivante : Sujet Verbe Objet http://www.danielhttp://www.w3.org/1999/ http://www.w3.org/ lemire.com/fr/ 02/22-rdf-syntax-ns#type 2000/ 10/swap/pim/ contact#Person Évidemment, nous pouvons tout simplement écrire ceci : <?xml version="1.0" encoding="ISO-8859-1"?> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/10/swap/pim/contact#" > <rdf:Description rdf:about="http://www.daniel-lemire.com/fr/"> <rdf:type rdf:resource="http://www.w3.org/2000/10/swap/pim/contact#Person" /> </rdf:Description> </rdf:RDF> Mais, avouons-le, c’est assez peu lisible. Dans « http://www.w3.org/2000/10/swap/pim/contact#Person », « Person » est un fragment. Dans les cas où l’URI contient un fragment, nous représentons l’affirmation de la façon suivante : <?xml version="1.0" encoding="ISO-8859-1"?> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/10/swap/pim/contact#" > <Person rdf:about="http://www.daniel-lemire.com/fr/"> </Person> </rdf:RDF> Nous remplaçons « rdf:Description » par le nom de la classe, soit « Person », avec le préfixe « http://www.w3.org/2000/10/swap/pim/contact# ». En pratique, cette dernière approche est presque toujours utilisée et son avantage devient évident quand on combine toutes les affirmations RDF de la première section : CC BY-NC-SA Introduction au RDF 257 Sujet http://www.daniellemire.com/ en/ Verbe http://www.w3.org/1999/ 02/22-rdf-syntax-ns#type http://www.daniellemire.com/ en/ http://www.w3.org/ 2000/ 10/swap/pim/ contact#fullName http://www.w3.org/ 2000/ 10/swap/pim/ contact#mailbox http://www.w3.org/ 2000/ 10/swap/pim/ contact#personalTitle http://www.daniellemire.com/ en/ http://www.daniellemire.com/ en/ Objet http://www.w3.org/ 2000/ 10/swap/pim/ contact#Person "Daniel Lemire" mailto:[email protected] "Professeur" Nous savons maintenant que nous pouvons représenter toutes ses informations par le XML suivant : <?xml version="1.0" encoding="ISO-8859-1" ?> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/10/swap/pim/contact#"> <Person rdf:about="http://www.daniel-lemire.com/fr/"> <fullName>Daniel Lemire</fullName> <mailbox rdf:resource="mailto:[email protected]" /> <personalTitle>Professeur</personalTitle> </Person> </rdf:RDF> C’est comme ça que nous pouvons écrire « Il y a une personne appelée Daniel Lemire dont l’adresse de courriel est [email protected] et qui est professeur. » en RDF/XML. 5.2.6 Et s’il n’y a pas de symbole « # » dans l’URI? Dans les exemples précédents, nous supposions que l’URI (du verbe) contenait un symbole « # », ce qui nous permettait de la décomposer en deux parties (nom et préfixe). Mais quoi faire si l’URI prend plutôt la forme « http://www.ondelette.com/employeur »? Dans un tel cas, nous pouvons choisir de retenir « http://www.ondelette.com/ » comme préfixe et « employeur » comme nom. Nous pourrons donc représenter les données RDF suivantes : Sujet Verbe Objet http://www.danielhttp:// http://www.uquebec.ca/ lemire.com/fr/ www.ondelette.com/ employeur par le XML suivant : CC BY-NC-SA Module 5 : Resource Description Framework (RDF) 258 <?xml version="1.0" encoding="ISO-8859-1" ?> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.ondelette.com/"> <rdf:Description rdf:about="http://www.daniel-lemire.com/fr/"> <employeur rdf:resource="http://www.uquebec.ca/" /> </rdf:Description> </rdf:RDF> 5.2.7 Des objets qui sont eux-mêmes des sujets Supposons que nous voulons dire que la pièce de théatre Othello a comme auteur William Shakespeare. En fait, nous voulons faire quatre affirmations : « Othello est une pièce de théatre », « Shakespeare est une personne », « Shakespeare est l’auteur d’Othello » et « Shakespeare a pour nom "William Shakespeare" ». Nous pourrions choisir de représenter en RDF ces quatre affirmations selon le tableau qui suit : Sujet Verbe Objet http://www.othello.org/ http://www.w3.org/1999/ http://unuri.org/PieceDe02/22-rdf-syntax-ns#type Theatre http://www.othello.org/ http://unuri.org/auteur http:// www.shakespeare.org http:// http://www.w3.org/1999/ http://unuri.org/Personne www.shakespeare.org 02/22-rdf-syntax-ns#type http:// http://unuri.org/nom "William Shakespeare" www.shakespeare.org Nous pouvons utiliser la représentation XML suivante : <?xml version="1.0" encoding="ISO-8859-1"?> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://unuri.org/"> <PieceDeTheatre rdf:about="http://www.othello.org/"> <auteur rdf:resource="http://www.shakespeare.org" /> </PieceDeTheatre> <Personne rdf:about="http://www.shakespeare.org"> <nom>William Shakespeare</nom> </Personne> </rdf:RDF> La représentation graphique du tableau RDF est : CC BY-NC-SA Introduction au RDF 259 http://www.othello.org/ type PieceDeTheatre auteur http://www.shakespeare.org type Personne nom William Shakespeare Nous pouvons cependant le faire plus brièvement. Considérons d’abord le modèle suivant : <?xml version="1.0" encoding="ISO-8859-1"?> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://unuri.org/"> <PieceDeTheatre rdf:about="http://www.othello.org/"> <auteur> (...) </auteur> </PieceDeTheatre> </rdf:RDF> Nous avons vu que si nous mettons un nœud de texte là où les points « (...) » apparaissent, nous associerons « http://www.othello.org/ » avec un objet texte par le verbe « http://unuri.org/auteur ». Cependant, si nous mettons plutôt un élément muni d’un attribut « rdf:about », ce sera l’URI contenu dans l’attribut qui deviendra l’objet; nous gagnons alors la possibilité d’utiliser ce même objet comme sujet à son tour, comme dans cet exemple : <?xml version="1.0" encoding="ISO-8859-1"?> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://unuri.org/"> <PieceDeTheatre rdf:about="http://www.othello.org/"> <!-- le verbe est http://unuri.org/auteur --> <auteur> <!-- début de l’objet --> <Personne rdf:about="http://www.shakespeare.org"> <!-- l’objet devient un sujet à son tour --> <nom>William Shakespeare</nom> </Personne><!-- fin de l’objet --> CC BY-NC-SA Module 5 : Resource Description Framework (RDF) 260 </auteur> </PieceDeTheatre> </rdf:RDF> Ce nouveau document RDF est équivalent aux trois affirmations RDF du début, mais il est un peu plus court. Nous pourrions pousser l’expérience plus loin - ce qui peut devenir absurde - comme dans l’exemple qui suit : <?xml version="1.0" encoding="ISO-8859-1"?> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://unuri.org/"> <PieceDeTheatre rdf:about="http://www.othello.org/"> <auteur rdf:resource="http://www.shakespeare.org" /> </PieceDeTheatre> <Personne rdf:about="http://www.shakespeare.org"> <nom> <Texte rdf:about="http://www.texte.org/william"> <contenu> William Shakespeare </contenu> </Texte> </nom> </Personne> </rdf:RDF> Ce document est maintenant équivalent au tableau suivant : Sujet Verbe Objet http://www.othello.org/ http://www.w3.org/1999/ http://unuri.org/PieceDe02/22-rdf-syntax-ns#type Theatre http://www.othello.org/ http://unuri.org/auteur http:// www.shakespeare.org http:// http://www.w3.org/1999/ http://unuri.org/Personne www.shakespeare.org 02/22-rdf-syntax-ns#type http://www.texte.org/ http://www.w3.org/1999/ http://unuri.org/Texte william 02/22-rdf-syntax-ns#type http://www.texte.org/ http://unuri.org/contenu "William Shakespeare" william http:// http://unuri.org/nom http://www.texte.org/ www.shakespeare.org william CC BY-NC-SA Introduction au RDF 5.2.8 261 Les contenants en RDF Il arrive fréquemment, en pratique, que l’on doive donner comme valeur à un objet, non pas une chaîne de caractères, mais plutôt un ensemble de chaînes de caractères. Par exemple, nous pouvons vouloir affirmer que « les étudiants du cours 101 sont Jean Roberge, Alexandre Coma et Julie LeChat ». Comment le faire? Supposons que l’URI du cours est « http://www.teluq.uqam.ca/101 » et que le verbe correspondant à « être inscrit à un cours » est identifié par l’URI « http://www.education.com#inscription ». Nous pouvons alors essayer ceci : <?xml version="1.0" encoding="ISO-8859-1" ?> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.education.com#"> <rdf:Description rdf:about="http://www.teluq.uqam.ca/101"> <inscription>Jean Roberge</inscription> <inscription>Alexandre Coma</inscription> <inscription>Julie LeChat</inscription> </rdf:Description> </rdf:RDF> Cela équivaut à remplacer l’affirmation « les étudiants du cours 101 sont Jean Roberge, Alexandre Coma et Julie LeChat » par les trois affirmations « le cours 101 a comme étudiant Jean Roberge », « le cours 101 a comme étudiant Alexandre Coma », « le cours 101 a comme étudiant Julie LeChat ». Il n’est pas certain qu’une telle décomposition de l’affirmation préserve toujours le sens original. Par exemple, nous pourrions vouloir donner la liste complète de tous les étudiants dans le cours. RDF nous permet de regrouper tous les étudiants dans un seul élément « Bag » (sac, en anglais) comme ceci : <?xml version="1.0" encoding="ISO-8859-1" ?> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.education.com#"> <rdf:Description rdf:about="http://www.teluq.uqam.ca/101"> <inscription> <rdf:Bag> <rdf:li>Jean Roberge</rdf:li> <rdf:li>Alexandre Coma</rdf:li> <rdf:li>Julie LeChat</rdf:li> </rdf:Bag> </inscription> </rdf:Description> </rdf:RDF> Les éléments dans un « Bag » ne sont pas ordonnés. Nous pourrons remplacer le XML précédent par celui-ci, sans problème : <?xml version="1.0" encoding="ISO-8859-1" ?> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" CC BY-NC-SA Module 5 : Resource Description Framework (RDF) 262 xmlns="http://www.education.com#"> <rdf:Description rdf:about="http://www.teluq.uqam.ca/101"> <inscription> <rdf:Bag> <rdf:li>Julie LeChat</rdf:li> <rdf:li>Jean Roberge</rdf:li> <rdf:li>Alexandre Coma</rdf:li> </rdf:Bag> </inscription> </rdf:Description> </rdf:RDF> Si l’ordre importe, alors nous utiliserons un élément « Seq » (pour séquence), comme dans l’exemple suivant qui énonce les jours de la semaine, dans l’ordre : <?xml version="1.0" encoding="ISO-8859-1" ?> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.jourdelasemaine.com#"> <rdf:Description rdf:about="http://www.jourdelasemaine.com/"> <journees> <rdf:Seq> <rdf:li>dimanche</rdf:li> <rdf:li>lundi</rdf:li> <rdf:li>mardi</rdf:li> <rdf:li>mercredi</rdf:li> <rdf:li>jeudi</rdf:li> <rdf:li>vendredi</rdf:li> <rdf:li>samedi</rdf:li> </rdf:Seq> </journees> </rdf:Description> </rdf:RDF> Finalement, nous pourrions ne pas connaître exactement la valeur de l’objet, mais savoir que la valeur appartient à un ensemble fini de possibilités. Par exemple, si nous jouons à un jeu de détective et qu’il n’y a que trois coupables possibles (le majordome, la princesse et le seigneur), nous écrirons : <?xml version="1.0" encoding="ISO-8859-1" ?> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.jeududetective.com#"> <rdf:Description rdf:about="http://www.jeududetective.com/partie/2004/10/"> <suspects> <rdf:Alt> <rdf:li>majordome</rdf:li> <rdf:li>princesse</rdf:li> <rdf:li>seigneur</rdf:li> CC BY-NC-SA Le RDF par l’exemple 263 </rdf:Alt> </suspects> </rdf:Description> </rdf:RDF> 5.2.9 RDFa Il peut sembler un peut lourd de créer des fichiers XML distincts pour stocker le RDF. Heureusement, il existe donc plusieurs approches pour inscrire le RDF à même des fichiers XHTML. La spécification RDFa permet d’inscrire du RDF directement au sein d’un document XHTML avec les attributs about et property. Voici un exemple d’annotation RDFa ajoutée à un élément XHTML : <ul xmlns:dc="http://purl.org/dc/elements/1.1/" about="http://www.example.com/books/wikinomics"> <li property="dc:title">Wikinomics</li> <li property="dc:author">Don Tapscott</li> <li property="dc:date">2006-10-01</li> </ul> 5.2.10 Conclusion Nous avons vu que le modèle RDF sert à décrire pratiquement n’importe quoi en associant des URI à tous les objets et relations. Les données RDF peuvent généralement être représentées en XML selon l’approche que nous avons décrite, ce qui permet de combiner les avantages du XML (format entièrement normalisé et non propriétaire, outils très disponibles, etc.), tout en gardant les avantages du RDF (contenu pouvant être traité par des machines, relative simplicité). Pour plus de détails, on peut consulter les articles du site mozilla.org sur le sujet (http://developer.mozilla.org/en/docs/RDF). Certains logiciels gratuits comme 4Suite (http://4suite.org/) peuvent traiter le contenu RDF/XML, mais ce n’est pas le cas des navigateurs web ou de la majorité des logiciels. Les graphiques de cette leçon furent générés avec 4Suite et inclus au texte en tant que SVG. 5.3 5.3.1 Le RDF par l’exemple Introduction Avant de lire ce texte, vous devez avoir lu « Introduction au RDF », car nous supposons que vous comprenez la syntaxe RDF de base. CC BY-NC-SA Module 5 : Resource Description Framework (RDF) 264 Le RDF se retrouve un peu partout sur le web, parfois de façon « invisible », c’est-à-dire qu’il est souvent utilisé dans les échanges automatiques entre les logiciels. En outre, il est utilisé au sein des portails, par exemple. Voyons maintenant quatre applications RDF bien établies : Dublin Core Il s’agit sans doute de l’utilisation la plus connue et la plus répandue du RDF. La norme Dublin Core est assez simple et vise à décrire les travaux rendus disponibles sur le web (auteur, titre, date, etc.). Cette norme s’inspire de la bibliothéconomie. Creative Commons Il s’agit d’une façon de décrire les droits accordés sur le contenu placé sur le web. Par exemple, vous voulez savoir si vous pouvez recopier telle ou telle page web; si l’auteur a utilisé la norme Creative Commons, alors vous devriez pouvoir savoir ce qui est permis par l’auteur. FOAF La norme FOAF (« Friend Of A Friend » - « ami d’un ami ») permet de décrire un individu et les gens qu’il connaît. Cette norme sert à traiter les réseaux sociaux. RSS/RDF La norme RSS est utilisée par les blogues et sites de nouvelles. Le site mozilla.org a plusieurs articles sur le sujet (http://developer.mozilla.org/en/docs/ RSS). En gros, un document RSS/RDF contient une version XML des dernières nouvelles. Par la suite, plusieurs de ces fichiers XML peuvent être combinés pour créer un portail de nouvelles ou utilisés avec un outil-client de type « RSS aggregator » pour obtenir automatiquement les dernières nouvelles (voir, par exemple, blogbridge). 5.3.2 Un exemple : Dublin Core La norme Dublin Core définit plusieurs « verbes » (au sein du RDF); on peut en consulter la liste à l’adresse http://dublincore.org/documents/dcmi-terms/ (en anglais). Cette norme a été publiée pour la première fois en juillet 1999. Le préfixe de la norme Dublin Core est « http://purl.org/dc/elements/1.1/ », du moins pour les éléments de base présentés ici. Voici les URI complets et leur signification : http://purl.org/dc/elements/1.1/creator Personne ou organisme qui est l’auteur du travail. http://purl.org/dc/elements/1.1/contributor Personne ou organisme qui a contribué à un travail, mais sans en être l’auteur. http://purl.org/dc/elements/1.1/coverage Lieu et période correspondant au travail. http://purl.org/dc/elements/1.1/date Date associée au travail, généralement sous la forme AAAA-MM-JJ. Il peut s’agir de la date de publication, de création ou de la dernière révision. http://purl.org/dc/elements/1.1/description Brève description du travail. CC BY-NC-SA Le RDF par l’exemple 265 http://purl.org/dc/elements/1.1/format Format sous lequel est publié le travail. Si le travail est publié en HTML, alors on utilisera souvent « text/html » pour décrire le format. http://purl.org/dc/elements/1.1/identifier Code ou URI qui correspond de façon unique au travail. Si un travail est publié à une adresse web, on peut utiliser cette adresse comme URI; si c’est un livre avec un ISBN, on peut utiliser un URI de la forme « urn:ISBN:0-123-12345-1 ». http://purl.org/dc/elements/1.1/language Code ISO-639/ISO-3166 décrivant le travail. Si le travail est publié en français, on peut utiliser « fr-CA »; sinon, en anglais, ce serait « en-CA » (CA signifie Canada). http://purl.org/dc/elements/1.1/publisher Organisme responsable de la publication du travail. http://purl.org/dc/elements/1.1/relation Ressource liée au travail. Par exemple, pour un travail fait en classe, on peut établir un lien avec l’exposé du travail. http://purl.org/dc/elements/1.1/rights Contient souvent une affirmation permettant de savoir qui est propriétaire du travail (détenteur du droit d’auteur). http://purl.org/dc/elements/1.1/source Résumé du travail de quelqu’un d’autre. Cet URI permet de pointer vers la source originale. http://purl.org/dc/elements/1.1/subject Généralement, une liste de mots clés. http://purl.org/dc/elements/1.1/title Titre du travail. http://purl.org/dc/elements/1.1/type Type de la ressource (texte, image, etc.). Notons que le « type » est différent du « format ». Par exemple, une image peut être en format Jpeg ou Gif, un texte peut être en format Word ou ASCII. Voyons comment nous pouvons décrire ce texte que vous êtes en train de lire, en utilisant la norme Dublin Core. Attribuons-lui l’URI « http://www.uqam.ca/rdfexemples.html ». Sujet Verbe Objet http://www.uqam.ca/ rd- http://purl.org/ dc/ http://www.danielfexemples.html elements/1.1/creator lemire.com/fr/ http://www.uqam.ca/ rd- http://purl.org/ dc/ "2004-07-27" fexemples.html elements/1.1/date http://www.uqam.ca/ rd- http://purl.org/ dc/ "Introduction au RDF" fexemples.html elements/1.1/title http://www.uqam.ca/ rd- http://purl.org/ dc/ "text" fexemples.html elements/1.1/type http://www.uqam.ca/ rd- http://purl.org/ dc/ "fr-CA" fexemples.html elements/1.1/Language http://www.uqam.ca/ rd- http://purl.org/ dc/ "RDF, Dublin Core, fexemples.html elements/1.1/subject Creative Commons, FOAF, RSS/RDF" http://www.uqam.ca/ rd- http://purl.org/ dc/ "Copyright 2005 Daniel fexemples.html elements/1.1/rights Lemire" CC BY-NC-SA Module 5 : Resource Description Framework (RDF) Sujet http://www.uqam.ca/ rdfexemples.html Verbe http://purl.org/ dc/ elements/1.1/description http://www.uqam.ca/ rdfexemples.html http://www.uqam.ca/ rdfexemples.html http://purl.org/ dc/ elements/1.1/format http://purl.org/ dc/ elements/1.1/identifier 266 Objet "Un document comprenant des exemples d’utilisation du RDF en gestion des connaissances." "text/html" http://www.uqam.ca/ rdfexemples.html Nous pouvons aussi représenter ce tableau en XML comme ceci : <?xml version="1.0" encoding="ISO-8859-1"?> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/"> <rdf:Description rdf:about="http://www.uqam.ca/rdfexemples.html"> <dc:creator rdf:resource="http://www.daniel-lemire.com/fr/" /> <dc:date>2004-07-27</dc:date> <dc:title>Introduction au RDF</dc:title> <dc:type>text</dc:type> <dc:Language>fr-CA</dc:Language> <dc:subject>RDF, Dublin Core, Creative Commons, FOAF, RSS/RDF</dc:subject> <dc:rights>Copyright 2005 Daniel Lemire</dc:rights> <dc:description>Un document comprenant des exemples d’utilisation du RDF en gestion des connaissances.</dc:description> <dc:format>text/html</dc:format> <dc:identifier rdf:resource="http://www.uqam.ca/rdfexemples.html" /> </rdf:Description> </rdf:RDF> Nous pouvons aussi représenter ce tableau sous la forme d’un graphe : CC BY-NC-SA Le RDF par l’exemple 267 http://www.daniel−lemire.com/fr/ creator 2004−07−27 date Introduction au RDF title identifier rdfexemples.html text type Language fr−CA subject rights RDF description Copyright 2005 Daniel Lemire format Un document comprenant des exemples d’utilisation du RDF en gestion des connaissances. html Évidemment, Dublin Core est une norme RDF et non pas une norme XML. Il est donc possible d’exprimer du contenu Dublin Core sans passer par le XML. Nous pourrions très bien nous en tenir au tableau sujet/verbe/complément ou utiliser une autre syntaxe. Notons aussi que les conventions d’espace de noms s’appliquent et que l’ordre n’est pas important. Nous pouvons donc remplacer le XML précédent par celui-ci : <?xml version="1.0" encoding="ISO-8859-1"?> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://purl.org/dc/elements/1.1/"> <rdf:Description rdf:about="http://www.uqam.ca/rdfexemples.html"> <creator rdf:resource="http://www.daniel-lemire.com/fr/" /> <title>Introduction au RDF</title> <date>2004-07-27</date> <type>text</type> <subject>RDF, Dublin Core, Creative Commons, FOAF, RSS/RDF</subject> <rights>Copyright 2005 Daniel Lemire</rights> <description>Un document comprenant des exemples d’utilisation du RDF en gestion des connaissances.</description> <format>text/html</format> <identifier rdf:resource="http://www.uqam.ca/rdfexemples.html" /> <Language>fr-CA</Language> </rdf:Description> CC BY-NC-SA Module 5 : Resource Description Framework (RDF) 268 </rdf:RDF> Il existe des applications plus sophistiquées de la norme Dublin Core, mais nous avons ici l’essentiel. Vous pouvez dès maintenant cataloguer les ressources d’une entreprise en utilisant simplement ce que nous venons de présenter. Comme la norme est utilisée partout dans le monde, il sera possible d’échanger ces descriptions ou d’utiliser des logiciels communs pour le traitement ou l’affichage des informations. 5.3.3 Un exemple : Creative Commons Une des limites apparentes de la norme Dublin Core est son incapacité à spécifier de façon précise les droits accordés sur un travail. Le problème est particulièrement fréquent sur le web : a-t-on le droit d’utiliser telle ou telle image gratuitement, de la reproduire, de la modifier, et ainsi de suite. Pour résoudre cette difficulté, les gens font appel à la norme Creative Commons, qui utilise le préfixe « http://web.resource.org/cc/ ». Cette norme définit une classe « Work » (travail, en anglais, ici au sens d’oœuvre), mais emprunte pratiquement tout le reste à Dublin Core qu’elle vient compléter. La norme Creative Commons a été proposée en 2001 par James Boyle, Michael Carroll, Lawrence Lessig, Hal Abelson, Eric Saltzman et Eric Eldred. Voici un exemple très simple d’une description utilisant la norme Creative Commons : Sujet Verbe Objet http://www.uqam.ca/ rd- http://www.w3.org/1999/ http://web.resource.org/ fexemples.html 02/22-rdf-syntax-ns#type cc/Work http://www.uqam.ca/ rd- http://purl.org/ dc/ "Le RDF par l’exemple" fexemples.html elements/1.1/title Et voici la version XML correspondante : <?xml version="1.0" encoding="ISO-8859-1"?> <rdf:RDF xmlns="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <Work rdf:about="http://www.uqam.ca/rdfexemples.html"> <dc:title>Le RDF par l’exemple</dc:title> </Work> </rdf:RDF> Tout ce que nous avons affirmé dans ce dernier document, c’est que la page actuelle appartient à la classe « Work ». Dans l’état actuel des choses, nous affirmons par défaut qu’il n’est pas permis d’utiliser cette page, car nous n’avons attribué aucune permission. Supposons que l’auteur désire accorder le droit au lecteur de redistribuer, de modifier et de partager cette page, pour autant qu’il utilise la même licence. Nous CC BY-NC-SA Le RDF par l’exemple 269 pourrions alors utiliser la licence « Attribution-ShareAlike 2.0 » dont l’URI est « http://creativecommons.org/licenses/by-sa/2.0/ ». Évidemment, nous pouvons aussi créer notre licence de toute pièce, mais dans l’exemple, nous utiliserons la licence « Attribution-ShareAlike 2.0 ». Pour faire un lien entre notre travail et une licence, nous utilisons le verbe dont l’URI est « http://web.resource.org/cc/license », comme ce qui suit; observez bien la dernière ligne du tableau. Sujet Verbe Objet http://www.uqam.ca/ rd- http://www.w3.org/1999/ http://web.resource.org/ fexemples.html 02/22-rdf-syntax-ns#type cc/Work http://www.uqam.ca/ rd- http://purl.org/ dc/ "Le RDF par l’exemple" fexemples.html elements/1.1/title http://www.uqam.ca/ rd- http://web.resource.org/ http://creativecomfexemples.html cc/license mons.org/licenses/by-sa/ 2.0/ Nous pouvons aussi utiliser le XML correspondant : <?xml version="1.0" encoding="ISO-8859-1"?> <rdf:RDF xmlns="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <Work rdf:about="http://www.uqam.ca/rdfexemples.html"> <dc:title>Le RDF par l’exemple</dc:title> <license rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/" /> </Work> </rdf:RDF> Voici la représentation sous la forme d’un graphe : title Le RDF par l’exemple rdfexemples.html {Work} license http://creativecommons.org/licenses/by−sa/2.0/ Nous avons alors un document Creative Commons complet. Cependant, un problème demeure. Supposons qu’un logiciel fasse automatiquement une recherche pour vous et que vous ne désiriez obtenir que les textes que vous pouvez modifier librement. Il n’est pas évident pour une machine de comprendre que l’URI « http://creativecommons.org/licenses/by-sa/2.0/ » vous donne ce droit; d’ailleurs, une telle recherche n’est peut-être pas très simple pour un humain... Creative Commons définit trois verbes et des objets permettant de décrire une licence et une classe. Toutes les licences appartiennent à la classe ayant pour URI « http://web.resource.org/cc/License ». Les URI des trois verbes sont : CC BY-NC-SA Module 5 : Resource Description Framework (RDF) 270 http://web.resource.org/cc/permits La licence le permet. Creative Commons définit trois URI pouvant être utilisés comme objet de ce verbe. Il y a d’abord « http://web.resource.org/cc/Reproduction », le droit de reproduire en tout ou en partie le travail. Il y a ensuite « http://web.resource.org/cc/Distribution », le droit de redistribuer le travail. Finalement, il y a « http://web.resource.org/cc/DerivativeWorks », le droit de modifier le travail. Évidemment, il est possible de définir ses propres objets. http://web.resource.org/cc/requires La licence pose comme condition. Creatives Commons définit quatre URI pouvant être utilisés comme objet de ce verbe : « http://web.resource.org/cc/Notice » pour spécifier qu’il faut reproduire intégralement les notes légales (licence et droits d’auteurs); « http://web.resource.org/cc/Attribution » pour spécifier qu’il faut attribuer à l’auteur le crédit du travail; « http://web.resource.org/cc/ShareAlike » pour spécifier que si l’on redistribue le travail, il faut le faire en gardant la même licence; « http://web.resource.org/cc/SourceCode » pour spécifier que le code source doit être redistribué. http://web.resource.org/cc/prohibits La licence interdit. Il n’y a qu’un seul URI défini par Creative Commons qui peut être utilisé avec ce verbe : « http://web.resource.org/cc/CommercialUse »; cela permet d’interdire l’utilisation à des fins commerciales. Encore une fois, il est possible de définir ses propres objets. Dans le cas de la licence « comme suit : Sujet http://creativecommons.org/ licenses/by-sa/ 2.0/ http://creativecommons.org/ licenses/by-sa/ 2.0/ http://creativecommons.org/ licenses/by-sa/ 2.0/ http://creativecommons.org/ licenses/by-sa/ 2.0/ http://creativecommons.org/ licenses/by-sa/ 2.0/ http://creativecommons.org/ licenses/by-sa/ 2.0/ Attribution-ShareAlike 2.0 », nous pouvons la décrire Verbe http://www.w3.org/1999/ 02/22-rdf-syntax-ns#type Objet http://web.resource.org/ cc/License http://web.resource.org/ cc/permits http://web.resource.org/ cc/Reproduction http://web.resource.org/ cc/permits http://web.resource.org/ cc/Distribution http://web.resource.org/ cc/requires http://web.resource.org/ cc/Notice http://web.resource.org/ cc/requires http://web.resource.org/ cc/Attribution http://web.resource.org/ cc/permits http://web.resource.org/ cc/DerivativeWorks CC BY-NC-SA Le RDF par l’exemple Sujet http://creativecommons.org/ licenses/by-sa/ 2.0/ 271 Verbe http://web.resource.org/ cc/requires Objet http://web.resource.org/ cc/ShareAlike Nous pouvons aussi utiliser le XML suivant : <?xml version="1.0" encoding="ISO-8859-1"?> <rdf:RDF xmlns="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <License rdf:about="http://creativecommons.org/licenses/by-sa/2.0/"> <permits rdf:resource="http://web.resource.org/cc/Reproduction" /> <permits rdf:resource="http://web.resource.org/cc/Distribution" /> <requires rdf:resource="http://web.resource.org/cc/Notice" /> <requires rdf:resource="http://web.resource.org/cc/Attribution" /> <permits rdf:resource="http://web.resource.org/cc/DerivativeWorks" /> <requires rdf:resource="http://web.resource.org/cc/ShareAlike" /> </License> </rdf:RDF> En pratique, nous combinons souvent le tout (description du travail et description de la licence) pour obtenir le XML suivant : <rdf:RDF xmlns="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <Work rdf:about="http://www.uqam.ca/rdfexemples.html"> <dc:title>Le RDF par l’exemple</dc:title> <license rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/" /> </Work> <License rdf:about="http://creativecommons.org/licenses/by-sa/2.0/"> <permits rdf:resource="http://web.resource.org/cc/Reproduction" /> <permits rdf:resource="http://web.resource.org/cc/Distribution" /> <requires rdf:resource="http://web.resource.org/cc/Notice" /> <requires rdf:resource="http://web.resource.org/cc/Attribution" /> <permits rdf:resource="http://web.resource.org/cc/DerivativeWorks" /> <requires rdf:resource="http://web.resource.org/cc/ShareAlike" /> </License> </rdf:RDF> Voilà! De cette manière, une machine pourra automatiquement déterminer quels droits l’utilisateur a sur une œuvre. Un logiciel pourrait automatiquement avertir l’utilisateur de ses obligations si jamais il tentait d’enregistrer sur son disque une copie de l’œuvre. Dans le cas d’une entreprise qui utilise beaucoup de contenu multimédia, l’utilisation de cette norme pourrait être très utile pour détecter automatiquement les violations des droits d’auteur. CC BY-NC-SA Module 5 : Resource Description Framework (RDF) 5.3.4 272 Un exemple : FOAF Les personnes sont souvent ce qu’il y a de plus important dans une organisation; il n’est donc pas étonnant qu’on veuille utiliser le RDF pour les décrire. Pour ce faire, on utilise souvent la norme FOAF pour « Friend-Of-A-Friend », ou un ami d’un ami, en français, (préfixe http://xmlns.com/foaf/0.1/) qui définit la classe « Person » (personne, en anglais). Le projet FOAF a été lancé de façon informelle par Daniel Brickley en 1998. À l’époque, il avait mis un texte RDF ressemblant à ceci sur sa page personnelle : (Attention.- Il ne s’agit pas de RDF/XML valable.) <RDF:RDF xmlns="vocabdemo.rdf"> xmlns:rdf="http://www.w3.org/TR/WD-rdf-syntax#"> <Person ID="dan"> <name> Dan Brickley </name> <Email> [email protected] </Email> <telephone rdf:resource = "phone:+44-1-+44(0)117-9287493" /> <pager rdf:resource = "phone:+44-1-+44(0)2523-1781115" /> <homePage rdf:resource= "http://purl.org/net/danbri/" /> <homePage rdf:resource= "http://www.ilrt.bris.ac.uk/about/staff/dan.html"/> </Person> </RDF:RDF> La norme FOAF est très riche; mais à la base, on trouve les verbes suivants : http://xmlns.com/foaf/0.1/name Verbe pointant vers le nom de la personne (John Smith) http://xmlns.com/foaf/0.1/nick Verbe pointant vers le surnom informel de la personne (joblo). http://xmlns.com/foaf/0.1/title Verbe pointant vers le titre de la personne (docteur, monsieur, madame). http://xmlns.com/foaf/0.1/homepage Verbe pointant vers la page personnelle de la personne. http://xmlns.com/foaf/0.1/mbox Verbe pointant vers l’adresse électronique de la personne. http://xmlns.com/foaf/0.1/img Verbe pointant vers une image de la personne, la représentant spécifiquement. http://xmlns.com/foaf/0.1/depiction Verbe pointant vers une image représentant la personne. Contrairement à « img », l’image peut être une photo de groupe. http://xmlns.com/foaf/0.1/family_name Verbe pointant vers le nom de famille de la personne (Smith). CC BY-NC-SA Le RDF par l’exemple 273 http://xmlns.com/foaf/0.1/givenname Verbe pointant vers le prénom de la personne (John). En XML, une description de l’auteur de ce document pourrait se présenter comme suit : <?xml version="1.0" encoding="ISO-8859-1"?> <rdf:RDF xmlns:foaf="http://xmlns.com/foaf/0.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <foaf:Person> <foaf:givenname>Daniel</foaf:givenname> <foaf:family_name>Lemire</foaf:family_name> <foaf:homepage rdf:resource="http://www.daniel-lemire.com/fr/" /> <foaf:mbox>[email protected]</foaf:mbox> <foaf:img rdf:resource="http://www.daniel-lemire.com/fr/images/GIF/zel2p.gif" /> </foaf:Person> </rdf:RDF> Voici le graphe équivalent : Daniel givenname Lemire family_name Anonymous Person homepage http://www.daniel−lemire.com/fr/ mbox img [email protected] zel2p.gif Notez que la balise « Person » n’a pas d’attribut « rdf:about ». Actuellement, il existe un débat sur cette question : Peut-on attribuer un URI unique à chaque individu et si oui, comment le choisir? C’est un cas où l’URI du sujet est « implicite » : cela signifie que dans les triplets sujet/verbe/objet, le sujet a un URI « fictif », qui n’est valable que dans le cadre du document que l’on traite. Autrement dit, le programme qui traite le document doit allouer dynamiquement un URI au sujet pour la durée du traitement. Rappelons-nous, en effet, que la norme RDF permet d’omettre le sujet, mais que si le sujet est spécifié, il doit être un URI. Nous pouvons imaginer que la norme FOAF sera éventuellement utilisée pour représenter les réseaux sociaux, les organisations, et ainsi de suite. Une fois l’information CC BY-NC-SA Module 5 : Resource Description Framework (RDF) 274 sociale représentée de façon formelle, nous pouvons croire qu’il sera possible de poser des questions à un ordinateur de l’ordre suivant : Est-ce que je connais quelqu’un qui connaît quelqu’un travaillant chez IBM? 5.3.5 Un exemple : RSS/RDF La version 1.0 de la norme RSS est un exemple de RDF. Cette norme dont l’acronyme n’a pas de définition établie, sert à représenter des fils de nouvelles. Elle a été imaginée par la compagnie Netscape et servait alors à la production du portail Netscape (1999). Elle est devenue très populaire et on trouve maintenant des milliers de fils de nouvelles en format RSS dans le monde. Par exemple, sur http://www.yulblog.org/, il y a des centaines de blogues écrits par des Montréalais et la plupart ont un fil de nouvelles en format RSS. Une nouvelle, appelée « item » en RSS, prend la forme suivante : <?xml version="1.0" encoding="ISO-8859-1"?> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://purl.org/rss/1.0/"> <item rdf:about="http://www.nouvelles.com/nouvelles1"> <title>La bourse fait faillite</title> <link>http://www.nouvelles.com/nouvelles1.html</link> <description> Aujourd’hui, on a appris que la bourse a fait faillite. </description> </item> </rdf:RDF> Nous constatons qu’il y a une classe (item) et trois verbes (title, link, description) qui représentent respectivement le titre, l’URL et le contenu de la nouvelle. Un document RSS est une liste d’items. Voici un document RSS : <?xml version="1.0" encoding="ISO-8859-1"?> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://purl.org/rss/1.0/"> <channel rdf:about="http://www.nouvelles.com/nouvelles.rss"> <title>Un site de nouvelles</title> <link>http://www.nouvelles.com/</link> <description> Nouvelles.com est un superbe site de nouvelles </description> <!-- Ensuite, on place une séquence de nouvelles, les unes après les autres--> <items> CC BY-NC-SA Le RDF par l’exemple 275 <rdf:Seq> <!-- chaque nouvelle a un URI --> <rdf:li resource="http://www.nouvelles.com/nouvelles1" /> <rdf:li resource="http://www.nouvelles.com/nouvelles2" /> </rdf:Seq> </items> </channel> </rdf:RDF> Nous constatons une classe « channel » (canal, en anglais) qui contient un titre, un URL (link) et une description. Il y a aussi une liste de nouvelles (item). Généralement, nous combinons le tout dans un seul fichier, comme ceci : <?xml version="1.0" encoding="ISO-8859-1"?> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://purl.org/rss/1.0/"> <channel rdf:about="http://www.nouvelles.com/nouvelles.rss"> <title>Un site de nouvelles</title> <link>http://www.nouvelles.com/</link> <description> Nouvelles.com est un superbe site de nouvelles </description> <!-- Ensuite, on place une séquence de nouvelles, les unes après les autres--> <items> <rdf:Seq> <!-- chaque nouvelle a un URI --> <rdf:li resource="http://www.nouvelles.com/nouvelles1" /> <rdf:li resource="http://www.nouvelles.com/nouvelles2" /> </rdf:Seq> </items> </channel> <item rdf:about="http://www.nouvelles.com/nouvelles1"> <title>La bourse fait faillite</title> <link>http://www.nouvelles.com/nouvelles1.html</link> <description> Aujourd’hui, on a appris que la bourse a fait faillite. </description> </item> <item rdf:about="http://www.nouvelles.com/nouvelles2"> <title>Rien ne va plus à l’école</title> <link>http://www.nouvelles.com/nouvelles2.html</link> <description> Un étudiant se serait rendu coupable d’apprentissage. </description> CC BY-NC-SA Module 5 : Resource Description Framework (RDF) 276 </item> </rdf:RDF> Les applications du RSS sont multiples. Supposons que votre organisation collabore avec plusieurs autres organisations et que vous vouliez rendre disponibles, sur une seule page web, toutes les nouvelles de toutes les organisations dont vous faites partie. Si chaque organisation rend disponible sur le web un document RSS toujours mis à jour, vous pouvez facilement récupérer les nouvelles de chacun et les afficher à un seul endroit. Au lieu de solliciter tous les membres par courriel, les fils de nouvelles RSS permettent à une machine de faire un tri et de personnaliser le contenu. La norme RSS est en voie d’être remplacée par la norme Atom. Un des avantages du nouveau format Atom est que chaque nouvelle doit avoir un identifiant unique ce qui permet d’éviter les doublons. Cependant, la norme RSS risque d’être toujours utile pendant bien des années. Atom n’est pas en RDF/XML. En voici un exemple : <?xml version="1.0" encoding="utf-8"?> <feed xmlns="http://www.w3.org/2005/Atom"> <title>Un site de nouvelles</title> <subtitle>Nouvelles.com est un superbe site de nouvelles</subtitle> <link href="http://www.nouvelles.com/"/> <updated>2003-12-13T18:30:02Z</updated> <author> <name>John Doe</name> <email>[email protected]</email> </author> <id>urn:uuid:60a76c80-d399-11d9-b91C-0003939e0af6</id> <entry> <title>La bourse fait faillite</title> <link href="http://www.nouvelles.com/nouvelles1.html"/> <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id> <updated>2003-12-13T18:30:02Z</updated> <summary>Aujourd’hui, on a appris que la bourse a fait faillite. </summary> </entry> </feed> 5.3.6 Conclusion Nous avons étudié quatre applications importantes du RDF sur le web. Le nombre d’applications est toutefois beaucoup plus important. CC BY-NC-SA Travail noté 6 277 Il faut garder à l’esprit que le RDF n’est pas le XML et que le XML ne sert qu’à représenter le RDF (et encore, ce n’est pas toujours possible). Il est probable que la syntaxe utilisée pour représenter le RDF en XML va encore évoluer. Pour en apprendre davantage sur le RDF, nous vous suggérons le livre de Shelley Powers, Practical RDF, publié chez O’Reilly en juillet 2003 (350 pages), en anglais seulement et coûtant environ 60 $. 5.4 5.4.1 Travail noté 6 Objectifs et pondération Ce travail porte principalement sur le RDF et compte pour 10 % de la note globale du cours. Il contribue à l’atteinte de l’objectif suivant : – Interpréter un fichier RDF comme un tableau sujet/verbe/objet. Le travail comporte sept exercices : les cinq premiers valent un point chacun et le sixième, qui porte sur le XSLT et contribue ainsi à renforcer les apprentissages du module 3, vaut 4 points, alors que le dernier compte pour un point, pour un total de 10 points. 5.4.2 Consignes Nous vous recommandons d’avoir terminé les activités d’autoévaluation du module 5 avant de faire ce travail noté. De plus, comme le sixième exercice exige une bonne compréhension du XSLT, vous devriez avoir terminé le module 3 avant de l’entreprendre. Lorsque vous aurez terminé le travail, transmettez à votre personne tutrice, par courriel, un seul document (Word 97/2000/XP, ODF, PDF, RTF ou en format texte) comprenant, pour chaque exercice, le tableau, le code XML ou le contenu de votre document XSLT. Ne transmettez pas vos solutions en plusieurs fichiers. Ne transmettez pas une archive compressée (zip ou autre). L’objet de votre courriel doit commencer par « [INF6450][TRAVAIL6] »; dans le message, indiquez votre nom, votre numéro d’étudiant (8 chiffres), la date de remise de votre travail et le nom de votre personne tutrice, ainsi que les mentions « Travail noté 6 » et « INF 6450 ». Il s’agit d’un travail personnel et vous ne devez pas partager vos solutions. Dans un tableau de triplets, les objets qui ne sont pas des URI, doivent être placés entre guillements (" "). CC BY-NC-SA Module 5 : Resource Description Framework (RDF) 5.4.3 278 Exercice 1 Représentez, dans un tableau de triplets (sujet, verbe, objet), le document RDF/XML suivant : <?xml version="1.0" encoding="ISO-8859-1" ?> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:md="http://www.mondomaine.com/"> <rdf:Description rdf:about="http://www.uqam.ca/"> <md:titre>Site de l’UQÀM</md:titre> <md:autre rdf:resource="http://www.uqam.ca/index.html" /> </rdf:Description> </rdf:RDF> 5.4.4 Exercice 2 Écrivez un programme Java qui utilise l’API DOM pour extraire tous les titres des items d’un document RSS 1.0. Vous pouvez supposer que le fichier réside sur votre disque. Ne joignez pas un fichier à l’extension java. 5.4.5 Exercice 3 Représentez, dans un tableau de triplets (sujet, verbe, objet), l’exemple en RDF qui suit et qui provient de la norme PRISM. <?xml version="1.0" encoding="UTF-8"?> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:pcv="http://prismstandard.org/namespaces/pcv/1.0/" xmlns:dc="http://purl.org/dc/elements/1.1/"> <rdf:Description rdf:about="http://wanderlust.com/2000/08/Corfu.jpg"> <dc:identifier rdf:resource="http://wanderlust.com/content/2357845" /> <dc:creator> <pcv:Descriptor rdf:about="http://wanderlust.com/emp3845"> <pcv:label>John Peterson </pcv:label> </pcv:Descriptor> </dc:creator> <dc:coverage> <pcv:Descriptor rdf:about="http://prismstandard.org/vocabs/ISO-3166/GR"> <pcv:label xml:lang="en">Greece</pcv:label> <pcv:label xml:lang="fr">Grece</pcv:label> </pcv:Descriptor> </dc:coverage> </rdf:Description> CC BY-NC-SA Travail noté 6 279 </rdf:RDF> 5.4.6 Exercice 4 Ecrivez un document XML/RDF correspondant au tableau suivant : Sujet Verbe Objet http://www.uqam.ca http://www.uquebec.ca/ "UQÀM" nom 5.4.7 Exercice 5 La licence identifié par l’URI « http://www.mondomaine.ca/licence » permet la reproduction, la distribution et la modification des œuvres. Décrivez cette licence en utilisant Creative Commons et le format RDF/XML. 5.4.8 Exercice 6 Note.- Cet exercice vaut 4 points et est substantiellement plus difficile que les exercices précédents. Avant de réaliser l’exercice... Il peut arriver qu’on veuille annoter un document XHTML avec Dublin Core ou avec un autre vocabulaire RDF, mais sans vouloir utiliser la notation RDF/XML. L’annotation est particulièrement facile si aucun des objets n’est un URI. Pour y arriver, nous utiliserons des éléments « meta » et « link » placés dans l’élément « head » du document. Considérons l’exemple qui suit : <?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <link rel="schema.DC" href="http://purl.org/dc/elements/1.1/" /> <meta name="DC.title" content="le titre de mon document" /> <meta name="DC.description" content="la description" /> <meta name="DC.date" content="2004-11-08" /> <meta name="DC.format" content="text/html" /> <meta name="DC.language" content="fr" /> <meta name="DC.publisher" content="L’Université du Québec" /> <title>un petit document</title> </head> CC BY-NC-SA Module 5 : Resource Description Framework (RDF) 280 <body> <p>Ceci est un document XHTML annoté avec Dublin Core.</p> </body> </html> Cette façon de faire est documentée par le mémo disponible à l’adresse http:// www.ietf.org/rfc/rfc2731.txt. Il n’est toutefois pas nécessaire de consulter ce mémo. Aux fins de cet exercice, nous allons supposer que seuls deux types de structures sont utilisés. D’abord, l’élément « link » peut être utilisé pour définir un préfixe, comme ceci : <link rel= "schema.PREFIXE" href="URI" /> D’autre part, le préfixe peut être utilisé pour faire un lien entre le document courant et un sujet : <meta name="PREFIXE.NOM" content="VALEUR" /> Prenons comme exemple les quatres éléments suivants placés dans un document XHTML à l’adresse « http://www.uqam.ca/index.html » : <link <meta <link <meta rel="schema.d" href="http://www.mondomaine.com/"> name= "d.a" content = "c"> rel="schema.e" href="http://www.mondomaine.com/2/"> name= "e.g" content = "f"> Cette notation aura alors la signification suivante en RDF : Sujet Verbe Objet http://www.uqam.ca http:// "c" www.mondomaine.com/ a http://www.uqam.ca http:// "f" www.mondomaine.com/ 2/g En notation RDF/XML, nous avons : <?xml version="1.0" encoding="ISO-8859-1" ?> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:d="http://www.mondomaine.com/" xmlns:e="http://www.mondomaine.com/" > <rdf:Description about="http://www.uqam.ca/index.html"> <d:a>c</d:a> <e:g>f</e:g> </rdf:Description> </rdf:RDF> CC BY-NC-SA Travail noté 6 281 Notez qu’aucun des objets n’est un URI. Exercice à réaliser... Écrivez un document XSLT qui, étant donné un document XHTML annoté selon cette méthode, donne le document RDF/XML correspondant, en supposant que le document courant possède l’URI « http://mondocument.org ». Pour que l’on puisse voir la solution dans Firefox, produisez un document HTML qui contient le code du document RDF/XML comme dans l’exemple qui suit : <html> <body><pre> <?xml version="1.0" encoding="ISO-8859-1" ?> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" > <rdf:Description rdf:about="http://mondocument.org"> <title xmlns="http://purl.org/dc/elements/1.1/"> le titre de mon document </title > </rdf:Description> </rdf:RDF> </pre></body></html> En somme, votre document XSLT doit produire un document débutant par la balise html et contenant le document RDF/XML écrit avec des appels d’entités (<,>). Toute solution qui utilisera les éléments XSLT « xsl:key », « xsl:param » et « xsl:variable » sera refusée; une note de zéro sera accordée. Voici quelques indices... – Les documents XHTML utilisent l’espace de noms « http://www.w3.org/1999/xhtml ». Pour pouvoir les traiter en XSLT, il vous faut définir cet espace de noms comme dans cet exemple : <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xhtml="http://www.w3.org/1999/xhtml" > <xsl:template match="xhtml:html" > <rdf:RDF></rdf:RDF> </xsl:template> CC BY-NC-SA Module 5 : Resource Description Framework (RDF) 282 – Les fonctions XPath « substring-before » et « substring-after » peuvent vous être utiles. La valeur de l’expression XPath « substring-before(’meta.dc’,’.’) » est « meta », alors que la valeur de l’expression « substring-after(’meta.dc’,’.’) » est « dc ». 5.4.9 Exercice 7 Le site flickr permet de chercher des photographies publiées avec une licence Creative Commons. Visitez la page http://www.flickr.com/photos/guppiecat/1351724368/ in/set-72157601927001088/ et trouvez la licence Creative Commons. Écrivez-la en XML. CC BY-NC-SA Annexe A : Glossaire Appel d’entité : Un appel d’entité est une suite de caractères (bout de texte) qui commence par une esperluette ( & ) et se termine par un point-virgule ( ; ). Les appels d’entité suivants font partie de la définition du XML : appel d’entité résultat < < & & > > " " ' ’ Attribut : Un attribut est un nom XML qui doit respecter les mêmes règles que les noms XML des balises; il est immédiatement suivi d’un signe d’égalité ( = ) et d’une valeur placée entre guillemets. Par exemple, la balise <lavie age="5"> a un attribut (age="5") dont le nom XML est "age". Une balise peut avoir plusieurs attributs, comme <lavie age="5" sexe="M">, mais chacun doit avoir un nom XML différent; la balise <lavie age="5" age="7"> n’est pas autorisée. Balise : Une balise est un texte commençant par le signe < et se terminant par le signe >, délimitant un élément. Il existe trois types de balises en XML : les balises qui commencent un élément, les balises qui terminent un élément et les balises d’élément vide. Par exemple, <lavie> est une balise qui ouvre un élément. Une balise qui commence par </ est une balise de fin, qui termine un élément, comme </lavie>. Finalement, une balise qui se termine par /> marque que l’élément est vide, comme <lavie />. Une déclaration de type de document (<!DOCTYPE>), une déclaration XML (<?xml?>), un commentaire (<!-- -->) ou une région CDATA (<![CDATA[ ]]>) ne sont pas des balises. 283 Glossaire 284 Bien formé : Un document XML bien formé respecte la grammaire XML et il peut être lu par n’importe quel parseur XML générique. Commentaire : Un commentaire commence par <!-- et se termine par -->; entre ces deux bornes, il ne peut y avoir deux tirets successifs (--), mais n’importe quoi d’autre peut s’y retrouver. CSS : Cascading StyleSheet. Déclaration de type de document : Une déclaration de type de document prend la forme <!DOCTYPE ... SYSTEM ... > , où l’on met à la place des premiers trois points le nom XML de l’élément-racine que le document doit avoir, et à la place des deuxièmes trois points, une URL vers le document DTD. Déclaration XML : La déclaration XML ressemble à s’y méprendre à une instruction de traitement et prend la forme <?xml ... ?>. Le contenu d’une déclaration XML comporte généralement au maximum trois attributs : version="...", encoding="..." et standalone="...". La version du XML la plus utilisée est la 1.0; bien que la version 1.1 existe, elle est fort peu utilisée. On utilisera souvent une déclaration XML avec « encoding="ISO-8859-1" » pour pouvoir utiliser les accents dans le document; par défaut, on ne peut pas utiliser les accents dans un document XML, sans des outils supportant les normes UTF-8/UTF-16. L’attribut « standalone » prend les valeurs yes ou no, selon que l’on veut que la DTD externe soit lue ou pas. La déclaration XML doit obligatoirement être au tout début du document ou être carrément absente : même un espace avant n’est pas permis. DocBook : C’est un format de document souvent utilisé pour la documentation technique. DOM (Document Object Model) : Le terme « DOM » a deux significations : un ensemble d’API utilisant un modèle en arbre ou un certain modèle en arbre. DTD (Définition de Type Document) : Une DTD permet de définir un type de document XML en spécifiant des contraintes sur les éléments, les attributs et leur contenu. Un document XML qui satisfait ces contraintes et qui est bien formé est dit valable. Élément : Un élément est l’ensemble du texte borné par deux balises ayant le même nom XML, comme <lavie> et </lavie>. On dit que l’élément <lavie></lavie> a le nom XML « lavie ». L’élément hérite des attributs de sa balise de départ : l’élément <lavie age="5"></lavie> possède l’attribut « age="5" ». Il est à noter que la casse est significative en XML : les balises < A > et < a > n’ont pas le même nom XML. Lorsque l’élément est vide, c’est-à-dire sans contenu, on peut remplacer <lavie></lavie> par <lavie />, pour être plus bref. Par ailleurs, un élément peut contenir d’autres éléments, comme dans <lavie><a></a></lavie>, ou du texte ou du texte et des éléments, comme <lavie>fd<a>fsd</a>fd</lavie>. Si un élément contient l’élément de début ou de fin d’un élément, alors il doit aussi contenir l’autre. Ainsi, un élément peut être contenu par un autre ou non, mais deux éléments ne peuvent se chevaucher, comme <b><a></b></a>, qui est du XML mal formé. CC BY-NC-SA Glossaire 285 Élément-racine : Tout document XML bien formé doit avoir un élément-racine, et un seul. Tous les autres éléments doivent être contenus dans cet élément-racine. Espace de noms : Les espaces de noms permettent d’utiliser plusieurs vocabulaires XML en même temps. Extensible : Voir Métalangage. Graphe : Un graphe est un ensemble de nœuds liés par des relations d’un nœud à un autre. Graphe dirigé : Un graphe est dirigé si les relations sont à sens unique. Graphe annoté : Un graphe est annoté si les relations entre deux nœuds peuvent être de différentes natures. HTML (HyperText Markup Language) : Le HTML est un langage à base de balises. La majorité des documents sur le web sont écrits en HTML. Instruction de traitement : L’instruction de traitement ne fait rien en soit, mais peut indiquer aux programmes comment obtenir un certain résultat. Une instruction de traitement débute par « <? » et se termine par « ?> »; immédiatement après le « <? », un nom XML valable doit apparaître et tous les noms XML valables sont autorisés à l’exception de xml, Xml, XMl, XML, XmL, xMl, xML et xmL. Ainsi n’importe quel autre texte peut être utilisé, mais il faut faire des appels d’entités pour « < » et « & », comme pour n’importe quel contenu textuel XML. Métalangage : Le XML est un « métalangage » permettant d’échanger de l’information, principalement sur le web. On dit que c’est un « métalangage » parce qu’il permet de créer de nouveaux langages pour l’échange d’informations, mais qu’il ne constitue pas un langage en soi. On dit donc que le XML est « extensible » (peut être étendu) et que c’est un métalangage : les deux affirmations ont le même sens et notent la capacité du XML à s’adapter à des besoins différents. Nom XML : Le nom XML d’une balise est le texte suivant le symbole « < » ou « </ » pour une balise de fin; il peut contenir n’importe quelle lettre (a, b,...) ou chiffre (0,1,2,...) et les signes de ponctuation suivants : la barre de soulignement ( _ ), le trait d’union ( - ) et le point ( . ); il ne peut contenir ni les autres signes de ponctuation ni un espace. En outre, un nom XML ne peut pas commencer par un nombre, un trait d’union ou un point. Par exemple, le nom XML de la balise <lavie> est « lavie », alors que la balise <7lavie> ne serait pas autorisée. RDF (Resource Description Framework) : Le RDF est un langage pour les métadonnées sur le web, c’est-à-dire un langage pour énoncer ce que l’on sait sur quelque chose ou quelqu’un. SGML : Standard Generalized Markup Language. Syntaxe : La syntaxe XML est la manière d’écrire les informations dans un document XML. Les notions importantes de la syntaxe de base du XML sont la balise, l’élément, l’élément-racine et l’attribut. CC BY-NC-SA Glossaire 286 URI : C’est une adresse Internet fictive. L’URI agit un peu comme le numéro d’assurance sociale des vocabulaires XML. Valable :: Un document est valable s’il répond à certains critères de base de l’application XML. Un document XML qui est bien formé, qui en plus satisfait aux contraintes dictant quels éléments et attributs peuvent être utilisés, et dans quel ordre et avec quel contenu, est dit valable. Vocabulaire XML : Un « vocabulaire XML » est un ensemble de noms de balises et d’attributs ayant une signification donnée. Un vocabulaire XML peut être associé à un document DTD. XHTML : Le XHTML est un format hybride : il tient à la fois du HTML et du XML. XML : eXtensible MarkupLanguage. XSL : eXtensible Stylesheet Language. XSLT : XSL Transformations. XSL-FO : eXtensible Stylesheet Language Formatting Objects. CC BY-NC-SA Annexe B : Webographie XML Tous les liens ont été vérifiés en février 2007. 1 Blogues – http://www.daniel-lemire.com/blogue/category/xml/ (blogue du cours) – http://www.tbray.org/ongoing/ – http://formats-ouverts.org/blog/ 2 Cours en ligne, en français – http://www.commentcamarche.net/xml/xmlintro.php3 – http://www.laltruiste.com/coursxml/sommaire.html 3 Cours en ligne, en anglais – http://www.w3schools.com/ – http://www.w3schools.com/xml/default.asp – http://www.w3schools.com/xml/xml_examples.asp 4 Liens généraux, en français – L’espace XML francophone : www.xmlfr.org – Rubrique XML chez Wikipedia 287 Webographie XML 5 288 Articles, en français – A. Crochet-Damais, Microsoft Office 2003 : le format XML pointé du doigt 6 Articles, en anglais – J. Hunt, et al. Why use DITA to produce HTML deliverables? – D. Terdiman, Weather Data for the Masses 7 Références tirées du site Wikipedia (anglais) 7.1 – – – – – Spécification XML Spécification XML annotée : http://www.xml.com/axml/testaxml.htm Site du World Wide Web Consortium : http://www.w3.org/ Page d’accueil XML du World Wide Web Consortium : http://www.w3.org/XML/ Spécification XML 1.1 : http://www.w3.org/TR/xml11 Spécification XML 1.0 : http://www.w3.org/TR/REC-xml 7.2 Software – Éditeur XML open : http://www.philo.de/xmledit/ – Librairie XML open pour Delphi/Kylix : http://www.philo.de/xml/ – Éditeur jEdit : http://jedit.org 7.3 Ressources pour les développeurs – – – – – – – – – FAQ XML : http://www.ucc.ie/xml/ xml.com, développement et ressources : http://www.xml.com/ Cafe con Leche, nouvelles et ressources XML : http://www.cafeconleche.org/ XML Cover Pages : http://xml.coverpages.org/ Page web des développeurs IBM : http://www-106.ibm.com/developerworks/xml/ Site de nouvelles pour les développeurs XML : http://www.xmlhack.com/ Mailing liste XML-L : http://listserv.heanet.ie/xml-l.html DTD et schemas XML : http://www.XMLPatterns.com/ Tutoriel sur Relax NG : http://www.oasis-open.org/committees/relax-ng/tutorial20010810.html (traduit en français : http://xmlfr.org/oasis/committees/relax-ng/ tutorial-20011203-fr.html) – Les problèmes du XML : http://c2.com/cgi/wiki?XmlSucks – XML : http://www.ericdigests.org/2000-4/xml.htm CC BY-NC-SA Liens vers des livres portant sur le XML, en anglais 289 – XML Linking : état de l’art : http://chinese-school.netfirms.com/xlink.html – Un outil XSLT (Markup of XML contents) : http://www.ultra-fluide.com/ressources/ en/semark/presentation.htm 8 Liens vers des livres portant sur le XML, en anglais – – – – – – XML: Managing Data Exchange (wikibook) XML in a Nutshell, by Harold and Means Beginning XML, 3rd Edition, by David Hunter, Andrew Watt, Jeff Rafter. Learning XML, by Erik T. Ray. XML Schema, by Eric Van Der Vlist. Processing XML with Java(TM): A Guide to SAX, DOM, JDOM, JAXP, and TrAX, by Elliotte Rusty Harold. CC BY-NC-SA Annexe C : Pense-bête DTD <!DOCTYPE nomXML_élémentRacine SYSTEM "URL"> : Déclaration de type de document <!ELEMENT ... > : Instruction ? : Élément optionnel * : Élément pouvant être présent plus d’une fois (de 0 à l’infini) + : Élément présent au moins une fois et qui peut être présent plusieurs fois | : Ou #PCDATA : Que du texte <!ATTLIST nomElementX nomAttributY...> : Spécifie que l’élément « X » a l’attribut « Y » CDATA : Attribut contient du texte #REQUIRED : Attribut obligatoire #IMPLIED : Attribut optionnel #FIXED : Attribut fixé avec une valeur <!ENTITY nomEntiteX "Yvaleur"> : L’entité « nomEntiteX » prend la valeur « Yvaleur » <!ENTITY % nomEntiteX "Yvaleur"> : Localement, l’entité « nomEntiteX » prend la valeur « Yvaleur » dans la DTD 291 Annexe D : Pense-bête HTML Balise Signification <p> </p> paragraphe <ul> <li> </li> </ul> liste non ordonnée élément de la liste <ol> <li> </li> </ol> liste ordonnée élément de la liste <table border="1"> <tr> <td> </td> </tr> </table> tableau ligne cellule <i> </i> italique <em> </em> italique (généralement) <b> </b> gras <strong> </strong> gras (généralement) <u> </u> souligné 293 Pense-bête HTML 294 Balise Signification <dl> <dt> </dt> <dd> </dd> </dl> liste de définitions terme à définir définition du terme <hr /> ligne horizontale <image src="URL" alt="description de l’image" /> affiche une image <a href="URL">texte</a> hyperlien <a name="URL">texte</a> marqueur CC BY-NC-SA Annexe E : Pense-bête XSLT Document XSLT de base <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> </xsl:stylesheet> « xsl:template » : Permet de définir un modèle avec un élément comme <xsl:template match="facture">; à chaque élément facture trouvé, le processeur XSLT applique le modèle correspondant. « xsl:apply-templates » : Cet élément donne le résultat obtenu par l’application de modèles (éléments « xsl:template »). « xsl:value-of » : Donne la valeur textuelle d’une expression XPath. Par exemple, l’instruction <xsl:value-of select="..." /> où « ... » est le nom de l’élément donne le texte contenu dans l’élément, les balises en moins. « <xsl:value-of select="@nas" /> » : Pour effectuer la sélection des attributs. Ici, l’attribut « nas » de l’élément « personne » (<personne nas="432444333">). Expression XPath avec « . » (un point) : Indique le nœud courant. Par exemple, l’instruction <xsl:value-of select="." /> donne le contenu textuel de l’élément courant. Expression XPath avec « / » (barre oblique) : Permet d’effectuer la sélection de nœuds contenus dans des éléments. L’instruction « <xsl:value-of select="nom/prenom" /> » donne le contenu textuel des éléments « prenom » contenus dans les éléments « nom » de l’élément courant. La barre oblique ( / ) peut aussi représenter le nœud-racine; ainsi, l’expression « /maison » sélectionne l’élément-racine, si et seulement s’il se nomme « maison ». Expression XPath avec « @ » : Permet d’effectuer la sélection des attributs. L’instruction « <xsl:value-of select="@nas" /> » donne le contenu textuel de l’attribut « nas » de l’élément courant. 295 Pense-bête XSLT 296 (accolades) : Pour spécifier la valeur d’un attribut; par exemple, avec l’expression <facture montant="..." />, le processeur XSLT va remplacer ... par la valeur de l’expression XPath « ... » et s’il s’agit du nom d’un élément, le contenu textuel de l’élément y sera inséré. Expression XPath avec « .. » (deux points successifs) : Permet d’obtenir la valeur de l’élément dans lequel le nœud courant est situé. On peut aller chercher le parent du parent avec l’instruction <xsl:value-of select="../.." />. Expression XPath avec « // » (deux barres obliques) : Permet de sélectionner tous les éléments et sous-éléments qui sont dans l’élément ou nœud courant. Par exemple, l’instruction <xsl:value-of select="count(//cours)" /> donne le nombre total d’éléments « cours » contenus dans l’élément ou nœud courant, incluant les éléments « cours » contenus dans les sous-éléments. Expression XPath avec « * » (astérisque) : Permet de sélectionner tous les éléments (mais pas les attributs ou les nœuds de texte) qui sont dans l’élément courant. Une expression avec « @* » sélectionne tous les attributs d’un élément. Expression XPath avec « | » (barre verticale) : Permet de sélectionner en utilisant plusieurs expressions à la fois; cette expression signifie « ou ». L’expression « nom|prenom » sélectionnera tous les éléments « nom » et « prenom » dans l’élément courant. « <xsl:value-of select="name(.)" /> » : Permet de sélectionner le nom d’un élément (et pas son contenu). Pour sélectionner le nom du parent, il faut utiliser « .. » au lieu de « . ». Fonction XPath « count » : Permet de compter le nombre de nœuds (éléments) sélectionnés; par exemple « count(montant) » compte le nombre d’éléments « montant ». Fonction XPath « sum » : Permet de faire la somme des valeurs numériques dans les nœuds (éléments) sélectionnés; par exemple « sum(montant) » fait la somme des valeurs numériques dans les éléments « montant ». « xsl:number » : Permet de numéroter des éléments correspondant à une expression avec l’attribut « count »; un exemple d’utilisation : <xsl:number count="montant" /> donnera le chiffre 3 pour le troisième élément « montant » contenu dans un même élément. Attribut « mode » : Permet d’avoir plusieurs modèles pour une même expression; s’applique aux éléments « xsl:apply-templates » et « xsl:template »; par exemple, <xsl:template match="cours" mode="initial"> ou <xsl:template match="cours" mode="complet">. Fonction XPath « generate-id » : Permet de générer un identifiant unique pour chaque nœud d’un document XML comme dans l’expression « generate-id(.) ». « xsl:choose » et « xsl:if » : permet de tester des conditions avec les symboles « < », « = », « != », « or », « and », « > », « >= », « <= ». Par exemple, l’instruction XSLT <xsl:choose> CC BY-NC-SA Pense-bête XSLT 297 <xsl:when test="name(.)=’montant’">montant</xsl:when> <xsl:otherwise>? </xsl:otherwise> </xsl:choose> donne le nom de l’élément si l’élément courant est un élément « montant » ou alors, le symbole « ? ». L’instruction XSLT <xsl:if test="count(maison) = 2">2 maisons</xsl:if> donne le chiffre 2, s’il y a deux éléments « maison » dans l’élément courant. Notion de liste d’éléments en XPath : Équivalent des tableaux en Java ou C/C++, mais la numérotation des éléments débute à 1; on utilise les crochets pour accéder aux éléments de la liste. L’expression XPath « para[1] » sélectionne le premier élément nommé « para ». L’expression « para[1]/em[2] » sélectionne le second élément « em » contenu dans le premier élément nommé « para ». Utilisation de XSLT comme base de données : Par exemple, l’expression XPath client[nom=’Sylvain’] nous donne les éléments « client » pour lesquels le contenu du sous-élément « nom » est « Sylvain ». « xsl:for-each » : Lorsqu’il y a un ensemble de résultats, on itère sur la séquence de tous les éléments « client » ayant comme nom « Sylvain » avec l’expression XPath //client[nom=’Sylvain’]. Par exemple, l’instruction « <xsl:for-each select="client" ><xsl:value-of select="." />,</xsl:for-each> » donnera une liste, séparée par des virgules, du contenu textuel de tous les éléments « client » contenus dans l’élément courant. Fonction XPath current() : Représente toujours l’élément XSLT courant. L’expression « //client[nom=current()/nom] » donne tous les éléments « client » qui ont un attribut « nom » dont la valeur est la même que l’élément courant. Par contre, l’expression « //client[nom=./nom] » a la même signification que « //client[nom] », c’est-àdire qu’on sélectionne tous les éléments « client » contenus dans l’élément courant ou ses sous-éléments qui ont un attribut « nom ». Fonctions arithmétiques XPath : On peut faire des calculs simples en XPath comme dans les expressions « 1+1 », « 2*1 » et « 5 div 2 ». On aussi les fonctions « floor », « ceiling » et « round ». CC BY-NC-SA Bibliographie [1] « IT 4247 XML fundamentals (course outline) ». [2] « Xml, xsl and web applications » – http://www.infosys.tuwien.ac.at/teaching/ courses/XML/. [3] « Draft standard for learning object metadata » – Tech. Report 1484.12.1-2002, IEEE, July 2002. [4] « Dublin core metadata element set, version 1.1: Reference description » – Tech. report, DCMI, 2003. [5] « W3 schools » – http://www.w3schools.com/, 2004. [6] A. B. ET AL . – XML: la synthèse, Dunod, 2003. [7] H. A. ET AL . – Building corporate portals using XML, McGraw Hill, 1999. [8] J. P. ET AL . – Professional XML, Wrox, 2001. [9] L. B IRKEDAL – « Advanced XML / data on the web (course outline) », http: //www.itu.dk/~birkedal/teaching/data-on-the-web-Fall-2002/. [10] H. B OLEY – « Auszug vorlesungsverzeichnis informatik », http://www.dfki. uni-kl.de/~boley/lexml/. [11] H. B OLEY et B. S PENCER – « CS 6905 semantic web techniques (course outline) », http://www.cs.unb.ca/~bspencer/cs6905swt/syllabus.html. [12] H. B OLEY, S. TABET et G. WAGNER – « Design Rationale of RuleML: A Markup Language for Semantic Web Rules », Proc. Semantic Web Working Symposium (SWWS’01), Stanford University, July/August 2001, p. 381–401. [13] M. D EAN et G. S CHREIBER – « OWL Web Ontology Language – Reference », W3C Candidate Recommendation, W3C, August 2003. [14] S. D OWNES – « Topic representation and learning object metadata », http://www. downes.ca/post/99, 2002. [15] E. R. H AROLD – XML bible, John Wiley & Sons, 2001. [16] E. R. H AROLD et W. S COTT – XML in a nutshell, O’Reilly, 2003. [17] J. H JELM – Creating the semantic web with RDF: Professional developer’s guide, John Wiley & Sons, 2001. 299 Bibliographie 300 [18] J. H UNT, D. DAY, E. H ENNUM , M. P RIESTLEY et D. A. S CHELL – « Why use DITA to produce HTML deliverables? », http://www-106.ibm.com/developerworks/ xml/library/x-dita6/index.html. [19] S. L UCAS – « CC432-G-SP: XML and related technologies (course outline) », http://www2.essex.ac.uk/courses/result.asp?coursecode=CC432&level=G&period= SP&yearofcourse=03. [20] B. M C L AUGHLIN – Java & XML, O’Reilly, 2001. [21] E. T. R AY – Learning XML, O’Reilly, 2001. [22] K. M. TADIOU – « IFT-62399 web sémantique ». [23] E. T ITTEL – XML, Schaum’s, Dunod, 2003. CC BY-NC-SA