很好用Python打印XML
什么是最好的方式(甚至是各种方式)漂亮的Python打印XML?
import xml.dom.minidom xml = xml.dom.minidom.parse(xml_fname) # or xml.dom.minidom.parseString(xml_string) pretty_xml_as_string = xml.toprettyxml()
lxml是最近更新的,并包含一个漂亮的打印function
import lxml.etree as etree x = etree.parse("filename") print etree.tostring(x, pretty_print=True)
查看lxml教程: http : //lxml.de/tutorial.html
另一个解决scheme是借用这个indent
函数 ,用于自2.5版本以来内置于Python的ElementTree库。 以下是这个样子:
from xml.etree import ElementTree def indent(elem, level=0): i = "\n" + level*" " j = "\n" + (level-1)*" " if len(elem): if not elem.text or not elem.text.strip(): elem.text = i + " " if not elem.tail or not elem.tail.strip(): elem.tail = i for subelem in elem: indent(subelem, level+1) if not elem.tail or not elem.tail.strip(): elem.tail = j else: if level and (not elem.tail or not elem.tail.strip()): elem.tail = j return elem root = ElementTree.parse('/tmp/xmlfile').getroot() indent(root) ElementTree.dump(root)
这是我的(哈克?)解决scheme来解决难看的文本节点问题。
uglyXml = doc.toprettyxml(indent=' ') text_re = re.compile('>\n\s+([^<>\s].*?)\n\s+</', re.DOTALL) prettyXml = text_re.sub('>\g<1></', uglyXml) print prettyXml
上面的代码将产生:
<?xml version="1.0" ?> <issues> <issue> <id>1</id> <title>Add Visual Studio 2005 and 2008 solution files</title> <details>We need Visual Studio 2005/2008 project files for Windows.</details> </issue> </issues>
而不是这个:
<?xml version="1.0" ?> <issues> <issue> <id> 1 </id> <title> Add Visual Studio 2005 and 2008 solution files </title> <details> We need Visual Studio 2005/2008 project files for Windows. </details> </issue> </issues>
免责声明:可能有一些限制。
正如其他人指出,lxml有一个漂亮的打印机内置。
请注意,虽然默认情况下它会将CDATA部分更改为普通文本,这可能会产生令人不快的结果。
这是一个保留input文件的Python函数,只改变缩进(注意strip_cdata=False
)。 此外,它确保输出使用UTF-8作为编码,而不是默认的ASCII(注意encoding='utf-8'
):
from lxml import etree def prettyPrintXml(xmlFilePathToPrettyPrint): assert xmlFilePathToPrettyPrint is not None parser = etree.XMLParser(resolve_entities=False, strip_cdata=False) document = etree.parse(xmlFilePathToPrettyPrint, parser) document.write(xmlFilePathToPrettyPrint, pretty_print=True, encoding='utf-8')
用法示例:
prettyPrintXml('some_folder/some_file.xml')
如果你有xmllint
你可以产生一个子xmllint
并使用它。 xmllint --format <file>
漂亮地将其inputXML打印到标准输出。
请注意,这个方法使用python外部的程序,这使得它成为一种破解。
def pretty_print_xml(xml): proc = subprocess.Popen( ['xmllint', '--format', '/dev/stdin'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, ) (output, error_output) = proc.communicate(xml); return output print(pretty_print_xml(data))
如果您使用的是DOM实现,则每种实现都有自己的内置漂亮打印forms:
# minidom # document.toprettyxml() # 4DOM # xml.dom.ext.PrettyPrint(document, stream) # pxdom (or other DOM Level 3 LS-compliant imp) # serializer.domConfig.setParameter('format-pretty-print', True) serializer.writeToString(document)
如果你使用的东西没有自己的漂亮的打印机 – 或者那些漂亮的打印机没有按照你想要的方式完成 – 你可能需要编写或inheritance自己的序列化程序。
我试图编辑上面的“ade”的答案,但Stack Overflow不会让我在匿名提供反馈后进行编辑。 这是一个function较差的版本,可以很好地打印ElementTree。
def indent(elem, level=0, more_sibs=False): i = "\n" if level: i += (level-1) * ' ' num_kids = len(elem) if num_kids: if not elem.text or not elem.text.strip(): elem.text = i + " " if level: elem.text += ' ' count = 0 for kid in elem: indent(kid, level+1, count < num_kids - 1) count += 1 if not elem.tail or not elem.tail.strip(): elem.tail = i if more_sibs: elem.tail += ' ' else: if level and (not elem.tail or not elem.tail.strip()): elem.tail = i if more_sibs: elem.tail += ' '
我有一些问题,迷你影印的漂亮。 我会得到一个UnicodeError,每当我试图漂亮的印刷文字与给定的编码以外的字符,例如,如果我有一个β在文档中,我尝试了doc.toprettyxml(encoding='latin-1')
。 这是我的解决方法:
def toprettyxml(doc, encoding): """Return a pretty-printed XML document in a given encoding.""" unistr = doc.toprettyxml().replace(u'<?xml version="1.0" ?>', u'<?xml version="1.0" encoding="%s"?>' % encoding) return unistr.encode(encoding, 'xmlcharrefreplace')
BeautifulSoup有一个易于使用的prettify()
function。
它缩进每个缩进级别的一个空间。 它比lxml的pretty_print好得多,又短又甜。
from bs4 import BeautifulSoup bs = BeautifulSoup(open(xml_file), 'xml') print bs.prettify()
from yattag import indent pretty_string = indent(ugly_string)
它不会在文本节点内添加空格或换行符,除非您要求:
indent(mystring, indent_text = True)
您可以指定缩进单元应该是什么,换行符应该是什么样子。
pretty_xml_string = indent( ugly_xml_string, indentation = ' ', newline = '\r\n' )
python的XML漂亮打印看起来相当不错。 (也适当地命名)
另一种方法是使用PyXML ,它有一个PrettyPrint函数 。
我写了一个解决scheme来遍历现有的ElementTree,并使用文本/尾部缩进,正如人们通常所期待的那样。
def prettify(element, indent=' '): queue = [(0, element)] # (level, element) while queue: level, element = queue.pop(0) children = [(level + 1, child) for child in list(element)] if children: element.text = '\n' + indent * (level+1) # for child open if queue: element.tail = '\n' + indent * queue[0][0] # for sibling open else: element.tail = '\n' + indent * (level-1) # for parent close queue[0:0] = children # prepend so children come before siblings
看看vkbeautify模块。
这是我的非常stream行的JavaScript / nodejs插件具有相同名称的python版本。 它可以漂亮地打印/缩小XML,JSON和CSS文本。 input和输出可以是任何组合的string/文件。 它非常紧凑,没有任何依赖性。
例如 :
import vkbeautify as vkb vkb.xml(text) vkb.xml(text, 'path/to/dest/file') vkb.xml('path/to/src/file') vkb.xml('path/to/src/file', 'path/to/dest/file')
另一种方法是如果你不需要重新分析,就有带有get_pprint()
函数的xmlpp.py库 。 它对我的用例非常顺利,无需重新分析为lxml ElementTree对象。
我有这个问题,并解决这个问题:
def write_xml_file (self, file, xml_root_element, xml_declaration=False, pretty_print=False, encoding='unicode', indent='\t'): pretty_printed_xml = etree.tostring(xml_root_element, xml_declaration=xml_declaration, pretty_print=pretty_print, encoding=encoding) if pretty_print: pretty_printed_xml = pretty_printed_xml.replace(' ', indent) file.write(pretty_printed_xml)
在我的代码中,这个方法是这样调用的:
try: with open(file_path, 'w') as file: file.write('<?xml version="1.0" encoding="utf-8" ?>') # create some xml content using etree ... xml_parser = XMLParser() xml_parser.write_xml_file(file, xml_root, xml_declaration=False, pretty_print=True, encoding='unicode', indent='\t') except IOError: print("Error while writing in log file!")
这仅仅是因为etree默认使用了two spaces
来缩进,我没有发现非常强调缩进,因此并不漂亮。 我不能设置任何函数的etree或参数来更改标准etree indent。 我喜欢使用etree是多么容易,但是这真的让我烦恼。
你可以使用stream行的外部库xmltodict , unparse
和pretty=True
你会得到最好的结果:
xmltodict.unparse( xmltodict.parse(my_xml), full_document=False, pretty=True)
full_document=False
针对<?xml version="1.0" encoding="UTF-8"?>
顶部。
我用一些代码行解决了这个问题,打开文件,通过它并添加缩进,然后再保存。 我正在使用小的XML文件,并不想添加依赖项,或更多的库来为用户安装。 无论如何,这是我最后的结果:
f = open(file_name,'r') xml = f.read() f.close() #Removing old indendations raw_xml = '' for line in xml: raw_xml += line xml = raw_xml new_xml = '' indent = ' ' deepness = 0 for i in range((len(xml))): new_xml += xml[i] if(i<len(xml)-3): simpleSplit = xml[i:(i+2)] == '><' advancSplit = xml[i:(i+3)] == '></' end = xml[i:(i+2)] == '/>' start = xml[i] == '<' if(advancSplit): deepness += -1 new_xml += '\n' + indent*deepness simpleSplit = False deepness += -1 if(simpleSplit): new_xml += '\n' + indent*deepness if(start): deepness += 1 if(end): deepness += -1 f = open(file_name,'w') f.write(new_xml) f.close()
它适用于我,也许有人会有一些使用它:)