491

PythonでXMLをきれいに印刷するための最良の方法(またはさまざまな方法)は何ですか?

4

27 に答える 27

426
import xml.dom.minidom

dom = xml.dom.minidom.parse(xml_fname) # or xml.dom.minidom.parseString(xml_string)
pretty_xml_as_string = dom.toprettyxml()
于 2009-07-30T14:12:29.050 に答える
184

lxml は最近更新され、きれいな印刷機能が含まれています

import lxml.etree as etree

x = etree.parse("filename")
print etree.tostring(x, pretty_print=True)

lxml チュートリアルをチェックしてください: http://lxml.de/tutorial.html

于 2009-04-15T00:21:19.413 に答える
118

もう 1 つの解決策は、2.5 以降 Python に組み込まれている ElementTree ライブラリで使用するために、このindent関数を借用することです。これは次のようになります。

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)
于 2011-01-04T01:57:31.667 に答える
49

醜いテキストノードの問題を回避するための私の(ハックな?)解決策は次のとおりです。

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>

免責事項:おそらくいくつかの制限があります。

于 2010-07-29T22:18:57.243 に答える
23

他の人が指摘したように、lxml にはかなりのプリンターが組み込まれています。

ただし、デフォルトでは CDATA セクションが通常のテキストに変更されるため、厄介な結果になる可能性があることに注意してください。

入力ファイルを保持し、インデントのみを変更する Python 関数を次に示します ( に注意してstrip_cdata=Falseください)。さらに、出力がデフォルトの ASCII ではなく UTF-8 をエンコーディングとして使用するようにします ( に注意して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')
于 2011-04-13T12:33:29.490 に答える
23

Python 3.9 の時点で、ElementTree にはindent()XML ツリーをきれいに印刷する機能があります。

https://docs.python.org/3/library/xml.etree.elementtree.html#xml.etree.ElementTree.indentを参照してください。

使用例:

import xml.etree.ElementTree as ET

element = ET.XML("<html><body>text</body></html>")
ET.indent(element)
print(ET.tostring(element, encoding='unicode'))

利点は、追加のライブラリを必要としないことです。詳細については、https://bugs.python.org/issue14465およびhttps://github.com/python/cpython/pull/15200を確認してください

于 2020-08-12T09:26:14.843 に答える
13

持っているxmllint場合は、サブプロセスを生成して使用できます。xmllint --format <file>入力 XML を標準出力にきれいに出力します。

この方法は、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))
于 2012-04-12T23:40:33.900 に答える
11

上記の「ade」の回答を編集しようとしましたが、最初に匿名でフィードバックを提供した後、Stack Overflow で編集できませんでした。これは、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 += '  '
于 2012-10-17T17:32:01.123 に答える
9

DOM 実装を使用している場合、それぞれに独自の形式の整形印刷が組み込まれています。

# 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)

独自のプリティ プリンターを使用せずに他のものを使用している場合、またはそれらのプリティ プリンターが思いどおりに機能しない場合は、おそらく独自のシリアライザーを作成またはサブクラス化する必要があります。

于 2009-04-15T00:48:22.377 に答える
6
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'
)

ドキュメントはhttp://www.yattag.orgホームページにあります。

于 2014-05-13T14:49:14.603 に答える
6

私は、既存の 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
于 2016-07-25T17:25:06.227 に答える
4

これは、醜い改行の問題 (大量の空白) を取り除き、他のほとんどの実装とは異なり、標準ライブラリのみを使用する Python3 ソリューションです。

import xml.etree.ElementTree as ET
import xml.dom.minidom
import os

def pretty_print_xml_given_root(root, output_xml):
    """
    Useful for when you are editing xml data on the fly
    """
    xml_string = xml.dom.minidom.parseString(ET.tostring(root)).toprettyxml()
    xml_string = os.linesep.join([s for s in xml_string.splitlines() if s.strip()]) # remove the weird newline issue
    with open(output_xml, "w") as file_out:
        file_out.write(xml_string)

def pretty_print_xml_given_file(input_xml, output_xml):
    """
    Useful for when you want to reformat an already existing xml file
    """
    tree = ET.parse(input_xml)
    root = tree.getroot()
    pretty_print_xml_given_root(root, output_xml)

ここで一般的な改行の問題を修正する方法を見つけました。

于 2020-02-12T17:03:19.483 に答える
3

Python 用の XML プリティ プリントは、このタスクに適しているように見えます。(名前も適当に。)

別の方法は、PrettyPrint関数を持つpyXMLを使用することです。

于 2009-04-15T00:07:19.557 に答える
3

一般的な外部ライブラリxmltodictを使用するunparsepretty=True、最良の結果が得られます。

xmltodict.unparse(
    xmltodict.parse(my_xml), full_document=False, pretty=True)

full_document=False反対<?xml version="1.0" encoding="UTF-8"?>する。

于 2016-09-07T17:02:38.220 に答える
-2

私はこれをいくつかのコード行で解決し、ファイルを開き、それを調べてインデントを追加し、再度保存しました。私は小さな 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()

それは私にとってはうまくいきます、おそらく誰かがそれを使用するでしょう:)

于 2013-07-12T11:01:36.767 に答える