William Jiang

JavaScript,PHP,Node,Perl,LAMP Web Developer – http://williamjxj.com; https://github.com/williamjxj?tab=repositories

XML Parser

package xml_parser; 

# William's xml parsing. Very fast, SAX style.
use XML::Parser;
use FileHandle;
use Data::Dumper;
use strict;
use constant LOGDIR => '/home/william_test/logs/'; 

# 1. setting global variables.
our ($scan_href, $pod_href, $context, @pickup_ary) = ({}, {}, undef, ());
 
# create download object.
sub new {
    my $proto = shift; 
    my $class = ref( $proto ) || $proto;
    my $self = {}; 

    # 1. initialize pod and pickup structure.
    $self->{pod} = {};
    $self->{pickup} = []; 

    # 2. create logfile to report xml parse process.
    # $self->{fh} = new FileHandle LOGDIR."/xml_parser.log", 
    "a"
    # or die "can not open logfile: $!"; 
    # such as: /home/prod/logs/ett_parser.log
    $self->{fh} = new FileHandle LOGDIR . __PACKAGE__ . ".log", 
    'a' or die "$!"; 
    $self->{fh}->autoflush( 1 ); 

    # 3. create xml parse object.
    $self->{parse} = new XML::Parser(Handlers => {
        'Start' => \&handle_start,
        'End' => \&handle_end,
        'Char' => \&handle_char
    }); 

	bless $self, $class;
} 

sub reset_pod_pickup {
    my $self = shift;
    foreach (keys %{ $self->{pod}} ) {
  	  $self->{pod}->{$_} = undef;
	}

    # $self->{pickup} = undef;
    undef( @pickup_ary );
} 

sub run {
    my ($self, $content) = @_;

    return unless ($content); 

    $self->reset_pod_pickup(); 
   
    eval {
	    $self->{parse}->parse( $content );
    }; 
   
    # report any error that stopped parsing, or announce success.
    if( $@ ) {
        $@ =~ s/at \/.*?$//s;
        $self->writeLog( "ERROR $@" ); 
        # william adds for track ERROR.
        $self->writeLog( $content );
        return;
    }
    else {
        #print {$self->{fh}} "'$file' is well-formed\n";
    } 

    # only pickup(scanType=08) and pod(scanType=20)
    @{ $self->{pickup} } = @pickup_ary;
    #grep( ($_->{ScanType} eq '08') || ($_->{ScanType} eq '20'), 
    @pickup_ary); 
    $self->{pod} = $pod_href; 
    return 1;
} 

# 4. define callback handlers.
# save element name and attributes.
sub handle_start {
    my ($expat, $element, %attribute) = @_;
    $context = $element; 
    # $expat->setHandlers('Char' => \&track_no) if ($element eq 'Number'); 
    $expat->setHandlers('Char' => \&track_no) if ($element eq 'TrackingNumber');
    $expat->setHandlers('Char' => \&ship_date) if ($element eq 'ShipDate');
    $expat->setHandlers('Char' => \&country_code) if ($element eq 'DestinationCountryCode' );
    $expat->setHandlers('Char' => \&city) if ($element eq 'DestinationCity');
    $expat->setHandlers('Char' => \&state) if ($element eq 'DestinationState');
    $expat->setHandlers('Char' => \&date) if ($element eq 'DeliveredDate');
    $expat->setHandlers('Char' => \&time) if ($element eq 'DeliveredTime');
    $expat->setHandlers('Char' => \&zip) if ($element eq 'DestinationZipCode');
    $expat->setHandlers('Char' => \&sign) if ($element eq 'SignedForBy');
    $expat->setHandlers('Char' => \&service) if ($element eq 'Service'); 
    $scan_href = undef if( $element eq 'Scan' ); 
} 

