Getting all instances of child node using xml.etree.ElementTree
Asked Answered
H

3

12

I have the following XML file as input:

<Test>
  <callEvents>
    <moc>
      <causeForTermination>0</causeForTermination>
      <serviceCode>
        <teleServiceCode>11</teleServiceCode>
      </serviceCode>
      <dialledDigits>5555555</dialledDigits>
      <connectedNumber>77777</connectedNumber>
    </moc>

    <moc>
      <causeForTermination>0</causeForTermination>
      <serviceCode>
        <teleServiceCode>11</teleServiceCode>
      </serviceCode>
      <dialledDigits>2222222</dialledDigits>
    </moc>
  </callEvents>
  <callEventsCount>100</callEventsCount>
</Test> 

I want to output all the values for dialledDigits. However, my code only displays the first instance of dialledDigits.

dialledDigits {} 5555555

My desired output should contain both instances.

dialledDigits {} 5555555
dialledDigits {} 2222222

Here is my code

import xml.etree.ElementTree as ET
tree = ET.parse('as.xml')
root = tree.getroot()
callevent=root.find('callEvents')

Moc1=callevent.find('moc')

for node in Moc1.getiterator():
    if node.tag=='dialledDigits':
        print node.tag, node.attrib, node.text
Hepzi answered 25/3, 2015 at 21:11 Comment(0)
S
12

Use findall:

moc1 = callevent.findall('moc')

for moc in moc1:
    for node in moc.getiterator():
        if node.tag=='dialledDigits':
            print node.tag, node.attrib, node.text

Output:

dialledDigits {} 5555555
dialledDigits {} 2222222
Shortfall answered 25/3, 2015 at 21:17 Comment(1)
But shouldn't there be a way to do it without an explicit if check, but rather like "for node in moc.inter("dialledDigits")"?Dictation
T
15

You can also write an XPath expression. Just 2 lines instead of 5 and a single loop:

for node in tree.findall('.//callEvents/moc/dialledDigits'):
    print node.tag, node.attrib, node.text 

Demo:

>>> import xml.etree.ElementTree as ET
>>> 
>>> 
>>> tree = ET.parse('as.xml')
>>> root = tree.getroot()
>>> 
>>> for node in tree.findall('.//callEvents/moc/dialledDigits'):
...     print node.tag, node.attrib, node.text
... 
dialledDigits {} 5555555
dialledDigits {} 2222222
Tomblin answered 25/3, 2015 at 21:18 Comment(3)
yes, xpath will work, Thank you. The xpath method is not available for ET. It is present in the lxml. +upvoteMiyokomizar
xpath syntax is available in ET: that's what alecxe used in the findall call....Lulululuabourg
I've only dabbled a bit and never used root = tree.getroot() yet. It is used in your code but, I can't see why?Stupid
S
12

Use findall:

moc1 = callevent.findall('moc')

for moc in moc1:
    for node in moc.getiterator():
        if node.tag=='dialledDigits':
            print node.tag, node.attrib, node.text

Output:

dialledDigits {} 5555555
dialledDigits {} 2222222
Shortfall answered 25/3, 2015 at 21:17 Comment(1)
But shouldn't there be a way to do it without an explicit if check, but rather like "for node in moc.inter("dialledDigits")"?Dictation
M
1

find() will return first tag object, so use finadall() which return all tag objects`

>>> Moc1=callevent.find('moc')
>>> Moc1
<Element 'moc' at 0x869a2ac>
>>> Moc1=callevent.findall('moc')
>>> Moc1
[<Element 'moc' at 0x869a2ac>, <Element 'moc' at 0x869a4ec>]
>>> 

Iterate on it:

>>> Mocs=callevent.findall('moc')
>>> for moc in Mocs:
...     for node in moc.getiterator():
...         if node.tag=='dialledDigits':
...             print node.tag, node.attrib, node.text
... 
dialledDigits {} 5555555
dialledDigits {} 2222222
Miyokomizar answered 25/3, 2015 at 21:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.