Le XML c'est terriiiiblement 2000's, non ? C'est même un sujet qui
nous ramène au siècle dernier. Bon, depuis on a sorti quelques trucs
et pris un peu de recul. Plutôt qu'un panorama du sujet, voici un
recueil de bonnes pratiques assaisonnées de réflexions sur les modèles
de programmation associés, le tout illustré par quelques études de
cas.
Comme c'est un article assez volumineux, il se découpe en 5 épisodes.
- Introduction. Le XML est-il l'ennemi ? Formes grammaticales.
- Déserialisation avec des bibliothèques existantes
- Lecture bas niveau : le producteur qui pousse (SAX)
- Lecture bas niveau : le consommateur qui tire (StAX)
- Production de XML. Petit dessert : XPath
== Le XML est-il l'ennemi ?
Le XML est un raffinement du "SGML"
http://en.wikipedia.org/wiki/Standard_Generalized_Markup_Language
(Standard Generalized Markup Language), qui est un méta-langage
représentant des documents sous formes d'arbres. À l'époque (1996) on
cherchait à définir un format lisible par des machines pour les
prochaines décennies, donc pas trop obscur pour un programmeur, mais
sans prétendre l'infliger à des humains. Depuis on se traîne tout un
tas d'horreurs : la définition des entités SGML dans ce langage qui
n'est pas du XML, les entités externes qui font ouvrir des connections
réseau alors qu'on veut juste parser un fichier SVG sur son serveur
d'application, une syntaxe absolument cauchemardesque pour les
commentaires, et cette obligation ridicule de refermer les balises en
mentionnant une deuxième fois leur nom.
Car le XML s'est évadé du monde de la gestion documentaire pour
s'imposer dans des domaines qui on peu à voir, comme les fichiers de
configuration et la sérialisation d'objets, avec SOAP qui en est la
déclinaison la plus hallucinée. J'avance l'hypothèse que la grande
majorité des programmeurs ne s'est pas remis des cours de Lex, Yacc,
Bison et les autres à l'école. Donc on se jette avec bonheur sur le
premier machin qui donne l'impression de ne //pas// devoir définir une
grammaire. À côté de ça il faut reconnaître qu'on n'a pas forcément
envie de se traîner une passe de génération de code. Dans un projet
Maven multi-modules c'est quasiment indolore si on utilise "ANTLR"
http://antlr.org
mais autrement le coût du ticket d'entrée peut s'avérer dissuasif.
Après, dire qu'on fait du XML c'est toujours faire miroiter diverses
caractéristiques d'intéropérabilité, d'extensibilité, bien qu'on ne
soit jamais à court de possibilités de tricher, par exemple en
embarquant du texte libre qui respecte une grammaire propriétaire.
Laissons de côté la représentation des documents textuels où avec le
XML ça se passe plutôt bien. Pour un graphe d'objets donné, quelque
soit la représentation choisie, XML ou autre, on est obligé d'écrire
du code spécifique pour extraire des informations pertinentes dans un
langage de programmation adéquat. Si la structure est hiérarchique il
faut se traîner une pile, si le graphe est cyclique il faut se traîner
des références "en l'air". Si on utilise un outil de sérialisation
magique, il faut soit se taper du mapping, soit accepter des compromis
au niveau de la structure de ces objets. Tout ce que fournit
l'attirail XML c'est :
- Une structure prédéterminée qui limite la créativité pour le pire ou
pour le meilleur.
- Une vaste panoplie d'outils avec divers choix de corde pour se pendre.
== Formes grammaticales
Même si le XML offre des choix structurellement limités, un graphe
d'objet donné peut se décliner sous diverses formes. D'après ce que
j'ai constaté, si on vise la lisibilité, moins on utilise de
fonctionnalités du XML, mieux ça fonctionne.
Déjà, on vire tout ce qui est namespace et référence à un schéma, et
surtout XML "mixte" où un élément peut contenir du texte //et// des
sous-éléments. On espère qu'il n'y ait pas trop de caractères
bizarres.
=== Forme 1 : un max d'attributs
Un idiome grammatical qui fonctionne bien consiste à mettre tout ce
qu'on peut dans les attributs et garder les sous-éléments pour des
entités plus ou moins composites. On évite autant que possible de
dédier des élements au rôle de conteneur de liste. Par exemple, on a
plusieurs éléments ``<y/>`` mais on se passe d'un élement-conteneur
``<ys>`` parce qu'on suppose que la structure à représenter ne permet
pas la confusion.
<<<
<?xml version="1.0" encoding="UTF-8"?>
<x a="A" b="B" >
<y/>
<y/>
<z c="C" />
</x>
>>>
Inconvénients :
- Pas possible de commenter un attribut en particulier.
- Obligé de se poser des questions sur ce qui doit être un attribut ou
un élément.
=== Forme 2 : pas d'attributs
Pour éviter de se poser des questions, il y a moyen de tout passer
sous forme d'élément, avec la possibilité de commenter facilement.
C'est plus long.
<<<
<?xml version="1.0" encoding="UTF-8"?>
<x>
<a>A</a>
<b>B</b>
<y/>
<y/>
<z>
<c>C</c>
</z>
</x>
>>>
=== Forme 3 : à la Lisp
En toilettant la syntaxe de la forme 2 pour arriver à un style plus
"Lisp" on voit combien le XML est bruité.
<<<
(x
(a A)
(b B)
(y)
(y)
(z
(c C)
)
)
>>>
Admettons qu'on se passe d'en-tête, que ce soit toujours de l'UTF-8 sans "BOM"
http://en.wikipedia.org/wiki/Byte_order_mark
. Même si les bon compromis pour les délimiteurs de chaînes de
caractères et les échappements ne sont pas évidents, il n'y a pas de
grande difficulté à écrire un parser générique pour ce format avec
ANTLR.
=== Forme 4 : JSON
Pour le fun voici une version possible en JSON, validée et formatée
avec "JSONLint"
http://www.jsonlint.com
.
<<<
{
"x" : {
"a" : "A",
"b" : "B",
"ys" : [
"y",
"y"
],
"z" : {
"c" : "C"
}
}
}
>>>
=== Aux résultats
C'est intéressant de compter le nombre de caractères pour les trois
formes. Je n'inclus pas l'en-tête XML qui fausse les rapports sur des
fichiers plus conséquents, ni les indentations.
| Forme | Nombre caractères |
| 1, max d'attributs | 43 |
| 2, pas d'attributs | 55 |
| 3, à la Lisp | 36 |
| 4, JSON | 77 |
Incroyable, mais le XML de la forme 1 arrive deuxième après la forme 3
façon Lisp! Bon c'est lié au fait qu'il y ait plus de sauts de ligne
et donc d'indentations avec la forme 3. Et JSON, la forme la plus
verbeuse, doit supporter le poids des métadonnées qui alourdissent
forcément la note.
Tout cela n'a pas force de démonstration ; il faudrait jouer avec des
variantes sans indentations, essayer plein de jeux de données... En
plus d'une certaine simplicité de mise en œuvre (pas besoin de se
fader ANTLR) le XML offre également une forme de familiarité
rassurante à de nombreuses personnes.
=== Bonus : forme dans du code Java
Indépendemment de la forme de XML choisi, voici une façon de faire
rentrer du XML dans du code Java sans trop forcer. C'est surtout
intéressant pour des jeux de test.
En reprenant la forme 1 on peut écrire :
<<<
public static final String XML =
"<x a=\"A\" b=\"B\" >\n <y/>\n <y/>\n <z c=\"C\" />\n</x>" ;
>>>
Ou, sans les sauts de ligne :
<<<
public static final String XML =
"<x a=\"A\" b=\"B\" ><y/><y/><z c=\"C\" /></x>" ;
>>>
Mais si on embarque le XML dans le test, c'est aussi pour augmenter
les chances d'un humain de comprendre ce que ça veut dire et là c'est
loupé. Heureusement "Guava Libraries"
http://code.google.com/p/guava-libraries
(anciennement Google Collections) est là pour nous aider :
<<<
private static final ImmutableList< String > LINES = ImmutableList.of(
"<x a='A' b='B' >",
" <y/>",
" <y/>",
" <z c='C' />",
"</x>"
) ;
public static final String XML = Joiner.on( "\n" ).join( LINES ) ;
>>>
Eh oui la simple quote est un délimiteur d'attribut autorisé ! Bon
c'est aussi verbeux que du Java puisse l'être mais au moins le XML ne
perd-t-il pas en lisibilité.
À suivre ! La prochaine fois on attaque un sujet plus corsé. Prochain
épisode : Déserialisation avec des bibliothèques existantes.
c.
deux remarques rapides:
- il manque peut-�tre quelque chose sur les donn�es binaires (embarqu�
dans le xml vs. "� c�t�" pour le json)
- quand tu compares les tailles des diff�rentes repr�sentations il manque
peut-�tre une colonne avec la taille gzip�e puisque c'est ce qui transite
souvent sur le r�seau
et une bonne resource sur le sujet:
http://blog.jclark.com/2010/11/xml-vs-web_24.html