使用 ElementTree 解析 XML 文件

一、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教程

猜你喜欢

转载自blog.csdn.net/mzpmzk/article/details/80887967