2011-12-05 58 views
6

我有一個遺留的文件格式,我將其轉換爲XML進行處理。該結構可以概括爲:LXML - 排序標記順序

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

標籤的數字部分可以去從01到99,並可能有差距。作爲處理的一部分,某些記錄可能會添加額外的標籤。處理完成後,我通過漫遊樹將文件轉換回傳統格式。這些文件相當大(約150,000個節點)。

這樣做的一個問題是,一些使用傳統格式的軟件假設標籤(或者說它的轉換時間字段)將按字母數字順序排列,但默認情況下,新標籤將被添加到該分支然後導致它們以錯誤順序從迭代器中出來。

我可以使用xpath根據標籤名稱找到前面的兄弟,每次我添加一個新的標籤,但我的問題是是否有一種更簡單的方法來在導出之前立即對樹進行排序?

編輯:

我想我已經在總結結構。

的記錄可以包含如上文所述,以得到類似幾個層次:

<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

我不太確定XML架構非常深思熟慮過。 A01和A02不是同一類型的東西嗎?他們應該共享相同的元素名稱。這個數字應該是一個屬性,而不是標籤名稱的一部分。此外,標籤名稱當然應該比這更可讀,但我意識到它們可能只是一個例子。 –

+0

不幸的是,我無法控制傳統格式,而是直接翻譯了它如何將數據存儲在鍵/值對中。在原始文件中,它可能會說「A01 = Bob」,然後應用程序知道該號碼保存着名字。 – George

+0

有很多方法可以在XML中實現它,但是您在這裏展示的不是一個非常有意義的翻譯。您的模式將變得複雜且不斷變化。我會建議''其中item是A01,A02表示的東西。 –

回答

17

可以寫一個輔助函數以便在正確的位置插入一個新的元素,但是如果不知道更多關於結構的信息,就很難使其具有通用性。

這裏是在整個文件分類的子元素的簡單的例子:

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) 

產量:

<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

謝謝 - lamba函數只是我需要的。 – George

+0

謝謝...我發現這些文章也很有用:http://wiki.python.org/moin/HowTo/Sorting http://www.secnetix.de/olli/Python/lambda_functions.hawk – Homer6

+0

我不明白你爲什麼使用'parent [:] =分配。 – Sdwdaw

4

你可以這樣你的XML元素進行排序:

from operator import attrgetter 
from lxml import etree 

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

如果這個速度太慢,你可能只是對標籤名稱進行排序並使用xpath獲取節點:

tag_list = [item.tag for item in root] 
sorted_taglist = sorted(tag_list)