0

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?

2
  • 2
    pretty sure you can find eveythin you need here https://docs.python.org/3/library/xml.etree.elementtree.html Commented Jun 28, 2016 at 14:01
  • lxml is another favorite. Commented Jun 28, 2016 at 14:06

3 Answers 3

1

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')
Sign up to request clarification or add additional context in comments.

Comments

0

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.

Comments

0

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)

Comments

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.