zl程序教程

您现在的位置是:首页 >  后端

当前栏目

python网络编程学习笔记(八):XML生成与解析(DOM、ElementTree)

2023-06-13 09:15:28 时间

xml.dom篇

   DOM是DocumentObjectModel的简称,XML文档的高级树型表示。该模型并非只针对Python,而是一种普通XML模型。Python的DOM包是基于SAX构建的,并且包括在Python2.0的标准XML支持里。

一、xml.dom的简单介绍

1、主要方法:

minidom.parse(filename):加载读取XML文件
doc.documentElement:获取XML文档对象
node.getAttribute(AttributeName):获取XML节点属性值
node.getElementsByTagName(TagName):获取XML节点对象集合
node.childNodes:返回子节点列表。
node.childNodes[index].nodeValue:获取XML节点值
node.firstChild:访问第一个节点,等价于pagexml.childNodes[0]
返回Node节点的xml表示的文本:
doc=minidom.parse(filename)
doc.toxml("UTF-8")

访问元素属性:

Node.attributes["id"]
a.name#就是上面的"id"
a.value#属性的值 

2、举例说明

例1:文件名:book.xml

复制代码代码如下:


<?xmlversion="1.0"encoding="utf-8"?>
<info>
  <intro>Bookmessage</intro>
   <listid="001">
       <head>bookone</head>
       <name>pythoncheck</name>
       <number>001</number>
       <page>200</page>
   </list>

   <listid="002">
       <head>booktwo</head>
       <name>pythonlearn</name>
       <number>002</number>
       <page>300</page>
   </list>

</info>

(1)创建DOM对象

复制代码代码如下:


importxml.dom.minidom
dom1=xml.dom.minidom.parse("book.xml")

(2)获取根字节

root=dom1.documentElement#这里得到的是根节点
printroot.nodeName,",",root.nodeValue,",",root.nodeType

返回结果为:

info,None,1

其中:

info是指根节点的名称root.nodeName
None是指根节点的值root.nodeValue

1是指根节点的类型root.nodeType,更多节点类型如下表:

NodeType

NamedConstant

1

ELEMENT_NODE

2

ATTRIBUTE_NODE

3

TEXT_NODE

4

CDATA_SECTION_NODE

5

ENTITY_REFERENCE_NODE

6

ENTITY_NODE

7

PROCESSING_INSTRUCTION_NODE

8

COMMENT_NODE

9

DOCUMENT_NODE

10

DOCUMENT_TYPE_NODE

11

DOCUMENT_FRAGMENT_NODE

12

NOTATION_NODE


(3)子元素、子节点的访问

A、返回root子节点列表

复制代码代码如下:
importxml.dom.minidom
dom1=xml.dom.minidom.parse("book.xml")
root=dom1.documentElement
#printroot.nodeName,",",root.nodeValue,",",root.nodeType
printroot.childNodes

运行结果为:

[<DOMTextnode"u"\n  "">,<DOMElement:introat0x124ef58>,<DOMTextnode"u"\n   "">,<DOMElement:listat0x1254058>,<DOMTextnode"u"\n\n   "">,<DOMElement:listat0x1254418>,<DOMTextnode"u"\n\n"">]

B、获取XML节点值,如返回根节点下第二个子节点intro的值和名字,添加下面一句

复制代码代码如下:
printroot.childNodes[1].nodeName,root.childNodes[1].nodeValue

运行结果为:

introNone

C、访问第一个节点

复制代码代码如下:
printroot.firstChild.nodeName

运行结果为:

#text

D、获取已经知道的元素名字的值,如要获取intro后的bookmessage可以使用下面的方法:

复制代码代码如下:
importxml.dom.minidom
dom1=xml.dom.minidom.parse("book.xml")
root=dom1.documentElement
#printroot.nodeName,",",root.nodeValue,",",root.nodeType
node=root.getElementsByTagName("intro")[0]
fornodeinnode.childNodes:
   ifnode.nodeTypein(node.TEXT_NODE,node.CDATA_SECTION_NODE):
       printnode.data

这种方法的不足之处是需要对类型进行判断,使用起来不是很方便。运行结果是:

Bookmessage

二、xml解析

对上面的xml进行解析

方法1代码如下:

复制代码代码如下:
#@小五义http://www.cnblogs.com/xiaowuyi
#xml解析

importxml.dom.minidom
dom1=xml.dom.minidom.parse("book.xml")
root=dom1.documentElement
book={}
booknode=root.getElementsByTagName("list")
forbooklistinbooknode:
   print"="*20
   print"id:"+booklist.getAttribute("id")
   fornodelistin booklist.childNodes:
       ifnodelist.nodeType==1:
           printnodelist.nodeName+":",
       fornodeinnodelist.childNodes:
           printnode.data

运行结果为:

====================
id:001
head:bookone
name:pythoncheck
number:001
page:200
====================
id:002
head:booktwo
name:pythonlearn
number:002
page:300

方法二:

代码:

复制代码代码如下:
#@小五义http://www.cnblogs.com/xiaowuyi
#xml解析

importxml.dom.minidom
dom1=xml.dom.minidom.parse("book.xml")
root=dom1.documentElement
book={}
booknode=root.getElementsByTagName("list")
forbooklistinbooknode:
   print"="*20
   print"id:"+booklist.getAttribute("id")
   print"head:"+booklist.getElementsByTagName("head")[0].childNodes[0].nodeValue.strip()
   print"name:"+booklist.getElementsByTagName("name")[0].childNodes[0].nodeValue.strip()
   print"number:"+booklist.getElementsByTagName("number")[0].childNodes[0].nodeValue.strip()
   print"page:"+booklist.getElementsByTagName("page")[0].childNodes[0].nodeValue.strip()

 运行结果与方法一一样。比较上面的两个方法,方法一根据xml的树结构进行了多次循环,可读性上不及方法二,方法直接对每一个节点进行操作,更加清晰。为了更加方法程序的调用,可以使用一个list加一个字典进行存储,具体见方法3:

