File Coverage

blib/lib/XML/DOMHandler.pm
Criterion Covered Total %
statement 6 70 8.5
branch 0 6 0.0
condition 0 18 0.0
subroutine 2 17 11.7
pod 2 4 50.0
total 10 115 8.7


line stmt bran cond sub pod time code
1             # $Id: DOMHandler.pm,v 1.1 2002/08/20 18:06:48 eray Exp eray $
2              
3             package XML::DOMHandler;
4 1     1   835 use strict;
  1         2  
  1         49  
5 1     1   6 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
  1         2  
  1         1705  
6             require Exporter;
7             @ISA = qw( Exporter );
8             @EXPORT = qw( Version );
9             $VERSION = '1.0';
10 0     0 1   sub Version { $VERSION; }
11              
12             #
13             # table of node types and internal handler methods
14             #
15             my %dispatch_table = (
16             &XML_ELEMENT_NODE => '_handle_element',
17             &XML_ATTRIBUTE_NODE => '_handle_attribute',
18             &XML_TEXT_NODE => '_handle_text',
19             &XML_CDATA_SECTION_NODE => '_handle_cdata',
20             &XML_ENTITY_REF_NODE => '_handle_entity_ref',
21             &XML_ENTITY_NODE => '',
22             &XML_PI_NODE => '_handle_pi',
23             &XML_COMMENT_NODE => '_handle_comment',
24             &XML_DOCUMENT_NODE => '_handle_doc_node',
25             &XML_DOCUMENT_TYPE_NODE => '_handle_doctype',
26             &XML_DOCUMENT_FRAG_NODE => '',
27             &XML_NOTATION_NODE => '',
28             &XML_HTML_DOCUMENT_NODE => '',
29             &XML_DTD_NODE => '',
30             &XML_ELEMENT_DECL_NODE => '',
31             &XML_ATTRIBUTE_DECL_NODE => '',
32             &XML_ENTITY_DECL_NODE => '',
33             &XML_NAMESPACE_DECL_NODE => '_handle_ns_decl',
34             &XML_XINCLUDE_START => '',
35             &XML_XINCLUDE_END => '',
36             );
37              
38             my $level; # depth in the tree
39             my $position; # position in parent's content list
40             my @pstack; # position stack
41             my $root;
42             my $rootset = 0;
43              
44              
45             sub new {
46             #
47             # initialize object with options
48             #
49 0     0 0   my $class = shift;
50 0           my $self = {@_};
51 0           reset();
52 0           return bless( $self, $class );
53             }
54              
55              
56             sub reset {
57             #
58             # set globals back to zero
59             #
60 0     0 0   $level = 0;
61 0           $position = 0;
62 0           @pstack = (0);
63             }
64              
65              
66             sub traverse {
67             #
68             # dispatch node to handler, recurse
69             #
70 0     0 1   my( $self, $node ) = @_;
71              
72 0           my $handled_flag = 0;
73 0           my $fun = $dispatch_table{ $node->nodeType };
74              
75 0 0         $root = $node unless( $rootset );
76 0           $rootset = 1;
77              
78 0 0         if( $fun ) {
79 0           $handled_flag = $self->$fun( $node );
80 0           return 1;
81              
82             # apply generic Node handler
83 0   0       $handled_flag =
84             $self->_apply_user_handler( $node, 'generic_node' )
85             || $handled_flag;
86            
87             # apply generic "else" node handler if no handlers applied
88 0   0       $handled_flag ||=
89             $self->_apply_user_handler( $node, 'else_generic_node' );
90             }
91              
92 0           return $handled_flag;
93             }
94              
95              
96             sub _handle_element {
97             #
98             # process an element, recurse if necessary
99             #
100 0     0     my( $self, $node ) = @_;
101 0           my $handled_flag = 0;
102              
103             # apply specific element handler
104 0           my $name = $node->nodeName;
105 0           $handled_flag = $self->_apply_user_handler( $node, $name );
106              
107             # apply generic element handler
108 0   0       $handled_flag = $self->_apply_user_handler( $node, 'generic_element' )
109             || $handled_flag;
110            
111             # apply generic "else" handler if no element handlers applied
112 0   0       $handled_flag ||=
113             $self->_apply_user_handler( $node, 'generic_element_else' );
114              
115 0   0       return $self->_handle_descendants( $node ) || $handled_flag;
116             }
117              
118              
119             #
120             # default handlers for node types
121             #
122             sub _handle_attribute {
123 0     0     my( $self, $node ) = @_;
124 0           return $self->_apply_user_handler( $node, 'generic_attribute' );
125             }
126              
127             sub _handle_text {
128 0     0     my( $self, $node ) = @_;
129 0           return $self->_apply_user_handler( $node, 'generic_text' );
130             }
131              
132             sub _handle_cdata {
133 0     0     my( $self, $node ) = @_;
134 0           return $self->_apply_user_handler( $node, 'generic_CDATA' );
135             }
136              
137             sub _handle_entity_ref {
138 0     0     my( $self, $node ) = @_;
139 0           return $self->_apply_user_handler( $node, 'generic_entity_ref' );
140             }
141              
142             sub _handle_pi {
143 0     0     my( $self, $node ) = @_;
144 0           return $self->_apply_user_handler( $node, 'generic_PI' );
145             }
146              
147             sub _handle_comment {
148 0     0     my( $self, $node ) = @_;
149 0           return $self->_apply_user_handler( $node, 'generic_comment' );
150             }
151              
152             sub _handle_doc_type {
153 0     0     my( $self, $node ) = @_;
154 0           return $self->_apply_user_handler( $node, 'generic_doctype' );
155             }
156              
157              
158             sub _handle_doc_node {
159             #
160             # process the document node, recurse if necessary
161             #
162 0     0     my( $self, $node ) = @_;
163 0           $self->_apply_user_handler( $node, 'generic_document' );
164 0           $level++;
165 0           $pstack[1] = 1;
166 0           $position = 1;
167 0           my $handled_flag = $self->traverse( $node->getDocumentElement );
168 0           $level--;
169 0           return $handled_flag;
170             }
171              
172              
173             sub _handle_descendants {
174             #
175             # recurse through descendants
176             #
177             # NOTES:
178             # 1. Removing a node that follows the current node is dangerous!
179             # 2. Nodes inserted before or after the current node won't be processed.
180             #
181 0     0     my( $self, $node ) = @_;
182 0           my $handled_flag = 0;
183 0           $level++;
184 0           $pstack[ $level ] = 0;
185 0           foreach my $child ( $node->getChildnodes ) {
186 0           $pstack[ $level ] ++;
187 0           $position = $pstack[ $level ];
188 0           $handled_flag += $self->traverse( $child );
189             }
190 0           $level--;
191 0           return $handled_flag;
192             }
193              
194              
195             sub _apply_user_handler {
196             #
197             # send reference to self and node to a handler method
198             #
199 0     0     my( $self, $node, $handler ) = @_;
200 0           my $handled_flag = 0;
201              
202 0 0 0       if( exists( $self->{ handler_package }) and
203             UNIVERSAL::can( $self->{ handler_package }, $handler )) {
204 0           $self->{ handler_package }->$handler( $self, $node );
205 0           $handled_flag = 1;
206             }
207              
208 0           return $handled_flag;
209             }
210              
211              
212             #
213             # Entity node types
214             #
215             sub XML_ELEMENT_NODE() {1;}
216             sub XML_ATTRIBUTE_NODE() {2;}
217             sub XML_TEXT_NODE() {3;}
218             sub XML_CDATA_SECTION_NODE() {4;}
219             sub XML_ENTITY_REF_NODE() {5;}
220             sub XML_ENTITY_NODE() {6;}
221             sub XML_PI_NODE() {7;}
222             sub XML_COMMENT_NODE() {8;}
223             sub XML_DOCUMENT_NODE() {9;}
224             sub XML_DOCUMENT_TYPE_NODE() {10;}
225             sub XML_DOCUMENT_FRAG_NODE() {11;}
226             sub XML_NOTATION_NODE() {12;}
227             sub XML_HTML_DOCUMENT_NODE() {13;}
228             sub XML_DTD_NODE() {14;}
229             sub XML_ELEMENT_DECL_NODE() {15;}
230             sub XML_ATTRIBUTE_DECL_NODE() {16;}
231             sub XML_ENTITY_DECL_NODE() {17;}
232             sub XML_NAMESPACE_DECL_NODE() {18;}
233             sub XML_XINCLUDE_START() {19;}
234             sub XML_XINCLUDE_END() {20;}
235              
236              
237             1;
238             __END__