1

Suppose I have one xml file as mentioned below and I want to extract the application name, machine and status tag value using unix commands and present it in comma separated format.

XML file:-

 <?xml version="1.0" encoding="UTF-8"?>
<applications>
<application name="Adapter/Code1">
<service name="Code1.par">
<deploymentStatus>Success</deploymentStatus>
<serviceInstance name="Code1-One">
    <machine>123</machine>
    <status>Running</status>
</serviceInstance>
<serviceInstance name="Code1-Two">
    <machine>456</machine>
    <status>Running</status>
</serviceInstance>
</service>
</application>
<application name="Adapter/Code2">
<service name="Code2.par">
<deploymentStatus>Success</deploymentStatus>
<serviceInstance name="Code2-One">
    <machine>123</machine>
    <status>Running</status>
</serviceInstance>
<serviceInstance name="Code2-Two">
    <machine>456</machine>
    <status>Running</status>
</serviceInstance>
</service>
</application>
</applications>

Output:-

Adapter/Code1,123,Running

Adapter/Code1,456,Running

Adapter/Code2,123,Running

Adapter/Code2,456,Running

Can you please help me in giving unixcommand/shell script for doing this activity.?

Thanks in advance!!!

1
  • 6
    Do what every question tagged xml here suggests: use an XML parser.
    – jasonwryan
    May 24 '17 at 7:54
2

Python 3.x solution (with xml.etree.ElementTree module):

import xml.etree.ElementTree as ET

tree = ET.parse("test.xml")
root = tree.getroot()
for app in root.findall('application'):
    for m,s in zip(app.iter('machine'), app.iter('status')):
        print("%s,%s,%s" % (app.get('name'), m.text, s.text))

The output:

Adapter/Code1,123,Running
Adapter/Code1,456,Running
Adapter/Code2,123,Running
Adapter/Code2,456,Running

https://docs.python.org/3.6/library/xml.etree.elementtree.html?highlight=etree#module-xml.etree.ElementTree


xmlstarlet + awk (used to group child nodes for each application element) solution:

xmlstarlet sel -t -v "//application/@name| .//machine/text()| .//status/text()" -n input.xml 
 | awk '/Adapter/{app=$0; r=app; c=0; next}
   { if(++c==2){ c=0; print r","$0; r=app } else { r=r","$0 }}'

The output:

Adapter/Code1,123,Running
Adapter/Code1,456,Running
Adapter/Code2,123,Running
Adapter/Code2,456,Running

  • "//application/@name| .//machine/text()| .//status/text()" - XPath expression to get the needed nodes

  • /Adapter/{app=$0; r=app; c=0; next} - capturing each application name for further concatenation

http://xmlstar.sourceforge.net/doc/UG/xmlstarlet-ug.html

2
  • cool ! ( +1 ) ( python version also works in Python2 ?)
    – JJoao
    May 24 '17 at 18:16
  • 1
    @JJoao, as for Python 2 - it has print function call without parenthesis (i.e. print <arg>), but I hope Python 2.x will die someday ) May 24 '17 at 19:44
1

Install xidel and use xpath.

In my opinion the best point of view is from serviceInstance:

xidel f.xml -e '//serviceInstance/string-join((../../@name, machine, status),",")'
Adapter/Code1,123,Running
Adapter/Code1,456,Running
Adapter/Code2,123,Running
Adapter/Code2,456,Running
0

Using xmlstarlet to loop over each serviceInstance node:

xmlstarlet sel -t \
    -m '//application/service/serviceInstance' \
    -v '../../@name' -o , \
    -v 'machine' -o , \
    -v 'status' -nl \
    file.xml

This matches the serviceInstance nodes, and for each such node, it extracts the name attribute of its grandparent node, the machine node's value and the status node's value. These are outputted with commas in-between them (-o ,) and a newline at the end (-nl).

You may also get quoted CSV output from xq (from https://kislyuk.github.io/yq/):

xq -r '
    .applications.application[] | ."@name" as $name |
    .service.serviceInstance[]  | [ $name, .machine, .status ] | @csv' file.xml
-1

If you have good reason for not using xml tools, you can use low-level parsing, as long as your application stays trivial as your example:

sed 's/<application name="\([^"]*\)">/\1/
Ta
h
d
:a
/<machine>/!d
G
N
s_.*<machine>\(.*\)</machine>\n\(.*\)\n.*<status>\(.*\)</status>.*_\2,\1,\3_' yourfile.xml

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.