xml解析
一、xml简介
XML 被设计用来传输和存储数据。
HTML 被设计用来显示数据。
1).什么是xml
- XML 指可扩展标记语言(EXtensible Markup Language)。
- XML 是一种很像HTML的标记语言。
- XML 的设计宗旨是传输数据,而不是显示数据。
- XML 标签没有被预定义。您需要自行定义标签。
- XML 被设计为具有自我描述性。
- XML 是 W3C 的推荐标准。
2).xml和html的区别
XML 不是 HTML 的替代。
XML 和 HTML 为不同的目的而设计:
- XML 被设计用来传输和存储数据,其焦点是数据的内容。
- HTML 被设计用来显示数据,其焦点是数据的外观。
HTML 旨在显示信息,而 XML 旨在传输信息。
***
XML 被设计用来结构化、存储以及传输信息。所以XML 不会做任何事情。
XML 语言没有预定义的标签。所以我们可以自定义标签,注意,尽量不定义关键字标签。
XML是对HTML的补充,但不是HTML的替代,在大多数 Web 应用程序中,XML 用于传输数据,而 HTML 用于格式化并显示数据。
XML 是独立于软件和硬件的信息传输工具。
python对XML的解析
常见的XML编程接口有DOM和SAX,这两种接口处理XML文件的方式不同,当然使用场合也不同。
python有三种方法解析XML,SAX,DOM,以及ElementTree:
方法 | 特点 |
SAX | SAX解析通过流模式在解析XML的过程中触发对应的事件(start_element、char_data、end_element)并调用用户定义的回调函数来处理XML文件。 |
DOM | 将XML数据在内存中解析成一个树,通过对树的操作来操作XML,占用内存大,解析速度较慢,优点是可以任意遍历树的节点。 |
ElementTree | 类似一个轻量级的DOM |
我们先使用ElementTree解析一个XML文件,文件如下:
<?xml version="1.0" encoding='utf-8'?> #申明为XML <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>
解析代码如下:
#usr/bin/python #-*-coding:utf-8-*- import xml.etree.ElementTree as ET ''' tag ,即标签,用于标识该元素表示哪种数据,即APP_KEY attrib,即属性,用Dictionary形式保存,即{'channel'='CSDN'} text ,文本字符串,可以用来存储一些数据,即hello123456789 ''' #先加载文档到内存里,形成一个倒桩的树结构 tree = ET.parse('huihui.xml') #获取根节点 root = tree.getroot() huihui={} for ele in root: value=[] for e in ele: if e.text is None: value.append(e.attrib) else: value.append({e.tag:e.text}) huihui[ele.attrib['name']]=value print(huihui)
上述代码我们先引用了一个xml.etree.ElementTree库,并另取名ET,然后加载文档到tree内存中,形成一个倒桩的树结构,然后我们获取了文本的根节点root。建立一个for循环,让ele遍历root,得到根节点(即country),然后再使e遍历ele,获取到子节点,再进行判断,子节点中是否存在文本,如果不存在,在value列表中追加子节点的属性,如果存在,则以tag为key,以text为value的字典模式追加到value的列表中,最后我们以ele的属性名为key,对应的value列表为value放在字典huihui中,输出huihui。
我们还可以查找需要的根/子节点,并修改,如下:
#仍以上述为模板 nodes=root.findall('country') for node in nodes: if node.attrib['name']=='Liechtenstein': root.remove(node) tree.write('huihuihui.xml') print('删除成功')
首先获取root中名为'country'的根节点,然后循环遍历,寻找属性名为'liechtenstein'的子节点,找到之后将其删除。
下面我们使用SAX解析XML
SAX是事件驱动的XML解析的标准接口。 使用SAX解析XML通常需要通过子类化xml.sax.ContentHandler来创建自己的ContentHandler。
ContentHandler处理XML样式/风格的特定标签和属性。 ContentHandler对象提供了处理各种解析事件的方法。它拥有的解析器在解析XML文件时调用ContentHandler方法。
在XML文件的开头和结尾分别调用:startDocument和endDocument方法。 characters(text)方法通过参数text传递XML文件的字符数据。
ContentHandler在每个元素的开头和结尾被调用。如果解析器不在命名空间模式下,则调用startElement(tag,attributes)和endElement(tag)方法; 否则,调用相应的方法startElementNS和endElementNS方法。 这里,tag是元素标签,属性是Attributes对象。
我们使用如下一个XML实践:
<?xml version="1.0" encoding="utf-8" ?> <collection shelf = "New Arrivals"> <movie title = "Enemy Behind"> <type>War, Thriller</type> <format>DVD</format> <year>2013</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>
代码如下:
#usr/bin/python #-*-coding:utf-8-*- import xml.sax #首先引用xml.sax库 class MovieHandler(xml.sax.ContentHandler): #创建一个类 def __init__(self): self.CurrentData = "" self.type = "" self.format = "" self.year = "" self.rating = "" self.stars = "" self.description = "" def startElement(self, tag, attributes): self.CurrentData = tag if tag == "movie": print("*****Movie*****") title = attributes["title"] print("Title:", title) 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 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 = "" if (__name__ == "__main__"): # 1 创建一个XMLReader parser = xml.sax.make_parser() # 2关闭命名空间 namepsaces工作目录 工作空间 命名空间 parser.setFeature(xml.sax.handler.feature_namespaces, 0) # 3 覆盖默认的 ContextHandler Handler = MovieHandler() parser.setContentHandler(Handler) # 设置当前的ContentHandler为我们自己写的handler实例。 #parse() 加载 parser.parse("movie.xml") #上述的xml存储在movie.xml中
我们先创建一个类,然后初始化参数(根据要解析的xml中的参数),使用startElement,将获取到的值赋值给CurrentDate,然后判断CurrentDate的值是否为movie,如果是,打印一个*****movie*****,并给title赋值获取节点的属性名,在打印出来。如果值不为movie,则依次判断CurrentDate的值为哪个参数,判断到了,则赋值给那个参数,然后在endElement中将对应的值打印,最后再清除CurrentDate的值,然后继续循环下一个节点,所以整个类是将XML中每一个节点都查找一遍,根据对应的值将其打印的模式进行。最终输出一下结果:
*****Movie***** Title: Enemy Behind Type: War, Thriller Format: DVD Year: 2013 Rating: PG Stars: 10 Description: Talk about a US-Japan war *****Movie***** Title: Transformers Type: Anime, Science Fiction Format: DVD Year: 1989 Rating: R Stars: 8 Description: A schientific fiction *****Movie***** Title: Trigun Type: Anime, Action Format: DVD Rating: PG Stars: 10 Description: Vash the Stampede! *****Movie***** Title: Ishtar Type: Comedy Format: VHS Rating: PG Stars: 2 Description: Viewable boredom