2010-01-31 39 views
43

Tôi đang sử dụng mô-đun Python ElementTree dựng sẵn. Nó là đơn giản để truy cập vào trẻ em, nhưng những gì về các nút cha mẹ hoặc anh chị em? - điều này có thể được thực hiện hiệu quả mà không đi qua toàn bộ cây?truy cập nút nút ElementTree nút cha

+1

Xem http://stackoverflow.com/questions/374245/how-to-retrieve-the-parent-node-using- celementtree – kennytm

Trả lời

33

Không có hỗ trợ trực tiếp dưới dạng thuộc tính parent, nhưng bạn có thể sử dụng các mẫu được mô tả here để đạt được hiệu quả mong muốn. Sau đây một liner được đề nghị (từ liên kết để gửi) để tạo ra một bản đồ trẻ em để cha mẹ cho toàn bộ một cây:

parent_map = dict((c, p) for p in tree.getiterator() for c in p) 
+0

Cập nhật cú pháp, 2017/python3 'parent_map = {(c, p) cho p trong cây.iter() cho c trong p} ' – gerardw

+1

Hiệu chỉnh: ' parent_map = {c: p cho p trong root.iter() cho c trong p} ' – gerardw

14

Vinay's answer vẫn phải làm việc, nhưng đối với Python 2.7+ và 3.2+ sự sau đây là đề nghị:

parent_map = {c:p for p in tree.iter() for c in p} 

getiterator() được phản đối ủng hộ iter(), và nó rất hay để sử dụng danh sách dict constructor hiểu mới.

Thứ hai, khi xây dựng một tài liệu XML, có thể một đứa trẻ sẽ có nhiều cha mẹ, mặc dù điều này sẽ bị xóa khi bạn tuần tự hóa tài liệu. Nếu điều đó quan trọng, bạn có thể thử điều này:

parent_map = {} 
for p in tree.iter(): 
    for c in p: 
     if c in parent_map: 
      parent_map[c].append(p) 
      # Or raise, if you don't want to allow this. 
     else: 
      parent_map[c] = [p] 
      # Or parent_map[c] = p if you don't want to allow this 
+1

Nếu bạn không có quyền truy cập vào cây thì sao? Giống như sau một .find() – Brett

+1

Tôi không biết bất kỳ cách nào để có được nút gốc (và do đó cha mẹ/tổ tiên) nếu bạn không lưu một tham chiếu đến nó. Nhưng tôi không hiểu làm thế nào '.find()' có bất cứ điều gì để làm với điều đó. – supergra

+0

tôi chỉ sử dụng '.find()' như một hàm ví dụ mà chỉ trả về một phần tử – Brett

2

Một cách khác nếu chỉ muốn một phụ huynh duy nhất của phụ huynh và cũng biết xpath của subElement.

parentElement = subElement.find(xpath+"/..") 
+2

Không làm việc cho tôi, tôi nhận được 'Không' - giống nhau nếu tôi chỉ sử dụng 'subElement.find ('..')'. – damian

1

Nếu bạn đang sử dụng lxml, tôi đã có thể để có được những yếu tố phụ huynh như sau:

parent_node = next(child_node.iterancestors()) 

này sẽ nâng cao một ngoại lệ StopIteration nếu nguyên tố này không có tổ tiên - vì vậy hãy chuẩn bị để nắm bắt điều đó nếu bạn có thể gặp phải tình huống đó.

4

Bạn có thể sử dụng ký hiệu xpath ... trong ElementTree.

<parent> 
    <child id="123">data1</child> 
</parent> 

xml.findall('.//child[@id="123"]...') 
>> [<Element 'parent'>] 
+0

Đây là giải pháp tuyệt vời, làm việc với find() cũng nếu bạn biết chỉ có một yếu tố duy nhất mà bạn đang tìm kiếm. Giống như vậy: 'root.find (" .//*[@ testname = 'generated_sql'] ... ")' – Bostone

3

Như đã đề cập trong Get parent element after using find method (xml.etree.ElementTree) bạn sẽ phải thực hiện tìm kiếm gián tiếp cho cha mẹ. Có xml:

<a> 
<b> 
    <c>data</c> 
    <d>data</d>  
</b> 
</a> 

Giả sử bạn đã tạo ra yếu tố etree vào xml biến, bạn có thể sử dụng:

In[1] parent = xml.find('.//c/..') 
In[2] child = parent.find('./c') 

Hệ quả là:

Out[1]: <Element 'b' at 0x00XXXXXX> 
Out[2]: <Element 'c' at 0x00XXXXXX> 

mẹ cao hơn sẽ được tìm thấy như: secondparent=xml.find('.//c/../..')<Element 'a' at 0x00XXXXXX>

1

Nhìn vào 19.7.2.2. phần: Supported XPath syntax ... mẹ

Find nút bằng cách sử dụng đường dẫn:

parent_node = node.find('..') 
+1

Bạn đã thử nghiệm điều này chưa? Nếu bạn có thể làm cho nó hoạt động, vui lòng đăng một ví dụ mã hoàn chỉnh để minh họa nó. Xem nhận xét này: https://stackoverflow.com/questions/2170610/access-elementtree-node-parent-node#comment44519212_21963494 – mzjn

+1

Tài liệu Python 3 cho biết: "Trả về' Không có 'nếu đường dẫn cố gắng tiếp cận tổ tiên của phần đầu phần tử (phần tử 'find' được gọi)." (https://docs.python.org/3/library/xml.etree.elementtree.html#supported-xpath-syntax). – mzjn

+0

Làm việc cho tôi. Câu trả lời tốt nhất và bảo thủ nhất. – ToTenMilan

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