今回は 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 -> 辞書への変換ができることが分かるかと思います。
今回はここまで。