0

I have a xml file which contains following text:

<Cluster>
     <Name>CLS_20</Name>
     <JMXUserName>admin</JMXUserName>
     <JMXPassword>mypwd</JMXPassword>
</Cluster>
<Server>
    <Name>Server_20</Name>
    <IpAddress>a.b.c.d</IpAddress>
    <Port>1234</Port>
</Server>
<Server>
    <Name>Server_21</Name>
    <IpAddress>e.f.g.h</IpAddress>
    <Port>1234</Port>
</Server>

I have the IP address of the server (a.b.c.d) I want to retrieve name of the server (Server_20)

How can this be achieved with SED Or with any other linux command.

Please help.

2 Answers2

0

Do not do this with sed; it will break horribly when benign formatting changes happen to the XML.

Use a proper XML-parsing tool. For example with xmlstarlet:

xmlstarlet sel -t -c '//Server[IpAddress="a.b.c.d"]/Name/node()' -n filename.xml

or with xmllint:

xmllint --xpath '//Server[IpAddress="a.b.c.d"]/Name/node()' filename.xml

or with old versions of xmllint that don't yet understand --xpath (if you are tempted to use this I encourage you to look at other tools):

echo 'cat //Server[IpAddress="a.b.c.d"]/Name/node()' | xmllint --shell filename.xml | sed '1d;$d'

or with the xpath utility from the XML::XPath Perl library:

xpath -q -e '//Server[IpAddress="a.b.c.d"]/Name/node()' filename.xml

...or with any of three dozen (dozen) other XML tools.

The heart of this is the XPath expression //Server[IpAddress="a.b.c.d"]/Name/node(). This consists of:

  • //Server refers to a Server node anywhere in the document
  • //Server/Name refers to a Name node that is the child of such a Server node
  • //Server/Name/node() refers to the contents of such a Name node
  • //Server[IpAddress="a.b.c.d"] refers to a server node that satisfies the condition IpAddress="a.b.c.d", which means that it has a child IpAddress node that contains a.b.c.d

Putting all that together, //Server[IpAddress="a.b.c.d"]/Name/node() refers to the contents of a Name node that is the child of a Server node anywhere in the document that has an IpAddress child node that contains a.b.c.d.

Wintermute
  • 42,983
  • 5
  • 77
  • 80
  • It is giving me unknown option --xpath when I am using xxllint : version is- xmllint: using libxml version 20706 – Sneha Patil Apr 17 '15 at 12:08
  • That appears to be an old version of xmllint. Hum. Do you have any other XML-handling tools lying around? There are many that can filter for XPath expressions, so I'd rather look for a tool to use than hack something dirty together with `xmllint --shell` and grep. – Wintermute Apr 17 '15 at 12:17
  • I can not use third party tools since its a customer machine. I am looking for simple and available way to parse that value within a script. – Sneha Patil Apr 17 '15 at 12:30
  • Okay, then. I edited in a way to do it with old xmllint, but for the record: I don't consider it very pretty. Better than parsing XML with plain-text tools, but still. – Wintermute Apr 17 '15 at 12:36
0

Sed is to use with caution on xml due to lot of variation in structure but based on this sample

sed -n '
 /<Server>/ h
 /<Server>/,\#</Server># {
   H
   \#</Server># { 
      x
      s#.*<Name>\([^<]*\)<.*IpAddress>a.b.c.d<.*#\1#p
      }
   }' YourFile

Principle:

  • don't print unless explicitly asked
  • load section Server in buffer
  • when reaching end of section
    • change the whole by keeping only name attribut if the ipadresse value is the same as a.b.c and in this case print the result
NeronLeVelu
  • 9,908
  • 1
  • 23
  • 43