【问题标题】:How to update/modify an XML file in python?如何在 python 中更新/修改 XML 文件?
【发布时间】:2010-12-08 04:11:01
【问题描述】:

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

我考虑过以"a"(附加)模式打开 XML 文件。问题是新数据会写在根结束标记之后。

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

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

感谢您的宝贵时间。

【问题讨论】:

  • “我当然可以读取唯一的文件和字符串操作” - 我不确定我是否理解最后一部分,请您改写一下吗?

标签: python xml io


【解决方案1】:

使用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 文本中列出的顺序将不会被保留。相反,它们将按字母顺序输出。 (另外,cmets 也被移除了。我觉得这很烦人)

即:xml输入文本&lt;b y='xxx' x='2'&gt;some body&lt;/b&gt;将输出为&lt;b x='2' y='xxx'&gt;some body&lt;/b&gt;(按字母顺序排序参数定义后)

这意味着在将原始文件和更改文件提交到修订控制系统(例如 SVN、CSV、ClearCase 等)时,这两个文件之间的差异可能看起来不太好。

【讨论】:

  • 我使用 python2,当我打开一个 xml 并写入另一个标签时,所有标签都更改为一个新标签 ns0:previoustag 为什么?
  • ns0 看起来像一个命名空间,阅读 docs.python.org/2/library/…
  • python 3.6+ 现在保留字典顺序。
【解决方案2】:

有用的 Python XML 解析器:

  1. Minidom - 功能有限
  2. ElementTree - 不错的性能,更多的功能
  3. lxml - 高性能在大多数情况下,包括真正的 xpath 支持在内的高性能

其中任何一个都比尝试将 XML 文件更新为文本字符串更好。

这对你意味着什么:

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

【讨论】:

    【解决方案3】:

    您绝对不应该这样做(见下文)的快速简便的方法是使用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 的正确方式,而且还是标准方式,使您的代码更加可移植,并且更易于其他程序员理解。

    Tim 的回答提到为此目的检查 xml.dom.minidom,我认为这将是一个好主意。

    【讨论】:

    • 在不使用任何解析器的情况下编辑 XML 是一种巨大的代码气味。我不得不解决其他发布执行此操作的软件的问题,这是一个可怕的组合。如果是 XML,那么 XML 具有某些应该遵守的属性——比如能够使用空格——移动标签但保持 XML 的相同语义,或者添加 XML cmets。结果程序变得脆弱,很可能首先失败。不要这样做!
    【解决方案4】:

    虽然我同意 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()
    

    【讨论】:

      【解决方案5】:

      您真正想做的是使用 XML 解析器并使用提供的 API 附加新元素。

      然后简单地覆盖文件。

      最容易使用的可能是像下面这样的 DOM 解析器:

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

      【讨论】:

        【解决方案6】:

        为了使这个过程更加健壮,您可以考虑使用 SAX 解析器(这样您就不必将整个文件保存在内存中),读取和写入到树的末尾,然后开始追加。

        【讨论】:

          【解决方案7】:

          对于修改,您可以使用xml 中的tag.text。这是sn-p:

          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文件内容。

          【讨论】:

            【解决方案8】:

            您应该使用特定的 XML 模块读取 XML 文件。这样您就可以在内存中编辑 XML 文档并将更改的 XML 文档重写到文件中。

            这是一个快速入门:http://docs.python.org/library/xml.dom.minidom.html

            还有很多其他 XML 实用程序,哪一种最好取决于您的 XML 文件的性质以及您希望以何种方式对其进行编辑。

            【讨论】:

              【解决方案9】:

              正如 Edan Maor 解释的那样,快速而肮脏的方法(对于 [utc-16] 编码的 .xml 文件),你应该按照 Edam Maor 解释的原因去做,可以做到如果时间限制不允许您学习(正确的)XML 解析,请使用以下 python 2.7 代码。

              假设你想:

              1. 删除原始 xml 文件中的最后一行。
              2. 添加一行
              3. 替换一行
              4. 关闭根标签。

              它在 python 2.7 中工作,修改位于文件夹“a”中名为“b.xml”的 .xml 文件,其中“a”位于 python 的“工作文件夹”中。它将新修改的文​​件输出为文件夹“a”中的“c.xml”,在 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.
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2010-09-05
                • 1970-01-01
                • 1970-01-01
                • 2022-06-23
                • 1970-01-01
                相关资源
                最近更新 更多