File Coverage

blib/lib/TEI/Lite/Element.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package TEI::Lite::Element;
2              
3             ##==================================================================##
4             ## Libraries and Variables ##
5             ##==================================================================##
6              
7             require 5.006;
8             require Exporter;
9              
10 6     6   3877 use strict;
  6         11  
  6         173  
11 6     6   31 use warnings;
  6         9  
  6         130  
12              
13 6     6   2255 use XML::LibXML;
  0            
  0            
14             use I18N::LangTags qw( is_language_tag );
15              
16             our $VERSION = "0.60";
17              
18             our @EXPORT = qw( %TEI_ELEMENT );
19              
20             our @ISA = qw( Exporter XML::LibXML::Element );
21              
22             ## Global array containing all of the global attributes of TEI Lite elements.
23             our @G_ATTR = qw( ana corresp id lang n next prev rend );
24              
25             ## Global hash that contains all of the TEI Lite elements and their
26             ## associated attributes.
27             our %TEI_ELEMENT = (
28             'abbr' => [ 'type', 'expan' ],
29             'add' => [ 'place' ],
30             'address' => [],
31             'addrLine' => [],
32             'anchor' => [],
33             'argument' => [],
34             'author' => [],
35             'authority' => [],
36             'availability' => [ 'status' ],
37             'back' => [],
38             'bibl' => [],
39             'biblFull' => [],
40             'biblScope' => [],
41             'body' => [],
42             'byline' => [],
43             'catDesc' => [],
44             'category' => [],
45             'catRef' => [ 'target' ],
46             'cell' => [ 'role', 'cols', 'rows' ],
47             'change' => [],
48             'cit' => [],
49             'classCode' => [ 'scheme' ],
50             'classDecl' => [],
51             'closer' => [],
52             'code' => [],
53             'corr' => [ 'sic', 'resp', 'cert' ],
54             'creation' => [],
55             'date' => [ 'calendar', 'value' ],
56             'dateline' => [],
57             'del' => [ 'type', 'status', 'hand' ],
58             'distributer' => [],
59             'div' => [ 'type' ],
60             'div0' => [ 'type' ],
61             'div1' => [ 'type' ],
62             'div2' => [ 'type' ],
63             'div3' => [ 'type' ],
64             'div4' => [ 'type' ],
65             'div5' => [ 'type' ],
66             'div6' => [ 'type' ],
67             'div7' => [ 'type' ],
68             'divGen' => [ 'type' ],
69             'docAuthor' => [],
70             'docDate' => [],
71             'docEdition' => [],
72             'docImprint' => [],
73             'docTitle' => [],
74             'edition' => [],
75             'editionStmt' => [],
76             'editor' => [ 'role' ],
77             'editorialDecl' => [],
78             'eg' => [],
79             'emph' => [],
80             'encodingDesc' => [],
81             'epigraph' => [],
82             'extent' => [],
83             'figDesc' => [],
84             'figure' => [ 'entity', 'url' ],
85             'fileDesc' => [],
86             'foreign' => [],
87             'formula' => [ 'notation' ],
88             'front' => [],
89             'funder' => [],
90             'gap' => [ 'desc', 'resp' ],
91             'gi' => [],
92             'gloss' => [ 'target' ],
93             'group' => [],
94             'head' => [],
95             'hi' => [],
96             'ident' => [],
97             'idno' => [ 'type' ],
98             'imprint' => [],
99             'index' => [ 'level1', 'level2', 'level3',
100             'level4', 'index' ],
101             'interp' => [ 'type', 'value', 'resp', 'inst' ],
102             'interpGrp' => [],
103             'item' => [],
104             'keywords' => [ 'scheme' ],
105             'kw' => [],
106             'l' => [ 'part' ],
107             'label' => [],
108             'langUsage' => [],
109             'lb' => [ 'ed' ],
110             'lg' => [],
111             'list' => [ 'type' ],
112             'listBibl' => [],
113             'mentioned' => [],
114             'milestone' => [ 'ed', 'unit' ],
115             'name' => [ 'type', 'key', 'reg' ],
116             'note' => [ 'type', 'resp', 'place',
117             'target', 'targetEnd', 'anchored' ],
118             'noteStmt' => [],
119             'num' => [ 'type', 'value' ],
120             'opener' => [],
121             'orig' => [ 'reg', 'resp' ],
122             'p' => [ 'type' ],
123             'pb' => [],
124             'principal' => [],
125             'profileDesc' => [],
126             'projectDesc' => [],
127             'ptr' => [ 'type', 'target', 'targType',
128             'crDate', 'resp' ],
129             'publicationStmt' => [],
130             'publisher' => [],
131             'pubPlace' => [],
132             'q' => [ 'type', 'who' ],
133             'ref' => [ 'type', 'target', 'targType',
134             'crDate', 'resp' ],
135             'refsDecl' => [],
136             'reg' => [ 'orig', 'resp' ],
137             'rendition' => [],
138             'resp' => [],
139             'respStmt' => [],
140             'revisionDesc' => [],
141             'row' => [ 'role' ],
142             'rs' => [ 'type', 'key', 'reg' ],
143             's' => [ 'type' ],
144             'salute' => [],
145             'samplingDecl' => [],
146             'seg' => [ 'type' ],
147             'series' => [],
148             'seriesStmt' => [],
149             'sic' => [ 'corr', 'resp', 'cert' ],
150             'signed' => [],
151             'soCalled' => [],
152             'sourceDesc' => [],
153             'sp' => [ 'who' ],
154             'speaker' => [],
155             'sponsor' => [],
156             'stage' => [ 'type' ],
157             'table' => [ 'rows', 'cols' ],
158             'tagsDecl' => [],
159             'tagUsage' => [ 'gi', 'occurs' ],
160             'taxonomy' => [],
161             'teiHeader' => [],
162             'term' => [],
163             'text' => [],
164             'textClass' => [],
165             'time' => [ 'value' ],
166             'title' => [ 'type', 'level' ],
167             'titlePage' => [],
168             'titlePart' => [ 'title' ],
169             'titleStmt' => [],
170             'trailer' => [],
171             'unclear' => [ 'reason', 'resp' ],
172             'xptr' => [ 'target', 'type', 'targType', 'crDate',
173             'resp', 'doc', 'from', 'to', 'url' ],
174             'xref' => [ 'target', 'type', 'targType', 'crDate',
175             'resp', 'doc', 'from', 'to', 'url' ]
176             );
177              
178             no strict "refs";
179              
180             ## Loop through each entry in our element hash and build a
181             ## closure for that element.
182             foreach my $element ( keys( %TEI_ELEMENT ) )
183             {
184             ## Add each of these elements to the default export list.
185             ## I can't use the below function because of the warnings it
186             ## will generate. What good is it?
187             #Exporter::export_tags( "tei_$element" );
188             push( @EXPORT, "tei_$element" );
189            
190             *{ "tei_$element" } = sub {
191             my $attributes = shift;
192             my @children = @_;
193              
194             ## Need to set the type argument so the constructor knows
195             ## what to create.
196             $$attributes{ '__type__' } = $element;
197            
198             ## Call the default constructor
199             my $node = TEI::Lite::Element->new( $attributes, @children );
200            
201             return( $node );
202             }
203             }
204              
205             use strict "refs";
206            
207             ##==================================================================##
208             ## Constructor(s)/Deconstructor(s) ##
209             ##==================================================================##
210              
211             ##----------------------------------------------##
212             ## new ##
213             ##----------------------------------------------##
214             sub new
215             {
216             ## Pull in what type of an object we will be.
217             my $type = shift;
218             ## Pull in the parameters, $attributes should be an array ref
219             ## and the rest of it should be children of the element.
220             my $attributes = shift;
221             my @children = @_;
222             ## We will use an XML::LibXML::Element object as the basis for our object.
223             my $self = XML::LibXML::Element->new( $$attributes{__type__} );
224             ## Determine what exact class we will be blessing this instance into.
225             my $class = ref( $type ) || $type;
226             ## Bless the class for it is good [tm].
227             bless( $self, $class );
228             ## Set the attributes of the element.
229             $self->setAttributes( $attributes );
230             $self->appendChildren( @children );
231             ## Send it back to the caller all happy like.
232             return( $self );
233             }
234              
235             ##----------------------------------------------##
236             ## TIEARRAY ##
237             ##----------------------------------------------##
238             sub TIEARRAY
239             {
240             my( $class, $self ) = @_;
241              
242             bless( $self, $class );
243              
244             return( $self );
245             }
246              
247             ##----------------------------------------------##
248             ## DESTROY ##
249             ##----------------------------------------------##
250             sub DESTROY
251             {
252             ## This is mainly a placeholder to keep things like mod_perl happy.
253             return;
254             }
255              
256             ##----------------------------------------------##
257             ## UNTIE ##
258             ##----------------------------------------------##
259             sub UNTIE
260             {
261             ## This is mainly a placeholder to keep things like mod_perl happy.
262             return;
263             }
264              
265             ##==================================================================##
266             ## Method(s) ##
267             ##==================================================================##
268              
269             ##----------------------------------------------##
270             ## appendChildren ##
271             ##----------------------------------------------##
272             sub appendChildren
273             {
274             my( $self, @children ) = @_;
275              
276             ## Loop through each of the children and determine what type of
277             ## data element they are ...
278             foreach( @children )
279             {
280             if( ( defined( $_ ) ) && ( $_ ne "" ) )
281             {
282             if( ( ref ) && ( $_->isa( "XML::LibXML::Node" ) ) )
283             {
284             ## If it is one of the items above, we should be able to
285             ## safely append it to our DOM tree.
286             $self->appendChild( $_ );
287             }
288             else
289             {
290             ## If it isn't one of the items above, assume that it is
291             ## text data.
292             $self->appendText( $_ );
293             }
294             }
295             }
296              
297             return;
298             }
299              
300             ##----------------------------------------------##
301             ## CLEAR ##
302             ##----------------------------------------------##
303             sub CLEAR
304             {
305             my $self = shift;
306              
307             ## Grab all the nodes of our element ...
308             my @childnodes = $self->childNodes;
309              
310             ## Run through all of the nodes and remove each one.
311             foreach( @childnodes )
312             {
313             $self->removeChild( $_ );
314             }
315              
316             return( $self );
317             }
318              
319             ##----------------------------------------------##
320             ## DELETE ##
321             ##----------------------------------------------##
322             sub DELETE
323             {
324             my( $self, $index ) = @_;
325              
326             ## Grab all of the nodes of our element ...
327             my @childnodes = $self->childNodes;
328              
329             ## Remove the requested node at $index.
330             $self->removeChild( $childnodes[ $index ] );
331              
332             return;
333             }
334              
335             ##----------------------------------------------##
336             ## EXISTS ##
337             ##----------------------------------------------##
338             sub EXISTS
339             {
340             my( $self, $index ) = @_;
341              
342             ## Grab all of the nodes of our element ...
343             my @childnodes = $self->childNodes;
344              
345             ## Check to see if we have a node at the $index.
346             if( defined( $childnodes[ $index ] ) )
347             {
348             return( 1 );
349             }
350             else
351             {
352             return( 0 );
353             }
354             }
355              
356             ##----------------------------------------------##
357             ## EXTEND ##
358             ##----------------------------------------------##
359             sub EXTEND
360             {
361             ## We don't do anything with this in our implementataion.
362             return;
363             }
364              
365             ##----------------------------------------------##
366             ## FETCH ##
367             ##----------------------------------------------##
368             sub FETCH
369             {
370             my( $self, $index ) = @_;
371              
372             ## Grab all of the nodes of our element ...
373             my @childnodes = $self->childNodes;
374              
375             return( $childnodes[ $index ] );
376             }
377              
378             ##----------------------------------------------##
379             ## FETCHSIZE ##
380             ##----------------------------------------------##
381             sub FETCHSIZE
382             {
383             my $self = shift;
384              
385             ## Grab the number of elements attached to our element.
386             my @childnodes = $self->childNodes;
387             my $size = scalar( @childnodes );
388              
389             return( $size );
390             }
391              
392             ##----------------------------------------------##
393             ## POP ##
394             ##----------------------------------------------##
395             sub POP
396             {
397             my $self = shift;
398              
399             ## Remove the last child and return it.
400             return( $self->removeChild( $self->lastChild ) );
401             }
402              
403             ##----------------------------------------------##
404             ## PUSH ##
405             ##----------------------------------------------##
406             sub PUSH
407             {
408             my( $self, @elements ) = @_;
409              
410             ## We will just call our trusty function to do the
411             ## pushing.
412             $self->appendChildren( @elements );
413              
414             return( $self->FETCHSIZE() );
415             }
416              
417             ##----------------------------------------------##
418             ## setAttributes ##
419             ##----------------------------------------------##
420             sub setAttributes
421             {
422             my( $self, $attributes ) = @_;
423              
424             ## Grab the type of element.
425             my $element = $self->nodeName;
426              
427             ## Loop through the global attributes and the element specific
428             ## attributes.
429             foreach( @G_ATTR, @{ $TEI_ELEMENT{ $element } } )
430             {
431             ## If it is defined in our attribute hash, then go ahead and
432             ## set it.
433             if( defined( $$attributes{ $_ } ) )
434             {
435             $self->setAttribute( $_, $$attributes{ $_ } );
436             }
437             }
438              
439             return;
440             }
441              
442             ##----------------------------------------------##
443             ## setLang ##
444             ##----------------------------------------------##
445             sub setLang
446             {
447             my( $self, $lang ) = @_;
448              
449             if( is_language_tag( $lang ) )
450             {
451             $self->setAttribute( "lang", $lang );
452             return( 1 );
453             }
454              
455             return( 0 );
456             }
457              
458             ##----------------------------------------------##
459             ## SHIFT ##
460             ##----------------------------------------------##
461             sub SHIFT
462             {
463             my $self = shift;
464              
465             ## Grab the first element, remove it and then
466             ## send it back to the caller.
467             return( $self->removeChild( $self->firstChild ) );
468             }
469              
470             ##----------------------------------------------##
471             ## STORE ##
472             ##----------------------------------------------##
473             sub STORE
474             {
475             my( $self, $index, $value ) = @_;
476            
477             ## Grab the number of elements attached to our element.
478             my @childnodes = $self->childNodes;
479             my $size = scalar( @childnodes );
480            
481             ## Check to see if our $index is greater then our current size.
482             if( $index >= ( $size - 1 ) )
483             {
484             ## Determine if we need to add "buffer" space to make
485             ## the insertion at the correct index.
486             my $blanknodes = $index - $size;
487              
488             for( my $i = 0; $i < $blanknodes; $i++ )
489             {
490             $self->appendTextNode( " " );
491             }
492            
493             ## We shall call our convience function to determine if
494             ## the data is text or another element.
495             $self->appendChildren( $value );
496             }
497             else
498             {
499             ## Determine what type of node we have and take the
500             ## appropriate function.
501             if( ( defined( $value ) ) && ( $value ne "" ) )
502             {
503             if( ( ref( $value ) ) && ( $value->isa( "XML::LibXML::Node" ) ) )
504             {
505             $childnodes[$index]->replaceNode( $value );
506             }
507             else
508             {
509             my $node = XML::LibXML::Text->new( $value );
510             $childnodes[$index]->replaceNode( $node );
511             }
512             }
513             }
514              
515             return;
516             }
517              
518             ##----------------------------------------------##
519             ## UNSHIFT ##
520             ##----------------------------------------------##
521             sub UNSHIFT
522             {
523             my( $self, @list ) = @_;
524              
525             foreach( @list )
526             {
527             my $first = $self->firstChild;
528            
529             if( $_->isa( "XML::LibXML::Node" ) )
530             {
531             $self->insertBefore( $_, $first );
532             }
533             else
534             {
535             my $node = XML::LibXML::Text->new( $_ );
536             $self->insertBefore( $node, $first );
537             }
538             }
539              
540             return;
541             }
542              
543             ##==================================================================##
544             ## Internal Functions ##
545             ##==================================================================##
546              
547             ##==================================================================##
548             ## End of Code ##
549             ##==================================================================##
550             1;
551              
552             ##==================================================================##
553             ## Plain Old Documentation (POD) ##
554             ##==================================================================##
555              
556             __END__