xml.dom篇

DOM是Document Object Model的简称,XML 文档的高级树型表示。该模型并非只针对 Python,而是一种普通XML 模型。Python 的 DOM 包是基于 SAX 构建的,并且包括在 Python 2.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

 <?xml version="1.0" encoding="utf-8"?>
<info>
<intro>Book message</intro>
<list id='001'>
<head>bookone</head>
<name>python check</name>
<number>001</number>
<page>200</page>
</list> <list id='002'>
<head>booktwo</head>
<name>python learn</name>
<number>002</number>
<page>300</page>
</list>
</info>

(1)创建DOM对象

import xml.dom.minidom
dom1=xml.dom.minidom.parse('book.xml')
print(dom1)

返回结果为:

<xml.dom.minidom.Document object at 0x00000000025CE468>

(2)获取根字节

root=dom1.documentElement # 这里得到的是根节点
print(root)
print(root.nodeName)
print(root.nodeValue)
print(root.nodeType)

返回结果为:

<DOM Element: info at 0x23619c8>
info
None
1

其中:

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

None是指根节点的值root.nodeValue

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

NodeType

Named Constant

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子节点列表

import xml.dom.minidom
dom1=xml.dom.minidom.parse('book.xml')
root=dom1.documentElement
print(root.childNodes)

运行结果为:

[<DOM Text node "'\n    '">, <DOM Element: intro at 0x2255470>, <DOM Text node "'\n    '">, <DOM Element: list at 0x2255508>, <DOM Text node "'\n\n    '">, <DOM Element: list at 0x2255800>, <DOM Text node "'\n'">]

for i in root.childNodes:
print(i)

结果:

Text也是一个节点,Text表示两个标签之间的内容,如

第一行结果表示<info>和<intro>之间的内容,为一个回车和4个空格

第五行结果表示</list>和<list id='002'>之间的内容,为两个回车和4个空格

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

print(root.childNodes[0].nodeName)
print(root.childNodes[0].nodeValue)
print(root.childNodes[1].nodeName)
print(root.childNodes[1].nodeValue)

运行结果为:

可以看出,第一个节点的值是一个回车加4个空格(竖线为鼠标光标)

C、访问第一个节点

print(root.firstChild.nodeName)

运行结果为:

#text

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

import xml.dom.minidom
dom1=xml.dom.minidom.parse('book.xml')
root=dom1.documentElement
node= root.getElementsByTagName('intro')[0]
for node in node.childNodes:
if node.nodeType in (node.TEXT_NODE,node.CDATA_SECTION_NODE):
print(node.data)

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

Book message

二、XML解析

对上面的xml进行解析

方法1 代码如下:

import xml.dom.minidom
dom1=xml.dom.minidom.parse('book.xml')
root=dom1.documentElement
booknode=root.getElementsByTagName('list')
for booklist in booknode:
print('='*20)
print('id:'+booklist.getAttribute('id'))
for nodelist in booklist.childNodes:
if nodelist.nodeType ==1:
print(nodelist.nodeName+':',)
for node in nodelist.childNodes:
print(node.data)

 

import xml.dom.minidom
dom1=xml.dom.minidom.parse('book.xml')
root=dom1.documentElement
# print(root) # <DOM Element: info at 0x2131a60>
booknode=root.getElementsByTagName('list') # 返回元素列表
# print(booknode) # [<DOM Element: list at 0x22505a0>, <DOM Element: list at 0x2250898>]
for booklist in booknode: # 循环列表,booklist表示每本书
print('='*20)
print('id:'+booklist.getAttribute('id')) # 标签属性值
# print(booklist.childNodes) # 每本书的节点,[<DOM Text node "'\n '">, <DOM Element: head at 0x2590638>, <DOM Text node "'\n '">, <DOM Element: name at 0x25906d0>, <DOM Text node "'\n '">, <DOM Element: number at 0x2590768>, <DOM Text node "'\n '">, <DOM Element: page at 0x2590800>, <DOM Text node "'\n '">]
for nodelist in booklist.childNodes: # 循环当前书的节点
if nodelist.nodeType ==1: # 如果节点类型是1,表示是ELEMENT_NODE
print(nodelist.nodeName+':',end='')
# print(type(nodelist))
'''
上面一句的输出结果
id:001
<class 'xml.dom.minidom.Element'>
<class 'xml.dom.minidom.Element'>
<class 'xml.dom.minidom.Element'>
<class 'xml.dom.minidom.Element'>
'''
# print(nodelist.childNodes)
'''
上面一句的输出结果
id:001
[<DOM Text node "'bookone'">]
[<DOM Text node "'python che'...">]
[<DOM Text node "'001'">]
[<DOM Text node "'200'">]
'''
for node in nodelist.childNodes:
print(node.data)

