0

Want to get the value of the sibling element in xml using ElementTree. sample.xml is as below want to get value 23 against John & 20 against Jin.

<MainTag xmlns="http://www.exmple.com">
    <Tag1>
        <Tag11>Sam</Tag11>
        <Tag12>New York</Tag12>
        <Tag13>21</Tag13>
        <Tag14>Dance</Tag14>
    </Tag1>
    <Tag1>
        <Tag11>John</Tag11>
        <Tag12>New York</Tag12>
        <Tag13>23</Tag13>
        <Tag14>Music</Tag14>
    </Tag1>
    <Tag1>
        <Tag11>Jenny</Tag11>
        <Tag12>Sydney</Tag12>
        <Tag13>20</Tag13>
    </Tag1>
    <Tag1>
        <Tag11>Jin</Tag11>
        <Tag12>Jakarta</Tag12>
        <Tag13>20</Tag13>
        <Tag14>Music</Tag14>
    </Tag1>
</MainTag>
MakHingse
  • 11
  • 1

1 Answers1

0

Interesting situation! Since your xml has a default namespace, you have to account for it. That can be done in one of two ways: either declare a namespace or use a wildcard.

In this case, you have a list of two target names (John and Jin) which presumably you want to iterate over and interpolate into the xpath expression using f-strings.

The problem is that both the wildcard namespace and f-strings use {}, so you either have to escape the {} if you want to use wildcards, or give that up and declare the namespaces.

So:

import xml.etree.ElementTree as ET
tags = """[your xml above]"""
doc = ET.fromstring(tags)
targets = ["John","Jin"]

#using wildcards without a namespace declaration:

for target in targets:
    print(doc.find(f'.//{{*}}Tag1[{{*}}Tag11="{target}"]/{{*}}Tag13').text)

#or without wildcards

ns = {'': 'http://www.exmple.com'}
for target in targets:
    print(doc.find(f'.//Tag1[Tag11="{target}"]/Tag13',namespaces=ns).text)

Output in either case is

23
20
Jack Fleeting
  • 24,385
  • 6
  • 23
  • 45