# if this is an <Scan>, collect all the data into a record.
sub handle_end {
    my ($expat, $element) = @_; 
    $expat->setHandlers('Char' => \&handle_char) if ($element eq 'TrackingNumber');
    $expat->setHandlers('Char' => \&handle_char) if ($element eq 'ShipDate');
    $expat->setHandlers('Char' => \&handle_char) if ($element eq 'DestinationCountryCode' );
    $expat->setHandlers('Char' => \&handle_char) if ($element eq 'DestinationCity');
    $expat->setHandlers('Char' => \&handle_char) if ($element eq 'DestinationState');
    $expat->setHandlers('Char' => \&handle_char) if ($element eq 'DeliveredDate');
    $expat->setHandlers('Char' => \&handle_char) if ($element eq 'DeliveredTime');
    $expat->setHandlers('Char' => \&handle_char) if ($element eq 'DestinationZipCode');
    $expat->setHandlers('Char' => \&handle_char) if ($element eq 'SignedForBy');
    $expat->setHandlers('Char' => \&handle_char) if ($element eq 'Service'); 

    return unless( $element eq 'Scan'); 
    push @pickup_ary, $scan_href;
} 

# collect character data into the recent element's buffer
sub handle_char {
    my ($expat, $string) = @_; 
    $scan_href->{ $context } = $string;
} 

sub track_no {
    my ($expat, $element) = @_;
    $pod_href->{ $context } = $element;
} 

sub ship_date {
    my ($expat, $element) = @_;
    $pod_href->{ $context } = $element;
}
......

sub service {
    my ($expat, $element) = @_;
    $pod_href->{ $context } = $element;
} 

sub writeLog {
    my ($self, $str) = @_;
    return unless $str; 
    unless (ref $str) {
        $str =~ s"\n""g; $str =~ s"\s+" "g;
        print {$self->{fh}} $str."\n";
    }
    else {
        $Data::Dumper::Varname = __PACKAGE__;
        print {$self->{fh}} Dumper($str);
    }
} 

sub get_pod {
    my $self = shift;
    return $self->{pod};
}
 
sub get_shipdate {
    my $self = shift;
    return $self->{pod}->{'ShipDate'};
}
 
# ref to array of hash.
sub get_pickup {
    my $self = shift;
    return $self->{pickup};
} 

sub get_pickup_1 {
    my $self = shift;
    my $scans_aref = []; 
    foreach my $t( @{$self->{pickup}} ) {
        push @$scans_aref, [ $t->{City}, $t->{CountryCode},
        $t->{Date}, $t->{Time}, $t->{ScanDescription}, $t->{ScanType} 
        ];
    }
    return $scans_aref;
} 

sub get_tracking_no {
    my $self = shift;
    return $self->{pod}->{'Number'}; #??????
    return $self->{pod}->{'TrackingNumber'};
} 

sub get_pod_delivery_location {
    my $self = shift;
    #$self->{pod}->{'DestinationCity'}.' '.$self->{pod}->{'DestinationState'};
    my $t=$self->{pod}->{'DestinationCity'} if $self->{pod}->{'DestinationCity'}; 
    
    $t .= ' ';
    $t.=$self->{pod}->{'DestinationState'} if $self->{pod}->{'DestinationState'};
    return $t;
} 

sub get_pod_country {
    my $self = shift;
    return $self->{pod}->{'DestinationCountryCode'} || '';
}

sub get_pod_delivery_country {
    my $self = shift;
    return $self->get_pod_country();
} 

sub get_pod_city {
    my $self = shift;
    return $self->{pod}->{'DestinationCity'} || '';
}

sub get_pod_delivery_city {
    my $self = shift;
    return $self->get_pod_city();
} 

sub get_pod_state {
    my $self = shift;
    return $self->{pod}->{'DestinationState'} || '';
}

sub get_pod_delivery_state {
    my $self = shift;
    return $self->get_pod_state();
} 

sub get_pod_delivery_date {
    my $self = shift;
    return $self->{pod}->{'DeliveredDate'} || '';
} 
......
sub get_pod_status {
    my $self = shift;
    return 
	($self->get_pod_delivery_date() && $self->get_pod_delivery_time()) ? 1:0;
} 

1;

One response to “XML Parser

  1. powercashadvance.com 10/26/2011 at 5:56 pm

    It’s rare to come across an experienced person in whom you will surely have some confidence. In the world today, nobody genuinely cares about showing others the way out in this subjecttopic. How blessed I am to have found a real wonderful blog as this. It is people like you that make a genuine difference in this world through the concepts they share.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: