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)

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

2 Comments

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?
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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.