1

There is a xml file like below:

<hh>
  <aa>
    <cc>
      <ee>
        <Name>John</Name>
      </ee>
    <cc>
      <ee>
        <Name>David</Name>
      </ee>
  </aa>
  <bb>
    <dd>
      <Name>John</Name>
    </dd>
    <dd>
      <Name>David</Name>
    </dd>
  </bb>
</hh>

I'm trying to modify the name: "John --> Rose", and "David --> Gina"

So I write the code as below:

import xml.etree.ElementTree as ET
import glob


for file in glob.glob("ff/*.xml"):
    tree = ET.parse(file)
    root = tree.getroot()

    a01 = "aa/cc[1]/ee"
    a02 = "bb/dd[1]"
    b01 = "aa/cc[2]/ee"
    b02 = "bb/dd[2]"

    apaths = [a01, a02]
    bpaths = [b01, b02]

    for i in apaths:
        aa = root.findall(apaths)
        aa.text = "Rose"

    tree.write(file)

    for i in bpaths:
        bb = root.findall(bpaths)
        bb.text = "Gina"

    tree.write(file)

But it response "TypeError: unhashable type: 'list'". Could someone help me to correct my code? Many thanks.

2
  • Please see my answer. It should work for you. Let me know what is missing? Commented Jul 20, 2018 at 6:34
  • I have added new code. Please check Commented Jul 20, 2018 at 6:43

2 Answers 2

1

Here is complete working code

Updated as per new requirements

import xml.etree.ElementTree as ET
import glob

for file in glob.glob("ff/*.xml"):
    tree = ET.parse(file)
    root = tree.getroot()

    for name in root.findall('.//aa//Name'):
        name.text = 'Rose'

    for name in root.findall('.//bb//Name'):
        name.text = 'Gina'

    tree.write(file)

Updated Code to operate on all xml files in a directory

import xml.etree.ElementTree as ET
import glob

name_map = {
    'John': 'Rose',
    'David': 'Gina',
}

for file in glob.glob("ff/*.xml"):
    tree = ET.parse(file)
    root = tree.getroot()

    for name in root.findall('.//Name'):
        new_name = name_map.get(name.text)
        if new_name:
            name.text = new_name

    tree.write(file)

Code to rename in an xml

import xml.etree.ElementTree as ET
xml_str = '''
<hh>
  <aa>
    <cc>
      <ee>
        <Name>John</Name>
      </ee>
    </cc>
      <ee>
        <Name>David</Name>
      </ee>
  </aa>
  <bb>
    <dd>
      <Name>John</Name>
    </dd>
    <dd>
      <Name>David</Name>
    </dd>
  </bb>
</hh>
'''


name_map = {
    'John': 'Rose',
    'David': 'Gina',
}

xml = ET.fromstring(xml_str)
print(ET.tostring(xml))

for name in xml.findall('.//Name'):
    new_name = name_map.get(name.text)
    if new_name:
        name.text = new_name

print(ET.tostring(xml))
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for your help. Sometimes the name is not "John" or "David" in my xml file, maybe "Anderson" or "Jack". But I still need to modify the names to "Rose" and "Gina" in my xml file, so I can't use name_map. Do you know any other method which can reach my purpose?
Thanks for the explanation. If a name is Anderson then what would be the condition to rename it? How would we decide to rename it to "Rose" or "Gina"? Also can you please update the question?
Sorry for unclear question. My purpose is to modify the "Name" to "Rose" in a01 and a02 , and "Gina" in b01 and b02. So whatever the name under "a path" or "b path", I need to modify them to "Rose" in "a path" and "Gina" in "b path".
0

You are calling Element.findall with a list argument, instead do:

for i in apaths:
        aa = root.findall(i)
        aa[0].text = "Rose"

and

 for i in bpaths:
        bb = root.findall(i)
        bb[0].text = "Gina"

5 Comments

After I modify the code, it stop at the line "aa.text = "Rose"", and response the error "AttributeError: 'list' object has no attribute 'text'".
Try setting: a01 = "aa/cc[1]/ee[1]" a02 = "bb/dd[1]" b01 = "aa/cc[2]/ee[1]" b02 = "bb/dd[2]"
It still stop at the same line and response the same message. Is it the issue of array?
Try printing aa after finall and see what it is set to.
Print result is like: "[<Element 'ee' at 0x00000000029FFCC8>]", is it correct?

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.