Chuyển đổi Python ElementTree thành chuỗi


84

Bất cứ khi nào tôi gọi ElementTree.tostring(e), tôi nhận được thông báo lỗi sau:

AttributeError: 'Element' object has no attribute 'getroot'

Có cách nào khác để chuyển đổi một đối tượng ElementTree thành một chuỗi XML không?

Tìm lại:

Traceback (most recent call last):
  File "Development/Python/REObjectSort/REObjectResolver.py", line 145, in <module>
    cm = integrateDataWithCsv(cm, csvm)
  File "Development/Python/REObjectSort/REObjectResolver.py", line 137, in integrateDataWithCsv
    xmlstr = ElementTree.tostring(et.getroot(),encoding='utf8',method='xml')
AttributeError: 'Element' object has no attribute 'getroot'

Câu trả lời:


106

Elementđối tượng không có .getroot()phương pháp. Bỏ cuộc gọi đó và .tostring()cuộc gọi hoạt động:

xmlstr = ElementTree.tostring(et, encoding='utf8', method='xml')

6
Đối với những người đến muộn từ công cụ tìm kiếm: khi mã hóa là 'utf8', nó sẽ thêm vào <?xml version='1.0' encoding='utf8'?>tiêu đề. Khi nó utf-8không có tiêu đề. Ngoài ra, nếu etlà một ElementTree, bạn phải vượt qua et.getroot().
Kenji Noguchi

23
Trong Python 3, encoding='utf8'trả về một bytestring thay vì một chuỗi. Tôi khuyên bạn nên sử dụng tostring(xml, encoding="unicode")thay thế .
Stevoisiak

1
@StevenVascellaro: XML thực sự là một định dạng nhị phân , trong đó định dạng dữ liệu bao gồm các byte trong một mã hóa nhất định (được chỉ định trong khai báo XML ở trên cùng, mặc định là UTF-8 nếu thiếu). Trong Python 2, strlà cùng một loại đối tượng với bytesPython 3. Việc xuất byte là hoàn toàn chính xác, việc sử dụng unicodelàm đầu ra về cơ bản là một phép bổ sung cho phép bạn tránh phải giải mã nếu bạn cần một chuỗi Unicode thay thế cho trường hợp sử dụng cụ thể của mình.
Martijn Pieters

Theo help, only encoding="unicode"sẽ trả về một chuỗi.
cz

45

Làm cách nào để chuyển đổi ElementTree.Elementsang Chuỗi?

Đối với Python 3:

xml_str = ElementTree.tostring(xml, encoding='unicode')

Đối với Python 2:

xml_str = ElementTree.tostring(xml, encoding='utf-8')

Để tương thích với cả Python 2 & 3:

xml_str = ElementTree.tostring(xml).decode()

Ví dụ sử dụng

from xml.etree import ElementTree

xml = ElementTree.Element("Person", Name="John")
xml_str = ElementTree.tostring(xml).decode()
print(xml_str)

Đầu ra:

<Person Name="John" />

Giải trình

Bất chấp tên của nó, ElementTree.tostring()trả về một bytestring theo mặc định trong Python 2 & 3. Đây là một vấn đề trong Python 3, sử dụng Unicode cho chuỗi .

Trong Python 2, bạn có thể sử dụng strkiểu cho cả dữ liệu văn bản và dữ liệu nhị phân . Thật không may, sự kết hợp của hai khái niệm khác nhau này có thể dẫn đến mã giòn, đôi khi hoạt động với một trong hai loại dữ liệu, đôi khi không. [...]

Để phân biệt giữa dữ liệu văn bản và dữ liệu nhị phân rõ ràng và rõ ràng hơn, [Python 3] đã tạo các kiểu dữ liệu văn bản và dữ liệu nhị phân riêng biệt không thể trộn lẫn với nhau một cách mù quáng .

Nguồn: Chuyển mã Python 2 sang Python 3

Nếu chúng ta biết phiên bản Python nào đang được sử dụng, chúng ta có thể chỉ định mã hóa là unicodehoặc utf-8. Mặt khác, nếu chúng ta cần khả năng tương thích với cả Python 2 & 3, chúng ta có thể sử dụngdecode() để chuyển đổi thành loại chính xác.

