What is python 2.6 equivalent of iterfind()

时间:2015-07-28 16:32:16

标签: python xml

I am trying to write Python (2.6.6) program to parse xml and use some of it's elements to check some conditions. I am using xml.etree.cElementTree as it was suggested by most online discussions. Sample xml I am using:

<?xml version="1.0" encoding="UTF-8"?>

<drum>
  <cmts>
    <Pre_EQ>
      <success field_name="success">1</success>
      <coefficient field_name="coefficient">080118000000ffd00000ffe00000fff0001000200020fff000000010002000003fa0000000000020003000000020ffd00010001000000000000000000010000000000020ffc0000000000020000000500010ffe0fff0ffe0ffd0fff0fff0ffd0ffd0fff0</coefficient>
    </Pre_EQ>
  </cmts>
</drum>

While searching different ways to fetch select elements from the xml, I found iterfind() can be used to select specific elements but I think it's not supported on 2.6.6 (2.7 onwards). So when I try to use iterfind() I get following error on python prompt:

>>> import xml.etree.cElementTree as ET
>>> tree = ET.ElementTree(file='Test.xml')
>>> for elem in tree.iterfind('Pre_EQ/success'):
...     print elem.tag, elem.attrib, elem.text
...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: ElementTree instance has no attribute 'iterfind'
>>> for elem in tree.iterfind('success[@field_name="success"]'):
...     print elem.tag, elem.attrib, elem.text
...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: ElementTree instance has no attribute 'iterfind'
>>>

I faced almost same issue with iter() which was not supported by 2.6.6 but I could find by searching here that it's equivalent is getiterator() (It worked for me). But, I am unable to find something that I can use like iterfind() (to search a specific tag name so as to get it's tag value/text) I have tried "find", "findall" and "findtext" by using tree.find, etc. but not able to get any of them working.

Can you please suggest me some way to get equivalent of iterfind() for 2.6.6 or some other way to search a specific tag name so as to get it's tag value/text.

1 个答案:

答案 0 :(得分:1)

From documentation of xml.etree.ElementTree -

iter(tag=None)

Creates a tree iterator with the current element as the root. The iterator iterates over this element and all elements below it, in document (depth first) order. If tag is not None or '*', only elements whose tag equals tag are returned from the iterator. If the tree structure is modified during iteration, the result is undefined.

New in version 2.7.

iterfind(match)

Finds all matching subelements, by tag name or path. Returns an iterable yielding all matching elements in document order.

New in version 2.7.

(Emphasis mine)

Just as you noticed, you cannot use iterfind or iter in Python 2.7 .

You will have to use findall() method , to get the data you want. And from my experience, findall() does not support XPath with predicates (for attributes) in Python 2.6 either. So you would need to get all elements with tag name as success and then check the attributes of those elements to see if they equal what you want.

Code -

First

>>> import xml.etree.cElementTree as ET
>>> tree = ET.ElementTree(file='Test.xml')
>>> for elem in tree.findall('.//Pre_EQ/success'):
...     print elem.tag, elem.attrib, elem.text

Second

>>> for elem in tree.findall('.//success'):
...     if elem.attrib.get('field_name') == "success":
...         print elem.tag, elem.attrib, elem.text

Demo -

>>> s='''<?xml version="1.0" encoding="UTF-8"?>
... <drum>
...   <cmts>
...     <Pre_EQ>
...       <success field_name="success">1</success>
...       <coefficient field_name="coefficient">080118000000ffd00000ffe00000fff0001000200020fff000000010002000003fa0000000000020003000000020ffd00010001000000000000000000010000000000020ffc0000000000020000000500010ffe0fff0ffe0ffd0fff0fff0ffd0ffd0fff0</coefficient>
...     </Pre_EQ>
...   </cmts>
... </drum>'''
>>> tree = ET.fromstring(s)
>>> for elem in tree.findall('.//Pre_EQ/success'):
...     print elem.tag, elem.attrib, elem.text
... 
success {'field_name': 'success'} 1
>>>
>>>
>>> for elem in tree.findall('.//success'):
...     if elem.attrib.get('field_name') == "success":
...         print elem.tag, elem.attrib, elem.text
... 
success {'field_name': 'success'} 1