Kim*_*uey 30 python xml pretty-print elementtree python-2.6
我正在使用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")
Run Code Online (Sandbox Code Playgroud)
我已经尝试使用tree.write("New_Database.xml", "utf-8")
上面代码的最后一行,但它根本没有编辑XML的布局 - 它仍然是混乱的混乱.
我还决定摆弄并尝试做:而不是将其打印到Python shell,这给出了错误AttributeError:'unicode'对象没有属性'write'.
tree = minidom.parseString(ET.tostring(root)).toprettyxml(indent = " ")
当我将我的树写到最后一行的XML文件时,是否有一种方法可以像在Python shell中那样打印到XML文件?
我可以toprettyxml()
在这里使用,还是有不同的方法来做到这一点?
小智 100
我简单地用这个indent()
函数解决了它:
xml.etree.ElementTree.indent(tree, space=" ", level=0)
将空格附加到子树以在视觉上缩进树。这可用于生成打印精美的 XML 输出。树可以是Element
或ElementTree
。space
是为每个缩进级别插入的空白字符串,默认情况下为两个空格字符。要在已缩进的树内缩进部分子树,请将初始缩进级别传递为level
。
tree = ET.ElementTree(root)
ET.indent(tree, space="\t", level=0)
tree.write(file_name, encoding="utf-8")
Run Code Online (Sandbox Code Playgroud)
请注意,该indent()
函数是在 Python 3.9 中添加的。
Jon*_*ice 42
无论您的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)
Run Code Online (Sandbox Code Playgroud)
有一种可能的复杂性,特别是在Python 2中,它对字符串中的Unicode字符不太严格和不太复杂.如果您的toprettyxml
方法u"something"
提交了一个Unicode字符串(),那么您可能希望将其转换为合适的文件编码,例如UTF-8.例如,用以下内容替换一个写行:
f.write(xmlstr.encode('utf-8'))
Run Code Online (Sandbox Code Playgroud)
Tat*_*ize 16
将本·安德森的答案作为一个函数进行重复。
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))
Run Code Online (Sandbox Code Playgroud)
因此对不漂亮的数据运行测试:
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())
Run Code Online (Sandbox Code Playgroud)
我们得到:
<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>
Run Code Online (Sandbox Code Playgroud)
小智 11
我找到了一种使用直接 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>
Run Code Online (Sandbox Code Playgroud)
要将第三个元素放入并保持美观,您需要以下代码:
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.
Run Code Online (Sandbox Code Playgroud)
要缩进内部标签(如内部数据标签),您必须将其添加到父元素的文本中。如果你想在一个元素之后(通常在子元素之后)缩进任何东西,你可以把它放在尾部。
当您将其写入文件时,此代码会给出以下结果:
<?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>
Run Code Online (Sandbox Code Playgroud)
另请注意,如果您希望程序统一使用\t
,您可能需要先将文件解析为字符串,然后将所有缩进空格替换为\t
.
这段代码是在 Python3.7 中编写的,但在 Python2.7 中仍然有效。
如果要使用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)`
Run Code Online (Sandbox Code Playgroud)
如果您看到 xml 命名空间,例如py:pytype="TREE"
,您可能希望在创建之前添加xml_object
etree.cleanup_namespaces(root)
Run Code Online (Sandbox Code Playgroud)
这对于您的代码中的任何修改都应该足够了。
安装 bs4
pip install bs4
Run Code Online (Sandbox Code Playgroud)
使用此代码可以漂亮地打印:
from bs4 import BeautifulSoup
x = your xml
print(BeautifulSoup(x, "xml").prettify())
Run Code Online (Sandbox Code Playgroud)