【问题标题】:Python: Tag mismatch while copying nodes in xml using lxmlPython:使用lxml在xml中复制节点时标记不匹配
【发布时间】:2020-06-17 09:04:00
【问题描述】:

我是 xml 新手,正在尝试复制一个节点。虽然它复制了节点,但当我附加它时,结束标签不匹配。这是我正在解析的 xml。

<doc>
    <branch name="release01" hash="f200013e">
        <sub-branch name="subrelease01">
            xml,sgml
        </sub-branch>
    </branch>
</doc>

这是我用来解析 xml 的代码:

import lxml.etree as ET
import copy

tree = ET.ElementTree(file="doc2.xml")
root = tree.getroot()

lst_nodes = tree.findall("branch")
ele = 0

while ele < len(lst_nodes):
    ref = lst_nodes[ele]
    if (lst_nodes[ele].attrib.get("name") == "release01"):
        count = 0
        while count < 1:
            copied = copy.deepcopy(ref)
            ref.append(copied)
            count=count+1
    ele+=1

ET.dump(root)

观察到的输出是:

<doc>
    <branch name="release01" hash="f200013e">
        <sub-branch name="subrelease01">
            xml,sgml
        </sub-branch>
    <branch name="release01" hash="f200013e">
        <sub-branch name="subrelease01">
            xml,sgml
        </sub-branch>
    </branch>
</branch>
</doc>

如您所见,“分支”的结束标记不匹配。有人可以帮我找出我在复制或附加节点时犯的错误吗?

【问题讨论】:

    标签: python xml lxml python-3.7


    【解决方案1】:

    我相信你试图产生的输出是:

    <doc>
        <branch name="release01" hash="f200013e">
            <sub-branch name="subrelease01">
                xml,sgml
            </sub-branch>
        </branch>
        <branch name="release01" hash="f200013e">
            <sub-branch name="subrelease01">
                xml,sgml
            </sub-branch>
        </branch>
    </doc>
    

    您犯的错误是您将ref 的副本附加到构成ref 本身的元素中,而不是将您的副本放在 ref 之后(即您想要副本是ref 的兄弟而不是孩子)。要实现所需的行为,您需要将 ref 的副本附加到 ref 的父元素,这可以通过使用 getparent() 方法然后使用 append() 来实现,或者更方便的是,您可以直接使用 Element 的 addnext()方法。

    即将ref.append(copy) 替换为ref.addnext(copy)

    addnext API Reference

    【讨论】:

    • 感谢您的回答。有效。但是在第一个分支的结束标记之后,新的兄弟姐妹在同一行而不是新行开始。 Pretty_print 没有解决问题。任何解决方案。
    • 这很奇怪,根据 API 参考,dump 似乎仅用于调试目的。打印 tostring() 方法的结果时是否会出现同样的问题? (使用 pretty_print=True)以及将 tostring() 写入文件时?
    • 是的。我尝试使用 tostring() 方法写入文件。结果是一样的。不需要在新兄弟的开头添加新行。
    • 基于此答案stackoverflow.com/a/9612463/5910149,使用删除空格的解析器实例化您的树对象。 parser = ET.XMLParser(remove_blank_text=True) 树 = ET.ElementTree(file="doc2.xml", parser=parser)
    • 在 lxml 文档中给出了这种行为的解释:lxml.de/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-13
    相关资源
    最近更新 更多