Search code examples
xmlstarlet

Use xmlstarlet to match on an attribute within a block and update a sibling attribute within the same block


Staring with an xml file, mg.xml

<?xml version="1.0"?>
<domain type="kvm">
  <name>Comus</name>
  <devices>
    <interface type="network">
      <mac address="52:54:00:46:a3:25"/>
      <source network="default"/>
      <model type="virtio"/>
      <link state="down"/>
      <address type="pci" domain="0x0000" bus="0x01" slot="0x00" function="0x0"/>
    </interface>
    <interface type="bridge">
      <mac address="52:54:00:6c:0e:d0"/>
      <source bridge="br0"/>
      <model type="virtio"/>
      <link state="up"/>
      <address type="pci" domain="0x0000" bus="0x07" slot="0x00" function="0x0"/>
    </interface>
  </devices>
</domain>

I need to update the link state attribute to "up" for the block where mac address matches "52:54:00:46:a3:25"

The end result should be

<?xml version="1.0"?>
<domain type="kvm">
  <name>Comus</name>
  <devices>
    <interface type="network">
      <mac address="52:54:00:46:a3:25"/>
      <source network="default"/>
      <model type="virtio"/>
      <link state="up"/>
      <address type="pci" domain="0x0000" bus="0x01" slot="0x00" function="0x0"/>
    </interface>
    <interface type="bridge">
      <mac address="52:54:00:6c:0e:d0"/>
      <source bridge="br0"/>
      <model type="virtio"/>
      <link state="up"/>
      <address type="pci" domain="0x0000" bus="0x07" slot="0x00" function="0x0"/>
    </interface>
  </devices>
</domain>

I got as far as

xmlstarlet edit -L -u "/domain/devices/interface/mac[@address='52:54:00:6c:0e:d0']/@address" -v "up" mg.xml

But of course this updates the mac address to "up", not the link state.


Solution

  • Like this:

    xmlstarlet edit -L -u '/domain/devices/interface/mac[@address="52:54:00:46:a3:25"]/../link/@state" -v 'up' mg.xml