Yanıtlar:
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 yakın zamanda güncellenir ve güzel bir yazdırma işlevi içerir
import lxml.etree as etree
x = etree.parse("filename")
print etree.tostring(x, pretty_print=True)
Lxml eğitimine göz atın: http://lxml.de/tutorial.html
aptitude install
uzakta. OS / X altında emin değilim.
print(etree.tostring(x, pretty_print=True, encoding="unicode"))
. Bir çıktı dosyasına yazmak sadece bir satırda mümkündür, aracı değişken gerekmez:etree.parse("filename").write("outputfile", encoding="utf-8")
Başka bir çözüm, bu indent
işlevi 2.5'ten beri Python'da yerleşik olan ElementTree kütüphanesi ile kullanmak için ödünç almaktır. İşte böyle görünecektir:
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])
dosyaya yazmak için yapabileceğinizi unutmayın ( tree
ElementTree örneği).
tree = ElementTree.parse('file) ; root = tree.getroot() ; indent(root); tree.write('Out.xml');
İşte çirkin metin düğümü sorununu çözmek için benim (hacky?) Çözüm.
uglyXml = doc.toprettyxml(indent=' ')
text_re = re.compile('>\n\s+([^<>\s].*?)\n\s+</', re.DOTALL)
prettyXml = text_re.sub('>\g<1></', uglyXml)
print prettyXml
Yukarıdaki kod üretecektir:
<?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>
Bunun yerine:
<?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>
Feragatname: Muhtemelen bazı sınırlamalar vardır.
re.compile
önce sizinki daha doğrudan sub
( re.findall()
iki kez kullanıyordum zip
ve ... for
ile bir döngü kullanıyordum str.replace()
)
Diğerlerinin de belirttiği gibi, lxml'de yerleşik güzel bir yazıcı var.
Bununla birlikte, varsayılan olarak CDATA bölümlerini normal metne değiştirdiğini ve bu da kötü sonuçlara neden olabileceğini unutmayın.
Girdi dosyasını koruyan ve sadece girintiyi değiştiren bir Python işlevi strip_cdata=False
. Ayrıca, çıkışın varsayılan ASCII yerine UTF-8 kullandığından emin olur (dikkat edin 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')
Örnek kullanım:
prettyPrintXml('some_folder/some_file.xml')
BeautifulSoup'un kullanımı kolay bir prettify()
yöntemi vardır.
Girinti seviyesi başına bir boşluk girintilidir. Lxml'nin pretty_print'inden çok daha iyi çalışır ve kısa ve tatlıdır.
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?
Varsa xmllint
bir alt işlem oluşturabilir ve kullanabilirsiniz.xmllint --format <file>
giriş XML'sini standart çıktıya yazdırır.
Bu yöntemin python için harici bir program kullandığını unutmayın, bu da onu bir tür hack yapar.
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))
Yukarıdaki "ade" yanıtını düzenlemeye çalıştım, ancak Stack Overflow başlangıçta anonim olarak geri bildirim sağladıktan sonra düzenlememe izin vermedi. Bu, bir ElementTree'yi güzel şekilde yazdırma işlevinin daha az hatalı bir sürümüdür.
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 += ' '
Bir DOM uygulaması kullanıyorsanız, her birinin kendi güzel baskı yerleşik biçimi vardır:
# 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)
Kendi güzel yazıcısı olmadan başka bir şey kullanıyorsanız - veya bu güzel yazıcılar bunu istediğiniz gibi yapmazsa - muhtemelen kendi serileştiricinizi yazmanız veya alt sınıflamanız gerekir.
Minidom'un güzel baskısıyla ilgili bazı problemlerim vardı. Belirli bir kodlamanın dışında karakterleri olan bir belgeyi güzel bir şekilde yazdırmayı denediğimde, örneğin bir belgede β varsa ve denediysem, bir UnicodeError alırdım doc.toprettyxml(encoding='latin-1')
. İşte benim geçici çözüm:
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)
Siz istemediğiniz sürece metin düğümlerinin içine boşluk veya satırsonu eklemez:
indent(mystring, indent_text = True)
Girinti biriminin ne olması gerektiğini ve yeni satırın nasıl görüneceğini belirleyebilirsiniz.
pretty_xml_string = indent(
ugly_xml_string,
indentation = ' ',
newline = '\r\n'
)
Doküman http://www.yattag.org ana sayfasındadır.
Varolan bir ElementTree üzerinden yürümek ve tipik olarak beklendiği gibi girintili metin / kuyruk kullanmak için bir çözüm yazdım.
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
Python için XML güzel baskı bu görev için oldukça iyi görünüyor. (Uygun şekilde adlandırılmış.)
Alternatif olarak PrettyPrint işlevi olan pyXML kullanmaktır .
HTTPError: 404 Client Error: Not Found for url: https://pypi.org/simple/xmlpp/
Bu projenin bugünlerde tavan arasında olduğunu düşünün, utanç.
İşte çirkin yeni satır sorunundan (tonlarca boşluk) kurtulan bir Python3 çözümü ve diğer birçok uygulamanın aksine sadece standart kütüphaneleri kullanıyor.
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)
Burada yeni satırsonu sorununu nasıl çözeceğimizi buldum .
Popüler harici kitaplık xmltodict ile birlikte kullanabilirsiniz unparse
ve pretty=True
en iyi sonucu elde edersiniz:
xmltodict.unparse(
xmltodict.parse(my_xml), full_document=False, pretty=True)
full_document=False
karşı <?xml version="1.0" encoding="UTF-8"?>
.
Vkbeautify modülüne bir göz atın .
Aynı adı taşıyan çok popüler javascript / nodejs eklentimin python sürümüdür. XML, JSON ve CSS metinlerini güzel bir şekilde basabilir / küçültebilir. Giriş ve çıkış herhangi bir kombinasyonda dize / dosya olabilir. Çok kompakttır ve herhangi bir bağımlılığı yoktur.
Örnekler :
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')
Yeniden çözümlemek istemiyorsanız alternatif olarak xmlpp.py kütüphanesi de bu get_pprint()
işleve sahiptir. Bir lxml ElementTree nesnesine yeniden ayrılmak zorunda kalmadan kullanım durumlarım için güzel ve sorunsuz çalıştı.
Bu varyasyonu deneyebilirsiniz ...
Yükleme BeautifulSoup
ve arka uç lxml
(ayrıştırıcı) kitaplıkları:
user$ pip3 install lxml bs4
XML belgenizi işleyin:
from bs4 import BeautifulSoup
with open('/path/to/file.xml', 'r') as doc:
for line in doc:
print(BeautifulSoup(line, 'lxml-xml').prettify())
'lxml'
lxml'nin HTML ayrıştırıcısını kullanır - BS4 belgelerine bakın . XML ayrıştırıcı için 'xml'
veya gerekiyor 'lxml-xml'
.
lxml’s XML parser BeautifulSoup(markup, "lxml-xml") BeautifulSoup(markup, "xml")
lxml-xml
) ve aynı gün aşağı doğru oy vermeye başladılar. S / O'ya resmi bir şikayet gönderdim ancak araştırmayı reddetti. Her neyse, o zamandan beri yine doğru olan (ve lxml-xml
başlangıçta yaptığı gibi) cevabımı "değiştirdim" . Teşekkür ederim.
Bu sorunu yaşadım ve şu şekilde çözdüm:
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)
Kodumda bu yöntem şöyle denir:
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!")
Bu sadece two spaces
girintiyi varsayılan olarak girintili olarak kullandığı için işe yarar, çünkü girintiyi çok fazla vurgulamıyorum ve bu nedenle hoş değil. Standart etree girintisini değiştirmek için herhangi bir işlev için etree veya parametre için herhangi bir ayar ind edemedim. Etree kullanmanın ne kadar kolay olduğunu seviyorum, ama bu beni gerçekten rahatsız ediyordu.
Tüm bir xml belgesini güzel bir xml belgesine dönüştürmek için
(ör. Bir LibreOffice Writer .odt veya .ods dosyasını [açtığınız] çıkarttığınız ve çirkin "content.xml" dosyasını güzel bir dosyaya dönüştürmek istediğinizi varsayalım. otomatik git sürüm denetimi ve git difftool
ing .odt / .ods dosyalarının ing, burada uygulamak gibi )
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()
Referanslar:
- Ben Noland'ın bu sayfadaki cevabını sağladım ve beni oraya götürdü.
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=' ',))
Çince ile xml için iyi çalışıyor!
Herhangi bir nedenden ötürü, diğer kullanıcıların bahsettiği Python modüllerinden herhangi birini alamıyorsanız, Python 2.7 için aşağıdaki çözümü öneriyorum:
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)
Bildiğim kadarıyla, bu çözüm xmllint
paketin yüklü olduğu Unix tabanlı sistemlerde çalışacaktır .
check_output
hatalarını basitleştirdim çünkü hata kontrolü yapmanıza gerek yok
Bunu bazı kod satırlarıyla çözdüm, dosyayı açtım, çukura gidip girinti ekledim, sonra tekrar kaydettim. Küçük xml dosyalarıyla çalışıyordum ve kullanıcı için yüklemek için bağımlılıklar veya daha fazla kitaplık eklemek istemiyordum. Her neyse, işte sonunda:
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()
Benim için çalışıyor, belki birileri biraz kullanacak :)