Python XML解析

时间:2013-09-21 01:46:06

标签: python xml parsing namespaces

我正在尝试使用Python解析从OCTranspo(渥太华城市公交公司)检索到的XML文件。我的问题是我似乎无法访问子域,例如纬度和经度。

以下是示例xml文件的大幅缩短版本,但仍会导致问题:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>

<Route xmlns="http://tempuri.org/">

<Trips>
<Trip><TripDestination>Barrhaven Centre</TripDestination
<TripStartTime>19:32</TripStartTime><Latitude>45.285458</Latitude
<Longitude>-75.746786</Longitude></Trip>
</Trips>

</Route>

</soap:Body>
</soap:Envelope>

这是我的代码:

import xml.etree.ElementTree as ET
import urllib

u = urllib.urlopen('https://api.octranspo1.com/v1.1/GetNextTripsForStop', 'appID=7a51d100&apiKey=5c5a8438efc643286006d82071852789&routeNo=95&stopNo=3044')
data = u.read()

f = open('route3044.xml', 'wb')
f.write(data)
f.close()

doc = ET.parse('route3044.xml')

for bus in doc.findall('Trip'):
    lat = bus.findtext('Latitude')
    #NEVER EXECUTES
    print trip

如果我对一个非常简单的xml文件(没有soap:Envelope ...)执行相同的代码,那么代码可以完美地运行。但是,由于我需要的xml是由OCTranspo生成的,我无法控制格式。

我不确定问题是否是“命名空间”问题或Python中的错误。

任何帮助都将不胜感激。

更新:2013年9月21日

我将搜索Lat和Lon的代码更改为:

doc = ET.parse('Stop1A.xml')

for a in doc.findall('{http://schemas.xmlsoap.org/soap/envelope/}Body'):
    for b in a.findall('{http://octranspo.com}GetNextTripsForStopResponse'): 
        for c in b.findall('{http://octranspo.com}GetNextTripsForStopResult'):   
            for d in c.findall('{http://tempuri.org/}Route'):
                for e in d.findall('{http://tempuri.org/}RouteDirection'):
                    direction = e.findtext('{http://tempuri.org/}Direction')
                    if direction == 'Eastbound':
                        for f in e.findall('{http://tempuri.org/}Trips'):
                            for g in f.findall('{http://tempuri.org/}Trip'):
                                lat = g.findtext('{http://tempuri.org/}Latitude')
                                lon = g.findtext('{http://tempuri.org/}Longitude')
                                print lat + ',' + lon
                                print 'Done'

最终结果是我现在可以看到95号路线上的“东行”巴士。我知道这段代码并不漂亮,但它确实有效。我的下一个目标是使用命名空间技巧进行优化。

如果有人想要尝试访问网址,请注意,通常会看到“没有公共汽车”5-7分钟,因为网址只返回最近的6条公交车到停靠点。三辆公共汽车向东行驶,三辆公共汽车向西行驶。如果最近的公共汽车超过7分钟,则返回为空。代码返回总线的Lat和Lon - 然后我可以使用Google Maps绘制位置。

凯利

2 个答案:

答案 0 :(得分:2)

根据ElementTree documentation

  

Element.findall()仅查找带有当前元素的直接子项标记的元素。 (强调添加)

幸运的是,ElementTree有XPath support

doc.findall('Trip')(搜索doc的直接子级)更改为doc.findall('.//Trip')(以递归方式搜索doc的子级),它应该按预期工作。

答案 1 :(得分:1)

这是获取每次旅行的纬度和经度的简单方法。您不需要遍历每个元素。请注意使用.//查找所有 {http://tempuri.org/}Trip元素。

import xml.etree.ElementTree as ET

doc = ET.parse("temp.xml")     # Your shortened XML document

for bus in doc.findall('.//{http://tempuri.org/}Trip'):
    lat = bus.findtext('{http://tempuri.org/}Latitude')
    lon = bus.findtext('{http://tempuri.org/}Longitude')
    print lat, lon

输出:

45.285458 -75.746786