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
- Nu folosiți niciodată bash pentru a analiza arborii structurați de date arbitrare. Folosiți un analizor XML real. Recomand XMLStarlet .
- stackoverflow.com/questions/893585/how-to -parse-xml-in-bash
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
- Pagina manuală: xmlsoft.org/xmllint.html
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.