我有一段看起来像这样的XML:
<ns:Vehicle>
<ns:Model>AVALON</ns:Model>
<ns:ModelYear>1998</ns:ModelYear>
<ns:MakeString>TY</ns:MakeString>
<ns:VehicleID>VIN NUMBER GOES HERE</ns:VehicleID>
</ns:Vehicle>
我有以下代码将车辆元素变成字典:
xml_file = open('6046179.xml')
soup = BeautifulSoup(xml_file)
# Vehicle elements
el_model = soup.find('ns:model').text
el_model_year = soup.find('ns:modelyear').text
el_make_string = soup.find('ns:makestring').text
el_vehicle_id = soup.find('ns:vehicleid').text
vehicle = {'model': '{}'.format(el_model),
'model_year': '{}'.format(el_model_year),
'make_string': '{}'.format(el_make_string),
'vehicle_id': '{}'.format(el_vehicle_id)}
print vehicle
我只是想知道是否有更好的方法来做到这一点,我不介意浏览XML中的其他元素并单独定义它们,我只是想知道是否有更干净的这样做的方法。
答案 0 :(得分:2)
可能会更清洁,但基本上没有什么不同:
tags = ['model', 'modelyear', 'makestring', 'vehicleid']
vehicle = {}
for tag in tags:
vehicle[tag] = '{}'.format(soup.find('ns:' + tag).text)
还有xmltodict可能值得一看。
答案 1 :(得分:1)
BeautifulSoup并不适用于XML - 它非常适合凌乱的HTML,这会破坏正确的解析器。
你最好使用etree接口(通过,也许是非常快的lxml),无论如何,IIRC是BS默认使用的。然后你得到root元素并用几行代码迭代它的所有子元素,例如:
#!/usr/bin/env python
import xml.etree.ElementTree as ET
import re
# Note the dummy namespace that must / should have been there...
xml = '''
<ns:Vehicle xmlns:ns="http://foo.bar">
<ns:Model>AVALON</ns:Model>
<ns:ModelYear>1998</ns:ModelYear>
<ns:MakeString>TY</ns:MakeString>
<ns:VehicleID>VIN NUMBER GOES HERE</ns:VehicleID>
</ns:Vehicle>'''
tree = ET.fromstring(xml)
vehicle = {re.sub(r'{.*}', '', node.tag): node.text for node in tree}
答案 2 :(得分:1)
如果你想要{em> all <ns:Vehicle>
元素中的子节点,你不需要明确指定它们 - 只需遍历所有子元素并将它们放入字典。
from bs4 import BeautifulSoup
soup = BeautifulSoup('''
<ns:Vehicle>
<ns:Model>AVALON</ns:Model>
<ns:ModelYear>1998</ns:ModelYear>
<ns:MakeString>TY</ns:MakeString>
<ns:VehicleID>VIN NUMBER GOES HERE</ns:VehicleID>
</ns:Vehicle>
''')
# loop if you have multiple vehicles
# Note that BS normalizes all tag names to lowercase -> we use 'ns:vehicle' rather 'ns:Vehicle'
for el_vehicle in soup.find_all('ns:vehicle'):
vehicle = {child.name: child.text for child in el_vehicle.findChildren()}
# stick `vehicle` in a list or do some other processing
这并不完全匹配您的输出,因为它不会从camelcase转换为以下划线分隔的名称(例如ModelYear
到model_year
),并且它也没有&#39;从名称名称中删除名称空间。如果您需要,那么在child.name
周围包含一个包装器以便相应地更改名称就不会太困难。