使用 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
我有两个文件夹,其中一个文件夹包含数千张图片,另一个文件夹有相应的 .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