关闭所有打开的xml标签

5 投票
4 回答
2095 浏览
提问于 2025-04-15 15:30

我有一个文件,它的内容会在短时间内发生变化。不过,我想在它准备好之前就读取它。问题是,这个文件是一个xml文件(日志)。所以当你读取它的时候,可能会出现一些标签没有关闭的情况。

我想知道有没有办法正确地关闭所有打开的标签,这样在浏览器中显示的时候(使用xslt样式表)就不会出现问题。这应该可以通过使用Python自带的功能来实现。

4 个回答

0

你可以使用任何SAX解析器,只要把目前已有的数据提供给它就行。使用一个SAX处理器,它只需要把源XML重新构建出来,保持一个打开的标签堆栈,最后再按照相反的顺序关闭这些标签。

1

如果我理解你的问题没错的话,你有一个日志文件,这个文件会不断地被添加内容,所以你看到的内容大概是这样的:

<root>
<entry> ... </entry>
<entry> ... </entry>
...
<entry> ... </entry
<!-- no closing root -->

在这种情况下,你不应该使用DOM解析器,因为它会试图读取一个完整的文档,而缺少的标签会让它出错。相反,使用SAX或Pull解析器会更合适,因为它像处理数据流一样读取文档,而不是把整个文档当成一棵树来处理。正如Denis上面提到的,你可以选择在最后补上缺失的标签,或者在写出内容之前忽略任何不完整的标签。

维基百科上的XML解析

6

有些XML解析器可以逐步解析XML文档,也就是说,解析器可以在文档还没完全加载的时候就开始工作。Python标准库中的xml.etree.ElementTree模块里的XMLTreeBuilder就是这样的解析器:Element Tree

在下面的例子中,你可以在从输入源读取数据时,逐步将数据提供给解析器。你的处理类中的合适方法会在各种XML“事件”发生时被调用(比如标签开始、标签数据读取、标签结束),这样你就可以在XML文档加载的过程中处理数据:

from xml.etree.ElementTree import XMLTreeBuilder
class MyHandler(object):
    def start(self, tag, attrib):
        # Called for each opening tag.
        print tag + " started"
    def end(self, tag):
        # Called for each closing tag.
        print tag  + " ended"
    def data(self, data):
        # Called when data is read from a tag
        print data  + " data read"
    def close(self):    
        # Called when all data has been parsed.
        print "All data read"

handler = MyHandler()

parser = XMLTreeBuilder(target=handler)

parser.feed(<sometag>)
parser.feed(<sometag-child-tag>text)
parser.feed(</sometag-child-tag>)
parser.feed(</sometag>)
parser.close()

在这个例子中,处理类会接收到五个事件并打印:

sometag 开始

sometag-child 开始

读取到“text”数据

sometag-child 结束

sometag 结束

所有数据已读取

撰写回答