Search code examples
xmlxpathxml-parsingxmlstarlet

xmlstarlet select and update xml


I'm trying to select the value of an xml file that matches a particular element(with specific value). For example the xml file below:

            <dependency>
                    <groupId>group1</groupId>
                    <artifactId>art1</artifactId>
                    <version>0.0.1</version>
                    <groupId>group2</groupId>
                    <artifactId>art2</artifactId>
                    <version>0.0.2</version>
                    <groupId>group3</groupId>
                    <artifactId>art3</artifactId>
                    <version>0.0.3</version>
                    <groupId>group4</groupId>
                    <artifactId>art4</artifactId>
                    <version>0.0.4</version>                        
            </dependency>

I'm trying to use this command but it gives a blank response.

xmlstarlet sel -t -v '//groupId[@artifactId="art1"]/version' -n test.xml

if I try to use just this command, it gives me the list of group id's

xmlstarlet sel -t -v '//groupId' -n test.xml

group1
group2
group3
group4

I just need to get the version number of a particular group Id and then I will update it so something like, if groupid = group1 and version = 0.0.1 then i will update the version to 0.0.1-done using xmlstarlet..

Any help will be appreciated as I'm new to using xmlstarlet. I tried reading some documentations but I'm really lost..


Solution

  • artifactId isn't an attribute so @artifactId won't select anything.

    If you want the value of version when artifactId = "art1", it would look like this...

    xmlstarlet sel -t -v "//artifactId[.='art1']/following-sibling::version[1]" test.xml
    

    If you're really wanting to do this:

    if groupid = group1 and version = 0.0.1 then i will update the version to 0.0.1-done

    You should use the ed command instead...

    xmlstarlet ed -u "//groupId[.='group1' and following-sibling::version[1] = '0.0.1']/following-sibling::version[1]" -x "concat(.,'-done')" test.xml
    

    output...

    <dependency>
      <groupId>group1</groupId>
      <artifactId>art1</artifactId>
      <version>0.0.1-done</version>
      <groupId>group2</groupId>
      <artifactId>art2</artifactId>
      <version>0.0.2</version>
      <groupId>group3</groupId>
      <artifactId>art3</artifactId>
      <version>0.0.3</version>
      <groupId>group4</groupId>
      <artifactId>art4</artifactId>
      <version>0.0.4</version>
    </dependency>