Analizați XML pentru a obține valoarea nodului în scriptul bash?

Aș dori să știu cum pot obține valoarea unui nod cu următoarele căi:

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 

din următorul 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> 

De asemenea, vreau să atribui acea valoare variabilei pentru o utilizare ulterioară. Anunță-mi ideea ta.

Comentarii

Răspuns

Utilizarea bash și xmllint (așa cum este dat de etichete):

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 

În cazul în care există doar un șir XML și trebuie evitată utilizarea unui fișier temporar, descriptorii de fișiere sunt calea de urmat cu xmllint (care este dat /dev/fd/3 ca argument de fișier aici):

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 

Comentarii

Răspuns

Deși există deja o mulțime de răspunsuri, o să aud cu 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 

Cu puțină magie le puteți seta chiar ca variabile direct:

Răspuns

Utilizarea xmllint și opțiunea –xpath , este foarte ușor. Puteți face acest lucru pur și simplu:

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 

Dacă trebuie să ajungeți la atributul unui element, acesta este ușor și cu XPath. Imaginați-vă că aveți fișierul:

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

Instrucțiunile shell necesare ar fi:

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

Răspuns

Următoarele funcționează atunci când rulează pe datele de testare:

{ 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) 

Aceasta plasează conținutul în variabile host, username, password și dbname.

Comentarii

  • xmlstarlet: comanda nu a fost găsită, deci această comandă nu îmi este utilă: (
  • @MagePsycho bash nu are nicio asistență încorporată pentru analiza XML. Fie că trebuie să aveți un instrument care să o facă (xmlstarlet, xsltproc, un Python modern etc.) sau nu puteți ‘ să analizați corect XML.
  • @CharlesDuffy există o modalitate de a obține valoarea folosind un model regex sau altceva?
  • @MagePsycho puteți instala xmlstarlet. În orice caz, nu ar trebui să să utilizați niciodată regul expresii ar pentru a analiza (X) HTML .
  • @MagePsycho Eram pe punctul de a posta același link terdon deja. Pe scurt: Nu.

Răspuns

Un bash pur funcție, doar pentru cazul nefericit când nu aveți voie să instalați nimic adecvat. Acest lucru poate și probabil va eșua pe un XML mai complicat:

 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 }  

Utilizare :

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

Probleme cunoscute:

  • lent
  • căutări numai după nume de etichete
  • nicio decodare a entității de caractere

Răspuns

Acest comentariu folosește doar comenzi și metode sh / bash! /test.xml este fișierul dvs. de tip XML la prima întrebare …

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

ieșire:

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

dacă doriți să scrieți aceste valori în fișier folosiți această metodă:

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

această metodă va suprascrie fișierele locale folosite doar obținând valori (datele dvs. se va pierde din fișierele de ieșire)

Răspuns

Puteți utiliza codarea interfeței liniei de comandă php în scripturile bash pentru a gestiona mai multe complexe scripturi care se întind de fapt pe mai multe linii de codare. Mai întâi, încercați să vă faceți soluția folosind scripturi PHP, iar mai apoi treceți parametrii folosind modul CLI. Astfel, puteți obține controlul asupra utilizărilor superbe ale analizatorilor XML.

Mediul pare că puteți utiliza PHP în modul client prin acces ssh / shell.

php -f yourxmlparser.php 

Acum, faceți toate lucrurile din fișierul php. Utilizați parametrii din linia de comandă pe care îi poate lua.

Puteți chiar atribui valorile returnate mediului Shell pentru a continua restul scripturilor dvs. shell.

Și cealaltă modalitate este să utilizați | opțiunea grep pentru a se potrivi cu valoarea dorită din fișierul xml, dacă sunteți destul de sigur de structura fișierului dvs. xml care nu se modifică în timp.

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *