Tuesday, October 8, 2013

parsing xml data with perl

So a coworker wanted to parse an xml file. This xml file was retrieved using netconf and was equivalent to issuing a show bgp summary on a juniper router.


> show bgp summary                
Groups: 1 Peers: 2 Down peers: 0
Table          Tot Paths  Act Paths Suppressed    History Damp State    Pending
inet.0              
                      14          8          0          0          0          0
bgp.l3vpn.0        
                       0          0          0          0          0          0
bgp.l2vpn.0        
                       0          0          0          0          0          0
Peer                     AS      InPkt     OutPkt    OutQ   Flaps Last Up/Dwn State|#Active/Received/Accepted/Damped...
1.1.1.3               65000       4067        684       0       3     3:21:14 Establ
  inet.0: 4/7/7/0
  bgp.l3vpn.0: 0/0/0/0
  bgp.l2vpn.0: 0/0/0/0
1.1.1.4               65000       3653        865       0       2     4:10:55 Establ
  inet.0: 4/7/7/0
  bgp.l3vpn.0: 0/0/0/0
  bgp.l2vpn.0: 0/0/0/0


The xml file (bgp_summary.xml) looks like this:


0> show bgp summary | display xml
<rpc-reply xmlns:junos="http://xml.juniper.net/junos/12.3R1/junos">
    <bgp-information xmlns="http://xml.juniper.net/junos/12.3R1/junos-routing">
        <group-count>1</group-count>
        <peer-count>2</peer-count>
        <down-peer-count>0</down-peer-count>
        <bgp-rib junos:style="brief">
            <name>inet.0</name>
            <total-prefix-count>14</total-prefix-count>
            <received-prefix-count>14</received-prefix-count>
            <accepted-prefix-count>14</accepted-prefix-count>
            <active-prefix-count>8</active-prefix-count>
            <suppressed-prefix-count>0</suppressed-prefix-count>
.......
truncated.

so using the library XML::XPATH you can parse this file and retrieve the information.

-----------------
output:


% perl bgp.pl bgp_summary.xml

========> Peer = 1.1.1.3

rib-name = inet.0
active = 4
received = 7
accepted = 7
suppressed = 0

rib-name = bgp.l3vpn.0
active = 0
received = 0
accepted = 0
suppressed = 0

rib-name = bgp.l2vpn.0
active = 0
received = 0
accepted = 0
suppressed = 0


========> Peer = 1.1.1.4

rib-name = inet.0
active = 4
received = 7
accepted = 7
suppressed = 0

rib-name = bgp.l3vpn.0
active = 0
received = 0
accepted = 0
suppressed = 0

rib-name = bgp.l2vpn.0
active = 0
received = 0
accepted = 0
suppressed = 0


---------------

I didn't write the script. In fact I was in the middle of making my own version when another coworker beat me to it. My wasn't a nice:

% perl bgp_old.pl bgp_summary.xml
peer-address = 1.1.1.3 
------------------
name inet.0
total-prefix-count 14
total-prefix-count 14
received-prefix-count 14
accepted-prefix-count 8
accepted-prefix-count 0
------------------
name bgp.l3vpn.0
total-prefix-count 0
total-prefix-count 0
received-prefix-count 0
accepted-prefix-count 0
accepted-prefix-count 0
------------------
name bgp.l2vpn.0
total-prefix-count 0
total-prefix-count 0
received-prefix-count 0
accepted-prefix-count 0
accepted-prefix-count 0

His was way better and simple.

-------------
source code:

#!/usr/bin/perl

#use strict;
#use warnings;

use XML::XPath;

my $xmlfile = $ARGV[0];

my $lxp1 = XML::XPath->new(filename => $xmlfile);

foreach my $bgpPeer ($lxp1->find('//bgp-information/bgp-peer[peer-state="Established"]')->get_nodelist) {
        printf ("\n========> Peer = %s\n\n", $bgpPeer->find('peer-address')->string_value);
        foreach my $ribs ($bgpPeer->find('bgp-rib')->get_nodelist()) {
                printf ("\t\trib-name = %s\n", $ribs->find('name')->string_value);
                printf ("\t\tactive = %d\n", $ribs->find('active-prefix-count'));
                printf ("\t\treceived = %d\n", $ribs->find('received-prefix-count'));
                printf ("\t\taccepted = %d\n", $ribs->find('accepted-prefix-count'));
                printf ("\t\tsuppressed = %d\n\n", $ribs->find('suppressed-prefix-count'));
        }
}





No comments:

Post a Comment