XML可扩展标记语言(eXtensible Markup Language),被设计用来传输和存储数据。
<?xml version="1.0" encoding="UTF-8"?>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
xml文档形成了一种树解构,它从根部开始,然后扩展到枝叶。在上面的文档中,第一行是xml的声明,定义了xml的版本和使用的编码方式。第二行描述文档的根元素(类似于本文档是一个note),接下来有4个子元素,(to,from,heading,body)。
例如下面的xml文档表示bookstore
<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>
语法结构
xml的声明中,省略关闭标签是非法的。所有元素都必须有关闭标签,类似于
。xml标签对大小写敏感,xml必须正确嵌套,xml的属性值必须加上引号。例如
<note date="12/11/2007">
<to>Tove</to>
<from>Jani</from>
</note>
xml中的字符拥有特殊的意义,xml中存在5个实体引用
- < <
- > >
- & &
- &apos ’
- " "
xml的注释语法如下,和html语法一样。
<!-- This is a comment -->
xml中空格会被保留,xml以LF存储换行。
python对xml文件解析
常见的xml编程接口有DOM和SAX,这两种接口处理xml文件方式不同。python中有三种方法解析xml,sax,dom一级ElementTree
1.SAX (simple API for XML )
Python 标准库包含 SAX 解析器,SAX 用事件驱动模型,通过在解析XML的过程中触发一个个的事件并调用用户定义的回调函数来处理XML文件。
2.DOM(Document Object Model)
将 XML 数据在内存中解析成一个树,通过对树的操作来操作XML。
3.ElementTree(元素树)
ElementTree就像一个轻量级的DOM,具有方便友好的API。代码可用性好,速度快,消耗内存少。
注:因DOM需要将XML数据映射到内存中的树,一是比较慢,二是比较耗内存,而SAX流式读取XML文件,比较快,占用内存少,但需要用户实现回调函数(handler)。
解析实例:
<collection shelf="New Arrivals">
<movie title="Enemy Behind">
<type>War, Thriller</type>
<format>DVD</format>
<year>2003</year>
<rating>PG</rating>
<stars>10</stars>
<description>Talk about a US-Japan war</description>
</movie>
<movie title="Transformers">
<type>Anime, Science Fiction</type>
<format>DVD</format>
<year>1989</year>
<rating>R</rating>
<stars>8</stars>
<description>A schientific fiction</description>
</movie>
<movie title="Trigun">
<type>Anime, Action</type>
<format>DVD</format>
<episodes>4</episodes>
<rating>PG</rating>
<stars>10</stars>
<description>Vash the Stampede!</description>
</movie>
<movie title="Ishtar">
<type>Comedy</type>
<format>VHS</format>
<rating>PG</rating>
<stars>2</stars>
<description>Viewable boredom</description>
</movie>
</collection>
xml处理子模块包括:
-
xml.etree.ElementTree: ElementTree API,一个简单而轻量级的XML处理器
-
xml.dom:DOM API 定义
-
xml.dom.minidom:最小的 DOM 实现
-
xml.dom.pulldom:支持构建部分 DOM 树
-
xml.sax:SAX2 基类和便利函数
-
xml.parsers.expat:Expat解析器绑定
ET模块解析xml文件
其中xml.etree.ElementTree模块实现了简单高效的API,可以用来解析和创建XML数据。
Element对象有下面的常用属性:
- Element.tag 标签
- Element.text,去除标签,获取标签中的内容。
例如 - Element.attrib,获取标签中的属性和属性值
- Element.findall(),找到带有标签的所有节点
- Element.append(),增加新的节点
- Element.set(),增加或者修改属性
- Element.remove(),删除节点。
- ElementTree.write()保存xml文件。
参考官方python的结构化标准处理工具XML
对于下面的示例xml文档:
<?xml version="1.0"?>
<data>
<country name="Liechtenstein">
<rank>1</rank>
<year>2008</year>
<gdppc>141100</gdppc>
<neighbor name="Austria" direction="E"/>
<neighbor name="Switzerland" direction="W"/>
</country>
<country name="Singapore">
<rank>4</rank>
<year>2011</year>
<gdppc>59900</gdppc>
<neighbor name="Malaysia" direction="N"/>
</country>
<country name="Panama">
<rank>68</rank>
<year>2011</year>
<gdppc>13600</gdppc>
<neighbor name="Costa Rica" direction="W"/>
<neighbor name="Colombia" direction="E"/>
</country>
</data>
>>> for country in root.findall('country'):
... rank = country.find('rank').text
... name = country.get('name')
... print(name, rank)
...
Liechtenstein 1
Singapore 4
Panama 68
例如下面voc标注的数据,格式为xml文件:
<annotation verified="yes">
<folder>Annotation</folder>
<filename>invoice_direction_0_0.jpg</filename>
<path>invoice_stamp-PascalVOC-export/Annotations/invoice_direction_0_0.jpg</path>
<source>
<database>Unknown</database>
</source>
<size>
<width>2962</width>
<height>1753</height>
<depth>3</depth>
</size>
<segmented>0</segmented>
<object>
<name>stamp</name>
<pose>Unspecified</pose>
<truncated>0</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>1872.3010033444816</xmin>
<ymin>1216.3294491525423</ymin>
<xmax>2370.9208472686732</xmax>
<ymax>1579.474458568738</ymax>
</bndbox>
</object><object>
<name>stamp</name>
<pose>Unspecified</pose>
<truncated>0</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>1152.4392419175028</xmin>
<ymin>123.59310263653484</ymin>
<xmax>1505.7658862876256</xmax>
<ymax>351.3840630885122</ymax>
</bndbox>
</object>
</annotation>
import xml.etree.ElementTree as ET
import os
from PIL import Image, ImageDraw, ImageFont
def parse_rec(filename):
tree = ET.parse(filename) # 解析读取xml函数
objects = []
img_dir =[]
# Element.findall()查找当前元素的直接子元素中带有指定标签的元素
# Element.find()找带有特定标签的第一个子级
# Elemtn.text 访问元素的文本内容
# Element.get 访问元素的属性。
for xml_name in tree.findall('filename'):
img_path = os.path.join(pic_path, xml_name.text)
img_dir.append(img_path)
for obj in tree.findall('object'):
obj_struct = {}
obj_struct['name'] = obj.find('name').text
obj_struct['pose'] = obj.find('pose').text
obj_struct['truncated'] = int(obj.find('truncated').text)
obj_struct['difficult'] = int(obj.find('difficult').text)
bbox = obj.find('bndbox')
obj_struct['bbox'] = [int(bbox.find('xmin').text),
int(bbox.find('ymin').text),
int(bbox.find('xmax').text),
int(bbox.find('ymax').text)]
objects.append(obj_struct)
return objects,img_dir
# 可视化目标框,并显示标签
def visualise_gt(objects,img_dir):
for id,img_path in enumerate(img_dir):
img = Image.open(img_path)
draw = ImageDraw.Draw(img)
for a in objects:
xmin =int(a['bbox'][0])
ymin =int(a['bbox'][1])
xmax =int(a['bbox'][2])
ymax =int(a['bbox'][3])
label = a['name']
draw.rectangle((xmin,ymin,xmax,ymax), fill=None, outline=(0,255,0),width=2)
draw.text((xmin-10,ymin-15), label, fill = (0,255,0),font=font) # 利用ImageDraw的内置函数,在图片上写入文字
img.show()
fontPath = "C:\Windows\Fonts\Consolas\consola.ttf" # 字体路径
root = 'F:/dataset/AQM'
ann_path = os.path.join(root, 'Annotations') # xml文件所在路径
pic_path = os.path.join(root, 'JPEGImages') # 样本图片路径
font = ImageFont.truetype(fontPath, 16)
for filename in os.listdir(ann_path):
xml_path = os.path.join(ann_path,filename)
object,img_dir = parse_rec(xml_path)
visualise_gt(object,img_dir )
180

被折叠的 条评论
为什么被折叠?



