Tears
Tears

Reputation: 39

Need help to modify xml with python

I have an XML string where I want to modify the model type for specific interface.

<domain type='kvm'>
   <devices>
     <interface type='network'>
       <mac address='52:54:00:a8:fe:3d'/>
       <source network='ovirtmgmt'/>
       <model type='virtio'/>
     </interface>
     <interface type='network'>
       <mac address='52:54:00:a8:fe:7d'/>
       <source network='nat'/>
       <model type='virtio'/>
     </interface>
     <interface type='network'>
       <mac address='52:80:00:a8:66:20'/>
       <source network='vm'/>
       <model type='virtio'/>
     </interface>
   </devices>
</domain>

Now, I want to change model type='e1000' where source network='nat'. How can I do that?

Upvotes: 0

Views: 144

Answers (3)

Robᵩ
Robᵩ

Reputation: 168796

You don't need multiple find*() calls. You can do it in one call:

from xml.etree import ElementTree as ET

tree = ET.parse('input.xml')

for model in tree.findall(".//source[@network='nat']/../model"):
    model.set('type', 'e1000')

tree.write('output.xml')

Upvotes: 1

Tears
Tears

Reputation: 39

Thanks for your answers, but this is also worked for me

root = ET.fromstring(xml)
for interface in root.findall('devices/interface'):
    if interface.find('source/[@network="nat"]') != None:
      model = interface.find('model')
      model.set('type', 'e1000')

new_xml = ET.tostring(root)

Upvotes: 0

PM 2Ring
PM 2Ring

Reputation: 55499

Here's some crude ElementTree code that does the job. In a real program you'd probably want some error checking. But if you're sure your XML data will always be perfect, and that every interface tag will always contain a source tag and a model tag, then this code will do the job.

import xml.etree.cElementTree as ET 

data = '''
<domain type='kvm'>
   <devices>
     <interface type='network'>
       <mac address='52:54:00:a8:fe:3d'/>
       <source network='ovirtmgmt'/>
       <model type='virtio'/>
     </interface>
     <interface type='network'>
       <mac address='52:54:00:a8:fe:7d'/>
       <source network='nat'/>
       <model type='virtio'/>
     </interface>
     <interface type='network'>
       <mac address='52:80:00:a8:66:20'/>
       <source network='vm'/>
       <model type='virtio'/>
     </interface>
   </devices>
</domain>
'''

tree = ET.fromstring(data)

for iface in tree.iterfind('devices/interface'):
    network = iface.find('source').attrib['network']
    if network == 'nat':
        model = iface.find('model')
        model.attrib['type'] = 'e1000'

ET.dump(tree)

output

<domain type="kvm">
   <devices>
     <interface type="network">
       <mac address="52:54:00:a8:fe:3d" />
       <source network="ovirtmgmt" />
       <model type="virtio" />
     </interface>
     <interface type="network">
       <mac address="52:54:00:a8:fe:7d" />
       <source network="nat" />
       <model type="e1000" />
     </interface>
     <interface type="network">
       <mac address="52:80:00:a8:66:20" />
       <source network="vm" />
       <model type="virtio" />
     </interface>
   </devices>
</domain>

If you're using an old version of Python you may not have iterfind. In which case, replace it with findall.

Upvotes: 0

Related Questions