27

如何在 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')
4

8 回答 8

43

最简单的解决方案可能是使用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 和 use etree.XMLParser(load_dtd=True),其中解析器将使用 dtd 来确定哪些空白节点是重要的或不重要的。

除此之外,您必须编写自己的代码来删除您不想要的空格(迭代后代,并在适当的情况下,设置.text.tail属性仅包含空格None或空字符串)

于 2010-07-23T09:39:29.500 回答
29

这是我想出的快速方法,因为我不想使用 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',则不要recur。)

于 2013-06-04T13:23:31.947 回答
7

空白在 XML 文档中很重要。使用空格进行缩进是对 XML 的不良使用,因为它在实际上没有空格的地方引入了重要的数据——遗憾的是,这是常态。您为去除空白而采取的任何编程方法充其量只是一种猜测——您需要更好地了解 XML 所传达的内容才能正确去除空白,而无需踩到某些数据的脚趾。

于 2010-07-22T22:44:29.093 回答
2

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>
于 2015-08-31T09:41:26.953 回答
1
xmlStr = xmlDocument.toprettyxml(indent='\t', newl='\n', encoding='UTF-8')
fix = re.compile(r'((?<=>)(\n[\t]*)(?=[^<\t]))|(?<=[^>\t])(\n[\t]*)(?=<)')
newXmlStr = re.sub(fix, '', xmlStr )

这个来源

于 2015-04-30T18:12:03.780 回答
-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>
于 2012-11-09T20:54:40.653 回答
-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)

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

于 2013-01-22T03:42:40.467 回答
-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 不是 Java

于 2010-07-22T15:45:06.457 回答