File Coverage

blib/lib/XML/Essex/Model.pm
Criterion Covered Total %
statement 223 288 77.4
branch 36 80 45.0
condition 42 84 50.0
subroutine 69 93 74.1
pod n/a
total 370 545 67.8


line stmt bran cond sub pod time code
1             package XML::Essex::Model;
2              
3             $VERSION = 0.000_1;
4              
5             =head1 NAME
6              
7             XML::Essex::Model - Essex objects representing SAX events and DOM trees
8              
9             =head1 SYNOPSIS
10              
11             Used internally by Essex, see below for external API examples.
12              
13             =head1 DESCRIPTION
14              
15             A description of all of the events explicitly supported so far.
16             Unsupported events are still handled as anonymous events, see
17             L for details.
18              
19             =head2 A short word on abbreviations
20              
21             A goal of essex is to allow code to be as terse or verbose as is
22             appropriate for the job at hand. So almost every object may be
23             abbreviated. So C may be abbreviated as C for
24             both the C method/function and for class creation.
25              
26             All objects are actually blessed in to classes using the long name, like
27             C even if you use an abbreviation like
28             Cnew> to create them.
29              
30             =head2 Stringification
31              
32             All events are stringifiable for debugging purposes and so that
33             attribute values, character data, comments, and processing instructions
34             may be matched with Perl string operations like regular expressions and
35             C. It is usually more effective to use EventPath, but you can
36             use stringified values for things like complex regexp matching.
37              
38             It is unwise to match other events with string operators because no XML
39             escaping of data is done, so "<" in an attribute value or character data
40             is stringified as "<", so Cing out the three events associated
41             with the sequence "<bar/>" will look like
42             "", obviously not what the document intended. Given
43             the rarity of such constructs in real life XML, though, this is
44             sufficient for debugging purposes, and does make it easy to match
45             against strings.
46              
47             Ordinarily, you tell C what kind of object you want using an
48             EventPath expression:
49              
50             my $start_element = get "start_element::*";
51              
52             You can also just C whatever's next in the document or use a
53             union expression. In this case, you may need to see what you've gotten.
54             The C method (see below) and the C functions (see
55             L) should be used to figure out what type of
56             object is being used before relying on the stringification:
57              
58             get until isa "chars" and /Bond, James Bond/;
59             get until type eq "characters" and /Bond, James Bond/;
60             get until isa( "chars" ) && /Bond, James Bond/;
61             get "text()" until /Bond, James Bond/;
62              
63             This makes it easier to match characters data, but other methods
64             should be used to select things like start tags and elements:
65              
66             get "start_element::*" until $_->name eq "address" && $_->{id} eq $id;
67             get "start_element::address" until $_->{id} eq $id;
68              
69             The lack of escaping only affects stringification of objects, for
70             instance:
71              
72             warn $_; ## See what event is being dealt with right now
73             /Bond, James Bond/ ## Match current event
74              
75             . Things are escaped properly when the put operator is used, using
76             C emits properly escaped XML.
77              
78             Some observervations:
79              
80             =over
81              
82             =item *
83              
84             Stringifying an event does not produce a well formed chunk of
85             XML. Events must be emitted through a downstream filter.
86              
87             =item *
88              
89             Events with no natural XML representation--like
90             start_document--stringify as their name: "start_document()". If it's
91             not listed on this page, it stringifies this way.
92              
93             =item *
94              
95             Whitespace is inserted only where manditory inside XML constructs, and
96             is a single space. It is left unmolested in character data, comments,
97             processing instructions (other than C<< >>, which is parsed
98             by all XML parsers).
99              
100             =item *
101              
102             Attributes in start_element events are stringified in alphabetical order
103             according to Perl's C function.
104              
105             =item *
106              
107             Processing instructions, including the C<< >> declaration,
108             often have things that look like attributes but are not, so the items
109             above about whitespace and attribute sort order do not apply. Actually,
110             the C<< >> declaration is well defined and there will
111             be only a single whitespace character, though the pseudo-attributes
112             version, encoding and standalone will not be sorted.
113              
114             =item *
115              
116             No escapes are used. See above.
117              
118             =item *
119              
120             Character data is catenated, including mixed data and CDATA, in to
121             single strings. CDATA sections are tracked and may be analyzed.
122              
123             =item *
124              
125             Namespaces are stringified according to any prefixes that have been
126             registered, otherwise they stringify in james clark notation
127             (C<"{}foo">), except for the empty namespace URI, which alway
128             stringifies as "" (ie no prefix). See L
129             section|XML::Essex/Namespaces> for details.
130              
131             =back
132              
133             =head1 Common Methods
134              
135             All of the objects in the model provide the following methods. These
136             methods are exported as functions from the L
137             module for convenience (those functions are wrappers around these
138             methods).
139              
140             =over
141              
142             =item isa
143              
144             Returns TRUE if the object is of the type, abbreviated type, or class
145             passed. So, for an object encapsulating a characters event, returns
146             TRUE for any of:
147              
148             XML::Essex::Event ## The base class for all events
149             XML::Essex::start_document ## The actuall class name
150             start_document ## The event type
151             start_doc ## The event type, abbreviated
152              
153             =item class
154              
155             Returns the class name, such as C.
156              
157             =item type
158              
159             Returns the class name, such as C.
160              
161             =item types
162              
163             Returns the class name, the type name and any abbreviations. The
164             abbreviations are sorted from longest to shortest.
165              
166             =back
167              
168             =head1 start_document
169              
170             aka: start_doc
171              
172             my $e = start_doc \%values; ## %values is not defined in SAX1/SAX2
173              
174             Stringifies as: C<< start_document($reserved) >>
175              
176             where $reserved is a character string that may sometime include
177             info passed in the start_document event, probably formatted as
178             attributes.
179              
180             =cut
181              
182 9     9   13026 use XML::Essex::Event;
  9         26  
  9         480  
