文章目录
前言
网上有许多Python 一键批量将 csv 文件转化成 xml 文件。本来想用随便搜一些博主的代码直接用的,但实际并没有那么顺利>﹏<。看了好多文章都是批量将***.csv转为***.xml。可我需要将一个csv每一行转为多个xml文件,emmm虽然如出一辙,但我还是要花了一下午学了一下如何写xml文件。我先将csv文件读入到list中在操作,如何读入写入csv请看上一篇博文
一、基于xml.dom.minidom模块实现创建一个XML文档。
1.引入库
import os
import xml.dom.minidom
2.创建一个文件夹,用来保存转换后的xml文件
# 创建一个文件夹 用来保存转换后的xml文件
path = os.path.join('xml_file')#其实直接赋值路径也是可以的哈哈
if not os.path.exists(path):#判断括号里的文件是否存在,如果存在返回True
os.mkdir(path)#创建目录也就是文件夹
3.创建XML的过程
def csv_to_xml(file_list):#我这里将csv文件的每一行做成list传入的函数中
rename = file_list[1][:5]#提取其中一部分可以给xml文件命名
xml_path=path+'\\'+rename+'.xml'
doc = xml.dom.minidom.Document() #在内存中创建一个空的文档
root_node = doc.createElement('annotation') #创建一个根节点annotation对象
root_node.setAttribute('object', 'coordinate') #设置根节点的属性
root_node.setAttribute('虫子', '坐标')
doc.appendChild(root) #将根节点添加到文档对象中
branch_node=doc.createElement('object')#创建一个分支
folder_node = doc.createElement('name')#创建一个叶子节点
folder_value = doc.createTextNode(file_list[3])
folder_node.appendChild(folder_value)#给叶子节点name设置一个文本节点,用于显示文本内容
branch_node.appendChild(folder_node)#将叶子节点添加到object分支
root_node.appendChild(branch_node)#将分支添加到根节点
#添加位置信息和上面一样的步骤
folder_node_total= doc.createElement('bndbox')
branch_node.appendChild(folder_node_total)
current_number = 0
coordinate=['xmin','ymin','xmax','ymax']
while current_number < 4:
folder_node = doc.createElement(coordinate[current_number])
folder_value = doc.createTextNode(file_list[current_number+6])
folder_node.appendChild(folder_value)
folder_node_total.appendChild(folder_node)
current_number = current_number + 1
with open(xml_path,"w", encoding="utf-8") as f:
doc.writexml(f, indent='', addindent='\t', newl='\n', encoding="utf-8")
# doc.writexml()第一个参数是目标文件对象,第二个参数是根节点的缩进格式,第三个参数是其他子节点的缩进格式, 第四个参数制定了换行格式,第五个参数制定了xml内容的编码。
# fp = open(xml_path, 'w',encoding="utf-8")
# doc.writexml(fp, indent='', addindent='\t', newl='\n', encoding="utf-8")
通过open()打开也可以读写,运行结果如下
二、基于ElementTree增加xml文件节点
1.引入库
import os
from xml.etree.ElementTree import Element, ElementTree
2.增加xml文件节点
将csv写入xml文件时,发现如果xml已经存在,再写入的话就会将原来存在的xml给覆盖掉,真是令人费解的问题。我就在想能不能直接在原来xml的基础上增加节点,其实基于xml.dom.minidom模块可以增加节点,嘿嘿,可谁让我这么好学呢,看了一下基于ElementTree写也挺简单的
#但这样写入会有个问题,写入的XML会在同一行,缺少换行符,Etree本身并没有提供换行的选项,看了网上大神的回答,对root处理以后,再次写入将有换行符。
def __indent(e, level=0):
if len(e) > 0:
e.text = '\n' + '\t' * (level + 1)
child = None
for child in e:
__indent(child, level + 1)
child.tail = child.tail[:-1]
e.tail = '\n' + '\t' * level
网上两个加换行符的,选择用其中一个就可以了
def __indent(elem, level=0):
i = "\n" + level*"\t"
if len(elem):
if not elem.text or not elem.text.strip():
elem.text = i + "\t"
if not elem.tail or not elem.tail.strip():
elem.tail = i
for elem in elem:
__indent(elem, level+1)
if not elem.tail or not elem.tail.strip():
elem.tail = i
else:
if level and (not elem.tail or not elem.tail.strip()):
elem.tail = i
def if_xml_exist(file_list):
rename = file_list[1][:5]#提取其中一部分可以给xml文件命名
xml_path=path+'\\'+rename+'.xml'
if (os.path.exists(xml_path)):如果新命名的xml文件已经存在就追加写入xml文件中
tree=ElementTree()#遍历整个文档树用ElementTree,遍历单独的节点或者子节点用Element
tree.parse(xml_path) #打开xml文件
root_node=tree.getroot()#获取根节点
element=Element('object')#创建第一个分支#element=Element('object',{}) #{}里面是字典,还可以给节点添加属性
folder_node=Element('name')#创建第二个分支
folder_node.text=file_list[3]#写入第二分支的值
element.append(folder_node)将第二分支加入到第一个分支
folder_node_all_location=Element('bndbox')##添加位置信息和上面一样的步骤
element.append(folder_node_all_location)
current_number = 0
coordinate=['xmin','ymin','xmax','ymax']
while current_number < 4:
folder_node_location =Element(coordinate[current_number])
folder_node_location.text = file_list[current_number + 6]
folder_node_all_location.append(folder_node_location)
current_number = current_number + 1
root_node.append(element)
__indent(root_node)
tree.write(xml_path, encoding='utf-8', xml_declaration=True)a
三、基于ElementTree修改xml文件节点
在目标检测对图片打标签时,不小心打错了标签的’name’,如果从新再来就太浪费时间,就想着应该可以直接批量修改xml的节点内容,有点懒>︿<,基于xml.dom.minidom模块不想写了,下次我遇到在更新吧
from xml.etree.ElementTree import Element, ElementTree
import os
list=[]
file_path='存放xml文件的路径'
all_xml_file = os.listdir(file_path)
for xml_file in all_xml_name:
xml_path=file_path+'\\'+xml_file
tree=ElementTree()
tree.parse(xml_path)
root_node=tree.getroot()
# root_node.findall可将根节点所有'object'存放到list
# root_node.find只返回根节点的第一个'object'
branch_node=root_node.findall('object')
for branch in branch_node:
folder_node=branch.find('name') # 找到打错标签的'name'
folder_node.text = insect_name # 修改标签内容
tree.write(xml_path, encoding='utf-8', xml_declaration=True)