如何在python中更新/修改XML文件?

时间:2009-10-19 22:52:31

标签: python xml io

我有一个XML文档,我想在它已经包含数据后更新。

我考虑过以"a"(追加)模式打开XML文件。问题是新数据将在根关闭标记之后写入。

如何删除文件的最后一行,然后从该点开始写入数据,然后关闭根标记?

当然我可以阅读整个文件并进行一些字符串操作,但我认为这不是最好的主意..

感谢您的时间。

9 个答案:

答案 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解析器:

  1. Minidom - 功能齐全但
  2. ElementTree - 性能不错,功能更强大
  3. lxml - 大多数情况下的高性能 ,包括真正的xpath支持在内的高性能
  4. 其中任何一个都比尝试将XML文件更新为文本字符串更好。

    这对您意味着什么:

    使用您选择的XML解析器打开您的文件,找到您感兴趣的节点,替换该值,然后将文件序列化。

答案 2 :(得分:6)

您绝对不应该(见下文)的快速简便方法是使用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)

你不应该这样做的原因是,除非你正在做一些非常快速的事情,否则你应该使用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解析器,如下所示:

http://docs.python.org/library/xml.dom.minidom.html

答案 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解析。

假设你想:

  1. 删除原始xml文件中的最后一行。
  2. 添加一行
  3. 替换一行
  4. 关闭根标记。
  5. 它在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.