xmlstarlet modify XML attribute in a body that also has an attribute with a specific value

51 Views Asked by At

I am creating a bash script to replace various values in a large XML file using XMLStarlet. For one specific situation I fail to find the proper XMLStarlet commandline syntax.

I created a simplified XML file (test.xml) to show my situation:

<?xml version="1.0"?>
<DATA VERSION="1.0">
  <TABLES>
    <ITEM>
      <ID>1234</ID>
      <prop3>ABCD</prop3>
    </ITEM>
    <ITEM>
      <ID>5678</ID>
      <prop3>EFGH</prop3>
    </ITEM>
  </TABLES>
</DATA>

I am trying to replace prop3 of an ITEM with a specific ID (e.g. 5678). I found a very similar question/reply on stackoverflow which gave me good hopes to bring me to the solution. It definitely helped but only partially.

I constructed the below command but it is not entirely right since it has no effect (XML unchanged):

xmlstarlet ed -u "/DATA/TABLES/ITEM[@ID='5678']/prop3" -v "succes" test.xml
2

There are 2 best solutions below

0
Shawn On

The XPath fragment ITEM[@ID='5678'] looks for an ITEM element with a matching ID attribute: <ITEM ID="5678">. Your sample XML document doesn't use attributes on ITEM elements, thus nothing in it will match. To match an element with a matching child element, drop the @ and it'll make the replacement:

$ xmlstarlet ed -u "/DATA/TABLES/ITEM[ID='5678']/prop3" -v "succes" test.xml
<?xml version="1.0"?>
<DATA VERSION="1.0">
  <TABLES>
    <ITEM>
      <ID>1234</ID>
      <prop3>ABCD</prop3>
    </ITEM>
    <ITEM>
      <ID>5678</ID>
      <prop3>succes</prop3>
    </ITEM>
  </TABLES>
</DATA>
0
PvSw-01 On

Thanks everyone.

xmlstarlet ed -u "/DATA/TABLES/ITEM[ID='5678']/prop3" -v "succes" test.xml

It works. I learned something more about XML.