Để tham khảo, tôi đã đưa vào so sánh .tostring()kết quả giữa Python 2 và Python 3.

ElementTree.tostring(xml)
# Python 3: b'<Person Name="John" />'
# Python 2: <Person Name="John" />

ElementTree.tostring(xml, encoding='unicode')
# Python 3: <Person Name="John" />
# Python 2: LookupError: unknown encoding: unicode

ElementTree.tostring(xml, encoding='utf-8')
# Python 3: b'<Person Name="John" />'
# Python 2: <Person Name="John" />

ElementTree.tostring(xml).decode()
# Python 3: <Person Name="John" />
# Python 2: <Person Name="John" />

Cảm ơn Martijn Peters đã chỉ ra rằng strkiểu dữ liệu đã thay đổi giữa Python 2 và 3.


Tại sao không sử dụng str ()?

Trong hầu hết các tình huống, sử dụng str()sẽ là cách " chuẩn tắc " để chuyển đổi một đối tượng thành một chuỗi. Thật không may, việc sử dụng điều này với Elementtrả về vị trí của đối tượng trong bộ nhớ dưới dạng chuỗi lục phân, chứ không phải là biểu diễn chuỗi dữ liệu của đối tượng.

from xml.etree import ElementTree

xml = ElementTree.Element("Person", Name="John")
print(str(xml))  # <Element 'Person' at 0x00497A80>

1
Trong Python 2 ElementTree.tostring()cũng tạo ra một bytestring. Các strloại là một bytestring bằng Python 2 (Python 3 của strloại được gọi unicodebằng Python 2).
Martijn Pieters

1
Tính năng đó chỉ được thêm vào phiên bản Python 3 và không được hỗ trợ lại cho Python 2. Nếu có, bạn sẽ lấy lại được một unicodechuỗi.
Martijn Pieters

0

Phần mở rộng câu trả lời không phải tiếng Latinh

Mở rộng cho câu trả lời của @ Stevoisiak và xử lý các ký tự không phải Latinh. Chỉ có một cách sẽ hiển thị các ký tự không phải Latinh cho bạn. Một phương pháp khác nhau trên cả Python 3 và Python 2.

Đầu vào

xml = ElementTree.fromstring('<Person Name="크리스" />')
xml = ElementTree.Element("Person", Name="크리스")  # Read Note about Python 2

LƯU Ý: Trong Python 2, khi gọi toString(...)mã, việc gán xmlvới ElementTree.Element("Person", Name="크리스")sẽ gây ra lỗi ...

UnicodeDecodeError: 'ascii' codec can't decode byte 0xed in position 0: ordinal not in range(128)

Đầu ra

ElementTree.tostring(xml)
# Python 3 (크리스): b'<Person Name="&#53356;&#47532;&#49828;" />'
# Python 3 (John): b'<Person Name="John" />'

# Python 2 (크리스): <Person Name="&#53356;&#47532;&#49828;" />
# Python 2 (John): <Person Name="John" />


ElementTree.tostring(xml, encoding='unicode')
# Python 3 (크리스): <Person Name="크리스" />             <-------- Python 3
# Python 3 (John): <Person Name="John" />

# Python 2 (크리스): LookupError: unknown encoding: unicode
# Python 2 (John): LookupError: unknown encoding: unicode

ElementTree.tostring(xml, encoding='utf-8')
# Python 3 (크리스): b'<Person Name="\xed\x81\xac\xeb\xa6\xac\xec\x8a\xa4" />'
# Python 3 (John): b'<Person Name="John" />'

# Python 2 (크리스): <Person Name="크리스" />             <-------- Python 2
# Python 2 (John): <Person Name="John" />

ElementTree.tostring(xml).decode()
# Python 3 (크리스): <Person Name="&#53356;&#47532;&#49828;" />
# Python 3 (John): <Person Name="John" />

# Python 2 (크리스): <Person Name="&#53356;&#47532;&#49828;" />
# Python 2 (John): <Person Name="John" />

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.