xml.dom.minidom --- Triển khai DOM tối thiểu

Source code: Lib/xml/dom/minidom.py


xml.dom.minidom là một triển khai tối thiểu của giao diện Mô hình đối tượng tài liệu, với API tương tự như trong các ngôn ngữ khác. Nó được thiết kế đơn giản hơn DOM đầy đủ và cũng nhỏ hơn đáng kể. Thay vào đó, những người dùng chưa thành thạo với DOM nên cân nhắc sử dụng mô-đun xml.etree.ElementTree để xử lý XML.

Ghi chú

Nếu bạn cần phân tích dữ liệu không đáng tin cậy hoặc chưa được xác thực, hãy xem bảo mật XML.

Các ứng dụng DOM thường bắt đầu bằng cách phân tích một số XML thành DOM. Với xml.dom.minidom, việc này được thực hiện thông qua các hàm phân tích cú pháp:

từ phân tích  pháp nhập xml.dom.minidom, ParseString

dom1 = parse('c:\\temp\\mydata.xml') # parse một tệp XML theo tên

nguồn dữ liệu = open('c:\\temp\\mydata.xml')
dom2 = phân tích  pháp (nguồn dữ liệu) # parse một tệp đang mở

dom3 = ParseString('<myxml>Một số dữ liệu<empty/> một số dữ liệu khác</myxml>')

Hàm parse() có thể lấy tên tệp hoặc đối tượng tệp đang mở.

xml.dom.minidom.parse(filename_or_file, parser=None, bufsize=None)

Trả về Document từ đầu vào đã cho. filename_or_file có thể là tên tệp hoặc đối tượng giống như tệp. parser, nếu được cung cấp, phải là đối tượng phân tích cú pháp SAX2. Hàm này sẽ thay đổi trình xử lý tài liệu của trình phân tích cú pháp và kích hoạt hỗ trợ không gian tên; cấu hình trình phân tích cú pháp khác (như đặt trình phân giải thực thể) phải được thực hiện trước.

Nếu bạn có XML trong một chuỗi, bạn có thể sử dụng hàm parseString() thay thế:

xml.dom.minidom.parseString(string, parser=None)

Trả về Document đại diện cho string. Phương thức này tạo một đối tượng io.StringIO cho chuỗi và chuyển nó sang parse().

Cả hai hàm đều trả về một đối tượng Document đại diện cho nội dung của tài liệu.

Chức năng của parse()parseString() là kết nối trình phân tích cú pháp XML với "trình tạo DOM" có thể chấp nhận các sự kiện phân tích cú pháp từ bất kỳ trình phân tích cú pháp SAX nào và chuyển đổi chúng thành cây DOM. Tên của các chức năng có thể gây nhầm lẫn nhưng lại dễ nắm bắt khi tìm hiểu các giao diện. Việc phân tích tài liệu sẽ được hoàn thành trước khi các hàm này quay trở lại; đơn giản là các hàm này không cung cấp khả năng triển khai trình phân tích cú pháp.

Bạn cũng có thể tạo Document bằng cách gọi một phương thức trên đối tượng "Triển khai DOM". Bạn có thể lấy đối tượng này bằng cách gọi hàm getDOMImplementation() trong gói xml.dom hoặc mô-đun xml.dom.minidom. Sau khi có Document, bạn có thể thêm các nút con vào đó để điền vào DOM:

từ xml.dom.minidom nhập getDOMImplementation

impl = getDOMImplementation()

newdoc = impl.createDocument(Không , "some_tag", Không )
top_element = newdoc.documentElement
text = newdoc.createTextNode('Một số nội dung văn bản.')
top_element.appendChild(văn bản)

Khi bạn có đối tượng tài liệu DOM, bạn có thể truy cập các phần của tài liệu XML thông qua các thuộc tính và phương thức của nó. Các thuộc tính này được xác định trong đặc tả DOM. Thuộc tính chính của đối tượng tài liệu là thuộc tính documentElement. Nó cung cấp cho bạn thành phần chính trong tài liệu XML: thành phần chứa tất cả những thành phần khác. Đây là một chương trình ví dụ:

dom3 = ParseString("<myxml>Một số dữ liệu</myxml>")
khẳng định dom3.documentElement.tagName == "myxml"

Khi bạn hoàn thành với cây DOM, bạn có thể tùy ý gọi phương thức unlink() để khuyến khích việc dọn dẹp sớm các đối tượng hiện không cần thiết. unlink() là một phần mở rộng dành riêng cho xml.dom.minidom- của DOM API khiến nút và các nút con của nó về cơ bản trở nên vô dụng. Nếu không, trình thu gom rác của Python cuối cùng sẽ xử lý các đối tượng trong cây.

Xem thêm

Document Object Model (DOM) Level 1 Specification

Đề xuất W3C cho DOM được xml.dom.minidom hỗ trợ.

Đối tượng DOM

Định nghĩa về DOM API cho Python được đưa ra như một phần của tài liệu mô-đun xml.dom. Phần này liệt kê những khác biệt giữa API và xml.dom.minidom.

Phá vỡ các tham chiếu nội bộ trong DOM để nó sẽ được thu thập rác trên các phiên bản Python không có GC tuần hoàn. Ngay cả khi có sẵn GC tuần hoàn, việc sử dụng tính năng này có thể cung cấp lượng lớn bộ nhớ sớm hơn, do đó, việc gọi tính năng này trên các đối tượng DOM ngay khi chúng không còn cần thiết là một cách làm tốt. Điều này chỉ cần được gọi trên đối tượng Document, nhưng có thể được gọi trên các nút con để loại bỏ các nút con của nút đó.

Bạn có thể tránh gọi phương thức này một cách rõ ràng bằng cách sử dụng câu lệnh with. Đoạn mã sau sẽ tự động hủy liên kết dom khi thoát khối with

với xml.dom.minidom.parse(datasource)  dom:
    ... # Work với dom.
Node.writexml(writer, indent='', addindent='', newl='', encoding=None, standalone=None)

Viết XML cho đối tượng nhà văn. Người viết nhận được văn bản nhưng không phải byte làm đầu vào, nó phải có phương thức write() khớp với phương thức của giao diện đối tượng tệp. Tham số indent là thụt lề của nút hiện tại. Tham số addindent là mức thụt lề tăng dần để sử dụng cho các nút con của nút hiện tại. Tham số newl chỉ định chuỗi sử dụng để chấm dứt dòng mới.

Đối với nút Document, một đối số từ khóa bổ sung encoding có thể được sử dụng để chỉ định trường mã hóa của tiêu đề XML.

Tương tự, việc nêu rõ đối số standalone sẽ khiến các khai báo tài liệu độc lập được thêm vào phần mở đầu của tài liệu XML. Nếu giá trị được đặt thành True, standalone="yes" sẽ được thêm vào, nếu không thì giá trị được đặt thành "no". Không nêu đối số sẽ bỏ qua phần khai báo khỏi tài liệu.

Thay đổi trong phiên bản 3.8: Phương thức writexml() hiện giữ nguyên thứ tự thuộc tính do người dùng chỉ định.

Thay đổi trong phiên bản 3.9: Tham số standalone đã được thêm vào.

Node.toxml(encoding=None, standalone=None)

Trả về một chuỗi hoặc chuỗi byte chứa XML được đại diện bởi nút DOM.

Với đối số encoding [1] rõ ràng, kết quả là một chuỗi byte trong mã hóa được chỉ định. Không có đối số encoding, kết quả là một chuỗi Unicode và khai báo XML trong chuỗi kết quả không chỉ định mã hóa. Mã hóa chuỗi này bằng mã hóa khác UTF-8 có thể không chính xác vì UTF-8 là mã hóa mặc định của XML.

Đối số standalone hoạt động chính xác như trong writexml().

Thay đổi trong phiên bản 3.8: Phương thức toxml() hiện giữ nguyên thứ tự thuộc tính do người dùng chỉ định.

Thay đổi trong phiên bản 3.9: Tham số standalone đã được thêm vào.

Node.toprettyxml(indent='\t', newl='\n', encoding=None, standalone=None)

Trả lại một phiên bản tài liệu được in đẹp. indent chỉ định chuỗi thụt lề và mặc định là trình lập bảng; newl chỉ định chuỗi phát ra ở cuối mỗi dòng và mặc định là \n.

Đối số encoding hoạt động giống như đối số tương ứng của toxml().

Đối số standalone hoạt động chính xác như trong writexml().

Thay đổi trong phiên bản 3.8: Phương thức toprettyxml() hiện giữ nguyên thứ tự thuộc tính do người dùng chỉ định.

Thay đổi trong phiên bản 3.9: Tham số standalone đã được thêm vào.

DOM Ví dụ

Chương trình ví dụ này là một ví dụ khá thực tế về một chương trình đơn giản. Trong trường hợp cụ thể này, chúng tôi không tận dụng được nhiều lợi thế về tính linh hoạt của DOM.

nhập xml.dom.minidom

