2012-01-26 9 views
3

私はElementTreeを使用した後にlxmlを学んでいますが、なぜ.fromstringと.tostringが可逆ではないように思われます。ここに私の例があります:lxml.etree fromsting()とtostring()が同じデータを返していません

import lxml.etree as ET 
f = open('somefile.xml','r') 
data = f.read() 
tree_in = ET.fromstring(data) 
tree_out = ET.tostring(tree_in) 
f2 = open('samefile.xml','w') 
f2.write(tree_out) 
f2.close 

「somefile.xml」は132 KBでした。 'samefile.xml' - 出力は113 KBでしたが、何らかの任意の点でファイルの最後が欠けています。ツリー全体の終了タグと最後の要素のいくつかの要素がなくなりました。

私のコードに何か問題がありますか、または元のXMLファイルのネストに何か問題がありますか?もしそうなら、私はElementTreeのBeautifulSoupを(xpathなしで)再び使用する必要がありますか?

注:多くの要素の中にあるテキストには、テキストに変換されたが、この問題の原因は何ですか?

例:

<QuestionIndex Id="Perm"><Answer><![CDATA[confirm]]></Answer><Answer><![CDATA[NotConfirm]]></Answer></QuestionIndex> 
<QuestionIndex Id="Actor"><Answer><![CDATA[GirlLt16]]></Answer><Answer><![CDATA[Fem17to25]]></Answer><Answer><![CDATA[BoyLt16]]></Answer><Answer><![CDATA[Mal17to25]]></Answer><Answer><![CDATA[Moth]]></Answer><Answer><![CDATA[Fath]]></Answer><Answer><![CDATA[Elder]]></Answer><Answer><![CDATA[RelLead]]></Answer><Answer><![CDATA[Auth]]></Answer><Answer><![CDATA[Teach]]></Answer><Answer><![CDATA[Oth]]></Answer></QuestionIndex> 
+0

一部のテキストデータが正しくエスケープされないことが考えられます。私はあなたの例からこれを判断することはできません。私が時々異なる言語(xmlだけでなく)の異なるxmlライブラリを使って実行している、よくある問題です。 –

答えて

2

この問題は、見た目よりも道に簡単であることが判明し、その答えは、私が提供されたコードの中に隠されています。

f.close 

は違いは、私がで結果をチェックしていたメモ帳++ファイルにそれを作ったことがない数十文字の残りのバッファである

f.close() 

されている必要があります。作られた本物ののファイルを閉じますすべての違いとコードが機能します。

9

「いくつかのarbirtrary時点でファイルの終わりを逃す」の問題は、完全な再現性の例なしで説明するのは難しいです。

しかし、私はあなたが "くその束"と呼ぶものはCDATA sectionsだと思っています。あなたの例にはいくつかの例があります(これは正しい形式のXML文書ではありません、btw)。

一般に、XMLパーサーは、CDATAセクションをそのまま保存する義務はありません。マークアップは、

<Answer><![CDATA[confirm]]></Answer> 

としてlxml.etree.XMLParserクラスは、CDATAセクションを保存するために使用することができるstrip_cdataパラメータを取り、しかし

<Answer>confirm</Answer>  

と等価です。パーサーのインスタンスはetree.fromstring()に渡すことができます。次に例を示します。

from lxml import etree 

XML = '<QuestionIndex Id="Perm"><Answer><![CDATA[confirm]]></Answer></QuestionIndex>' 

print "Original size:", len(XML) 
tree1 = etree.fromstring(XML) 

out = etree.tostring(tree1) 
print "With CDATA stripped:", len(out) 
print out 

parser = etree.XMLParser(strip_cdata=False) 
tree2 = etree.fromstring(XML, parser) 

out = etree.tostring(tree2) 
print "With CDATA kept:", len(out) 
print out 

=>

Original size: 77 
With CDATA stripped: 65 
<QuestionIndex Id="Perm"><Answer>confirm</Answer></QuestionIndex> 
With CDATA kept: 77 
<QuestionIndex Id="Perm"><Answer><![CDATA[confirm]]></Answer></QuestionIndex> 
+1

これは良い推測でしたが、** lxml **はすべてのCDATAフィールドを正しく解析して、出力ファイルのプレーンテキストに変換しました。問題のファイルを正しく閉じることができませんでした。 –

関連する問題