Wednesday, November 7, 2012

How to retrieve or extract the tag value from XML in Linux?



How to fetch the tag value for a given tag from a simple XML file?
  Let us consider a simple XML file, cust.xml, with  customer details as below:
<?xml version="1.0" encoding="ISO-8859-1"?>
<CustDetails>
<CustName>Unix</CustName>
<CustomerId>999</CustomerId>
<Age>28</Age>
</CustDetails>
The requirement is to retrieve the tag value of "CustName" from the xml file. Let us see how to get this done in different ways:

1. Using the sed command:
$ sed -n '/CustName/{s/.*<CustName>//;s/<\/CustName.*//;p;}' cust.xml
Unix
Using sed substitution command, the pattern matching till the beginning of the opening tag is deleted. Another substitution is done to remove the pattern from the closing tag till the end. After this, only the tag value will be left in the pattern space.

2. Another sed way:
$ sed -n '/CustName/{s/.*<CustName>\(.*\)<\/CustName>.*/\1/;p}' cust.xml
Unix
The entire line is matched using the regular expression, however, only the value part is grouped. Hence, by using the backreference( \1) in the replacement part, only the value is obtained.

Using a variable:
$ x="CustName"
$ sed -n "/$x/{s/.*<$x>\(.*\)<\/$x>.*/\1/;p}" cust.xml
Unix
The only difference being the use of double-quotes. Since variable is used, double quotes are needed for the variables to get expanded.

 3. Using awk:
$ awk -F "[><]" '/CustName/{print $3}' cust.xml
Unix
Using multiple delimiter ( < and >) in awk, the special variable $3 will contain the value in our example. By filtering the data only for CustName, the tag value is retrieved.

 4. Using Perl:
$ perl -ne 'if (/CustName/){ s/.*?>//; s/<.*//;print;}' cust.xml
Unix
This perl solution is little similar to the sed. Using perl susbtitution, the pattern till the first ">" is removed, and then from the "<" till the end is removed. With this, only the tag value will be left with.

 5. Using the GNU grep command:
$ grep -oP '(?<=<CustName>).*(?=</CustName)' cust.xml
Unix
-o option is to only print the pattern matched instead of the entire line. -P option is for Perl like regular expressions. Using -P, we can do the perl kind of look ahead and look behind pattern matching in grep. This regular expression means: print the pattern which is preceeded(?<=) by "", and followed(?=) by "<CustName>".

Note: These above methods are useful only when the XML is a simple one. For complex XML's, XML parser modules present in Perl are highly useful which we will discuss in future.

No comments:

Post a Comment