Junos Automation (Scripting)
Reply
Super Contributor
B2
Posts: 208
Registered: ‎05-06-2010
0

Processing XML in PERL

  I've been working with PERL and the NETCONF module to run commands and process output from Juniper routers, I was wondering about the best method to process/parse the XML that is returned.  The examples provided in the packages use external .xsl files which is quite cumbersome and doesn't seem practical.  The automation guides mention using the SAX or DOM packages to process the XML.  Does anyone have recommendations either way?  Are there PERL examples out there using these packages to process the output from Juniper devices?

Super Contributor
jschulman
Posts: 146
Registered: ‎11-03-2009

Re: Processing XML in PERL

HI B2,

 

I have spend *a lot* of time working with Perl and NETCONF.  In my experience the best package to use is XML::LibXML.  It is the most comprehesive and best supported package I could find.  The downside to it is that there doesn't seem to be a lot of good documentation on it.  It took me a good bit of "trial and error" and a lot of Googling to figure out how to do what I needed.  The good news is that I'd be happy to share what I learned with you and the forum.

 

Cheers,

-- Jeremy

Cheers,
-- Jeremy

@nwkautomaniac
Super Contributor
B2
Posts: 208
Registered: ‎05-06-2010
0

Re: Processing XML in PERL

Thanks for the reply Jeremy, I did a quick search on LibXML and found a page that said this:

 

"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."

 

That pretty much has me sold right there.  I think I'll start playing with this library soon, as a starting point, is there any example code that could be provided?  Perhaps the get_chassis_inventory.pl example script written using that library?

Super Contributor
jschulman
Posts: 146
Registered: ‎11-03-2009
0

Re: Processing XML in PERL

Hi B2,

 

I've got a good snipped that can get you started.  This bit of code is used to process EX switch VLAN information as a result of running the command to show the ethernet switch VLAN information.  Hope this helps.

 

Cheers,

-- Jeremy

 

$xml_string = xml_loadfile( $xml_filename );

$dom = XML::LibXML->load_xml( string => $xml_string );
$top = $dom->documentElement;

@vlan_ifdlist = $dom->findnodes('/switching-interface-information/interface');

foreach my $ifd (@vlan_ifdlist) {

    $vlan_ifname = $ifd->find('./interface-name');

    @vlan_members = $ifd->findnodes(
       './interface-vlan-member-list/' .
       'interface-vlan-member[not(interface-vlan-name = "default")]');

    foreach my $vlan (@vlan_members) {
       $vlan_name = $vlan->find('interface-vlan-name');
       $vlan_id = $vlan->find('interface-vlan-member-tagid');
       print "Interface $vlan_ifname: $vlan_name($vlan_id)\n";
   }
}

 

 

And the output of this looks like:

 

 

Interface ge-0/0/0.0: FOO(100)
Interface ge-0/0/1.0: FOO(100)
Interface ge-0/0/2.0: FOO(100)
Interface ge-0/0/3.0: FOO(100)
Interface ge-0/0/10.0: Engineering(501)
Interface ge-0/0/11.0: Engineering(501)
Interface ge-0/0/12.0: Accounting(500)
Interface ge-0/0/12.0: Engineering(501)
Interface ge-0/0/13.0: Engineering(501)
Interface ge-0/0/13.0: FOO(100)
Interface ge-0/0/20.0: Accounting(500)
Interface ge-0/0/21.0: Accounting(500)
Interface ge-0/0/22.0: Accounting(500)

Cheers,
-- Jeremy

@nwkautomaniac
Super Contributor
B2
Posts: 208
Registered: ‎05-06-2010
0

Re: Processing XML in PERL

I've been trying to write a simple script to query a router and print out the names of the chassis modules (the XML I'm processing is the output of the 'show chassis hardware detail' command).  But it does not appear that the findnodes with Xpath expression is returning any nodes.

 

I've run the function $dom->toString() and printed it, it appears that the XML is properly getting installed into the object.  In your example, what is this line for?

 

