2009-10-02 22 views
5

我試圖解析*大型文件(> 5GB)的結構化標記數據。數據格式本質上是XML,但沒有明確的根元素。什麼是最有效的方法呢?解析Python中的大型僞XML文件

SAX解析器的問題在於它們需要一個根元素,所以要麼向數據流添加一個僞元素(在Python中是否有相當於Java的SequenceInputStream?)或者我必須切換到一個非SAX符合事件的解析器(是否有sgmllib的繼承者?)

數據的結構非常簡單。元素基本上列表:

<Document> 
    <docid>1</docid> 
    <text>foo</text> 
</Document> 
<Document> 
    <docid>2</docid> 
    <text>bar</text> 
</Document> 

*實際上遍歷

回答

11

http://docs.python.org/library/xml.sax.html

請注意,您可以通過一個 '流' 對象xml.sax.parse。這意味着您可以將任何具有類似文件的方法的對象(如read)傳遞給parse調用...創建您自己的對象,它將首先放置您的虛擬根啓動標記,然後是文件內容,然後是虛擬根目錄結束標籤。我想你只需要實現read方法......但這可能取決於你將使用的sax解析器。

的例子,對我的作品:

import xml.sax 
import xml.sax.handler 

class PseudoStream(object): 
    def read_iterator(self): 
     yield '<foo>' 
     yield '<bar>' 
     for line in open('test.xml'): 
      yield line 
     yield '</bar>' 
     yield '</foo>' 

    def __init__(self): 
     self.ri = self.read_iterator() 

    def read(self, *foo): 
     try: 
      return self.ri.next() 
     except StopIteration: 
      return '' 

class SAXHandler(xml.sax.handler.ContentHandler): 
    def startElement(self, name, attrs): 
     print name, attrs 

d = xml.sax.parse(PseudoStream(), SAXHandler()) 
+0

是'回報 '''真的是正確的事情上'StopIteration'?如果該代碼的客戶端只使用'read()',那麼它會如何注意EOF? – 2009-10-02 11:38:45

+4

python中類流對象的屬性之一是read()調用要麼阻塞並返回至少一個字節,要麼在EOF的情況下返回空字符串。原來的file.read方法就是這樣工作的。 – liori 2009-10-02 11:43:42

+1

您可能希望將其與PullDOM結合使用 - 它將SAX的流式性質與DOM的分層特性相結合。 – RichieHindle 2009-10-02 11:52:29

1

的快速和骯髒的答案是增加一個根元素(如字符串),因此這將是一個有效的XML。

問候。

1

添加根元素,並使用SAX,STAX或VTD-XML ..

+0

張先生 - 很好的回答。我已經提高了它。 – 2009-10-03 17:14:18

+0

我將這個元帳戶與這個聯繫起來了,你承諾的100分在哪裏? – 2009-10-03 19:29:41

0

xml.parsers.expat - 使用外籍 的xml.parsers.expat模塊快速XML解析是Python接口外籍非驗證XML解析器。該模塊提供了一種擴展類型xmlparser,它表示XML解析器的當前狀態。在創建xmlparser對象後,可以將對象的各種屬性設置爲處理函數。然後,當XML文檔被提供給解析器時,處理函數被調用用於XML文檔中的字符數據和標記。

更多信息:http://www.python.org/doc/2.5/lib/module-xml.parsers.expat.html