Search and replace specific tag value in XML file with sed command

13,659

Using XMLStarlet, and assuming that the document has a root node:

xmlstarlet ed \
    -u '//context-param[param-name = "com.sun.faces.numberOfViewsInSession"]/param-value[. = 25]' \
    -v 3 file.xml

This selects the correct param-value node (the one that has a value of 25 (drop the [. = 25] bit if the old value is unimportant) and is a child node of the context-param node whose param-name child node has the value com.sun.faces.numberOfViewsInSession), and changes its value to 3.

The resulting document will be (with a fake root node inserted):

<?xml version="1.0"?>
<root>
  <context-param>
    <param-name>com.sun.faces.sendPoweredByHeader</param-name>
    <param-value>false</param-value>
  </context-param>
  <context-param>
    <param-name>com.sun.faces.numberOfViewsInSession</param-name>
    <param-value>3</param-value>
  </context-param>
  <context-param>
    <param-name>testing</param-name>
    <param-value>25</param-value>
  </context-param>
</root>
Share:
13,659

Related videos on Youtube

user3611640
Author by

user3611640

Updated on September 18, 2022

Comments

  • user3611640
    user3611640 over 1 year

    I have a task where by I have to manipulate an XML file through a bash shell script.

    Here are the steps:

    • Query XML file for a value.
    • Replace the value of a different element with the new value.

    Here is the sample xml:

    <context-param>
        <param-name>com.sun.faces.sendPoweredByHeader</param-name>
        <param-value>false</param-value>
      </context-param>
      <context-param>
        <param-name>com.sun.faces.numberOfViewsInSession</param-name>
        <param-value>25</param-value>
      </context-param>
      <context-param>
        <param-name>testing</param-name>
        <param-value>25</param-value>
      </context-param>
    

    I need to update the parm value of <param-value>25</param-value> to <param-value>3</param-value> using a shell script.

    Any idea what will be the SED command to update only param value of param name(<param-name>com.sun.faces.numberOfViewsInSession</param-name>)?

    i tried with below command,

    sed -i 's/<param-value>25<\/param-value>/<param-value>3<\/param-value>/' test.xml
    

    but this command will update all the param-values. i need to update only for com.sun.faces.numberOfViewsInSession

    • Jeff Schaller
      Jeff Schaller over 5 years
      Choroba may not see this, since you deleted the post that they answered...
    • Kusalananda
      Kusalananda over 5 years
      Is that the complete XML document? It doesn't have a root node?
    • user3611640
      user3611640 over 5 years
      yes its complete XML Doc, also its having root node also, i just gave sample example.
    • user3611640
      user3611640 over 5 years
      @JeffSchaller...by mistake my old post got deleted...choroba has given me some solution i need some clarification on that.
  • user3611640
    user3611640 over 5 years
    thank you so much for the solution, sorry but i am new to shell/bash script...i tried your command, i am getting below error: xmlstarlet: command not found
  • Kusalananda
    Kusalananda over 5 years
    @user3611640 Well, yes. It relies on having the xmlstarlet tool installed. On some Unices, it may be installed as just xml, on others you will have to install it from the packaging system. It's available on Linux and BSD, at least.
  • user3611640
    user3611640 over 5 years
    @kusalananda....i am not sure i will be able to install xmlstarlet at client box, any other approach is there to achieve this..like using xml or sed command.
  • Kusalananda
    Kusalananda over 5 years
    @user3611640 I'm not going to give you a sed answer. Structured document formats like XML (or JSON or even some forms of CSV) require parsing by a real parser, not a line-oriented text tool like sed or awk or any of the other standard Unix text manipulation tools. You could also parse the XML in Python or Perl with some XML module, obviously.
  • user3611640
    user3611640 over 5 years
    @kusalananda...i got the solution using sed command, also its working as expected. sed -i '/<param-name>com.sun.faces.numberOfViewsInSession<\/param-n‌​ame>/{n;s/<param-val‌​ue>3<\/param-value>/‌​<param-value>25<\/pa‌​ram-value>/}' web.xml
  • Kusalananda
    Kusalananda over 4 years
    This would possibly change irrelevant lines in the document. In the example given, two lines would be changed instead of the intended single line. In fact, this is exactly equivalent to the command that the user in the question tried for themselves.