我有一个XML文档,我想在它已经包含数据后更新。
我考虑过以"a"
(追加)模式打开XML文件。问题是新数据将在根关闭标记之后写入。
如何删除文件的最后一行,然后从该点开始写入数据,然后关闭根标记?
当然我可以阅读整个文件并进行一些字符串操作,但我认为这不是最好的主意..
感谢您的时间。
答案 0 :(得分:55)
使用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')
注意:输出写入file_new.xml
供您进行试验,写回file.xml
将替换旧内容。
重要信息:ElementTree库在dict中存储属性,因此,不会保留xml文本中列出这些属性的顺序。相反,它们将按字母顺序输出。 (同样,评论被删除。我发现这很烦人)
ie:xml输入文本<b y='xxx' x='2'>some body</b>
将输出为<b x='2' y='xxx'>some body</b>
(在定义订单参数字母后)
这意味着在将原始文件和更改的文件提交到版本控制系统(例如SVN,CSV,ClearCase等)时,两个文件之间的差异可能看起来不太漂亮。
答案 1 :(得分:20)
有用的Python XML解析器:
其中任何一个都比尝试将XML文件更新为文本字符串更好。
这对您意味着什么:
使用您选择的XML解析器打开您的文件,找到您感兴趣的节点,替换该值,然后将文件序列化。
答案 2 :(得分:6)
您绝对不应该(见下文)的快速简便方法是使用readlines()
将整个文件读入字符串列表。我写这个是为了快速简便的解决方案是你正在寻找的。 p>
只需使用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)
你不应该这样做的原因是,除非你正在做一些非常快速的事情,否则你应该使用XML解析器。这是一个库,允许您使用DOM,树和节点等概念智能地处理XML。这不仅是使用XML的正确方法,它也是标准方法,使您的代码更易于移植,并且更容易让其他程序员理解。
蒂姆的回答提到为此目的检查xml.dom.minidom
,我认为这是个好主意。
答案 3 :(得分:2)
虽然我同意Tim和Oben Sonne你应该使用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()
答案 4 :(得分:1)
您真正想要做的是使用XML解析器并使用提供的API附加新元素。
然后只是覆盖文件。
最容易使用的可能是DOM解析器,如下所示:
答案 5 :(得分:1)
为了使这个过程更加健壮,您可以考虑使用SAX解析器(这样您就不必将整个文件保存在内存中),read&amp;写到树的末尾,然后开始追加。
答案 6 :(得分:1)
对于修改,您可以使用xml中的tag.text
。这是代码段:
import xml.etree.ElementTree as ET
tree = ET.parse('country_data.xml')
root = tree.getroot()
for rank in root.iter('rank'):
new_rank = int(rank.text) + 1
rank.text = str(new_rank)
tree.write('output.xml')
代码中的rank
是标记的示例,它取决于您的XML文件内容。
答案 7 :(得分:0)
您应该使用特定的XML模块读取XML文件。这样,您就可以在内存中编辑XML文档,并将更改后的XML文档重写到文件中。
这是一个快速入门:http://docs.python.org/library/xml.dom.minidom.html
还有很多其他XML实用程序,其中一个最好取决于XML文件的性质以及编辑它的方式。
答案 8 :(得分:0)
正如Edan Maor所解释的那样,快速而肮脏的方式(对于[utc-16]编码的.xml文件),你应该不为Edam Maor解释的那些文件所做的那样,可以做到使用以下python 2.7代码,以防时间限制不允许您学习(propper)XML解析。
假设你想:
它在python 2.7中修改名为&#34; b.xml&#34;的.xml文件。位于文件夹&#34; a&#34;,其中&#34; a&#34;位于&#34;工作文件夹&#34; python。它将新修改的文件输出为&#34; c.xml&#34;在文件夹&#34; a&#34;中,在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.