tài liệu = """\
<trình chiếu>
<title>Trình chiếu demo</title>
<slide><title>Tiêu đề trang trình bày</title>
<point>Đây là bản demo</point>
<point>Của chương trình xử lý slide</point>
</slide>

<slide><title>Một slide demo khác</title>
<point>Điều quan trọng</point>
<point>Để có nhiều hơn</point>
<point>một slide</point>
</slide>
</trình chiếu>
"""

dom = xml.dom.minidom.parseString(tài liệu)

def getText(danh sách nút):
    rc = []
    cho nút trong danh sách nút:
        nếu node.nodeType == node.TEXT_NODE:
            RC.append(node.data)
    return ''.join(rc)

def xử lýSlideshow(trình chiếu):
    in("<html>")
    handSlideshowTitle(slideshow.getElementsByTagName("title")[0])
    slide = slideshow.getElementsByTagName("slide")
    xử lýToc(slide)
    xử lýSlide(slide)
    in("</html>")

def xử lýSlides(slide):
    cho slide trong slide:
        xử lýSlide(trượt)

def xử lýSlide(trượt):
    handSlideTitle(slide.getElementsByTagName("title")[0])
    handPoints(slide.getElementsByTagName("point"))

def xử lýSlideshowTitle(title):
    print(f"<title>{getText(title.childNodes)</title>")

def xử lýSlideTitle(title):
    print(f"<h2>{getText(title.childNodes)</h2>")

def xử lýPoints(điểm):
    in("<ul>")
    cho điểm trong điểm:
        xử lýPoint(điểm)
    in("</ul>")

def xử lýPoint(điểm):
    print(f"<li>{getText(point.childNodes)</li>")

def handToc(slide):
    cho slide trong slide:
        tiêu đề = slide.getElementsByTagName("title")[0]
        print(f"<p>{getText(title.childNodes)</p>")

xử lýSlideshow(dom)

minidom và tiêu chuẩn DOM

Mô-đun xml.dom.minidom về cơ bản là DOM tương thích với DOM 1.0 với một số tính năng của DOM 2 (chủ yếu là các tính năng không gian tên).

Việc sử dụng giao diện DOM trong Python rất đơn giản. Các quy tắc ánh xạ sau đây được áp dụng:

  • Các giao diện được truy cập thông qua các đối tượng thể hiện. Các ứng dụng không nên tự khởi tạo các lớp; họ nên sử dụng các hàm tạo có sẵn trên đối tượng Document. Giao diện phái sinh hỗ trợ tất cả các hoạt động (và thuộc tính) từ giao diện cơ sở, cộng với mọi hoạt động mới.

  • Hoạt động được sử dụng như phương pháp. Vì DOM chỉ sử dụng tham số in nên các đối số được truyền theo thứ tự bình thường (từ trái sang phải). Không có đối số tùy chọn. Hoạt động void trả về None.

  • Thuộc tính IDL ánh xạ tới các thuộc tính thể hiện. Để tương thích với ánh xạ ngôn ngữ OMG IDL cho Python, thuộc tính foo cũng có thể được truy cập thông qua các phương thức truy cập _get_foo()_set_foo(). Thuộc tính readonly không được thay đổi; điều này không được thực thi trong thời gian chạy.

  • Các loại short int, unsigned int, unsigned long longboolean đều ánh xạ tới các đối tượng số nguyên Python.

  • Loại DOMString ánh xạ tới chuỗi Python. xml.dom.minidom hỗ trợ byte hoặc chuỗi nhưng thường sẽ tạo ra chuỗi. Các giá trị của loại DOMString cũng có thể là None khi được phép có giá trị IDL null theo thông số DOM từ W3C.

  • Khai báo const ánh xạ tới các biến trong phạm vi tương ứng của chúng (ví dụ: xml.dom.minidom.Node.PROCESSING_INSTRUCTION_NODE); chúng không được thay đổi.

  • DOMException hiện không được hỗ trợ trong xml.dom.minidom. Thay vào đó, xml.dom.minidom sử dụng các ngoại lệ Python tiêu chuẩn như TypeErrorAttributeError.

  • Các đối tượng NodeList được triển khai bằng loại danh sách có sẵn của Python. Các đối tượng này cung cấp giao diện được xác định trong đặc tả DOM, nhưng với các phiên bản Python trước đó, chúng không hỗ trợ API chính thức. Tuy nhiên, chúng "Pythonic" hơn nhiều so với giao diện được xác định trong khuyến nghị W3C.

Các giao diện sau không được triển khai trong xml.dom.minidom:

  • DOMTimeStamp

  • EntityReference

Hầu hết những thông tin này phản ánh thông tin trong tài liệu XML không có ích chung cho hầu hết người dùng DOM.

Chú thích cuối trang