web-dev-qa-db-fra.com

Linux Bash XMLLINT avec XPATH

Aujourd'hui, j'apprends à utiliser correctement xmllint. Il ne semble pas être bien couvert ou expliqué. Je prévois d'utiliser un fichier de ressource linguistique unique pour exécuter l'ensemble de mon système. J'ai un mélange de scripts bash et de pages php qui doivent lire ce fichier de langue.

J'utilise actuellement le format suivant dans mon fichier xml en.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>

   <item id="index.php">
        <label>LABEL</label>
        <value>VALUE</value>
        <description>DESCRIPTION</description>
   </item>
   <item id="config.php">
        <label>LABEL</label>
        <value>VALUE</value>
        <description>DESCRIPTION</description>
   </item>

</resources>

Maintenant, je dois commencer par une ligne de script bash qui doit extraire les valeurs de données du fichier XML. Par exemple, je souhaite obtenir la valeur DESCRIPTION à partir de l'élément index.php.

J'utilisais 

xmllint --xpath 'string(//description)' /path/en.xml

pour une présentation différente qui a fonctionné, mais maintenant que je modifie la présentation de mon fichier xml, je ne sais plus comment cibler au mieux un <item> spécifique, puis explorer son élément enfant dans le script bash.

Quelqu'un peut-il aider avec une ligne xmllint --xpath pour obtenir cette valeur s'il vous plaît?

11
RootWannaBe

comment cibler au mieux un élément spécifique, puis accéder à son élément enfant

L’expression XPath correcte à faire est la suivante:

/resources/item[@id="index.php"]/description/text()

En clair: Commencez du nœud du document à l'élément de document resources, à son enfant item, mais uniquement si la valeur de l'attribut id est "index.php", à son enfant description et récupérez sa valeur textuelle.

J'utilise xmllint pour valider les documents XML, mais jamais pour les expressions de chemin. Dans un shell bash (du moins sous Mac OS), il existe un outil encore plus simple pour évaluer les expressions XPath, appelé "xpath":

$ xpath en.xml '/resources/item[@id="index.php"]/description/text()'

Ensuite, le résultat suivant est obtenu:

Found 1 nodes:
-- NODE --
DESCRIPTION

Si vous préférez toujours xmllint, utilisez-le de la manière suivante:

$ xmllint --xpath '/resources/item[@id="index.php"]/description/text()' en.xml > result.txt

Par défaut, --xpath implique --noout, ce qui empêche xmllint de générer quoi que ce soit. Rediriger la sortie vers un fichier.

$ cat result.txt 
DESCRIPTION
12
Mathias Müller

Mon préféré est xmlstarlet car il semble être plus puissant que xmllint :

xmlstarlet sel -t -v '/resources/item[@id="index.php"]/description/text()' en.xml
1
typelogic

J'ai eu le même problème il y a quelques minutes et j'ai vu ce post.

Après avoir piraté un peu, j'ai trouvé la solution suivante pour extraire la ville:

(wget 'http://maps.googleapis.com/maps/api/geocode/xml?latlng=53.244921,-2.479539&sensor=true' -O dummy.xml -o /dev/null;xmllint --format --xpath '/GeocodeResponse/result[type = "postal_town"]/address_component[type = "postal_town"]/short_name/node()'  dummy.xml)

Vous devez spécifier le chemin X correct pour obtenir la balise XML souhaitée, puis renvoyer uniquement la valeur du noeud.

0
Andreas Cordes