Удаление пробелов в строке XML

Как удалить пробелы и разрывы строк в строке XML в Python 2.6? Я попробовал следующие пакеты:

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, который обеспечил бы

8 ответов


самым простым решением, вероятно, является использование библиотека 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>

ведущие или конечные пробелы из textnodes не будут удаленный. Однако в некоторых случаях он будет удалять узлы пробелов из смешанного содержимого: если синтаксический анализатор еще не обнаружил узлы без пробелов на этом уровне.

>>> 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 или пустая строка)


вот что я быстро придумал, потому что я не хотел использовать 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 директива, но, честно говоря, так много другого программного обеспечения, связанного с XMLs, что это довольно забавное требование :) кроме того, вы сможете легко добавить такую функциональность в код выше (просто проверьте space атрибут, и не recure если свое значение "сохранить".)


пробелы значимы в XML-документе. Использование пробелов для отступов-это плохое использование XML, поскольку оно вводит значительные данные там, где их действительно нет, и, к сожалению, это норма. Любой программный подход к удалению пробелов будет, в лучшем случае, догадкой - вам нужно лучше знать, что передает XML, чтобы правильно удалить пробелы, не наступая на пальцы некоторых данных.


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 )

С этот источник


единственное, что меня беспокоит в xml.дом.toprettyxml () minidom заключается в том, что он добавляет пустые строки. Кажется, я не получаю разделенные компоненты, поэтому я просто написал простую функцию для удаления пустых строк:

#!/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>

немного неуклюжее решение без 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>

Если пробелы в узлах "не-листа" - это то, что мы пытаемся удалить, то следующая функция сделает это (рекурсивно, если указано):

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, поэтому используйте их с осторожностью.


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