使用 ElementTree 将新的子元素添加到现有 XML 文件中

Adding new SubElement into existing XML file using ElementTree

我有两个文件夹,其中一个文件夹包含数千张图片,另一个文件夹有相应的 .xml 文件。 XML 文件和图像名称相同(即 2007.xml 和 2007.jpg)。 现在我想将图像名称 (2007.jpg) 添加到相应的文件 (2007.xml) 中。 .xml 文件格式为:

<?xml version='1.0' encoding='ASCII'?>
<annotation>
  <size>
    <width>1820</width>
    <height>940</height>
  </size>
  <object>
    <name>Car</name>
    <bndbox>
      <xmin>74.0</xmin>
      <ymin>509.0</ymin>
      <xmax>236.0</xmax>
      <ymax>609.0</ymax>
    </bndbox>
</annotation>  

我想添加新的子元素

<?xml version='1.0' encoding='ASCII'?>
    <annotation>
      <filename>2007.jpg</filename>
      <size>
        <width>1820</width>
        <height>940</height>
      </size>
      <object>
        <name>Car</name>
        <bndbox>
          <xmin>74.0</xmin>
          <ymin>509.0</ymin>
          <xmax>236.0</xmax>
          <ymax>609.0</ymax>
        </bndbox>
    </annotation>  

我正在尝试这样:

import xml.etree.ElementTree as ET
import os
doc = ET.parse('00390.xml')
root = doc.getroot()
s = '/image/00390.jpg'
filename = (os.path.basename(s))
userElement = ET.Element("annotation")
newSub = ET.SubElement(userElement, "filename")
newSub.set(filename, '')
root.insert(0, newSub)
tree = ET.ElementTree(root)
tree.write(open('3.xml', 'w'), encoding = 'UTF-8')

收到输出:<filename 00390.jpg=""/> 虽然输出应该是 <filename>00390.jpg</filename> 我认为问题是使用 newSub.set() 需要 3 个输入参数。

正如@mzjn 提到的,请尝试使用 Element.insert 方法。这允许您在要插入索引的确切位置指定索引。

例如,要在第二个元素之前插入:

import xml.etree.ElementTree as ET

#your tree
root = ET.fromstring('''
<element>
    <att1></att1>
    <att3></att3>
</element>
 ''')

#Create a new element
new = ET.Element('att2')
root.insert(1, new)  # <-----------Insert operaton
print(ET.tostring(root))

#output
"""
<root>
    <att1/>
    <att2/>#newly inserted 
    <att3/>
</root>
"""

编辑:

ElementTree.write 方法默认为 us-ascii 编码,因此需要打开一个用于写入二进制文件的文件:

The output is either a string (str) or binary (bytes). This is controlled by the encoding argument. If encoding is "unicode", the output is a string; otherwise, it’s binary. Note that this may conflict with the type of file if it’s an open file object; make sure you do not try to write a string to a binary stream and vice versa.

所以要么以二进制模式打开文件进行写入:

tree.write(open('person.xml', 'wb'))

或者以文本模式打开文件写入并给"unicode"作为编码:

tree.write(open('person.xml', 'w'), encoding='unicode')

新问题的更新答案

import xml.etree.ElementTree as ET
import os
doc = ET.parse('00390.xml')
root = doc.getroot()
s = '/image/00390.jpg'
filename = (os.path.basename(s))
userElement = ET.Element("annotation")
newSub = ET.SubElement(userElement, "filename")
newSub.set(filename, '')#<----- ***** 
root.insert(0, newSub)
tree = ET.ElementTree(root)
tree.write(open('3.xml', 'w'), encoding = 'UTF-8')

这将的输出 return

<filename 00390.jpg=""/>

而不是

<filename>00390.jpg</filename>

这是因为在 (*) 处您设置的是属性值而不是 XML 子元素标记中的文本。

要解决您的问题,请将此 newSub.set(filename, '') 替换为此

newSub.text = filename#Assigns text
root.insert(0,newSub)
#Returns this <filename>00390.jpg</filename>

看例子here