Analizza XML per ottenere il valore del nodo nello script bash?

Vorrei sapere come posso ottenere il valore di un nodo con i seguenti percorsi:

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 

dal seguente XML:

<?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> 

Inoltre voglio assegnare quel valore alla variabile per un ulteriore utilizzo. Fammi sapere la tua idea.

Commenti

Risposta

Utilizzo di bash e xmllint (come indicato dai tag):

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 

Nel caso in cui ci sia solo una stringa XML e si debba evitare luso di un file temporaneo, i descrittori di file sono la strada da percorrere con xmllint (che viene fornito /dev/fd/3 come argomento del file qui):

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 

Commenti

Risposta

Anche se ci sono già molte risposte, interloquisco con 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 

Con un po di magia puoi persino impostarle direttamente come variabili:

Risposta

Utilizzo di xmllint e lopzione –xpath , è molto semplice. Puoi semplicemente farlo:

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 

Se hai bisogno di raggiungere lattributo di un elemento, è facile anche usare XPath. Immagina di avere il file:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <addon name="Turn Off" version="0.10.0" provider-name="Dag Wieërs"> ..snip.. </addon> 

Le istruzioni della shell necessarie sarebbero:

VERSION=$(xmllint --xpath "string(/addon/@version)" $ADDON_XML) AUTHOR=$(xmllint --xpath "string(/addon/@provider-name)" $ADDON_XML) 

Risposta

Quanto segue funziona quando viene eseguito sui dati del 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) 

Ciò inserisce il contenuto nelle variabili host, username, password e dbname.

Commenti

  • xmlstarlet: comando non trovato, quindi questo comando non mi è utile: (
  • @MagePsycho bash non ha alcun supporto integrato per lanalisi XML. È necessario disporre di uno strumento che lo faccia (xmlstarlet, xsltproc, un moderno Python, ecc.) , oppure puoi ‘ t analizzare XML correttamente.
  • @CharlesDuffy cè un modo per ottenere il valore potrebbe usare il pattern regex o altro?
  • @MagePsycho puoi semplicemente installare xmlstarlet. In ogni caso, non usare mai regul espressioni ar per analizzare (X) HTML .
  • @MagePsycho Stavo per pubblicare lo stesso link che aveva già fatto terdon. In breve: No.

Risposta

Un bash puro funzione, solo per lo sfortunato caso in cui non ti è permesso installare qualcosa di appropriato. Questo potrebbe, e probabilmente fallirà, con un XML più complicato:

 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 }  

Utilizzo :

bash-4.1$ xmlpath "config/global/resources/default_setup/connection/host" < MagePsycho.xml localhost 

Problemi noti:

  • lento
  • cerca solo per nomi di tag
  • nessuna decodifica di entità carattere

Risposta

Questo commento usa solo comandi e metodi sh / bash! /test.xml è il tuo file di tipo XML alla prima domanda …

#!/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 

output:

host: localhost username: root password: pass123 dbname: testdb 

se vuoi scrivere questi valori su file usa questo metodo:

#!/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 

questo metodo sovrascriverà i tuoi file locali usati solo ottenendo valori (i tuoi dati andrà perso dai file di output)

Risposta

Puoi usare la codifica dellinterfaccia della riga di comando php negli script bash per gestire diversi complessi script che in realtà si estendono su più righe di codice. Innanzitutto, prova a creare la tua soluzione utilizzando gli script PHP, quindi in seguito passa i parametri utilizzando la modalità CLI. In questo modo, puoi ottenere il controllo sugli utilizzi superbi dei parser XML.

Lambiente sembra che tu possa utilizzare PHP in modalità client tramite laccesso ssh / shell.

php -f yourxmlparser.php 

Ora, fai tutte le cose allinterno del tuo file php. Utilizza i parametri della riga di comando che può richiedere.

Puoi persino assegnare quei valori di ritorno allambiente Shell per continuare il resto dei tuoi script di shell.

E laltro modo è usare | opzione grep per abbinare il valore richiesto allinterno del file xml, se sei abbastanza sicuro della struttura del tuo file xml che non cambia nel tempo.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *