我有看起来像的XML数据:

<xml>
The captial of <place pid="1">South Africa</place> is <place>Pretoria</place>.
</xml>

我希望能够提取:
  • 当前在etree中提供的XML元素。
  • 文档的纯文本,在开始和结束标记之间。
  • 每个起始元素的纯文本位置,以字符偏移量表示。

  • (3)是目前最重要的要求; etree提供(1)罚款。

    我看不到任何直接执行(3)的方法,但是希望对文档树中的元素进行迭代将返回许多可以重新组合的小字符串,从而提供(2)和(3)。但是,请求根节点的.text仅返回根节点和第一个元素之间的文本,例如“的首都 ”。

    使用SAX进行(1)可能涉及实现许多已经被多次编写的内容,例如极简主义和etree。对于要插入此代码的软件包,不能选择使用lxml。有人可以帮忙吗?

    最佳答案

    iterparse()函数可在xml.etree中使用:

    import xml.etree.cElementTree as etree
    
    for event, elem in etree.iterparse(file, events=('start', 'end')):
        if event == 'start':
           print(elem.tag) # use only tag name and attributes here
        elif event == 'end':
           # elem children elements, elem.text, elem.tail are available
           if elem.text is not None and elem.tail is not None:
              print(repr(elem.tail))
    

    另一个选择是重写start()data()end()etree.TreeBuilder()方法:
    from xml.etree.ElementTree import XMLParser, TreeBuilder
    
    class MyTreeBuilder(TreeBuilder):
    
        def start(self, tag, attrs):
            print("&lt;%s>" % tag)
            return TreeBuilder.start(self, tag, attrs)
    
        def data(self, data):
            print(repr(data))
            TreeBuilder.data(self, data)
    
        def end(self, tag):
            return TreeBuilder.end(self, tag)
    
    text = """<xml>
    The captial of <place pid="1">South Africa</place> is <place>Pretoria</place>.
    </xml>"""
    
    # ElementTree.fromstring()
    parser = XMLParser(target=MyTreeBuilder())
    parser.feed(text)
    root = parser.close() # return an ordinary Element
    

    输出
    <xml>
    '\nThe captial of '
    <place>
    'South Africa'
    ' is '
    <place>
    'Pretoria'
    '.\n'
    

    10-08 07:52