2010-08-31 25 views

Trả lời

190

Những ngày này, các lựa chọn phổ biến nhất (và rất đơn giản) là ElementTree API, mà đã được bao gồm trong thư viện chuẩn từ Python 2.5.

Các tùy chọn có sẵn cho điều đó là:

  • ElementTree (Cơ bản, thực hiện thuần Python Phần ElementTree của thư viện tiêu chuẩn kể từ 2.5.)
  • cElementTree (Tối ưu hóa C thực hiện ElementTree Cũng có sẵn bằng tiếng. thư viện tiêu chuẩn từ 2.5)
  • lxml (Dựa trên libxml2. Cung cấp một siêu giàu của API ElementTree cũng XPath, CSS Selectors, và nhiều hơn nữa)

Dưới đây là một ví dụ về làm thế nào để tạo ra tài liệu ví dụ của bạn bằng cách sử dụng cElementTree trong stdlib:

import xml.etree.cElementTree as ET 

root = ET.Element("root") 
doc = ET.SubElement(root, "doc") 

ET.SubElement(doc, "field1", name="blah").text = "some value1" 
ET.SubElement(doc, "field2", name="asdfasd").text = "some vlaue2" 

tree = ET.ElementTree(root) 
tree.write("filename.xml") 

Tôi đã thử nghiệm nó và nó hoạt động, nhưng tôi giả định khoảng trắng là không đáng kể. Nếu bạn cần "thụt đầu dòng", hãy cho tôi biết và tôi sẽ tìm cách để làm điều đó. (. Nó có thể là một lựa chọn lxml cụ thể tôi không sử dụng thực hiện stdlib nhiều)

Để đọc thêm, đây là một số liên kết hữu ích:

Lưu ý cuối cùng, hoặc cElementTree hoặc LXML phải đủ nhanh cho mọi nhu cầu của bạn (cả hai đều là mã C tối ưu), nhưng trong trường hợp bạn đang ở trong một tình huống mà bạn cần phải bóp ra mỗi bit cuối cùng của hiệu suất, các tiêu chuẩn trên trang web lxml chỉ ra rằng:

  • lxml thắng rõ ràng cho serializing (tạo) XML
  • là một dụng phụ hiệu quả của việc triển khai thực hiện truyền tải cha mẹ thích hợp, LXML chậm hơn một chút so với cElementTree để phân tích cú pháp.
+0

Tôi nhận được 'import xml.etree.cElementTree như ET',' ImportError: Không có module nào có tên là etree.cElementTree' - python OSX 10.8 chuẩn, nhưng bằng cách nào đó nó hoạt động khi tôi chạy nó từ bên trong ipython. – guaka

+1

@Kasper: Tôi không có máy Mac nên tôi không thể cố gắng sao chép vấn đề. Cho tôi biết phiên bản Python và tôi sẽ xem liệu tôi có thể sao chép nó trên Linux không. – ssokolow

+0

@ssokolow, tôi đang ở trên OSX 10.9 bây giờ và điều này đã được giải quyết bằng cách nào đó, tôi không nhớ đó có phải là hành động của riêng tôi hay tôi đã làm gì đó để giải quyết nó. – guaka

5

Đối với sự lựa chọn đơn giản nhất, tôi muốn đi với minidom: http://docs.python.org/library/xml.dom.minidom.html. Nó được xây dựng trong thư viện chuẩn python và rất dễ sử dụng trong các trường hợp đơn giản.

Dưới đây là một khá dễ dàng để làm theo hướng dẫn: http://www.boddie.org.uk/python/XML_intro.html

+0

Câu trả lời này nên bao gồm một ví dụ về minidom được sử dụng. –

46

lxml library bao gồm cú pháp rất thuận tiện cho việc tạo XML, được gọi là E-factory.Đây là cách tôi muốn làm ví dụ bạn đưa ra:

#!/usr/bin/python 
import lxml.etree 
import lxml.builder  

E = lxml.builder.ElementMaker() 
ROOT = E.root 
DOC = E.doc 
FIELD1 = E.field1 
FIELD2 = E.field2 

the_doc = ROOT(
     DOC(
      FIELD1('some value1', name='blah'), 
      FIELD2('some value2', name='asdfasd'), 
      ) 
     ) 

print lxml.etree.tostring(the_doc, pretty_print=True) 

Output:

<root> 
    <doc> 
    <field1 name="blah">some value1</field1> 
    <field2 name="asdfasd">some value2</field2> 
    </doc> 
</root> 

Nó cũng hỗ trợ thêm vào một nút đã gây ra, ví dụ sau khi ở trên bạn có thể nói

the_doc.append(FIELD2('another value again', name='hithere')) 
+1

Nếu tên của thẻ không phù hợp với các quy tắc định danh Python, sau đó bạn có thể sử dụng 'getattr', ví dụ,' getattr (E, "some-tag") '. – haridsv

9

Yattag http://www.yattag.org/ hoặc https://github.com/leforestier/yattag cung cấp một API thú vị để tạo ra tài liệu XML như vậy (và cũng tài liệu HTML).

Đang sử dụng context managerwith từ khóa.

from yattag import Doc, indent 

doc, tag, text = Doc().tagtext() 

with tag('root'): 
    with tag('doc'): 
     with tag('field1', name='blah'): 
      text('some value1') 
     with tag('field2', name='asdfasd'): 
      text('some value2') 

result = indent(
    doc.getvalue(), 
    indentation = ' '*4, 
    newline = '\r\n' 
) 

print(result) 

do đó bạn sẽ nhận được:

<root> 
    <doc> 
     <field1 name="blah">some value1</field1> 
     <field2 name="asdfasd">some value2</field2> 
    </doc> 
</root> 
0

Đối với một cấu trúc XML đơn giản như vậy, bạn có thể không muốn liên quan đến một mô-đun XML thổi đầy đủ. Hãy xem xét một chuỗi mẫu cho các cấu trúc đơn giản nhất, hoặc Jinja cho một cái gì đó phức tạp hơn một chút. Jinja có thể xử lý vòng lặp qua danh sách dữ liệu để tạo ra xml bên trong của danh sách tài liệu của bạn. Đó là một chút phức tạp hơn với các mẫu chuỗi python thô

Ví dụ về Jinja, xem answer to a similar question của tôi.

Dưới đây là ví dụ về việc tạo xml của bạn với các mẫu chuỗi.

import string 
from xml.sax.saxutils import escape 

inner_template = string.Template(' <field${id} name="${name}">${value}</field${id}>') 

outer_template = string.Template("""<root> 
<doc> 
${document_list} 
</doc> 
</root> 
""") 

data = [ 
    (1, 'foo', 'The value for the foo document'), 
    (2, 'bar', 'The <value> for the <bar> document'), 
] 

inner_contents = [inner_template.substitute(id=id, name=name, value=escape(value)) for (id, name, value) in data] 
result = outer_template.substitute(document_list='\n'.join(inner_contents)) 
print result 

Output:

<root> 
<doc> 
    <field1 name="foo">The value for the foo document</field1> 
    <field2 name="bar">The &lt;value&gt; for the &lt;bar&gt; document</field2> 
</doc> 
</root> 

Các Downer của mẫu tiếp cận là bạn sẽ không nhận được thoát của <> miễn phí. Tôi đã nhảy múa xung quanh vấn đề đó bằng cách kéo trong một util từ xml.sax

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