简体   繁体   中英

Need help in shell scripting to find and replace value in xml file

I have the following XML format

<object class="Class A">
<directory>someString1</directory>
<attr>
     <name>length</name>
     <value>6</value>
 </attr>
 <attr>
     <name>parent</name>
     <value>1</value>
 </attr>
 <attr>
     <name>Status</name>
     <value>1</value>
 </attr>
 <attr>
     <name>className</name>
     <value>Class A</value>
 </attr>
 <attr>
     <name>Instance</name>
     <value>InstanceValue</value>
 </attr>
 </object>
 ...
 <object class="Class D">
 <directory>someString4</directory>
 <attr>
     <name>length</name>
     <value>8</value>
 </attr>
 <attr>
     <name>parent</name>
     <value>1</value>
 </attr>
 <attr>
     <name>Status</name>
     <value>1</value>
 </attr>
 <attr>
     <name>className</name>
     <value>Class D</value>
 </attr>
 <attr>
     <name>Instance</name>
     <value></value>
 </attr>
 </object>
 ....

I need to find particular class D object only and find whether Instance value is empty for that object, If empty fill up with some value provided as an argument. Please note that there can be multiple objects in the XML file and XML tags name and value are quite a bit repeated. Further, I need to do it with shell scripting only on suse Linux.

I am new to shell scripting and SED. I tried my level best to find existing questions and answers in stackoverflow, but coulnd't find a relevant one. Any help is highly appreciated.

If you can use xmlstarlet , you can do something like:

xml ed -L -u "//object[@class='Class D']/attr[name='Instance'][value='']/value" -v "new value" input.xml

Note: The -L edits the file in-place. Remove it if this is unwanted.

Alternatively, you could use xsltproc to process the XML with XSLT:

xsltproc -o output.xml stylesheet.xsl input.xml

Where stylesheet.xsl is:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="object[@class='Class D']/attr[name='Instance' and value='']/value">
    <xsl:copy>
      <xsl:text>new value</xsl:text>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

Can you check if it works as you need?

#!/bin/bash

VALUE="NewValue"
sed -i data.xml -re "
/Class D/,/<\/object>/ {
    /<name.*>Instance<\/name>/,/<\/value>/ {
        s/(<value.*>)(<\/value>)/\1${VALUE}\2/
    }
}
"

It should find your class, then find name "Instance", and then insert new value if there is no value, otherwise it should not do anything

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM