Как обновить/изменить XML файл в python?
У меня есть документ XML, который я хотел бы обновить после того, как он уже содержит данные.
Я думал об открытии XML файла в режиме "a" (append). Проблема в том, что новые данные будут записаны после тега закрытия корня.
Как удалить последнюю строку файла, затем начать запись данных с этой точки, а затем закрыть корневой тег?
Конечно, я мог бы прочитать весь файл и сделать некоторые строковые манипуляции, но я не думаю, что лучшая идея..
Спасибо за ваше время.
Ответы
Ответ 1
Быстрый и простой способ, который вы определенно не должны делать (см. ниже), состоит в том, чтобы прочитать весь файл в списке строк, используя readlines(). Я пишу это, если быстрое и простое решение - это то, что вы ищете.
Просто откройте файл, используя open(), затем вызовите метод readlines(). Вы получите список всех строк в файле. Теперь вы можете легко добавить строки перед последним элементом (просто добавьте в список один элемент до последнего). Наконец, вы можете записать их обратно в файл с помощью writelines().
Пример может помочь:
my_file = open(filename, "r")
lines_of_file = my_file.readlines()
lines_of_file.insert(-1, "This line is added one before the last line")
my_file.writelines(lines_of_file)
Причина, по которой вы не должны этого делать, состоит в том, что, если вы не делаете что-то очень быстрое n 'грязное, вы должны использовать XML-анализы. Это библиотека, которая позволяет работать с XML разумно, используя такие понятия, как DOM, деревья и узлы. Это не только правильный способ работы с XML, но и стандартный способ, который делает ваш код более переносимым и понятным для других программистов.
В ответе Тима упоминается проверка http://docs.python.org/library/xml.dom.minidom.html для этой цели, которая, я думаю, была бы отличной идеей.
Ответ 2
Использование ElementTree
:
import xml.etree.ElementTree
# Open original file
et = xml.etree.ElementTree.parse('file.xml')
# Append new tag: <a x='1' y='abc'>body text</a>
new_tag = xml.etree.ElementTree.SubElement(et.getroot(), 'a')
new_tag.text = 'body text'
new_tag.attrib['x'] = '1' # must be str; cannot be an int
new_tag.attrib['y'] = 'abc'
# Write back to file
#et.write('file.xml')
et.write('file_new.xml')
note: вывод, записанный на file_new.xml
для экспериментов, запись на file.xml
заменит старый контент.
ВАЖНО: библиотека ElementTree хранит атрибуты в dict, поэтому порядок, в котором эти атрибуты указаны в XML-тексте, НЕ будет сохранен. Вместо этого они будут выводиться в алфавитном порядке.
(также комментарии удалены. Я нахожу это довольно раздражающим)
т.е.: текст ввода xml <b y='xxx' x='2'>some body</b>
будет выводиться как <b x='2' y='xxx'>some body</b>
(после алфавита определяются параметры порядка)
Это означает, что при передаче оригинала и измененных файлов в систему контроля версий (например, SVN, CSV, ClearCase и т.д.) разница между этими двумя файлами может выглядеть не очень хорошо.
Ответ 3
Полезные парсеры XML Python:
- Minidom - функциональный, но ограниченный
- ElementTree - достойная производительность, большая функциональность
- lxml - высокая производительность в большинстве случаев, высокая функциональность, включая реальную поддержку xpath
Любой из них лучше, чем пытаться обновить XML файл в виде строк текста.
Что это значит для вас:
Откройте ваш файл с помощью синтаксического анализатора XML по вашему выбору, найдите интересующий вас node, замените значение, выполните сериализацию файла.
Ответ 4
Пока я согласен с Тимом и Обеном Зонном, что вы должны использовать библиотеку XML, есть способы по-прежнему манипулировать им как простым строковым объектом.
Вероятно, я бы не попытался использовать один указатель на файл для того, что вы описываете, и вместо этого прочитайте файл в памяти, отредактируйте его и запишите.
inFile = open('file.xml', 'r')
data = inFile.readlines()
inFile.close()
# some manipulation on `data`
outFile = open('file.xml', 'w')
outFile.writelines(data)
outFile.close()
Ответ 5
Что вы действительно хотите сделать, так это использовать парсер XML и добавить новые элементы с предоставленным API.
Затем просто перезапишите файл.
Самый простой в использовании, вероятно, будет парсер DOM, такой как ниже:
http://docs.python.org/library/xml.dom.minidom.html
Ответ 6
Чтобы сделать этот процесс более надежным, вы можете рассмотреть использование анализатора SAX (таким образом, вам не нужно хранить весь файл в памяти), читать и писать до конца дерева, а затем начинать добавление.
Ответ 7
Вы должны прочитать XML файл, используя определенные модули XML. Таким образом, вы можете редактировать XML-документ в памяти и переписать измененный XML-документ в файл.
Вот быстрый старт: http://docs.python.org/library/xml.dom.minidom.html
Существует множество других утилит XML, которые лучше всего зависят от характера вашего XML файла и того, каким образом вы хотите его редактировать.
Ответ 8
Как объяснил Эдам Маор, быстрый и грязный способ сделать это (для [utc-16] закодированных файлов .xml), которые вы должны не делать для резонов, которые объяснил Эдам Маор, можно сделать со следующим кодом python 2.7, если временные ограничения не позволяют вам изучать (propper) XML-анализы.
Предполагая, что вы хотите:
- Удалить последнюю строку в исходном XML файле.
- Добавить строку
- заменить строку
- Закройте корневой тег.
Он работал в python 2.7, изменяя XML файл с именем "b.xml", расположенный в папке "a" , где "a" находился в "рабочей папке" python. Он выводит новый измененный файл как "c.xml" в папку "a" , не принося при этом ошибок кодирования (для меня) в дальнейшем использовании вне python 2.7.
pattern = '<Author>'
subst = ' <Author>' + domain + '\\' + user_name + '</Author>'
line_index =0 #set line count to 0 before starting
file = io.open('a/b.xml', 'r', encoding='utf-16')
lines = file.readlines()
outFile = open('a/c.xml', 'w')
for line in lines[0:len(lines)]:
line_index =line_index +1
if line_index == len(lines):
#1. & 2. delete last line and adding another line in its place not writing it
outFile.writelines("Write extra line here" + '\n')
# 4. Close root tag:
outFile.writelines("</phonebook>") # as in:
#http://tizag.com/xmlTutorial/xmldocument.php
else:
#3. Substitue a line if it finds the following substring in a line:
pattern = '<Author>'
subst = ' <Author>' + domain + '\\' + user_name + '</Author>'
if pattern in line:
line = subst
print line
outFile.writelines(line)#just writing/copying all the lines from the original xml except for the last.