2014-09-20 21 views
5

Tôi lấy một tài liệu XML theo cách này:Kiểm tra xem phần tử có trẻ em hay không

import xml.etree.ElementTree as ET 

root = ET.parse(urllib2.urlopen(url)) 
for child in root.findall("item"): 
    a1 = child[0].text # ok 
    a2 = child[1].text # ok 
    a3 = child[2].text # ok 
    a4 = child[3].text # BOOM 
    # ... 

XML trông như thế này:

<item> 
    <a1>value1</a1> 
    <a2>value2</a2> 
    <a3>value3</a3> 
    <a4> 
    <a11>value222</a11> 
    <a22>value22</a22> 
    </a4> 
</item> 

Làm thế nào để kiểm tra xem a4 (trong trường hợp đặc biệt này, nhưng nó có thể là bất kỳ yếu tố nào khác) có con không?

Trả lời

6

Bạn có thể thử các list chức năng trên các yếu tố:

>>> xml = """<item> 
    <a1>value1</a1> 
    <a2>value2</a2> 
    <a3>value3</a3> 
    <a4> 
    <a11>value222</a11> 
    <a22>value22</a22> 
    </a4> 
</item>""" 
>>> root = ET.fromstring(xml) 
>>> list(root[0]) 
[] 
>>> list(root[3]) 
[<Element 'a11' at 0x2321e10>, <Element 'a22' at 0x2321e48>] 
>>> len(list(root[3])) 
2 
>>> print "has children" if len(list(root[3])) else "no child" 
has children 
>>> print "has children" if len(list(root[2])) else "no child" 
no child 
>>> # Or simpler, without a call to list within len, it also works: 
>>> print "has children" if len(root[3]) else "no child" 
has children 

Tôi đã sửa đổi mẫu của bạn vì lệnh gọi hàm findall trên gốc item không hoạt động (vì findall sẽ tìm kiếm hậu duệ trực tiếp chứ không phải phần tử hiện tại). Nếu bạn muốn truy cập văn bản của các con sau này trong chương trình làm việc của mình, bạn có thể làm:

for child in root.findall("item"): 
    # if there are children, get their text content as well. 
    if len(child): 
    for subchild in child: 
     subchild.text 
    # else just get the current child text. 
    else: 
    child.text 

Điều này phù hợp cho một đệ quy.

+0

không hoạt động. Bạn có thể sử dụng ví dụ của tôi với lặp lại không? –

+1

nó không hoạt động, bởi vì vòng lặp lặp của bạn không tạo ra các phần tử, vì không có phần tử nào có tên 'item' – marscher

+0

có, nó mang lại chúng trong ứng dụng thực của tôi. –

0

Lớp yếu tố có phương thức nhận con. Vì vậy, bạn nên sử dụng một cái gì đó như thế này, để kiểm tra xem có trẻ em và kết quả lưu trữ trong một cuốn từ điển bằng phím name = tag:

result = {} 
for child in root.findall("item"): 
    is child.getchildren() == []: 
     result[child.tag] = child.text 
+0

'getchildren' không được dùng nữa kể từ phiên bản 2.7. [Từ tài liệu] (https://docs.python.org/2/library/xml.etree.elementtree.html): Sử dụng danh sách (elem) hoặc lặp lại. – jlr

+0

bạn nói đúng. Không nên sử dụng nó nữa – marscher

0

Cá nhân tôi khuyên bạn nên sử dụng trình phân tích cú pháp xml hỗ trợ đầy đủ các biểu thức xpath. subset supported by xml.etree không đủ cho các tác vụ như thế này.

Ví dụ, trong lxml tôi có thể làm:

"cho tôi tất cả trẻ em của những đứa trẻ của nút <item>":

doc.xpath('//item/*/child::*') #equivalent to '//item/*/*', if you're being terse 
Out[18]: [<Element a11 at 0x7f60ec1c1348>, <Element a22 at 0x7f60ec1c1888>] 

hay,

"cho tôi tất cả các <item> Con của chúng ta không có con cái mình ":

doc.xpath('/item/*[count(child::*) = 0]') 
Out[20]: 
[<Element a1 at 0x7f60ec1c1588>, 
<Element a2 at 0x7f60ec1c15c8>, 
<Element a3 at 0x7f60ec1c1608>] 

hay,

"cho tôi tất cả những yếu tố mà không có bất kỳ trẻ em":

doc.xpath('//*[count(child::*) = 0]') 
Out[29]: 
[<Element a1 at 0x7f60ec1c1588>, 
<Element a2 at 0x7f60ec1c15c8>, 
<Element a3 at 0x7f60ec1c1608>, 
<Element a11 at 0x7f60ec1c1348>, 
<Element a22 at 0x7f60ec1c1888>] 

# and if I only care about the text from those nodes... 
doc.xpath('//*[count(child::*) = 0]/text()') 
Out[30]: ['value1', 'value2', 'value3', 'value222', 'value22'] 
+0

Đề xuất lxml giả định có vấn đề với hiệu năng và tính năng xpath thiếu. Nó chắc chắn tốt hơn so với ElementTree nhưng tôi sẽ không đi theo cách này nếu không có vấn đề với sau này, đặc biệt là xem xét rằng lxml yêu cầu cài đặt và nó không phải luôn luôn là một đi bộ tốt đẹp trong công viên. – jlr

+1

Hiệu suất là một điều, vâng, nhưng hỗ trợ xpath đầy đủ có nghĩa là bạn thực hiện tất cả công việc chọn các nút ở một nơi nhỏ gọn. truy vấn xpath đưa tôi một vài giây để viết; viết mã python để đi bộ cây và chọn các nút mà tôi muốn mất nhiều thời gian hơn và rất dễ tạo lỗi. Có rất nhiều lợi ích khác ngoài hiệu suất. – roippi

2

Cách đơn giản nhất tôi đã có thể tìm thấy là sử dụng các giá trị bool của nguyên tố này trực tiếp. Điều này có nghĩa bạn có thể sử dụng a4 trong một tuyên bố có điều kiện như-là:

a4 = Element('a4') 
if a4: 
    print('Has kids') 
else: 
    print('No kids yet') 

a4.append(Element('x')) 
if a4: 
    print('Has kids now') 
else: 
    print('Still no kids') 

Chạy đoạn mã này sẽ in

No kids yet 
Has kids now 

Giá trị boolean của một phần tử không nói bất cứ điều gì về text, tail hoặc các thuộc tính. Nó chỉ cho thấy sự hiện diện hay vắng mặt của trẻ em, đó là những gì câu hỏi ban đầu đã được yêu cầu.

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