Поиск элемента в XML с Python - PullRequest
0 голосов
/ 12 февраля 2019

Я пытаюсь проанализировать XML перед преобразованием его содержимого в списки, а затем в CSV.К сожалению, я думаю, что мои условия поиска для нахождения начального элемента терпят неудачу, вызывая последующие поиски далее вниз по иерархии.Я новичок в XML, поэтому я попробовал варианты словарей пространств имен, включая ссылки на пространства имен ... Упрощенный XML приведен ниже:

<?xml version="1.0" encoding="utf-8"?>
<StationList xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
			xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
			xmlns:add="http://www.govtalk.gov.uk/people/AddressAndPersonalDetails" 
			xmlns:com="http://nationalrail.co.uk/xml/common"            xsi:schemaLocation="http://internal.nationalrail.co.uk/xml/XsdSchemas/External/Version4.0/nre-station-v4-0.xsd" 
			xmlns="http://nationalrail.co.uk/xml/station">
  <Station xsi:schemaLocation="http://internal.nationalrail.co.uk/xml/XsdSchemas/External/Version4.0/nre-station-v4-0.xsd">
    <ChangeHistory>
      <com:ChangedBy>spascos</com:ChangedBy>
      <com:LastChangedDate>2018-11-07T00:00:00.000Z</com:LastChangedDate>
    </ChangeHistory>
    <Name>Aber</Name>
  </Station>​

Код, который я использую для извлечения элемента com / ... xml / station / ChangedBy, находится ниже

tree = ET.parse(rootfilepath + "NRE_Station_Dataset_2019_raw.xml")
root = tree.getroot()

#get at the tags and their data
#for elem in tree.iter():
#    print(f"this the tag {elem.tag} and this is the data: {elem.text}")

#open file for writing
station_data = open(rootfilepath + 'station_data.csv','w')

csvwriter = csv.writer(station_data)

station_head = []

count = 0
#inspiration for this code: http://blog.appliedinformaticsinc.com/how-to-  parse-and-convert-xml-to-csv-using-python/
#this is where it goes wrong; some combination of the namespace and the tag can't find anything in line 27, 'StationList'
for member in root.findall('{http://nationalrail.co.uk/xml/station}Station'):
station = []
if count == 0:
changedby = member.find('{http://nationalrail.co.uk/xml/common}ChangedBy').tag
station_head.append(changedby)

    name = member.find('{http://nationalrail.co.uk/xml/station}Name').tag
    station_head.append(name)

    count = count+1

changedby = member.find('{http://nationalrail.co.uk/xml/common}ChangedBy').text
station.append(changedby)

name = member.find('{http://nationalrail.co.uk/xml/station}Name').text
station.append(name)

csvwriter.writerow(station)

Я пытался:

  • с использованием словарей пространств имен, но это приводит к тому, что вообще ничего не найдено
  • с использованием жестко закодированных пространств имен, но это приводит к «Ошибка атрибута: у объекта NoneType нет тега attribute»

Заранее благодарим за помощь и помощь.

Ответы [ 3 ]

0 голосов
/ 12 февраля 2019

Вы можете использовать Beautifulsoup, который является парсером HTML и XML

from bs4 import BeautifulSoup

fd = open(rootfilepath + "NRE_Station_Dataset_2019_raw.xml")  
soup = BeautifulSoup(fd,'lxml-xml')

for i in soup.findAll('ChangeHistory'):      
    print(i.ChangedBy.text)
0 голосов
/ 13 февраля 2019

Прежде всего, ваш XML неверен (</StationList> отсутствует в конце файла).

Предполагается, что у вас есть действительный файл XML:

<?xml version="1.0" encoding="utf-8"?>
<StationList xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns:add="http://www.govtalk.gov.uk/people/AddressAndPersonalDetails"
            xmlns:com="http://nationalrail.co.uk/xml/common"            xsi:schemaLocation="http://internal.nationalrail.co.uk/xml/XsdSchemas/External/Version4.0/nre-station-v4-0.xsd"
            xmlns="http://nationalrail.co.uk/xml/station">
  <Station xsi:schemaLocation="http://internal.nationalrail.co.uk/xml/XsdSchemas/External/Version4.0/nre-station-v4-0.xsd">
    <ChangeHistory>
      <com:ChangedBy>spascos</com:ChangedBy>
      <com:LastChangedDate>2018-11-07T00:00:00.000Z</com:LastChangedDate>
    </ChangeHistory>
    <Name>Aber</Name>
  </Station>​
</StationList>

Затем вы можете преобразоватьваш XML в JSON и просто обратитесь к требуемому значению:

import xmltodict
with open('file.xml', 'r') as f:
    data = xmltodict.parse(f.read())
changed_by = data['StationList']['Station']['ChangeHistory']['com:ChangedBy']

Вывод:

spascos
0 голосов
/ 12 февраля 2019

Попробуйте lxml:

#!/usr/bin/env python3

from lxml import etree

ns = {"com": "http://nationalrail.co.uk/xml/common"}

with open("so.xml") as f:
    tree = etree.parse(f)
    for t in tree.xpath("//com:ChangedBy/text()", namespaces=ns):
        print(t)

Вывод:

spascos
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...