复制代码代码如下:
#@小五义http://www.cnblogs.com/xiaowuyi
#xml解析
importxml.dom.minidom
dom1=xml.dom.minidom.parse("book.xml")
root=dom1.documentElement
book=[]
booknode=root.getElementsByTagName("list")
forbooklistinbooknode:
   bookdict={}
   bookdict["id"]=booklist.getAttribute("id")
   bookdict["head"]=booklist.getElementsByTagName("head")[0].childNodes[0].nodeValue.strip()
   bookdict["name"]=booklist.getElementsByTagName("name")[0].childNodes[0].nodeValue.strip()
   bookdict["number"]=booklist.getElementsByTagName("number")[0].childNodes[0].nodeValue.strip()
   bookdict["page"]=booklist.getElementsByTagName("page")[0].childNodes[0].nodeValue.strip()
   book.append(bookdict)
printbook

运行结果为:

[{"head":u"bookone","page":u"200","number":u"001","id":u"001","name":u"pythoncheck"},{"head":u"booktwo","page":u"300","number":u"002","id":u"002","name":u"pythonlearn"}]

该列表里包含了两个字典。

三、建立XML文件
这里用方法三得到的结果,建立一个xml文件。

复制代码代码如下:
#-*-coding:cp936-*-
#@小五义http://www.cnblogs.com/xiaowuyi
#xml创建

importxml.dom
defcreate_element(doc,tag,attr):
   #创建一个元素节点
   elementNode=doc.createElement(tag)
   #创建一个文本节点
   textNode=doc.createTextNode(attr)
   #将文本节点作为元素节点的子节点
   elementNode.appendChild(textNode)
   returnelementNode

dom1=xml.dom.getDOMImplementation()#创建文档对象,文档对象用于创建各种节点。
doc=dom1.createDocument(None,"info",None)
top_element=doc.documentElement#得到根节点
books=[{"head":u"bookone","page":u"200","number":u"001","id":u"001","name":u"pythoncheck"},{"head":u"booktwo","page":u"300","number":u"002","id":u"002","name":u"pythonlearn"}]
forbookinbooks:
   sNode=doc.createElement("list")
   sNode.setAttribute("id",str(book["id"]))
   headNode=create_element(doc,"head",book["head"])
   nameNode=create_element(doc,"name",book["name"])
   numberNode=create_element(doc,"number",book["number"])
   pageNode=create_element(doc,"page",book["page"])
   sNode.appendChild(headNode)
   sNode.appendChild(nameNode)
   sNode.appendChild(pageNode)
   top_element.appendChild(sNode)#将遍历的节点添加到根节点下
xmlfile=open("bookdate.xml","w")
doc.writexml(xmlfile,addindent=""*4,newl="\n",encoding="utf-8")
xmlfile.close()

运行后生成bookdate.xml文件,该文件与book.xml一样。

 xml.etree.ElementTree篇

依然使用例1的例子,对xml进行解析分析。

1、加载XML

方法一:直接加载文件

复制代码代码如下:
importxml.etree.ElementTree
root=xml.etree.ElementTree.parse("book.xml")

方法二:加载指定字符串

复制代码代码如下:
importxml.etree.ElementTree
root=xml.etree.ElementTree.fromstring(xmltext)这里xmltext是指定的字符串。

2、获取节点

方法一利用getiterator方法得到指定节点

book_node=root.getiterator("list")

方法二利用getchildren方法得到子节点,如例1中,要得到list下面子节点head的值:

复制代码代码如下:
#@小五义http://www.cnblogs.com/xiaowuyiimportxml.etree.ElementTree
root=xml.etree.ElementTree.parse("book.xml")
book_node=root.getiterator("list")
fornodeinbook_node:
   book_node_child=node.getchildren()[0]
   printbook_node_child.tag+":"+book_node_child.text

运行结果为:

head:bookone
head:booktwo

方法三使用find和findall方法

 find方法找到指定的第一个节点:

复制代码代码如下:
#-*-coding:cp936-*-
#@小五义
importxml.etree.ElementTree
root=xml.etree.ElementTree.parse("book.xml")
book_find=root.find("list")
fornoteinbook_find:
   printnote.tag+":"+note.text

运行结果:

head:bookone
name:pythoncheck
number:001
page:200

findall方法将找到指定的所有节点:

复制代码代码如下:
#-*-coding:cp936-*-
#@小五义
importxml.etree.ElementTree
root=xml.etree.ElementTree.parse("book.xml")
book=root.findall("list")
forbook_listinbook:
   fornoteinbook_list:
       printnote.tag+":"+note.text

运行结果:

head:bookone
name:pythoncheck
number:001
page:200
head:booktwo
name:pythonlearn
number:002
page:300

3、对book.xml进行解析的实例

复制代码代码如下:
#-*-coding:cp936-*-
#@小五义
importxml.etree.ElementTree
root=xml.etree.ElementTree.parse("book.xml")
book=root.findall("list")
forbook_listinbook:
   print"="*20
   if book_list.attrib.has_key("id"):
       print"id:"+book_list.attrib["id"]
   fornoteinbook_list:
       printnote.tag+":"+note.text
print"="*20

运行结果为:

====================
id:001
head:bookone
name:pythoncheck
number:001
page:200
====================
id:002
head:booktwo
name:pythonlearn
number:002
page:300
====================

注意:
当要获取属性值时,如listid="001",用attrib方法。
当要获取节点值时,如<head>bookone</head>中的bookone用text方法。
当要获取节点名时,用tag方法。