运行结果为:

==================== 
id:001 
head: bookone 
name: python check 
number: 001 
page: 200 
==================== 
id:002 
head: booktwo 
name: python learn 
number: 002 
page: 300

方法二:

代码:

import xml.dom.minidom
dom1 = xml.dom.minidom.parse('book.xml')
root = dom1.documentElement
booknode = root.getElementsByTagName('list')
for booklist in booknode:
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加一个字典进行存储

xml转换为字典(方法一):

import xml.dom.minidom
dom1=xml.dom.minidom.parse('book.xml')
root=dom1.documentElement
book=[]
booknode=root.getElementsByTagName('list')
for booklist in booknode:
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)
print(book)

运行结果为:

[{'id': '001', 'head': 'bookone', 'name': 'python check', 'number': '001', 'page': '200'}, {'id': '002', 'head': 'booktwo', 'name': 'python learn', 'number': '002', 'page': '300'}]

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

xml转换为字典(方法二):

 <?xml version="1.0"?>
<root>
<person age="18">
<name>张三</name>
<sex>男</sex>
</person>
<person age="19" des="您好">
<name>李四</name>
<sex>女</sex>
</person>
</root>
from xml.etree import ElementTree as et
import json # 从xml文件读取结点 转换为json格式,并保存到文件中
print('read node from xmlfile, transfer them to json, and save into jsonFile:')
root1 = et.parse("testXml.xml") # 直接加载文件
print(root1) # <xml.etree.ElementTree.ElementTree object at 0x00000000023E3D30>
f = open('testJson.json', 'a', encoding="utf8")
for each in root1.getiterator("person"): # 利用getiterator方法得到指定节点
print(each) # <Element 'person' at 0x000000000211C638>, <Element 'person' at 0x00000000025DFC78>
tempDict = each.attrib # attrib获取XML节点属性值,返回字典
print(type(tempDict)) # <class 'dict'>
print(tempDict) # {'age': '18'}, {'age': '19', 'des': '您好'}
for childNode in each.getchildren(): # 利用getchildren方法得到子节点
print(childNode) # <Element 'name' at 0x00000000023E3C28>, <Element 'sex' at 0x00000000025BFC28>
tempDict[childNode.tag] = childNode.text # tag获取节点名,text获取节点值
print(tempDict) # {'age': '18', 'name': '张三', 'sex': '男'}, {'age': '19', 'des': '您好', 'name': '李四', 'sex': '女'}
# 上面的字典,里面键值都是单引号,dumps后,变成双引号
tempJson = json.dumps(tempDict, ensure_ascii=False)
print(tempJson) # {"age": "18", "name": "张三", "sex": "男"}, {"age": "19", "des": "您好", "name": "李四", "sex": "女"}
f.write(tempJson + "\n")
f.close() # 从json文件中读取,并打印
print('read json from jsonfile:')
for eachJson in open('testJson.json', 'r', encoding='utf8'):
tempStr = json.loads(eachJson)
print(tempStr) 

结果:

read node from xmlfile, transfer them to json, and save into jsonFile:
<xml.etree.ElementTree.ElementTree object at 0x0000000001E33DD8>
<Element 'person' at 0x0000000001E1C408>
<class 'dict'>
{'age': '18'}
<Element 'name' at 0x0000000002205C28>
<Element 'sex' at 0x00000000025DEC28>
{'age': '18', 'name': '张三', 'sex': '男'}
{"age": "18", "name": "张三", "sex": "男"}
<Element 'person' at 0x00000000025DECC8>
<class 'dict'>
{'age': '19', 'des': '您好'}
<Element 'name' at 0x00000000025DED18>
<Element 'sex' at 0x00000000025DED68>
{'age': '19', 'des': '您好', 'name': '李四', 'sex': '女'}
{"age": "19", "des": "您好", "name": "李四", "sex": "女"}
read json from jsonfile:
{'age': '18', 'name': '张三', 'sex': '男'}
{'age': '19', 'des': '您好', 'name': '李四', 'sex': '女'}

三、建立XML文件

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

