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