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文件加载到内 ...
随机推荐
- [Swift]LeetCode916.单词子集 | Word Subsets
We are given two arrays A and B of words. Each word is a string of lowercase letters. Now, say that ...
- redux-thunk 源码学习记录
redux触发store更新,使用的dispatch(action),在关于createStore的源码解读中可以看到,store.dispatch限制了action必须是一个纯对象.是为了保持red ...
- 9.Flask Cookie和Session
1.1.概念 cookie:在网站中,http请求是无状态的.也就是说即使第一次和服务器连接后并且登录成功后,第二次请求服务器依然不能知道当前请求是哪个用户.cookie的出现就是为了解决这个问题,第 ...
- Git的使用--如何将本地项目上传到Github(三种简单、方便的方法)
一.第一种方法: 1.首先你需要一个github账号,所以还没有的话先去注册吧! https://github.com/ 我们使用git需要先安装git工具,这里给出下载地址,下载后一路(傻瓜式安装) ...
- DOM事件第二弹(UIEvent事件)
此文章主要总结UIEvent相关的事件,如有不对的地方,欢迎指正. 一.uitls.js(绑定事件公共类) var fixs = { 'focusin': { standard: 'focus', i ...
- 说一说MVC的Authentication过滤(四)
前沿: 一般情况下,在我们做访问权限管理的时候,会把用户的正确登录后的基本信息保存在Session中,以后用户每次请求页面或接口数据的时候,拿到 Session中存储的用户基本信息,查看比较他有没有登 ...
- 【offer收割机必备】我简历上的Java项目都好low,怎么办?
这篇文章我们来聊一聊,在系统设计和项目经验这两块,应该如何充分的准备,才能拿出有技术含量的项目经验战胜跟你同台竞技的其他工程师,征服你的面试官,收获各种心仪的offer. (1)高级工程师必备:系统设 ...
- es6学习笔记--模板字符串
这几天简单看了一下深入浅出es6这本书,感觉特实用,学习了一个新特性---模板字符串在项目开发中,拼接字符串是不可缺少的,动态创建dom元素以及js操作数据都要拼接字符串,在es6出来之前,我们都通常 ...
- 从0打卡leetcode之day 3 -- 最大子序列和
前言 就有要把leetcode的题刷完,每天一道题,每天进步一点点 从零打卡leetcode之day 3 题目描述: 给定一个int类型的数组,求最大子序列的和. 也就是说,从这个数组中截取一个子数组 ...
- SpringCloud入门之常用的配置文件 application.yml和 bootstrap.yml区别
作者其他技术文章 1) Spring Boot 简介 2)SpringCloud入门之YAML格式文件规范学习 3)SpringCloud入门之Spring Boot多环境配置切换指南 4) Elas ...