-2

I have an input xml file like below

INPUT FILE

<ReconSummary>
<entryName>Total Deep</entryName>
<Code>777</Code>
<License>L</License>
<Tran>H20</Tran>
<job>1234</job>
</ReconSummary>


<ReconSummary>
<entryName>Total Saurav</entryName>
<Code>666</Code>
<License>L</License>
<Tran>H20</Tran>
<job>1234</job>
</ReconSummary>


<ReconSummary>
<entryName>Total Ankur</entryName>
<Code>555</Code>
<License>L</License>
<Tran>H20</Tran>
<job>1234</job>
</ReconSummary>

I want to comment the tag if i find the pattern "Total Deep" so that the output file looks like below

OUTPUT

<!--<ReconSummary>
<entryName>Total Deep</entryName>
<Code>777</Code>
<License>L</License>
<Tran>H20</Tran>
<job>1234</job>
</ReconSummary>-->


<ReconSummary>
<entryName>Total Saurav</entryName>
<Code>666</Code>
<License>L</License>
<Tran>H20</Tran>
<job>1234</job>
</ReconSummary>


<ReconSummary>
<entryName>Total Ankur</entryName>
<Code>555</Code>
<License>L</License>
<Tran>H20</Tran>
<job>1234</job>
</ReconSummary>

Since i am new to shell scripting, can anyone help me out as to how i can apply this with the help of shell scripting?

5
  • There are tools for XML processing. To start, see stackoverflow.com/questions/91791/…. – berndbausch Mar 10 at 9:16
  • i have to do with shell scripting – DEEP MUKHERJEE Mar 10 at 9:22
  • 1
    Assuming that <ReconSummary> is not nested, use awk. When you detect this tag, collect lines in an array until you reach <entryName>. If it contains Total Deep, write "<!--", then the lines from the array. Write the rest until you hit the closing tag, then write "-->". If it contains something else, do the same but omit the comment strings. – berndbausch Mar 10 at 9:29
  • Since i am new to shell scripting can you please help me out with the code for awk? – DEEP MUKHERJEE Mar 10 at 9:30
  • 1
    It would take me too long to do that for free. – berndbausch Mar 10 at 9:35
2

It's easy to use an XML parsing tool like xmlstarlet to delete bits of XML matching some particular XPATH pattern.

In this case, to delete all ReconSummary nodes whose entryName child node has the value Total Deep, you would do

xmlstarlet ed -d '//ReconSummary[entryName = "Total Deep"]' file.xml >newfile.xml

... assuming your file is a well-formed XML file (which your example isn't since it lack as single top-level node).

However, to comment out a bit of XML is a bit trickier, and xmlstarlet can't do it directly.

You can instead apply an XSL transformation which rewrites your XML.

Using an answer that I wrote to a similar question, the XSL transformation

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

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

  <xsl:template match="//ReconSummary[entryName = 'Total Deep']">
    <xsl:text disable-output-escaping="yes">&lt;!-- </xsl:text>
    <xsl:copy-of select="."/>
    <xsl:text disable-output-escaping="yes"> --&gt;</xsl:text>
  </xsl:template>

</xsl:transform>

would insert the XML comment markers <!-- and --> around every ReconSummary node whose entryName child node had the value Total Deep.

You would apply this XSL transformation to your XML file using either of

xmlstarlet tr transform.xsl file.xml >newfile.xml

or

xsltproc transform.xsl file.xml >newfile.xml

where you file is file.xml and the transformation is stored in transform.xsl.

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.