Я новичок в 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 в вопросе все еще не правильно сформирован):
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 и загружу код утром.
Единственное изменение, которое мне пришлось внести в ваш код, — это добавить синтаксический анализ в третью строку: с doc=etree.XML(hosts) на etree.parse(hosts). В противном случае он дает мне точные данные на выходе. Большое спасибо! это сэкономило мне часы работы.
Во-первых, ваш xml сформирован неправильно; пожалуйста, отредактируйте с помощью короткого репрезентативного образца xml. Во-вторых, укажите точный ожидаемый результат от этого образца.