如何让Python的ElementTree打印到XML文件?

时间:2015-03-02 15:48:53

标签: python xml python-2.6 elementtree pretty-print

背景

我正在使用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 shell中一样打印到XML文件?

我可以在这里使用toprettyxml(),还是有不同的方式来做到这一点?

7 个答案:

答案 0 :(得分:30)

无论您的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中,它对字符串中的Unicode字符不太严格和不太复杂。如果您的toprettyxml方法提交了一个Unicode字符串(u"something"),那么您可能希望将其转换为合适的文件编码,例如UTF-8。例如。用以下内容替换一个写行:

f.write(xmlstr.encode('utf-8'))

答案 1 :(得分:3)

安装bs4

pip install bs4

使用此代码进行打印:

from bs4 import BeautifulSoup

x = your xml

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

答案 2 :(得分:3)

对本安德森的回答作为一个函数进行取笑。

def _pretty_print(current, parent=None, index=-1, depth=0):
    for i, node in enumerate(current):
        _pretty_print(node, current, i, depth + 1)
    if parent is not None:
        if index == 0:
            parent.text = '\n' + ('\t' * depth)
        else:
            parent[index - 1].tail = '\n' + ('\t' * depth)
        if index == len(parent) - 1:
            current.tail = '\n' + ('\t' * (depth - 1))

所以在不漂亮的数据上运行测试:

import xml.etree.ElementTree as ET
root = ET.fromstring('''<?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>
''')
_pretty_print(root)

tree = ET.ElementTree(root)
tree.write("pretty.xml")
with open("pretty.xml", 'r') as f:
    print(f.read())

我们得到:

<root>
    <data version="1">
        <data>76939</data>
    </data>
    <data version="2">
        <data>266720</data>
        <newdata>3569</newdata>
    </data>
    <data version="3">
        <data>5431</data>
    </data>
</root>

答案 3 :(得分:2)

查看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 

答案 4 :(得分:2)

如果想要使用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) 

这对于代码中的任何修改都应该足够了。

答案 5 :(得分:1)

我找到了一种使用直接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>

要在其中放置第三个元素并使它保持美观,您需要以下代码:

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。 / p>

此代码是在Python3.7中创建的,但仍在Python2.7中有效。

答案 6 :(得分:0)

我只是这样解决的:

<块引用>

xml.etree.ElementTree.indent(tree, space=" ", level=0) 追加 子树的空白以在视觉上缩进树。这可以是 用于生成打印精美的 XML 输出。树可以是 ElementElementTreespace 是将插入的空白字符串 每个缩进级别,默认两个空格字符。用于缩进 已经缩进的树内的部分子树,通过初始 缩进级别为 level

tree = ET.ElementTree(root)
ET.indent(tree, space="\t", level=0)
tree.write(file_name, encoding="utf-8")