Je voudrais savoir comment je peux obtenir la valeur dun nœud avec les chemins suivants:
config/global/resources/default_setup/connection/host config/global/resources/default_setup/connection/username config/global/resources/default_setup/connection/password config/global/resources/default_setup/connection/dbname
à partir du XML suivant:
<?xml version="1.0"?> <config> <global> <install> <date><![CDATA[Tue, 11 Dec 2012 12:31:25 +0000]]></date> </install> <crypt> <key><![CDATA[70e75d7969b900b696785f2f81ecb430]]></key> </crypt> <disable_local_modules>false</disable_local_modules> <resources> <db> <table_prefix><![CDATA[]]></table_prefix> </db> <default_setup> <connection> <host><![CDATA[localhost]]></host> <username><![CDATA[root]]></username> <password><![CDATA[pass123]]></password> <dbname><![CDATA[testdb]]></dbname> <initStatements><![CDATA[SET NAMES utf8]]></initStatements> <model><![CDATA[mysql4]]></model> <type><![CDATA[pdo_mysql]]></type> <pdoType><![CDATA[]]></pdoType> <active>1</active> </connection> </default_setup> </resources> <session_save><![CDATA[files]]></session_save> </global> <admin> <routers> <adminhtml> <args> <frontName><![CDATA[admin]]></frontName> </args> </adminhtml> </routers> </admin> </config>
Je souhaite également attribuer cette valeur à la variable pour une utilisation ultérieure. Faites-moi savoir votre idée.
Commentaires
- Nutilisez jamais bash pour analyser des arbres structurés de données arbitraires. Utilisez un véritable analyseur XML. Je recommande XMLStarlet .
- stackoverflow.com/questions/893585/how-to -parse-xml-in-bash
Réponse
Utilisation de bash
et xmllint
(comme indiqué par les balises):
xmllint --version # xmllint: using libxml version 20703 # Note: Newer versions of libxml / xmllint have a --xpath option which # makes it possible to use xpath expressions directly as arguments. # --xpath also enables precise output in contrast to the --shell & sed approaches below. #xmllint --help 2>&1 | grep -i "xpath"
{ # the given XML is in file.xml host="$(echo "cat /config/global/resources/default_setup/connection/host/text()" | xmllint --nocdata --shell file.xml | sed "1d;$d")" username="$(echo "cat /config/global/resources/default_setup/connection/username/text()" | xmllint --nocdata --shell file.xml | sed "1d;$d")" password="$(echo "cat /config/global/resources/default_setup/connection/password/text()" | xmllint --nocdata --shell file.xml | sed "1d;$d")" dbname="$(echo "cat /config/global/resources/default_setup/connection/dbname/text()" | xmllint --nocdata --shell file.xml | sed "1d;$d")" printf "%s\n" "host: $host" "username: $username" "password: $password" "dbname: $dbname" } # output # host: localhost # username: root # password: pass123 # dbname: testdb
Dans le cas où il ny a quune chaîne XML et que lutilisation dun fichier temporaire est à éviter, les descripteurs de fichiers sont la solution avec xmllint
(qui est donné /dev/fd/3
comme argument de fichier ici):
set +H { xmlstr="<?xml version="1.0"?> <config> <global> <install> <date><![CDATA[Tue, 11 Dec 2012 12:31:25 +0000]]></date> </install> <crypt> <key><![CDATA[70e75d7969b900b696785f2f81ecb430]]></key> </crypt> <disable_local_modules>false</disable_local_modules> <resources> <db> <table_prefix><![CDATA[]]></table_prefix> </db> <default_setup> <connection> <host><![CDATA[localhost]]></host> <username><![CDATA[root]]></username> <password><![CDATA[pass123]]></password> <dbname><![CDATA[testdb]]></dbname> <initStatements><![CDATA[SET NAMES utf8]]></initStatements> <model><![CDATA[mysql4]]></model> <type><![CDATA[pdo_mysql]]></type> <pdoType><![CDATA[]]></pdoType> <active>1</active> </connection> </default_setup> </resources> <session_save><![CDATA[files]]></session_save> </global> <admin> <routers> <adminhtml> <args> <frontName><![CDATA[admin]]></frontName> </args> </adminhtml> </routers> </admin> </config> " # exec issue #exec 3<&- 3<<<"$xmlstr" #exec 3<&- 3< <(printf "%s" "$xmlstr") exec 3<&- 3<<EOF $(printf "%s" "$xmlstr") EOF { read -r host; read -r username; read -r password; read -r dbname; } < <( echo "cat /config/global/resources/default_setup/connection/*[self::host or self::username or self::password or self::dbname]/text()" | xmllint --nocdata --shell /dev/fd/3 | sed -e "1d;$d" -e "/^ *--* *$/d" ) printf "%s\n" "host: $host" "username: $username" "password: $password" "dbname: $dbname" exec 3<&- } set -H # output # host: localhost # username: root # password: pass123 # dbname: testdb
Commentaires
- Page de manuel: xmlsoft.org/xmllint.html
Réponse
Bien quil y ait déjà beaucoup de réponses, je « répondrai avec xml2
.
$ xml2 < test.xml /config/global/install/date=Tue, 11 Dec 2012 12:31:25 +0000 /config/global/crypt/key=70e75d7969b900b696785f2f81ecb430 /config/global/disable_local_modules=false /config/global/resources/db/table_prefix /config/global/resources/default_setup/connection/host=localhost /config/global/resources/default_setup/connection/username=root /config/global/resources/default_setup/connection/password=pass123 /config/global/resources/default_setup/connection/dbname=testdb /config/global/resources/default_setup/connection/initStatements=SET NAMES utf8 /config/global/resources/default_setup/connection/model=mysql4 /config/global/resources/default_setup/connection/type=pdo_mysql /config/global/resources/default_setup/connection/pdoType /config/global/resources/default_setup/connection/active=1 /config/global/session_save=files /config/admin/routers/adminhtml/args/frontName=admin
Avec un peu de magie, vous pouvez même les définir directement comme variables:
Réponse
Utilisation de xmllint et loption –xpath , cest très simple. Vous pouvez simplement faire ceci:
XML_FILE=/path/to/file.xml HOST=$(xmllint --xpath "string(/config/global/resources/default_setup/connection/host)" $XML_FILE USERNAME=$(xmllint --xpath "string(/config/global/resources/default_setup/connection/username)" $XML_FILE PASSWORD=$(xmllint --xpath "string(/config/global/resources/default_setup/connection/password)" $XML_FILE DBNAME=$(xmllint --xpath "string(/config/global/resources/default_setup/connection/dbname)" $XML_FILE
Si vous avez besoin daccéder à lattribut dun élément, cest aussi facile en utilisant XPath. Imaginez que vous ayez le fichier:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <addon name="Turn Off" version="0.10.0" provider-name="Dag Wieërs"> ..snip.. </addon>
Les instructions shell nécessaires seraient:
VERSION=$(xmllint --xpath "string(/addon/@version)" $ADDON_XML) AUTHOR=$(xmllint --xpath "string(/addon/@provider-name)" $ADDON_XML)
Réponse
Ce qui suit fonctionne lorsquil est exécuté sur vos données de test:
{ read -r host; read -r username; read -r password; read -r dbname; } \ < <(xmlstarlet sel -t -m /config/global/resources/default_setup/connection \ -v ./host -n \ -v ./username -n \ -v ./password -n \ -v ./dbname -n)
Cela place le contenu dans les variables host
, username
, password
et dbname
.
Commentaires
- xmlstarlet: commande introuvable, donc cette commande ne mest pas utile: (
- @MagePsycho
bash
na pas de support intégré pour lanalyse XML. Vous devez soit avoir un outil qui le fait (xmlstarlet, xsltproc, un Python moderne, etc.) , ou vous pouvez ‘ analyser correctement le XML. - @CharlesDuffy existe-t-il un moyen dobtenir la valeur peut-être en utilisant un modèle dexpression régulière ou bien?
- @MagePsycho vous pouvez simplement installer xmlstarlet. Dans tous les cas, vous ne devez jamais utiliser regul ar expressions pour analyser (X) HTML .
- @MagePsycho Jétais sur le point de publier le même lien que terdon a déjà fait. En bref: Non.
Réponse
Un pur bash
fonction, juste pour le cas malheureux où vous nêtes pas autorisé à installer quoi que ce soit dapproprié. Cela peut échouer, et échouera probablement sur du XML plus compliqué:
function xmlpath() { local expr="${1//\// }" local path=() local chunk tag data while IFS="" read -r -d "<" chunk; do IFS=">" read -r tag data <<< "$chunk" case "$tag" in "?"*) ;; "!–-"*) ;; "![CDATA["*) data="${tag:8:${#tag}-10}" ;; ?*"/") ;; "/"?*) unset path[${#path[@]}-1] ;; ?*) path+=("$tag") ;; esac [[ "${path[@]}" == "$expr" ]] && echo "$data" done }
Utilisation :
bash-4.1$ xmlpath "config/global/resources/default_setup/connection/host" < MagePsycho.xml localhost
Problèmes connus:
- lent
- recherche uniquement par nom de balise
- aucun décodage dentité de caractère
Réponse
Ce commentaire utilise uniquement les commandes et méthodes sh / bash! /test.xml est votre fichier de type XML à la première question …
#!/bin/sh cat /test.xml | while read line;do [ "$(echo "$line" | grep "<host>")" ]&& echo "host: $(echo $line | cut -f3 -d"[" | cut -f1 -d"]")" [ "$(echo "$line" | grep "<username>")" ]&& echo "username: $(echo $line | cut -f3 -d"[" | cut -f1 -d"]")" [ "$(echo "$line" | grep "<password>")" ]&& echo "password: $(echo $line | cut -f3 -d"[" | cut -f1 -d"]")" [ "$(echo "$line" | grep "<dbname")" ]&& echo "dbname: $(echo $line | cut -f3 -d"[" | cut -f1 -d"]")" done
résultat:
host: localhost username: root password: pass123 dbname: testdb
si vous voulez écrire ces valeurs dans un fichier, utilisez cette méthode:
#!/bin/sh cat /test.xml | while read line;do [ "$(echo "$line" | grep "<host>")" ]&& echo "$line" | cut -f3 -d"[" | cut -f1 -d"]" > /config/global/resources/default_setup/connection/host [ "$(echo "$line" | grep "<username>")" ]&& echo "$line" | cut -f3 -d"[" | cut -f1 -d"]" > /config/global/resources/default_setup/connection/username [ "$(echo "$line" | grep "<password>")" ]&& echo "$line" | cut -f3 -d"[" | cut -f1 -d"]" > /config/global/resources/default_setup/connection/password [ "$(echo "$line" | grep "<dbname")" ]&& echo "$line" | cut -f3 -d"[" | cut -f1 -d"]" > /config/global/resources/default_setup/connection/dbname done
cette méthode écrasera vos fichiers locaux utilisés uniquement pour obtenir des valeurs (vos données sera perdu des fichiers de sortie)
Réponse
Vous pouvez utiliser le codage dinterface de ligne de commande php dans les scripts bash pour gérer plusieurs scripts qui couvrent en fait plusieurs lignes de codage. Tout dabord, essayez de créer votre solution à laide de scripts PHP, puis transmettez plus tard les paramètres en mode CLI. Ainsi, vous pouvez contrôler les superbes utilisations des analyseurs XML.
Lenvironnement semble que vous puissiez utiliser PHP en mode client via laccès ssh / shell.
php -f yourxmlparser.php
Maintenant, faites toutes les choses dans votre fichier php. Utilisez les paramètres de ligne de commande que cela peut prendre.
Vous pouvez même attribuer ces valeurs de retour à lenvironnement Shell pour continuer le reste de vos scripts shell.
Et lautre façon est dutiliser | grep pour correspondre à votre valeur requise dans le fichier xml, si vous êtes assez sûr de la structure de votre fichier xml qui ne change pas avec le temps.