删除XML字符串中的空格

时间:2010-07-22 15:34:07

标签: python xml xml-serialization python-2.6 elementtree

如何在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

我不能使用提供method参数的Python 2.7。

minidom:就是一样:

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

7 个答案:

答案 0 :(得分:34)

最简单的解决方案可能是使用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或空字符串)

答案 1 :(得分:19)

我想出了一些快速的东西,因为我不想使用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属性,如果其值为“保留”,则不会恢复。)

答案 2 :(得分:7)

空格在XML文档中很重要。使用空格进行缩进是对XML的一种不良使用,因为它引入了重要的数据,而实际上并没有 - 而且遗憾的是,这是常态。你用来剥离空白的任何程序化方法都充其量只是猜测 - 你需要更好地了解XML正在传达什么来正确删除空格,而不是踩到一些数据的脚趾。

答案 3 :(得分:0)

唯一让我困扰xml.dom.minidom的toprettyxml()的是它添加空行。我似乎没有得到拆分组件,所以我只写了一个简单的函数来删除空行:

#!/usr/bin/env python

import xml.dom.minidom

# toprettyxml() without the blank lines
def prettyPrint(x):
    for line in x.toprettyxml().split('\n'):
        if not line.strip() == '':
            print line

xml_string = "<monty>\n<example>something</example>\n<python>parrot</python>\n</monty>"

# parse XML
x = xml.dom.minidom.parseString(xml_string)

# clean
prettyPrint(x)

这就是代码输出的内容:

<?xml version="1.0" ?>
<monty>
        <example>something</example>
        <python>parrot</python>
</monty>

如果我单独使用toprettyxml(),即print(toprettyxml(x)),则会添加不必要的空行:

<?xml version="1.0" ?>
<monty>


        <example>something</example>


        <python>parrot</python>


</monty>

答案 4 :(得分:-1)

有点笨拙的解决方案没有lxml : - )

data = """<root>

    <head></head>    <content></content>

</root>"""

data3 = []
data2 = data.split('\n')
for x in data2:
    y = x.strip()
    if y: data3.append(y)
data4 = ''.join(data3)
data5 = data4.replace("  ","").replace("> <","><")

print data5

Output: <root><head></head><content></content></root>

答案 5 :(得分:-1)

如果“非叶子”节点中的空格是我们要删除的内容,则以下函数将执行此操作(如果指定则递归):

from xml.dom import Node

def stripNode(node, recurse=False):
    nodesToRemove = []
    nodeToBeStripped = False

    for childNode in node.childNodes:
        # list empty text nodes (to remove if any should be)
        if (childNode.nodeType == Node.TEXT_NODE and childNode.nodeValue.strip() == ""):
            nodesToRemove.append(childNode)

        # only remove empty text nodes if not a leaf node (i.e. a child element exists)
        if childNode.nodeType == Node.ELEMENT_NODE:
            nodeToBeStripped = True

    # remove flagged text nodes
    if nodeToBeStripped:
        for childNode in nodesToRemove:
            node.removeChild(childNode)

    # recurse if specified
    if recurse:
        for childNode in node.childNodes:
            stripNode(childNode, True)

然而,Thanatos是正确的。空格可以用XML表示数据,因此请谨慎使用。

答案 6 :(得分:-3)

xmlStr = ' '.join(xmlStr.split()))

这会将所有文本放在一行中,用一个空格替换多个空格。

xmlStr = ''.join(xmlStr.split()))

这将删除包含文本内部空格的完整空间,并且无法使用。

对于您提供的输入,第一个表格可以与风险(但您要求)一起使用:

xmlStr = '''<root>
    <head></head>
    <content></content>
</root>'''
xmlStr = ' '.join(xmlStr.split())
print xmlStr
""" Output:
<root> <head></head> <content></content> </root>
"""

这将是有效的xml。它可能需要使用某种xml检查器进行检查。您是否确定要使用XML?你读过这篇文章了吗: Python Is Not Java