移除XML字符串中的空格

31 投票
8 回答
44388 浏览
提问于 2025-04-16 01:41

我想知道怎么在Python 2.6中去掉XML字符串里的空格和换行符。我试过以下几个库:

etree:这个代码片段保留了原来的空格:

xmlStr = '''<root>
    <head></head>
    <content></content>
</root>'''

xmlElement = xml.etree.ElementTree.XML(xmlStr)
xmlStr = xml.etree.ElementTree.tostring(xmlElement, 'UTF-8')
print xmlStr

我不能使用Python 2.7,因为它会提供一个叫method的参数。

minidom:结果也是一样:

xmlDocument = xml.dom.minidom.parseString(xmlStr)
xmlStr = xmlDocument.toprettyxml(indent='', newl='', encoding='UTF-8')

8 个回答

7

在XML文档中,空白字符是很重要的。用空白字符来缩进代码其实并不是一个好的做法,因为这样会引入一些实际上并不存在的重要数据,而可悲的是,这种做法已经成为常态。无论你用什么程序来去掉空白字符,结果最多也只是个猜测——你需要更好地理解XML所传达的信息,才能正确地去掉空白,而不影响到某些数据。

33

这是我快速想出来的一个方法,因为我不想使用lxml库:

from xml.dom import minidom
from xml.dom.minidom import Node

def remove_blanks(node):
    for x in node.childNodes:
        if x.nodeType == Node.TEXT_NODE:
            if x.nodeValue:
                x.nodeValue = x.nodeValue.strip()
        elif x.nodeType == Node.ELEMENT_NODE:
            remove_blanks(x)

xml = minidom.parse('file.xml')
remove_blanks(xml)
xml.normalize()
with file('file.xml', 'w') as result:
    result.write(xml.toprettyxml(indent = '  '))

我其实只是想重新调整一个XML文件的缩进,因为它的缩进本来就乱七八糟。这个方法不支持preserve指令,但说实话,很多处理XML的软件也不支持这个,所以这其实是个挺搞笑的要求 :) 另外,你也可以很容易地在上面的代码中添加这种功能(只需检查space属性,如果它的值是'preserve',就不要再处理了)。

50

最简单的解决办法可能就是使用lxml这个库。在这里,你可以设置一个选项,让它忽略元素之间的空白。

>>> from lxml import etree
>>> parser = etree.XMLParser(remove_blank_text=True)
>>> xml_str = '''<root>
>>>     <head></head>
>>>     <content></content>
>>> </root>'''
>>> elem = etree.XML(xml_str, parser=parser)
>>> print etree.tostring(elem)
<root><head/><content/></root>

这可能已经足够满足你的需求了,但为了安全起见,有几点需要注意:

这个方法只是会去掉元素之间的空白节点,而尽量不去掉那些在包含混合内容的元素内部的空白节点。

>>> elem = etree.XML('<p> spam <a>ham</a> <a>eggs</a></p>', parser=parser)
>>> print etree.tostring(elem)
<p> spam <a>ham</a> <a>eggs</a></p>

文本节点前后的空白不会被去掉。不过在某些情况下,它仍然可能会去掉混合内容中的空白节点,尤其是当解析器在那个层级还没有遇到非空白节点时。

>>> elem = etree.XML('<p><a> ham</a> <a>eggs</a></p>', parser=parser)
>>> print etree.tostring(elem)
<p><a> ham</a><a>eggs</a></p>

如果你不想这样,可以使用xml:space="preserve",这样就会被尊重。另一个选择是使用dtd,并用etree.XMLParser(load_dtd=True),这样解析器会根据dtd来判断哪些空白节点是重要的,哪些不是。

除此之外,你可能需要自己写代码来去掉不想要的空白(可以遍历子节点,并在合适的地方把只包含空白的.text.tail属性设置为None或者空字符串)。

撰写回答