【问题标题】:Parsing Network Device Inventory in XML Format with Python使用 Python 解析 XML 格式的网络设备清单
【发布时间】:2020-12-12 19:51:38
【问题描述】:

我是 Python 新手,试图解析一个包含交换机和路由器清单的 xml 文件。 我已经通过导入 ET 并使用以下代码来获取 xml 文件中的前一两行库存来尝试此操作: (我已经阅读了此站点上解析 xml 文件的其他解决方案,并尝试了其中一些,即使使用 BeautifulSoup,但我的 xml 文件的结构却没有运气。)。

我可以使用 Python 识别根的根和子,但是,我遇到的问题是向下钻取并调用“table_data”下包含的实际数据。下面是xml文件的sn-p,文件里大概还有20多个设备。 在 for 循环中,我尝试了“字段名称”,也尝试了“字段”和“名称”,但没有结果。 当然,此时在“for 循环”中调用其他标签不起作用。 如果您能指出正确的方向,我将不胜感激。

import xml.etree.ElementTree as ET
tree = ET.parse('ios_inventory.xml')
root = tree.getroot()


for f in root.findall('field'):
    att=f.attrib
    n=att.get('name')

“ios_inventory.xml”的内容

  <?xml version="1.0"?>
<mysqldump xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<database name="IOS_INVENTORY">
    <table_structure name="Cisco_IOS_Inventory">
        <field Field="Hostname" Type="varchar(100)" Null="YES" Key="" Extra="" Comment="" />
        <field Field="Local_IPs" Type="varchar(5000)" Null="YES" Key="" Extra="" Comment="" />
        <field Field="Local_SVI_IPs" Type="varchar(5000)" Null="YES" Key="" Extra="" Comment="" />
        <field Field="IOS_Image" Type="varchar(200)" Null="YES" Key="" Extra="" Comment="" />
        <field Field="IOSVersion" Type="varchar(200)" Null="YES" Key="" Extra="" Comment="" />
        <field Field="Flash" Type="varchar(200)" Null="YES" Key="" Extra="" Comment="" />
        <field Field="SerialNo" Type="varchar(2000)" Null="YES" Key="" Extra="" Comment="" />
        <options Name="Cisco_IOS_Inventory" Engine="InnoDB" Version="10" Row_format="Compact" 
        Rows="37" Avg_row_length="442" Data_length="16384" Max_data_length="0" Index_length="0" 
        Data_free="5242880" Create_time="2017-05-31 04:23:01" Collation="latin1_swedish_ci" 
        Create_options="" Comment="" />`
    </table_structure>
    <table_data name="Cisco_IOS_Inventory">
    <row>
        <field name="Hostname">SW2
</field>
        <field name="Local_IPs"></field>
        <field name="Local_SVI_IPs">10.100.x.x</field>
        <field name="IOS_Image">CAT3K_CAA-UNIVERSALK9-M</field>
        <field name="IOSVersion">03.06.10E RELEASE SOFTWARE (fc2)</field>
        <field name="Flash">1621966848 bytes total</field>
        <field name="SerialNo">xxxxxxxxxxxxx</field>
    </row>
    <row>
        <field name="Hostname">SW3
</field>
        <field name="Local_IPs"></field>
        <field name="Local_SVI_IPs">10.100.x.x</field>
        <field name="IOS_Image">CAT3K_CAA-UNIVERSALK9-M</field>
        <field name="IOSVersion">03.06.10E RELEASE SOFTWARE (fc2)</field>
        <field name="Flash">1621966848 bytes total</field>
        <field name="SerialNo">xxxxxxxxxxxxx</field>
    </row>
    <row>
        <field name="Hostname">RTR_2</field>
        <field name="Local_IPs">10.100.x.x | 10.253.x.x</field>
        <field name="Local_SVI_IPs"></field>
        <field name="IOS_Image">X86_64_LINUX_IOSD-UNIVERSALK9-M</field>
        <field name="IOSVersion">16.4.2, RELEASE SOFTWARE (fc1)</field>
        <field name="Flash">6741659648 bytes total</field>
        <field name="SerialNo">XXXXXXXXX</field>
    </row>
    

谢谢杰克。我在底部粘贴了简短的 xml 示例。想要获得如下所示的输出 - 具有相应的值。 请注意:Local_SVI_IP 在 xml 文件中可以有多个 IP 地址。

hostname: 
Local_SVI_IPs:
IOS_Image: 
IOSVersion: 
Flash:
SerialNo:



        <field name="Hostname">SW2</field>
        <field name="Local_IPs"></field>
        <field name="Local_SVI_IPs">10.100.x.x</field>
        <field name="IOS_Image">CAT3K_CAA-UNIVERSALK9-M</field>
        <field name="IOSVersion">03.06.10E RELEASE SOFTWARE (fc2)</field>
        <field name="Flash">1621966848 bytes total</field>
        <field name="SerialNo">xxxxxxxxxxxxx</field>
    </row>

【问题讨论】:

  • 首先,您的 xml 格式不正确;请用一个简短的、有代表性的 xml 示例进行编辑。其次,请说明您对该样本的确切预期输出。

标签: python xml-parsing


【解决方案1】:

在你的实际 xml 上试试这个;但是使用您提供的那个(请注意,问题中的 xml 格式仍然不正确):

from lxml import etree
hosts = """[your xml above, fixed]"""
doc = etree.XML(hosts)
rows  = doc.xpath('//row')
for row in rows:    
        print('hostname: ',row.xpath('field[@name="Hostname"]/text()')[0].strip())
        if len(row.xpath('field[@name="Local_SVI_IPs"]/text()'))>0:
            print('Local_SVI_IPs: ',row.xpath('field[@name="Local_SVI_IPs"]/text()')[0].strip())
        else:
            print('Local_SVI_IPs: NA')
        print('IOS_Image: ',row.xpath('field[@name="IOS_Image"]/text()')[0].strip())
        print('IOSVersion: ',row.xpath('field[@name="IOSVersion"]/text()')[0].strip())
        print('Flash: ',row.xpath('field[@name="Flash"]/text()')[0].strip())
        print('SerialNo: ',row.xpath('field[@name="SerialNo"]/text()')[0].strip())    
        print('-------')

输出:

hostname:  SW2
Local_SVI_IPs:  10.100.x.x
IOS_Image:  CAT3K_CAA-UNIVERSALK9-M
IOSVersion:  03.06.10E RELEASE SOFTWARE (fc2)
Flash:  1621966848 bytes total
SerialNo:  xxxxxxxxxxxxx
-------
hostname:  SW3
Local_SVI_IPs:  10.100.x.x
IOS_Image:  CAT3K_CAA-UNIVERSALK9-M
IOSVersion:  03.06.10E RELEASE SOFTWARE (fc2)
Flash:  1621966848 bytes total
SerialNo:  xxxxxxxxxxxxx
-------
hostname:  RTR_2
Local_SVI_IPs: NA
IOS_Image:  X86_64_LINUX_IOSD-UNIVERSALK9-M
IOSVersion:  16.4.2, RELEASE SOFTWARE (fc1)
Flash:  6741659648 bytes total
SerialNo:  XXXXXXXXX

【讨论】:

  • 感谢您的回复。我会修复xml文件并在早上加载代码。
  • 我必须对您的代码进行的唯一更改是将 parse 添加到第三行:从 doc=etree.XML(hosts) 到 etree.parse(hosts)。否则,它会给我输出中的确切数据。太感谢了!这为我节省了几个小时的工作时间。
猜你喜欢
  • 2019-08-04
  • 1970-01-01
  • 2012-02-12
  • 1970-01-01
  • 2022-10-06
  • 2017-05-29
  • 1970-01-01
  • 2012-05-20
  • 1970-01-01
相关资源
最近更新 更多