Command-Line

解析 XML 以獲取 bash 腳本中的節點值?

  • July 15, 2021

我想知道如何通過以下路徑獲取節點的值:

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>

我還想將該值分配給變數以供進一步使用。讓我知道你的想法。

使用bashand 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

引用自:https://unix.stackexchange.com/questions/83385