Skip to content

Enrichir ses tableurs Excel ou LibreOffice Calc grâce à des API (3/4) : les espaces de noms et XPath

26/07/2016

On est est resté, à la fin de l’épisode précédent, à un fichier XML tout simple que l’expression XPath envisagée n’arrivait pas à retrouver.

Voici un des fichiers XML récupérés grâce l’ISBN :

<sparql xmlns="http://www.w3.org/2005/sparql-results#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.w3.org/2001/sw/DataAccess/rf1/result2.xsd">
<head>
<variable name="ark"/>
</head>
<results distinct="false" ordered="true">
<result>
<binding name="ark"><literal>ark:/12148/cb34657300h</literal></binding>
</result>
</results>
</sparql>

Tel est le résultat renvoyé par un Sparql Endpoint quand on lui demande une réponse en XML

Un espace de nom, c’est quoi ?

C’est simple : dans les fichiers XML qu’on peut rencontrer, c’est ce qui précède le « : » dans le nom de la balise.

Ainsi, si dans un fichier XML vous rencontrez <dc:title>Education européenne  [Texte imprimé]  / Romain Gary</dc:title>, la balise title a comme espace de nom dc : cela signifie que la propriété title appartient à un vocabulaire spécifique, et que ce vocabulaire est précisé dans le fichier XML.

Je ne sais pas pourquoi, les navigateurs n’affichent pas les déclarations d’espaces de nom, et si vous ouvrez cette notice RDF l’espace de nom « dc » ne semblera pas déclaré.

espace de nom dctitle

Pour le voir, il vous faut afficher le code source de cette page (Clic droit > Code source de la page ou Ctrl+U). Il n’y a pas d’indentation dans le code source, c’est pas de bol, ça ne facilite pas la lecture. En tout cas voilà ce que ça donne :

RDF - liste des namespace

J’ai surligné en jaune un ensemble d’attributs affectés à la balise racine du fichier <rdf:RDF>. Tous ces attributs s’appellent xmlns:quelquechose="uri"

« ns » signifie namespace (espace de nom). xmlns:quelquechose="uri" signifie donc : espace de nom XML QuelqueChose est la manière abrégée de raccrocher un ensemble de balise au même vocabulaire qu’on désigne par un uri commun

Et donc si vous regardez bien, vous verrez que s’y trouve la déclaration de l’espace de nom « dc » sous la forme :

 xmlns:dc="http://purl.org/dc/elements/1.1/"

Et si vous suivez l’URL http://purl.org/dc/elements/1.1/, vous tombez (évidemment) sur la description du vocabulaire Dublin Core (non étendu)

Avec XPath, il faut donc désigner un élément en précisant son espace de nom. Pour accéder à la balise dc:title dans le fichier ci-dessus, il faudrait donc préciser « //dc:title » et non pas « //title »

« Oui, mais dans le résultat Sparql, la balise en question n’a pas de préfixe… »

C’est vrai, le résultat est dans la ligne :

<binding name="ark"><literal>ark:/12148/cb34657300h</literal></binding>

Mais dans la balise racine, on trouve l’attribut suivant :

xmlns="http://www.w3.org/2005/sparql-results#"

Ce qui signifie que toutes les balises sans préfixe-espace de nom se rattachent par défaut au vocabulaire http://www.w3.org/2005/sparql-results#

Je précise que cette situation est très fréquente dans les API : les résultats Marc21 de WorldCat par exemple on un espace de nom vide (c’est-à-dire sans préfixe).

Comportement différencié dans Excel et dans Calc

Dans Excel, on constate la chose suivante :

  • quand la balise a un préfixe déclaré (comme dc:), on peut l’ajouter dans le XPath.
    Par exemple, on peut récupérer le dc:title en écrivant
    =FILTRE.XML(SERVICEWEB("http://www.sudoc.fr/082268789.rdf");"//dc:title")
  • quand la balise se rattache à un espace de nom sans préfixe (comme c’est le cas dans les résultats XML de Sparql), le XPath ne trouve rien.

Dans Calc, c’est pire

Qu’il y ait un préfixe ou non, Calc n’arrive pas à accéder aux balises dès lors qu’elles sont associées à un espace de nom.

