Pages

Tuesday, April 9, 2013

Perl Modules : Xml Parsing In perl

Parsing Text Files is always an easy way using perl .As a System Admin there was a requirement for adding Data Sources using the Perl.

In Tomcat or Jboss we do have the Context.xml or xx-ds.xml file where we need to update these or create these for configuring the Data Sources.

These Can also be created using Java JMX or any other way but what if we need to parse xml files using PERL.

Perl Provides a couple of ways for parsing xml files.This articles tell you about the XML::Simple and XML::LibXML.

For this article Purpose we use Tomcat Context.xml file and alos Jboss xxx-ds.xml files for reading , Writing and Deleting.

XML::Simple , an easy API to read and write XML. XML::Simple is implemented as an API layer over the XML::Parser module

Now I Need to Find out the How Many Of the Resources are available and are configured in Context.xml file for a Tomcat server.

The Code that I have used for parsing the context.xml file for the above requirement is

$EWS_DS_FILE="$EWS_CFG_DIR/$VIRT_TARGET/conf/context.xml";

my $parser=XML::Simple->new();
my $doc = $parser->XMLin($EWS_DS_FILE,, ForceArray => qr{Resource} ,
keyAttr=> { 'Resource', 'name',KeepRoot => 1 }
);

foreach my $key (keys (%{$doc->{Resource}})) {
print $key;
print "\n";
}
}


Every object of the XML::Simple class exposes two methods, XMLin() and XMLout(). The XMLin() method reads an XML file or string and converts it to a Perl representation; the XMLout() method does the reverse, reading a Perl structure and returning it as an XML document instance

The above XMLin reads the file and stores the result in $doc variable.

ForceArray : This option should be set to true to force nested elements to be represented as arrays even when there is only one

I used “Resource” as Key attribute.

Now the Result that I Obtained

jdbc/com.sample.app.jon.manPoolTXDS2
jdbc/com.sample.app.jon.manPoolTXDS3
jdbc/com.sample.app.jon.manPoolTXDS1
If you need to extract values assigned to elements in XML ,we can use

$POOLNAME="jdbc/" . $POOL_NAME;
$EWS_CFG_DIR=$ENV{JBS_CFGDIR};
$EWS_DS_FILE="$EWS_CFG_DIR/$VIRT_TARGET/conf/context.xml";

my $parser=XML::Simple->new();
my $doc = $parser->XMLin($EWS_DS_FILE,, ForceArray => qr{Resource} ,
keyAttr=> { 'Resource', 'name',KeepRoot => 1 }
);

foreach my $key (keys (%{$doc->{Resource}})) {

if($key eq $POOLNAME) {
print "Name: $key\n";
print "URL: $doc->{Resource}->{$key}->{url}\n";
print "JNDI: $key\n";
print "Factory: $doc->{Resource}->{$key}->{factory}\n";
print "Type: $doc->{Resource}->{$key}->{type}\n";
print "DriverName: $doc->{Resource}->{$key}->{driverClassName}\n";
print "MaxCapacity: $doc->{Resource}->{$key}->{maxActive}\n";
print "InitialCapacity: $doc->{Resource}->{$key}->{initialSize}\n";
print "Max Wait: $doc->{Resource}->{$key}->{maxWait}\n";
print "Time Between Eviction Run: $doc->{Resource}->{$key}->{timeBetweenEvictionRunsMillis}\n";
print "Validation Query: $doc->{Resource}->{$key}->{validationQuery}\n";
print "Remove Abondoned: $doc->{Resource}->{$key}->{removeAbandoned}\n";
print "Test While Idle: $doc->{Resource}->{$key}->{testWhileIdle}\n";
print "UserID: $doc->{Resource}->{$key}->{username}\n";
print "PasswordEncrypted: $doc->{Resource}->{$key}->{password}\n";
}

}


}

Now iam passing the Server name and Pool Name .When I run the Code I get the results as

Name: jdbc/com.sample.app.jon.manPoolTXDS1
URL: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
JNDI: jdbc/com.sample.app.jon.manPoolTXDS1
Factory:
Type: javax.sql.DataSource
DriverName: oracle.jdbc.OracleDriver
MaxCapacity: 1
InitialCapacity: 5
Max Wait: 100
Time Between Eviction Run: 300000
Validation Query: SELECT * FROM DUAL
Remove Abondoned: true
Test While Idle: true
UserID: xxxxx
PasswordEncrypted: xxxxx

I can get any details I need.


XML::LibXML : XML::LibXML provides a standard W3C DOM interface. Documents are treated as a tree of nodes and the data those nodes contain are accessed by calling methods on the node objects themselves.

One of the more exciting features of XML::LibXML is that, in addition to the DOM interface, it allows you to select nodes using the XPath language

Iam have used this for Deleting of Nodes in the Context.xml file.We can also use this package which can perform the above things as XML::Simple.

Now if I want to delete the Few Elements I can use

$EWS_CFG_DIR=$ENV{JBS_CFGDIR};
$EWS_DS_FILE="$EWS_CFG_DIR/$VIRT_TARGET/conf/context.xml";
$DS_NAME="jdbc/".$DS_NAME;

my $parser = XML::LibXML->new();
my $tree = $parser->parse_file($EWS_DS_FILE);
my $root = $tree->getDocumentElement;
my @appPolicies = $root->getElementsByTagName('Resource');

foreach my $policy (@appPolicies) {
my $policy_name = $policy->getAttribute('name');

if($policy_name eq $DS_NAME) {
$policy->parentNode()->removeChild($policy);
print "In Equal Policies";
}#Closing Of If PolicY Nmae
}#Closing of App Policies

my $changed = $tree -> toString;
$tree->toFile($EWS_DS_FILE);


DS_NAME is the Name of the Data Source that I Sent as an Argument for deleting.

This is how we can parse Xml files in perl.Iam still working more on these Packages.I will upload more examples of these.

Happy learning :-)