ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Net-XMPP2/lib/Net/XMPP2/Node.pm
Revision: 1.6
Committed: Fri Jul 20 20:41:48 2007 UTC (19 years, 2 months ago) by elmex
Branch: MAIN
Changes since 1.5: +41 -5 lines
Log Message:
lots of changes. added as_string to Net::XMPP2::Node to restore
the original xml document part of a stanza or subtree.
also implemented the jabber component protocol.

File Contents

# User Rev Content
1 elmex 1.1 package Net::XMPP2::Node;
2     use strict;
3     use Net::XMPP2::Namespaces qw/xmpp_ns/;
4    
5     use constant {
6     NS => 0,
7     NAME => 1,
8     ATTRS => 2,
9     TEXT => 3,
10     NODES => 4,
11     PARSER => 5,
12 elmex 1.6 RAW => 6
13     };
14    
15     use constant {
16     NNODE => 0,
17     NTEXT => 1,
18     NRAW => 2,
19 elmex 1.1 };
20    
21     =head1 NAME
22    
23 elmex 1.5 Net::XMPP2::Node - XML node tree helper for the parser.
24 elmex 1.1
25     =head1 SYNOPSIS
26    
27     use Net::XMPP2::Node;
28     ...
29    
30 elmex 1.4 =head1 DESCRIPTION
31    
32     This class represens a XML node. L<Net::XMPP2> should usually not
33     require messing with the parse tree, but sometimes it is neccessary.
34    
35     If you experience any need for messing with these and feel L<Net::XMPP2> should
36     rather take care of it drop me a mail, feature request or most preferably a patch!
37    
38     Every L<Net::XMPP2::Node> has a namespace, attributes, text and child nodes.
39    
40     You can access these with the following methods:
41    
42 elmex 1.1 =head1 METHODS
43    
44 elmex 1.4 =over 4
45    
46     =item B<new ($ns, $el, $attrs, $parser)>
47 elmex 1.1
48     Creates a new Net::XMPP2::Node object with the node tag name C<$el> in the
49     namespace URI C<$ns> and the attributes C<$attrs>. The C<$parser> must be
50     the instance of C<Net::XMPP2::Parser> which generated this node.
51    
52     =cut
53    
54     sub new {
55     my $this = shift;
56     my $class = ref($this) || $this;
57     my $self = [];
58     $self->[0] = $_[0];
59     $self->[1] = $_[1];
60     $self->[2] = $_[2];
61     $self->[5] = $_[3];
62 elmex 1.6 $self->[6] = '';
63 elmex 1.1 bless $self, $class;
64     return $self
65     }
66    
67 elmex 1.4 =item B<name>
68 elmex 1.1
69     The tag name of this node.
70    
71     =cut
72    
73     sub name {
74     $_[0]->[NAME]
75     }
76    
77 elmex 1.4 =item B<namespace>
78 elmex 1.1
79     Returns the namespace URI of this node.
80    
81     =cut
82    
83     sub namespace {
84     $_[0]->[NS]
85     }
86    
87 elmex 1.4 =item B<eq ($namespace_or_alias, $name) or eq ($node)>
88 elmex 1.1
89     Returns true whether the current element matches the tag name C<$name>
90     in the namespaces pointed at by C<$namespace_or_alias>.
91    
92     You can either pass an alias that was defined in L<Net::XMPP2::Namespaces>
93     or pass an namespace URI in C<$namespace_or_alias>. If no alias with the name
94     C<$namespace_or_alias> was found in L<Net::XMPP2::Namespaces> it will be
95     interpreted as namespace URI.
96    
97     The first argument to eq can also be another L<Net::XMPP2::Node> instance.
98    
99     =cut
100    
101     sub eq {
102     my ($self, $n, $name) = @_;
103     if (ref $n) {
104     return $self->[PARSER]->nseq ($n->namespace, $n->name, $self->name);
105     } else {
106     my $ns = xmpp_ns ($n);
107     return $self->[PARSER]->nseq (($ns ? $ns : $n), $name, $self->name);
108     }
109     }
110    
111 elmex 1.4 =item B<eq_ns ($namespace_or_alias) or eq_ns ($node)>
112 elmex 1.1
113     This method return true if the namespace of this instance of L<Net::XMPP2::Node>
114     matches the namespace described by C<$namespace_or_alias> or the
115     namespace of the C<$node> which has to be another L<Net::XMPP2::Node> instance.
116    
117     See C<eq> for the meaning of C<$namespace_or_alias>.
118    
119     =cut
120    
121     sub eq_ns {
122     my ($self, $n) = @_;
123     if (ref $n) {
124     return ($n->namespace eq $self->namespace);
125     } else {
126     my $ns = xmpp_ns ($n);
127     $ns ||= $n;
128     return ($ns eq $self->namespace);
129     }
130     }
131    
132 elmex 1.4 =item B<attr ($name)>
133 elmex 1.1
134     Returns the contents of the C<$name> attribute.
135    
136     =cut
137    
138     sub attr {
139     $_[0]->[ATTRS]->{$_[1]};
140     }
141    
142 elmex 1.4 =item B<add_node ($node)>
143 elmex 1.1
144     Adds a sub-node to the current node.
145    
146     =cut
147    
148     sub add_node {
149     my ($self, $node) = @_;
150 elmex 1.6 push @{$self->[NODES]}, [NNODE, $node];
151 elmex 1.1 }
152    
153 elmex 1.4 =item B<nodes>
154 elmex 1.1
155     Returns a list of sub nodes.
156    
157     =cut
158    
159     sub nodes {
160 elmex 1.6 map { $_->[1] }
161     grep { $_->[0] == NNODE }
162     @{$_[0]->[NODES] || []};
163 elmex 1.1 }
164    
165 elmex 1.4 =item B<add_text ($string)>
166 elmex 1.1
167     Adds character data to the current node.
168    
169     =cut
170    
171     sub add_text {
172     my ($self, $text) = @_;
173 elmex 1.6 push @{$self->[NODES]}, [NTEXT, $text];
174 elmex 1.1 }
175    
176 elmex 1.4 =item B<text>
177 elmex 1.1
178     Returns the text for this node.
179    
180     =cut
181    
182     sub text {
183 elmex 1.6 join '', map $_->[1], grep { $_->[0] == NTEXT } @{$_[0]->[NODES] || []}
184 elmex 1.1 }
185    
186 elmex 1.4 =item B<find_all (@path)>
187 elmex 1.1
188     This method does a recursive descent through the sub-nodes and
189     fetches all nodes that match the last element of C<@path>.
190    
191     The elements of C<@path> consist of a array reference to an array with
192     two elements: the namespace key known by the C<$parser> and the tagname
193     we search for.
194    
195     =cut
196    
197     sub find_all {
198     my ($self, @path) = @_;
199     my $cur = shift @path;
200     my @ret;
201     for my $n ($self->nodes) {
202     if ($n->eq (@$cur)) {
203     if (@path) {
204     push @ret, $n->find_all (@path);
205     } else {
206     push @ret, $n;
207     }
208     }
209     }
210     @ret
211     }
212    
213 elmex 1.4 =item B<write_on ($writer)>
214 elmex 1.2
215     This writes the current node out to the L<Net::XMPP2::Writer> object in C<$writer>.
216    
217     =cut
218    
219     sub write_on {
220     my ($self, $w) = @_;
221    
222     my ($ns, $tag) = ($self->namespace, $self->name);
223     $w->addPrefix ($ns => ''); # omg, xmpp is soo broken...
224     if ($self->nodes) {
225     $w->startTag ([$ns, $tag], %{$self->[ATTRS]});
226     $_->write_on ($w) for $self->nodes;
227     $w->endTag;
228     } else {
229     $w->emptyTag ([$ns, $tag], %{$self->[ATTRS]});
230     }
231     }
232    
233 elmex 1.4 =back
234    
235 elmex 1.6 =item B<as_string ()>
236    
237     This method returns the original character representation of this XML element
238     (and it's children nodes). Please note that the string is UTF-8 encoded (that
239     means to get a unicode string you need to decode ('UTF-8', ...) it)!
240    
241     =cut
242    
243     sub as_string {
244     my ($self) = @_;
245     join '',
246     map { $_->[0] == NRAW ? $_->[1] : $_->[1]->as_string }
247     grep { $_->[0] != NTEXT }
248     @{$self->[NODES] || []};
249     }
250    
251     =item B<append_raw ($string)>
252    
253     This method is called by the parser to store original strings of this element.
254    
255     =cut
256    
257     sub append_raw {
258     my ($self, $str) = @_;
259     push @{$self->[NODES]}, [NRAW, $str];
260     }
261    
262 elmex 1.1 =head1 AUTHOR
263    
264 elmex 1.4 Robin Redeker, C<< <elmex at ta-sa.org> >>, JID: C<< <elmex at jabber.org> >>
265 elmex 1.1
266     =head1 COPYRIGHT & LICENSE
267    
268     Copyright 2007 Robin Redeker, all rights reserved.
269    
270     This program is free software; you can redistribute it and/or modify it
271     under the same terms as Perl itself.
272    
273     =cut
274    
275     1; # End of Net::XMPP2