5

Let's say I have an existing trivial XML file named 'MyData.xml' that contains the following:

<?xml version="1.0" encoding="utf-8" ?>
<myElement>foo</myElement>

I want to change the text value of 'foo' to 'bar' resulting in the following:

<?xml version="1.0" encoding="utf-8" ?>
<myElement>bar</myElement>

Once I am done, I want to save the changes.

What is the easiest and simplest way to accomplish all this?

Ray
  • 187,153
  • 97
  • 222
  • 204

4 Answers4

4

Use Python's minidom

Basically you will take the following steps:

  1. Read XML data into DOM object
  2. Use DOM methods to modify the document
  3. Save new DOM object to new XML document

The python spec should hold your hand rather nicely though this process.

Ray
  • 187,153
  • 97
  • 222
  • 204
Ryan
  • 9,918
  • 7
  • 42
  • 57
  • So, for # 3 would I have explicitly overwrite the existing file versus using some built-in function in minidom that might implicitly do that for me? – Ray Oct 07 '08 at 16:52
  • 2
    Ray: yes, any DOM manipulations will be in-memory only. You'll have to copy to a new file or overwrite the existing file. For tips on how to handle modifying an existing file, see this post: http://stackoverflow.com/questions/125703/how-do-i-modify-a-text-file-in-python – technomalogical Oct 07 '08 at 17:15
3

For quick, non-critical XML manipulations, i really like P4X. It let's you write like this:

import p4x
doc = p4x.P4X (open(file).read)
doc.myElement = 'bar'
thegrinner
  • 11,546
  • 5
  • 41
  • 64
Javier
  • 60,510
  • 8
  • 78
  • 126
  • the current version of this (last updated 2005) gives a syntax error when importing into Python 2.7.2. Can't use it as is. – Roni Yaniv Dec 12 '11 at 14:32
3

This is what I wrote based on @Ryan's answer:

from xml.dom.minidom import parse
import os

# create a backup of original file
new_file_name = 'MyData.xml'
old_file_name = new_file_name + "~"
os.rename(new_file_name, old_file_name)

# change text value of element
doc = parse(old_file_name)
node = doc.getElementsByTagName('myElement')
node[0].firstChild.nodeValue = 'bar'

# persist changes to new file
xml_file = open(new_file_name, "w")
doc.writexml(xml_file, encoding="utf-8")
xml_file.close()

Not sure if this was the easiest and simplest approach but it does work. (@Javier's answer has less lines of code but requires non-standard library)

Community
  • 1
  • 1
Ray
  • 187,153
  • 97
  • 222
  • 204
1

You also might want to check out Uche Ogbuji's excellent XML Data Binding Library, Amara: http://uche.ogbuji.net/tech/4suite/amara

(Documentation here: http://platea.pntic.mec.es/~jmorilla/amara/manual/)

The cool thing about Amara is that it turns an XML document in to a Python object, so you can just do stuff like:

record = doc.xml_create_element(u'Record')

nameElem = doc.xml_create_element(u'Name', content=unicode(name))

record.xml_append(nameElem)

valueElem = doc.xml_create_element(u'Value', content=unicode(value))

record.xml_append(valueElem

(which creates a Record element that contains Name and Value elements (which in turn contain the values of the name and value variables)).

thegrinner
  • 11,546
  • 5
  • 41
  • 64
machineghost
  • 33,529
  • 30
  • 159
  • 234