Python使用XPATH解析特定结构XML文件速度提升方法
2016-04-01 18:27
1091 查看
首先
来看XML格式
类似这样的FieldName中的i与FieldValue中同样i值的两部分组成字段的字段名和值,这样的字段有数百个,而我们可能只需要从中提取几个。开始的解决方案是
1. 建立要获取字段字段名的列表list_n,如list_n = [‘a’, ‘b’, ‘d’]
2. 建立以i值为key,FieldName中对应的text为值的字典dict_i_name,且value为list_n中的值,如
dict_i_name = {‘1’: ‘a’, ‘2’: ‘b’, ‘4’:’d’}
3. 在Vv这个Element里遍历V,当
假设有300个字段,有10000个Vv标签,那么需要遍历300*10000次才完成。
中间方法:
假设我们需要提取n个字段,而最后一个字段的位置为i=’x’,那么如果加入一个计数器cnt记录已取到的当前Vv标签中值的个数,循环后面再做一个判断,如果cnt>=n,则break。遍历次数10000*x,同时还需要做10000*n次自增和10000*x次数值大小比较的判断,自增和判断先不考虑,若n=8,x=10,则只需要10000*10次遍历,减少很多很多。但其对x特别依赖,很不幸,还真有一个文件x是最后一个!这样不仅没减少遍历次数,反而增加了自增和比较……
最终方法:
所以还是需要寻找更好的方法,在网上大致一搜,没找到最需要的方法,找官方的doc,xml.etree.elementtree中19.7.2节中介绍的XPath Support可以满足要求
之前只知道find(‘tag’),而不知道其他的。原来find/findall还能有这么多不同的变换!
经过思考,使用一下方法:
其中,parent_node是V的父节点,即Vv,dict_i_name与上述相同,attrib_name是V标签中的attrib,即i,df_input是一个DataFrame,其column为list_n。
遍历dict_i_name中的key,即’1’, ‘2’, ‘4’,对应的condition为
的意思为寻找parent_node标签下的子标签(V)中,所有有attrib为i,且i=’1’的所有Element,注意result是Element类型的。然后再用result.text就获得到该字段的值了。
实测速度比最初的方法快太多了,与中间方法中最好的情况没什么差别。虽然不知道实现原理,但还是满足我的需要了。
import xml.etree.cElementTree as et
来看XML格式
<?xml version="1.0" encoding="UTF-8"?> <File xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FileFormat.xsd"> <FileHeader> <DateTime>2016-01-06T03:30:10+08:00</DateTime> </FileHeader> <Objects> <ObjectType>EutranCellTdd</ObjectType> <FieldName> <N i="1">a</N> <N i="2">b</N> <N i="3">c</N> <N i="4">d</N> <N i="5">f</N> <N i="6">g</N> <N i="7">h</N> <N i="8">i</N> <N i="9">j</N> <N i="10">k</N> </FieldName> <FieldValue> <Vv Label="xxx"> <V i="1">1</V> <V i="2">汉字</V> <V i="3">还是汉字</V> <V i="4">一直是汉字</V> <V i="5">1</V> <V i="6">怎样?</V> <V i="7"></V> <V i="8"></V> <V i="9"></V> <V i="10">{0}</V> </Vv> </Objects> </File>
类似这样的FieldName中的i与FieldValue中同样i值的两部分组成字段的字段名和值,这样的字段有数百个,而我们可能只需要从中提取几个。开始的解决方案是
1. 建立要获取字段字段名的列表list_n,如list_n = [‘a’, ‘b’, ‘d’]
2. 建立以i值为key,FieldName中对应的text为值的字典dict_i_name,且value为list_n中的值,如
dict_i_name = {‘1’: ‘a’, ‘2’: ‘b’, ‘4’:’d’}
3. 在Vv这个Element里遍历V,当
dict_i_name[V.attrib['i']] in list_n的时候,就把该字段的值拿出来,存储起来
假设有300个字段,有10000个Vv标签,那么需要遍历300*10000次才完成。
中间方法:
假设我们需要提取n个字段,而最后一个字段的位置为i=’x’,那么如果加入一个计数器cnt记录已取到的当前Vv标签中值的个数,循环后面再做一个判断,如果cnt>=n,则break。遍历次数10000*x,同时还需要做10000*n次自增和10000*x次数值大小比较的判断,自增和判断先不考虑,若n=8,x=10,则只需要10000*10次遍历,减少很多很多。但其对x特别依赖,很不幸,还真有一个文件x是最后一个!这样不仅没减少遍历次数,反而增加了自增和比较……
最终方法:
所以还是需要寻找更好的方法,在网上大致一搜,没找到最需要的方法,找官方的doc,xml.etree.elementtree中19.7.2节中介绍的XPath Support可以满足要求
之前只知道find(‘tag’),而不知道其他的。原来find/findall还能有这么多不同的变换!
经过思考,使用一下方法:
def DealingSingleValue(parent_node, dict_i_name, attrib_name, list_n): for attrib_value in dict_i_name: condition = ".//*[@"+attrib_name+"='"+attrib_value+"']" result = parent_node.find(condition) df_input[dict_i_name[attrib_value]] = result.text return df_input
其中,parent_node是V的父节点,即Vv,dict_i_name与上述相同,attrib_name是V标签中的attrib,即i,df_input是一个DataFrame,其column为list_n。
遍历dict_i_name中的key,即’1’, ‘2’, ‘4’,对应的condition为
condition = ".//*[@i='1']" condition = ".//*[@i='2']" condition = ".//*[@i='4']"
result = parent_node.find(condition)
的意思为寻找parent_node标签下的子标签(V)中,所有有attrib为i,且i=’1’的所有Element,注意result是Element类型的。然后再用result.text就获得到该字段的值了。
实测速度比最初的方法快太多了,与中间方法中最好的情况没什么差别。虽然不知道实现原理,但还是满足我的需要了。
相关文章推荐
- 学习python单元测试框架nose之---03nose的xml测试报告输出
- 使用python的zabbix_api模块
- 学习python单元测试框架nose之---02nose多进程并行测试
- IP地址地理位置接口(python版)
- 学习python单元测试框架nose之---01nose框架初探
- python 多线程
- A Byte of Python 笔记(9) 面向对象编程
- [Java学习] Iterator, foreach, generics and callback in Java, C# and Python
- Python kmean
- Install Python 3.5.1 on Windows
- python文件和目录操作方法大全(含实例)
- python rpyc的应用 ——聊天的功能(带认证)
- Python开发测试工具(一)—Monkey
- python之js/url/python互动
- numpy
- python依赖包numpy、scipy、scikit-learn运行冲突解决方案
- think python学习心得-(6)利用words.txt来进行填字游戏
- Python中的threading
- Spark入门(Python版)
- 安装配置远程ipython notebook