Git --projet-boite-à-outils

Extraction XML

Extraction XML avec LibXML

Je rappelle que le code a été refactorisé de façon à utiliser une référence à une fonction d’extraction. Ainsi, toute la partie concernant l’ouverture des fichiers, le parcours récursif du répertoire et la création des fichiers de sortie n’est pas dupliquée.

Pour que cela fonctionne, il faut bien évidemment que les fonctions d’extractions (basées sur des opérations sur les chaînes ou sur XML) aient la même interface : elles doivent prendre les mêmes arguments et renvoyer le même type de résultat.

C’est pourquoi le code originel de la fonction d’extraction par chaîne a été légèrement modifié : à l’origine il supprimait les balises les plus externes du contenu qu’il extrayait. Mais ce comportement ne permettait pas à la fonction d’extraction XML de fonctionner, puisque cela engendrait une erreur de parsing lorsqu’on l’appelait successivement pour extraire le contenu d’un élément précédemment extrait, c’est à dire en composant la fonction avec elle-même (par exemple extraire le titre d’un item).

Le code en lui même est d'une simplicité enfantine, puisqu'il ne s'agit que de faire un appel à la fonction DOM getElementsByTagName sur une représentation objet d'un noeud XML préalablement construite à partir de la chaîne passée en paramètre.

lib-parcours-xml.pl
use warnings;
use strict;
use XML::LibXML;
use Try::Tiny;

# param $content : texte xml à traiter
# param $tag : nom (sans crochets) du tag xml dont il faut récupérer le contenu
# return : la liste des contenus du tag contenu dans le texte
sub extract_xml
{
    my ($content, $tag) = @_;
    
    my @list = ();
    my $parser = new XML::LibXML;
    
    try {
        my $xml_doc = $parser->parse_string($content);

        foreach my $t ($xml_doc->getElementsByTagName($tag))
        {
            push @list, $t->toStringEC14N;
        }
    } catch {
        warn "Erreur dans extract_rss : $_";
    };
    
    return @list;
}

1;

Extraction XPATH

Bien que l’API XPATH soit relativement simple d’utilisation, une méthode d’extraction l’utilisant n’a pas été implémentée. En effet, j’ai déjà évoqué le fait que la méthode d’extraction doit renvoyer une chaîne et doit pouvoir travailler en prenant comme argument le retour d’un autre appel à elle-même.

Cependant, l’API ne permet de le faire (du moins pas raisonnablement facilement) car un appel à string_value va enlever tout les noms des nœuds enfants pour ne garder que le texte visible. Si ce n’est pas un problème majeur lorsqu’il s’agit d’un élement feuille, c’est très problématique pour travailler sur les nœuds item d’un flux RSS.

Je n’ai pas vu venir ce problème suffisamment tôt dans le développement, car j’ai l’habitude d’utiliser un framework dont le comportement était celui que j’attendais, à savoir qu’un appel à une méthode type toString renvoie le contenu du nœud sous forme XML (cf. System.Xml.Linq.XNode.ToString). Et je n'avais pas envie de refaire la majeure partie de mon code pour me plier à une API mal designée.

Extraction RSS

Il existe un module Perl basé sur LibXML spécialisé dans le traitement des fichiers RSS. Il n'a pas été non plus utilisé, car il ne peut parser que des fichiers RSS, ce qui incompatible avec l'approche utilisée.

En effet, l'extraction doit pouvoir travailler sur des fragments de XML bien formé, alors que l'API travaille sur des fichiers RSS entier. Ceci dit, l'utilisation de ce module est relativement simple, et vous pouvez consulter le travail d'une camarade sur le sujet.