$top = $dom->documentElement;

 

What is it doing? 

 

If possible, could you attach the XML that your program is processing?  It might help me follow along a bit better.

Super Contributor
jschulman
Posts: 146
Registered: ‎11-03-2009
0

Re: Processing XML in PERL

Hi B2,

 

Attached is the input XML.  I also wrote a subroutine to strip out the XML attributes.  This was necessary to get the XPath parsing to work "easier".

 

Here is my subroutine:

 

sub xml_loadfile {
    my ($xml_filename) = @_;
    my $xml_string = '';

    open (XML, $xml_filename);
    while(<XML>) {
       s/(<[\w-]+)(.*?)(\/?>)/\1\3/m;    # remove attributes
       $xml_string .= $_;
    }

    close (XML);
    return $xml_string;
}

 

The line $top = $dome->documentElement is used to assign $top to the root-element of the XML, in this case <switching-interface-information>.  In reviewing the code I posted, it looks like I'm not using $top.  I'm pretty sure that I could have done this:

 

@vlan_ifdlist = $top->findnodes('interface');

 

in place of this:

 

@vlan_ifdlist = $dom->findnodes('/switching-interface-information/interface');


Hope this helps.

 

Cheers,

-- Jeremy

Cheers,
-- Jeremy

@nwkautomaniac
Super Contributor
B2
Posts: 208
Registered: ‎05-06-2010
0

Re: Processing XML in PERL

So why exactly are you stripping off the attributes?  They are valid XML, I dont see why an Xpath expression would have a problem with them.  Is it a quirk of the LibXML library?  Does your script work without stripping off the attributes?

I'm also wondering about a few lines:

 $vlan_ifname = $ifd->find('./interface-name');

would 'interface-name' work there as an argument to the find function?  Is the './' necessary?

Super Contributor
jschulman
Posts: 146
Registered: ‎11-03-2009
0

Re: Processing XML in PERL

B2,

 

I've attached an updated version of the perl script that uses $top as well as removes the './' you mentioned.  So net-net, you are correct.

 

Regarding the attribute stripping, I ran into difficulties with XPath expressions when they existed.  For example, calling findnodes() would return an empty list when the attributes were present.  I tried a number of different LibXML techniques, but couldn't seem to figure out the right kung-fu to make it work.  I'll probably try cracking the code again when I have some free-cycles.

 

Hope this helps,

-- Jeremy

Cheers,
-- Jeremy

@nwkautomaniac
Super Contributor
B2
Posts: 208
Registered: ‎05-06-2010
0

Re: Processing XML in PERL

So I experimented with using the XML::smileyvery-happy:OM::XPath package, and now with my same code things are working fine.  Not sure how it may be different than the package you are working with.

Recognized Expert
Mattia
Posts: 198
Registered: ‎03-17-2010
0

Re: Processing XML in PERL

[ Edited ]

I am using another module, XML::smileyfrustrated:imple; it is very simple to use. Here is a little example, showing how to retrieve the router's hostname:

 

my $jnx = new JUNOS::Device(%deviceinfo);
my $configuration;
unless ( ref $jnx )
{
die "ERROR: $deviceinfo{hostname}: failed to connect.\n";
}

my $res = $jnx->get_configuration;
unless ( ref $res )
{
die "ERROR: $deviceinfo{hostname}: can't execute command.\n";
}

my $err = $res->getFirstError();
if ($err)
{
print STDERR "ERROR: $deviceinfo{'hostname'} - ", $err->{message}, "\n";
}
else
{

my $xmlfile = "$deviceinfo{hostname}.xml";
$res->printToFile($xmlfile);
$configuration = XMLin($xmlfile);
}


$host_name = $configuration->{'system'}->{'host-name'};

 I hope it helps you!

 

.................................................................................
JNCIP-ENT, JNCIP-SEC, JNCIS-SP
(If this post helped you, please mark it as an "Accepted Solution"; kudos are also appreciated!)


Copyright© 1999-2013 Juniper Networks, Inc. All rights reserved.