xml了解

  1. Xml简介

XML指可扩展标记语言(Extensible Markup Language)
XML被设计用于结构化、存储和传输数据
XML是一种标记语言,很类似于HTML
XML没有像HTML那样具有预定义标签,需要程序员自定义标签。
XML被设计为具有自我描述性,并且是W3C的标准

  1. Xml文档树结构

XML文档形成了一种树结构,它从“ 根部” 开始,然后扩展到“ 树
枝” 。
XML文档必须包含根元素,该元素是所有其他元素的父元素,文档中的所有元素形成了一棵文档树,这课树从根开始,并扩展到树的最顶端,并且所有的元素都可以有子元素。

  1. Xml元素

XML的元素是指从开始标签直到结束标签的部分(均包括开始结束)。
一个元素可以包含:

1、其他元素
2、文本
3、属性
4、或混合以上所有

  1. 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>

  1. Xml元素命名规则

名称可以包含字母、数字以及其他字符
名称不能以数字或标点符号开头
名称不能以字母xml或XML开始
名称不能包含空格
可以使用任何名称,没有保留字
名称应该具有描述性,简短和简单,可以同时使用下划线。
避免“ -” 、“ .” 、“:”等字符。

  1. Xml的注释

XML注释格式为:
<!-- 注释内容 -->

  1. CDATAUnparsed Character Data)指的是不应由XML解析器进行解析的
    文本数据。

语法格式:

<![CDATA[“ 我们自己的代码"]]>

注意:
CDATA部分不能包含字符串“ ]]>” ,并且]]>” 之间不能有空格或折行等字符,

如果包含了,会以为是CDATA的结束。也不允许嵌套CDATA部分。

  1. Python解析xml的三种方法

SAX(simple API for XML):边读边解析,占用内存少,但需要用户实现回调函数(handler)。

DOM(Document Object Model):把xml文件解析成一棵树,可以非常灵活的遍历里面的对象。但是xml文件较大时占用内存大,不适合解析大文件。

ElementTree(Object Model):对dom的改进,速度快,占用内存少

  1. xml.dom解析xml常用Api

xml.dom解析xml思路 :

一个DOM的解析器在解析一个XML文档时,一次性读取整个文档,把文档中所有元素保存在内存中的一个树结构里,之后利用DOM提供的不同函数来读取该文档的内容和结构,也可以把修改过的内容写入XML文件。 

  1. xml.dom解析xml常用APIminidom.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:\book.xml")
print type(DOMTree)

结果:

E:\>python a.py

<type 'instance'>

  1. xml.dom解析xml常用APIdoc.documentElement获取xml文档对象,就是拿到DOM树的根

#coding=utf-8

#从xml.dom.minidom模块引入解析器parse

from xml.dom.minidom import parse 

#minidom解析器打开xml文档并将其解析为内存中的一棵树

DOMTree = parse(r"E:\book.xml")

print type(DOMTree)

booklist = DOMTree.documentElement

print booklist

结果:

E:\>python a.py

<type 'instance'>

<DOM Element: booklist at 0x1c73b70>

 

  1. 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:\book.xml")

print type(DOMTree)

booklist = DOMTree.documentElement

print booklist

print u"xml文档内容:\n%s" %DOMTree.toxml()

 

  1. 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:\book.xml")

#print type(DOMTree)

booklist = DOMTree.documentElement

#print booklist

#print u"xml文档内容:\n%s" %DOMTree.toxml()

if booklist.hasAttribute("type") :

  #判断根节点booklist是否有type属性

    print u"booklist元素存在type属性"

else :

    print u"booklist元素不存在type属性"

 

 

  1. 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:\book.xml")

#print type(DOMTree)

booklist = DOMTree.documentElement

#print booklist

#print u"xml文档内容:\n%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")

 

 

  1. 获取节点元素:node.getElementsByTagName(name)获取XML文档中某个父节点下具有相同节点名的节点对象集合,是一个list对象。

#coding=utf-8

#从xml.dom.minidom模块引入解析器parse

from xml.dom.minidom import parse 

#minidom解析器打开xml文档并将其解析为内存中的一棵树

DOMTree = parse(r"E:\book.xml")

#print type(DOMTree)

booklist = DOMTree.documentElement

#print booklist

#print u"xml文档内容:\n%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

  1. 获取节点元素:node.childNodes返回节点node下所有子节点组成的list

#coding=utf-8

from xml.dom.minidom import parse #从xml.dom.minidom模块引入解析器parse

#minidom解析器打开xml文档并将其解析为内存中的一棵树

DOMTree = parse(r"E:\book.xml")

#获取xml文档对象,就是拿到树的根

booklist = DOMTree.documentElement

#获取booklist对象中所有book节点的list集合

books = booklist.getElementsByTagName("book")

print books[0].childNodes

 

  1. 获取节点文本值: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:\book.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:\book.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'\n    '">, <DOM Element: title at 0x23
"u'\n    '">, <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:\book.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'\n    '">  book 后的回车

<DOM Element: title at 0x4115608> title结点

<DOM Text node "u'\n    '">title后的文本结点,内容是回车

<DOM Element: author at 0x4115708>author结点

<DOM Text node "u'\n    '">author后的文本结点,内容是回车

<DOM Element: pageNumber at 0x4115808>pagenuber结点

<DOM Text node "u'\n  '">pagenumber后的文本结点,内容是回车

 

 

  1. 解析的例题:

#coding=utf-8

import xml.dom.minidom

from xml.dom.minidom import parse 

#minidom解析器打开xml文档并将其解析为内存中的一棵树

DOMTree = xml.dom.minidom.parse(r"E:\book.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

 

 

  1. 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)

 

  1. 创建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>

  1. 创建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

  1. 添加节点属性: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科技

 

  1. 创建一个新节点,加文本节点: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

给叶子节点添加文本节点成功

吴总

 

  1. 完整创建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>

 

  1. 生成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='\t', newl='\n', encoding="utf-8")

fp.close()

 

 

  1. 创建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='\t', addindent='\t', newl='\n', encoding="utf-8")

fp.close()

posted @ 2018-03-21 22:57  小七Libra  阅读(338)  评论(0编辑  收藏  举报