Comment faire ?

On entre alors dans le bidouillage / bricolage. Comme je l’ai déjà dit, la documentation est indigente concernant cette fonction, que ce soit pour Excel ou pour Calc. Il existe peut-être une manière propre de déclarer dans la fonction FILTRE.XML (Excel) ou FILTREXML (Calc) un espace de nom, mais je n’ai pas trouvé comment. Si vous avez la réponse « académique », elle m’intéresse.

En attendant, voilà comment je me débrouille :

Pour faire simple, j’introduis entre FILTREXML et SERVICEWEBune étape de transformation-modification du résultat XML afin d’escamoter l’espace de nom.

Deux cas de figure

  • les balises ont un espace de nom avec préfixe (« dc: », « rdf: », etc.) :
    [manipulation inutile sous Excel, comme je le dis plus haut]
    J’utilise la fonction SUBSTITUE() (SUBSTITUTE() en anglais) qui va chercher toutes les occurrences de ce préfixe et les remplacer par rien.
    Exemple : =SUBSTITUE("<dc:title>Education européenne  [Texte imprimé]  / Romain Gary</dc:title>";"dc:";"") récupère les toutes les occurrences de « dc: » dans la chaîne de caractères indiquée, et le remplace par rien.
    Application : =FILTREXML(SUBSTITUE(SERVICEWEB("http://www.sudoc.fr/082268789.rdf");"dc:";"");"//title")

    • SERVICEWEB() récupère le contenu « natif » de la notice RDF
    • la fonction SUBSTITUE() récupère le contenu de SERVICEWEB() et y enlève tous les « dc: »
    • la fonction FILTREXML() exploite ce fichier XML retraité pour en récupérer la balise <title> qui a remplacé <dc:title>
  • les balises ont un espace de nom sans nom (comme dans le résultat XML de Sparql)
    J’utilise alors la fonction SUBSTITUE() pour supprimer la déclaration de l’espace de nom « vide » :
    Exemple : =SUBSTITUE("<sparql xmlns=""http://www.w3.org/2005/sparql-results#"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xsi:schemaLocation=""http://www.w3.org/2001/sw/DataAccess/rf1/result2.xsd">";" xmlns=""http://www.w3.org/2005/sparql-results#"";"")
    Attention : dans Excel comme dans Calc, on peut mettre des guillemets à l’intérieur de valeurs de formule en les répétant : "" au lieu de ".
    Application : =FILTREXML(SUBSTITUE(SERVICEWEB("http://data.bnf.fr/sparql?default-graph-uri=&query=PREFIX+bnf-onto%3A+%3Chttp%3A%2F%2Fdata.bnf.fr%2Fontology%2Fbnf-onto%2F%3Eselect+%28substr%28str%28%3Furi%29%2C20%2C22%29+as+%3Fark%29+where+%7B++%3Furi+bnf-onto%3Aisbn+%222-901040-29-2%22%0D%0A%7D&format=application%2Fsparql-results%2Bxml&timeout=0&should-sponge=&debug=on");" xmlns=""http://www.w3.org/2005/sparql-results#""";"");"//binding[@name='ark']")

Au bout d’un moment, je reconnais qu’il peut être plus prudent de découper le processus en plusieurs colonnes successives…

Sur un Sparql Endpoint, le HTML pourra être plus pertinent, sauf si par exemple vous voulez récupérer plusieurs valeurs (plusieurs colonnes) en une seule requête :

  • en HTML, il faudra dans le XPath tenir compte du numéro de la colonne : "//td[1]", "//td[2]", etc
    Et on risque de perdre pied
  • En XML, on précise dans le XPath le nom de la variable mis dans la requête : "//binding[@name='ark']", "//binding[@name='isbn']", "//binding[@name='DateDeNaissance']", etc.

Il me reste un dernier billet à rédiger : comme faire quand une requête renvoie plusieurs réponses (par exemple : un ISBN renvoie plusieurs ARK, ou plusieurs PPN).

Car la méthode FILTREXML ne renvoie que la première réponse…

%d blogueurs aiment cette page :