3

I have a xml file and i am searching looking for a specific string in it. when that string is found, i want to return it's parent name. here is my xml:

<context>
    <name>AccuCapacityApp</name>
    <message>
        <source>Capacity</source>
        <translation type="unfinished">Kapazität</translation>
    </message>
    <message>
        <source>Charge Level</source>
        <translation type="unfinished"></translation>
    </message>
    <message>
        <source>Sel (Yes)</source>
        <translation type="unfinished">Sel (Ja)</translation>
    </message>
    <message>
        <source>Esc (No)</source>
        <translation type="unfinished">Esc (Nein)</translation>
    </message>
</context>

I want to search for "unfinished" and return "Capacity" as "source" and "AccuCapacityApp" as "Main".

i tried this but it prints nothing:

import xml.etree.ElementTree as ET

file = "work.xml"

tree = ET.parse(file)
for elem in tree.findall('context/message'):
   found = elem.get('unfinished')
   print(found.attrib)
John
  • 83
  • 7

1 Answers1

1

You are iterating all message nodes using tree.findall('context/message') but you need the translation nodes (they hold the type attribute). So this will work as a subsitute to your code:

for message in tree.iterfind('.//translation[@type="unfinished"]/..'):
    print(message.attrib)

It will iterate the message nodes caontaining a child translation with attribute type that equals to undefined. For more guidance please read about XPath in Python docs. Notice I used iterfind which is more efficient.

Next, for achieving what you want you will need to use message in order to extract source:

for message in tree.iterfind('.//translation[@type="unfinished"]/..'):
    print("Source: ", message.find('source').text)

In order to get the name tag you will need to get the parent of message. For that see this SE question. Or just get the that tag from tree (tree.find('./name')).

Good luck.

Doron Cohen
  • 1,026
  • 8
  • 13
  • Printing sources works accurately. But I have tried printing `print("Source: ", tree.find('./name'))` , but it prints "None". I have visited the link you have given here. I am not sure which answer to follow. `tree.find('.//b/..')` also returns "None". The most voted answer contains another for loop. How should I include that with this one? – John Sep 05 '17 at 12:01
  • 1
    I have figured it out how to do that . After mapping the parent with `parent_map = dict((c, p) for p in tree.getiterator() for c in p)`, I printed the parent with `parent_map[message].find('name').text`. Thanks for the help. – John Sep 06 '17 at 07:05