什么是XML

XML是可扩展标记语言(Extensible Markup Language)的缩写,其中标记是关键部分。用户可以创建内容,然后使用限定标记标记它,从而使每个单词、短语或块成为可识别、可分类的信息。
标记语言从早起的私有公司和政府制定形式逐渐演变成标准通用标记语言(Standard Generalized Markup Language,SGML)、超文本标记语言(Hypertext Markup Language,HTML),并且最终演变成XML。XML有以下几个特点:

  • XML的设计宗旨是传输数据,而非显示数据
  • XML的标签没有被预定义,用户需要自行定义标签
  • XML被设计为具有自我描述性
  • XML是W3C的推荐标准

Python对XML文件的解析


常见的XML编程接口有DOM和SAX,这两种接口处理XML文件的方式不同,使用场合也不同。DOM是由W3C官方提出的标准,它会把整个XML文件读入内存,并将该文件解析成树,我们可以通过访问树的节点的方式访问XML中的标签,但是这种方法占用内存大,解析慢,如果读入文件过大,尽量避免使用这种方法。SAX是事件驱动的,通过在解析XML的过程中触发一个个的事件并调用用户自定义的回调函数来处理XML文件,速度比较快,占用内存少,但是需要用户实现回调函数,因此Python标准库的官方文档中这样介绍SAX:SAX每次只允许你查看文档的一小部分,你无法通过当前获取的元素访问其他元素。Python中提供了很多包支持XML文件的解析,如xml.dom,xml.sax,xml.dom.minidom和xml.etree.ElementTree等,本文重点介绍xml.dom.minidom。

xml.dom.minidom包

xml.dom.minidom是DOM API的极简化实现,比完整版的DOM要简单的多,而且这个包也小得多,下面以movie.xml文件为例进行操作。

  1. <collection shelf="New Arrivals">
  2. <movie title="Enemy Behind">
  3. <type>War, Thriller</type>
  4. <format>DVD</format>
  5. <year>2003</year>
  6. <rating>PG</rating>
  7. <stars>10</stars>
  8. <description>Talk about a US-Japan war</description>
  9. </movie>
  10. <movie title="Transformers">
  11. <type>Anime, Science Fiction</type>
  12. <format>DVD</format>
  13. <year>1989</year>
  14. <rating>R</rating>
  15. <stars>8</stars>
  16. <description>A schientific fiction</description>
  17. </movie>
  18. <movie title="Trigun">
  19. <type>Anime, Action</type>
  20. <format>DVD</format>
  21. <episodes>4</episodes>
  22. <rating>PG</rating>
  23. <stars>10</stars>
  24. <description>Vash the Stampede!</description>
  25. </movie>
  26. <movie title="Ishtar">
  27. <type>Comedy</type>
  28. <format>VHS</format>
  29. <rating>PG</rating>
  30. <stars>2</stars>
  31. <description>Viewable boredom</description>
  32. </movie>
  33. </collection>

然后我们调用xml.dom.minidom.parse方法读入xml文件并解析成DOM树

  1. from xml.dom.minidom import parse
  2. import xml.dom.minidom
  3.  
  4. # 使用minidom解析器打开 XML 文档
  5. DOMTree = xml.dom.minidom.parse("F:/project/Breast/codes/AllXML/aa.xml")
  6. collection = DOMTree.documentElement
  7. if collection.hasAttribute("shelf"):
  8. print("Root element : %s" % collection.getAttribute("shelf"))
  9.  
  10. # 在集合中获取所有电影
  11. movies = collection.getElementsByTagName("movie")
  12.  
  13. # 打印每部电影的详细信息
  14. for movie in movies:
  15. print("*****Movie*****")
  16. if movie.hasAttribute("title"):
  17. print("Title: %s" % movie.getAttribute("title"))
  18.  
  19. type = movie.getElementsByTagName('type')[0]
  20. print("Type: %s" % type.childNodes[0].data)
  21. format = movie.getElementsByTagName('format')[0]
  22. print("Format: %s" % format.childNodes[0].data)
  23. rating = movie.getElementsByTagName('rating')[0]
  24. print("Rating: %s" % rating.childNodes[0].data)
  25. description = movie.getElementsByTagName('description')[0]
  26. print("Description: %s" % description.childNodes[0].data)

