使用python在xml中查找元素

时间:2019-02-12 13:56:26

标签: python xml parsing

我正在尝试解析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'对象没有属性'tag'

预先感谢您提供的所有帮助。

3 个答案:

答案 0 :(得分:0)

尝试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

答案 1 :(得分:0)

您可以使用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)

答案 2 :(得分:0)

首先,您的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