ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Net-XMPP2/lib/Net/XMPP2/Parser.pm
Revision: 1.3
Committed: Fri Feb 9 20:23:06 2007 UTC (19 years, 7 months ago) by elmex
Branch: MAIN
Changes since 1.2: +0 -38 lines
Log Message:
removed unneccessary documentation and added neglected documentation.

File Contents

# User Rev Content
1 elmex 1.1 package Net::XMPP2::Parser;
2     use warnings;
3     use strict;
4     # OMFG!!!111 THANK YOU FOR THIS MODULE TO HANDLE THE XMPP INSANITY:
5     use Net::XMPP2::Node;
6     use XML::Parser::Expat;
7    
8     =head1 NAME
9    
10     Net::XMPP2::Parser - A parser for XML streams (helper for Net::XMPP2)
11    
12     =head1 SYNOPSIS
13    
14     use Net::XMPP2::Parser;
15     ...
16    
17 elmex 1.2 =head1 DESCRIPTION
18    
19     This is a XMPP XML parser helper class, which helps me to cope with the XMPP XML.
20    
21     See also L<Net::XMPP2::Writer> for a discussion of the issues with XML in XMPP.
22    
23 elmex 1.1 =head1 METHODS
24    
25     =head2 new
26    
27     This creates a new Net::XMPP2::Parser and calls C<init>.
28    
29     =cut
30    
31     sub new {
32     my $this = shift;
33     my $class = ref($this) || $this;
34     my $self = { stanza_cb => sub { die "No stanza callback provided!" }, @_ };
35     bless $self, $class;
36     $self->init;
37     $self
38     }
39    
40     =head2 set_stanza_cb ($cb)
41    
42     Sets the 'XML stanza' callback.
43    
44     C<$cb> must be a code reference. The first argument to
45     the callback will be this Net::XMPP2::Parser instance and
46     the second will be the stanzas root Net::XMPP2::Node as first argument.
47    
48     =cut
49    
50     sub set_stanza_cb {
51     my ($self, $cb) = @_;
52     $self->{stanza_cb} = $cb;
53     }
54    
55     =head2 init
56    
57     This methods (re)initializes the parser.
58    
59     =cut
60    
61     sub init {
62     my ($self) = @_;
63     $self->{parser} = XML::Parser::ExpatNB->new (
64     Namespaces => 1,
65     ProtocolEncoding => 'UTF-8'
66     );
67     $self->{parser}->setHandlers (
68     Start => sub { $self->cb_start_tag (@_) },
69     End => sub { $self->cb_end_tag (@_) },
70     Char => sub { $self->cb_char_data (@_) },
71     );
72     $self->{nso} = {};
73     $self->{nodestack} = [];
74     }
75    
76     =head2 nseq ($namespace, $tagname, $cmptag)
77    
78     This method checks whether the C<$cmptag> matches the C<$tagname>
79     in the C<$namespace>.
80    
81     C<$cmptag> needs to come from the XML::Parser::Expat as it has
82     some magic attached that stores the namespace.
83    
84     =cut
85    
86     sub nseq {
87     my ($self, $ns, $name, $tag) = @_;
88    
89     unless (exists $self->{nso}->{$ns}->{$name}) {
90     $self->{nso}->{$ns}->{$name} =
91     $self->{parser}->generate_ns_name ($name, $ns);
92     }
93    
94     return $self->{parser}->eq_name ($self->{nso}->{$ns}->{$name}, $tag);
95     }
96    
97     =head2 feed ($data)
98    
99     This method feeds a chunk of unparsed data to the parser.
100    
101     =cut
102    
103     sub feed {
104     my ($self, $data) = @_;
105     $self->{parser}->parse_more ($data);
106     }
107    
108    
109     sub cb_start_tag {
110     my ($self, $p, $el, %attrs) = @_;
111     push @{$self->{nodestack}}, Net::XMPP2::Node->new ($p->namespace ($el), $el, \%attrs, $self);
112     }
113    
114     sub cb_char_data {
115     my ($self, $p, $str) = @_;
116     unless (@{$self->{nodestack}}) {
117     warn "characters outside of tag: [$str]!\n";
118     return;
119     }
120     $self->{nodestack}->[-1]->add_text ($str);
121     }
122    
123     sub cb_end_tag {
124     my ($self, $p, $el) = @_;
125    
126     unless (@{$self->{nodestack}}) {
127     warn "end tag </$el> read without any starting tag!\n";
128     return;
129     }
130    
131     if (!$p->eq_name ($self->{nodestack}->[-1]->name, $el)) {
132     warn "end tag </$el> doesn't match start tags ($self->{tags}->[-1]->[0])!\n";
133     return;
134     }
135    
136     my $node = pop @{$self->{nodestack}};
137    
138     # > 1 because we don't want the stream tag to save all our children...
139     if (@{$self->{nodestack}} > 1) {
140     $self->{nodestack}->[-1]->add_node ($node);
141     }
142    
143     if (@{$self->{nodestack}} == 1) {
144     $self->{stanza_cb}->($self, $node);
145     }
146     }
147    
148     =head1 AUTHOR
149    
150     Robin Redeker, C<< <elmex at ta-sa.org> >>
151    
152     =head1 COPYRIGHT & LICENSE
153    
154     Copyright 2007 Robin Redeker, all rights reserved.
155    
156     This program is free software; you can redistribute it and/or modify it
157     under the same terms as Perl itself.
158    
159     =cut
160    
161     1; # End of Net::XMPP2