2013-07-12 29 views
0

我想在python中使用ElementTree處理下面的xml。 當UserValue標題爲THIRD且其值不爲空時,我需要查找所有實例名稱。所以在這個例子中,結果將是大理石和鼠標。可以findall或finditer在這個python ElementTree示例中使用嗎?

<?xml version="1.0" encoding="utf-8"?> 
<Data> 
    <Instance id="61" name="atom"> 
     <UserData id="30"> 
      <UserValue value="" title="FIRST"></UserValue> 
      <UserValue value="" title="SECOND"></UserValue> 
      <UserValue value="" title="THIRD"></UserValue> 
      <UserValue value="watch" title="FOURTH"></UserValue> 
     </UserData> 
    </Instance> 
    <Instance id="64" name="marble" ref="33"> 
     <UserData id="34"> 
      <UserValue value="" title="FIRST"></UserValue> 
      <UserValue value="stuff" title="SECOND"></UserValue> 
      <UserValue value="airplane" title="THIRD"></UserValue> 
      <UserValue value="" title="FOURTH"></UserValue> 
     </UserData> 
    </Instance> 
    <Instance id="65" name="rock"> 
     <UserData id="36"> 
      <UserValue value="" title="FIRST"></UserValue> 
      <UserValue value="" title="SECOND"></UserValue> 
      <UserValue value="" title="THIRD"></UserValue> 
      <UserValue value="" title="FOURTH"></UserValue> 
     </UserData>  
    </Instance> 
    <Instance id="66" name="mouse"> 
     <UserData id="38"> 
      <UserValue value="" title="FIRST"></UserValue> 
      <UserValue value="" title="SECOND"></UserValue> 
      <UserValue value="rocket" title="THIRD"></UserValue> 
      <UserValue value="" title="FOURTH"></UserValue> 
     </UserData>  
    </Instance> 
</Data> 

這是我想出的python代碼。它工作正常,並返回大理石和鼠標。 有沒有辦法使用findall或finditer來做同樣的事情?

另一個問題是,ElementTree似乎將整個XML加載到內存進行處理,這可能是一個問題,我的真正的XML這是近300MB。

import xml.etree.ElementTree as xml 

tree = xml.parse("example.xml") 

for node in tree.iter('Instance'): 

    name = node.get('name') 

    for col in node.iter('UserValue'): 
     title = col.attrib.get('title') 
     value = col.attrib.get('value') 

     if (title == "THIRD" and value != ""): 
      print "  name =", name 

回答

2

我建議您使用lxml。您可以使用lxml使用xpath表達式。

import lxml.etree 

root = lxml.etree.parse("example.xml") 
for instance in root.xpath('//Instance[descendant::UserValue[@title = "THIRD"][@value != ""]]'): 
    print instance.get('name') 

如果上面的代碼需要太多的內存嘗試下面的代碼:

import lxml.etree 

class InstanceNamePrinter(object): 
    def start(self, tag, attrib): 
     if tag == 'Instance': 
      self.name = attrib['name'] 
     elif tag == 'UserValue': 
      if attrib['title'] == 'THIRD' and attrib['value'] != '': 
       print self.name 
    def close(self): 
     pass 

with open('example.xml') as xml: 
    parser = lxml.etree.XMLParser(target=InstanceNamePrinter()) 
    lxml.etree.parse(xml, parser) 
+0

感謝falstru .. LXML比ElementTree的在我的情況 – panofish

+0

@panofish快10倍,你嘗試第二個版本在我的答案? – falsetru

+0

是的......它的工作原理是一樣的,但性能改進只是稍快一點​​。我的代碼花了100秒,你的第一個技巧花了11秒,第二個技巧花了9秒。但我想它的優勢在於它如何使用更少的內存 – panofish

相關問題