次のパスを使用してノードの値を取得する方法を知りたいです。
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
次の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>
また、その値を変数に割り当てて、後で使用できるようにします。あなたのアイデアを教えてください。
bash
とxmllint
の使用(タグで指定):
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
XML文字列のみがあり、一時ファイルの使用を避けたい場合は、ファイル記述子はxmllint
(/dev/fd/3
ここにファイル引数として):
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
答えはたくさんありますが、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
ちょっとした魔法で、それらを直接変数として設定することさえできます:
$ eval $(xml2 < test.xml | tr '/, ' '___' | grep =)
$ echo $_config_global_resources_default_setup_connection_Host
localhost
xmllintおよび-xpathオプションを使用すると、非常に簡単です。あなたは単にこれを行うことができます:
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
要素の属性にアクセスする必要がある場合は、XPathを使用するのも簡単です。次のファイルがあるとします。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addon id="screensaver.turnoff"
name="Turn Off"
version="0.10.0"
provider-name="Dag Wieërs">
..snip..
</addon>
必要なシェルステートメントは次のとおりです。
VERSION=$(xmllint --xpath 'string(/addon/@version)' $ADDON_XML)
AUTHOR=$(xmllint --xpath 'string(/addon/@provider-name)' $ADDON_XML)
純粋なbash
関数。適切なものをインストールすることが許可されていないという不幸な場合のために。これは、より複雑な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
}
使用法:
bash-4.1$ xmlpath 'config/global/resources/default_setup/connection/Host' < MagePsycho.xml
localhost
既知の問題点:
テストデータに対して実行すると、以下が機能します。
{ 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)
これにより、コンテンツが変数Host
、username
、password
、dbname
に入れられます。
Phpコマンドラインインターフェイスコーディングをbashスクリプトで使用して、実際には複数行のコーディングにまたがるいくつかの複雑なスクリプトを処理できます。まず、PHPスクリプトを使用してソリューションを作成し、その後、CLIモードを使用してパラメーターを渡します。これにより、XMLパーサーの優れた使用法を制御できます。
Ssh/Shellアクセスを介してクライアントモードでPHP=を使用できる環境です。
php -f yourxmlparser.php
次に、phpファイル内ですべてのことを行います。使用できるコマンドラインパラメータを使用します。
その戻り値をシェル環境に割り当てて、残りのシェルスクリプトを続行することもできます。
もう1つの方法は、| grepオプションを使用して、xmlファイル内の必要な値を一致させることです。これは、時間の経過に伴って変化しないxmlファイルの構造がかなり確実な場合です。
このコメントは、sh/bashコマンドとメソッドのみを使用します! /test.xmlは、最初の質問でのXMLタイプファイルです...
#!/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
出力:
Host: localhost
username: root
password: pass123
dbname: testdb
この値をファイルに書き込む場合は、このメソッドを使用します。
#!/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
このメソッドは、値の取得のみに使用されるローカルファイルを上書きします(データは出力ファイルから失われます)