- Xml简介
➢XML指可扩展标记语言(Extensible Markup Language)
➢XML被设计用于结构化、存储和传输数据
➢XML是一种标记语言,很类似于HTML
➢XML没有像HTML那样具有预定义标签,需要程序员自定义标签。
➢XML被设计为具有自我描述性,并且是W3C的标准
- Xml文档树结构
XML文档形成了一种树结构,它从“ 根部” 开始,然后扩展到“ 树
枝” 。
XML文档必须包含根元素,该元素是所有其他元素的父元素,文档中的所有元素形成了一棵文档树,这课树从根开始,并扩展到树的最顶端,并且所有的元素都可以有子元素。
- Xml元素
XML的元素是指从开始标签直到结束标签的部分(均包括开始结束)。
一个元素可以包含:
1、其他元素
2、文本
3、属性
4、或混合以上所有
- Xml语法规则
所有的XML元素都必须有一个开始标签和结束标签,省略结束标签是非法的。如:
<root> content </root>
✓XML标签对大小写敏感;比如: 下面是两个不同的标签
<Note>this is a test1</Note>
<note>this is a test2</note>
✓XML文档必须有根元素。如:
<note>
<b>this is a test2</b>
<name>joy</name>
</note>
✓XML必须正确嵌套,父元素必须完全包住子元素。如:
<note><b>this is a test2</b></note>
✓XML属性值必须加引号,元素的属性值都是一个键值对形式。如:
<book category=" Python"></book>
- Xml元素命名规则
➢名称可以包含字母、数字以及其他字符
➢名称不能以数字或标点符号开头
➢名称不能以字母xml或XML开始
➢名称不能包含空格
➢可以使用任何名称,没有保留字
➢名称应该具有描述性,简短和简单,可以同时使用下划线。
➢避免“ -” 、“ .” 、“:”等字符。
- Xml的注释
XML注释格式为:
<!-- 注释内容 -->
- CDATA(Unparsed Character Data)指的是不应由XML解析器进行解析的
文本数据。
语法格式:
<![CDATA[“ 我们自己的代码"]]>
注意:
CDATA部分不能包含字符串“ ]]>” ,并且]]>” 之间不能有空格或折行等字符,
如果包含了,会以为是CDATA的结束。也不允许嵌套CDATA部分。
- Python解析xml的三种方法
SAX(simple API for XML):边读边解析,占用内存少,但需要用户实现回调函数(handler)。
DOM(Document Object Model):把xml文件解析成一棵树,可以非常灵活的遍历里面的对象。但是xml文件较大时占用内存大,不适合解析大文件。
ElementTree(Object Model):对dom的改进,速度快,占用内存少
- xml.dom解析xml常用Api
xml.dom解析xml思路 :
一个DOM的解析器在解析一个XML文档时,一次性读取整个文档,把文档中所有元素保存在内存中的一个树结构里,之后利用DOM提供的不同函数来读取该文档的内容和结构,也可以把修改过的内容写入XML文件。
- xml.dom解析xml常用API:minidom.parse(parser=None, bufsize=None)
该函数的作用是使用parse解析器打开xml文档,并将其解析为DOM文档,也就是内存中的一棵树,并得到这个DOM对象。
#coding=utf-8
#从xml.dom.minidom模块引入解析器parse
from xml.dom.minidom import parse
#minidom解析器打开xml文档并将其解析为内存中的一棵树
DOMTree = parse(r"E:ook.xml")
print type(DOMTree)
结果:
E:>python a.py
<type 'instance'>
- xml.dom解析xml常用API:doc.documentElement获取xml文档对象,就是拿到DOM树的根
#coding=utf-8
#从xml.dom.minidom模块引入解析器parse
from xml.dom.minidom import parse
#minidom解析器打开xml文档并将其解析为内存中的一棵树
DOMTree = parse(r"E:ook.xml")
print type(DOMTree)
booklist = DOMTree.documentElement
print booklist
结果:
E:>python a.py
<type 'instance'>
<DOM Element: booklist at 0x1c73b70>
- xml.dom解析xml常用API:获取xml文档函数 doc.toxml(encoding=None)
#coding=utf-8
#从xml.dom.minidom模块引入解析器parse
from xml.dom.minidom import parse
#minidom解析器打开xml文档并将其解析为内存中的一棵树
DOMTree = parse(r"E:ook.xml")
print type(DOMTree)
booklist = DOMTree.documentElement
print booklist
print u"xml文档内容: %s" %DOMTree.toxml()
- xml.dom解析xml常用API: hasAttribute(name)判断某个节点node是否存在某个属性,存在则返回True,否则返回False。
#coding=utf-8
#从xml.dom.minidom模块引入解析器parse
from xml.dom.minidom import parse
#minidom解析器打开xml文档并将其解析为内存中的一棵树
DOMTree = parse(r"E:ook.xml")
#print type(DOMTree)
booklist = DOMTree.documentElement
#print booklist
#print u"xml文档内容: %s" %DOMTree.toxml()
if booklist.hasAttribute("type") :
#判断根节点booklist是否有type属性
print u"booklist元素存在type属性"
else :
print u"booklist元素不存在type属性"
- xml.dom解析xml常用API :node. getAttribute(attname)获取节点node的某个属性的值。
#coding=utf-8
#从xml.dom.minidom模块引入解析器parse
from xml.dom.minidom import parse
#minidom解析器打开xml文档并将其解析为内存中的一棵树
DOMTree = parse(r"E:ook.xml")
#print type(DOMTree)
booklist = DOMTree.documentElement
#print booklist
#print u"xml文档内容: %s" %DOMTree.toxml()
if booklist.hasAttribute("type") :
#判断根节点booklist是否有type属性
print u"booklist元素存在type属性"
else :
print u"booklist元素不存在type属性"
print "Root element is", booklist.getAttribute("type")
- 获取节点元素:node.getElementsByTagName(name)获取XML文档中某个父节点下具有相同节点名的节点对象集合,是一个list对象。
#coding=utf-8
#从xml.dom.minidom模块引入解析器parse
from xml.dom.minidom import parse
#minidom解析器打开xml文档并将其解析为内存中的一棵树
DOMTree = parse(r"E:ook.xml")
#print type(DOMTree)
booklist = DOMTree.documentElement
#print booklist
#print u"xml文档内容: %s" %DOMTree.toxml()
if booklist.hasAttribute("type") :
#判断根节点booklist是否有type属性
print u"booklist元素存在type属性"
else :
print u"booklist元素不存在type属性"
#print "Root element is", booklist.getAttribute("type")
books = booklist.getElementsByTagName("book")
print type(books)
print books
练习:
print books[0].toxml()
print books[0].tagName
print books[0].getElementsByTagName("title")
print books[0].getElementsByTagName("title")[0].toxml()
只提取title里面的内容,怎么取?
books = booklist.getElementsByTagName("book")
print books[0].childNodes
- 获取节点元素:node.childNodes返回节点node下所有子节点组成的list。
#coding=utf-8
from xml.dom.minidom import parse #从xml.dom.minidom模块引入解析器parse
#minidom解析器打开xml文档并将其解析为内存中的一棵树
DOMTree = parse(r"E:ook.xml")
#获取xml文档对象,就是拿到树的根
booklist = DOMTree.documentElement
#获取booklist对象中所有book节点的list集合
books = booklist.getElementsByTagName("book")
print books[0].childNodes
- 获取节点文本值:node.childNodes[index].data获取节点node的文本值,即标签之间的文本内容。
#coding=utf-8
import xml.dom.minidom
from xml.dom.minidom import parse
#minidom解析器打开xml文档并将其解析为内存中的一棵树
DOMTree = xml.dom.minidom.parse(r"E:ook.xml")
#获取xml文档对象,就是拿到树的根
booklist = DOMTree.documentElement
if booklist.hasAttribute("type") :
#判断根节点booklist是否有type属性,有则获取并打印属性的值
print u"Root element is", booklist.getAttribute("type")
#获取booklist对象中所有book节点的list集合
books = booklist.getElementsByTagName("book")
print u"book节点的个数:", books.length
for book in books :
print "*******************book*******************"
if book.hasAttribute("category") :
print u"category is", book.getAttribute("category")
#根据结点名title拿到这个book结点下所有的title结点的集合list。
#[0]表示第一个title标签,因为一个<book>...</book>之间可能会
#定义多个title标签
title = book.getElementsByTagName('title')[0]
print "Title is", title.childNodes[0].data
author = book.getElementsByTagName('author')[0]
print "author is", author.childNodes[0].data
pageNumber = book.getElementsByTagName('pageNumber')[0]
print "pageNumber is", pageNumber.childNodes[0].data
结果:
标签里的内容是节点,标签外的内容是文本节点。
练习:
把李四相关标签取出来放到一个字典里。
#coding=utf-8
#从xml.dom.minidom模块引入解析器parse
from xml.dom.minidom import parse
#minidom解析器打开xml文档并将其解析为内存中的一棵树
DOMTree = parse(r"e:ook.xml")
print type(DOMTree)
booklist = DOMTree.documentElement
print booklist
print "*"*30
books = booklist.getElementsByTagName("book")
d={}
for i in range(1,6,2): #这里的结果是1,3,5 2是步长
tag_name = books[1].childNodes[i].tagName
d[tag_name]=books[1].childNodes[i].childNodes[0].data
print d
for k,v in d.items():
print k,v
老师分析过程如下:
第一步,获取父节点下所有子节点对象,存到books这个list中
>>> books = booklist.getElementsByTagName("book")
>>> print books
[<DOM Element: book at 0x230b308>, <DOM Element: book at
第二步,获取books这个list中的第2个结点,books[1]
>>> print books[1]
<DOM Element: book at 0x230b808>
第三步,获取第2个结点books[1]的文档
>>> print books[1].toxml()
<book category="Python">
<title>learning Python</title>
<author>李四</author>
<pageNumber>600</pageNumber>
</book>
第四步,获取第二个结点books[1]下的子节点list
>>> print books[1].childNodes
[<DOM Text node "u'
'">, <DOM Element: title at 0x23
"u'
'">, <DOM Element: author at 0x230bac8>, <DOM Te
DOM Element: pageNumber at 0x230bbc8>, <DOM Text node "u'
第五步,获取第2个结点books[1]下的第2个子节点childNode[1]
>>> print books[1].childNodes[1]
<DOM Element: title at 0x230b9c8>
第六步,获取第2个结点books[1]下的第2个子节点childNode[1]的文档
>>> print books[1].childNodes[1].toxml()
<title>learning Python</title>
第七步,获取第2个结点books[1]下的第2个子节点childNode[1]作为父节点下的子节点对象
>>> print books[1].childNodes[1].tagName
title
第八步,把获取到的tagname存入字典的key
>>> d={}
>>> key=books[1].childNodes[1].tagName
>>> print key
title
第九步,获取该结点的文本值
>>> print books[1].childNodes[1].childNodes[0].data
learning Python
第十步,把获取到的文本值存入字典的value
>>> d[key]=books[1].childNodes[1].childNodes[0].data
打印最后的结果
>>> print d
{u'title': u'learning Python'}
练习2:把第一个book的title和pagenumber的标签名字和内容放到一个字典里面
自己的答案:
#coding=utf-8
#从xml.dom.minidom模块引入解析器parse
from xml.dom.minidom import parse
#minidom解析器打开xml文档并将其解析为内存中的一棵树
DOMTree = parse(r"e:ook.xml")
#print type(DOMTree)
booklist = DOMTree.documentElement
#print booklist
books = booklist.getElementsByTagName("book")
#print books
d={}
for i in range(1,6,4): #这里的结果是1,5 4是步长
tag_name = books[0].childNodes[i].tagName
d[tag_name]=books[0].childNodes[i].childNodes[0].data
#print d
#print books[0].childNodes[i].childNodes[0].data
for k,v in d.items():
print k,v
结果:
E:>python a.py
pageNumber 561
title learning math
位置的对应关系:
<DOM Text node "u' '"> book 后的回车
<DOM Element: title at 0x4115608> title结点
<DOM Text node "u' '">title后的文本结点,内容是回车
<DOM Element: author at 0x4115708>author结点
<DOM Text node "u' '">author后的文本结点,内容是回车
<DOM Element: pageNumber at 0x4115808>pagenuber结点
<DOM Text node "u' '">pagenumber后的文本结点,内容是回车
- 解析的例题:
#coding=utf-8
import xml.dom.minidom
from xml.dom.minidom import parse
#minidom解析器打开xml文档并将其解析为内存中的一棵树
DOMTree = xml.dom.minidom.parse(r"E:ook.xml")
#获取xml文档对象,就是拿到树的根
booklist = DOMTree.documentElement
if booklist.hasAttribute("type") :
#判断根节点booklist是否有type属性,有则获取并打印属性的值
print u"Root element is", booklist.getAttribute("type")
#获取booklist对象中所有book节点的list集合
books = booklist.getElementsByTagName("book")
print u"book节点的个数:", books.length
for book in books : #获取结点中的属性值
print "*******************book*******************"
if book.hasAttribute("category") :
print u"category is", book.getAttribute("category")
#根据结点名title拿到这个book结点下所有的title结点的集合list。
#[0]表示第一个title标签,因为一个<book>...</book>之间可能会
#定义多个title标签
title = book.getElementsByTagName('title')[0] #拿到第一个title结点
print "Title is", title.childNodes[0].data
author = book.getElementsByTagName('author')[0]
print "author is", author.childNodes[0].data
pageNumber = book.getElementsByTagName('pageNumber')[0]
print "pageNumber is", pageNumber.childNodes[0].data
结果:
E:>python a.py
Root element is science and engineering
book节点的个数: 2
*******************book*******************
category is math
Title is learning math
author is 张三
pageNumber is 561
*******************book*******************
category is Python
Title is learning Python
author is 李四
pageNumber is 600
- Movies.xm解析实例:
#coding=utf-8
from xml.dom.minidom import parse
import xml.dom.minidom
# 使用minidom解析器打开 XML 文档
DOMTree = xml.dom.minidom.parse(r"E:movies.xml")
collection = DOMTree.documentElement
if collection.hasAttribute("shelf"):
print "Root element : %s" % collection.getAttribute("shelf")
# 在集合中获取所有电影
movies = collection.getElementsByTagName("movie")
# 打印每部电影的详细信息
for movie in movies:
print "*****Movie*****"
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
结果:
E:>python a.py
Root element : New Arrivals
*****Movie*****
Title: Enemy Behind
Type: War, Thriller
Format: DVD
Rating: PG
Description: Talk about a US-Japan war
*****Movie*****
Title: Transformers
Type: Anime, Science Fiction
Format: DVD
Rating: R
Description: A schientific fiction
*****Movie*****
Title: Trigun
Type: Anime, Action
Format: DVD
Rating: PG
Description: Vash the Stampede!
*****Movie*****
Title: Ishtar
Type: Comedy
Format: VHS
Rating: PG
Description: Viewable boredom
上面的程序完善,增加操作动态标签的名字:
#coding=utf-8
from xml.dom.minidom import parse
import xml.dom.minidom
# 使用minidom解析器打开 XML 文档
DOMTree = xml.dom.minidom.parse(r"e:movies.xml")
collection = DOMTree.documentElement
if collection.hasAttribute("shelf"):
print "Root element : %s" % collection.getAttribute("shelf")
# 在集合中获取所有电影
movies = collection.getElementsByTagName("movie")
# 打印每部电影的详细信息
for movie in movies:
print "*****Movie*****"
if movie.hasAttribute("title"):
print "Title: %s" % movie.getAttribute("title")
type = movie.getElementsByTagName('type')[0]
tag_name= movie.getElementsByTagName('type')[0].tagName
print "%s: %s" %(tag_name,type.childNodes[0].data)
format = movie.getElementsByTagName('format')[0]
tag_name= movie.getElementsByTagName('format')[0].tagName
print "%s: %s" %(tag_name,format.childNodes[0].data)
rating = movie.getElementsByTagName('rating')[0]
tag_name= movie.getElementsByTagName('rating')[0].tagName
print "%s: %s" %(tag_name,rating.childNodes[0].data)
description = movie.getElementsByTagName('description')[0]
tag_name= movie.getElementsByTagName('description')[0].tagName
print "%s: %s" %(tag_name,description.childNodes[0].data)
- 创建xml空文档:minidom.Document()该方法用于创建一个空白的xml文档对象,并返回这个doc对象。每个xml文档都是一个Document对象,代表着内存中的DOM树。
#coding=utf-8
import xml.dom.minidom
#在内存中创建一个空的文档
doc = xml.dom.minidom.Document()
print doc
结果:
E:>python a.py
<xml.dom.minidom.Document instance at 0x01ABFBC0>
- 创建xml文档根节点:doc.createElement(tagName)生成xml文档节点。参数表示要生成节点的名称。
#coding=utf-8
import xml.dom.minidom
#在内存中创建一个空的文档
doc = xml.dom.minidom.Document()
print doc
#创建一个根节点Managers对象
root = doc.createElement('Managers')
print u"添加的xml标签为:", root.tagName
结果:
E:>python a.py
<xml.dom.minidom.Document instance at 0x01ADEDA0>
添加的xml标签为: Managers
- 添加节点属性:node.setAttribute(attname, value)该方法表示给节点添加属性值对(Attribute)。参数说明:attname :属性的名称 value :属性的值
#coding=utf-8
import xml.dom.minidom
#在内存中创建一个空的文档
doc = xml.dom.minidom.Document()
print doc
#创建一个根节点Managers对象
root = doc.createElement('Managers')
print u"添加的xml标签为:", root.tagName
# 给根节点root添加属性
root.setAttribute('company', 'xx科技')
value = root.getAttribute('company')
print u"root元素的'company'属性值为:", value.decode('utf-8').encode('gbk')
结果:
E:>python a.py
<xml.dom.minidom.Document instance at 0x01A9FDC8>
添加的xml标签为: Managers
root元素的'company'属性值为: xx科技
- 创建一个新节点,加文本节点:doc.createTextNode(data)给叶子节点添加文本节点。
#coding=utf-8
import xml.dom.minidom
#在内存中创建一个空的文档
doc = xml.dom.minidom.Document()
print doc
#创建一个根节点Managers对象
root = doc.createElement('Managers')
print u"添加的xml标签为:", root.tagName
# 给根节点root添加属性
root.setAttribute('company', 'xx科技')
value = root.getAttribute('company')
print u"root元素的'company'属性值为:", value.decode('utf-8').encode('gbk')
ceo = doc.createElement('CEO')
#给叶子节点name设置一个文本节点,用于显示文本内容
ceo.appendChild(doc.createTextNode('吴总'))
print ceo.tagName
print u"给叶子节点添加文本节点成功"
print ceo.childNodes[0].data.decode("utf-8") #验证下添加的子节点是不是对的
结果:
E:>python a.py
<xml.dom.minidom.Document instance at 0x01BCFDC8>
添加的xml标签为: Managers
root元素的'company'属性值为: xx科技
CEO
给叶子节点添加文本节点成功
吴总
- 完整创建xml例子:doc/parentNode.appendChild(node)将节点node添加到文档对象doc作为文档树的根节点或者添加到父节点parentNode下作为其子节点。
#coding=utf-8
import xml.dom.minidom
#在内存中创建一个空的文档
doc = xml.dom.minidom.Document()
#创建一个根节点company对象
root = doc.createElement('companys')
# 给根节点root添加属性
root.setAttribute('name', u'公司信息')
#将根节点添加到文档对象中
doc.appendChild(root)
# 给根节点添加一个叶子节点
company = doc.createElement('gloryroad')
# 叶子节点下再嵌套叶子节点
name = doc.createElement("Name")
# 给节点添加文本节点
name.appendChild(doc.createTextNode(u"光荣之路教育科技公司"))
ceo = doc.createElement('CEO')
ceo.appendChild(doc.createTextNode(u'吴总'))
# 将各叶子节点添加到父节点company中
# 然后将company添加到跟节点companys中
company.appendChild(name)
company.appendChild(ceo)
root.appendChild(company)
print doc.toxml()
#文本结点挂到子节点,子节点挂到根节点。
#我们可以有多个子节点,挂到根节点。
#可以创建多级节点。
结果:
E:>python a.py
<?xml version="1.0" ?><companys name="公司信息"><gloryroad><Name>光荣之路教育科
技公司</Name><CEO>吴总</CEO></gloryroad></companys>
- 生成xml文档:doc.writexml()
#coding=utf-8
import codecs
import xml.dom.minidom
#在内存中创建一个空的文档
doc = xml.dom.minidom.Document()
#创建一个根节点company对象
root = doc.createElement('companys')
# 给根节点root添加属性
root.setAttribute('name', u'公司信息')
#将根节点添加到文档对象中
doc.appendChild(root)
# 给根节点添加一个叶子节点
company = doc.createElement('gloryroad')
# 叶子节点下再嵌套叶子节点
name = doc.createElement("Name")
# 给节点添加文本节点
name.appendChild(doc.createTextNode(u"光荣之路教育科技公司"))
ceo = doc.createElement('CEO')
ceo.appendChild(doc.createTextNode(u'吴总'))
# 将各叶子节点添加到父节点company中
# 然后将company添加到跟节点companys中
company.appendChild(name)
company.appendChild(ceo)
root.appendChild(company)
print doc.toxml()
#文本结点挂到子节点,子节点挂到根节点。
#我们可以有多个子节点,挂到根节点。
#可以创建多级节点。
fp = codecs.open('e:\company.xml', 'w','utf-8')
doc.writexml(fp, indent='', addindent=' ', newl=' ', encoding="utf-8")
fp.close()
- 创建xml文档完整实例2:
#coding=utf-8
import xml.dom.minidom
#在内存中创建一个空的文档
doc = xml.dom.minidom.Document()
#创建一个根节点Managers对象
root = doc.createElement('Managers')
#设置根节点的属性
root.setAttribute('company', 'xx科技')
root.setAttribute('address', '科技软件园')
#将根节点添加到文档对象中
doc.appendChild(root)
managerList = [{'name' : 'joy', 'age' : 27, 'sex' : '女'},
{'name' : 'tom', 'age' : 30, 'sex' : '男'},
{'name' : 'ruby', 'age' : 29, 'sex' : '女'} ]
for i in managerList :
nodeManager = doc.createElement('Manager')
nodeName = doc.createElement('name')
#给叶子节点name设置一个文本节点,用于显示文本内容
nodeName.appendChild(doc.createTextNode(str(i['name'])))
nodeAge = doc.createElement("age")
nodeAge.appendChild(doc.createTextNode(str(i["age"])))
nodeSex = doc.createElement("sex")
nodeSex.appendChild(doc.createTextNode(str(i["sex"])))
#将各叶子节点添加到父节点Manager中,
#最后将Manager添加到根节点Managers中
nodeManager.appendChild(nodeName)
nodeManager.appendChild(nodeAge)
nodeManager.appendChild(nodeSex)
root.appendChild(nodeManager)
#开始写xml文档
fp = open('e:\Manager.xml', 'w')
doc.writexml(fp, indent=' ', addindent=' ', newl=' ', encoding="utf-8")
fp.close()