一、XML 简介
- XML(
eXtensible Markup Language
) 指可扩展标记语言,被设计用来结构化、存储以及传输数据;它可以视为一种树结构
,必须包含根元素,该元素是所有其他元素的父元素
,所有的元素都可以有子元素
;所有的元素都可以有文本内容和属性
, 元数据(有关数据的数据)应当存储为属性,而数据本身应当存储为元素 - xml 示例图及代码如下所示:
<!--实例中的根元素是 <bookstore>。文档中的所有 <book> 元素都被包含在 <bookstore> 中。-->
<!--<book> 元素有 4 个子元素:<title>、<author>、<year>、<price>。-->
<!--XML 一个元素可以有多个属性,属性值必须加引号。-->
<!--eg: <元素名 属性名1="属性值1" 属性名2="属性值2">-->
<bookstore>
<book category="COOKING">
<title lang="en">Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price>30.00</price>
</book>
<book category="CHILDREN">
<title lang="en">Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
<book category="WEB">
<title lang="en">Learning XML</title>
<author>Erik T. Ray</author>
<year>2003</year>
<price>39.95</price>
</book>
</bookstore>
二、ElementTree 模块的导入及根节点的获取
- ET 使用
ElementTree 类
来表示整个 XML 文档,使用Element 类
来表示 XML 的一个结点 - 对
整个 XML 文档
的操作一般是在ElementTree 对象
上进行,而对XML 结点
的操作一般是对Element 对象
上进行 - 我们一般使用
Element 对象
的各种属性和方法对其结点元素
进行操作
# 导入 ElementTree 模块,python3.3 之后该模块会自动寻找可用的 C 库来加快速度
try:
import xml.etree.cElementTree as ET
except ImportError:
import xml.etree.ElementTree as ET
tree = ET.parse("example.xml") # Parses an XML section into an element tree
root = tree.getroot() # Returns the root element for this tree
三、Element 类常用属性和方法
Element 对象
的常用属性:
tag
:string 对象,表示数据代表的种类attrib
:dictionary 对象,表示附有的属性text
:string 对象,表示 element 的内容child elements
:若干子元素
<!-- xml 中的具体组织形式如下:-->
<tag attrib="hi">text</tag>
Element 对象
的常用方法:
iter(tag=None)
:遍历该 Element 所有后代,也可以指定 tag 进行遍历寻找findall(match)
:查找当前元素下 tag 或 path 能够匹配的直系节点find(match)
:查找当前元素下 tag 或 path 能够匹配的首个直系节点get(key, default=None)
:获取元素指定 key 对应的属性值,如果没有该属性,则返回default值。
四、代码实践
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
import cv2
import glob
import numpy as np
import xml.etree.ElementTree as ET
# from lxml import etree
def crop_plates(label_path, save_path):
count = 0
wrong_cnt = 0
for anno_xml in glob.glob(os.path.join(label_path, '*')):
img_path = anno_xml.replace('Label', 'Image').replace('xml', 'jpg')
try:
tree = ET.parse(anno_xml) # open xml doc
# tree = etree.parse(anno_xml) # use lxml
root = tree.getroot() # get root node
except Exception as e:
print("Error: cannot parse file: %s" % anno_xml)
wrong_cnt += 1
continue
for obj in root.iter('Plate'):
row_count = obj.find('PlateRowCount').text
plate_num = obj.find('PlateNo').text
plate_coord = obj.find('PlateCoordinate')
leftTopx = plate_coord.find('leftTopX').text
leftTopy = plate_coord.find('leftTopY').text
rightTopx = plate_coord.find('rightTopX').text
rightTopy = plate_coord.find('rightTopY').text
rightBottomx = plate_coord.find('rightBtmX').text
rightBottomy = plate_coord.find('rightBtmY').text
leftBottomx = plate_coord.find('leftBtmX').text
leftBottomy = plate_coord.find('leftBtmY').text
xmin = min(leftTopx, leftBottomx)
xmax = max(rightTopx, rightBottomx)
ymin = min(leftTopy, rightTopy)
ymax = max(leftBottomy, rightBottomy)
img = cv2.imdecode(np.fromfile(img_path, np.uint8), 1)
if row_count == '2':
img_crop = img[int(ymin): int(ymax), int(xmin): int(xmax), :]
cv2.imencode('.jpg', img_crop)[1].tofile(os.path.join(save_path, plate_num + '_' + str(count) + '.jpg'))
count += 1
print('Successfully extract %d plates!' % count)
print('Can not parse %d plates!' % wrong_cnt)
if __name__ == '__main__':
LABEL_PATH = r'E:\4_Projects\tf_in_action\2line_plate_crop\Label'
SAVE_PATH = r'E:\4_Projects\tf_in_action\2line_plate_crop\2line_plate_cropped'
crop_plates(LABEL_PATH, SAVE_PATH)
五、参考资料
1、菜鸟教程:XML
2、https://docs.python.org/2/library/xml.etree.elementtree.html#reference
3、Python 使用 ElementTree 模块来处理 XML
4、Python 标准库之 xml.etree.ElementTree
5、Python lxml教程