Python使用XPATH解析特定结构XML文件速度提升方法

首先

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就获得到该字段的值了。
实测速度比最初的方法快太多了,与中间方法中最好的情况没什么差别。虽然不知道实现原理,但还是满足我的需要了。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值