Python xmltodict 在 XML 数组中显示不一致的行为
Python xmltodict shows inconsistent behaviour in XML arrays
恕我直言,我在 Python xmltodoct.parse 函数中看到了一些不一致的行为。
- 当一个数组只有 1 个元素时,它 returns 一个带有子元素的迭代器
- 当一个数组有超过 1 个元素时,它 returns 一个包含 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
return 一个包含 child.
的列表
虽然根据 https://github.com/martinblech/xmltodict/issues/14,开发人员知道这一点但不会修复它。
可接受的解决方法是将 force_list
作为参数添加到解析中,从而强制 child 元素的列表为 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}")´
也有人提议用defaultdict
覆盖dict_constructor
。
但是如果您愿意的话,您可以浏览这个问题。
恕我直言,我在 Python xmltodoct.parse 函数中看到了一些不一致的行为。
- 当一个数组只有 1 个元素时,它 returns 一个带有子元素的迭代器
- 当一个数组有超过 1 个元素时,它 returns 一个包含 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
return 一个包含 child.
虽然根据 https://github.com/martinblech/xmltodict/issues/14,开发人员知道这一点但不会修复它。
可接受的解决方法是将 force_list
作为参数添加到解析中,从而强制 child 元素的列表为 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}")´
也有人提议用defaultdict
覆盖dict_constructor
。
但是如果您愿意的话,您可以浏览这个问题。