XML基础知识
XML 全称可扩展标记语言,是一种用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型。
XML 的声明
XML 文档的声明是可选的,如果要声明,需要将其放在文档的第一行最顶端。
<?xml version="1.0" encoding="utf-8"?>
以上定义了 XML 的版本1.0和所使用的编码utf-8。
元素
XML 元素指的是 XML 文件中出现的标签,一个标签分为开始标签和结束标签,结束标签与开始标签名称相同,只是要在前面加一个斜杠/,比如:
<hello></hello>
<to></to>
一个标签中也可以嵌套其他的若干个子标签。但所有的标签必须合理的嵌套,绝不允许交叉嵌套。
格式良好的 XML 文档必须有且仅有一个根元素,其他的元素都是这个元素的子孙元素。
元素的命名规则:
- 名称可以包含字母、数字以及其他的字符
- 名称不能以数字或者标点符号开始
- 名称不能以字母 xml(或者 XML、Xml 等等)开始
- 名称不能包含空格
- 名称是大小写敏感的
XML 没有保留字,元素名称可以任意使用。
属性
一个元素可以有多个属性,每个属性都有它自己的名称和取值。同一个元素下,属性名称不能重复。属性的值一定要用双引号或者单引号括起来,比如:
<date year="2018" month="7" day="28"></date>
属性的命名规范和元素的命名规范一样。
注释
XML 文件中注释采用:<!--注释内容-->
这样的格式,注释没有结束标签,不能嵌套。
使用SAX库解析XML
解析器
解析器负责读取 XML 文档,并向事件处理器发送事件,比如元素开始跟元素结束事件。
SAX提供了两个函数:parse
和parseString
。前者用于从文件中解析 XML 数据,后者用于从字符串中解析 XML 数据。
两个函数的声明如下:
xml.sax.parse( xmlfile, contenthandler)
xml.sax.parseString(xmlstring, contenthandler)
parse函数的第一个参数是 XML 文件的路径,比如:
xml.sax.parse("test.xml",contenthandler)
parseString函数的第一个参数是,含有 XML 数据的字符串,比如:
data = "<data>Hello</data>"
xml.sax.parseString(data,contenthandler)
而它们的第二个参数则是事件处理器。
事件处理器
事件处理器则负责对事件作出响应,对传递的 XML 数据进行处理。
一个事件处理器必须是ContentHandler类型的子类,通过重写父类的以下函数来响应解析器的事件请求:
cha\fracters(content)
函数,它会在以下时机被调用:- 如果从一行开始,遇到标签之前,存在字符,则
content
的值为这些字符串; - 如果从一个标签,遇到下一个标签之前,存在字符,则
content
的值为这些字符串; - 如果从一个标签,遇到行结束符(换行符)之前,存在字符,则
content
的值为这些字符串; - 标签可以是开始标签,也可以是结束标签。
- 如果从一行开始,遇到标签之前,存在字符,则
startDocument()
函数,它在文档启动的时候调用;endDocument()
函数,它在解析器到达文档结尾时调用;startElement(name, attrs)
函数,它在遇到 XML 开始标签时调用,name
是标签的名字,attrs
是标签的属性值字典;endElement(name)
函数,它在遇到 XML 结束标签时调用。
使用ElementTree解析XML
ElementTree
xml.etree.ElementTree
模块是一个轻量级的 DOM(文件对象模型),具有方便友好的 API。代码可用性好,速度快,消耗内存少。
ElementTree模块大致可以三部分:ElementTree类,Element类以及一些操作 XML 的函数。
解析
xml.etree.ElementTree
提供了两个函数:parse
和fromstring
,用于从文件和字符串解析 XML 数据。
parse
函数返回一个ElementTree对象,fromstring
返回一个Element对象。
Element对象代表一个 XML 元素。ElementTree对象代表一个 XML 文档,它提供了函数getroot,来获取一个文档的根元素。
查找元素
Element对象和ElementTree对象都提供了用于在子元素查找元素的函数:
- find(name):用于在直接子元素中,查找一个名为name的元素;
- findall(name):用于在直接子元素中,查找所有名为name的元素,它的返回值可以看做一个所有元素都是Element对象的tuple对象,可以对它进行迭代操作或者索引[]操作;
- iter(name = None):用于在当前元素下的所有子元素中,查找名为name的元素,如果不指定name,则返回所有子元素。它返回一个迭代器对象。
获取元素的文本与属性值
Element有一个属性text,这个属性用于获取直接在这个元素的开始、结束标志之间的文本。如果没有文本,则返回空字符串。
如果要获取一个元素的某个属性,可以使用get(name)函数,它会寻找当前元素上名为name的属性。如果找到就返回这个属性的值,没找到则返回空字符串。