import xml.dom
def create_element(doc,tag,attr):
#创建一个元素节点
elementNode=doc.createElement(tag)
#创建一个文本节点
textNode=doc.createTextNode(attr)
#将文本节点作为元素节点的子节点
elementNode.appendChild(textNode)
return elementNode dom1=xml.dom.getDOMImplementation()#创建文档对象,文档对象用于创建各种节点。
doc=dom1.createDocument(None,"info",None)
top_element = doc.documentElement# 得到根节点
books=[{'id': '001', 'head': 'bookone', 'name': 'python check', 'number': '001', 'page': '200'}, {'id': '002', 'head': 'booktwo', 'name': 'python learn', 'number': '002', 'page': '300'}]
for book in books:
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

方法一:直接加载文件

import xml.etree.ElementTree
root=xml.etree.ElementTree.parse('book.xml')
print(root)

结果:  

<xml.etree.ElementTree.ElementTree object at 0x00000000022095F8>

方法二:加载指定字符串

import xml.etree.ElementTree
root = xml.etree.ElementTree.fromstring(xmltext)

这里xmltext是指定的字符串。

2、获取节点

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

book_node=root.getiterator("list")
print(book_node)

结果:

[<Element 'list' at 0x00000000021E6F98>, <Element 'list' at 0x00000000025EF3B8>]

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

import xml.etree.ElementTree
root=xml.etree.ElementTree.parse('book.xml')
book_node=root.getiterator("list")
for node in book_node:
book_node_child=node.getchildren()[0]
print(book_node_child.tag+':'+book_node_child.text)

运行结果为:

head:bookone 
head:booktwo

方法三 使用find和findall方法

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

import xml.etree.ElementTree
root=xml.etree.ElementTree.parse('book.xml')
book_find=root.find('list')
# print(book_find) # <Element 'list' at 0x0000000002406F48>
# print(type(book_find)) # <class 'xml.etree.ElementTree.Element'>
for note in book_find:
# print(note)
'''
<Element 'head' at 0x00000000025F6B38>
<Element 'name' at 0x00000000025F6B88>
<Element 'number' at 0x000000000260A228>
<Element 'page' at 0x000000000260F368>
'''
print(note.tag+':'+note.text)

运行结果:

head:bookone 
name:python check 
number:001 
page:200

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

import xml.etree.ElementTree
root=xml.etree.ElementTree.parse('book.xml')
book=root.findall('list')
print(book) # [<Element 'list' at 0x0000000001E66F48>, <Element 'list' at 0x00000000025DF368>]
for book_list in book:
for note in book_list:
print(note.tag+':'+note.text)

运行结果:

head:bookone 
name:python check 
number:001 
page:200 
head:booktwo 
name:python learn 
number:002 
page:300

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

import xml.etree.ElementTree
root=xml.etree.ElementTree.parse('book.xml')
book=root.findall('list')
for book_list in book:
print('='*20)
# print(type(book_list.attrib)) # <class 'dict'>
if 'id' in book_list.attrib:
print("id:"+book_list.attrib['id'])
for note in book_list:
print(note.tag+':'+note.text)
print('='*20)

运行结果为:

==================== 
id:001 
head:bookone 
name:python check 
number:001 
page:200 
==================== 
id:002 
head:booktwo 
name:python learn 
number:002 
page:300 
====================

注意:

当要获取属性值时,如list id=’001’,用attrib方法。

当要获取节点值时,如<head>bookone</head>中的bookone用text方法。

当要获取节点名时,用tag方法。

》》》》》参考1:http://www.cnblogs.com/xiaowuyi/archive/2012/10/17/2727912.html

》》》》》参考2:http://blog.csdn.net/laoyaotask/article/details/41384719

