0

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.

4
  • 2
    I suggest to use an XML/HTML parser (xmlstarlet, xmllint ...). Commented Sep 26, 2017 at 15:02
  • 1
    Please post a valid xml file and your desired output for that sample to your question. Commented Sep 26, 2017 at 15:04
  • 3
    Can you clarify what sort of restrictiions you have when you say "I need to do it with shell scripting only"? Typically this means "I cannot install any extra software", but sometimes it means "perl and python are not allowed" or even "only shell and simple commands like grep and sed and whatever else they've taught us in class are allowed". Commented Sep 26, 2017 at 15:10
  • To be clear, the best ways to do this involve a real XML parser. Many of these are available from the command line (including xsltproc, which many Linux distributions are shipping out-of-the-box these days). Commented Sep 26, 2017 at 23:28

2 Answers 2

2

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>
Sign up to request clarification or add additional context in comments.

3 Comments

You might also discuss using xmlstarlet to build a XSLT template, which can then be run on systems that don't have xmlstarlet itself installed.
(The OP indicates in the question that they're using SuSE, which ships xsltproc as part of the libxslt package -- so it's there out-of-the-box on a baseline install. Thus, xmlstarlet may or may not be present on the OP's target enviromnent, but xsltproc certainly is).
@CharlesDuffy - Good points. I added an xsltproc example. If the OP would like me to discuss using xmlstarlet to build an XSLT stylesheet, I can.
0

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

3 Comments

And don't forget to backup your XML file before you run the script, it will change the file without asking
This approach is innately fragile. It can't understand comments, it can't understand CDATA sections, it can't understand namespaces (whereby inside only a certain section of the document, name can really mean {http://example.com/some/namespace/prefix}name); it can't even understand <name foo="example"> being a superset of <name>. Folks running services that generate XML output hate it when customers do this kind of fragile processing, because it means we get complaints every time we change something, even if the new document is a proper superset of the old one semantically.
Agree. I myself would recommend something like xmlstarlet, but 1) the author of the question says that he needs shell scripting only, 2) the data given in the question is covered OK. If he needs something more sophisticated, he should give some more information

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.