2011-12-05 46 views
6

Tôi có một định dạng tệp kế thừa mà tôi đang chuyển đổi thành XML để xử lý. Cấu trúc có thể được tóm tắt là:LXML - Sắp xếp Thứ tự Thẻ

<A> 
    <A01>X</A01> 
    <A02>Y</A02> 
    <A03>Z</A03> 
</A> 

Phần số của thẻ có thể đi từ 01 đến 99 và có thể có khoảng trống. Là một phần của quá trình xử lý, một số bản ghi nhất định có thể có thêm thẻ. Sau khi quá trình xử lý hoàn tất, tôi chuyển đổi tệp trở lại định dạng cũ bằng cách lặp lại cây. Các tệp có kích thước khá lớn (~ 150.000 nút).

Một vấn đề với điều này là một số phần mềm sử dụng định dạng cũ giả định rằng các thẻ (hoặc các trường thay đổi theo thời gian được chuyển đổi) sẽ theo thứ tự chữ số, nhưng thẻ mới mặc định sẽ được thêm vào cuối các chi nhánh mà sau đó gây ra cho họ để đi ra khỏi iterator theo thứ tự sai.

Tôi có thể sử dụng xpath để tìm anh chị em dựa trên tên thẻ mỗi khi tôi đến để thêm thẻ mới nhưng câu hỏi của tôi là liệu có cách đơn giản hơn để sắp xếp cây cùng một lúc ngay trước khi xuất không?

Chỉnh sửa:

Tôi nghĩ rằng tôi đã tóm tắt cấu trúc.

Một hồ sơ có thể chứa nhiều tầng lớp như mô tả ở trên để cung cấp cho một cái gì đó như:

<X> 
    <X01>1</X01> 
    <X02>2</X02> 
    <X03>3</X03> 
    <A> 
     <A01>X</A01> 
     <A02>Y</A02> 
     <A03>Z</A03> 
    </A> 
    <B> 
     <B01>Z</B02> 
     <B02>X</B02> 
     <B03>C</B03> 
    </B> 
</X> 
+2

Tôi không như vậy chắc chắn các lược đồ XML là rất tốt nghĩ qua. Không phải là A01 và A02 cùng loại thứ? Họ nên chia sẻ cùng một tên phần tử. Số có lẽ nên là một thuộc tính, không phải là một phần của tên thẻ. Ngoài ra, các tên thẻ phải dễ đọc hơn tất nhiên, nhưng tôi nhận ra rằng chúng có thể chỉ là một ví dụ. –

+0

Rất tiếc, tôi không có quyền kiểm soát định dạng cũ và đây là bản dịch trực tiếp về cách lưu trữ dữ liệu trong các cặp khóa/giá trị. Trong tập tin gốc nó có thể nói "A01 = Bob" và các ứng dụng sau đó biết rằng số giữ tên. – George

+0

Có nhiều cách để thực hiện điều này trong XML nhưng cách bạn đã hiển thị ở đây không phải là một bản dịch rất ngữ nghĩa. Lược đồ của bạn sẽ phức tạp và luôn thay đổi. Tôi sẽ đề nghị ' giá trị' trong đó mục là thứ mà A01, A02 đại diện. –

Trả lời

17

Có thể viết helper fu nction để chèn một phần tử mới vào đúng vị trí, nhưng không biết nhiều hơn về cấu trúc thì thật khó để làm cho nó trở nên chung chung.

Dưới đây là một ví dụ ngắn sắp xếp phần tử con trên toàn bộ tài liệu:

from lxml import etree 

data = """<X> 
    <X03>3</X03> 
    <X02>2</X02> 
    <A> 
     <A02>Y</A02> 
     <A01>X</A01> 
     <A03>Z</A03> 
    </A> 
    <X01>1</X01> 
    <B> 
     <B01>Z</B01> 
     <B02>X</B02> 
     <B03>C</B03> 
    </B> 
</X>""" 

doc = etree.XML(data,etree.XMLParser(remove_blank_text=True)) 

for parent in doc.xpath('//*[./*]'): # Search for parent elements 
    parent[:] = sorted(parent,key=lambda x: x.tag) 

print etree.tostring(doc,pretty_print=True) 

yielding:

<X> 
    <A> 
    <A01>X</A01> 
    <A02>Y</A02> 
    <A03>Z</A03> 
    </A> 
    <B> 
    <B01>Z</B01> 
    <B02>X</B02> 
    <B03>C</B03> 
    </B> 
    <X01>1</X01> 
    <X02>2</X02> 
    <X03>3</X03> 
</X> 
+0

Cảm ơn - chức năng lamba chỉ làm những gì tôi cần. – George

+0

Cảm ơn ...Tôi cũng thấy bài viết này hữu ích: http://wiki.python.org/moin/HowTo/Sorting http://www.secnetix.de/olli/Python/lambda_functions.hawk – Homer6

+0

Tôi không hiểu tại sao bạn sử dụng 'cha mẹ [:] = 'trong bài tập. – Sdwdaw

4

Bạn có thể sắp xếp bạn yếu tố xml như thế này:

from operator import attrgetter 
from lxml import etree 

root = etree.parse(xmlfile) 
children = list(root) 
sorted_list = sorted(children, key=attrgetter('tag')) 

Nếu đây chạy quá chậm, bạn có thể chỉ sắp xếp tên thẻ và nhận nút bằng cách sử dụng xpath:

tag_list = [item.tag for item in root] 
sorted_taglist = sorted(tag_list) 
Các vấn đề liên quan