【问题标题】:Preserving XML structure after adding elements using lxml in python在python中使用lxml添加元素后保留XML结构
【发布时间】:2019-09-23 11:33:05
【问题描述】:

首先,我是堆栈溢出的新手,所以请善待并提出建设性的批评意见,如果有空间可以改进这个问题。

问题: 我想保留下面代码创建的 XML 文件的结构。我希望它看起来像这样:

<?xml version="1.0" encoding="UTF-8" ?>
<save>
    <header version="2" />
    <version major="3" minor="6" revision="2" build="0" />
    <region id="ModuleSettings">
        <node id="root">
            <children>
                <node id="ModOrder">
                    <children>
                        <node id="Module">
                            <attribute id="UUID" value="627f624f-e2b8-4b37-977e-03044e500fec" type="22" />
                        </node>
                        <node id="Module">
                            <attribute id="UUID" value="7e737d2f-31d2-4751-963f-be6ccc59cd0c" type="22" />
                        </node>
                    </children>
                </node>
                <node id="Mods">
                    <children>
                        <node id="ModuleShortDesc">
                            <attribute id="Folder" value="somestuff1" type="30" />
                            <attribute id="MD5" value="somestuff1" type="23" />
                            <attribute id="Name" value="somestuff1" type="22" />
                            <attribute id="UUID" value="627f624f-e2b8-4b37-977e-03044e500fec" type="22" />
                            <attribute id="Version" value="1" type="4" />
                        </node>
                        <node id="ModuleShortDesc">
                            <attribute id="Folder" value="somestuff2" type="30" />
                            <attribute id="MD5" value="" type="23" />
                            <attribute id="Name" value="somestuff2" type="22" />
                            <attribute id="UUID" value="7e737d2f-31d2-4751-963f-be6ccc59cd0c" type="22" />
                            <attribute id="Version" value="2" type="4" />
                        </node>
                    </children>
                </node>
            </children>
        </node>
    </region>
</save>

而是得到这个:

<?xml version="1.0" encoding="UTF-8" ?>
<save>
    <header version="2" />
    <version major="3" minor="6" revision="2" build="0" />
    <region id="ModuleSettings">
        <node id="root">
            <children>
                <node id="ModOrder">
                    <children>
                    <node id="Module"><attribute id="UUID" value="627f624f-e2b8-4b37-977e-03044e500fec" type="22" /></node><node id="Module"><attribute id="UUID" value="7e737d2f-31d2-4751-963f-be6ccc59cd0c" type="22" /></node></children>
                </node>
                <node id="Mods">
                    <children>
                    <node id="ModuleShortDesc"><attribute id="Folder" value="somestuff1" type="30" /><attribute id="MD5" value="somestuff1" type="23" /><attribute id="Name" value="somestuff1" type="22" /><attribute id="UUID" value="627f624f-e2b8-4b37-977e-03044e500fec" type="22" /><attribute id="Version" value="1" type="4" /></node><node id="ModuleShortDesc"><attribute id="Folder" value="somestuff2" type="30" /><attribute id="MD5" value="" type="23" /><attribute id="Name" value="somestuff2" type="22" /><attribute id="UUID" value="7e737d2f-31d2-4751-963f-be6ccc59cd0c" type="22" /><attribute id="Version" value="2" type="4" /></node></children></node>
            </children>
        </node>
    </region>
</save>

只关注 ModOrder 节点,这是我当前的代码:

# Create a Module element as object:
def new_module(uuid, ModOrder):

    ''' Example Module:
        <node id="Module">
            <attribute id="UUID" value="627f624f-e2b8-4b37-977e-03044e500fec" type="22" />
        </node>
    '''

    uuid = str(uuid)

    module = et.SubElement(ModOrder, "node")
    module.set("id", "Module")

    attribute_uuid = et.SubElement(module, "attribute")
    attribute_uuid.set("id", "UUID")
    attribute_uuid.set("value", uuid)
    attribute_uuid.set("type", "22")

    return module

def generator2():

    # mods_dictionary returns 2 lists of dictionaries:
    info = mods_dictionary(a1)

    # info[0] contains a list of dictionaries.
    # Each dictionary contains information of each mod pulled from meta.lsx file inside each pak
    data_list = info[0]
    # error_list = info[1] # Not needed

    # ModOrderTree = element tree object @ <node id="Module">
    ModOrderTree = tree.xpath('//node[@id="ModOrder"]')[0]

    # ModOrder = element tree object @ <children>   
    ModOrder = ModOrderTree.find('children')

    # For each dictionary inside data_list
    for mods in data_list:
        order = new_module(mods["UUID"],ModOrder)
        desc = new_moduleshortdesc(mods["Name"], mods["Author"], mods["Version"], mods["UUID"], mods["Folder"])

    # Then write to file:    
    tree.write('testwrite.xml')

generator2()

问题 有没有办法实现我想要的?

请记住,我是编程新手,还在学习中,所以我确信有更多的 Python 方法可以更有效地编写代码。如果我做了任何无聊的事情来打扰你,请随时提出建议:p

尝试过的事情:

    t1 = et.tostring(tree, encoding="unicode",method="xml",pretty_print=True)
    with open(test_file,'w') as f:
        f.write(t1)
tree.write('testwrite.xml', pretty_print=True). 

【问题讨论】:

  • 更具体地说,您想保留换行符和缩进吗?那将是一个关于如何将您的 XML 文档序列化为漂亮格式的问题,对吧?看看你的 XML 工具是否支持 xml:space 属性,但是那里没有任何额外的空间可能会更有效,不是吗?
  • tree.write('testwrite.xml', pretty_print=True) 不幸的是没有工作:( 是的,Miro,所以我要问的技术名称是序列化?谢谢这真的有帮助,我会调查它和 xml :空间。我目前正在使用 lxml。是的,它会更有效,但我想保留它以提高可读性。此功能将添加、删除和修改可能数百个节点的位置。删除该空白使任何错误都不可能出现去看看。
  • 我可以吻你:3

标签: xml python-3.x lxml elementtree


【解决方案1】:

解决方案:(感谢 woodm1979 Python pretty XML printer with lxml

只需从整个文档中删除每一位空白,然后让解析器正确重新格式化它:

def reformat(file):
    generator2()

    parser = et.XMLParser(remove_blank_text=True)
    tree = et.parse(test_file,parser)
    tree.write(test_file, encoding='utf-8',pretty_print=True,xml_declaration=True)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-22
    • 2020-05-29
    • 1970-01-01
    • 2011-11-20
    相关资源
    最近更新 更多