我在Python xmltodoct.parse函数中看到了一些IMHO不一致的行为。
- 当一个数组只有1个元素时,它会返回一个带有子元素的迭代器
- 当一个数组有多个元素时,它会返回一个迭代器,其中包含OrderedDict中的元素
请参阅下面的示例:
import xmltodict
if __name__ == "__main__":
xml01 = """
<A>
<C>
<D>DDDD</D>
<E>EEEE</E>
</C>
</A>
"""
xd = xmltodict.parse(xml01)
print(xd)
for x in xd['A']['C']:
print(f"xml01: {x}")
xml02 = """
<A>
<C>
<D>DDDD</D>
<E>EEEE</E>
</C>
<C>
<D>DDDD</D>
<E>EEEE</E>
</C>
</A>
"""
xd = xmltodict.parse(xml02)
for x in xd['A']['C']:
print(f"xml02: {x}")
输出为:
xml01: D
xml01: E
xml02: OrderedDict([('D', 'DDDD'), ('E', 'EEEE')])
xml02: OrderedDict([('D', 'DDDD'), ('E', 'EEEE')])
我希望第一个迭代器的输出是:
xml01: OrderedDict([('D', 'DDDD'), ('E', 'EEEE')])
现在,您需要对迭代器的返回值进行一些类型检查,以确定是否有一个或多个元素。有了更多的元素,你需要做一个新的循环。
我很好奇Python专家对此有何看法,以及他们的解决方案是什么
你说得对。
如果你问我的意见,那么我认为应该改变,让xml01
返回一个有一个孩子的列表。
尽管根据https://github.com/martinblech/xmltodict/issues/14,开发人员已经意识到了这一点,但不会修复它
公认的解决方法是将force_list
作为参数添加到解析中,从而强制为子元素创建一个OrderedDict
列表。
在你的情况下,这看起来像这样:
import xmltodict
if __name__ == "__main__":
xml01 = """
<A>
<C>
<D>DDDD</D>
<E>EEEE</E>
</C>
</A>
"""
xd = xmltodict.parse(xml01, force_list=set('C'))
for x in xd['A']['C']:
print(f"xml01: {x}")
xml02 = """
<A>
<C>
<D>DDDD</D>
<E>EEEE</E>
</C>
<C>
<D>DDDD</D>
<E>EEEE</E>
</C>
</A>
"""
xd = xmltodict.parse(xml02, force_list=set('C'))
for x in xd['A']['C']:
print(f"xml02: {x}")´
还有一种建议是覆盖dict_constructor
以使用defaultdict
。
但如果你想这样做的话,你可以浏览这个问题。