13

我有以下代码。

from xml.dom.minidom import Document

doc = Document()

root = doc.createElement('root')
doc.appendChild(root)
main = doc.createElement('Text')
root.appendChild(main)

text = doc.createTextNode('Some text here')
main.appendChild(text)

print doc.toprettyxml(indent='\t')

结果是:

<?xml version="1.0" ?>
<root>
    <Text>
        Some text here
    </Text>
</root>

这一切都很好,很漂亮,但是如果我希望输出看起来像这样呢?

<?xml version="1.0" ?>
<root>
    <Text>Some text here</Text>
</root>

这很容易做到吗?

欧阳普...

4

6 回答 6

7

这很容易做到吗?

这取决于您想要什么确切的规则,但通常不,您几乎无法控制漂亮的打印。如果你想要一个特定的格式,你通常必须编写自己的 walker。

pxdom中的 DOM Level 3 LS 参数 format-pretty-print与您的示例非常接近。它的规则是,如果一个元素只包含一个 TextNode,则不会添加额外的空格。然而,它(目前)使用两个空格而不是四个缩进。

>>> doc= pxdom.parseString('<a><b>c</b></a>')
>>> doc.domConfig.setParameter('format-pretty-print', True)
>>> print doc.pxdomContent
<?xml version="1.0" encoding="utf-16"?>
<a>
  <b>c</b>
</a>

(为您正在执行的任何类型的序列化调整编码和输出格式。)

如果这是您想要的规则,并且您可以侥幸逃脱,您也可以对 minidom 的 Element.writexml 进行猴子补丁,例如:

>>> from xml.dom import minidom
>>> def newwritexml(self, writer, indent= '', addindent= '', newl= ''):
...     if len(self.childNodes)==1 and self.firstChild.nodeType==3:
...         writer.write(indent)
...         self.oldwritexml(writer) # cancel extra whitespace
...         writer.write(newl)
...     else:
...         self.oldwritexml(writer, indent, addindent, newl)
... 
>>> minidom.Element.oldwritexml= minidom.Element.writexml
>>> minidom.Element.writexml= newwritexml

所有关于猴子补丁坏处的常见警告都适用。

于 2009-02-03T15:30:32.183 回答
2

我正在寻找完全相同的东西,我遇到了这篇文章。(xml.dom.minidom 中提供的缩进破坏了我用来操作 XML 的另一个工具,我需要缩进)我用一个稍微复杂的示例尝试了公认的解决方案,结果如下:

In [1]: import pxdom

In [2]: xml = '<a><b>fda</b><c><b>fdsa</b></c></a>'

In [3]: doc = pxdom.parseString(xml)

In [4]: doc.domConfig.setParameter('format-pretty-print', True)

In [5]: print doc.pxdomContent
<?xml version="1.0" encoding="utf-16"?>
<a>
  <b>fda</b><c>
    <b>fdsa</b>
  </c>
</a>

打印出来的漂亮 XML 格式不正确,而且我对猴子补丁不太满意(即我几乎不知道它的含义,并且理解它很糟糕),所以我寻找了另一种解决方案。

我正在将输出写入文件,因此我可以使用 Ubuntu 的 xmlindent 程序($sudo aptitude install xmlindent)。所以我只是将未格式化的文件写入文件,然后从 python 程序中调用 xmlindent:

from subprocess import Popen, PIPE
Popen(["xmlindent", "-i", "2", "-w", "-f", "-nbe", file_name], 
      stderr=PIPE, 
      stdout=PIPE).communicate()

-w 开关会导致文件被覆盖,但令人讨厌的是会留下一个名为“myfile.xml~”的文件,您可能希望将其删除。其他开关可以让格式正确(对我来说)。

PS xmlindent 是一个流格式化程序,即您可以按如下方式使用它:

cat myfile.xml | xmlindent > myfile_indented.xml

因此,如果需要,您可以在 python 脚本中使用它而无需写入文件。

于 2009-08-19T19:58:11.553 回答
1

这可以通过 toxml() 来完成,使用正则表达式来整理。

>>> from xml.dom.minidom import Document
>>> import re
>>> doc = Document()
>>> root = doc.createElement('root')
>>> _ = doc.appendChild(root)
>>> main = doc.createElement('Text')
>>> _ = root.appendChild(main)
>>> text = doc.createTextNode('Some text here')
>>> _ = main.appendChild(text)
>>> out = doc.toxml()
>>> niceOut = re.sub(r'><', r'>\n<', re.sub(r'(<\/.*?>)', r'\1\n', out))
>>> print niceOut
<?xml version="1.0" ?>
<root>
<Text>Some text here</Text>
</root>
于 2012-08-27T16:43:31.887 回答
0

pyxml 包通过使用 xml.dom.ext.PrettyPrint() 函数提供了一个简单的解决方案。它还可以打印到文件描述符。

但是 pyxml 包不再维护。

欧尔扬·彼得森

于 2009-03-08T16:48:22.527 回答
0

该解决方案对我有用,无需猴子修补或停止使用 minidom:

from xml.dom.ext import PrettyPrint
from StringIO import StringIO

def toprettyxml_fixed (node, encoding='utf-8'):
    tmpStream = StringIO()
    PrettyPrint(node, stream=tmpStream, encoding=encoding)
    return tmpStream.getvalue()

http://ronrothman.com/public/leftbraned/xml-dom-minidom-toprettyxml-and-silly-whitespace/#best-solution

于 2010-03-25T16:18:07.500 回答
0

最简单的方法是使用 prettyxml,并删除标签内的 \n 和 \t。这样,您就可以按照示例中的要求保持缩进。

xml_output = doc.toprettyxml() nojunkintags = re.sub('>(\n|\t)</', '', xml_output) print nojunkintags

于 2015-04-07T13:51:20.917 回答