Удаление пробелов в строке 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