2009-10-02 41 views
5

Tôi đang cố gắng phân tích cú pháp * một tệp lớn (> 5 GB) dữ liệu đánh dấu có cấu trúc. Định dạng dữ liệu về cơ bản là XML nhưng không có phần tử gốc rõ ràng. Cách hiệu quả nhất để làm điều đó là gì?Phân tích cú pháp các tệp giả xml lớn trong python

Vấn đề với trình phân tích cú pháp SAX là chúng yêu cầu phần tử gốc, vì vậy tôi phải thêm phần tử giả vào luồng dữ liệu (có tương đương với chuỗi SequenceInputStream của Java trong Python không?) Hoặc tôi đã chuyển sang một trình phân tích cú pháp dựa trên sự kiện không tuân thủ SAX (có sự kế thừa của sgmllib không?)

Cấu trúc của dữ liệu khá đơn giản. Về cơ bản một danh sách các yếu tố:

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

* thực sự để lặp

Trả lời

11

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

Lưu ý, bạn có thể vượt qua một đối tượng 'dòng' để xml.sax.parse. Điều này có nghĩa là bạn có thể truyền bất kỳ đối tượng nào có các phương thức giống như tệp (như read) đến cuộc gọi parse ... Tạo đối tượng của riêng bạn, trước tiên sẽ đặt thẻ bắt đầu ảo gốc của bạn, sau đó nội dung của tệp, sau đó là root ảo thẻ kết thúc. Tôi đoán rằng bạn chỉ cần thực hiện phương pháp read ... nhưng điều này có thể phụ thuộc vào trình phân tích cú pháp sax bạn sẽ sử dụng.

Ví dụ làm việc cho tôi:

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

Có phải 'return ''' thực sự là điều đúng đắn để thực hiện trên 'StopIteration'? Làm thế nào một khách hàng của mã đó sẽ nhận thấy EOF nếu nó chỉ sử dụng 'read()' sau đó? –

+4

Một trong các thuộc tính của các đối tượng giống như dòng trong python là một cuộc gọi read() hoặc là các khối và trả về ít nhất một byte, hoặc trong trường hợp EOF, trả về chuỗi rỗng. Đó là cách phương thức file.read gốc hoạt động. – liori

+1

Bạn có thể muốn sử dụng điều này cùng với PullDOM - nó kết hợp tính chất phát trực tiếp của SAX với bản chất phân cấp của DOM. – RichieHindle

1

Câu trả lời nhanh chóng và bẩn sẽ được bổ sung thêm một phần tử gốc (như String) để nó sẽ là một XML hợp lệ.

Trân trọng.

1

yếu tố Add gốc và sử dụng SAX, Stax hoặc VTD-XML ..

+0

Ông Zhang - câu trả lời hay. Tôi đã upvoted nó. –

+0

Tôi đã liên kết tài khoản meta với tài khoản này, 100 điểm mà bạn đã hứa ở đâu? –

0

xml.parsers.expat - Nhanh chóng phân tích cú pháp XML sử dụng Expat Module xml.parsers.expat là một giao diện Python để phi Expat -giảm giá trị phân tích cú pháp XML. Mô-đun này cung cấp một loại mở rộng duy nhất, xmlparser, đại diện cho trạng thái hiện tại của một trình phân tích cú pháp XML. Sau khi một đối tượng xmlparser đã được tạo, các thuộc tính khác nhau của đối tượng có thể được đặt thành các hàm xử lý. Khi một tài liệu XML sau đó được cung cấp cho trình phân tích cú pháp, các hàm xử lý được gọi cho dữ liệu ký tự và đánh dấu trong tài liệu XML.

Thông tin khác: http://www.python.org/doc/2.5/lib/module-xml.parsers.expat.html

Các vấn đề liên quan