XML parseren om knooppuntwaarde in bash-script te krijgen?

Ik zou graag willen weten hoe ik de waarde van een knooppunt met de volgende paden kan krijgen:

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 

uit de volgende 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> 

Ook wil ik die waarde aan de variabele toewijzen voor verder gebruik. Laat me je idee weten.

Reacties

Antwoord

Met bash en xmllint (zoals gegeven door de tags):

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 

In het geval dat er slechts een XML-string is en het gebruik van een tijdelijk bestand moet worden vermeden, zijn bestandsdescriptors de juiste keuze met xmllint (die hier /dev/fd/3 als bestandsargument wordt gegeven):

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 

Reacties

Antwoord

Hoewel er al veel antwoorden zijn, “bel ik in met 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 

Met een beetje magie kun je deze zelfs rechtstreeks als variabelen instellen:

Antwoord

Met xmllint en de –xpath optie, het is heel gemakkelijk. U kunt dit eenvoudig doen:

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 

Als u naar het kenmerk van een element moet gaan, is dat ook gemakkelijk met XPath. Stel je voor dat je het bestand hebt:

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

De benodigde shell-instructies zouden zijn:

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

Answer

Het volgende werkt als het wordt uitgevoerd tegen uw testgegevens:

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

Dit plaatst de inhoud in variabelen host, username, password en dbname.

Reacties

  • xmlstarlet: commando niet gevonden, dus dit commando is niet nuttig voor mij: (
  • @MagePsycho bash heeft geen ingebouwde ondersteuning voor XML-parsing. Je hebt ofwel een tool nodig die dat wel doet (xmlstarlet, xsltproc, een moderne Python, enz.) , of je kunt ‘ XML correct parseren.
  • @CharlesDuffy is er een manier om de waarde te krijgen door het gebruik van een regex-patroon of anders?
  • @MagePsycho, je kunt gewoon xmlstarlet installeren. In elk geval mag je nooit regul gebruiken ar-expressies om (X) HTML te ontleden.
  • @MagePsycho Ik stond op het punt dezelfde link te plaatsen die terdon al deed. In het kort: Nee.

Antwoord

Een pure bash functie, alleen voor het ongelukkige geval dat u niets passend mag installeren. Dit kan en zal waarschijnlijk mislukken bij meer gecompliceerde XML:

 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 }  

Gebruik :

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

Bekende problemen:

  • langzaam
  • zoekt alleen op tagnamen
  • geen karakter-entiteit-decodering

Antwoord

Deze opmerking gebruikt alleen sh / bash-commandos en -methoden! /test.xml is uw XML-typebestand bij de eerste vraag …

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

als u deze waarden naar een bestand wilt schrijven, gebruik dan deze methode:

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

deze methode overschrijft uw lokale bestanden die alleen worden gebruikt om waarden op te halen (uw gegevens zal verloren gaan uit outputbestanden)

Answer

Je kunt gebruik maken van php command line interface codering in bash scripts om verschillende complexe scripts die feitelijk meerdere coderegels beslaan. Probeer eerst uw oplossing te maken met behulp van PHP-scripts en geef de parameters later door in de CLI-modus. Zodoende kunt u controle krijgen over uitmuntend gebruik van XML-parsers.

De omgeving lijkt erop dat u PHP in client-modus kunt gebruiken via ssh / shell-toegang.

php -f yourxmlparser.php 

Doe nu alle dingen in je php-bestand. Maak gebruik van opdrachtregelparameters die nodig zijn.

U kunt zelfs die retourwaarden toewijzen aan de Shell-omgeving om de rest van uw shell-scripts voort te zetten.

En de andere manier is om | grep-optie om uw vereiste waarde in het xml-bestand overeen te laten komen, als u vrij zeker bent van de structuur van uw xml-bestand die in de loop van de tijd niet verandert.

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *