2011-12-05 8 views
6

私は処理のためにXMLに変換している従来のファイル形式を持っています。構造は以下のように要約することができます。LXML - タグの並べ替え

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

タグの数値部分は、01から99までの間にあり、ギャップが存在する可能性があります。処理の一部として、特定のレコードに追加のタグが追加されることがあります。処理が完了した後、私はツリーを繰り返してレガシー形式にファイルを変換しています。ファイルは相当に大きい(約150,000ノード)。

これは、従来の形式を使用する一部のソフトウェアでは、タグ(または変換されるまでのフィールド)が英数字の順序であると想定されていますが、デフォルトでは新しいタグが末尾に追加されますそのブランチは、それらを間違った順序で反復子から出させます。

私は、新しいタグを追加するたびに、先行する兄弟をタグ名に基づいて見つけることができますが、私の質問は、エクスポートの直前に一度にツリーを並べ替える簡単な方法があるかどうかです。

編集:

私は構造を要約したと思います。これはあまりにも遅い実行している、あなただけの可能性がある場合

from operator import attrgetter 
from lxml import etree 

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

:あなたはこのようなあなたのXML要素を並べ替えることができます

<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"と表示され、アプリケーションはその番号がforenameを保持していることを認識します。 – 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

:上記のように

記録のような何かを与えるために、いくつかのレベルを含めることができますタグ名をソートし、xpathを使用してノードを取得します。

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