2017-04-26 12 views
1

私はlxml要素ツリーのリストを持っています。私は木のリストのいずれかのサブトラクションにサブツリーが現れる回数を辞書に記憶したいと思う。lxml要素のツリー文字列をチェックする方法は?

defaultdict(<type 'int'>, {'<E attribute1="1"><B><C/></B></E>': 1, '<C/>': 2, '<A attribute1="1"><D><C attribute="2"/></D></A>': 1, '<B><C/></B>': 2, '<C attribute="2"/>': 1, '<D><C attribute="2"/></D>': 1, '<A attribute1="1"><B><C/></B></A>': 1}) 

この特定の例では、この唯一の作品:例

tree1='''<A attribute1="1"><B><C/></B></A>''' 
tree2='''<A attribute1="1"><D><C attribute="2"/></D></A>''' 
tree3='''<E attribute1="1"><B><C/></B></E>''' 
list_trees=[tree1,tree2,tree3] 
print list_trees 
from collections import defaultdict 
from lxml import etree as ET 
mydict=defaultdict(int) 
for tree in list_trees: 
    root=ET.fromstring(tree) 
    for sub_root in root.iter(): 
     print ET.tostring(sub_root) 
     mydict[ET.tostring(sub_root)]+=1 
print mydict 

のために私は次のように正しい結果を得ます。しかし、一般的なケースでは、xmlは同一でも構いませんが、属性の順序が異なったり、余分な空白や新しい行が問題になりません。しかし、この一般的なケースは私のシステムを破壊するでしょう。私は2つの同一のxmlツリーをチェックする方法についての記事があることを知っていますが、上記のこの特定のアプリケーションを行うためにxmlを文字列に変換したいと考えています(簡単な比較と柔軟性将来的に)また、SQLでうまく格納することができるようになります。順序付けや余分なスペース、余分な行にかかわらず、一貫性のある問題でXMLをどのように文字列にすることができますか?

動作しないケースを与えるための編集: これらの3つのxmlツリーは同じですが、属性や余分な空白や改行の順番が異なります。

tree4='''<A attribute1="1" attribute2="2"><B><C/></B></A>''' 
tree5='''<A attribute1="1"  attribute2="2" > 
<B><C/></B></A>''' 
tree6='''<A attribute2="2" attribute1="1"><B><C/></B></A>''' 

私の出力は次のようになります:

defaultdict(<type 'int'>, {'<B><C/></B>': 3, '<A attribute1="1" attribute2="2"><B><C/></B></A>': 1, '<A attribute1="1" attribute2="2">\n<B><C/></B></A>': 1, '<C/>': 3, '<A attribute2="2" attribute1="1"><B><C/></B></A>': 1}) 

ただし、出力は次のようになります。

defaultdict(<type 'int'>, {'<B><C/></B>': 3, '<A attribute1="1" attribute2="2"><B><C/></B></A>': 3, '<C/>': 3}) 
+0

と期待出力するときには、* ISN 'ここでは動作するXMLがいくつかありますが、動作しない他のXMLがあります。 – miken32

+0

が合意されました。コメントありがとうございました。今編集中。 – user2015487

答えて

1

あなたはXMLツリーの文字列表現を比較することを主張した場合、私はBeautifulSoupの使用をお勧めしますlxmlの上に。特に、ツリーの任意の部分にprettify()を呼び出すと、空白と入力からの奇妙な書式を無視する明確な表現が作成されます。出力文字列はもう少し冗長ですが、動作します。私は先に進んで改行を "fake newlines"('\n' -> '\\n')に置き換えたので、出力はよりコンパクトです。 (いくつかの余分な改行やスペースで)望ましい結果を出力

from collections import defaultdict 
from bs4 import BeautifulSoup as Soup 

tree4='''<A attribute1="1" attribute2="2"><B><C/></B></A>''' 
tree5='''<A attribute1="1"  attribute2="2" > 
<B><C/></B></A>''' 
tree6='''<A attribute2="2" attribute1="1"><B><C/></B></A>''' 
list_trees = [tree4, tree5, tree6] 

mydict = defaultdict(int) 
for tree in list_trees: 
    root = Soup(tree, 'lxml-xml') # Use the LXML XML parser. 
    for sub_root in root.find_all(): 
     print(sub_root) 
     mydict[sub_root.prettify().replace('\n', '\\n')] += 1 

print('Results') 
for key, value in mydict.items(): 
    print(u'%s: %s' % (key, value)) 

$パイソンcounter.py

<A attribute1="1" attribute2="2">\n <B>\n <C/>\n </B>\n</A>: 3 
<B>\n <C/>\n</B>: 3 
<C/>\n: 3 
サンプルXMLを提供しないのはなぜ
+0

ありがとうございました!私はmydict [sub_root.prettify()。replace( '\ n'、 '')] + = 1が必要であることを発見しました。これで私はまだ事例が見つからないが、それはうまくいかない。 – user2015487

関連する問題