File Coverage

blib/lib/TEI/Lite/Document.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             package TEI::Lite::Document;
2              
3             ##==================================================================##
4             ## Libraries and Variables ##
5             ##==================================================================##
6              
7             require 5.006;
8              
9 6     6   4730 use strict;
  6         40  
  6         299  
10 6     6   33 use warnings;
  6         9  
  6         154  
11              
12 6     6   34 use Carp;
  6         11  
  6         615  
13 6     6   2621 use XML::LibXML;
  0            
  0            
14             use TEI::Lite::Element;
15             use I18N::LangTags qw( is_language_tag );
16              
17             our $AUTOLOAD;
18              
19             our $VERSION = "0.60";
20              
21             ##==================================================================##
22             ## Constructor(s)/Deconstructor(s) ##
23             ##==================================================================##
24              
25             ##----------------------------------------------##
26             ## new ##
27             ##----------------------------------------------##
28             sub new
29             {
30             ## Pull in what type of an object we will be.
31             my $type = shift;
32             ## Grab a copy of our parameters.
33             my %params = @_;
34             ## Declare a variable that will later become our object instance.
35             my $self;
36             ## Check to see if a filename is defined, if it is then attempt to load
37             ## it ... otherwise just init a blank object.
38             if( defined( $params{ 'Filename' } ) )
39             {
40             $self = _load_teilite_file( %params );
41             }
42             elsif( defined( $params{ 'String' } ) )
43             {
44             $self = _load_teilite_string( %params );
45             }
46             else
47             {
48             $self = _init_object_instance( %params );
49             }
50             ## Determine what exact class we will be blessing this instance into.
51             my $class = ref( $type ) || $type;
52             ## Bless the class for it is good [tm].
53             bless( $self, $class );
54             ## Send it back to the caller all happy like.
55             return( $self );
56             }
57              
58             ##----------------------------------------------##
59             ## DESTROY ##
60             ##----------------------------------------------##
61             sub DESTROY
62             {
63             ## This is mainly a placeholder to keep things like mod_perl happy.
64             return;
65             }
66              
67             ##==================================================================##
68             ## Method(s) ##
69             ##==================================================================##
70              
71             ##----------------------------------------------##
72             ## addBackMatter ##
73             ##----------------------------------------------##
74             sub addBackMatter
75             {
76             my $self = shift;
77              
78             ## We need to look to see if we are a corpus document.
79             if( $self->{ "Corpus" } != 0 )
80             {
81             croak( "Corpus documents do not contain back matter." );
82             }
83              
84             ## Look to see if a back matter is already defined for this active text.
85             if( !defined( $self->{ "back" }->{ $self->{ "active" } } ) )
86             {
87             ## Create the back matter element.
88             my $back = tei_back();
89              
90             ## Insert the back matter after the body element.
91             $self->{ "text" }->{ $self->{ "active" } }->appendChild( $back );
92              
93             ## Stick a reference into the hash tree.
94             $self->{ "back" }->{ $self->{ "active" } } = $back;
95              
96             return( $back );
97             }
98             else
99             {
100             carp( "The specified text has a pre-existing back element. " .
101             "Only one back element may exist per text. " );
102            
103             return;
104             }
105             }
106              
107             ##----------------------------------------------##
108             ## addCompositeBackMatter ##
109             ##----------------------------------------------##
110             sub addCompositeBackMatter
111             {
112             my $self = shift;
113              
114             ## Do some error checking ...
115             if( ( $self->{ "Corpus" } != 0 ) || ( $self->{ "Composite" } != 0 ) )
116             {
117             croak( "This method only works on TEI composite documents." );
118             }
119              
120             ## Look to see if a back matter is already defined for this active text.
121             if( !defined( $self->{ "back" }->{ "Composite" } ) )
122             {
123             ## Create the back matter element.
124             my $back = tei_back();
125              
126             ## Find the top text node and the last child of that node.
127             my( $node ) = $self->{DOM}->findnodes( '//TEI.2/text' );
128              
129             ## Append the back element onto the text node.
130             $node->appendChild( $back );
131              
132             ## Stick a reference into the hash tree.
133             $self->{ "back" }->{ $self->{ "Composite" } } = $back;
134              
135             return( $back );
136             }
137             else
138             {
139             carp( "The specified text has a pre-existing composite back element. " .
140             "Only one back element may exist per composite document. " );
141            
142             return;
143             }
144             }
145              
146             ##----------------------------------------------##
147             ## addCompositeFrontMatter ##
148             ##----------------------------------------------##
149             sub addCompositeFrontMatter
150             {
151             my $self = shift;
152              
153             ## Do some error checking ...
154             if( ( $self->{ "Corpus" } != 0 ) || ( $self->{ "Composite" } != 0 ) )
155             {
156             croak( "This method only works on TEI composite documents." );
157             }
158              
159             ## Look to see if a back matter is already defined for this active text.
160             if( !defined( $self->{ "front" }->{ "Composite" } ) )
161             {
162             ## Create the back matter element.
163             my $front = tei_front();
164              
165             ## Find the top text node and the first child of that node.
166             my( $node ) = $self->{DOM}->findnodes( '//TEI.2/text' );
167             my $child = $node->firstChild;
168            
169             ## Insert the front element before all the rest of the child nodes.
170             $node->insertBefore( $front, $child );
171              
172             ## Stick a reference into the hash tree.
173             $self->{ "front" }->{ $self->{ "Composite" } } = $front;
174              
175             return( $front );
176             }
177             else
178             {
179             carp( "The specified text has a pre-existing composite " .
180             "front element. Only one back element may exist per " .
181             "composite document. " );
182            
183             return;
184             }
185             }
186              
187             ##----------------------------------------------##
188             ## addDocument ##
189             ##----------------------------------------------##
190             sub addDocument
191             {
192             my $self = shift;
193            
194             ## Do some error checking to ensure that we are operating on a
195             ## corpus document.
196             if( $self->{ "Corpus" } == 0 )
197             {
198             croak( "Can only add additional documents to TEI corpus documents." );
199             }
200            
201             ## Create a new TEI document.
202             $self->{ "document" }->{ $self->{ "Corpus" } } =
203             TEI::Lite::Document->new();
204            
205             ## Add the document to the corpus DOM.
206             $self->{ "DOM" }->documentElement->appendChild(
207             $self->{ "document" }->{ $self->{ "Corpus" } }->documentElement() );
208            
209             ## Increment the corpus document count.
210             $self->{ "Corpus" }++;
211              
212             ## Return the new corpus document count.
213             return( $self->{ "Corpus" } );
214             }
215              
216             ##----------------------------------------------##
217             ## addFrontMatter ##
218             ##----------------------------------------------##
219             sub addFrontMatter
220             {
221             my $self = shift;
222              
223             ## We need to look to see if we are a corpus document.
224             if( $self->{ "Corpus" } != 0 )
225             {
226             croak( "Corpus documents do not contain front matter." );
227             }
228              
229             ## Look to see if a back matter is already defined for this active text.
230             if( !defined( $self->{ "front" }->{ $self->{ "active" } } ) )
231             {
232             ## Create the back matter element.
233             my $front = tei_front();
234              
235             ## Insert the back matter after the body element.
236             $self->{ "text" }->{ $self->{ "active" } }->
237             insertBefore( $front, $self->{ "body" }->{ $self->{ "active" } } );
238              
239             ## Stick a reference into the hash tree.
240             $self->{ "front" }->{ $self->{ "active" } } = $front;
241              
242             return( $front );
243             }
244             else
245             {
246             carp( "The specified text has a pre-existing back element. " .
247             "Only one back element may exist per text. " );
248            
249             return;
250             }
251             }
252              
253             ##----------------------------------------------##
254             ## addHeader ##
255             ##----------------------------------------------##
256             sub addHeader
257             {
258             my $self = shift;
259              
260             ## Determine what type of header we are adding.
261             if( $self->{ "Corpus" } != 0 )
262             {
263             ## Call the default constructor for a TEI::Lite::Header.
264             my $header = TEI::Lite::Header->new( Type => 'Corpus' );
265            
266             ## Stick a reference to this in the document hash for easy
267             ## access later.
268             $self->{ "header" } = $header;
269            
270             ## Find the root element of a document.
271             my $root = shift( @{ $self->{ "DOM" }->find( "teiCorpus.2" ) } );
272            
273             ## We need to find the firstChild of this root element.
274             my $child = $root->firstChild;
275            
276             ## Finally insert into the document before the firstChild.
277             $root->insertBefore( $header, $child );
278              
279             return( $header );
280             }
281             else
282             {
283             ## Call the default constructor for a TEI::Lite::Header.
284             my $header = TEI::Lite::Header->new();
285            
286             ## Stick a reference to this in the document hash for easy
287             ## access later.
288             $self->{ "header" } = $header;
289            
290             ## Find the root element of a document.
291             my $root = shift( @{ $self->{ "DOM" }->find( "TEI.2" ) } );
292            
293             ## We need to find the firstChild of this root element.
294             my $child = $root->firstChild;
295            
296             ## Finally insert into the document before the firstChild.
297             $root->insertBefore( $header, $child );
298            
299             return( $header );
300             }
301             }
302              
303             ##----------------------------------------------##
304             ## addText ##
305             ##----------------------------------------------##
306             sub addText
307             {
308             my $self = shift;
309            
310             if( ( $self->{ "Corpus" } != 0 ) || ( $self->{ "Composite" } == 0 ) )
311             {
312             croak( "Can only add additional texts to a TEI composite document." );
313             }
314            
315             ## Create a new text node for inclusion ...
316             $self->{ "text" }->{ $self->{ "Composite" } } = tei_text();
317            
318             ## Find the group element in the DOM tree.
319             my( $node ) = $self->{ "DOM" }->findnodes( '//TEI.2/text/group' );
320            
321             ## Append the child into the tree.
322             $node->appendChild( $self->{ "text" }->{ $self->{ "Composite" } } );
323            
324             ## Increment the corpus document count.
325             $self->{ "Composite" }++;
326              
327             ## Return the new corpus document count.
328             return( $self->{ "Composite" } );
329             }
330              
331             ##----------------------------------------------##
332             ## AUTOLOAD ##
333             ##----------------------------------------------##
334             sub AUTOLOAD
335             {
336             my $self = shift;
337            
338             ## Pull in AUTOLOAD ...
339             my $function = ( split( /::/, $AUTOLOAD ) )[3];
340            
341             ## Return the AUTOLOAD call on the DOM tree.
342             return( $self->{ "DOM" }->$function( @_ ) );
343             }
344              
345             ##----------------------------------------------##
346             ## getActiveDocument ##
347             ##----------------------------------------------##
348             sub getActiveDocument
349             {
350             my $self = shift;
351              
352             if( $self->{ "Corpus" } == 0 )
353             {
354             croak( "TEI composite and unitary documents do not contain other " .
355             "TEI documents." );
356             }
357              
358             ## Return the active text ...
359             return( $self->{ "active" } );
360             }
361              
362             ##----------------------------------------------##
363             ## getActiveText ##
364             ##----------------------------------------------##
365             sub getActiveText
366             {
367             my $self = shift;
368              
369             if( $self->{ "Corpus" } != 0 )
370             {
371             croak( "TEI corpus documents do not contain texts." );
372             }
373              
374             ## Return the active text ...
375             return( $self->{ "active" } );
376             }
377              
378             ##----------------------------------------------##
379             ## getBackMatter ##
380             ##----------------------------------------------##
381             sub getBackMatter
382             {
383             my $self = shift;
384              
385             if( $self->{ "Corpus" } != 0 )
386             {
387             carp( "TEI corpus documents do not directly contain back matter. " .
388             "Please acccess each individual document contained within " .
389             "the corpus document to get the back matter for that " .
390             "document." );
391             }
392              
393             return( $self->{ "back" }->{ $self->{ "active" } } );
394             }
395              
396             ##----------------------------------------------##
397             ## getBody ##
398             ##----------------------------------------------##
399             sub getBody
400             {
401             my $self = shift;
402              
403             if( $self->{ "Corpus" } != 0 )
404             {
405             carp( "TEI corpus documents do not directly contain body elements. " .
406             "Please acccess each individual document contained within " .
407             "the corpus document to get the body elements for that " .
408             "document." );
409             }
410            
411             return( $self->{ "body" }->{ $self->{ "active" } } );
412             }
413              
414             ##----------------------------------------------##
415             ## getCompositeBackMatter ##
416             ##----------------------------------------------##
417             sub getCompositeBackMatter
418             {
419             my $self = shift;
420              
421             if( $self->{ "Corpus" } != 0 )
422             {
423             carp( "TEI corpus documents do not directly contain back matter. " .
424             "Please acccess each individual document contained within " .
425             "the corpus document to get the back matter for that " .
426             "document." );
427             }
428              
429             return( $self->{ "back" }->{ $self->{ "Composite" } } );
430             }
431              
432             ##----------------------------------------------##
433             ## getCompositeFrontMatter ##
434             ##----------------------------------------------##
435             sub getCompositeFrontMatter
436             {
437             my $self = shift;
438              
439             if( $self->{ "Corpus" } != 0 )
440             {
441             carp( "TEI corpus documents do not directly contain front matter. " .
442             "Please acccess each individual document contained within " .
443             "the corpus document to get the front matter for that " .
444             "document." );
445             }
446              
447             return( $self->{ "front" }->{ $self->{ "Composite" } } );
448             }
449              
450             ##----------------------------------------------##
451             ## getDocument ##
452             ##----------------------------------------------##
453             sub getDocument
454             {
455             my $self = shift;
456              
457             ## We need to do a simple sanity check.
458             if( $self->{ "Corpus" } == 0 )
459             {
460             croak( "TEI corpus documents are the only document type containing " .
461             "other TEI documents. " );
462             }
463            
464             ## Return the document associated with the value in "active".
465             return( $self->{ "document" }->{ $self->{ "active" } } );
466             }
467              
468             ##----------------------------------------------##
469             ## getDocuments ##
470             ##----------------------------------------------##
471             sub getDocuments
472             {
473             my $self = shift;
474              
475             ## We need to do a simple sanity check.
476             if( $self->{ "Corpus" } == 0 )
477             {
478             croak( "TEI corpus documents are the only document type containing " .
479             "other TEI documents. " );
480             }
481            
482             ## Declare a variable to hold our results.
483             my @documents;
484              
485             ## Loop through each of the documents and return a reference to
486             ## that document.
487             foreach( keys( %{ $self->{ "document" } } ) )
488             {
489             push( @documents, $self->{ "document" }->{ $_ } );
490             }
491              
492             ## If we call ourselves in a scalar context, return the
493             ## number of corpus documents.
494             return( wantarray ? @documents : scalar( @documents ) );
495             }
496              
497             ##----------------------------------------------##
498             ## getDocumentLang ##
499             ##----------------------------------------------##
500             sub getDocumentLang
501             {
502             my $self = shift;
503              
504             return( $self->{ "DOM" }->documentElement->getAttribute( "lang" ) );
505             }
506              
507             ##----------------------------------------------##
508             ## getFrontMatter ##
509             ##----------------------------------------------##
510             sub getFrontMatter
511             {
512             my $self = shift;
513            
514             if( $self->{ "Corpus" } != 0 )
515             {
516             carp( "TEI corpus documents do not directly contain front matter. " .
517             "Please acccess each individual document contained within " .
518             "the corpus document to get the front matter for that " .
519             "document." );
520             }
521              
522             return( $self->{ "front" }->{ $self->{ "active" } } );
523             }
524              
525             ##----------------------------------------------##
526             ## getHeader ##
527             ##----------------------------------------------##
528             sub getHeader
529             {
530             my $self = shift;
531              
532             return( $self->{ "header" } );
533             }
534              
535             ##----------------------------------------------##
536             ## getText ##
537             ##----------------------------------------------##
538             sub getText
539             {
540             my $self = shift;
541              
542             ## Do some basic error checking ...
543             if( $self->{ "Corpus" } != 0 )
544             {
545             croak( "TEI composite and unitary documents are the only document " .
546             "types of the TEI specification that contain texts." );
547             }
548            
549             ## Declare a variable to hold our results.
550             my @texts;
551              
552             return( $self->{ "text" }->{ $self->{ "active" } } );
553             }
554              
555             ##----------------------------------------------##
556             ## getTexts ##
557             ##----------------------------------------------##
558             sub getTexts
559             {
560             my $self = shift;
561              
562             ## Do some basic error checking ...
563             if( $self->{ "Corpus" } != 0 )
564             {
565             croak( "TEI composite and unitary documents are the only document " .
566             "types of the TEI specification that contain texts." );
567             }
568            
569             ## Declare a variable to hold our results.
570             my @texts;
571              
572             ## Loop through each of the texts and return a reference to
573             ## that document.
574             foreach( keys( %{ $self->{ "text" } } ) )
575             {
576             push( @texts, $self->{ "text" }->{ $_ } );
577             }
578              
579             ## If we call ourselves in a scalar context, return the
580             ## number of corpus texts.
581             return( wantarray ? @texts : scalar( @texts ) );
582             }
583              
584             ##----------------------------------------------##
585             ## setActiveDocument ##
586             ##----------------------------------------------##
587             sub setActiveDocument
588             {
589             my( $self, $active ) = @_;
590              
591             ## If the passed in $active modifier is not a number,
592             ## then that is obviously an error.
593             if( $active !~ /^\d+$/ )
594             {
595             croak( "The specified active document must be in numeric form." );
596             }
597            
598             ## Corpus texts do not have active documents as they
599             ## are viewed as Document object containing more
600             ## document objects.
601             if( $self->{ "Corpus" } == 0 )
602             {
603             croak( "TEI corpus documents are the only document type containing " .
604             "other TEI documents." );
605             }
606              
607             ## If our $active text is greater then the number of
608             ## texts in our composite document, then that is
609             ## obviously an error.
610             if( $self->{ "Corpus" } < $active )
611             {
612             croak( "The specified active document does not exist in this TEI " .
613             "corpus document." );
614             }
615              
616             ## Set the instance variable ...
617             $self->{ "active" } = $active;
618              
619             return( $self->{ "active" } );
620             }
621              
622             ##----------------------------------------------##
623             ## setActiveText ##
624             ##----------------------------------------------##
625             sub setActiveText
626             {
627             my( $self, $active ) = @_;
628              
629             ## If the passed in $active modifier is not a number,
630             ## then that is obviously an error.
631             if( $active !~ /^\d+$/ )
632             {
633             croak( "The specified active text must be in numeric form." );
634             }
635            
636             ## Corpus texts do not have active documents as they
637             ## are viewed as Document object containing more
638             ## document objects.
639             if( $self->{ "Corpus" } > 0 )
640             {
641             croak( "TEI composite and unitary documents are the only document " .
642             "types containing other texts." );
643             }
644              
645             ## If our $active text is greater then the number of
646             ## texts in our composite document, then that is
647             ## obviously an error.
648             if( $self->{ "Composite" } < $active )
649             {
650             croak( "The specified active text does not exist in this " .
651             "TEI document." );
652             }
653              
654             ## Set the instance variable ...
655             $self->{ "active" } = $active;
656              
657             return( $self->{ "active" } );
658             }
659              
660             ##----------------------------------------------##
661             ## setDocumentLang ##
662             ##----------------------------------------------##
663             sub setDocumentLang
664             {
665             my( $self, $lang ) = @_;
666              
667             if( is_language_tag( $lang ) )
668             {
669             $self->{ "DOM" }->documentElement->setAttribute( "lang", $lang );
670             return( 1 );
671             }
672              
673             return( 0 );
674             }
675              
676             ##==================================================================##
677             ## Internal Function(s) ##
678             ##==================================================================##
679              
680             ##----------------------------------------------##
681             ## _init_object_instance ##
682             ##----------------------------------------------##
683             ## Internal function to initialize the object ##
684             ## instance. ##
685             ##----------------------------------------------##
686             sub _init_object_instance
687             {
688             ## Pull in the parameters ...
689             my %params = @_;
690            
691             ## Create an anonymous hash to hold the basis of our object.
692             my $self = {};
693              
694             ## We also define some variables that we will fill in later.
695             my( $root_node );
696            
697             ## We need to clean up our two main augmentation parameters.
698              
699             ## Clean up the Corpus modifier ...
700             ## Corpus: 0 == false, # > 0 = Number of combined texts
701             if( defined( $params{ "Corpus" } ) )
702             {
703             $params{ "Corpus" } = 0 if( $params{ "Corpus" } < 0 );
704             }
705             else
706             {
707             $params{ "Corpus" } = 0;
708             }
709            
710             ## Stick it in our hash object.
711             $self->{ "Corpus" } = $params{ "Corpus" };
712            
713             ## Clean up the Composite modifier ...
714             ## Composite: 0 == false, # > 0 = Number of group "segments"
715             if( defined( $params{ "Composite" } ) )
716             {
717             $params{ "Composite" } = 0 if( $params{ "Composite" } < 0 );
718             }
719             else
720             {
721             $params{ "Composite" } = 0;
722             }
723            
724             ## Stick it in our hash object.
725             $self->{ "Composite" } = $params{ "Composite" };
726            
727             ## Begin the construction of our internal DOM tree ...
728             $self->{ "DOM" } = XML::LibXML::Document->new( "1.0", "UTF8" );
729            
730             if( $params{ "Corpus" } > 0 )
731             {
732             $root_node = XML::LibXML::Element->new( "teiCorpus.2" );
733             }
734             else
735             {
736             $root_node = XML::LibXML::Element->new( "TEI.2" );
737             }
738              
739             ## Make the $root_node the real root node.
740             $self->{ "DOM" }->setDocumentElement( $root_node );
741              
742             ## Now we need to setup the rest of the basic document based on the
743             ## given parameters.
744             if( $params{ "Corpus" } > 0 )
745             {
746             ## TEI Corpus Document
747             foreach( my $loop = 0; $loop < $params{ "Corpus" }; $loop++ )
748             {
749             $self->{ "document" }->{ $loop } = TEI::Lite::Document->new();
750             $root_node->appendChild(
751             $self->{ "document" }->{ $loop }->documentElement() );
752             }
753              
754             }
755             elsif( $params{ "Composite" } > 0 )
756             {
757             my $text = tei_text();
758             my $group = tei_group();
759              
760             foreach( my $loop = 0; $loop < $params{ "Composite" }; $loop++ )
761             {
762             $self->{ "text" }->{ $loop } = tei_text();
763             $self->{ "body" }->{ $loop } = tei_body();
764             $self->{ "text" }->{ $loop }->
765             appendChild( $self->{ "body" }->{ $loop } );
766             $group->appendChild( $self->{ "text" }->{ $loop } );
767             }
768              
769             $root_node->appendChild( $text );
770             $text->appendChild( $group );
771             }
772             else
773             {
774             ## TEI Unitary Document
775             $self->{ "text" }->{ "0" } = tei_text();
776             $self->{ "body" }->{ "0" } = tei_body();
777             $self->{ "text" }->{ "0" }->appendChild( $self->{ "body" }->{ "0" } );
778             $root_node->appendChild( $self->{ "text" }->{ "0" } );
779             }
780              
781             ## Setup a default text to be active ... as in all operations by
782             ## default act upon this text.
783             $self->{ "active" } = 0;
784            
785             ## Return what we have constructed.
786             return( $self );
787             }
788              
789             ##----------------------------------------------##
790             ## _load_teilite_file ##
791             ##----------------------------------------------##
792             ## Attempts to load a document that is in the ##
793             ## TEILite schema format. ##
794             ##----------------------------------------------##
795             sub _load_teilite_file
796             {
797             my %params = @_;
798            
799             ## We need a variable to hold our instance variable.
800             my $self = {};
801            
802             ## Create an instance of the LibXML parser to load the file.
803             my $parser = XML::LibXML->new();
804              
805             ## Attempt to load the file.
806             my $doc = $parser->parse_file( $params{ 'Filename' } );
807              
808             ## Grab the document element ...
809             my $root = $doc->getDocumentElement();
810              
811             ## Determine whaat type of document we are working with now.
812             if( $root->nodeName eq "teiCorpus.2" )
813             {
814             $self = _parse_teicorpus_document( $doc );
815             }
816             elsif( $root->nodeName eq "TEI.2" )
817             {
818             $self = _parse_tei_document( $doc );
819             }
820             else
821             {
822             croak( "The specified file is not a recognized TEILite document.\n" );
823             }
824            
825             return( $self );
826             }
827              
828             ##----------------------------------------------##
829             ## _load_teilite_string ##
830             ##----------------------------------------------##
831             ## Attempts to load a document that is in the ##
832             ## TEILite schema format. ##
833             ##----------------------------------------------##
834             sub _load_teilite_string
835             {
836             my %params = @_;
837            
838             ## We need a variable to hold our instance variable.
839             my $self = {};
840            
841             ## Create an instance of the LibXML parser to load the file.
842             my $parser = XML::LibXML->new();
843              
844             ## Attempt to load the file.
845             my $doc = $parser->parse_string( $params{ 'String' } );
846              
847             ## Grab the document element ...
848             my $root = $doc->getDocumentElement();
849              
850             ## Determine whaat type of document we are working with now.
851             if( $root->nodeName eq "teiCorpus.2" )
852             {
853             $self = _parse_teicorpus_document( $doc );
854             }
855             elsif( $root->nodeName eq "TEI.2" )
856             {
857             $self = _parse_tei_document( $doc );
858             }
859             else
860             {
861             croak( "The specified file is not a recognized TEILite document.\n" );
862             }
863              
864             return( $self );
865             }
866              
867             ##----------------------------------------------##
868             ## _parse_tei_document ##
869             ##----------------------------------------------##
870             ## Function to break-apart a TEILite document ##
871             ## into the instance variable structure. ##
872             ##----------------------------------------------##
873             sub _parse_tei_document
874             {
875             my $doc = shift;
876              
877             ## We use an anonymous hash as our internal structure.
878             my $self = {};
879            
880             ## Grab the root element of the document.
881             my $root = $doc->getDocumentElement();
882              
883             ## We set the entire DOM tree into the DOM key.
884             $self->{ "DOM" } = $doc;
885            
886             ## We are not a corpus document.
887             $self->{ "Corpus" } = 0;
888              
889             ## We now need to determine if we are a composite or unitary document.
890             my( @texts ) = $root->findnodes( "//text" );
891              
892             ## Loop through each of the texts loading them into our internal struct.
893             for( my $i = 0; $i < scalar( @texts ); $i++ )
894             {
895             ## Set the Composite document counter.
896             $self->{ "Composite" } = $i;
897              
898             ## Set the base "text" element.
899             $self->{ "text" }->{ $i } = $texts[ $i ];
900              
901             ## Grab the children of the text element.
902             my( @children ) = $texts[ $i ]->childNodes;
903              
904             foreach( @children )
905             {
906             if( $_->nodeName eq "front" )
907             {
908             $self->{ "front" }->{ $i } = $_;
909             }
910             elsif( $_->nodeName eq "body" )
911             {
912             $self->{ "body" }->{ $i } = $_;
913             }
914             elsif( $_->nodeName eq "back" )
915             {
916             $self->{ "back" }->{ $i } = $_;
917             }
918             }
919             }
920            
921             return( $self );
922             }
923              
924             ##----------------------------------------------##
925             ## _parse_teicorpus_document ##
926             ##----------------------------------------------##
927             ## Function to break-apart a TEILite document ##
928             ## into the instance variable structure. ##
929             ##----------------------------------------------##
930             sub _parse_teicorpus_document
931             {
932             my $doc = shift;
933              
934             ## We use an anonymous hash as our internal structure.
935             my $self = {};
936            
937             ## We set the entire DOM tree into the DOM key.
938             $self->{ "DOM" } = XML::LibXML::Document->new();
939            
940             my $root = XML::LibXML::Element->new( "teiCorpus.2" );
941            
942             $self->{ "DOM" }->setDocumentElement( $root );
943            
944             ## We are not a composite document.
945             $self->{ "Composite" } = 0;
946              
947             ## We now need to determine if we are a composite or unitary document.
948             my( @texts ) = $doc->getDocumentElement()->findnodes( "//TEI.2" );
949              
950             ## Loop through each of the texts loading them into our internal struct.
951             for( my $i = 0; $i < scalar( @texts ); $i++ )
952             {
953             ## Set the Composite document counter.
954             $self->{ "Corpus" } = $i;
955              
956             ## Set the base "text" element.
957             $self->{ "document" }->{ $i } =
958             TEI::Lite::Document->new( String => $_->toString() );
959              
960             $root->appendChild( $self->{ "document" }->{ $i }->documentElement );
961             }
962              
963             return( $self );
964             }
965              
966             ##==================================================================##
967             ## End of Code ##
968             ##==================================================================##
969             1;
970              
971             ##==================================================================##
972             ## Plain Old Documentation (POD) ##
973             ##==================================================================##
974              
975             __END__