如何从 ElementTree 中删除 <text:soft-page-break /> 元素?

How to remove the <text:soft-page-break /> element from the ElementTree?

摘要: 具有以下 ElementTree 元素形式的片段...

<text:p>Text of the paragraph, <text:span>wrapped text</text:span>
continuing <text:soft-page-break />and more of the text.</text:p>

如何从结构中有效删除 <text:soft-page-break /> 元素?

详细信息: 我从 my.odt 文件中提取了 content.xml 文件,以 OpenDocument 格式存储(来自 Microsoft Word)。我的目标是将其转换为 AsciiDoc 格式。意思是认清重要的部分,把其他的部分丢掉。

我正在使用 xml.etree.ElementTree 将 XML 文件解析到内存中。由于文档没有很好的内部标记(您知道用户如何使用所见即所得工具),因此转换是针对特定文档(一本书)量身定制的。

说,我想实现remove_empty_elements(root, 'text:soft-page-break', namespaces)这样的功能。我知道 element.remove(subelement) 可以从父元素中删除子元素。以下实现不正确:

def remove_empty_elements(root, tag, namespaces):
    lst = []
    for parent in root.iterfind('.//' + tag + '/..', namespaces):
        e = parent.find('./' + tag, namespaces)
        if e.text is None:
            lst.append((parent, e))

    for parent, e in lst:
        parent.remove(e)

不正确,因为 and more of the text. 部分属于被删除的元素(如 e.tail),文本将与元素一起被删除。

如何将 e.tail 文本连接到前一个元素的尾部?或者有什么更好的方法吗?

这里是一个只依赖于xml.etree.ElementTreedocumented API的解决方案。

import xml.etree.ElementTree as ET

sample = '''
<doc xmlns:text="http://example.com/">
    <text:p>Text of the paragraph, <text:span>wrapped text</text:span>
    continuing <text:soft-page-break />and more of the text.</text:p>
</doc>
'''

class MyTreeBuilder(ET.TreeBuilder):

    def start(self, tag, attrib):
        if not tag.endswith('soft-page-break'):
            return super(MyTreeBuilder, self).start(tag, attrib)

    def end(self, tag):
        if not tag.endswith('soft-page-break'):
            return super(MyTreeBuilder, self).end(tag)

def my_fromstring(data):
    parser = ET.XMLParser(target=MyTreeBuilder())
    parser.feed(data)
    return parser.close()

print ET.tostring(my_fromstring(sample))