web-dev-qa-db-ja.com

PythonのElementTreeをXMLファイルにきれいに印刷するにはどうすればよいですか?

バックグラウンド

SQLiteを使用してデータベースにアクセスし、必要な情報を取得しています。 Pythonバージョン2.6でElementTreeを使用して、その情報を含むXMLファイルを作成しています。

コード

_import sqlite3
import xml.etree.ElementTree as ET

# NOTE: Omitted code where I acccess the database,
# pull data, and add elements to the tree

tree = ET.ElementTree(root)

# Pretty printing to Python Shell for testing purposes
from xml.dom import minidom
print minidom.parseString(ET.tostring(root)).toprettyxml(indent = "   ")

#######  Here lies my problem  #######
tree.write("New_Database.xml")
_

試み

上記のコードの最後の行の代わりにtree.write("New_Database.xml", "utf-8")を使用しようとしましたが、XMLのレイアウトをまったく編集しませんでした-まだ混乱しています。

私もいじってみると決めました:
tree = minidom.parseString(ET.tostring(root)).toprettyxml(indent = " ")
これをPython Shellに出力する代わりに、エラーが発生します AttributeError:「unicode」オブジェクトには「write」属性がありません

ご質問

最後の行でXMLファイルにツリーを書き込むとき、Pythonシェルと同じようにXMLファイルにきれいに印刷する方法はありますか?

ここでtoprettyxml()を使用できますか、これを行う別の方法がありますか?

27
Kimbluey

XML文字列が何であっても、ファイルを開いて文字列を書き込み、ファイルに書き込むことで、選択したファイルに書き込むことができます。

from xml.dom import minidom

xmlstr = minidom.parseString(ET.tostring(root)).toprettyxml(indent="   ")
with open("New_Database.xml", "w") as f:
    f.write(xmlstr)

特に、Python 2)には複雑さが1つあります。これは、文字列内のUnicode文字に関する厳密さと洗練度の両方が劣ります。toprettyxmlメソッドがUnicode文字列(u"something")、UTF-8などの適切なファイルエンコーディングにキャストすることができます。例えば。 1つの書き込み行を次のように置き換えます。

f.write(xmlstr.encode('utf-8'))
35
Jonathan Eunice

インストールbs4

pip install bs4

このコードを使用して、きれいに印刷します。

from bs4 import BeautifulSoup

x = your xml

print(BeautifulSoup(x, "xml").prettify())
3
RJX

Lxmlを使用する場合は、次の方法で実行できます。

from lxml import etree

xml_object = etree.tostring(root,
                            pretty_print=True,
                            xml_declaration=True,
                            encoding='UTF-8')

with open("xmlfile.xml", "wb") as writter:
    writter.write(xml_object)`

Xml名前空間が表示されている場合py:pytype="TREE"xml_objectの作成前に追加したい場合があります

etree.cleanup_namespaces(root) 

これは、コードの適応に十分なはずです。

3
Nick

vkbeautify モジュールを見てください。

入力と出力は、任意の組み合わせの文字列/ファイルにすることができます。非常にコンパクトで、依存関係はありません。

import vkbeautify as vkb

a) pretty_text = vkb.xml(your_xml_text)  #return String   

b) vkb.xml(your_xml_text, 'path/to/dest/file') #save in file 
2
vadimk

まっすぐなElementTreeを使用する方法を見つけましたが、かなり複雑です。

ElementTreeには、element.text="text"element.tail="tail"など、要素のテキストとテールを編集する関数があります。これらを特定の方法で使用して整列させる必要があるため、エスケープ文字を知っていることを確認してください。

基本的な例として:

次のファイルがあります。

<?xml version='1.0' encoding='utf-8'?>
<root>
    <data version="1">
        <data>76939</data>
    </data>
    <data version="2">
        <data>266720</data>
        <newdata>3569</newdata>
    </data>
</root>

3番目の要素を配置してきれいに保つには、次のコードが必要です。

addElement = ET.Element("data")             # Make a new element
addElement.set("version", "3")              # Set the element's attribute
addElement.tail = "\n"                      # Edit the element's tail
addElement.text = "\n\t\t"                  # Edit the element's text
newData = ET.SubElement(addElement, "data") # Make a subelement and attach it to our element
newData.tail = "\n\t"                       # Edit the subelement's tail
newData.text = "5431"                       # Edit the subelement's text
root[-1].tail = "\n\t"                      # Edit the previous element's tail, so that our new element is properly placed
root.append(addElement)                     # Add the element to the tree.

内部タグ(内部データタグなど)をインデントするには、親要素のテキストに追加する必要があります。要素の後(通常はサブ要素の後)にインデントする場合は、末尾に配置します。

このコードをファイルに書き込むと、次の結果が得られます。

<?xml version='1.0' encoding='utf-8'?>
<root>
    <data version="1">
        <data>76939</data>
    </data>
    <data version="2">
        <data>266720</data>
        <newdata>3569</newdata>
    </data> <!--root[-1].tail-->
    <data version="3"> <!--addElement's text-->
        <data>5431</data> <!--newData's tail-->
    </data> <!--addElement's tail-->
</root>

別の注意として、プログラムで\tを統一的に使用する場合は、最初にファイルを文字列として解析し、インデントのすべてのスペースを\tに置き換えます。

このコードはPython3.7で作成されましたが、Python2.7でも動作します。

1
Ben Anderson