Python: xmltodict を使って XML を辞書へ変換

今回は Python ネタです。

最近のネットワーク機器ではコマンドのアウトプットなどを XML で表示させることが可能です。通常の CLI 出力を頑張って正規表現で各値を取得してもいいのですが、xmltodict というライブラリを使うことで簡単に XML形式の出力を Python の辞書データに変更することが可能です。

xmltodict のインストール

XML -> 辞書への変換には xmltodict というライブラリを使います。下記 pip コマンドでインストールできます。

$ pip install xmltodict

XML形式のデータは Cisco Nexus から取得

今回は XML 形式のデータは Cisco の Nexus から取得してみました。まずは通常の CLI での出力は下記です。

# sh ip int brief
IP Interface Status for VRF "default"(1)
Interface            IP Address      Interface Status
Lo0                  3.3.3.3         protocol-up/link-up/admin-up       
Lo1                  4.4.4.4         protocol-up/link-up/admin-up       

次にパイプをして xml と入力すると、XML 形式で出力を得ることができます。

# sh ip int brief | xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<nf:rpc-reply xmlns:nf="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns="http://w
ww.cisco.com/nxos:7.0.3.I5.2.:ip">
 <nf:data>
  <show>
   <ip>
    <interface>
     <brief>
      <__readonly__>
       <TABLE_vrf>
        <ROW_vrf>
         <vrf-name-out>default</vrf-name-out>
        </ROW_vrf>
       </TABLE_vrf>
       <TABLE_intf>
        <ROW_intf>
         <intf-name>Lo0</intf-name>
         <prefix>3.3.3.3</prefix>
         <ip-disabled>FALSE</ip-disabled>
         <iod>180</iod>
         <proto-state>up</proto-state>
         <link-state>up</link-state>
         <admin-state>up</admin-state>
        </ROW_intf>
       </TABLE_intf>
       <TABLE_vrf>
        <ROW_vrf>
         <vrf-name-out>default</vrf-name-out>
        </ROW_vrf>
       </TABLE_vrf>
       <TABLE_intf>
        <ROW_intf>
         <intf-name>Lo1</intf-name>
         <prefix>4.4.4.4</prefix>
         <ip-disabled>FALSE</ip-disabled>
         <iod>181</iod>
         <proto-state>up</proto-state>
         <link-state>up</link-state>
         <admin-state>up</admin-state>
        </ROW_intf>
       </TABLE_intf>
      </__readonly__>
     </brief>
    </interface>
   </ip>
  </show>
 </nf:data>
</nf:rpc-reply>
]]>]]>

上記の最後の行にある “]]>]]>” は不要なので、この行を除く残りを Python のコードに持っていきます。

XML->辞書変換の Python コード

簡単なので、いきなり全ソースコードを貼ります。

#!/usr/bin/env python

import xmltodict
import pprint

show_xml_output = '''<?xml version="1.0" encoding="ISO-8859-1"?>
<nf:rpc-reply xmlns:nf="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns="http://w
ww.cisco.com/nxos:7.0.3.I5.2.:ip">
 <nf:data>
  <show>
   <ip>
    <interface>
     <brief>
      <__readonly__>
       <TABLE_vrf>
        <ROW_vrf>
         <vrf-name-out>default</vrf-name-out>
        </ROW_vrf>
       </TABLE_vrf>
       <TABLE_intf>
        <ROW_intf>
         <intf-name>Lo0</intf-name>
         <prefix>3.3.3.3</prefix>
         <ip-disabled>FALSE</ip-disabled>
         <iod>180</iod>
         <proto-state>up</proto-state>
         <link-state>up</link-state>
         <admin-state>up</admin-state>
        </ROW_intf>
       </TABLE_intf>
       <TABLE_vrf>
        <ROW_vrf>
         <vrf-name-out>default</vrf-name-out>
        </ROW_vrf>
       </TABLE_vrf>
       <TABLE_intf>
        <ROW_intf>
         <intf-name>Lo1</intf-name>
         <prefix>4.4.4.4</prefix>
         <ip-disabled>FALSE</ip-disabled>
         <iod>181</iod>
         <proto-state>up</proto-state>
         <link-state>up</link-state>
         <admin-state>up</admin-state>
        </ROW_intf>
       </TABLE_intf>
      </__readonly__>
     </brief>
    </interface>
   </ip>
  </show>
 </nf:data>
</nf:rpc-reply>
'''

if __name__ == '__main__':
    result = xmltodict.parse(show_xml_output)
    pprint.pprint(result)

XML形式の出力を文字列として変数に入れて、最後から2行目でパースするだけで、代入している result が辞書になります。最後の行では辞書を整形して表示するため、pprint を使ってます。

実行結果

それでは実行結果を見てます。

> ./xml_to_dict.py 
{'nf:rpc-reply': {'@xmlns:nf': 'urn:ietf:params:xml:ns:netconf:base:1.0',
                  '@xmlns': 'http://w ww.cisco.com/nxos:7.0.3.I5.2.:ip',
                  'nf:data': {'show': {'ip': {'interface': {'brief': {'__readonly__': {'TABLE_vrf': [{'ROW_vrf': {'vrf-name-out': 'default'}},
                                                                                                     {'ROW_vrf': {'vrf-name-out': 'default'}}],
                                                                                       'TABLE_intf': [{'ROW_intf': {'intf-name': 'Lo0',
                                                                                                                    'prefix': '3.3.3.3',
                                                                                                                    'ip-disabled': 'FALSE',
                                                                                                                    'iod': '180',
                                                                                                                    'proto-state': 'up',
                                                                                                                    'link-state': 'up',
                                                                                                                    'admin-state': 'up'}},
                                                                                                      {'ROW_intf': {'intf-name': 'Lo1',
                                                                                                                    'prefix': '4.4.4.4',
                                                                                                                    'ip-disabled': 'FALSE',
                                                                                                                    'iod': '181',
                                                                                                                    'proto-state': 'up',
                                                                                                                    'link-state': 'up',
                                                                                                                    'admin-state': 'up'}}]}}}}}}}}

xmltodict を使えば、非常に簡単に XML -> 辞書への変換ができることが分かるかと思います。

今回はここまで。

スポンサーリンク