首页 文章

在Python中打印XML

提问于
浏览
354

在Python中打印xml的最佳方式(甚至是各种方法)是什么?

19 回答

  • 0

    您可以使用流行的外部库xmltodictunparsepretty=True 您将获得最佳结果:

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

    full_document=False 反对 <?xml version="1.0" encoding="UTF-8"?> 在顶部 .

  • 46

    如果您不想重新分析,则可以使用带有 get_pprint() 函数的xmlpp.py library . 对于我的用例,它工作得很顺利,而不必重新解析为lxml的ElementTree对象 .

  • 2

    看一下vkbeautify模块 .

    它是我非常流行的javascript / nodejs插件的python版本,具有相同的名称 . 它可以打印/缩小XML,JSON和CSS文本 . 输入和输出可以是任何组合的字符串/文件 . 它非常紧凑,没有任何依赖性 .

    Examples

    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')
    
  • 1
    import xml.dom.minidom
    
    xml = xml.dom.minidom.parse(xml_fname) # or xml.dom.minidom.parseString(xml_string)
    pretty_xml_as_string = xml.toprettyxml()
    
  • 5

    lxml是最新的,更新的,并包含一个漂亮的打印功能

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

    查看lxml教程:http://lxml.de/tutorial.html

  • 9

    另一个解决方案是借用this indent function,与ElementTree库一起使用's built in to Python since 2.5. Here' s看起来像什么:

    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)
    
  • 0

    这是我的(hacky?)解决方案来解决丑陋的文本节点问题 .

    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>
    

    免责声明:可能存在一些限制 .

  • 1

    正如其他人指出的那样,lxml内置了漂亮的打印机 .

    请注意,默认情况下它会将CDATA部分更改为普通文本,这可能会产生令人讨厌的结果 .

    这是一个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')
    
  • 8

    BeautifulSoup有一个易于使用的 prettify() 功能 .

    它每个缩进级别缩进一个空格 . 它的效果比lxml的pretty_print好得多,而且简短而且甜美 .

    from bs4 import BeautifulSoup
    
    bs = BeautifulSoup(open(xml_file), 'xml')
    print bs.prettify()
    
  • 6

    如果你有 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))
    
  • -1

    我尝试编辑上面的“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 += '  '
    
  • 11

    如果你正在使用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)
    

    如果你在没有自己的漂亮打印机的情况下使用别的东西 - 或者那些漂亮的打印机并不是你想要的那样 - 你可能必须编写或子类化你自己的序列化器 .

  • 10

    我遇到一些问题minidom 's pretty print. I' d每当我尝试使用给定编码之外的字符打印漂亮的文档时会得到一个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')
    
  • 140
    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主页上 .

  • 18

    XML pretty print for python看起来非常适合这项任务 . (也恰如其名 . )

    另一种方法是使用pyXML,它有一个PrettyPrint function .

  • 323

    我编写了一个解决方案来遍历现有的ElementTree并使用text / tail来缩进它,就像人们通常期望的那样 .

    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
    
  • 92

    我遇到了这个问题并解决了这个问题:

    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是多么容易,但这真让我烦恼 .

  • 3

    For converting an entire xml document to a pretty xml document
    (例如:假设您已经解压缩[解压]了一个LibreOffice Writer .odt或.ods文件,并且您希望将丑陋的"content.xml"文件转换为非常适合自动git版本控制和.odt / .ods文件的 git difftool ,比如我正在实施here

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

    参考文献:

  • 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()
    

    它适用于我,也许有人会有一些使用它:)

相关问题