xmlstarlet - delete a xml element - shell scripting

CuriousToLearn picture CuriousToLearn · Jul 29, 2015 · Viewed 7.1k times · Source

My XML :

<?xml version='1.0' encoding='UTF-8'?>
<mm2-moduleset plugin="[email protected]">
..
    <buildType class="hudson.mm.MMModuleSet$Component">
       <viewableName>Component</viewableName>
    </buildType>
    <selectedCodeComponents>
       <string>admin-content</string>
       <string>admin</string>
    </selectedCodeComponents>
    <incrementalBuild>false</incrementalBuild>
    ...
    ...
</mm2-moduleset>
</xml>

Basically, im trying to get the job details from the jenkins-cli plugin, and update the configuration of the xml file(the configuration of the jenkins job) and then update the jenkins job using shell-script.

For that, I need to replace "string" attribute values of the "selectedCodeComponents" attribute according to the user input using shell script. if the input is check, check-content, bank, then

    <selectedCodeComponents>
       <string>check-content</string>
       <string>check</string>
       <string>bank</string>     
    </selectedCodeComponents>

My code:

${JAVA_HOME}/bin/java -Djavax.net.ssl.trustStore=${JENKINS_HOST}.keystore -Djavax.net.ssl.trustStorePassword=112012 -jar ./jenkins-cli.jar -s https://$USERNAME:$API_TOKEN\@$JENKINS_HOST:$JENKINS_PORT\/jenkins get-job job_1 > job1.xml

(Jenkins-cli - get-job returns configuration in xml file)

I thought of first deleting the string elements in selectedcodecomponents and append with what ever user gives. Like this,

xmlstarlet ed -d "mm2-moduleset/selectedCodeComponents/string" abc.xml

// some logic
xmlstarlet ed -a "mm2-moduleset/selectedCodeComponents/string" --type elem -n string -v "something" abc.xml

But after executing the first command (xmlstarlet ed -d), it deletes the seletedcodecomponents as well. But i wanted to delete only string elements inside it.

<?xml version='1.0' encoding='UTF-8'?>
 <mm2-moduleset plugin="[email protected]">
..
    <buildType class="hudson.mm.MMModuleSet$Component">
       <viewableName>Component</viewableName>
    </buildType>
    </selectedCodeComponents>
    <incrementalBuild>false</incrementalBuild>
    ...
    ...
 </mm2-moduleset>
</xml>,

append command also appending twice.(xmlstarlet ed -a ) For ex,

xmlstarlet ed -a "mm2-moduleset/selectedCodeComponents/string" --type elem -n string -v "check" abc.xml


<?xml version='1.0' encoding='UTF-8'?>
<mm2-moduleset plugin="[email protected]">
..
    <buildType class="hudson.mm.MMModuleSet$Component">
       <viewableName>Component</viewableName>
    </buildType>
    <selectedCodeComponents>
       <string>admin-content</string>
       <string>check</string>
       <string>admin</string>
       <string>check</string>

    </selectedCodeComponents>
    <incrementalBuild>false</incrementalBuild>
    ...
    ...
</mm2-moduleset>
</xml>

could you please tell me how to delete only string elements inside selectedcodecomponents element and why append command appends twice

I'm new to shell script hence your suggestions would help me

Answer

glenn jackman picture glenn jackman · Jul 29, 2015

Fixing up your sample XML file a bit, to give it a root tag:

$ cat file.xml
<?xml version='1.0' encoding='UTF-8'?>
<root>
    <buildType class="hudson.mm.MMModuleSet$Component">
       <viewableName>Component</viewableName>
    </buildType>
    <selectedCodeComponents>
       <string>admin-content</string>
       <string>admin</string>
    </selectedCodeComponents>
    <incrementalBuild>false</incrementalBuild>
</root>

You delete the string nodes like this

$ xmlstarlet ed -d '//selectedCodeComponents/string' file.xml 
<?xml version="1.0" encoding="UTF-8"?>
<root>
  <buildType class="hudson.mm.MMModuleSet$Component">
    <viewableName>Component</viewableName>
  </buildType>
  <selectedCodeComponents/>
  <incrementalBuild>false</incrementalBuild>
</root>

And then add new string subnodes like this

$ xmlstarlet ed -d '//selectedCodeComponents/string' file.xml |
xmlstarlet ed -s '//selectedCodeComponents' -t elem -n string -v something1 |
xmlstarlet ed -s '//selectedCodeComponents' -t elem -n string -v something2 |
xmlstarlet ed -s '//selectedCodeComponents' -t elem -n string -v something3
<?xml version="1.0" encoding="UTF-8"?>
<root>
  <buildType class="hudson.mm.MMModuleSet$Component">
    <viewableName>Component</viewableName>
  </buildType>
  <selectedCodeComponents>
    <string>something1</string>
    <string>something2</string>
    <string>something3</string>
  </selectedCodeComponents>
  <incrementalBuild>false</incrementalBuild>
</root>