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

时间:2015-06-26 19:44:10

标签: python xml 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 />元素?

详细信息:我从 OpenDocument 格式(来自Microsoft Word)存储的content.xml文件中提取了my.odt个文件。我的目标是将其转换为AsciiDoc格式。这意味着识别重要部分,并丢弃其他部分。

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

说,我想实现像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文本加入前一个元素的尾部?或者有更好的方法吗?

1 个答案:

答案 0 :(得分:1)

以下解决方案仅依赖于xml.etree.ElementTree的{​​{3}}。

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))