在python中将数组dict转换为xml?

use*_*139 8 python xml arrays

我有这个数组,我需要转换为xml.

array = [
    {
        'time': {"hour":"1", "minute":"30","seconds": "40"}
    },
    {
        'place': {"street":"40 something", "zip": "00000"}
    }
]
Run Code Online (Sandbox Code Playgroud)

xml应该有一个我可以作为变量输入的标题,例如,

xml_title = "test"
Run Code Online (Sandbox Code Playgroud)

基于上面的数组我想要的结果和xml标题是这样的:

<test>
    <time hour="1" minute="30" second="40"></time>
    <place>
        <street>40 something</street>
        <zip>00000</zip>
    </place>
</test>
Run Code Online (Sandbox Code Playgroud)

我喜欢在类似的堆栈溢出问题(/sf/answers/1329388441/)中给出的答案,但我很困惑如何使用该答案来获得所需的结果.

请帮忙.

Jar*_*uen 16

如评论中所述,您的原始问题会混合属性和元素.如果您想将所有内容都作为元素,那么您可以使用它dicttoxml.例如:

from dicttoxml import dicttoxml

array = [
    {
        'time': {"hour":"1", "minute":"30","seconds": "40"}
    },
    {
        'place': {"street":"40 something", "zip": "00000"}
    }
]

xml = dicttoxml(array, custom_root='test', attr_type=False)
Run Code Online (Sandbox Code Playgroud)

生成以下XML:

<?xml version="1.0" encoding="UTF-8" ?>
<test>
    <item>
        <time>
            <seconds>40</seconds>
            <minute>30</minute>
            <hour>1</hour>
        </time>
    </item>
    <item>
        <place>
            <street>40 something</street>
            <zip>00000</zip>
        </place>
    </item>
</test>
Run Code Online (Sandbox Code Playgroud)

如果您可以将字典转换为:

dictionary = {
    'time': {"hour":"1", "minute":"30","seconds": "40"},
    'place': {"street":"40 something", "zip": "00000"}
}
Run Code Online (Sandbox Code Playgroud)

然后您的XML将按预期显示.

<?xml version="1.0" encoding="UTF-8" ?>
<test>
    <place>
        <street>40 something</street>
        <zip>00000</zip>
    </place>
    <time>
        <seconds>40</seconds>
        <minute>30</minute>
        <hour>1</hour>
    </time>
</test>
Run Code Online (Sandbox Code Playgroud)

请注意,通常,字典键的顺序不能保证,因此如果要保留a中键的顺序dict,可能需要签出collections.OrderedDict.

  • 尽管这个 `dicttoxml` 东西似乎仍然有效,但自 **2016 年 7 月 8 日**以来,它就没有在 pypi / github 上更新。这个项目似乎已经死了,我不太确定人们是否应该仍然使用它。 (2认同)

Jos*_*ush 8

对于简单的情况,你可以这样做:

def object_to_xml(data: Union[dict, bool], root='object'):
    xml = f'<{root}>'
    if isinstance(data, dict):
        for key, value in data.items():
            xml += object_to_xml(value, key)

    elif isinstance(data, (list, tuple, set)):
        for item in data:
            xml += object_to_xml(item, 'item')

    else:
        xml += str(data)

    xml += f'</{root}>'
    return xml
Run Code Online (Sandbox Code Playgroud)

例子:

xml = object_to_xml([1, 2, 3], 'root')
# <root><item>1</item><item>2</item><item>3</item></root>
Run Code Online (Sandbox Code Playgroud)
xml = object_to_xml({"name": "the matrix", "age": 20, "metadata": {"dateWatched": datetime.datetime.now()}}, 'movie')
# <movie><name>the matrix</name><age>20</age><metadata><dateWatched>2020-11-01 00:35:39.020358</dateWatched></metadata></movie>
Run Code Online (Sandbox Code Playgroud)


cri*_*007 1

我最终从这里获取了解决方案,然后在数组中的元素上添加了一个 for 循环。不过,输出使用属性而不是像您所要求的元素。

该函数之外的完整代码是这样的。我最终使用正则表达式去掉中间<test></test>标签,然后将其放在最后的外面。

import re 

array = [
    {
        'time': {"hour":"1", "minute":"30","seconds": "40"}
    },
    {
        'place': {"street":"40 something", "zip": "00000"}
    }
]

xml_title = "test"
xml_tag_pattern = re.compile(r'</?{}>'.format(xml_title))
inner_xml = re.sub(xml_tag_pattern, '', ''.join(dict2xml(e, root_node=tag_name) for e in array))

print('<{0}>{1}</{0}>'.format(xml_title, inner_xml))
Run Code Online (Sandbox Code Playgroud)

输出是这样的(为了清晰起见添加了新行)

<test>
    <time hour="1" seconds="40" minute="30"/>
    <place street="40 something" zip="00000"/>
</test>
Run Code Online (Sandbox Code Playgroud)