以上程序执行结果如下:

  1. Root element : New Arrivals
  2. *****Movie*****
  3. Title: Enemy Behind
  4. Type: War, Thriller
  5. Format: DVD
  6. Rating: PG
  7. Description: Talk about a US-Japan war
  8. *****Movie*****
  9. Title: Transformers
  10. Type: Anime, Science Fiction
  11. Format: DVD
  12. Rating: R
  13. Description: A schientific fiction
  14. *****Movie*****
  15. Title: Trigun
  16. Type: Anime, Action
  17. Format: DVD
  18. Rating: PG
  19. Description: Vash the Stampede!
  20. *****Movie*****
  21. Title: Ishtar
  22. Type: Comedy
  23. Format: VHS
  24. Rating: PG
  25. Description: Viewable boredom

实战—批量修改XML文件


最近在用caffe-ssd训练比赛的数据集,但是官方给的数据集用来标记的XML文件并不是标准格式,一些标签的命名不对,导致无法正确生成lmdb文件,因此需要修改这些标签,下面用Python实现了一个批量修改XML文件的脚本。

  1. # -*- coding:utf-8 -*-
  2.  
  3. import os
  4.  
  5. import xml.dom.minidom
  6.  
  7. xml_file_path = "/home/lyz/data/VOCdevkit/MyDataSet/Annotations/"
  8. lst_label = ["height", "width", "depth"]
  9. lst_dir = os.listdir(xml_file_path)
  10.  
  11. for file_name in lst_dir:
  12. file_path = xml_file_path + file_name
  13. tree = xml.dom.minidom.parse(file_path)
  14. root = tree.documentElement #获取根结点
  15. size_node = root.getElementsByTagName("size")[0]
  16. for size_label in lst_label: #替换size标签下的子节点
  17. child_tag = "img_" + size_label
  18. child_node = size_node.getElementsByTagName(child_tag)[0]
  19. new_node = tree.createElement(size_label)
  20. text = tree.createTextNode(child_node.firstChild.data)
  21. new_node.appendChild(text)
  22. size_node.replaceChild(new_node, child_node)
  23.  
  24. #替换object下的boundingbox节点
  25. lst_obj = root.getElementsByTagName("object")
  26. data = {}
  27. for obj_node in lst_obj:
  28. box_node = obj_node.getElementsByTagName("bounding_box")[0]
  29. new_box_node = tree.createElement("bndbox")
  30. for child_node in box_node.childNodes:
  31. tmp_node = child_node.cloneNode("deep")
  32. new_box_node.appendChild(tmp_node)
  33. x_node = new_box_node.getElementsByTagName("x_left_top")[0]
  34. xmin = x_node.firstChild.data
  35. data["xmin"] = (xmin, x_node)
  36. y_node = new_box_node.getElementsByTagName("y_left_top")[0]
  37. ymin = y_node.firstChild.data
  38. data["ymin"] = (ymin, y_node)
  39. w_node = new_box_node.getElementsByTagName("width")[0]
  40. xmax = str(int(xmin) + int(w_node.firstChild.data))
  41. data["xmax"] = (xmax, w_node)
  42. h_node = new_box_node.getElementsByTagName("height")[0]
  43. ymax = str(int(ymin) + int(h_node.firstChild.data))
  44. data["ymax"] = (ymax, h_node)
  45.  
  46. for k, v in data.items():
  47. new_node = tree.createElement(k)
  48. text = tree.createTextNode(v[0])
  49. new_node.appendChild(text)
  50. new_box_node.replaceChild(new_node, v[1])
  51. obj_node.replaceChild(new_box_node, box_node)
  52.  
  53. with open(file_path, 'w') as f:
  54. tree.writexml(f, indent="\n", addindent="\t", encoding='utf-8')
  55.  
  56. #去掉XML文件头(一些情况下文件头的存在可能导致错误)
  57. lines = []
  58. with open(file_path, 'rb') as f:
  59. lines = f.readlines()[1:]
  60. with open(file_path, 'wb') as f:
  61. f.writelines(lines)
  62.  
  63. print("-----------------done--------------------")

关于writexml方法:indent参数表示在当前节点之前插入的字符,addindent表示在该结点的子节点前插入的字符

读取只包含标签的xml的更多相关文章

  1. 读取配置文件包含properties和xml文件

    读取properties配置文件 /** * 读取配置文件 * @author ll-t150 */ public class Utils { private static Properties pr ...

  2. 死磕Spring之IoC篇 - 解析自定义标签(XML 文件)

    该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读 Spring 版本:5.1. ...

  3. 19 标签:xml或者html

    1       标签:xml或者html 1.1  使用XmlSlurper解析xml groovy处理xml非常容易.XmlSlurper 类用来处理xml.在处理xml方面,还有其他的处理方式,但 ...

  4. 51Nod 1010 只包含因子2 3 5的数 Label:None

    K的因子中只包含2 3 5.满足条件的前10个数是:2,3,4,5,6,8,9,10,12,15. 所有这样的K组成了一个序列S,现在给出一个数n,求S中 >= 给定数的最小的数. 例如:n = ...

  5. 51Nod--1010 只包含235的数

    51Nod: http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1010 1010 只包含因子2 3 5的数 基准时间限制:1 ...

  6. 做参数可以读取参数 保存参数 用xml文件的方式

    做参数可以读取参数 保存参数 用xml文件的方式 好处:供不同用户保存适合自己使用的参数

  7. sql语句读取所有父子标签

    select A.HOSPITAL_ID from T_HOSPITAL A connect by prior A.HOSPITAL_ID=A.PARENT_ID start with A.HOSPI ...

  8. 只包含schema的dll生成和引用方法

    工作中,所有的tools里有一个project是只包含若干个schema的工程,研究了一下,发现创建这种只包含schema的dll其实非常简单. 首先,在visual studio-new proje ...

  9. 1007 正整数分组 1010 只包含因子2 3 5的数 1014 X^2 Mod P 1024 矩阵中不重复的元素 1031 骨牌覆盖

    1007 正整数分组 将一堆正整数分为2组,要求2组的和相差最小. 例如:1 2 3 4 5,将1 2 4分为1组,3 5分为1组,两组和相差1,是所有方案中相差最少的.   Input 第1行:一个 ...

随机推荐

  1. Druid-代码段-1-2

    所属文章:池化技术(一)Druid是如何管理数据库连接的? 本代码段对应流程1.1,责任链的执行: //DruidDataSource类里的方法:获取连接 public DruidPooledConn ...

  2. apache httpd反向代理的用法

    代理方式有三种:正向代理.透明代理和反向代理 正向代理 httpd通过ProxyRequests指令配置正向代理的功能.例如: ProxyRequests On ProxyVia On <Pro ...

  3. LeetCode解题笔记 - 3. Longest Substring Without Repeating Characters

    Given a string, find the length of the longest substring without repeating characters. Examples: Giv ...

  4. WPF (DataGridRowHeaderStyle)实现自义定行样式 并绑定数据

    原文:WPF (DataGridRowHeaderStyle)实现自义定行样式 并绑定数据 功能阐述 就上面那图片 刚开始 考虑使用 RowHeaderTemplate 来实现  发现总绑定不上数据  ...

  5. <Math> 29 365

    29. Divide Two Integers class Solution { public int divide(int dividend, int divisor) { if(dividend ...

  6. .NET Core 序列化对象输出字节数大小比较

    写代码验证了一下 .NET Core 中序列化对象输出字节数大小,.NET Core 版本是 3.0.100-preview8-013656 ,对象属性使用了 Guid 与 DateTime 类型,胜 ...

  7. JDBC释放数据库连接

    try(){}写法会自动关闭连接 String sql = "select password from user where name = ?"; try(Connection c ...

  8. CentOS 7 firewalld详解,添加删除策略

    一.CentOS7中firewall防火墙 修改防火墙配置文件之前,需要对之前防火墙[/etc/firewalld/zones/public.xml]做好备份 重启防火墙后,需要确认防火墙状态和防火墙 ...

  9. c# Winform 继承窗体 无法拖动修改控件大小

    问题描述: 一个窗体集成父窗体,发现无法直接拖动修改的控件,比如修改大小等 特征: 不禁使父窗体控件,就算新加一个控件也会这样:鼠标放到控件移动手方块上会出现一个“继承的控件”的tooptip, 异常 ...

  10. String substring(int start,int end)截取当前字符串中指定范围内的字符串

    package seday01;/** * String substring(int start,int end) * 截取当前字符串中指定范围内的字符串. * java api有一个特点:通常用两个 ...