使用BeautifulSoup将XML解析为字典

使用BeautifulSoup将XML解析为字典,xml,python-2.7,beautifulsoup,Xml,Python 2.7,Beautifulsoup,我有一段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:Vehic

我有一段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中的其余元素并像这样单独定义它们,我只是想知道是否有更干净的方法来做到这一点。

可能更干净一些,但本质上没有什么不同:

tags = ['model', 'modelyear', 'makestring', 'vehicleid']
vehicle = {}
for tag in tags:
    vehicle[tag] = '{}'.format(soup.find('ns:' + tag).text)

还有一个可能值得一看。

可能更干净一点,但本质上没有什么不同:

tags = ['model', 'modelyear', 'makestring', 'vehicleid']
vehicle = {}
for tag in tags:
    vehicle[tag] = '{}'.format(soup.find('ns:' + tag).text)

还有一点可能值得一看。

BeautifulSoup并不是真正用于XML的,它非常适合凌乱的HTML,这会破坏一个合适的解析器

您最好使用接口(通过,也许是非常快的),不管怎样,IIRC是BS默认使用的。然后获取根元素并在几行代码中迭代其所有子元素,例如:

#!/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}
#/usr/bin/env python
将xml.etree.ElementTree作为ET导入
进口稀土
#请注意必须/应该存在的虚拟命名空间。。。
xml=“”
阿瓦隆
1998
泰
VIN号在这里
'''
tree=ET.fromstring(xml)
vehicle={re.sub(r'{.*}','',node.tag):树中节点的node.text}

BeautifulSoup并不是真正用于XML的,它是凌乱HTML的理想选择,这会破坏一个合适的解析器

您最好使用接口(通过,也许是非常快的),不管怎样,IIRC是BS默认使用的。然后获取根元素并在几行代码中迭代其所有子元素,例如:

#!/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}
#/usr/bin/env python
将xml.etree.ElementTree作为ET导入
进口稀土
#请注意必须/应该存在的虚拟命名空间。。。
xml=“”
阿瓦隆
1998
泰
VIN号在这里
'''
tree=ET.fromstring(xml)
vehicle={re.sub(r'{.*}','',node.tag):树中节点的node.text}
如果希望所有子节点都位于
元素中,则无需显式指定它们-只需循环所有子元素并将它们放入字典中即可

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
从bs4导入美化组
汤=美汤(“”)
阿瓦隆
1998
泰
VIN号在这里
''')
#如果您有多辆车,请循环
#请注意,BS将所有标记名规范化为小写->我们使用“ns:vehicle”而不是“ns:vehicle”
对于汤中的el_车辆。查找所有('ns:vehicle'):
vehicle={child.name:child.text用于el_vehicle.findChildren()中的子对象
#将'vehicle'粘贴在列表中或进行其他处理
这与您的输出不完全匹配,因为它不会从camelcase转换为下划线分隔名称(例如,
ModelYear
转换为
model\u year
),而且它也不会从元素名称中去掉名称空间。如果需要,在
child.name
周围包含一个包装器来相应地更改名称应该不会太困难。

如果希望
元素中的所有子节点,则不需要显式指定它们-只需循环所有子元素并将它们放入字典中即可

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
从bs4导入美化组
汤=美汤(“”)
阿瓦隆
1998
泰
VIN号在这里
''')
#如果您有多辆车,请循环
#请注意,BS将所有标记名规范化为小写->我们使用“ns:vehicle”而不是“ns:vehicle”
对于汤中的el_车辆。查找所有('ns:vehicle'):
vehicle={child.name:child.text用于el_vehicle.findChildren()中的子对象
#将'vehicle'粘贴在列表中或进行其他处理

这与您的输出不完全匹配,因为它不会从camelcase转换为下划线分隔名称(例如,
ModelYear
转换为
model\u year
),而且它也不会从元素名称中去掉名称空间。如果需要,在
child.name
周围包含一个包装器来相应地更改名称应该不会太困难。

我尝试了xmltodict,而我正在使用的xml是一堆嵌套的OrderedDict。感谢您提供的这个解决方案,它比我的解决方案干净得多。我尝试了xmltodict,而我正在使用的xml是一堆嵌套的OrderedDict。谢谢你的解决方案,比我的要干净得多。