Recherche sur le blog

jeudi 17 octobre 2013

[Java] Exemple d’utilisation de l’API StAX 2

StAX 2 est une API expérimentale, de type “pull”, basée sur l’API StAX. La seule implémentation connue jusqu’à présent est Woodstox. Elle vise à étendre les possibilités de StAX en ajoutant des fonctionnalités supplémentaires : l’accès à des informations qui étaient inaccessibles auparavant (DOCTYPE, index de l’attribut, vérifier si l’élément est vide, obtenir le niveau actuel de l’élément), la conversion du contenu textuel en contenu typé (v3.0 – Woodstock v4.0),etc. Le téléchargement des packages se fait sur la page officielle.

L’utilisation de StAX est intéressante, surtout pour effectuer un traitement sur des gros fichiers, car sa consommation mémoire est très basse. De plus, l’accès est séquentiel : les retours arrière ne sont pas possibles.

Dans l’exemple, nous utilisons l’API de type “curseur”. Celui-ci nous renvoie la position dans le document, ensuite il suffit d’utiliser une série de fonctions pour obtenir telle ou telle information.

Initialisation et configuration

Il faut tout d’abord initialiser et configurer notre parseur. Nous utilisons ici l’API expérimentale, donc certaines classes se voient suffixées d’un “2”. On utilise la fonction “newInstance()” de la factory (“fabrique”).

init-stax2

Il faut ensuite configurer les propriétés. Certaines sont booléennes, d’autres sont des propriétés objet. Par exemple, la propriété “IS_COALESCING” à “False” permet de renvoyer de multiples évènements de types “caractère”, plutôt que de stocker tout le texte en mémoire. Petite note : lors du parcours, le buffer est limité à 8000 caractères, ensuite il se vide pour se remplir à nouveau.

Des fonctions supplémentaires, comme “configureForSpeed()”, sont utiles dans le cas où on ne souhaite pas définir chaque paramètre un à un. En effet, les valeurs de certains paramètres seront choisies en fonction de la méthode utilisée. La documentation officielle indique quels sont les paramètres impactés et les valeurs effectives.

Récupérer un parseur

La seconde étape consiste à récupérer un parseur grâce à la méthode “createXMLStreamReader()”. Celle-ci est surchargée, on peut donc lui passer un objet de type “File”.

createXMLStreamReader

Cela crée un parseur de type “curseur”. Pour savoir s’il reste des éléments à lire, on doit utiliser la méthode “hasNext()”. Pour passer à l’élément suivant, on utilise la fonction “next()”. Cela renvoie un entier qui correspond à une constante (exemples : CHARACTERS, START_ELEMENT, END_ELEMENT, ATTRIBUTE, etc). Dans une boucle, on pourra tester cet entier.

Effectuer un traitement différent selon l’évènement

Les constantes pour les types d’évènements sont définies dans la classe “XMLEvent2”. Il en existe une bonne dizaine mais en général, elles ne sont pas toutes utilisées. On peut par exemple effectuer un “switch…case…” pour effectuer un traitement différent, comme dans l’exemple ci-dessous (cliquez pour agrandir)…

exemple

Lorsqu’on se trouve face à un élément de type “Characters”, on peut commencer à traiter le contenu et stocker le tout dans une ou plusieurs chaines différentes. Par exemple, on souhaite récupérer le contenu de l’élément “<UPC>”. Comme nous l’avons mentionné ci-dessus, nous avons désactivé la propriété “Is Coalescing”. Nous travaillons avec un buffer pré-défini de 8000 caractères. Il faut donc s’assurer de bien compléter chaque chaine pour retrouver l’ensemble du contenu.

getText-characters

La méthode “getText()” permet de récupérer le contenu et de le stocker dans une chaine de caractères. Une fois le contenu récupéré, on regarde à quel élément il appartient (on connait la position actuelle car on a stocké le nom de l’élément parcouru lors du traitement de l’évènement “START_ELEMENT”). Ensuite, comme on voit qu’il s’agit de l’élément “<UPC>”, on ajoute le contenu à la chaine “sUPC” puis on vérifie si elle a atteint 13 caractères (souvenez-vous : le buffer…)

Lorsqu’on arrive à l’élément de fin (END_ELEMENT)…

En général, c’est là qu’on va appliquer une opération d’insertion dans la base de données par exemple. Effectivement, supposons la structure suivante, qui décrit un article (un livre), que l’on veut ajouter à la base de données.

<article>
   <upc>9781234567890</upc>
   <title>Ceci est un livre</title>
</article>

C’est au moment où l’on rencontre la balise fermante qu’il faut idéalement enregistrer les données dans votre table. En résumé, dans votre boucle, vous devez tester si votre évènement est de type “END_ELEMENT”, ensuite indiquer les différents paramètres dans un “PreparedStatement”, éventuellement initialisé à l’avance.

Libérer les ressources

En Java, il est très important de faire attention aux ressources utilisées, et il faut bien entendu les libérer à un moment donné, afin de vider la mémoire. Toujours prendre l’habitude d’appeler la méthode “close()” quand elle est disponible. C’est le cas ici pour notre parseur.

StreamReaderClose

Une bonne pratique consiste à placer ce code dans le bloc d’instruction “finally” de votre traitement d’exceptions. Ainsi, même si une erreur se produit, tout le code placé dans ce bloc sera exécuté quoi qu’il arrive.

Sources

Introduction à StAX – Développez

Aucun commentaire: