1

I have an XML file like below. I want change the values at is-required place and default-value place of each argument name using a shell script..

  • where argument name=protocol then is-required = "true" and default-value=tcp,
  • where argument name =port then is-required = "true" default-value= 7223,
  • where argument name =then and is-required = "true" default-value=test,

Example:

<task-arguments>
    <argument name="protocol" is-required="false" default-value="ssl"/>
    <argument name="port" is-required="true" default-value="7222"/>
    <argument name="username" is-required="true" default-value="admin"/>
</task-arguments>
  • You can use the python xml library – Ijaz Ahmad Khan Jul 11 '16 at 10:01
1

In general, XML processing should be done with an XML parser.

UPDATE: In fact, I think it's unfortunate that this answer was picked as the "accepted answer" since @SatoKatsura's answer is in all ways correct and better. It uses a proper XML parser and it is shorter. See also comments from @cas to my answer. XML parsing really should not be attempted with line-oriented tools.

However, treating you document as plain text:

#!/usr/bin/sed -f

/argument name="protocol"/{
    i\
<argument name="protocol" is-required="true" default-value="tcp"/>
    d
}

/argument name="port"/{
    i\
<argument name="port" is-required="true" default-value="7223"/>
    d
}

/argument name="username"/{
    i\
<argument name="username" is-required="true" default-value="test"/>
    d
}

This sed script will find the lines that you want to modify and replace the whole line with a line containing the XML that you want.

I'm choosing to do it in this (rather heavy-handed) way, because it gives you an easy way to change the values to whatever you want, and does not rely on too much regular expression wizardry.

EDIT:

The script would go in a file of its own, maybe script.sed. You would then run it with

$ sed -f script.sed data.xml >data.new

This will apply the script to the file data.xml and output the result into the file data.new.

The following is a script that allows you to set the values of the protocol, port and user, as well as what data files should be read and written:

#!/bin/sh

xmlfile_in="data.xml"
xmlfile_out="data.new"

protocol="tcp"
port="7223"
user="test"

sed -f /dev/stdin "$xmlfile_in" >"$xmlfile_out" <<END_SED
/argument name="protocol"/{
    i\\
<argument name="protocol" is-required="true" default-value="$protocol"/>
    d
}

/argument name="port"/{
    i\\
<argument name="port" is-required="true" default-value="$port"/>
    d
}

/argument name="username"/{
    i\\
<argument name="username" is-required="true" default-value="$user"/>
    d
}
END_SED
  • HI Kusalanda, Thanks for your comment,, I wanted to update in xml file and my values coming form my script.. let say i have script file like abc.sh and xml fiel like monitor.xml file... if run abc.sh file the values should update at xml file... As you said,,, XML processing should be done with an XML parser.. My case i have chance xmlstarlet-0.5.1-19.x86_64.rpm packge to use.. – Sureshchandra Jarugula Jul 11 '16 at 9:11
  • Please guide me accordingly... as per your example where is the sed function used.. – Sureshchandra Jarugula Jul 11 '16 at 9:19
  • @SureshchandraJarugula See updated answer. – Kusalananda Jul 11 '16 at 9:21
  • 1
    Hi Kusalanda. It's looks good now... Thanks for your help.. – Sureshchandra Jarugula Jul 11 '16 at 9:58
  • 1
    If you're going to use sed to modify XML input, at least use xml2 to convert it to a line-oriented format and 2xml to convert it back to XML afterwards. e.g. xml2 <input.xml | sed ..... | 2xml > output.xml. That, at least, will prevent the sed script from breaking due to relatively minor changes in the input. also works for grep, awk, cut, and other line-oriented tools. – cas Jul 12 '16 at 7:03
5

Using XMLStarlet:

xml ed -P \
    -u '//argument[@name="protocol"]/@is-required' -v true \
    -u '//argument[@name="protocol"]/@default-value' -v tcp \
    -u '//argument[@name="port"]/@is-required' -v true \
    -u '//argument[@name="port"]/@default-value' -v 7223 \
    -u '//argument[@name="username"]/@is-required' -v true \
    -u '//argument[@name="username"]/@default-value' -v admin \
        file.xml

Result for your sample:

<task-arguments>
    <argument name="protocol" is-required="true" default-value="tcp"/>
    <argument name="port" is-required="true" default-value="7223"/>
    <argument name="username" is-required="true" default-value="admin"/>
</task-arguments>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.