2

I am trying to replace the value test with lookup in input.xml. The script is executing without any error but it is not replacing the value.

sed -i '/<Filter>/,/<\/Filter>/s/test/lookup/' input.xml > input_1.xml

below is my input.xml file:

<NikuDataBus
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="./src/webroot/WEB-INF/xog/xsd/nikuxog_entity.xsd">
    <Header version="14.2" action="read" objectType="contentPack" externalSource="NIKU"/>
    <LookupQuery>
        <Filter name="code" criteria="EQUALS">test</Filter>
    </LookupQuery>
</NikuDataBus>
2
  • please click edit and add the sample input to question.. after adding the sample, select them and use the {} button or ctrl+k to format the data for better viewing... also, use parsers like xmlstarlet instead of sed for editing xml data Commented Aug 2, 2018 at 6:44
  • 1
    can you help me with xmlstarlet sample to edit the xml. I am new to shell scripting Commented Aug 2, 2018 at 7:08

2 Answers 2

7

Parsing XML with a non-syntax aware tool like sed is a bad idea. The solution would break is there is a slightest change in the XML formatting. Use xmlstarlet which is syntax aware tool for editing files.

Since your file is syntactically valid also, it is pretty straightforward to solve your problem. Just do

xmlstarlet edit --update '//NikuDataBus/LookupQuery/Filter' --value 'lookup' input.xml

To make the edit of the file in-place just like sed -i, use the -L flag to the solution if your version supports it or use a temporary file (> temp && mv temp input.xml)

xmlstarlet edit -L --update '//NikuDataBus/LookupQuery/Filter' --value 'lookup' input.xml 

Or you could go one step further and do the replace only if the Filter tag contains test which you can do as

xmlstarlet edit --update '//NikuDataBus/LookupQuery/Filter[contains(.,"test")]' --value 'lookup' input.xml

Tested on Centos 7 on the following version.

$ xmlstarlet --version
compiled against libxml2 2.9.1, linked with 20901
compiled against libxslt 1.1.28, linked with 10128

Thanks to one of the useful comments from ever Perl expert - Sundeep, you could see the list of paths that could be traversed on which you can apply operations with xmlstarlet

$ xmlstarlet el input.xml
NikuDataBus
NikuDataBus/Header
NikuDataBus/LookupQuery
NikuDataBus/LookupQuery/Filter
Sign up to request clarification or add additional context in comments.

2 Comments

what if I want to edit the xml using shell script only. I dont have permissions to use xmlstarlet. My requirement is to update the <Filter> tag value based on the user input .
@priyanka: This is the ideal way to your problem. If you can't use xmlstarlet, good luck using other tools to solve the problem
1

I totally agree with everything Inian said, but you should also note that your regular expression is incorrect: your sample data does not contain the string <Filter>. Hence, you need to use a different pattern, like:

 sed '/<Filter/,/<\/Filter>/s/test/lookup/' ...

But, again, you shouldn't.

3 Comments

you mean in the syntax I have to add whole '<Filter name="code" criteria="EQUALS">' thing ?
It worked. Thanks . May I know why I should not use this ?
Because it is too brittle. The basic building block of sed is a line, and the basic building block of XML is a node. You want to change data within a node. In your example, this node happens to be neatly isolated on a single line, but in general, this cannot be taken for granted.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.