2004-08-11

XML on the road

Désormais, dans ma bibliothèque de fonctions dkstd, j'ai la possibilité de charger et manipuler un fichier XML. J'utilise souvent le XML pour des fichiers de configuration de mes logiciels, lorsque les fichiers INI se trouvent trop limités. Les fichiers XML permettent de manipuler plusieurs niveaux de hiérarchie, chose impossible avec les fichiers INI.

Un fichier INI tordu :

[MainWindow]
ShowStatusBar=1
BackgroundImage=gfx/bk.png
Item0=List 10, 10, 40, 50
Item1=List 60, 10, 40, 50
Item2=List 110, 10, 40, 50

En version XML, c'est mieux :

<Main>
  <Window ShowStatusBar="true" BackgroundImage="gfx/bk.png">
    <List x="10" y="10" width="40" height="50" />
    <List x="60" y="10" width="40" height="50" />
    <List x="110" y="10" width="40" height="50" />
  </Window>
</Main>

Malheureusement jusqu'ici le parseur XML que j'avais fait était très simple et manquait de fonctionnalité. Je me suis donc attelé à la tâche à l'aide du document de référence XML du W3C, afin de réaliser un meilleur parseur :

  • qui travaille en Unicode (avant mon parseur parsait bêtement des caractères 8 bits).
  • reconnait tout type d'encodage. Le nouveau parseur sait lire de l'UTF-8, de l'UCS-2 little ou big endian, de l'UCS-4 little ou big endian, de l'UTF-16 little ou big endian, ou des caractères sur 8 bits. Dans ce derniers cas il reconnait l'encodage et convertira le tout proprement vers un caractère Unicode en fonction du charset indiqué.
  • les références sont reconnues. Soit une référence sur caractères, comme &#160; (une espace insécable) ou une référence sur entité, comme &amp; (une esperluette). Avant je me tapais un ReplaceAll tout bête mais c'était loin d'être élégant et sans risques.
  • le parsing des noms suit la grammaire de la norme. Non, une lettre ce n'est pas seulement un truc compris entre A et Z :) Pareil pour les chiffres, faut compter les chiffres exprimés dans les écritures des différentes langues :)
  • pleins de détections d'erreurs avec des messages explicites. C'est l'inconvénient quand on crée un logiciel pour parser des fichiers textes, il y a davantage de code de gestion d'erreur que de code vraiment utile :-p
  • pleins de petits détails pour rendre le tout conforme à la norme.

Il y a encore des fonctionnalités à ajouter, ça se fera au fur et à mesure, comme la gestion des balises de doctype. Il y aussi l'éternel problème du stockage des chaines Unicode. Je gère tout en UCS-2, ce n'est pas parfait mais c'est un bon compromis.

Quoi qu'il en soit, le nouveau parseur est en place et c'est bien pratique ; à moi le parsing de fichiers XML évolué ! ^^, Et pourquoi pas un navigateur web xhtml ? :) (Du vrai xhtml bien formé délivré en application/xhtml+xml, sinon ça ne fonctionnera pas). Le tout se charge facilement, comme illustré ici :

CXmlDocument xd;
if( !xd.Load("config.xml"))
{
  Print(L"Erreur de chargement " + xd.GetLastErrorString() + L"\n");
}

La nouvelle version de la classe sera disponible dans la prochaine version de la dkstd :)

L'extraction d'un caractère issu d'un encodage particulier est une opération un peu délicate. De plus je construis mes chaines caractère par caractère, ce qui m'a fait un peu peur au niveau des performances. J'ai donc amélioré ce que j'ai pu, notamment l'opération de concaténation de caractère dans ma classe de chaine. J'ai aussi revu le code pour éviter le maximum de copies. Pour tester les performances, j'ai utilisé un gros fichier XML de 5000 lignes.

Résultat : 120 millisecondes pour le chargement quand le fichier est en cache, 160 sinon. Ça me parait pas mal, mais je ne sais pas trop vraiment sur quoi baser mon apréciation. Il faudrait que je télécharge et teste du code de parsing XML sur le Net, mais en attendant, je suis allé voir deux logiciels que j'ai sous la main et qui parsent du XML : Internet Explorer et Firefox. J'ai minimisé la fenêtre pour ne pas trop compter le temps d'affichage. Voici les résultats :

  • Internet Explorer : une seconde
  • Firefox 0.9 : une minute 55

Oui, vous avez bien lu, 115 secondes pour charger mon fichier XML ! Là je crois qu'il y a un réel problème dans Gecko. Si j'ai un peu de temps j'ouvrirai une fiche de bug, parce que voilà des perfs dignes d'une limace :-p