1. 什么是 XML?
XML 指可扩展标记语言(EXtensible Markup Language)。
a.
XML 是一种很像HTML的标记语言。
b.
XML 的设计宗旨是传输数据,而不是显示数据
。
c.
XML 标签没有被预定义。您需要自行定义标签。
d.
XML 被设计为具有自我描述性。
e.
XML 是 W3C 的推荐标准。
2. XML 和 HTML 之间的差异
XML 不是 HTML 的替代
。
a.
XML 和 HTML 为不同的目的而设计:
b.
XML 被设计用来传输和存储数据,其焦点是数据的内容。
c.
HTML 被设计用来显示数据,其焦点是数据的外观。
d.
HTML 旨在显示信息,而 XML 旨在传输信息。
3. 通过 XML 可以自定义标签
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
上面实例中的标签没有在任何 XML 标准中定义过(比如 <to>
和 <from>
)。这些标签是由 XML 文档的创作者发明的
。
这是因为 XML 语言没有预定义的标签
。HTML 中使用的标签都是预定义的。HTML 文档只能使用在 HTML 标准中定义过的标签(如 <p>
、<h1>
等等)。XML 允许创作者定义自己的标签和自己的文档结构
。
4. python中对XML的解析
XML比JSON复杂,在Web中应用也不如以前多了,不过仍有很多地方在用,所以,有必要了解如何操作XML。
python有三种方法解析XML,SAX
,DOM
,以及 ElementTree
。
本篇中使用到的XML实例文件如下:movies.xml
。
# movies.xml
<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>
5. 使用 SAX方式 解析 xml
SAX 是一种基于事件驱动
的API。
利用 SAX 解析 XML 文档牵涉到两个部分: 解析器
和事件处理器
。
解析器
:负责读取 XML 文档,并向事件处理器发送事件
,如元素开始跟元素结束事件。
事件处理器
:负责对事件作出响应,对传递的 XML 数据进行处理
。
(1) 对大型文件进行处理;
(2) 只需要文件的部分内容,或者只需从文件中得到特定信息;
(3) 想建立自己的对象模型的时候。
在 python 中使用 SAX 方式
处理 xml 要先引入 xml.sax 中的 parse
函数,还有 xml.sax.handler 中的 ContentHandler
。
import xml.sax
class MovieHandler(xml.sax.ContentHandler):
def __init__(self):
self.CurrentData = ""
self.type = ""
self.format = ""
self.year = ""
self.rating = ""
self.stars = ""
self.description = ""
# 元素开始调用 => 遇到XML开始标签时调用, tag是标签的名字, attributes是标签的属性字典值
def startElement(self, tag, attributes):
self.CurrentData = tag
if tag == "movie":
print('')
print("Title:", attributes["title"])
# 元素结束调用 => 遇到XML结束标签时调用
def endElement(self, tag):
if self.CurrentData == "type":
print("Type:", self.type)
elif self.CurrentData == "format":
print("Format:", self.format)
elif self.CurrentData == "year":
print("Year:", self.year)
elif self.CurrentData == "rating":
print("Rating:", self.rating)
elif self.CurrentData == "stars":
print("Stars:", self.stars)
elif self.CurrentData == "description":
print("Description:", self.description)
self.CurrentData = ""
# 读取字符时调用
def characters(self, content):
if self.CurrentData == "type":
self.type = content
elif self.CurrentData == "format":
self.format = content
elif self.CurrentData == "year":
self.year = content
elif self.CurrentData == "rating":
self.rating = content
elif self.CurrentData == "stars":
self.stars = content
elif self.CurrentData == "description":
self.description = content
if __name__ == "__main__":
# 创建一个 XMLReader
parser = xml.sax.make_parser()
# 关闭命名空间
parser.setFeature(xml.sax.handler.feature_namespaces, 0)
# 重写 ContextHandler
parser.setContentHandler(MovieHandler())
# 解析xml文档
parser.parse("movies.xml")
6. 使用 DOM方式 解析 xml
文件对象模型
(Document Object Model,简称DOM
),是W3C组织推荐的处理可扩展置标语言的标准编程接口。
一个 DOM 的解析器在解析一个XML文档时,一次性读取整个文档
,把文档中所有元素保存在内存中的一个树结构里,之后你可以利用DOM 提供的不同的函数来读取或修改文档的内容和结构,也可以把修改过的内容写入xml文件。
DOM会把整个XML读入内存,解析为树
,因此占用内存大,解析慢,优点是可以任意遍历树的节点。
在 python 中使用 DOM 方式
处理 xml 则要通过 xml.dom.minidom
来解析 xml 文件。
import xml.dom.minidom
if __name__ == "__main__":
# 使用minidom解析器打开XML文档
DOMTree = xml.dom.minidom.parse("movies.xml")
collection = DOMTree.documentElement
if collection.hasAttribute("shelf"):
print("Root element : %s" % collection.getAttribute("shelf"))
# 在集合中获取所有电影(整个movie节点项)
movies = collection.getElementsByTagName("movie")
# 打印每部电影的详细信息
for movie in movies:
print('')
if movie.hasAttribute("title"):
print("Title: %s" % movie.getAttribute("title"))
type = movie.getElementsByTagName('type')[0]
print("Type: %s" % type.childNodes[0].data)
format = movie.getElementsByTagName('format')[0]
print("Format: %s" % format.childNodes[0].data)
rating = movie.getElementsByTagName('rating')[0]
print("Rating: %s" % rating.childNodes[0].data)
description = movie.getElementsByTagName('description')[0]
print("Description: %s" % description.childNodes[0].data)
7. 使用 ElementTree方式 解析xml
xml.etree.ElementTree(简称ET)模块提供了一个轻量级、Pythonic的API,同时还有一个高效的C语言实现,即xml.etree.cElementTree。与DOM相比,ET的速度更快,API使用更直接、方便
。与SAX相比,ET.iterparse函数同样提供了按需解析的功能,不会一次性在内存中读入整个文档
。ET的性能与SAX模块大致相仿,但是它的API更加高层次,用户使用起来更加便捷
。
Element类型是一种灵活的容器对象,用于在内存中存储结构化数据。
[注意] xml.etree.ElementTree模块在应对恶意结构数据时显得并不安全。
每个element对象都具有以下属性:
1. tag:string对象,表示数据代表的种类。
2. attrib:dictionary对象,表示附有的属性。
3. text:string对象,表示element的内容。
4. tail:string对象,表示element闭合之后的尾迹。
<tag attrib1=1>text</tag>tail
1 2 3 4
import xml.etree.ElementTree as ET
tree = ET.parse('movies.xml')
root = tree.getroot()
# print(root.tag, ',', root.attrib) # 打印根元素标签及属性
# child就是movie结点
# children是moive结点的项item
for Node in root.findall("movie"):
print('')
for item in Node:
print(item.tag, ':', item.text)
8. 写在最后
更多详细API及demo请参考官网网站:
https://docs.python.org/3.9/library/markup.html#structured-markup-processing-tools