Python как убрать пробелы из текстовых узлов xml
У меня есть XML-файл следующим образом
<Person>
<name>
My Name
</name>
<Address>My Address</Address>
</Person>
У тега есть дополнительные новые строки. Есть ли быстрый Pythonic способ обрезать это и генерировать новый xml.
Я нашел это, но это урезает только те, которые между тегами не значение https://skyl.org/log/post/skyl/2010/04/remove-insignificant-whitespace-from-xml-string-with-python/
Обновление 1 - Обработка следующего XML, который имеет хвостовые пространства в <name>
тег
<Person>
<name>
My Name<shortname>My</short>
</name>
<Address>My Address</Address>
</Person>
Дескриптор принятого ответа над обоими видами XML
Обновление 2 - я разместил свою версию в ответе ниже, я использую ее для удаления всех видов пробелов и создания довольно xml в файле с кодировками xml
/questions/42596994/python-kak-ubrat-probelyi-iz-tekstovyih-uzlov-xml/42597017#42597017
5 ответов
С lxml
Вы можете перебрать все элементы и проверить, есть ли у него текст strip()
:
from lxml import etree
tree = etree.parse('xmlfile')
root = tree.getroot()
for elem in root.iter('*'):
if elem.text is not None:
elem.text = elem.text.strip()
print(etree.tostring(root))
Это дает:
<Person><name>My Name</name>
<Address>My Address</Address>
</Person>
ОБНОВЛЕНИЕ, чтобы раздеться tail
текст тоже:
from lxml import etree
tree = etree.parse('xmlfile')
root = tree.getroot()
for elem in root.iter('*'):
if elem.text is not None:
elem.text = elem.text.strip()
if elem.tail is not None:
elem.tail = elem.tail.strip()
print(etree.tostring(root, encoding="utf-8", xml_declaration=True))
Принятый ответ, полученный Birei с использованием lxml, отлично справляется с этой задачей, но я хотел обрезать все виды белого / пустого пространства, пустых строк и восстановить довольно xml в файле xml.
Следующий код сделал то, что я хотел
from lxml import etree
#discard strings which are entirely white spaces
myparser = etree.XMLParser(remove_blank_text=True)
root = etree.parse('xmlfile',myparser)
#from Birei's answer
for elem in root.iter('*'):
if elem.text is not None:
elem.text = elem.text.strip()
if elem.tail is not None:
elem.tail = elem.tail.strip()
#write the xml file with pretty print and xml encoding
root.write('xmlfile', pretty_print=True, encoding="utf-8", xml_declaration=True)
Вы должны сделать разбор XML для этого так или иначе, так что, возможно, используйте xml.sax
и копировать в выходной поток при каждом событии (пропуск ignorableWhitespace
) и добавьте маркеры тегов по мере необходимости. Проверьте пример кода здесь http://www.knowthytools.com/2010/03/sax-parsing-with-python.html.
Вы можете использовать Beautifulsoup. Обходите все элементы, и для каждого, который содержит некоторый текст, замените его его урезанной версией:
from bs4 import BeautifulSoup
soup = BeautifulSoup(open('xmlfile', 'r'), 'xml')
for elem in soup.find_all():
if elem.string is not None:
elem.string = elem.string.strip()
print(soup)
Если предположить, xmlfile
с содержанием, представленным в вопросе, это дает:
<?xml version="1.0" encoding="utf-8"?>
<Person>
<name>My Name</name>
<Address>My Address</Address>
</Person>
Я работаю со старой версией Python (2.3), и в настоящее время я застрял в стандартной библиотеке. Чтобы показать ответ, который в значительной степени обратно совместим, я написал это с xml.dom
а также xml.minidom
функции.
import codecs
from xml.dom import minidom
# Read in the file to a DOM data structure.
original_document = minidom.parse("original_document.xml")
# Open a UTF-8 encoded file, because it's fairly standard for XML.
stripped_file = codecs.open("stripped_document.xml", "w", encoding="utf8")
# Tell minidom to format the child text nodes without any extra whitespace.
original_document.writexml(stripped_file, indent="", addindent="", newl="")
stripped_file.close()
Пока это не BeautifulSoup
Это решение довольно элегантно и использует всю силу API нижнего уровня. Обратите внимание, что фактическое форматирование занимает всего одну строку:)
Документация по вызовам API, используемая здесь:
minidom.parse
minidom.Node.writexml
codecs.open