1. 程式人生 > >Python解析大XML檔案及讀取XML不全的問題

Python解析大XML檔案及讀取XML不全的問題

之前用python的minidom寫過解析xml的指令碼檔案,在前期是比較好用的,因為xml檔案比較小。但是當xml檔案超過了70M的時候,minidom不僅效率低,而且會佔用非常大的記憶體空間,因為他是將整個xml讀入進去並且按照整個xml樹進行建樹(雖然這樣寫程式碼邏輯清晰,但是確實效率低,記憶體佔用高)。70M的xml,我8G記憶體吃了4個多G,太可怕了。考慮到以後這個讀取的xml檔案可能還需要擴大,所以抓緊時間寫了一個一個新的讀取指令碼。

在此之前,參考了這篇文章以及這篇文章之後,決定採用裡面說的ET_iter方式實現。

然後,我找到了這個博主的文章,仿照這上面的程式碼進行了進行了編寫:

# 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()
前面使用自己構造的xml檔案發現沒有問題:
<?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>
不過當真正使用的時候,發現有時候文字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.
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->