Replacing XML element in Python
Asked Answered
C

4

5

I am trying to replace the element inside of bbox with a new set of coordinates.

my code :

    # import element tree
    import xml.etree.ElementTree as ET 


    #import xml file
    tree = ET.parse('C:/highway.xml')
    root = tree.getroot()

    #replace bounding box with new coordinates

    elem = tree.findall('bbox')
    elem.txt = '40.5,41.5,-12.0,-1.2'

my xml file:

   <geoEtl>
    <source>
        <server>localhost</server>
        <port>xxxx</port>
        <db>vxxx</db>
        <user>xxxx</user>
        <passwd>xxxx</passwd>
    </source>
    <targetDir>/home/firstuser/</targetDir>
    <bbox>-52.50,-1.9,52.45,-1.85</bbox>
    <extractions>
        <extraction>
            <table>geo_db_roads</table>
            <outputName>highways</outputName>
            <filter>highway = 'motorway'</filter>
            <geometry>way</geometry>
            <fields>
                <field>name</field>             
            </fields>
        </extraction>
    </extractions>
   </geoEtl>

have tried a variety of ways to do of things i found here but it doesnt seem to be working. thanks.

The error I'm receiving is as follows:

line 20, in <module> elem.txt = '40.5,41.5,-12.0,-1.2' AttributeError: 'list' object has no attribute 'txt' –
Chau answered 2/7, 2013 at 22:51 Comment(2)
What happens when you try?Goulet
line 20, in <module> elem.txt = '40.5,41.5,-12.0,-1.2' AttributeError: 'list' object has no attribute 'txt'Chau
G
9

The findall function, as the name implies, finds all matching elements, not just one.

So, after this:

elem = tree.findall('bbox')

elem is a list of Elements. And, as with any other list, this:

elem.txt = '40.5,41.5,-12.0,-1.2'

Is going to give you an error:

AttributeError: 'list' object has no attribute 'txt'

If you want to do something to every member of a list, you have to loop over it:

elems = tree.findall('bbox')
for elem in elems:
    elem.txt = '40.5,41.5,-12.0,-1.2'
Goulet answered 2/7, 2013 at 22:55 Comment(2)
ok awesome it runs no problem now, should be it rewriting the new coordinates on my XML file or is that a different issue?Chau
@Moggy: ET.parse('C:/highway.xml') just parses the file into a tree in memory. If you want to modify the XML file, you have to edit the tree, then _save it back to a file_. You can do tree.write('C:/highway.xml')` if you want to overwrite the original version with the new one.Goulet
H
3

If your file isn't update it is most likely because you are not saving it, you can use the tree.write method to do just that.

tree.write('output.xml')
Heartsome answered 2/7, 2013 at 23:15 Comment(0)
R
1
# import element tree
import xml.etree.ElementTree as ET 

#import xml file
tree = ET.parse('C:/highway.xml')
root = tree.getroot()

elems = root.findall(".//bbox")

for elem in elems:
    elem.text = '40.5,41.5,-12.0,-1.2'

tree.write('C:/highway.xml')
Roundsman answered 12/12, 2016 at 14:25 Comment(0)
R
0

If you want to replace the text of all boundingboxes with '40.5,41.5,-12.0,-1.2', try this

bboxes = tree.xpath('//bbox')
for bbox in bboxes:
    bbox.text= '40.5,41.5,-12.0,-1.2'
Rhyolite answered 2/7, 2013 at 22:56 Comment(3)
i get AttributeError: 'ElementTree' object has no attribute 'xpath'Chau
Yes - sorry. I also had slightly simpler code for parsing - I used etree as my base class and etree includes the xpath function. I had assumed that ElementTree has that too but I never double-checked itRhyolite
@kamjagin: There is no class called etree anywhere. In both the 2.x and 3.x stdlibs, etree is a package with nothing in it but the ElementTree module; in the separately-installable module from Fredrick Lundh's website, nothing at all has that name; in lxml, etree is a module with roughly the same API as ElementTree in the others. Element handles XPath syntax in the findall method; in the lxml implementation you can also call it as xpath, but you still call it on Elements, not an empty package that you've somehow used as a base class.Goulet

© 2022 - 2024 — McMap. All rights reserved.