Search code examples
xmlbashxpathxmlstarlet

How to filter on multiple attributes in XMLStarlet?


For example, given:

<fruit>
   <banana source='Ecuador' category='I'>
      <quantity>1</quantity>
   </banana>
   <banana source='Costa Rica' category='I'>
      <quantity>1</quantity>
   </banana>
</fruit>

Say I want to change

<banana source='Costa Rica' category='I'> 

to

<banana source='Costa Rica' category='II'> 

or its quantity to 2, how would I reference it if I want to filter on both the source and the initial category value?


I'm trying to do the following:

xmlstarlet ed -u "/fruit/banana[@source='Ecuador' @category='I']/quantity" -v 2

...but this results in a syntax error, as follows:

Invalid predicate: /fruit/banana[@source='Ecuador' @category='I']/quantity
Invalid expression: /fruit/banana[@source='Ecuador' @category='I']/quantity

Solution

  • After quite a bit of trial and error, reached a solution:

    I need to close and re-open [] with the next attribute. For example:

    xmlstarlet ed -u "/fruit/banana[@source='Ecuador'][@category='I']/quantity" -v 2 example.xml
    

    And would correctly output:

    <?xml version="1.0"?>
    <fruit>
      <banana source="Ecuador" category="I">
        <quantity>2</quantity>
      </banana>
      <banana source="Costa Rica" category="I">
        <quantity>1</quantity>
      </banana>
    </fruit>
    

    Edit: also works:

    xmlstarlet ed -u "/fruit/banana[@source='Ecuador' and @category='I']/quantity" -v 2 example.xml