XML解析(DOM、ElementTree)及转换为JSON的更多相关文章

  1. 将XML文件中的内容转换为Json对象

    using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Xml;u ...

  2. Python XML解析之ElementTree

    参考网址: http://www.runoob.com/python/python-xml.html https://docs.python.org/2/library/xml.etree.eleme ...

  3. XML 解析---dom解析和sax解析

    眼下XML解析的方法主要用两种: 1.dom解析:(Document Object Model.即文档对象模型)是W3C组织推荐的解析XML的一种方式. 使用dom解析XML文档,该解析器会先把XML ...

  4. XML解析——DOM解析

    XML:可扩展性标记语言,主要用来传输和存储数据,相对于HTML的各种标签规范,XML的标签可以让用户根据语义自己进行定义,适用于web传输. JSON和XML的区别: (1).XML定义 扩展标记语 ...

  5. Android中XML解析-Dom解析

    Android中需要解析服务器端传过来的数据,由于XML是与平台无关的特性,被广泛运用于数据通信中,有的时候需要解析xml数据,格式有三种方式,分别是DOM.SAX以及PULL三种方式,本文就简单以D ...

  6. Xml解析(Dom解析xml)

    xml四种解析方式: DOM 平台无关的官方解析方式 优点:形成了树结构,直观好理解,代码更易编写 解析过程中树结构保留在内存中,方便修改 缺点:当xml文件较大时,对内存耗费比较大,容易影响解析性能 ...

  7. XML解析(DOM)

    001 public class DOM_Parser { 002   003     public static void main(String[] args) { 004         try ...

  8. XML解析之DOM详解及与SAX解析方法的比较

    XML解析(DOM) XML文件解析方法介绍 我们所用到的NSXMLParser是采用SAX方法解析 SAX(Simple API for XML) 只能读,不能修改,只能顺序访问,适合解析大型XML ...

  9. XML概念定义以及如何定义xml文件编写约束条件java解析xml DTD XML Schema JAXP java xml解析 dom4j 解析 xpath dom sax

    本文主要涉及:xml概念描述,xml的约束文件,dtd,xsd文件的定义使用,如何在xml中引用xsd文件,如何使用java解析xml,解析xml方式dom sax,dom4j解析xml文件 XML来 ...

  10. 使用XWAF框架(5)——XML解析器:CXDP

    XWAF推出了自己的组合式XML文档解析器,英文名叫:“CXDP”,是“Combined XML Document Parser”的缩写.核心代码属XWAF原创,注释.日志和帮助文档采用全中文描述,特 ...

随机推荐

  1. Spring Cloud 入门教程(十):和RabbitMQ的整合 -- 消息总线Spring Cloud Netflix Bus

    在本教程第三讲Spring Cloud 入门教程(三): 配置自动刷新中,通过POST方式向客户端发送/refresh请求, 可以让客户端获取到配置的最新变化.但试想一下, 在分布式系统中,如果存在很 ...

  2. Flutter - 自动生成Android & iOS图标

    对于要发布的app来说,做图标是一个麻烦的事,你需要知道N个图标的分辨率,然后用PhotoShop一个个修改导出. PS好图标之后,按照各自的位置放进去. ********************** ...

  3. Webpack 2 视频教程 007 - 配置 WDS 进行浏览器自动刷新

    原文发表于我的技术博客 这是我免费发布的高质量超清「Webpack 2 视频教程」. Webpack 作为目前前端开发必备的框架,Webpack 发布了 2.0 版本,此视频就是基于 2.0 的版本讲 ...

  4. 跨平台、跨语言应用开发,Elements 介绍

    目录 1,Elements 介绍 2,Elements 版本 3,Elements 能干嘛 4,Elements  IDES 5,Elements 工具 1,Elements 介绍 RemObject ...

  5. NuGet 使用笔记

    环境准备 1. 下载nuget : https://www.nuget.org/downloads 2. 设置到环境变量Path, 使生效:在Cmd打入: set path=abc  关闭Cmd (C ...

  6. Sql语句报ORA-01795: 列表中的最大表达式数为 1000

    错误信息:java.sql.SQLException: ORA-01795: 列表中的最大表达式数为 1000,错误信息如下: serviceid是:work -------------other W ...

  7. 数据结构--图 的JAVA实现(下)

    在上一篇文章中记录了如何实现图的邻接表.本文借助上一篇文章实现的邻接表来表示一个有向无环图. 1,概述 图的实现与邻接表的实现最大的不同就是,图的实现需要定义一个数据结构来存储所有的顶点以及能够对图进 ...

  8. js和JQuery区别

    this.class="btn-default btn-info"; $(this).toggleClass("btn-default btn-info"); ...

  9. Flask-论坛开发-5-memcached缓存系统

    对Flask感兴趣的,可以看下这个视频教程:http://study.163.com/course/courseLearn.htm?courseId=1004091002 ### 介绍:哪些情况下适合 ...

  10. PDF文档打印太慢怎么办

    如下图,用Adobe Acrobat打开PDF文件,然后[高级]-打勾[作为图像打印]即可