Python解析大XML檔案及讀取XML不全的問題
之前用python的minidom寫過解析xml的指令碼檔案,在前期是比較好用的,因為xml檔案比較小。但是當xml檔案超過了70M的時候,minidom不僅效率低,而且會佔用非常大的記憶體空間,因為他是將整個xml讀入進去並且按照整個xml樹進行建樹(雖然這樣寫程式碼邏輯清晰,但是確實效率低,記憶體佔用高)。70M的xml,我8G記憶體吃了4個多G,太可怕了。考慮到以後這個讀取的xml檔案可能還需要擴大,所以抓緊時間寫了一個一個新的讀取指令碼。
在此之前,參考了這篇文章以及這篇文章之後,決定採用裡面說的ET_iter方式實現。
然後,我找到了這個博主的文章,仿照這上面的程式碼進行了進行了編寫:
前面使用自己構造的xml檔案發現沒有問題:# coding=utf-8 __author__ = 'Arthur' import mysql.connector import sys import xml.etree.cElementTree as ET if __name__=="__main__": for event, elem in ET.iterparse("test2.xml", events=('start','end')): if event == 'start': if elem.tag=='product' or elem.tag=='property' or elem.tag=='evaluation': print(elem.attrib) elif elem.tag == 'result': a_result = {} a_result=elem.attrib a_result['value']=elem.text if(elem.text==None): print("result none") else: print(a_result) elif event == 'end': if elem.tag == 'products': print("deal with products over") elif elem.tag == 'propertys': print("deal with propertys over") elif elem.tag == 'evaluations': print("deal with evaluations over") elif elem.tag == 'results': print("deal with results over") elem.clear()
不過當真正使用的時候,發現有時候文字elem.text讀取不正確,明明有值但是讀取的時候發現還是None。調了半天都不知道為什麼(因為自己構造的xml始終不是真實的,所以肯定不能完全模擬),找了半天終於找到了一段官方說明: Note iterparse() only guarantees that it has seen the “>” character of a starting tag when it emits a “start” event, so the attributes are defined, but the contents of the text and tail attributes are undefined at that point. The same applies to the element children; they may or may not be present.<?xml version='1.0' encoding='utf-8'?> <testresults source="ICRT EvalDB" type="data" user="unknown"> <project id_project="697" icrt_code="IC16539" name="Combined Wearables" comment=""> <snapshots> <snapshot id_snapshot="4" name="Combined snapshot" timestamp_created="1471515160" timestamp_lastchange="1482147798" time_lastchange="2016-12-19 (11:43)"> <manufacturers> <manufacturer id_manufacturer="1" name="Apple" comment="" timestamp_created="1465471929" timestamp_lastchange="0" /> <manufacturer id_manufacturer="2" name="Fitbit" comment="" timestamp_created="1465471929" timestamp_lastchange="0" /> </manufacturers> <productgroups> <productgroup id_productgroup="1" name="SMARTWATCH" comment="" timestamp_created="1465471929" timestamp_lastchange="0" /> <productgroup id_productgroup="2" name="FITNESS TRACKER" comment="" timestamp_created="1465471929" timestamp_lastchange="0" /> </productgroups> <products> <product id_product="10" icrt_code="IC16539-0036-00" modelname="Gear S2" completename="Samsung Gear S2" shortname="" systemmodelid="" releasedate="" labreportdate="2016-05-27T00:00:00.000" labarrivaldate="2016-05-06T00:00:00.000" boughtbyorganisation="WHICH" serialnumber="RFAH105HFQF" articlenumber="8.80608808859E+12" comment="" id_productgroup="1" id_manufacturer="9" sortorder="0" batch="1" labcode="" parentmodelcode="" similarmodelscodes="" testtype="" picture_lores="" picture_hires="" timestamp_created="1465471929" timestamp_lastchange="1466062628" /> <product id_product="11" icrt_code="IC16539-0040-00" modelname="Vivofit 3" completename="Garmin Vivofit 3" shortname="" systemmodelid="" releasedate="" labreportdate="2016-06-15T00:00:00.000" labarrivaldate="2016-06-24T00:00:00.000" boughtbyorganisation="WHICH" serialnumber="4R0201708" articlenumber="53759 15457" comment="" id_productgroup="2" id_manufacturer="3" sortorder="0" batch="2" labcode="" parentmodelcode="" similarmodelscodes="" testtype="" picture_lores="" picture_hires="" timestamp_created="1469800248" timestamp_lastchange="1475593828" /> <product id_product="12" icrt_code="IC16539-0047-00" modelname="Go" completename="Withings Go" shortname="" systemmodelid="" releasedate="" labreportdate="2016-06-15T00:00:00.000" labarrivaldate="2016-06-24T00:00:00.000" boughtbyorganisation="WHICH" serialnumber="00:24:E4:39:F0:0D" articlenumber="700546 701481" comment="" id_productgroup="2" id_manufacturer="10" sortorder="0" batch="2" labcode="" parentmodelcode="" similarmodelscodes="" testtype="" picture_lores="" picture_hires="" timestamp_created="1469800248" timestamp_lastchange="1475593828" /> </products> <propertygroups> <propertygroup id_propertygroup="36" name="Features|inventory" comment="" timestamp_created="1465222484" timestamp_lastchange="0" /> <propertygroup id_propertygroup="37" name="Features|Smart" comment="" timestamp_created="1465222484" timestamp_lastchange="0" /> </propertygroups> <propertys> <property id_property="381" id_propertygroup="" binding="FIRMWARE" name="Firmware version on device" comment="" max="0" min="0" unit="" precision="0" type="String" use="1" testprogram="1.1.3" timestamp_created="1465222485" timestamp_lastchange="1465222485" /> <property id_property="382" id_propertygroup="" binding="COMPATABILITY" name="What phones are compatible with device" comment="" max="0" min="0" unit="" precision="0" type="String" use="1" testprogram="1.1.7" timestamp_created="1465222485" timestamp_lastchange="1468831229" /> </propertys> <calculationtypes> <calculationtype id_calculationtype="0" name="Arithmetic mean calculation" /> <calculationtype id_calculationtype="5" name="Geometric mean calculation" /> <calculationtype id_calculationtype="1" name="Versatility calculation" /> <calculationtype id_calculationtype="2" name="Free formula calculation (complex)" /> <calculationtype id_calculationtype="3" name="Minimum calculation" /> <calculationtype id_calculationtype="4" name="Maximum calculation" /> </calculationtypes> <evaluations> <evaluation id_evaluation="3165" id_childs="3185,3199,3176,3166,3180,3175,3195,3615" id_parent="0" id_calculationtype="0" name="total test result" binding="" use_inheritna="0" use_lookuptable="0" use_limiting="0" weighting_normalized="0" weighting_given="1" lookuptable="0.5,1.5,2.5,3.5,4.5,5.5" unit="" precision="3" timestamp_created="1465222499" timestamp_lastchange="1467972637" /> <evaluation id_evaluation="3166" id_childs="3167" id_parent="3165" id_calculationtype="0" name="App" binding="" use_inheritna="0" use_lookuptable="0" use_limiting="0" weighting_normalized="0" weighting_given="0" lookuptable="0.5,1.5,2.5,3.5,4.5,5.5" unit="" precision="3" timestamp_created="1465222499" timestamp_lastchange="1467969418" /> </evaluations> <results> <result id_product="1" id_evaluation="3165" is_downgrading="0" downgrading_value="">3.98268146</result> <result id_product="1" id_evaluation="100000635" is_downgrading="0" downgrading_value="">Provides reminders to stand every hour. You can set progress updates to be given every 4, 6 or 8 hours. Congratulates you when you complete a goal and provides individual feedback and history of activity data. Notifications to focus on specific goals _eg activity__, tells you what percentage of your goal is complete </result> <result id_product="1" id_evaluation="100000636" is_downgrading="0" downgrading_value="">1</result> <result id_product="1" id_evaluation="100000637" is_downgrading="0" downgrading_value="">Using the workout app gives you a breakdown of steps, total and active calories and distance covered for that session as well adding these values onto daily accumulated totals</result> <result id_product="1" id_evaluation="100000638" is_downgrading="0" downgrading_value="">1</result> </results> </snapshot> </snapshots> </project> </testresults>
If you need a fully populated element, look for “end” events instead.
好了,原來是因為start事件開始的時候只能保證屬性存在,不能保證value值以及子節點存在。所以目測改成了使用end事件響應就對了。然而我改成end事件響應過後,發現居然連小xml檔案讀取都有問題……這是為什麼呢?好在這個問題好除錯,除錯一番發現問題其實很簡單:因為我的觸發訊號是start以及end,但是start觸發過後什麼也沒有做就把elem.clear()了,結果到end事件進來響應的時候只有一個空節點了……
所以說!!!!!觸發事件一般不用使用start和end兩個觸發條件,之前看那個博主同時使用start以及end完全不必要,使用一個就好,除非你有其他特殊需求,比如需要繼續使用根節點之類的,讀取值的時候要保證是在end的時候讀取並且end時當前節點沒有clear.
最後完成的有效程式碼:
# coding=utf-8
__author__ = 'Arthur'
import mysql.connector
import sys
import xml.etree.cElementTree as ET
if __name__=="__main__":
for event, elem in ET.iterparse("test.xml", events=('end',)):#注意這裡只使用end進行觸發即可
if elem.tag=='product' or elem.tag=='property' or elem.tag=='evaluation':
print(elem.attrib)
elif elem.tag == 'result':
a_result = {}
a_result=elem.attrib
a_result['value']=elem.text
if(elem.text==None):
print("result none")
else:
print(a_result)
if elem.tag == 'products':
print("deal with products over")
elif elem.tag == 'propertys':
print("deal with propertys over")
elif elem.tag == 'evaluations':
print("deal with evaluations over")
elif elem.tag == 'results':
print("deal with results over")
elem.clear()
從調研新XML解析方法到實現重構程式碼只花了1小時,結果寫出bug調程式碼一搞就是1個半小時,蛋疼。
相關推薦
Python解析大XML檔案及讀取XML不全的問題
之前用python的minidom寫過解析xml的指令碼檔案,在前期是比較好用的,因為xml檔案比較小。但是當xml檔案超過了70M的時候,minidom不僅效率低,而且會佔用非常大的記憶體空間,因為他是將整個xml讀入進去並且按照整個xml樹進行建樹(雖然這樣寫程式碼邏輯
Android核心技術-day02-09-生成xml檔案 及 解析
AndroidManifest.xml 方式一: package com.gaozewen.savexmlinfo; import android.Manifest; import android.os.Bundle; import android.os.Environment;
python讀取xml檔案報錯xml.parsers.expat.ExpatError: XML or text declaration not at start of entity
先說明一下我之前對python的xml.dom.minidom模組不熟,遇到這個問題時先想到的是百度,結果轉了一圈回來發現大家都寫的是xml檔案中的第一行,也就是 <?xml version="1.0" encoding="GBK"?> 這個可能沒有頂格寫,有空格。可是我遇到的問
Java中讀取XML檔案,生成XML格式的字串並解析這個字串
由於最近要用的是XML格式的字串,而不用寫到檔案中,所以對原始程式碼進行了修改如下: 要讀的xml檔案 <?xml version="1.0" encoding="GB2312"?> <學生花名冊> <學生 性別 = "男">
如何讀取xml檔案,根據xml節點屬性查詢並輸出xml檔案
主要是應用SimpleXML和遞迴函式來根據key值來查詢,並將結果以xml格式輸出。 <?php header("Content-type: text/xml"); //以xml格式輸出檔案 @$key=$_GET['key']; $find=false; //echo $key."<
python 將yaml標籤檔案轉化為xml格式的標籤檔案
最近在跑SSD和Faster R-CNN深度學習程式碼,下載了一些資料集,但是這些資料集標籤檔案不是xml格式檔案,而是yaml檔案,雖然網上有線上轉化的工具,但是這種做法對我來說顯然是很低效率的。為了提高效率,自己寫了相關的程式碼。現在分享給大家。感謝Bosch Small
使用dom4j對xml檔案進行讀取和輸出操作
1.xml檔案的讀取 讀取xml檔案的方式有兩種,一種是面向模型的DOM方式,一種是面向事件的SAX方式 DOM方式原理:一次性的將xml文件加入記憶體,在記憶體中形成一顆dom樹,然後通過語言對樹的節點進行操作。 顯然這種操作查詢元素快,但
DOM物件對xml檔案的讀取和寫入
解析的XML檔案對應的java類 package com.nm; public class Employee { private String eid; private String name; private String g
C# 載入xml文件檔案及載入xml字串
//建立XmlDocument物件 XmlDocument xmlDoc = new XmlDocument(); //載入xml檔名 xmlDoc.Load(filename); //如果是xml字串,則用以下形式 xmlDoc.LoadXml(xmldata
Java如何解析某個目錄下xml檔案,將XML檔案轉換為報表資料來源?
在Java開發的報表工具FineReport中,假如在目錄下儲存了幾個XML檔案,希望把XML檔案轉換為報表資料來源,同時希望展示動態xml資料來源的效果,這時可通過引數的方式,動態獲取xml欄位中的值再作為報表資料來源。Northwind.xml記錄資料格式如下:<?
C#基礎精華06(Linq To XML,讀取xml檔案,寫入xml)
Linq To XML xml 標記語言 html xml 側重於儲存資料 html顯示資料 註釋<!-- 註釋 --> xml沒有預定義標籤 html有 核心類XElement,一個XElement表示一個元素,new XElement(“Order”
記錄Maven和Mybatis整合時打包漏掉mapper的xml檔案及其它資源
最近在把愛酷學習網的專案組織方式改成Maven,其中遇到了不少問題,最為嚴重的是,Mybatis啟動老是報繫結錯誤(找不到Mapper對應的 SQL配置),經過一番Google未能解決問題(大家都說是XML沒寫對之類的),根本就沒有懷疑到漏掉XML檔案,最後迫不得已,去查看
libxml2庫 讀取xml檔案,寫xml檔案
所用xml檔案內容: <?xml version="1.0" encoding="utf-8"?> <style name="file"> <contents name="type"> <content>.mp3&
spring-mvc.xml檔案及基本約束
" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
windows 系統在vs2010 中配置libxml2,及讀取xml程式碼例子
1、先下載libxml2 (下載地址 http://download.csdn.net/detail/luoww1/8095273),裡面包括了三個資料夾分別:zlib-1.2.3.win32 和iconv-1.9.2.win32 和libxml2-2.7.6.win32
使用Pull解析器解析XML檔案和寫XML
本文是基於黎活明老師的傳智部落格android第7個和8個視訊總結的,如果想更清楚的理解,建議觀看視訊 以下面這個xml檔案為例 <?xml version="1.0" encoding="UTF-8"?> <persons> <person
Sax 解析xml檔案時, 資料資訊不完整問題解決方法
使用Sax對xml檔案進行解析時,Sax每次只讀入2k資料,當xml檔案大於2k時,資料資訊可能回出現不完成的情況. 此時,我們只需要使用StringBuffer對資訊進行組合. 同時,在使用完StringBuffer之後,需要對StringBuffer進行清空操作.
Qt-QML-C++互動實現檔案IO系統-後繼-讀取XML檔案和建立XML檔案
在前面兩篇中,大致完成了一個檔案IO的讀和寫操作。前面兩篇文章連結 今天這個是,今天主要是寫了怎麼把配置檔案寫入到XML中 上今天的詳程式碼 QJsonObject DLFileIOSystem::DLReadXML() { qDebug()<&
TXMLDocument對XML檔案進行讀取和寫入 (bcb)
{ 讀ReportObject屬性 } Node1 := XML.DocumentElement.ChildNodes.FindNode('ReportObjectProperty'); ReportName := Node1.ChildNodes.FindNode('ReportName
IDEA中建立自定義的mybatis的Mapper.xml檔案及遇到建立後不識別的問題
在IDEA建立Mybatis的XXMapper.xml檔案: 1.先自定義建立模板: File->setting->