2009-09-29 610 views
24

Tôi thích Python, nhưng tôi không muốn viết 10 dòng chỉ để có được một thuộc tính từ một phần tử. Có lẽ đó chỉ là tôi, nhưng minidom không phải là mini. Mã tôi phải viết để phân tích cú pháp một cái gì đó bằng cách sử dụng nó trông rất giống mã Java.Có bất kỳ trình phân tích cú pháp XML Python nào được thiết kế với con người trong tâm trí không?

Có điều gì đó hơn user-friendly không? Một cái gì đó với các toán tử quá tải, và ánh xạ các phần tử nào đến các đối tượng?

Tôi muốn để có thể truy cập vào đây:


<root> 
<node value="30">text</node> 
</root> 

như một cái gì đó như thế này:


obj = parse(xml_string) 
print obj.node.value 

và không sử dụng getChildren hoặc một số phương pháp khác như thế.

+1

XPath có được tính là thân thiện với người dùng không? http://stackoverflow.com/questions/8692/how-to-use-xpath-in-python – Welbog

+0

Tôi muốn được rất nhiều quan tâm đến một phiên bản Java này! – Federer

Trả lời

22

Bạn nên xem ElementTree. Nó không làm chính xác những gì bạn muốn nhưng nó tốt hơn rất nhiều rồi minidom. Nếu tôi nhớ chính xác, bắt đầu từ python 2.4, nó được bao gồm trong các thư viện chuẩn. Để có thêm tốc độ sử dụng cElementTree. Để biết thêm tốc độ (và nhiều tính năng hơn), bạn có thể sử dụng lxml (kiểm tra API đối tượng cho nhu cầu/cách tiếp cận của bạn).

Tôi nên thêm rằng BeautifulSoup làm một phần những gì bạn muốn. Ngoài ra còn có Amara có cách tiếp cận này.

+3

+1, ElementTree thật tuyệt vời. – Mark

+0

ElementTree thật tuyệt vời. –

+0

Đồng ý, ElementTree cực kỳ dễ sử dụng. Không tuyệt vời như vậy với các không gian tên lạ mắt (chưa) nhưng ngày càng tốt hơn. Tránh minidom khi có thể. –

3

Tôi thực sự đã viết một thư viện thực hiện mọi thứ theo cách bạn tưởng tượng. Thư viện được gọi là "xe" và bạn có thể lấy nó từ: http://home.avvanta.com/~steveha/xe.html

xe có thể nhập XML để cho phép bạn làm việc với dữ liệu theo cách hướng đối tượng. Nó thực sự sử dụng xml.dom.minidom để thực hiện phân tích cú pháp, nhưng sau đó nó đi qua cây kết quả và gói dữ liệu vào các đối tượng xe.

EDIT: OK, tôi đã tiếp tục và triển khai ví dụ của bạn trong xe, vì vậy bạn có thể xem cách hoạt động. Dưới đây là các lớp để triển khai XML bạn đã hiển thị:

import xe 

class Node(xe.TextElement): 
    def __init__(self, text="", value=None): 
     xe.TextElement.__init__(self, "node", text) 
     if value is not None: 
      self.attrs["value"] = value 

class Root(xe.NestElement): 
    def __init__(self): 
     xe.NestElement.__init__(self, "root") 
     self.node = Node() 

Và đây là ví dụ về cách sử dụng ở trên. Tôi đặt XML mẫu của bạn vào một tệp có tên là "example.xml", nhưng bạn cũng có thể đặt nó vào một chuỗi và truyền chuỗi đó.

>>> root = Root() 
>>> print root 
<root/> 
>>> root.import_xml("example.xml") 
<Root object at 0xb7e0c52c> 
>>> print root 
<root> 
    <node value="30">text</node> 
</root> 
>>> print root.node.attrs["value"] 
30 
>>> 

Lưu ý rằng trong ví dụ này, loại "giá trị" sẽ là một chuỗi. Nếu bạn thực sự cần thuộc tính của một kiểu khác, điều đó cũng có thể xảy ra với một chút công việc, nhưng tôi không bận tâm ví dụ này. (Nếu bạn nhìn vào PyFeed, có một lớp cho OPML có thuộc tính không phải là văn bản.)

2

Tôi có cùng một nhu cầu cho trình phân tích xml đơn giản và sau một thời gian dài để kiểm tra các thư viện khác nhau mà tôi tìm thấy xmltramp.

Dựa trên ví dụ xml của bạn:

import xmltramp 

xml_string = """<root> 
<node value="30">text</node> 
</root>""" 

obj = xmltramp.parse(xml_string) 
print obj.node('value')    # 30 
print str(obj.node)     # text 

tôi không tìm thấy bất cứ điều gì hơn người dùng thân thiện.

0

Tôi đã dành một chút thời gian để xem xét các ví dụ được cung cấp ở trên và thông qua các kho được liệt kê trên pip.

Các đơn giản nhất (và hầu hết Pythonic) cách phân tích cú pháp XML mà tôi đã tìm thấy cho đến nay đã được XMLToDict - https://github.com/martinblech/xmltodict

Các ví dụ từ các tài liệu có sẵn tại GitHub trên là sao chép dán dưới đây; Nó làm cho cuộc sống rất đơn giản và dễ dàng cho tôi rất nhiều lần;

>>> doc = xmltodict.parse(""" 
... <mydocument has="an attribute"> 
... <and> 
...  <many>elements</many> 
...  <many>more elements</many> 
... </and> 
... <plus a="complex"> 
...  element as well 
... </plus> 
... </mydocument> 
... """) 
>>> 
>>> doc['mydocument']['@has'] 
u'an attribute' 
>>> doc['mydocument']['and']['many'] 
[u'elements', u'more elements'] 
>>> doc['mydocument']['plus']['@a'] 
u'complex' 
>>> doc['mydocument']['plus']['#text'] 
u'element as well' 

Nó hoạt động thực sự tốt và chỉ cho tôi những gì tôi đang tìm kiếm. Tuy nhiên, nếu bạn đang xem xét các phép biến đổi ngược, thì đó hoàn toàn là một vấn đề hoàn toàn khác.