2017-09-04 16 views
0

我有一個像Python的:如何處理與很多孩子的大型XML文件中的1根

<report> 
    <table> 
    <detail name="John" surname="Smith"> 
    <detail name="Michael" surname="Smith"> 
    <detail name="Nick" surname="Smith"> 
    ... {a lot of <detail> elements} 
    </table> 
</report> 

我需要檢查與數據結構的XML文件是否具有屬性「名稱」元素=='姓」。

XML文件大於1 GB,並且我嘗試使用etree.parse(文件)

如何使用Python和LXML一對一地處理元素?

+1

那是什麼,你所得到的錯誤? –

+1

你想要做什麼處理? –

回答

0

考慮iterparse,它允許您在構建樹時處理元素。下面檢查是否名稱屬性相當於屬性。使用if塊進一步處理像有條件追加值的列表:

import xml.etree.ElementTree as et 

data = [] 
path = "/path/to/source.xml" 

# get an iterable 
context = et.iterparse(path, events=("start", "end")) 

# turn it into an iterator 
context = iter(context) 

# get the root element 
ev, root = next(context) 

for ev, el in context: 
    if ev == 'start' and el.tag == 'detail': 
     print(el.attrib['name'] == el.attrib['surname']) 
     data.append([el.attrib['name'], el.attrib['surname']]) 
     root.clear() 

print(data) 
# False 
# False 
# False 

# [['John', 'Smith'], ['Michael', 'Smith'], ['Nick', 'Smith']] 
+0

完美!謝謝! – user2401432

0

可能使用iterparse方法,這意味着處理大型XML文件。但是,您的文件具有特別簡單的結構。使用iterparse會不必要的複雜。

我會在一個腳本中提供兩個答案。我直接通過展示如何使用lxml解析xml中的行來回答你的問題,並提供我認爲可能是使用正則表達式更好的答案。

該代碼讀取xml中的每一行,並忽略那些不以'try ... except開頭的行。當腳本找到這樣的一行時,它將它從lxml傳遞給etree進行解析,然後顯示行中的屬性。之後,它使用正則表達式來解析出相同的屬性並顯示它們。

我強烈懷疑正則表達式會更快。

>>> from lxml import etree 
>>> report = '''\ 
... <report> 
...  <table> 
...   <detail name="John" surname="Smith"> 
...   <detail name="Michael" surname="Smith"> 
...   <detail name="Nick" surname="Smith"> 
...  </table> 
... </report>''' 
>>> import re 
>>> re.search(r'name="([^"]*)"\s+surname="([^"]*)', line).groups() 
('John', 'Smith') 
>>> for line in report.split('\n'): 
...  if line.strip().startswith('<detail'): 
...   tree = etree.fromstring(line.replace('>', '/>')) 
...   tree.attrib['name'], tree.attrib['surname'] 
...   re.search(r'name="([^"]*)"\s+surname="([^"]*)', line).groups() 
...   
('John', 'Smith') 
('John', 'Smith') 
('Michael', 'Smith') 
('Michael', 'Smith') 
('Nick', 'Smith') 
('Nick', 'Smith') 
+0

我們是否在X/HTML上使用正則表達式?不是[推薦的方法](https://stackoverflow.com/a/1732454/1422451)。 – Parfait

+0

@Parfait:你看過檔案嗎? –

1

基本上有三種標準方法來解析XML:

  • 建立一個內存Document Object Model(DOM) - 你的整個文件加載到內存中,可以沿着綠樹任意行走
  • 編寫推送SAX解析器 - 對文檔的處理成爲您可以訂閱的幾個事件(開始標記,文本,結束標記,註釋,處理指令等)的一系列事件。你註冊回調並運行解析。直到最後讀取文檔,但解析器不會構建整個文檔的內部表示。
  • 編寫的牽引StAX分析器 - 解析器流不同的事件,您按順序處理所有的人,但可以在任何時間(有用的文檔的開頭爲XML元數據的解析和停止處理)停止

lxml是一個綁定到libxml的C庫,它是DOM的一個實現,iterparse方法似乎是StAX方法的實現。 SAX解析器內置於python本身中:https://docs.python.org/3.6/library/xml.sax.html

對於您的情況,標準方法是使用SAX解析器。