183              
184             {
185 9     9   110 use strict;
  9         15  
  9         292  
186 9     9   45 use Carp ();
  9         19  
  9         3277  
187              
188             sub _jclarkify {
189 9     9   14 my ( $name ) = @_;
190              
191 9 100       30 return $name if substr( $name, 0, 1 ) eq "{";
192              
193 8 50       23 if ( $name =~ /(.*):(.*)/ ) { ## prefix notation
194             ## "TODO: Namespace prefix access for attrs";
195 0         0 return "{foo}$name";
196             }
197              
198             ## TODO: default to default ns instead of empty ns
199 8         24 return "{}$name";
200             }
201              
202              
203             sub _split_name {
204 2     2   4 my ( $name ) = @_;
205              
206 2 50       5 return ( $1, $2 ) if /^\{(.*)\}(.*)\z/;
207              
208             ## TODO: prefix => URI Namespace mapping
209 2 50       9 return ( "http://foo/", $2 ) if $name =~ /(.*):(.*)/;
210              
211             ## TODO: default to default ns instead of empty ns
212 2         5 return ( "", $name );
213             }
214              
215              
216             sub _render_name {
217 0     0   0 my ( $ns, $local_name ) = @_;
218              
219 0 0       0 $local_name = "*UNDEFINED NAME*" unless defined $local_name;
220              
221 0 0 0     0 return $local_name unless defined $ns && length $ns;
222              
223             ## TODO: ns => prefix mapping
224 0 0       0 return "foo:$local_name" if $ns =~ /foo/;
225              
226 0         0 return "{$ns}$local_name";
227             }
228              
229             sub _render_event_name {
230 0     0   0 _render_name @{$_[0]}{qw( NamespaceURI LocalName )};
  0         0  
231             }
232             }
233              
234             {
235             package XML::Essex::Event::start_document;
236              
237             @ISA = qw( XML::Essex::Event );
238              
239 9     9   60 use strict;
  9         15  
  9         2263  
240              
241 3     3   163 sub type { "start_document" }
242              
243 0     0   0 sub types { ( __PACKAGE__, "start_document", "start_doc" ) }
244              
245             sub isa {
246 4     4   784 my $self = shift;
247 4   66     37 return $_[0] eq "start_document"
248             || $_[0] eq "start_doc"
249             || $self->SUPER::isa( @_ );
250             }
251              
252             @XML::Essex::Event::start_doc::ISA = qw( XML::Essex::Event::start_document );
253             sub XML::Essex::Event::start_doc::new {
254 1     1   165 my $proto = shift;
255 1 50 33     8 $proto = __PACKAGE__
256             if ! ref $proto && $proto eq "XML:Essex::start_doc";
257 1         7 $proto->XML::Essex::Event::start_document::new( @_ )
258             }
259             }
260              
261             =head1 xml_decl
262              
263             aka: (no abbreviations)
264              
265             my $e = xml_decl;
266              
267             my $e = xml_decl
268             Version => "1",
269             Encoding => "UTF-8",
270             Standalone => "yes";
271              
272             my $e = xml_decl {
273             Version => "1",
274             Encoding => "UTF-8",
275             Standalone => "yes"
276             };
277              
278              
279             Stringifies as: C<<
280             standalone="$yes_or_no"?> >>
281              
282             Note that this does not follow the sorted attribute order behavior of
283             start_element, as the seeming attributes here are not attributes, like
284             processing instructions that have pretend attributes.
285              
286             =cut
287              
288             {
289             package XML::Essex::Event::xml_decl;
290              
291             @ISA = qw( XML::Essex::Event );
292              
293 9     9   61 use strict;
  9         28  
  9         602  
294              
295 9     9   46 use overload '""' => \&_stringify;
  9         16  
  9         66  
296              
297 1     1   416 sub type { "xml_decl" }
298              
299 0     0   0 sub types { ( __PACKAGE__, "xml_decl" ) }
300              
301             sub _stringify {
302 1     1   83 my $self = shift;
303 1 50 33     10557 return join "",
    50 33        
304             qq[{Version}"],
305             exists $$self->{Encoding} && $$self->{Encoding}
306             ? qq[ encoding="$$self->{Encoding}"] : (),
307             exists $$self->{Standalone} && defined $$self->{Standalone}
308             ? qq[ standalone="$$self->{Standalone}"] : (),
309             qq[?>];
310             }
311              
312             sub isa {
313 2     2   666 my $self = shift;
314 2   66     25 return $_[0] eq "xml_decl"
315             || $self->SUPER::isa( @_ );
316             }
317              
318             }
319              
320             =head1 end_document
321              
322             aka: end_doc
323              
324             my $e = end_doc \%values; ## %values is not defined in SAX1/SAX2
325              
326             Stringifies as: C<< end_document($reserved) >>
327              
328             where $reserved is a character string that may sometime include
329             info passed in the end_document event, probably formatted as
330             attributes.
331              
332             =cut
333              
334             {
335             package XML::Essex::Event::end_document;
336              
337             @ISA = qw( XML::Essex::Event );
338              
339 9     9   2786 use strict;
  9         170  
  9         1903  
340              
341 3     3   330 sub type { "end_document" }
342              
343 0     0   0 sub types { ( __PACKAGE__, "end_document", "end_doc" ) }
344              
345             sub isa {
346 4     4   891 my $self = shift;
347 4   66     38 return $_[0] eq "end_document"
348             || $_[0] eq "end_doc"
349             || $self->SUPER::isa( @_ );
350             }
351              
352             @XML::Essex::Event::end_doc::ISA = qw( XML::Essex::Event::end_document );
353             sub XML::Essex::Event::end_doc::new {
354 1     1   305 my $proto = shift;
355 1 50 33     23 $proto = __PACKAGE__
356             if ! ref $proto && $proto eq "XML:Essex::end_doc";
357 1         7 $proto->XML::Essex::Event::end_document::new( @_ )
358             }
359             }
360              
361             =head1 start_element
362              
363             aka: start_elt
364              
365             my $e = start_elt foo => { attr => "val" };
366             my $e = start_elt $start_elt; ## Copy constructor
367             my $e = start_elt $end_elt; ## end_elt deconstructor
368             my $e = start_elt $elt; ## elt deconstructor
369              
370             Stringifies as: C<< >>
371              
372             The element name and any attribute names are prefixed according to
373             namespace mappings registered in the Essex processor, the prefixes they
374             had in the source document are ignored. If no prefix has been mapped,
375             jclark notation (C<{http:...}foo>) is used. Then they are sorted
376             according to Perl's C function, so jclarked attribute names come
377             last, as it happens.
378              
379             TODO: Support attribute ordering via consecutive {...} sets.
380              
381             Attributes may be accessed using hash dereferences:
382              
383             get "start_element::*" until $_->{id} eq "10"; ## No namespace prefix
384             get "start_element::*" until $_->{"{}id"} eq "10";
385             get "start_element::*" until $_->{"{http://foo/}id"} eq "10";
386             get "start_element::*" until $_->{"foo:id"} eq "10";
387              
388             and the attribute names may be obtained by:
389              
390             keys %$_;
391              
392             . Keys are returned in no predictable order, see
393             L for details on the three formats
394             keys may be returned in.
395              
396             =head2 Methods
397              
398             =over
399              
400             =cut
401              
402             {
403             package XML::Essex::Event::start_element;
404              
405             @ISA = qw( XML::Essex::Event );
406              
407 9     9   46 use strict;
  9         19  
  9         482  
408              
409             use overload(
410 9         63 '""' => \&_stringify,
411             '%{}' => \&_hash_deref,
412 9     9   41 );
  9         26  
413              
414             sub new {
415             my $self = shift->SUPER::new(
416             ! ref $_[0]
417 7 100   7   648 ? do {
418 3         7 my $elt_name = shift;
419 3         6 my $attrs = shift;
420             (
421 2         28 Name => $elt_name,
422             LocalName => $elt_name,
423             $attrs
424             ? (
425             Attributes => {
426 3 100       24 map { ( "{}$_" => {
427             Name => $_,
428             LocalName => $_,
429             Value => $attrs->{$_},
430             } ) } keys %$attrs
431             }
432             )
433             : (),
434             )
435             }
436             : @_
437             );
438              
439 7         267 delete $$self->{StartElement}; ## In case an ::element was passed in
440 7         14 delete $$self->{EndElement}; ## In case an ::element was passed in
441 7         11 delete $$self->{Content}; ## In case an ::element was passed in
442 7         210 return $self;
443             }
444              
445 2     2   211 sub type { "start_element" }
446              
447 0     0   0 sub types { ( __PACKAGE__, "start_element", "start_elt" ) }
448              
449             sub _stringify {
450 14     14   63 my $self = shift;
451              
452 14         21 my $name = $$self->{LocalName};
453              
454 14 50 33     49 if ( defined $$self->{NamespaceURI}
455             && length $$self->{NamespaceURI}
456             ) {
457             ## TODO namespace -> prefix translation
458 0         0 $name = "foo:$name";
459             }
460              
461             ## Work around some odd thread safety thing.
462             ## TODO: See if this can be removed with perl5.8.1
463 14         22 my $s = $$self;
464 14         20 my $a = $s->{Attributes};
465              
466 33         47 my $foo = join "",
467             qq[<],
468             $name,
469             keys %$a
470             ? sort map {
471 14 50       45 my $name = $_->{LocalName};
472              
473 33 50 66     75 if ( defined $_->{NamespaceURI}
474             && length $_->{NamespaceURI}
475             ) {
476             ## TODO namespace -> prefix translation
477 0         0 $name = "foo:$name";
478             }
479              
480 33         119 join "", qq[ ], $name, qq[="], $_->{Value}, qq["];
481             } values %$a
482             : (),
483             qq[>];
484              
485 14         157 return $foo;
486             }
487              
488             sub _hash_deref {
489 16     16   2521 my $self = shift;
490 16   66     57 $$self->{_TiedAttributes} ||= do {
491 2         3 my %h;
492 2         16 tie
493             %h,
494             "XML::Essex::Event::_tied_attributes",
495             $$self->{Attributes};
496 2         9 \%h;
497             };
498 16         226 return $$self->{_TiedAttributes};
499             }
500              
501             sub isa {
502 4     4   789 my $self = shift;
503 4   66     200 return $_[0] eq "start_element"
504             || $_[0] eq "start_elt"
505             || $self->SUPER::isa( @_ );
506             }
507              
508             sub generate_SAX {
509 1     1   2 my $self = shift;
510 1 50       11 return $self->SUPER::generate_SAX( @_ )
511             unless exists $$self->{_TiedAttributes};
512              
513 0         0 my $ta = delete $$self->{_TiedAttributes};
514              
515 0         0 my $r;
516              
517 0         0 my $ok = eval {
518 0         0 $r = $self->SUPER::generate_SAX( @_ );
519 0         0 1;
520             };
521 0         0 $$self->{_TiedAttributes} = $ta;
522 0 0       0 die $@ unless $ok;
523              
524 0         0 return $r;
525             }
526              
527             @XML::Essex::Event::start_elt::ISA = qw( XML::Essex::Event::start_element );
528             sub XML::Essex::Event::start_elt::new {
529 1     1   174 my $proto = shift;
530 1 50 33     9 $proto = __PACKAGE__
531             if ! ref $proto && $proto eq "XML:Essex::start_elt";
532 1         5 $proto->XML::Essex::Event::start_element::new( @_ )
533             }
534              
535             =item name
536              
537             Returns the name of the node according to the namespace stringification
538             rules.
539              
540             =cut
541              
542             sub name {
543 0     0   0 my $self = shift;
544 0         0 return XML::Essex::Model::_render_event_name( $$self );
545             }
546              
547             =item jclark_name
548              
549             Returns the name of the node in James Clark notation.
550              
551             =cut
552              
553             sub jclark_name {
554 0     0   0 my $self = shift;
555 0 0       0 return join( "",
556             "{",
557             defined $$self->{NamespaceURI}
558             ? $$self->{NamespaceURI} : "",
559             "}",
560             $$self->{LocalName}
561             );
562             }
563              
564             =item jclark_keys
565              
566             my @keys = $e->jclark_keys
567              
568             Returns a list of attribute names in jclark notation ("{...}name").
569              
570             =cut
571              
572 2     2   217 sub jclark_keys { keys %{${shift()}->{Attributes}} }
  2         3  
  2         21  
573              
574             package XML::Essex::Event::_tied_attributes;
575              
576             ## tie %h, "XML...", $event;
577              
578             sub TIEHASH {
579 2     2   4 my $proto = shift;
580 2         21 return bless {
581             Attributes => shift,
582             Wrappers => {},
583             }, $proto;
584             }
585              
586             sub EXISTS {
587             return
588 0     0   0 exists shift->{Attributes}->{XML::Essex::Model::_jclarkify shift};
589             }
590              
591             sub FETCH {
592 6     6   112 my $self = shift;
593 6         14 my $name = XML::Essex::Model::_jclarkify shift;
594              
595             return $self->{Wrappers}->{$name}
596             ||= XML::Essex::Event::attribute->new(
597 6   66     47 $self->{Attributes}->{$name} ||= do {
      100        
598 1         4 my ( $ns, $name ) = XML::Essex::Model::_split_name $name;
599             {
600 1         7 LocalName => $name,
601             NamespaceURI => $ns,
602             Value => "",
603             }
604             }
605             );
606             }
607              
608             sub STORE {
609 2     2   5 my $self = shift;
610 2         5 my $name = XML::Essex::Model::_jclarkify shift;
611 2         4 my $value = shift;
612              
613 2   66     12 $self->{Attributes}->{$name} ||= do {
614 1         4 my ( $ns, $name ) = XML::Essex::Model::_split_name $name;
615             {
616 1         7 LocalName => $name,
617             NamespaceURI => $ns,
618             }
619             };
620              
621 2         10 $self->{Attributes}->{$name}->{Value} = $value;
622             }
623              
624             sub DELETE {
625 1     1   2 my $self = shift;
626 1         3 my $name = XML::Essex::Model::_jclarkify shift;
627 1         3 delete $self->{Attributes}->{$name};
628 1         5 delete $self->{Wrappers}->{$name};
629             }
630              
631             sub FIRSTKEY {
632 7     7   12 my $self = shift;
633 7         8 keys %{$self->{Attributes}}; ## reset each()'s state
  7         20  
634             ## TODO: apply ns=>prefix mappings
635 7         10 my $r = each %{$self->{Attributes}};
  7         24  
636 7         32 $r =~ s/^\{\}//;
637 7         33 return $r;
638             }
639              
640             sub NEXTKEY {
641 12     12   14 my $self = shift;
642             ## TODO: apply ns=>prefix mappings
643 12         16 my $r = each %{$self->{Attributes}};
  12         27  
644 12         27 $r =~ s/^\{\}//;
645 12         206 return $r;
646             }
647             }
648              
649             =back
650              
651             =head1 attribute
652              
653             aka: attr
654              
655             my $name_attr = $start_elt->{name};
656             my $attr = attr $name;
657             my $attr = attr $name => $value;
658             my $attr = attr {
659             LocalName => $local_name,
660             NamespaceURI => $ns_uri,
661             Value => $value,
662             };
663              
664              
665             Stringifies as its value: C<< harvey >>
666              
667             This is not a SAX event, but an object returned from within element or
668             start_element objects that gives you access to the C,
669             C, and C fields of the attribute. Does not give
670             access to the Name or Prefix fields present in SAX events.
671              
672             If you create an attribute with an undefined value, it will stringify
673             as the Cined value. Attributes that are created without an
674             explicit Cined C field will be given the defaul value
675             of "", including attributes that are autovivified. This allows
676              
677             get "*" until $_->{id} eq "10";
678              
679             to work. This has the side effect of addingan C attribute to all
680             elements without an C attribute. To avoid the side effect, use the
681             C function to detect nonexistant attributes:
682              
683             get "*" until exists $_->{id} and $_->{id} eq "10";
684              
685             =cut
686              
687             {
688             package XML::Essex::Event::attribute;
689              
690             @ISA = qw( XML::Essex::Event );
691              
692 9     9   13149 use strict;
  9         20  
  9         529  
693              
694 9     9   47 use overload '""' => \&_stringify;
  9         15  
  9         97  
695              
696             sub new {
697             my $self = shift->SUPER::new(
698             ! ref $_[0]
699 4 50   4   30 ? do {
700 0         0 my ( $ns, $name ) = XML::Essex::Model::_split_name shift;
701 0 0       0 my $value = @_ ? shift : "";
702             (
703 0         0 NamespaceURI => $ns,
704             LocalName => $name,
705             Value => $value,
706             Name => undef,
707             Prefix => undef,
708             )
709             }
710             : @_
711             );
712              
713 4         84 delete $$self->{StartElement}; ## In case an ::element was passed in
714 4         51 delete $$self->{EndElement}; ## In case an ::element was passed in
715 4         16 delete $$self->{Content}; ## In case an ::element was passed in
716 4         14 return $self;
717             }
718              
719 0     0   0 sub type { "attribute" }
720              
721 0     0   0 sub types { ( __PACKAGE__, "attribute", "attr" ) }
722              
723 14     14   15 sub _stringify { ${shift()}->{Value} }
  14         65  
724              
725             sub isa {
726 0     0   0 my $self = shift;
727 0   0     0 return $_[0] eq "attribute"
728             || $_[0] eq "attr"
729             || $self->SUPER::isa( @_ );
730             }
731              
732             @XML::Essex::Event::attr::ISA = qw( XML::Essex::Event::attribute );
733             sub XML::Essex::Event::attr::new {
734 0     0   0 my $proto = shift;
735 0 0 0     0 $proto = __PACKAGE__
736             if ! ref $proto && $proto eq "XML:Essex::attr";
737 0         0 $proto->XML::Essex::Event::attribute::new( @_ )
738             }
739             }
740              
741              
742             =head1 end_element
743              
744             aka: end_elt
745              
746             my $e = end_element "foo";
747             my $e = end_element $start_elt;
748             my $e = end_element $end_elt;
749             my $e = end_element $elt;
750              
751             Stringifies as: C<< >>
752              
753             See L for details on namespace handling.
754              
755             =cut
756              
757             {
758             package XML::Essex::Event::end_element;
759              
760             @ISA = qw( XML::Essex::Event );
761              
762 9     9   3822 use strict;
  9         17  
  9         376  
763              
764 9     9   56 use overload '""' => \&_stringify;
  9         35  
  9         172  
765              
766             sub new {
767             my $self = shift->SUPER::new(
768             ! ref $_[0]
769 7 100   7   559 ? do {
770 2         4 my $elt_name = shift;
771             (
772 2         24 Name => $elt_name,
773             LocalName => $elt_name,
774             )
775             }
776             : shift
777             );
778              
779 7         254 delete $$self->{StartElement}; ## In case an ::element was passed in
780 7         10 delete $$self->{Content}; ## In case an ::element was passed in
781 7         11 delete $$self->{EndElement}; ## In case an ::element was passed in
782 7         12 delete $$self->{Attributes}; ## ::element or ::start_element
783 7         19 return $self;
784             }
785              
786 2     2   339 sub type { "end_element" }
787              
788 0     0   0 sub types { ( __PACKAGE__, "end_element", "end_elt" ) }
789              
790             sub _stringify {
791 6     6   40 my $self = shift;
792              
793 6         9 my $name = $$self->{LocalName};
794              
795 6 50 33     21 if ( defined $$self->{NamespaceURI}
796             && length $$self->{NamespaceURI}
797             ) {
798             ## TODO namespace -> prefix translation
799 0         0 $name = "foo:$name";
800             }
801              
802 6         85 return join $name, qq[];
803             }
804              
805             sub isa {
806 4     4   899 my $self = shift;
807 4   66     40 return $_[0] eq "end_element"
808             || $_[0] eq "end_elt"
809             || $self->SUPER::isa( @_ );
810             }
811              
812             @XML::Essex::Event::end_elt::ISA = qw( XML::Essex::Event::end_element );
813             sub XML::Essex::Event::end_elt::new {
814 1     1   190 my $proto = shift;
815 1 50 33     9 $proto = __PACKAGE__
816             if ! ref $proto && $proto eq "XML:Essex::end_elt";
817 1         6 $proto->XML::Essex::Event::end_element::new( @_ )
818             }
819             }
820              
821             =head1 element
822              
823             aka: elt
824              
825             my $e = elt foo => "content", $other_elt, "more content", $pi, ...;
826             my $e = elt foo => { attr1 => "val1" }, "content", ...;
827              
828             Stringifies as: C<< content >>
829              
830             Never stringifies as an empty element tag (C<< >>), although
831             downstream filters and handlers may choose to do that.
832              
833             Constructs an element. An element is a sequence of events between a
834             matching start_element and end_element, inclusive.
835              
836             Attributes may be accessed using Perl hash dereferencing, as with
837             start_element events, see L for details.
838              
839             Content may be accessed using Perl array dereferencing:
840              
841             my @content = @$_;
842             unshift @$_, "prefixed content";
843             push @$_, "appended content";
844              
845             Note that
846              
847             my $elt2 = elt $elt1; ## doesn't copy content, just name+attra
848              
849             only copies the name and attributes, it does I copy the content.
850             To copy content do either of:
851              
852             my $elt2 = elt $elt1, @$elt1;
853             my $elt2 = $elt1->clone;
854              
855             This is because the first parameter is converted to a start/end_element
856             pair and any content is ignored. This is so that:
857              
858             my $elt2 = elt $elt1, "new content";
859              
860             creates an element with the indicated content.
861              
862             =head2 Methods
863              
864             =over
865              
866             =cut
867              
868              
869             {
870             package XML::Essex::Event::element;
871              
872             @ISA = qw( XML::Essex::Event );
873              
874 9     9   4775 use strict;
  9         25  
  9         1074  
875              
876             use overload(
877             '""' => \&_stringify,
878 2     2   600 '%{}' => sub { ${shift()}->{StartElement}->_hash_deref },
  2         18  
879 5     5   826 '@{}' => sub { ${shift()}->{Content} },
  5         24  
880 9     9   50 );
  9         16  
  9         112  
881              
882             sub new {
883 3     3   402 my $proto = shift;
884 3         172 my $self = $proto->SUPER::new;
885              
886 3 50       12 if ( @_ ) {
887 3         5 my $arg1 = shift;
888              
889 3 100       18 $arg1 = $$arg1->{StartElement}
890             if UNIVERSAL::isa( $arg1, __PACKAGE__ );
891              
892 3         4 $$self->{StartElement} = do {
893 3         4 my @args;
894 3   100     19 push @args, shift while @_ && ref $_[0] eq "HASH";
895 3         11 XML::Essex::Event::start_element->new( $arg1, @args );
896             };
897              
898 3 50 66     18 if ( @_ && UNIVERSAL::isa( $_[-1], "XML::Essex::Model::end_element" ) ) {
899 0         0 $$self->{EndElement} = pop;
900             }
901              
902 3 0       31 @{$$self->{Content}} = map
  3 50       11  
903             ! ref $_ ? XML::Essex::Event::characters->new( $_ )
904             : ref eq "ARRAY" ? XML::Essex::Event::element->new( @$_ )
905             : Carp::croak( "$_ is not a content for $self" ),
906             @_;
907             }
908              
909 3         8 return $self;
910             }
911              
912             sub _set_default_end_element {
913 3     3   4 my $self = shift;
914              
915 3 50       10 return if $$self->{EndElement};
916              
917 3         18 $$self->{EndElement} =
918             XML::Essex::Event::end_element->new( $$self->{StartElement} );
919             }
920              
921             ## Utility functions used in XML::Handler::Essex to build elements
922             ## from incoming events.
923             sub _start_element {
924 0     0   0 my $self = shift;
925 0 0       0 $$self->{StartElement} = shift if @_;
926 0         0 $$self->{StartElement};
927             }
928              
929             sub _add_content {
930 0     0   0 my $self = shift;
931 0         0 push @{$$self->{Content}}, shift;
  0         0  
932             }
933              
934             sub _end_element {
935 0     0   0 my $self = shift;
936 0 0       0 $$self->{EndElement} = shift if @_;
937 0         0 $$self->{EndElement};
938             }
939              
940             sub clone {
941 0     0   0 my $clone = shift->SUPER::clone;
942              
943 0         0 $_ = $_->clone for $clone->{StartElement},
  0         0  
944             @{$clone->{Content}},
945             $clone->{EndElement};
946              
947 0         0 return $clone;
948             }
949              
950 1     1   179 sub type { "element" }
951              
952 0     0   0 sub types { ( __PACKAGE__, "element", "elt" ) }
953              
954             sub _stringify {
955 3     3   46 my $self = shift;
956              
957 3 50       10 Carp::croak "Can't stringify element with no start_element event"
958             unless $$self->{StartElement};
959              
960 3         12 $self->_set_default_end_element;
961              
962 3         10 return join "",
963             $$self->{StartElement},
964 3         6 @{$$self->{Content}},
965             $$self->{EndElement};
966             }
967              
968              
969             sub isa {
970 4     4   1096 my $self = shift;
971 4   66     60 return $_[0] eq "element"
972             || $_[0] eq "elt"
973             || $self->SUPER::isa( @_ );
974             }
975              
976             sub generate_SAX {
977 0     0   0 my $self = shift;
978 0 0       0 Carp::croak "Can't generate SAX events for element with no start_element event"
979             unless $$self->{StartElement};
980              
981 0         0 $self->_set_default_end_element;
982              
983 0         0 $_->generate_SAX( @_ )
984 0         0 for $$self->{StartElement},
985             @{$$self->{Content}},
986             $$self->{EndElement};
987             }
988              
989             @XML::Essex::Event::elt::ISA = qw( XML::Essex::Event::element );
990             sub XML::Essex::Event::elt::new {
991 1     1   185 my $proto = shift;
992 1 50 33     9 $proto = __PACKAGE__
993             if ! ref $proto && $proto eq "XML:Essex::elt";
994 1         6 $proto->XML::Essex::Event::element::new( @_ )
995             }
996              
997             =item jclark_keys
998              
999             Returns the names of attributes as a list of JamesClarkified
1000             keys, just like start_element's C.
1001              
1002             =cut
1003              
1004 1     1   214 sub jclark_keys { ${shift()}->{StartElement}->jclark_keys }
  1         6  
1005              
1006             =item name
1007              
1008             Returns the name of the node according to the namespace stringification
1009             rules.
1010              
1011             =cut
1012              
1013 0     0   0 sub name { ${shift()}->{StartElement}->name }
  0         0  
1014              
1015             =item jclark_name
1016              
1017             Returns the name of the node in James Clark notation.
1018              
1019             =cut
1020              
1021 0     0   0 sub jclark_name { ${shift()}->{StartElement}->jclark_name }
  0         0  
1022             }
1023              
1024             =back
1025              
1026             =head1 characters
1027              
1028             aka: chars
1029              
1030             my $e = chars "A stitch", " in time", " saves nine";
1031             my $e = chars {
1032             Data => "A stitch in time saves nine",
1033             };
1034              
1035             Stringifies like a string: C<< A stitch in time saves nine. >>
1036              
1037             Character events are aggregated.
1038              
1039             TODO: make that aggregation happen.
1040              
1041             =cut
1042              
1043             {
1044             package XML::Essex::Event::characters;
1045              
1046             @ISA = qw( XML::Essex::Event );
1047              
1048 9     9   9861 use strict;
  9         17  
  9         438  
1049              
1050 9     9   49 use overload '""' => \&_stringify;
  9         44  
  9         60  
1051              
1052             sub new {
1053 5 100   5   436 my $self = shift->SUPER::new(
1054             ! ref $_[0]
1055             ? (
1056             Data => join( "", @_ ),
1057             )
1058             : shift
1059             );
1060              
1061 5         14 return $self;
1062             }
1063              
1064 2     2   320 sub type { "characters" }
1065              
1066 0     0   0 sub types { ( __PACKAGE__, "characters", "chars" ) }
1067              
1068 7     7   305 sub _stringify { ${shift()}->{Data} };
  7         42  
1069              
1070             sub isa {
1071 4     4   830 my $self = shift;
1072 4   66     43 return $_[0] eq "characters"
1073             || $_[0] eq "chars"
1074             || $self->SUPER::isa( @_ );
1075             }
1076              
1077             @XML::Essex::Event::chars::ISA = qw( XML::Essex::Event::characters );
1078             sub XML::Essex::Event::chars::new {
1079 1     1   179 my $proto = shift;
1080 1 50 33     19 $proto = __PACKAGE__
1081             if ! ref $proto && $proto eq "XML:Essex::chars";
1082 1         7 $proto->XML::Essex::Event::characters::new( @_ )
1083             }
1084             }
1085              
1086             =head1 comment
1087              
1088             aka: (no abbreviation)
1089              
1090             my $e = comment "A stitch in time saves nine";
1091             my $e = comment {
1092             Data => "A stitch in time saves nine",
1093             };
1094              
1095             Stringifies like a string: C<< A stitch in time saves nine. >>
1096              
1097             =cut
1098              
1099             {
1100             package XML::Essex::Event::comment;
1101              
1102             @ISA = qw( XML::Essex::Event );
1103              
1104 9     9   3922 use strict;
  9         20  
  9         612  
1105              
1106 9     9   1904 use overload '""' => \&_stringify;
  9         17  
  9         211  
1107              
1108             sub new {
1109 2 100   2   624 my $self = shift->SUPER::new(
1110             ! ref $_[0]
1111             ? (
1112             Data => shift,
1113             )
1114             : shift
1115             );
1116              
1117 2         6 return $self;
1118             }
1119              
1120 1     1   204 sub type { "comment" }
1121              
1122 0     0   0 sub types { ( __PACKAGE__, "comment" ) }
1123              
1124 2     2   174 sub _stringify { ${shift()}->{Data} };
  2         15  
1125              
1126             sub isa {
1127 2     2   428 my $self = shift;
1128 2   66     20 return $_[0] eq "comment"
1129             || $self->SUPER::isa( @_ );
1130             }
1131             }
1132              
1133             =head1 Implementation Details
1134              
1135             =head2 References and blessed, tied or overloaded SAX events.
1136              
1137             Instances of the Essex object model classes carry a reference to the
1138             original data (SAX events), rather than copying it. This means that
1139             there are fewer copies (a good thing; though there is an increased cost
1140             of getting at any data in the events) and that upstream filters may send
1141             blessed, tied, or overloaded objects to us and they will not be molested
1142             unless the Essex filter messes with them. There is also an
1143             implementation reason for this, it makes overloading hash accesses
1144             like C<$_->{}> easier to implement.
1145              
1146             Passing an Essex event to a constructor for a new Essex event does
1147             result in a deep copy of the referenced data (via
1148             C).
1149              
1150             =head2 Class files, or the lack thereof
1151              
1152             The objects in the Essex object model are not available independantly
1153             as class files. You must use C to get at them. This
1154             is because there is a set of event types used in almost all SAX filters
1155             and it is cheaper to compile one file containing these than to open
1156             multiple files.
1157              
1158             This does not mean that all classes are loaded when the
1159             XML::Essex::Model is Ced or Ced, rare events are
1160             likely to be autoloaded.
1161              
1162             =head2 Class names
1163              
1164             In order to allow
1165              
1166             my $e = XML::Essex::start_elt( ... );
1167              
1168             to work as expected--in case the calling package prefers not to import
1169             C, for instance--the objects in the model are all in the
1170             XML::Essex::Event::... namespace, like
1171             C.
1172              
1173             =head1 TODO
1174              
1175             =over
1176              
1177             =item Allow escaping to be configured
1178              
1179             =item Allow " vs. ' for attr quotes to be configured.
1180              
1181             =item Allow CDATA to be tested for, either by stringifying it or by
1182             allowing it to be returned as an array or something.
1183              
1184             =back
1185              
1186             =for the future
1187             =head1 LIMITATIONS
1188              
1189             =head1 COPYRIGHT
1190              
1191             Copyright 2002, R. Barrie Slaymaker, Jr., All Rights Reserved
1192              
1193             =head1 LICENSE
1194              
1195             You may use this module under the terms of the BSD, Artistic, oir GPL licenses,
1196             any version.
1197              
1198             =head1 AUTHOR
1199              
1200             Barrie Slaymaker
1201              
1202             =cut
1203              
1204             1;