在Python中是否有一个快速的XML解析器允许我在流中将标记的开头作为字节偏移量?

时间:2010-07-06 15:58:54

标签: python xml parsing indexing sax

我正在使用包含来自我的项目的复杂跟踪信息的潜在巨大XML文件。

我想为这些XML文件构建索引,以便人们可以快速找到XML文档的子部分,而无需将其全部加载到内存中。

如果我创建了一个“搁置”索引,其中可能包含“作者乔书籍”等信息的偏移[22322,35446,54545]那么我可以像普通文本文件一样打开xml文件并寻找那些偏移,然后将其与一个带有文件或字符串的DOM解析器。

我还没想到的部分是如何快速解析XML并创建这样的索引。

所以我需要一个快速的SAX解析器,它允许我在文件中找到标签的起始偏移量以及起始事件。因此,我可以将XML的一个子部分与文档的起点一起解析,提取关键信息并将关键字和偏移量存储在搁置索引中。

1 个答案:

答案 0 :(得分:3)

由于定位器返回行号和列号代替偏移量,因此需要一点包裹来跟踪行尾 - 一个简化示例(可能有一些offbyones; - )...:

import cStringIO
import re
from xml import sax
from xml.sax import handler

relinend = re.compile(r'\n')

txt = '''<foo>
            <tit>Bar</tit>
        <baz>whatever</baz>
     </foo>'''
stm = cStringIO.StringIO(txt)

class LocatingWrapper(object):
    def __init__(self, f):
        self.f = f
        self.linelocs = []
        self.curoffs = 0

    def read(self, *a):
        data = self.f.read(*a)
        linends = (m.start() for m in relinend.finditer(data))
        self.linelocs.extend(x + self.curoffs for x in linends)
        self.curoffs += len(data)
        return data

    def where(self, loc):
        return self.linelocs[loc.getLineNumber() - 1] + loc.getColumnNumber()

locstm = LocatingWrapper(stm)

class Handler(handler.ContentHandler):
    def setDocumentLocator(self, loc):
        self.loc = loc
    def startElement(self, name, attrs):
        print '%s@%s:%s (%s)' % (name, 
                                 self.loc.getLineNumber(),
                                 self.loc.getColumnNumber(),
                                 locstm.where(self.loc))

sax.parse(locstm, Handler())

当然你不需要保留所有的线条 - 为了节省内存,你可以删除“旧的”(低于最新查询的那个),但是你需要将linelocs作为dict等等。 / p>