Анализ инвентаризации сетевых устройств в формате XML с помощью Python

Я новичок в Python, пытаюсь разобрать xml-файл, содержащий инвентарь коммутатора и маршрутизатора. Я попробовал это, импортировав ET и используя приведенный ниже код, чтобы просто получить первые одну или две строки инвентаризации в файле xml: (Я читал другие решения для анализа XML-файлов на этих сайтах и ​​пробовал некоторые из них, даже с BeautifulSoup, но мне не повезло со структурой моего XML-файла.).

Я могу определить корень и дочерний элемент корня с помощью Python, однако у меня возникают проблемы с разверткой и вызовом фактических данных, содержащихся в «table_data». Ниже фрагмент xml файла, в файле еще около 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 могут иметь несколько IP-адресов в xml-файле.

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. Во-вторых, укажите точный ожидаемый результат от этого образца.

Jack Fleeting 12.12.2020 22:05
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
1
142
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 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 и загружу код утром.

tony ramsey 13.12.2020 03:27

Единственное изменение, которое мне пришлось внести в ваш код, — это добавить синтаксический анализ в третью строку: с doc=etree.XML(hosts) на etree.parse(hosts). В противном случае он дает мне точные данные на выходе. Большое спасибо! это сэкономило мне часы работы.

tony ramsey 13.12.2020 16:55

Другие вопросы по теме