Python XML解析之DOM
API导入:
from xml.dom.minidom import parse
from xml.dom.minidom import parseString
import xml.dom.minidom
dom和etree是xml package目录下的两个subpackage,minidom和ElementTree是dom和etree下的两个module文件,以.py后缀,其中定义了一系列的类和方法。
Document.documentElement相当于Etree中的tree.getroot()用于获取整个树唯一的根节点
概念解析:
1.DOMImplementation
2.Node
Node是最重要的类,XML被解析为一个树,所有的节点都是都是node的子类,这些节点可以是element、comments等等,官网列出的节点类型就有:
ELEMENT_NODE, ATTRIBUTE_NODE, TEXT_NODE, CDATA_SECTION_NODE, ENTITY_NODE, PROCESSING_INSTRUCTION_NODE, COMMENT_NODE,DOCUMENT_NODE, DOCUMENT_TYPE_NODE, NOTATION_NODE,每个节点有一个数字表示,只要是node类型就可以使用node.nodeType来判断他属于哪一种node,例如if child.nodeType==child.ELEMENT_NODE:或者if child.nodeType==1: --两者等价
3.NodeList --通过getElementsByTagName()方法返回的nodelist,此方法只有element和document两个类有。
4.DocumentType
5.Document --整个XML文件解析树,包含所有element、attribute、comments、text等等,也是node的子类。
6.Element
7.Attr --element的属性,这个类型的node只能由Element.getAttributeNode(attrname)来获取,无法遍历获取,而且其既不是element node的子节点也不是兄弟节点。几乎从无必要获取此节点,直接使用element类的getAttribute(attrname)来得到属性的值即可。
8.Comment --comment节点,表示XML文件注释节点
9.Text --xml.etree.ElementTree中的text表示的是element中的内容,而这里的text类型表示一个node,这个node可以是element中的data节点也可以是element之间的换行和制表符(\n\t),如果是element的data内容那么此text是element的唯一子节点,通过childNodes[0].data或firstChild.data获取element内容,如果是换行制表符那么此节点element的兄弟节点。
10.ProcessingInstruction
除node类之外,对于XML解析最重要的就是Document类和Element、text、Comment、Attr等类,前者配合parse()或parseString()将xml文件或字符串在内存中实例化为一个tree(document类型),后边的类用于对XML树做各种操作和查询。
鉴于几乎所有的可操作对象类都是继承于node类,这里贴一下node的各种属性和方法的链接:
另外再列出node一些常见的属性和方法:
Node.nodeType --详见上边对Node类的解释
Node.attributes --只有element类型的node才有此属性
Node.childNodes
--返回节点的子节点nodelist,与通过getElementsByTagName()获取nodelist的区别在于此方法只返回直接子节点而非全部子节点,此外这两个方法的最大区别是:childNodes返回的是所有子节点的集合,而getElementsByTagName(tagName)必须指定tagName。
Node.previousSibling --node的左兄弟节点,如果没有则返回none
Node.nextSibling --node的右兄弟节点,如果没有则返回none
Node.nodeName --不常用,因为继承于node的各种类都有自己的更便于识别的name属性,例如element.tagName
Node.appendChild(newChild)
XML文件解析示例:
--有一个如下的XML文件:proxool.xml:
<?xml version="1.0" encoding="utf-8"?>
<something-else-entirely>
<proxool>
<alias>myPool</alias>
<!-- mysql 连接配置,注意修改database_hostname为相应的数据库主机名、或IP地址 -->
<driver-url>
jdbc:mysql://dbsrv:3306/TEST?useUnicode=true&characterEncoding=UTF8
</driver-url>
<driver-class>com.mysql.jdbc.Driver</driver-class>
<!-- 用户名、密码 -->
<driver-properties>
<property name="user" value="leo" />
<property name="password" value="leo" />
</driver-properties>
<!--自动侦察各个连接状态的时间间隔(毫秒),侦察到空闲的连接就马上回收,超时的销毁 -->
<house-keeping-sleep-time>30000</house-keeping-sleep-time>
<house-keeping-test-sql>select CURRENT_DATE from dual
</house-keeping-test-sql>
<!--最大连接数(默认5个),超过了这个连接数,再有请求时,就排在队列中等候,最大的等待请求数由maximum-new-connections决定 -->
<maximum-connection-count>120</maximum-connection-count>
<!--最小连接数(默认2个) -->
<minimum-connection-count>5</minimum-connection-count>
<!--没有空闲连接可以分配而在队列中等候的最大请求数,超过这个请求数的用户连接就不会被接受,该参数已经不建议使用,由simultaneous-build-throttle替代 -->
<!--一个活动连接最大活动时间默认5分钟 -->
<maximum-active-time>3600000</maximum-active-time>
<!--最少保持的空闲连接数(默认2个),如果当前的连接池中的可用连接少于这个数值, 新的连接将被建立 -->
<prototype-count>5</prototype-count>
<!--可一次建立的最大连接数 -->
<simultaneous-build-throttle>20</simultaneous-build-throttle>
<!--如果为true,那么每个被执行的SQL语句将会在执行期被log记录 -->
<trace>false</trace>
</proxool>
</something-else-entirely>
现在将其中的内容解析为如下格式:
*****
描述:最大连接数(默认5个),超过了这个连接数,再有请求时,就排在队列中等候,最大的等待请求数由maximum-new-connections决定
配置项:maximum-connection-count
配置值:120
*****
描述:xxx
配置项:xxx
配置值:xxx
*****
......
代码如下:
# -*- coding:utf-8 -*-
# 本脚本适用于Python2和3
from xml.dom.minidom import parse
import xml.dom.minidom
import sys
# file = sys.argv[1]
file = "/root/proxool.xml"
# 先写一个判断节点是否包含element类型子节点的判断函数
def has_element_child(nodename):
has_element_child = 0
for child in nodename.childNodes:
if child.nodeType==1:
has_element_child += 1
return has_element_child
# 定义解析示例XML文件的方法
def parse_xml(file):
if not file:
sys.exit(0)
tree = parse(file) # document类型的解析树
root = tree.getElementsByTagName('proxool')[0] # 将父节点定位到proxool element
for child in root.childNodes:
if child.nodeType==child.ELEMENT_NODE and has_element_child(child)==0: # 当node为element类型,且无element类型的子节点时
print u'配置项'+": %s" % child.tagName
print u'配置值'+": %s" % child.firstChild.data.strip()
elif child.nodeType==child.ELEMENT_NODE and has_element_child(child)>0: # 当节点包含element类型子节点时
for child_child in child.childNodes:
if child_child.nodeType==child.ELEMENT_NODE:
print u'配置项'+": %s" % child_child.getAttribute('name')
print u'配置值'+": %s" % child_child.getAttribute('value')
elif child.nodeType==child.COMMENT_NODE: # 当node为comment类型时
print "*****"
print u'描述'+": %s" % child.data
else:
pass
# 处理示例XML文件
parse_xml(file)
XML文件比较修改示例:
# -*- coding:utf-8 -*-
# 本脚本适用于Python2和3
from xml.dom.minidom import parse
import xml.dom.minidom
import sys
reload(sys)
sys.setdefaultencoding("utf-8")
old_file = sys.argv[1]
new_file = sys.argv[2]
# 先写一个判断节点是否包含element类型子节点的判断函数
def has_element_child(nodename):
has_element_child = 0
for child in nodename.childNodes:
if child.nodeType==1:
has_element_child += 1
return has_element_child
# 定义解析示例XML文件的方法
def match_xml(old_file,new_file):
if not new_file:
sys.exit(0)
tree_old = parse(old_file) # document类型的解析树
tree_new = parse(new_file)
root_old = tree_old.getElementsByTagName('proxool')[0] # 将父节点定位到proxool
root_new = tree_new.getElementsByTagName('proxool')[0]
old_dict = {} # 定义旧XML文件的tag和data的字典
new_dict = {}
for child in root_old.childNodes: #将tagName和data存入old_dict{}中
if child.nodeType==child.ELEMENT_NODE and has_element_child(child)==0: # 当node为element类型,且无element类型的子节点时
old_dict[child.tagName] = child.firstChild.data.replace("\n", "").replace("\t", "")
for child in root_new.childNodes:
if child.nodeType==child.ELEMENT_NODE and has_element_child(child)==0:
new_dict[child.tagName] = child.firstChild.data.replace("\n", "").replace("\t", "")
for tag,data in new_dict.items():
if not old_dict.get(tag): # 当旧XML中找不到对应的tag时,进行tag新增操作
new_element=tree_new.getElementsByTagName(tag)
for child in new_element:
root_old.appendChild(child) # 新增element节点
with open('proxool_modified.xml','w') as f:
tree_old.writexml(f)
f.close
# 处理示例XML文件
match_xml(old_file,new_file)
--比较XML文件:
# python xml_match_dom.py proxool.xml proxool.xml.new
--然后就可以在proxool_modified.xml中看到新的XML内容了
Python XML解析之DOM的更多相关文章
- Python XML解析之ElementTree
参考网址: http://www.runoob.com/python/python-xml.html https://docs.python.org/2/library/xml.etree.eleme ...
- Python XML解析(转载)
Python XML解析 什么是XML? XML 指可扩展标记语言(eXtensible Markup Language). 你可以通过本站学习XML教程 XML 被设计用来传输和存储数据. XML是 ...
- python大法好——Python XML解析
Python XML解析 什么是XML? XML 被设计用来传输和存储数据. XML是一套定义语义标记的规则,这些标记将文档分成许多部件并对这些部件加以标识. 它也是元标记语言,即定义了用于定义其他与 ...
- - XML 解析 总结 DOM SAX PULL MD
目录 目录 XML 解析 总结 DOM SAX PULL MD 几种解析方式简介 要解析的内容 DOM 解析 代码 输出 SAX 解析 代码 输出 JDOM 解析 代码 输出 DOM4J 解析 代码 ...
- Python XML解析
什么是XML? XML 指可扩展标记语言(eXtensible Markup Language). 你可以通过本站学习XML教程 XML 被设计用来传输和存储数据. XML是一套定义语义标记的规则,这 ...
- Python XML 解析
什么是 XML? XML 指可扩展标记语言(eXtensible Markup Language). XML 被设计用来传输和存储数据. XML 是一套定义语义标记的规则,这些标记将文档分成许多部件并 ...
- Python XML 解析Ⅱ
make_parser方法 以下方法创建一个新的解析器对象并返回. 参数说明: parser_list - 可选参数,解析器列表 parser方法 以下方法创建一个 SAX 解析器并解析xml文档: ...
- XML解析之DOM详解及与SAX解析方法的比较
XML解析(DOM) XML文件解析方法介绍 我们所用到的NSXMLParser是采用SAX方法解析 SAX(Simple API for XML) 只能读,不能修改,只能顺序访问,适合解析大型XML ...
- 【Java】XML解析之DOM
DOM介绍 DOM(Document Object Model)解析是官方提供的XML解析方式之一,使用时无需引入第三方包,代码编写简单,方便修改树结构,但是由于DOM解析时是将整个XML文件加载到内 ...
随机推荐
- OpenOCD的概念,安装和使用
概念: OpenOCD是一个运行于PC上的开源调试软件,它可以控制包括Wiggler之内的很多JTAG硬件:我们可以将它理解为一种GDB服务程序.OpenOCD的源码只能通过SVN下载,地址是:svn ...
- Python内置函数(7)——bytearray
英文文档: class bytearray([source[, encoding[, errors]]]) Return a new array of bytes. The bytearray cla ...
- expect--自动批量分发公钥脚本
1.在使用之前,先安装epel源,yum install expect -y2.写分发脚本,后缀为exp #!/usr/bin/expect set host_ip [lindex $argv 0] ...
- SQLplus下命令输入错误如何删掉重新输入
如下当我们输入命令出错时想删掉重新输入,按delete或者backspace键无法删除且出现如下情况: SQL> show urerej ^H^H^H^H^H 可以是使用ctrl+backsp ...
- 8分钟学会使用AutoMapper
一.什么是AutoMapper与为什么用它. 它是一种对象与对象之间的映射器,让AutoMapper有意思的就是在于它提供了一些将类型A映射到类型B这种无聊的实例,只要B遵循AutoMapper已经建 ...
- .Net 调用中国气象台Web Service
接口地址http://www.webxml.com.cn/WebServices/WeatherWebService.asmx 调用步骤:项目添加服务引用-高级-添加web引用 简单代码: web服务 ...
- Owin学习笔记(二) 中间件开发
Owin中也有类似于ASP.NET的管道,以前在做ASP.NET项目的时候,可以制作很多不同功能HttpHandler或者HttpModule并注册在Web.config中重复使用.在Owin的管道中 ...
- Python爬虫入门教程 29-100 手机APP数据抓取 pyspider
1. 手机APP数据----写在前面 继续练习pyspider的使用,最近搜索了一些这个框架的一些使用技巧,发现文档竟然挺难理解的,不过使用起来暂时没有障碍,估摸着,要在写个5篇左右关于这个框架的教程 ...
- Java基础12:深入理解Class类和Object类
更多内容请关注微信公众号[Java技术江湖] 这是一位阿里 Java 工程师的技术小站,作者黄小斜,专注 Java 相关技术:SSM.SpringBoot.MySQL.分布式.中间件.集群.Linux ...
- sql distinct详解以及优化
一.distinct简介 distinct这个关键字来过滤掉多余的重复记录只保留一条,但往往只用 它来返回不重复记录的条数,而不是用它来返回不重记录的所有值.其原因是distinct只有用二重循环查询 ...