Подтвердить что ты не робот

Удаление пробелов в строке 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, который предоставил бы параметр method.

minidom: то же самое:

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

Ответ 1

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

Ответ 2

Вот что-то быстрое, что я придумал, потому что я не хотел использовать 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 и не выберете, если его значение "сохранить".)

Ответ 3

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

Ответ 4

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 )

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

Ответ 5

Единственное, что меня беспокоит в 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>

Ответ 6

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

Ответ 7

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

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

Ответ 8

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