source: main/trunk/greenstone2/perllib/plugins/LOMPlugin.pm@ 31492

Last change on this file since 31492 was 31492, checked in by kjdon, 7 years ago

renamed EncodingUtil to CommonUtil, BasePlugin to BaseImporter. The idea is that only top level plugins that you can specify in your collection get to have plugin in their name. Modified all other plugins to reflect these name changes

  • Property svn:keywords set to Author Date Id Revision
File size: 20.0 KB
Line 
1###########################################################################
2#
3# LOMPlugin.pm -- plugin for import the collection from LOM
4#
5# A component of the Greenstone digital library software
6# from the New Zealand Digital Library Project at the
7# University of Waikato, New Zealand.
8#
9# Copyright (C) 2005 New Zealand Digital Library Project
10#
11# This program is free software; you can redistribute it and/or modify
12# it under the terms of the GNU General Public License as published by
13# the Free Software Foundation; either version 2 of the License, or
14# (at your option) any later version.
15#
16# This program is distributed in the hope that it will be useful,
17# but WITHOUT ANY WARRANTY; without even the implied warranty of
18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19# GNU General Public License for more details.
20#
21# You should have received a copy of the GNU General Public License
22# along with this program; if not, write to the Free Software
23# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24#
25###########################################################################
26
27### Note this plugin currently can't download source documents from outside if you are behind a firewall.
28# Unless, you set the http_proxy environment variable to be your proxy server,
29# and set proxy_user and proxy_password in .wgetrc file in home directory.
30# (does that work on windows??)
31
32package LOMPlugin;
33
34use extrametautil;
35use ReadTextFile;
36use MetadataPass;
37use MetadataRead;
38use util;
39use FileUtils;
40use XMLParser;
41use Cwd;
42
43# methods with identical signatures take precedence in the order given in the ISA list.
44sub BEGIN {
45 @ISA = ('MetadataRead', 'ReadTextFile', 'MetadataPass');
46}
47
48use strict; # every perl program should have this!
49no strict 'refs'; # make an exception so we can use variables as filehandles
50
51
52my $arguments =
53 [ { 'name' => "process_exp",
54 'desc' => "{BaseImporter.process_exp}",
55 'type' => "string",
56 'deft' => &get_default_process_exp(),
57 'reqd' => "no" },
58 { 'name' => "root_tag",
59 'desc' => "{LOMPlugin.root_tag}",
60 'type' => "regexp",
61 'deft' => q/^(?i)lom$/,
62 'reqd' => "no" },
63 { 'name' => "check_timestamp",
64 'desc' => "{LOMPlugin.check_timestamp}",
65 'type' => "flag" },
66 { 'name' => "download_srcdocs",
67 'desc' => "{LOMPlugin.download_srcdocs}",
68 'type' => "regexp",
69 'deft' => "",
70 'reqd' => "no" }];
71
72my $options = { 'name' => "LOMPlugin",
73 'desc' => "{LOMPlugin.desc}",
74 'abstract' => "no",
75 'inherits' => "yes",
76 'args' => $arguments };
77
78
79
80my ($self);
81sub new {
82 my $class = shift (@_);
83 my ($pluginlist,$inputargs,$hashArgOptLists) = @_;
84 push(@$pluginlist, $class);
85
86 push(@{$hashArgOptLists->{"ArgList"}},@{$arguments});
87 push(@{$hashArgOptLists->{"OptList"}},$options);
88
89 $self = new ReadTextFile($pluginlist, $inputargs, $hashArgOptLists);
90
91 if ($self->{'info_only'}) {
92 # don't worry about creating the XML parser as all we want is the
93 # list of plugin options
94 return bless $self, $class;
95 }
96
97 #create XML::Parser object for parsing dublin_core.xml files
98 my $parser = new XML::Parser('Style' => 'Stream',
99 'Handlers' => {'Char' => \&Char,
100 'Doctype' => \&Doctype
101 });
102 $self->{'parser'} = $parser;
103
104 $self->{'extra_blocks'} = {};
105
106 return bless $self, $class;
107}
108
109sub get_default_process_exp {
110 my $self = shift (@_);
111
112 return q^(?i)\.xml$^;
113}
114
115
116sub can_process_this_file {
117 my $self = shift(@_);
118 my ($filename) = @_;
119
120 if ($self->SUPER::can_process_this_file($filename) && $self->check_doctype($filename)) {
121 return 1; # its a file for us
122 }
123 return 0;
124}
125
126sub metadata_read {
127 my $self = shift (@_);
128 my ($pluginfo, $base_dir, $file, $block_hash,
129 $extrametakeys, $extrametadata, $extrametafile,
130 $processor, $gli, $aux) = @_;
131
132 my $outhandle = $self->{'outhandle'};
133
134 # can we process this file??
135 my ($filename_full_path, $filename_no_path) = &util::get_full_filenames($base_dir, $file);
136 return undef unless $self->can_process_this_file_for_metadata($filename_full_path);
137
138 $file =~ s/^[\/\\]+//; # $file often begins with / so we'll tidy it up
139
140 print $outhandle "LOMPlugin: extracting metadata from $file\n"
141 if $self->{'verbosity'} > 1;
142
143 my ($dir,$tail) = $filename_full_path =~ /^(.*?)([^\/\\]*)$/;
144 $self->{'output_dir'} = $dir;
145
146 eval {
147 $self->{'parser'}->parsefile($filename_full_path);
148 };
149
150 if ($@) {
151 print $outhandle "LOMPlugin: skipping $filename_full_path as not conformant to LOM syntax\n" if ($self->{'verbosity'} > 1);
152 print $outhandle "\n Perl Error:\n $@\n" if ($self->{'verbosity'}>2);
153 return 0;
154 }
155
156 $self->{'output_dir'} = undef;
157
158 my $file_re;
159 my $lom_srcdoc = $self->{'lom_srcdoc'};
160
161 if (defined $lom_srcdoc) {
162 my $dirsep = &util::get_re_dirsep();
163 $lom_srcdoc =~ s/^$base_dir($dirsep)//;
164 $self->{'extra_blocks'}->{$file}++;
165 $file_re = $lom_srcdoc;
166 }
167 else {
168 $file_re = $tail;
169 }
170
171 # Indexing into the extrameta data structures requires the filename's style of slashes to be in URL format
172 # Then need to convert the filename to a regex, no longer to protect windows directory chars \, but for
173 # protecting special characters like brackets in the filepath such as "C:\Program Files (x86)\Greenstone".
174 $file_re = &util::filepath_to_url_format($file_re);
175 $file_re = &util::filename_to_regex($file_re);
176 $self->{'lom_srcdoc'} = undef; # reset for next file to be processed
177
178 &extrametautil::addmetakey($extrametakeys, $file_re);
179 &extrametautil::setmetadata($extrametadata, $file_re, $self->{'saved_metadata'});
180 if (defined $lom_srcdoc) {
181 # copied from oaiplugin
182 if (!defined &extrametautil::getmetafile($extrametafile, $file_re)) {
183 &extrametautil::setmetafile($extrametafile, $file_re, {});
184 }
185 #maps the file to full path
186 &extrametautil::setmetafile_for_named_file($extrametafile, $file_re, $file, $filename_full_path);
187 }
188
189 return 1;
190}
191
192sub check_doctype {
193 $self = shift (@_);
194
195 my ($filename) = @_;
196
197 if (open(XMLIN,"<$filename")) {
198 my $doctype = $self->{'root_tag'};
199 ## check whether the doctype has the same name as the root element tag
200 while (defined (my $line = <XMLIN>)) {
201 ## find the root element
202 if ($line =~ /<([\w\d:]+)[\s>]/){
203 my $root = $1;
204 if ($root !~ $doctype){
205 close(XMLIN);
206 return 0;
207 }
208 else {
209 close(XMLIN);
210 return 1;
211 }
212 }
213 }
214 close(XMLIN);
215 }
216
217 return undef; # haven't found a valid line
218
219}
220
221sub read_file {
222 my $self = shift (@_);
223 my ($filename, $encoding, $language, $textref) = @_;
224
225 my $metadata_table = $self->{'metadata_table'};
226
227 my $rawtext = $metadata_table->{'rawtext'};
228
229 delete $metadata_table->{'rawtext'};
230
231 $$textref = $rawtext;
232}
233
234sub read {
235 my $self = shift (@_);
236 my ($pluginfo, $base_dir, $file, $block_hash, $metadata, $processor, $maxdocs, $total_count, $gli) = @_;
237
238 my $outhandle = $self->{'outhandle'};
239
240 return 0 if (defined $self->{'extra_blocks'}->{$file});
241
242 # can we process this file??
243 my ($filename_full_path, $filename_no_path) = &util::get_full_filenames($base_dir, $file);
244 return undef unless $self->can_process_this_file($filename_full_path);
245
246 $self->{'metadata_table'} = $metadata;
247
248 my $lom_language = $metadata->{'lom_language'};
249
250 my $store_input_encoding;
251 my $store_extract_language;
252 my $store_default_language;
253 my $store_default_encoding;
254
255 if (defined $lom_language) {
256 delete $metadata->{'lom_language'};
257
258 $store_input_encoding = $self->{'input_encoding'};
259 $store_extract_language = $self->{'extract_language'};
260 $store_default_language = $self->{'default_language'};
261 $store_default_encoding = $self->{'default_encoding'};
262
263 $self->{'input_encoding'} = "utf8";
264 $self->{'extract_language'} = 0;
265 $self->{'default_language'} = $lom_language;
266 $self->{'default_encoding'} = "utf8";
267 }
268
269 my $rv = $self->SUPER::read(@_);
270
271 if (defined $lom_language) {
272 $self->{'input_encoding'} = $store_input_encoding;
273 $self->{'extract_language'} = $store_extract_language;
274 $self->{'default_language'} = $store_default_language;
275 $self->{'default_encoding'} = $store_default_encoding;
276 }
277
278 $self->{'metadata_table'} = undef;
279
280 return $rv;
281}
282
283# do plugin specific processing of doc_obj
284sub process {
285 my $self = shift (@_);
286 my ($textref, $pluginfo, $base_dir, $file, $metadata, $doc_obj, $gli) = @_;
287 my $outhandle = $self->{'outhandle'};
288
289 my $cursection = $doc_obj->get_top_section();
290 $doc_obj->add_utf8_text($cursection, $$textref);
291
292 return 1;
293}
294
295sub Doctype {
296 my ($expat, $name, $sysid, $pubid, $internal) = @_;
297
298 my $root_tag = $self->{'root_tag'};
299
300 if ($name !~ /$root_tag/) {
301 die "Root tag $name does not match regular expression $root_tag";
302 }
303}
304
305sub StartTag {
306 my ($expat, $element) = @_;
307
308 my %attr = %_;
309
310 my $raw_tag = "&lt;$element";
311 map { $raw_tag .= " $_=\"$attr{$_}\""; } keys %attr;
312 $raw_tag .= "&gt;";
313
314 if ($element =~ m/$self->{'root_tag'}/) {
315 $self->{'raw_text'} = $raw_tag;
316
317 $self->{'saved_metadata'} = {};
318 $self->{'metaname_stack'} = [];
319 $self->{'lom_datatype'} = "";
320 $self->{'lom_language'} = undef;
321 $self->{'metadatatext'} = "<table class=\"metadata\" width=\"_pagewidth_\" >\n";
322 }
323 else {
324 my $xml_depth = scalar(@{$self->{'metaname_stack'}});
325 $self->{'raw_text'} .= "\n";
326 $self->{'raw_text'} .= "&nbsp;&nbsp;" x $xml_depth;
327 $self->{'raw_text'} .= $raw_tag;
328
329 my $metaname_stack = $self->{'metaname_stack'};
330 push(@$metaname_stack,$element);
331 if (scalar(@$metaname_stack)==1) {
332 # top level LOM category
333 my $style = "class=\"metadata\"";
334 my $open_close
335 = "<a id=\"${element}opencloselink\" href=\"javascript:hideTBodyArea('$element')\">\n";
336 $open_close
337 .= "<img id=\"${element}openclose\" border=\"0\" src=\"_httpopenmdicon_\"></a>\n";
338
339 my $header_line = " <tr $style ><th $style colspan=\"3\">$open_close \u$element</th></tr>\n";
340 my $md_tbody = "<tbody id=\"$element\">\n";
341
342 $self->{'mdheader'} = $header_line;
343 $self->{'mdtbody'} = $md_tbody;
344 $self->{'mdtbody_text'} = "";
345 }
346 }
347}
348
349sub EndTag {
350 my ($expat, $element) = @_;
351
352 my $raw_tag = "&lt;/$element&gt;";
353
354 if ($element =~ m/$self->{'root_tag'}/) {
355 $self->{'raw_text'} .= $raw_tag;
356
357 my $metadatatext = $self->{'metadatatext'};
358 $metadatatext .= "</table>";
359
360 my $raw_text = $self->{'raw_text'};
361
362 $self->{'saved_metadata'}->{'MetadataTable'} = $metadatatext;
363 $self->{'metadatatext'} = "";
364
365 $self->{'saved_metadata'}->{'rawtext'} = $raw_text;
366 $self->{'raw_text'} = "";
367
368 if (defined $self->{'lom_language'}) {
369 $self->{'saved_metadata'}->{'lom_language'} = $self->{'lom_language'};
370 $self->{'lom_language'} = undef;
371 }
372 }
373 else {
374 my $metaname_stack = $self->{'metaname_stack'};
375
376 if (scalar(@$metaname_stack)==1) {
377 my $header_line = $self->{'mdheader'};
378 my $tbody_start = $self->{'mdtbody'};
379 my $tbody_text = $self->{'mdtbody_text'};
380 if ($tbody_text !~ m/^\s*$/s) {
381 my $tbody_end = "</tbody>\n";
382 my $table_chunk
383 = $header_line.$tbody_start.$tbody_text.$tbody_end;
384
385 $self->{'metadatatext'} .= $table_chunk;
386 }
387 $self->{'mdtheader'} = "";
388 $self->{'mdtbody'} = "";
389 $self->{'mdtbody_text'} = "";
390 }
391
392 pop(@$metaname_stack);
393
394 my $xml_depth = scalar(@{$self->{'metaname_stack'}});
395 $self->{'raw_text'} .= "\n";
396 $self->{'raw_text'} .= "&nbsp;&nbsp;" x $xml_depth;
397 $self->{'raw_text'} .= $raw_tag;
398 }
399}
400
401sub process_datatype_info
402{
403 my $self = shift(@_);
404 my ($metaname_stack,$md_content) = @_;
405
406 my @without_dt_stack = @$metaname_stack; # without datatype stack
407
408 my $innermost_element = $without_dt_stack[$#without_dt_stack];
409
410 # Loose last item if encoding datatype information
411 if ($innermost_element =~ m/^(lang)?string$/) {
412 $self->{'lom_datatype'} = $innermost_element;
413
414 pop @without_dt_stack;
415 $innermost_element = $without_dt_stack[$#without_dt_stack];
416 }
417 elsif ($innermost_element =~ m/^date(Time)?$/i) {
418 if ($innermost_element =~ m/^date$/i) {
419 $self->{'lom_datatype'} = "dateTime";
420 }
421 else {
422 $self->{'lom_datatype'} = $innermost_element;
423
424 pop @without_dt_stack;
425 $innermost_element = $without_dt_stack[$#without_dt_stack];
426 }
427
428 if ($md_content =~ m/^(\d{1,2})\s*(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\w*\s*(\d{4})/i) {
429 my ($day,$mon,$year) = ($1,$2,$3);
430
431 my %month_lookup = ( 'jan' => 1, 'feb' => 2, 'mar' => 3,
432 'apr' => 4, 'may' => 5, 'jun' => 6,
433 'jul' => 7, 'aug' => 8, 'sep' => 9,
434 'oct' => 10, 'nov' => 11, 'dec' => 12 );
435
436 my $mon_num = $month_lookup{lc($mon)};
437
438 $md_content = sprintf("%d%02d%02d",$year,$mon_num,$day);
439 }
440
441 $md_content =~ s/\-//g;
442 }
443
444 if ($innermost_element eq "source") {
445 $self->{'lom_source'} = $md_content;
446 }
447 elsif ($innermost_element eq "value") {
448 $self->{'lom_value'} = $md_content;
449 }
450
451 return (\@without_dt_stack,$innermost_element,$md_content);
452}
453
454sub reset_datatype_info
455{
456 my $self = shift(@_);
457
458 $self->{'lom_datatype'} = "";
459}
460
461
462sub pretty_print_text
463{
464 my $self = shift(@_);
465
466 my ($pretty_print_text) = @_;
467
468## $metavalue_utf8 = &util::hyperlink_text($metavalue_utf8);
469 $pretty_print_text = &util::hyperlink_text($pretty_print_text);
470
471#### $pretty_print_text =~ s/(BEGIN:vCard.*END:vCard)/<pre>$1<\/pre>/sg;
472
473 if ($self->{'lom_datatype'} eq "dateTime") {
474 if ($pretty_print_text =~ m/^(\d{4})(\d{2})(\d{2})$/) {
475 $pretty_print_text = "$1-$2-$3";
476 }
477 }
478
479 return $pretty_print_text;
480}
481
482sub pretty_print_table_tr
483{
484 my $self = shift (@_);
485 my ($without_dt_stack) = @_;
486
487 my $style = "class=\"metadata\"";
488
489 my $innermost_element = $without_dt_stack->[scalar(@$without_dt_stack)-1];
490 my $outermost_element = $without_dt_stack->[0];
491
492 # Loose top level stack item (already named in pretty print table)
493 my @pretty_print_stack = @$without_dt_stack;
494 shift @pretty_print_stack;
495
496 if ($innermost_element eq "source") {
497 return if (!defined $self->{'lom_value'});
498 }
499
500 if ($innermost_element eq "value") {
501 return if (!defined $self->{'lom_source'});
502 }
503
504 my $pretty_print_text = "";
505
506 if (($innermost_element eq "value") || ($innermost_element eq "source")) {
507 my $source = $self->{'lom_source'};
508 my $value = $self->pretty_print_text($self->{'lom_value'});
509
510 $self->{'lom_source'} = undef;
511 $self->{'lom_value'} = undef;
512
513 pop @pretty_print_stack;
514
515 $pretty_print_text = "<td $style>$source</td><td $style>$value</td>";
516 }
517 else {
518 $pretty_print_text = $self->pretty_print_text($_);
519 $pretty_print_text = "<td $style colspan=2>$pretty_print_text</td>";
520 }
521 my $pretty_print_fmn = join(' : ',map { "\u$_"; } @pretty_print_stack);
522
523
524 # my $tr_attr = "id=\"$outermost_element\" style=\"display:block;\"";
525 my $tr_attr = "$style id=\"$outermost_element\"";
526
527 my $mdtext_line = " <tr $tr_attr><td $style><nobr>$pretty_print_fmn</nobr></td>$pretty_print_text</tr>\n";
528 $self->{'mdtbody_text'} .= $mdtext_line;
529}
530
531
532sub check_for_language
533{
534 my $self = shift(@_);
535 my ($innermost_element,$md_content) = @_;
536
537 # Look for 'language' tag
538 if ($innermost_element eq "language") {
539 my $lom_lang = $self->{'lom_language'};
540
541 if (defined $lom_lang) {
542 my $new_lom_lang = $md_content;
543 $new_lom_lang =~ s/-.*//; # remove endings like -US or -GB
544
545 if ($lom_lang ne $new_lom_lang) {
546 my $outhandle = $self->{'outhandle'};
547
548 print $outhandle "Warning: Conflicting general language in record\n";
549 print $outhandle " $new_lom_lang (previous value for language = $lom_lang)\n";
550 }
551 # otherwise, existing value OK => do nothing
552 }
553 else {
554 $lom_lang = $md_content;
555 $lom_lang =~ s/-.*//; # remove endings like -US or -GB
556
557 $self->{'lom_language'} = $lom_lang;
558 }
559 }
560}
561
562sub found_specific_identifier
563{
564 my $self = shift(@_);
565 my ($specific_id,$full_mname,$md_content) = @_;
566
567 my $found_id = 0;
568 if ($full_mname eq $specific_id) {
569 if ($md_content =~ m/^(http|ftp):/) {
570 $found_id = 1;
571 }
572 }
573
574 return $found_id;
575}
576
577sub download_srcdoc
578{
579 my $self = shift(@_);
580 my ($doc_url) = @_;
581
582 my $outhandle = $self->{'outhandle'};
583 my $output_dir = $self->{'output_dir'};
584
585 $output_dir = &FileUtils::filenameConcatenate($output_dir,"_gsdldown.all");
586
587 if (! -d $output_dir) {
588 mkdir $output_dir;
589 }
590
591 my $re_dirsep = &util::get_re_dirsep();
592 my $os_dirsep = &util::get_dirsep();
593
594 my $file_url = $doc_url;
595 $file_url =~ s/$re_dirsep/$os_dirsep/g;
596 $file_url =~ s/^(http|ftp):\/\///;
597 $file_url .= "index.html" if ($file_url =~ m/\/$/);
598
599 my $full_file_url = &FileUtils::filenameConcatenate($output_dir,$file_url);
600 # the path to srcdoc will be used later in extrametadata to associate
601 # the lom metadata with the document. Needs to be relative to current
602 # directory.
603 my $srcdoc_path = &FileUtils::filenameConcatenate("_gsdldown.all", $file_url);
604 my $check_timestamp = $self->{'check_timestamp'};
605 my $status;
606
607 if (($check_timestamp) || (!$check_timestamp && !-e $full_file_url)) {
608 if (!-e $full_file_url) {
609 print $outhandle "Mirroring $doc_url\n";
610 }
611 else {
612 print $outhandle "Checking to see if update needed for $doc_url\n";
613 }
614
615 # on linux, if we pass an absolute path as -P arg to wget, then it
616 # stuffs up the
617 # URL rewriting in the file. Need a relative path or none, so now
618 # we change working directory first.
619 my $changed_dir = 0;
620 my $current_dir = cwd();
621 my $wget_cmd = "";
622 if ($ENV{'GSDLOS'} ne "windows") {
623 $changed_dir = 1;
624
625 chdir "$output_dir";
626 $wget_cmd = "wget -nv --timestamping -k -p \"$doc_url\"";
627 } else {
628 $wget_cmd = "wget -nv -P \"$output_dir\" --timestamping -k -p \"$doc_url\"";
629 }
630 ##print STDERR "**** wget = $wget_cmd\n";
631
632 # the wget binary is dependent on the gnomelib_env (particularly lib/libiconv2.dylib) being set, particularly on Mac Lions (android too?)
633 &util::set_gnomelib_env(); # this will set the gnomelib env once for each subshell launched, by first checking if GEXTGNOME is not already set
634
635 $status = system($wget_cmd);
636 if ($changed_dir) {
637 chdir $current_dir;
638 }
639 if ($status==0) {
640 $self->{'lom_srcdoc'} = $srcdoc_path;
641 }
642 else {
643 $self->{'lom_srcdoc'} = undef;
644 print $outhandle "Error: failed to execute $wget_cmd\n";
645 }
646 }
647 else {
648 # not time-stamping and file already exists
649 $status=0;
650 $self->{'lom_srcdoc'} = $srcdoc_path;
651 }
652
653 return $status==0;
654
655}
656
657
658sub check_for_identifier
659{
660 my $self = shift(@_);
661 my ($full_mname,$md_content) = @_;
662
663 my $success = 0;
664
665 my $download_re = $self->{'download_srcdocs'};
666 if (($download_re ne "") && $md_content =~ m/$download_re/) {
667
668 if ($self->found_specific_identifier("general^identifier^entry",$full_mname,$md_content)) {
669 $success = $self->download_srcdoc($md_content);
670 }
671
672 if (!$success) {
673 if ($self->found_specific_identifier("technical^location",$full_mname,$md_content)) {
674 $success = $self->download_srcdoc($md_content);
675 }
676 }
677 }
678
679 return $success;
680}
681
682
683sub Text {
684 if ($_ !~ m/^\s*$/) {
685 #
686 # Work out indentations and line wraps for raw XML
687 #
688 my $xml_depth = scalar(@{$self->{'metaname_stack'}})+1;
689 my $indent = "&nbsp;&nbsp;" x $xml_depth;
690
691 my $formatted_text = "\n".$_;
692
693 # break into lines < 80 chars on space
694 $formatted_text =~ s/(.{50,80})\s+/$1\n/mg;
695 $formatted_text =~ s/^/$indent/mg;
696 ## $formatted_text =~ s/\s+$//s;
697
698 $self->{'raw_text'} .= $formatted_text;
699 }
700
701 my $metaname_stack = $self->{'metaname_stack'};
702 if (($_ !~ /^\s*$/) && (scalar(@$metaname_stack)>0)) {
703
704 my ($without_dt_stack,$innermost_element,$md_content)
705 = $self->process_datatype_info($metaname_stack,$_);
706
707 $self->pretty_print_table_tr($without_dt_stack);
708
709 my $full_mname = join('^',@{$without_dt_stack});
710 $self->set_filere_metadata(lc($full_mname),$md_content);
711
712 $self->check_for_language($innermost_element,$md_content);
713 $self->check_for_identifier($full_mname,$md_content); # source doc
714
715 $self->reset_datatype_info();
716 }
717}
718
719# This Char function overrides the one in XML::Parser::Stream to overcome a
720# problem where $expat->{Text} is treated as the return value, slowing
721# things down significantly in some cases.
722sub Char {
723 $_[0]->{'Text'} .= $_[1];
724 return undef;
725}
726
7271;
Note: See TracBrowser for help on using the repository browser.