답변:
import xml.dom.minidom
dom = xml.dom.minidom.parse(xml_fname) # or xml.dom.minidom.parseString(xml_string)
pretty_xml_as_string = dom.toprettyxml()
lxml은 최근에 업데이트되었으며, 예쁜 인쇄 기능을 포함합니다
import lxml.etree as etree
x = etree.parse("filename")
print etree.tostring(x, pretty_print=True)
lxml 튜토리얼을 확인하십시오 : http://lxml.de/tutorial.html
aptitude install
멀리 있습니다. OS / X에서 확실하지 않습니다.
print(etree.tostring(x, pretty_print=True, encoding="unicode"))
. 출력 파일에 쓰기는 단 한 줄로 가능하며 중간 변수가 필요하지 않습니다.etree.parse("filename").write("outputfile", encoding="utf-8")
또 다른 해결책은 2.5 이후 파이썬에 내장 된 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)
tree.write([filename])
파일에 쓰기 작업 을 수행 할 수 있습니다 tree
.
tree = ElementTree.parse('file) ; root = tree.getroot() ; indent(root); tree.write('Out.xml');
추악한 텍스트 노드 문제를 해결하는 내 (해키?) 솔루션이 있습니다.
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>
면책 조항 : 아마도 몇 가지 제한 사항이 있습니다.
re.compile
전에 사용하여 더 직접적입니다 sub
( re.findall()
두 번 사용 zip
하고 for
루프가 str.replace()
...)
다른 사람들이 지적했듯이 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')
BeautifulSoup에는 사용하기 쉬운 prettify()
방법이 있습니다.
들여 쓰기 레벨 당 하나의 공간을 들여 쓰기합니다. lxml의 pretty_print보다 훨씬 잘 작동하며 짧고 달콤합니다.
from bs4 import BeautifulSoup
bs = BeautifulSoup(open(xml_file), 'xml')
print bs.prettify()
bs4.FeatureNotFound: Couldn't find a tree builder with the features you requested: xml. Do you need to install a parser library?
당신이 경우 xmllint
당신은 하위 프로세스를 생성하고 사용할 수 있습니다.xmllint --format <file>
입력 XML을 표준 출력으로 출력합니다.
이 방법은 파이썬 외부의 프로그램을 사용하므로 일종의 해킹이됩니다.
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))
위의 "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 += ' '
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)
자신 만의 pretty-printer없이 다른 것을 사용하고 있거나, 그런 pretty-printer가 원하는 방식으로 그것을하지 않는다면, 아마도 여러분 자신의 serialiser를 작성하거나 서브 클래 싱해야 할 것입니다.
minidom의 예쁜 글씨에 문제가있었습니다. 주어진 인코딩 외부의 문자로 문서를 예쁘게 인쇄하려고 할 때마다 유니 코드 오류가 발생합니다 (예 : 문서에 β가 있고 시도한 경우) 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')
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 홈페이지에 있습니다.
기존 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
파이썬 용 XML 예쁜 프린트 는이 작업에 매우 적합합니다. (적절하게 명명 된 이름도 있습니다.)
대안으로 사용하는 PyXML에는 가지고 PrettyPrint 기능 .
HTTPError: 404 Client Error: Not Found for url: https://pypi.org/simple/xmlpp/
요즘 프로젝트가 다락방에 있다고 생각하십시오.
추악한 줄 바꿈 문제 (수백 개의 공백)를 제거하고 다른 대부분의 구현과 달리 표준 라이브러리 만 사용하는 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)
당신은 인기있는 외부 라이브러리 사용할 수 있습니다 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"?>
상단.
vkbeautify를 살펴 보십시오 모듈을 .
그것은 같은 이름을 가진 매우 인기있는 javascript / nodejs 플러그인의 파이썬 버전입니다. XML, JSON 및 CSS 텍스트를 예쁘게 인쇄 / 축소 할 수 있습니다. 입력과 출력은 조합으로 문자열 / 파일이 될 수 있습니다. 매우 작고 의존성이 없습니다.
예 :
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')
다른 방법으로 재분석 할 필요가 없다면 xmlpp.py 라이브러리 가 get_pprint()
있습니다. lxml ElementTree 객체로 다시 구문 분석하지 않고도 유스 케이스에서 훌륭하고 부드럽게 작동했습니다.
이 변형을 시도해 볼 수 있습니다 ...
설치 BeautifulSoup
및 백엔드 lxml
(파서) 라이브러리 :
user$ pip3 install lxml bs4
XML 문서를 처리하십시오.
from bs4 import BeautifulSoup
with open('/path/to/file.xml', 'r') as doc:
for line in doc:
print(BeautifulSoup(line, 'lxml-xml').prettify())
lxml’s XML parser BeautifulSoup(markup, "lxml-xml") BeautifulSoup(markup, "xml")
lxml-xml
)을 무단 변경 한 다음 같은 날 그것을 downvote로 진행했습니다. S / O에 공식 불만을 제출했지만 조사를 거부했습니다. 어쨌든, 나는 이제 내 대답을 "무단 변경"했습니다. 이는 이제 다시 정확합니다 ( lxml-xml
원래대로 지정 ). 감사합니다.
나는이 문제가 있었고 다음과 같이 해결했다.
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 또는 매개 변수에 대한 설정을 지정할 수 없습니다. 나는 etree를 사용하는 것이 얼마나 쉬운 지 좋아하지만 이것은 정말 성가신 일이었습니다.
전체 xml 문서를 예쁜 xml 문서로 변환하는 경우
(예 : LibreOffice Writer .odt 또는 .ods 파일을 압축 해제 한 후 추악한 "content.xml"파일을 다음과 같이 변환하려는 경우) 자동화 된 자식 버전 제어 및 git difftool
.odt / .ods 파일의 ing ( 예 : 여기에서 구현 중 )
import xml.dom.minidom
file = open("./content.xml", 'r')
xml_string = file.read()
file.close()
parsed_xml = xml.dom.minidom.parseString(xml_string)
pretty_xml_as_string = parsed_xml.toprettyxml()
file = open("./content_new.xml", 'w')
file.write(pretty_xml_as_string)
file.close()
참고 자료 :
- 이 페이지에서 Ben Noland의 답변 덕분에 저에게 가장 많은 도움이되었습니다.
from lxml import etree
import xml.dom.minidom as mmd
xml_root = etree.parse(xml_fiel_path, etree.XMLParser())
def print_xml(xml_root):
plain_xml = etree.tostring(xml_root).decode('utf-8')
urgly_xml = ''.join(plain_xml .split())
good_xml = mmd.parseString(urgly_xml)
print(good_xml.toprettyxml(indent=' ',))
중국어와 XML에 잘 작동합니다!
어떤 이유로 다른 사용자가 언급 한 Python 모듈을 사용할 수 없다면 Python 2.7에 대한 다음 솔루션을 제안합니다.
import subprocess
def makePretty(filepath):
cmd = "xmllint --format " + filepath
prettyXML = subprocess.check_output(cmd, shell = True)
with open(filepath, "w") as outfile:
outfile.write(prettyXML)
내가 아는 한,이 솔루션은 xmllint
패키지가 설치된 유닉스 기반 시스템에서 작동합니다 .
check_output
하면 오류 검사를 할 필요가 없기 때문에
나는 몇 줄의 코드 로이 문제를 해결하고 파일을 열고 여물통을 들여 들여 쓰기를 추가 한 다음 다시 저장합니다. 작은 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()
그것은 나를 위해 작동합니다, 아마도 누군가가 그것을 사용할 것입니다 :)