[英]Parse large python xml using xmltree
我有一個Python腳本,可以解析巨大的xml文件(最大的是446 MB)
try:
parser = etree.XMLParser(encoding='utf-8')
tree = etree.parse(os.path.join(srcDir, fileName), parser)
root = tree.getroot()
except Exception, e:
print "Error parsing file "+str(fileName) + " Reason "+str(e.message)
for child in root:
if "PersonName" in child.tag:
personName = child.text
這是我的xml的樣子:
<?xml version="1.0" encoding="utf-8"?>
<MyRoot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" uuid="ertr" xmlns="http://www.example.org/yml/data/litsmlv2">
<Aliases authority="OPP" xmlns="http://www.example.org/yml/data/commonv2">
<Description>myData</Description>
<Identifier>43hhjh87n4nm</Identifier>
</Aliases>
<RollNo uom="kPa">39979172.201167159</RollNo>
<PersonName>Miracle Smith</PersonName>
<Date>2017-06-02T01:10:32-05:00</Date>
....
我要做的就是獲取PersonName標簽的內容。 我不在乎的其他標簽。
不幸的是,我的文件很大,使用上面的代碼時,我總是收到此錯誤消息:
Error parsing file 2eb6d894-0775-e611.xml Reason unknown error, line 1, column 310915857
Error parsing file 2ecc18b5-ef41-e711-80f.xml Reason Extra content at the end of the document, line 1, column 3428182
Error parsing file 2f0d6926-b602-e711-80f4-005.xml Reason Extra content at the end of the document, line 1, column 6162118
Error parsing file 2f12636b-b2f5-e611-80f3-00.xml Reason Extra content at the end of the document, line 1, column 8014679
Error parsing file 2f14e35a-d22b-4504-8866-.xml Reason Extra content at the end of the document, line 1, column 8411238
Error parsing file 2f50c2eb-55c6-e611-80f0-005056a.xml Reason Extra content at the end of the document, line 1, column 7636614
Error parsing file 3a1a3806-b6af-e611-80ef-00505.xml Reason Extra content at the end of the document, line 1, column 11032486
我的XML非常好,沒有多余的內容。似乎大文件解析會導致錯誤。 我已經看過iterparse(),但是它要實現的目標似乎很復雜,因為它提供了整個DOM的解析,而我只希望位於根目錄下的一個標記。 另外,不是給我一個很好的示例以按標簽名稱獲取正確的值嗎?
我應該使用正則表達式解析還是grep / awk方式做到這一點? 或對我的代碼進行的任何調整都會使我在這些巨大的文件中獲得“人名”?
更新:嘗試過此示例,它似乎正在從xml打印整個世界,除了我的標簽?
是否iterparse從文件的底部讀取到頂部? 在那種情況下,到達頂部即我的PersonName標簽將花費很長時間。 我嘗試更改下面的行以讀取end to start events =(“ end”,“ start”),它做同樣的事情!!!
path = []
for event, elem in ET.iterparse('D:\\mystage\\2-80ea-005056.xml', events=("start", "end")):
if event == 'start':
path.append(elem.tag)
elif event == 'end':
# process the tag
print elem.text // prints whole world
if elem.tag == 'PersonName':
print elem.text
path.pop()
在這種情況下,Iterparse並不難使用。
temp.xml
是您的問題中顯示的文件,最后以</MyRoot>
為一行。
如果可以的話,可以將source =
視為鍋爐庫,它將分析xml文件並逐元素返回該數據塊,指示該塊是元素的“開始”還是“結束”,並提供有關元素的信息。元件。
在這種情況下,我們只需要考慮“開始”事件。 我們注意“ PersonName”標簽並拾取其文本。 在xml文件中找到了唯一的一項后,我們放棄了處理。
>>> from xml.etree import ElementTree
>>> source = iter(ElementTree.iterparse('temp.xml', events=('start', 'end')))
>>> for an_event, an_element in source:
... if an_event=='start' and an_element.tag.endswith('PersonName'):
... an_element.text
... break
...
'Miracle Smith'
編輯,以回應評論中的問題:
通常,您不會這樣做,因為iterparse
旨在用於大塊xml。 但是,通過將字符串包裝在StringIO
對象中,可以使用iterparse
處理iterparse
。
>>> from xml.etree import ElementTree
>>> from io import StringIO
>>> xml = StringIO('''\
... <?xml version="1.0" encoding="utf-8"?>
... <MyRoot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" uuid="ertr" xmlns="http://www.example.org/yml/data/litsmlv2">
... <Aliases authority="OPP" xmlns="http://www.example.org/yml/data/commonv2">
... <Description>myData</Description>
... <Identifier>43hhjh87n4nm</Identifier>
... </Aliases>
... <RollNo uom="kPa">39979172.201167159</RollNo>
... <PersonName>Miracle Smith</PersonName>
... <Date>2017-06-02T01:10:32-05:00</Date>
... </MyRoot>''')
>>> source = iter(ElementTree.iterparse(xml, events=('start', 'end')))
>>> for an_event, an_element in source:
... if an_event=='start' and an_element.tag.endswith('PersonName'):
... an_element.text
... break
...
'Miracle Smith'
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.