Comment analyser XML en utilisant shellscript? [dupliquer]
cette question a déjà une réponse ici:
- comment analyser XML en Bash? 14 réponses
j'aimerais savoir quelle serait la meilleure façon d'analyser un fichier XML en utilisant shellscript ?
- Doit-on le faire à la main ?
- Existe-t-il une bibliothèque de troisième niveau ?
Si vous avez déjà si vous pouviez laissez-moi savoir comment avez-vous réussi à le faire
11 réponses
Vous pouvez essayer de xmllint
le programme xmllint part un ou plusieurs Fichiers XML, spécifiés sur la commande ligne xmlfile. Il imprime divers les types de sortie, selon le les options sélectionnées. Il est utile pour détection des erreurs à la fois dans le code XML et dans L'analyseur XML itse
il vous permet de sélectionner des éléments dans le XML doc par xpath, en utilisant l'option --pattern.
sur Mac OS X (Yosemite), il est installé par défaut.
Sur Ubuntu, s'il n'est pas déjà installé, vous pouvez lancer apt-get install libxml2-utils
voici un exemple complet.
Si c'est seulement l'extraction des adresses email vous pourriez juste faire quelque chose comme:
1) supposons que le spam du fichier XML.xml est comme
<spam>
<victims>
<victim>
<name>The Pope</name>
<email>pope@vatican.gob.va</email>
<is_satan>0</is_satan>
</victim>
<victim>
<name>George Bush</name>
<email>father@nwo.com</email>
<is_satan>1</is_satan>
</victim>
<victim>
<name>George Bush Jr</name>
<email>son@nwo.com</email>
<is_satan>0</is_satan>
</victim>
</victims>
</spam>
2) Vous pouvez obtenir les e-mails et les traiter avec ce code bash court:
#!/bin/bash
emails=($(grep -oP '(?<=email>)[^<]+' "/my_path/spam.xml"))
for i in ${!emails[*]}
do
echo "$i" "${emails[$i]}"
# instead of echo use the values to send emails, etc
done
résultat de cet exemple est:
0 pope@vatican.gob.va
1 father@nwo.com
2 son@nwo.com
remarque Importante:
Ne l'utilisez pas pour des choses sérieuses. C'est OK pour jouer autour, obtenir des résultats rapides, apprendre grep, etc. mais vous devez certainement rechercher, apprendre et utiliser un analyseur XML pour la production (voir le commentaire de Micha ci-dessous).
je suis surpris que personne n'ait mentionné xmlsh . La déclaration de mission:
un shell de ligne de commande pour XML basé sur la philosophie et la conception de la Unix Shells
xmlsh fournit un environnement de script familier, mais spécifiquement adapté au script des processus xml.
une liste de commandes shell similaires est fournie ici .
j'utilise la commande xed
qui est l'équivalent de sed
pour XML, et permet la recherche basée sur XPath
et remplace.
avez-vous des xml_grep installé? C'est une norme d'utilité perl basée sur certaines distributions (elle est venue pré-installée sur mon système CentOS). Plutôt que de les donner une expression régulière, vous lui donnez une expression xpath.
un projet assez nouveau est le paquet xml-coreutils avec xml-cat, xml-cp, xml-cut, xml-grep, ...
essayez xpath. Vous pouvez l'utiliser pour analyser les éléments d'un arbre xml.
http://www.ibm.com/developerworks/xml/library/x-tipclp/index.html
c'est vraiment au-delà des capacités du script shell. Shell script et les outils Unix standard sont bons pour analyser les fichiers orientés ligne, mais les choses changent quand vous parlez de XML. Même les étiquettes simples peuvent présenter un problème:
<MYTAG>Data</MYTAG>
<MYTAG>
Data
</MYTAG>
<MYTAG param="value">Data</MYTAG>
<MYTAG><ANOTHER_TAG>Data
</ANOTHER_TAG><MYTAG>
imaginez essayer d'écrire un script shell qui peut lire les données contenues dans . Les trois exemples très, très simplement XML montrent tous de différentes façons que cela peut être un problème. Les deux premiers exemples sont la même syntaxe en XML. Le troisième a un attribut attaché à elle. La quatrième contient les données dans une autre balise. Les commandes simples sed
, awk
et grep
ne peuvent pas saisir toutes les possibilités.
vous devez utiliser un langage de script complet comme Perl, Python ou Ruby. Chacun de ces modules peut analyser des données XML et faciliter l'accès à la structure sous-jacente. J'ai utilisé XML:: Simple en Perl. Il m'a fallu quelques essais pour comprendre, mais il a fait ce dont j'avais besoin, et fait ma programmation beaucoup plus facile.
Voici une fonction qui convertira les paires nom-valeur XML et les attributs en variables de bash.
Voici une solution utilisant xml_grep (parce que xpath ne faisait pas partie de notre distribuable et que je ne voulais pas l'ajouter à toutes les machines de production)...
si vous recherchez un paramètre spécifique dans un fichier XML, et si tous les éléments à un niveau d'arbre donné sont uniques, et qu'il n'y a pas d'attributs, alors vous pouvez utiliser cette fonction pratique:
# File to be parsed
xmlFile="xxxxxxx"
# use xml_grep to find settings in an XML file
# Input (): path to setting
function getXmlSetting() {
# Filter out the element name for parsing
local element=`echo | sed 's/^.*\///'`
# Verify the element is not empty
local check=${element:?getXmlSetting invalid input: }
# Parse out the CDATA from the XML element
# 1) Find the element (xml_grep)
# 2) Remove newlines (tr -d \n)
# 3) Extract CDATA by looking for *element> CDATA <element*
# 4) Remove leading and trailing spaces
local getXmlSettingResult=`xml_grep --cond $xmlFile 2>/dev/null | tr -d '\n' | sed -n -e "s/.*$element>[[:space:]]*\([^[:space:]].*[^[:space:]]\)[[:space:]]*<\/$element.*//p"`
# Return the result
echo $getXmlSettingResult
}
#EXAMPLE
logPath=`getXmlSetting //config/logs/path`
check=${logPath:?"XML file missing //config/logs/path"}
cela fonctionnera avec cette structure:
<config>
<logs>
<path>/path/to/logs</path>
<logs>
</config>
il fonctionnera aussi avec ceci (mais il ne gardera pas les nouvelles lignes):
<config>
<logs>
<path>
/path/to/logs
</path>
<logs>
</config>
si vous avez dupliqué
FYI: ce code fonctionne sur RedHat 6.3 avec GNU BASH 4.1.2, mais je ne pense pas que je fasse quelque chose de particulier à cela, donc devrait fonctionner partout.
NOTE: pour toute personne nouvelle au script, faire bien sûr, vous utilisez les bons types de guillemets, tous les trois sont utilisés dans ce code (guillemet simple normal '=littéral, guillemet simple en arrière `=execute, et guillemet double "=group).