/[webpac]/trunk2/all2xml.pl
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /trunk2/all2xml.pl

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 32 by dpavlin, Sun Feb 23 07:53:01 2003 UTC revision 182 by dpavlin, Sat Nov 29 15:59:19 2003 UTC
# Line 8  use XML::Simple; Line 8  use XML::Simple;
8  use Text::Unaccent 1.02;        # 1.01 won't compile on my platform,  use Text::Unaccent 1.02;        # 1.01 won't compile on my platform,
9  use Text::Iconv;  use Text::Iconv;
10  use Config::IniFiles;  use Config::IniFiles;
11    use Encode;
12    #use GDBM_File;
13    use Fcntl;      # for O_RDWR
14    use TDB_File;
15    
16  $|=1;  $|=1;
17    
# Line 17  die "FATAL: can't find configuration fil Line 21  die "FATAL: can't find configuration fil
21    
22  my $config;  my $config;
23    
24  use index_DBI;  # there is no other, right now ;-)  #use index_DBI;         # default DBI module for index
25    use index_DBI_cache;    # faster DBI module using memory cache
26  my $index = new index_DBI();    # open index  my $index;
27    
28  my %opts;  my %opts;
29    
# Line 31  my %opts; Line 35  my %opts;
35    
36  getopts('d:m:qs', \%opts);  getopts('d:m:qs', \%opts);
37    
38  my $db_dir;  my $path;       # this is name of database
   
 #die "usage: $0 -d [database_dir] -m [database1,database2] " if (! %opts);  
39    
40  #print Dumper($config->{indexer});  Text::Iconv->raise_error(0);     # Conversion errors don't raise exceptions
 #print "-" x 70,"\n";  
41    
42  Text::Iconv->raise_error(1);     # Conversion errors raise exceptions  # this is encoding of all files on disk, including import_xml/*.xml file and
43    # filter/*.pm files! It will be used to store strings in perl internally!
44    my $codepage = 'ISO-8859-2';
45    
46    my $utf2cp = Text::Iconv->new('UTF-8',$codepage);
47    # this function will convert data from XML files to local encoding
48    sub x {
49            return $utf2cp->convert($_[0]);
50    }
51    
52  my $isis_codepage;  # decode isis/excel or other import codepage
53  my $index_codepage;  my $import2cp;
 my $cludge_codepage = Text::Iconv->new('UTF8','ISO8859-1');  
 my $xml_codepage;  
54    
55  my $XML_CHARSET = 'UTF8';  # outgoing xml must be in UTF-8
56    my $cp2utf = Text::Iconv->new($codepage,'UTF-8');
57    
58    # mapping between data type and tag which specify
59    # format in XML file
60    my %type2tag = (
61            'isis' => 'isis',
62            'excel' => 'column',
63            'marc' => 'marc',
64            'feed' => 'feed'
65    );
66    
67    my $cache;      # for cacheing
68    
69    # lookup hash (tied to file)
70    my %lhash;
71    # this option will cache all lookup entries in memory.
72    # if you are tight on memory, turn this off
73    my $use_lhash_cache = 1;
74    
75  sub isis2xml {  sub data2xml {
76    
77          use xmlify;          use xmlify;
78    
79            my $type = shift @_;
80          my $row = shift @_;          my $row = shift @_;
81          my $add_xml = shift @_;          my $add_xml = shift @_;
82            # needed to read values from configuration file
83            my $cfg = shift @_;
84            my $database = shift @_;
85    
86          my $xml;          my $xml;
87    
# Line 65  sub isis2xml { Line 93  sub isis2xml {
93    
94          # sort subrouting using order="" attribute          # sort subrouting using order="" attribute
95          sub by_order {          sub by_order {
96                  return 0 if (! $config->{indexer}->{$a}->{order});                  my $va = $config->{indexer}->{$a}->{order} ||
97                  return 0 if (! $config->{indexer}->{$b}->{order});                          $config->{indexer}->{$a};
98                    my $vb = $config->{indexer}->{$b}->{order} ||
99                            $config->{indexer}->{$b};
100    
101                  return $config->{indexer}->{$a}->{order} <=>                  return $va <=> $vb;
102                          $config->{indexer}->{$b}->{order} ;          }
103    
104            my @sorted_tags;
105            if ($cache->{tags_by_order}) {
106                    @sorted_tags = @{$cache->{tags_by_order}};
107            } else {
108                    @sorted_tags = sort by_order keys %{$config->{indexer}};
109                    $cache->{tags_by_order} = \@sorted_tags;
110            }
111    
112            # lookup key
113            my $lookup_key;
114    
115            # cache for field in pages
116            delete $cache->{display_data};
117            delete $cache->{swish_data};
118            delete $cache->{swish_exact_data};
119            delete $cache->{index_data};
120            my @page_fields;        # names of fields
121    
122    
123            # subs used to produce output
124    
125            sub get_field_name($$$) {
126                    my ($config,$field,$field_usage) = @_;
127    
128                    # find field name (signular, plural)
129                    my $field_name = "";
130                    if ($config->{indexer}->{$field}->{name_singular} && $field_usage == 1) {
131                            $field_name = $config->{indexer}->{$field}->{name_singular};
132                    } elsif ($config->{indexer}->{$field}->{name_plural}) {
133                            $field_name = $config->{indexer}->{$field}->{name_plural};
134                    } elsif ($config->{indexer}->{$field}->{name}) {
135                            $field_name = $config->{indexer}->{$field}->{name};
136                    } else {
137                            print STDERR "WARNING: field '$field' doesn't have 'name' attribute!";
138                    }
139                    if ($field_name) {
140                            return x($field_name);
141                    }
142          }          }
143    
         foreach my $field (sort by_order keys %{$config->{indexer}}) {  
144    
145            # begin real work: go field by field
146            foreach my $field (@sorted_tags) {
147    
148                    $field=x($field);
149                  $field_usage{$field}++;                  $field_usage{$field}++;
150    
151                  my $swish_data = "";                  my $swish_data = "";
152                    my $swish_exact_data = "";
153                  my $display_data = "";                  my $display_data = "";
154                  my $line_delimiter = "";                  my @index_data;
155                    my $line_delimiter;
156    
157                  foreach my $x (@{$config->{indexer}->{$field}->{isis}}) {                  my ($swish,$display);
158    
159                          my $format = $x->{content};                  my $tag = $type2tag{$type} || die "can't find which tag to use for type $type";
                         my $delimiter = $x->{delimiter} || ' ';  
160    
161                          # FIX: this is ugly, UGLY, cludge string is returned                  # is this field page-by-page?
162                          # in UTF8 encoding , but as if source charset                  my $iterate_by_page = $config->{indexer}->{$field}->{iterate_by_page};
163                          # is ISO8859-1 and not some other. This break other                  push @page_fields,$field if ($iterate_by_page);
164                          # character encodings, so we convert it first                  my %page_max = ();
165                          # back to ISO8859-1                  # default line_delimiter if using
166                          $format = $xml_codepage->convert($format);                  my $page_line_delimiter = $config->{indexer}->{$field}->{page_line_delimiter} || '<br/>';
                         $delimiter = $xml_codepage->convert($delimiter) if ($delimiter);  
167    
168                          my $isis_i = 0;         # isis repeatable offset                  foreach my $x (@{$config->{indexer}->{$field}->{$tag}}) {
169    
170                          my ($s,$d,$i) = (1,1,0);        # swish, display default                          my $format = x($x->{content});
171                            my $delimiter = x($x->{delimiter}) || ' ';
172    
173                            my $repeat_off = 0;     # init repeatable offset
174    
175                            # swish, swish_exact, display, index, index_lookup
176                            # swish and display defaults
177                            my ($s,$se,$d,$i,$il) = (1,0,1,0,0);
178                          $s = 0 if (lc($x->{type}) eq "display");                          $s = 0 if (lc($x->{type}) eq "display");
179                          $d = 0 if (lc($x->{type}) eq "swish");                          $d = 0 if (lc($x->{type}) eq "swish");
180                          ($s,$d,$i) = (0,0,1) if (lc($x->{type}) eq "index");                          ($s,$se,$d,$i) = (0,0,0,1) if (lc($x->{type}) eq "index");
181  #print STDERR "## s: $s d: $d i: $i ## $format ##\n";                            ($s,$se,$d,$i) = (0,1,0,0) if (lc($x->{type}) eq "swish_exact");
182                            ($s,$se,$d,$i,$il) = (0,1,0,0,1) if (lc($x->{type}) =~ /^lookup/);
183    
184                          $display_data .= $line_delimiter if ($display_data && $display_data !~ /$line_delimiter$/);                          # what will separate last line from this one?
185                            if ($display_data && $x->{append}) {
186                                    $line_delimiter = ' ';
187                            } elsif ($display_data) {
188                                    $line_delimiter = '<br/>';
189                            }
190    
191                          my ($swish,$display) = (1,1);                          # init vars so that we go into while...
192                            ($swish,$display) = (1,1);
193    
194                            # placeholder for all repeatable entries for index
195    
196                            sub mkformat {
197                                    my $x = shift || die "mkformat needs tag reference";
198                                    my $data = shift || return;
199                                    my $format_name = x($x->{format_name}) || return $data;
200                                    my $fmt = x($config->{format}->{$format_name}->{content}) || die "<format name=\"$format_name\"> is not defined!";
201                                    my $format_delimiter = x($x->{format_delimiter});
202                                    my @data;
203                                    if ($format_delimiter) {
204                                            @data = split(/$format_delimiter/,$data);
205                                    } else {
206                                            push @data,$data;
207                                    }
208    
209                                    if ($fmt) {
210                                            my $nr = scalar $fmt =~ s/%s/%s/g;
211                                            if (($#data+1) == $nr) {
212                                                    return sprintf($fmt,@data);
213                                            } else {
214                                                    print STDERR "mkformat: [$data] can't be split on [$format_delimiter] to $nr fields!\n";
215                                                    return $data;
216                                            }
217                                    } else {
218                                            print STDERR "usage of link '$format_name' without defined format (<link> tag)\n";
219                                    }
220                            }
221    
222                            # while because of repeatable fields
223                          while ($swish || $display) {                          while ($swish || $display) {
224                                  ($swish,$display) = parse_format($format,$row,$isis_i++);                                  my $page = $repeat_off;
225  #print STDERR "s: $swish\nd: $display\n" if ($swish);                                  $page_max{$field} = $page if ($iterate_by_page && $page > ($page_max{$field} || 0));
226                                    ($swish,$display) = parse_format($type, $format,$row,$repeat_off++,$import2cp);
227                                    if ($repeat_off > 1000) {
228                                            print STDERR "loop (more than 1000 repeatable fields) deteced in $row, $format\n";
229                                            last;
230                                    }
231    
232  #print STDERR "swish: $swish<-- display: $display<--\n";                                  # is this field is lookup?
233                                    if ($display && $x->{lookup}) {
234                                            my $null = "<!-- null -->";
235                                            if ($use_lhash_cache) {
236                                                    if (!defined($cache->{lhash}->{$display})) {
237                                                            my $new_display = $lhash{$display};
238                                                            if (defined($new_display)) {
239    #print STDERR "lookup cache store '$display' = '$new_display'\n";
240                                                                    $display = $new_display;
241                                                                    $cache->{lhash}->{$display} = $new_display;
242                                                            } else {
243                                                                    print STDERR "WARNING: lookup for '$display' didn't find anything.\n";
244                                                                    $display = "";
245                                                                    $cache->{lhash}->{$display} = $null;
246                                                            }
247                                                    } else {
248                                                            $display = $cache->{lhash}->{$display};
249                                                    }
250                                            } else {
251                                                    $display = $lhash{$display} || $null;
252                                            }
253                                    }
254    
255                                  # filter="name" ; filter this field through                                  # filter="name" ; filter this field through
256                                  # filter/[name].pm                                  # filter/[name].pm
257                                  my $filter = $x->{filter};                                  my $filter = $x->{filter};
258                                  if ($filter) {                                  if ($filter && !$cache->{filter_loaded}->{$filter}) {
259                                          require "filter/".$filter.".pm";                                          require "filter/".$filter.".pm";
260                                            $cache->{filter_loaded}->{$filter}++;
261                                  }                                  }
262                                  # type="swish" ; field for swish                                  # type="swish" ; field for swish
263                                  if ($s && $swish) {                                  if ($swish) {
264                                          if ($filter) {                                          if ($filter && ($s || $se)) {
 #print STDERR "using filter '$filter'\n";  
265                                                  no strict 'refs';                                                  no strict 'refs';
266                                                  $swish_data .= join(" ",&$filter($swish));                                                  my $tmp = join(" ",&$filter($swish)) if ($s || $se);
267                                                    $swish_data .= $tmp if ($s);
268                                                    $swish_exact_data .= $tmp if ($se);
269    
270                                          } else {                                          } else {
271                                                  $swish_data .= $swish;                                                  $swish_data .= $swish if ($s);
272                                                    $swish_exact_data .= $swish if ($se);
273                                          }                                          }
274                                  }                                  }
275    
276                                  # type="display" ; field for display                                  # type="display" ; field for display
277                                  if ($d && $display) {                                  if ($d && $display) {
278                                            if ($line_delimiter && $display_data) {
279                                                    $display_data .= $line_delimiter;
280                                            }
281                                          if ($filter) {                                          if ($filter) {
282                                                  no strict 'refs';                                                  no strict 'refs';
283                                                  $display_data .= join($delimiter,&$filter($display));                                                  if ($display_data) {
284                                                            $display_data .= $delimiter.join($delimiter,mkformat($x,&$filter($display)));
285                                                    } else {
286                                                            $display_data = join($delimiter,mkformat($x,&$filter($display)));
287                                                    }
288                                          } else {                                          } else {
289                                                  if ($display_data) {                                                  if ($display_data) {
290                                                          $display_data .= $delimiter.$display;                                                          $display_data .= $delimiter.mkformat($x,$display);
291                                                  } else {                                                  } else {
292                                                          $display_data .= $display;                                                          $display_data = mkformat($x,$display);
293                                                  }                                                  }
294                                          }                                          }
295                                  }                                  }
296                                                                                                    
297                                  # type="index" ; insert into index                                  # type="index" ; insert into index
298                                    my $idisplay;
299                                  if ($i && $display) {                                  if ($i && $display) {
300                                          my $index_data = $index_codepage->convert($display) || $display;                                          $idisplay = $display;
301                                          if ($filter) {                                          if ($filter) {
302                                                  no strict 'refs';                                                  no strict 'refs';
303                                                  foreach my $d (&$filter($index_data)) {                                                  $idisplay = &$filter($idisplay);
304                                                          $index->insert($field, $d, $db_dir);                                          }
305                                            push @index_data, $idisplay if (! $iterate_by_page);
306                                    }
307    
308                                    # store fields in lookup
309                                    if ($il && $display) {
310                                            if (lc($x->{type}) eq "lookup_key") {
311                                                    if ($lookup_key) {
312                                                            print STDERR "WARNING: try to redefine lookup_key (keys shouldn't be repeatable fields!)";
313                                                    } else {
314                                                            $lookup_key = $display;
315                                                    }
316                                            } elsif (lc($x->{type}) eq "lookup_val") {
317                                                    if ($lookup_key) {
318                                                            $lhash{$lookup_key} = $display;
319                                                    } else {
320                                                            print STDERR "WARNING: no lookup_key defined for  '$display'?";
321                                                  }                                                  }
322                                          } else {                                          }
323                                                  $index->insert($field, $index_data, $db_dir);  
324                                    }
325    
326                                    # store data for page-by-page repeatable fields
327                                    if ($iterate_by_page) {
328                                            sub iterate_fld($$$$$$) {
329                                                    my ($cache,$what,$field,$page,$data,$append) = @_;
330                                                    return if (!$data);
331    
332                                                    my $ldel = $page_line_delimiter;
333                                                    $ldel = " " if ($append);
334    #print STDERR "line delimiter: ",Dumper($ldel) if ($ldel);
335                                                    if (! $cache->{$what}->{$field}->[$page]) {
336                                                            $cache->{$what}->{$field}->[$page] = $data;
337                                                    } else {
338                                                            $cache->{$what}->{$field}->[$page] .= $ldel.$data;
339                                                    }
340                                            }
341    
342                                            if ($display_data) {
343                                                    iterate_fld($cache,'display_data',$field,$page,$display_data,$x->{append});
344                                            }
345                                                    $display_data = "";
346                                            if ($swish_data) {
347                                                    iterate_fld($cache,'swish_data',$field,$page,$swish_data,$x->{append});
348                                                    $swish_data = "";
349                                            }
350                                            if ($swish_exact_data) {
351                                                    iterate_fld($cache,'swish_exact_data',$field,$page,$swish_exact_data,$x->{append});
352                                                    $swish_exact_data = "";
353                                            }
354    
355                                            if ($idisplay) {
356                                                    my $ldel=$page_line_delimiter;
357                                                    my @index_data;
358                                                    if ($cache->{index_data}->{$field}->[$page]) {
359    
360                                                            @index_data = @{$cache->{index_data}->{$field}->[$page]};
361                                                    }
362                                                    if ($x->{append}) {
363                                                            $index_data[$#index_data] .= $idisplay;
364                                                    } else {
365                                                            push @index_data, $idisplay;
366                                                    }
367                                                    $idisplay = "";
368                                                    @{$cache->{index_data}->{$field}->[$page]} = @index_data;
369                                          }                                          }
370                                  }                                  }
371                          }                          }
372                          if ($x->{append}) {  
373                                  $line_delimiter = ' ';                          if (! $iterate_by_page) {
374                          } else {                                  # fill data in index
375                                  $line_delimiter = '<br/>';                                  foreach my $d (@index_data) {
376                                            $index->insert($field, $d, $path);
377                                    }
378                                    @index_data = ();
379                          }                          }
380                  }                  }
381    
382                    # now try to parse variables from configuration file
383                    foreach my $x (@{$config->{indexer}->{$field}->{'config'}}) {
384    
385                            my $delimiter = x($x->{delimiter}) || ' ';
386                            my $val = $cfg->val($database, x($x->{content}));
387    
388  #print STDERR "s_d: $swish_data\nd_d: $display_data\n" if ($swish_data);                          my ($s,$d,$i) = (1,1,0);        # swish, display default
389                  if ($display_data) {                          $s = 0 if (lc($x->{type}) eq "display");
390                            $d = 0 if (lc($x->{type}) eq "swish");
391                            # no support for swish exact in config.
392                            # IMHO, it's useless
393                            ($s,$d,$i) = (0,0,1) if (lc($x->{type}) eq "index");
394    
395                          # remove last <br>                          if ($val) {
396                          $display_data =~ s/$line_delimiter$//;                                  $display_data .= $delimiter.$val if ($d);
397                                    $swish_data .= $val if ($s);
398                                    $index->insert($field, $val, $path) if ($i);
399                            }
400    
401                          $display_data = $isis_codepage->convert($display_data) || die "Can't convert '$display_data' !";                          if ($iterate_by_page) {
402                          # FIX: this is removed and replaced by html tag.                                  # FIXME data from config tag will appear just
403                          #$xml .= xmlify($field."_display", $display_data);                                  # on first page!!!
404                                    my $page = 0;
405                          if ($field eq "headline") {                                  if ($display_data) {
406                                  $xml .= xmlify("headline", $display_data);                                          $cache->{display_data}->{$field}->[$page] = $display_data;
407                          } else {                                          $display_data = "";
   
                                 # find field name (signular, plural)  
                                 my $field_name = "";  
                                 if ($config->{indexer}->{$field}->{name_singular} && $field_usage{$field} == 1) {  
                                         $field_name = $config->{indexer}->{$field}->{name_singular}."#-#";  
                                 } elsif ($config->{indexer}->{$field}->{name_plural}) {  
                                         $field_name = $config->{indexer}->{$field}->{name_plural}."#-#";  
                                 } elsif ($config->{indexer}->{$field}->{name}) {  
                                         $field_name = $config->{indexer}->{$field}->{name}."#-#";  
                                 } else {  
                                         print STDERR "WARNING: field '$field' doesn't have 'name' attribute!";  
408                                  }                                  }
409                                  if ($field_name) {                                  if ($swish_data) {
410                                          $html .= $xml_codepage->convert($field_name);                                          $cache->{swish_data}->{$field}->[$page] = $swish_data;
411  #                                       $html .= "-->".$field_name."<--";                                          $swish_data = "";
412                                    }
413                                    if ($swish_exact_data) {
414                                            $cache->{swish_exact_data}->{$field}->[$page] = $swish_exact_data;
415                                            $swish_exact_data = "";
416                                  }                                  }
                                 $html .= $display_data."###\n";  
417                          }                          }
418                  }                  }
                 if ($swish_data) {  
                         my $i = Text::Iconv->new($config->{isis_codepage},'ISO8859-2');  
                         # remove extra spaces  
                         $swish_data =~ s/ +/ /g;  
                         $swish_data =~ s/ +$//g;  
419    
420                          $swish_data = $i->convert($swish_data);                  # save data page-by-page
421                          $xml .= xmlify($field."_swish",unac_string('ISO8859-2',$swish_data));                  foreach my $field (@page_fields) {
422                          #$swish_data = $isis_codepage->convert($swish_data)."##" || $swish_data;                          my $nr_pages = $page_max{$field} || next;
423                          #$xml .= xmlify($field."_swish",unac_string($config->{isis_codepage},$swish_data));  #print STDERR "field '$field' iterate over ",($nr_pages || 0)," pages...\n";
424    #print STDERR Dumper($cache->{display_data});
425                            for (my $page=0; $page <= $nr_pages; $page++) {
426    
427                                    my $display_data = $cache->{display_data}->{$field}->[$page];
428                                    if ($display_data) { # default
429                                            if ($field eq "headline") {
430                                                    $xml .= xmlify("headline", $display_data);
431                                            } else {
432    
433                                                    # fallback to empty field name if needed
434                                                    $html .= get_field_name($config,$field,$field_usage{$field}) || '';
435                                                    $html .= "#-#".$display_data."###\n";
436                                            }
437                                    }
438                                    
439                                    my $swish_data = $cache->{swish_data}->{$field}->[$page];
440                                    if ($swish_data) {
441                                            # remove extra spaces
442                                            $swish_data =~ s/ +/ /g;
443                                            $swish_data =~ s/ +$//g;
444    
445                                            $xml .= xmlify($field."_swish", unac_string($codepage,$swish_data));
446                                    }
447    
448                                    my $swish_exact_data = $cache->{swish_exact_data}->{$field}->[$page];
449                                    if ($swish_exact_data) {
450                                            $swish_exact_data =~ s/ +/ /g;
451                                            $swish_exact_data =~ s/ +$//g;
452    
453                                            # add delimiters before and after word.
454                                            # That is required to produce exact match
455                                            $xml .= xmlify($field."_swish_exact", unac_string($codepage,'xxbxx '.$swish_exact_data.' xxexx'));
456                                    }
457                                    
458                                    foreach my $d (@{$cache->{index_data}->{$field}->[$page]}) {
459                                            $index->insert($field, $d, $path);
460    #print STDERR "index $field: $d [$path]\n";
461                                    }
462                            }
463            
464                  }                  }
465                    
466                    if (! $iterate_by_page) {
467                            if ($display_data) {
468                                    if ($field eq "headline") {
469                                            $xml .= xmlify("headline", $display_data);
470                                    } else {
471    
472                                            # fallback to empty field name if needed
473                                            $html .= get_field_name($config,$field,$field_usage{$field}) || '';
474                                            $html .= "#-#".$display_data."###\n";
475                                    }
476                            }
477                            if ($swish_data) {
478                                    # remove extra spaces
479                                    $swish_data =~ s/ +/ /g;
480                                    $swish_data =~ s/ +$//g;
481    
482                                    $xml .= xmlify($field."_swish", unac_string($codepage,$swish_data));
483                            }
484    
485                            if ($swish_exact_data) {
486                                    $swish_exact_data =~ s/ +/ /g;
487                                    $swish_exact_data =~ s/ +$//g;
488    
489                                    # add delimiters before and after word.
490                                    # That is required to produce exact match
491                                    $xml .= xmlify($field."_swish_exact", unac_string($codepage,'xxbxx '.$swish_exact_data.' xxexx'));
492                            }
493                    }
494          }          }
495    
496          # dump formatted output in <html>          # dump formatted output in <html>
497          if ($html) {          if ($html) {
498                  $xml .= xmlify("html",$html);                  #$xml .= xmlify("html",$html);
499                    $xml .= "<html><![CDATA[ $html ]]></html>";
500          }          }
501                    
502          if ($xml) {          if ($xml) {
 #print STDERR "x: $xml\n";  
503                  $xml .= $add_xml if ($add_xml);                  $xml .= $add_xml if ($add_xml);
504                  return "<xml>\n$xml</xml>\n";                  return "<xml>\n$xml</xml>\n";
505          } else {          } else {
# Line 226  sub isis2xml { Line 509  sub isis2xml {
509    
510  ##########################################################################  ##########################################################################
511    
512    # read configuration for this script
513  my $cfg = new Config::IniFiles( -file => $config_file );  my $cfg = new Config::IniFiles( -file => $config_file );
514    
515    # read global.conf configuration
516    my $cfg_global = new Config::IniFiles( -file => 'global.conf' );
517    
518    # open index
519    $index = new index_DBI(
520                    $cfg_global->val('global', 'dbi_dbd'),
521                    $cfg_global->val('global', 'dbi_dsn'),
522                    $cfg_global->val('global', 'dbi_user'),
523                    $cfg_global->val('global', 'dbi_passwd') || '',
524            );
525    
526    my $show_progress = $cfg_global->val('global', 'show_progress');
527    
528    my $unac_filter = $cfg_global->val('global', 'unac_filter');
529    if ($unac_filter) {
530            require $unac_filter;
531    }
532    
533  foreach my $database ($cfg->Sections) {  foreach my $database ($cfg->Sections) {
534    
535          my $isis_db = $cfg -> val($database, 'isis_db');          my $type = lc($cfg -> val($database, 'type')) || die "$database doesn't have 'type' defined";
536          my $type = $cfg -> val($database, 'type');          my $add_xml = $cfg -> val($database, 'xml');    # optional
         my $add_xml = $cfg -> val($database, 'xml');  
537    
538          # read configuration for this type          # create new lookup file
539          $config=XMLin("./import_xml/$type.xml", forcearray => [ 'isis' ], forcecontent => 1);          my $lookup_file = $cfg -> val($database, 'lookup_newfile'); # optional
540          $isis_codepage = Text::Iconv->new($config->{isis_codepage},$XML_CHARSET);          if ($lookup_file) {
541          $index_codepage = Text::Iconv->new($config->{isis_codepage},$config->{index_codepage});                  #tie %lhash, 'GDBM_File', $lookup_file, &GDBM_NEWDB, 0644;
542          $xml_codepage = Text::Iconv->new($cfg->val($database,'xml_codepage'),$XML_CHARSET);                  tie %lhash, 'TDB_File', $lookup_file, TDB_CLEAR_IF_FIRST, O_RDWR, 0644;
543                    print STDERR "creating lookup file '$lookup_file'\n";
544            }
545    
546          my $db = OpenIsis::open( $isis_db );          # open existing lookup file
547          if (0) {          $lookup_file = $cfg -> val($database, 'lookup_open'); # optional
548  #       # FIX          if ($lookup_file) {
549  #       if (! $db ) {                  #tie %lhash, 'GDBM_File', $lookup_file, &GDBM_READER, 0644;
550                  print STDERR "WARNING: can't open '$isis_db'\n";                  tie %lhash, 'TDB_File', $lookup_file, TDB_DEFAULT, O_RDWR, 0644;
551                  next ;                  print STDERR "opening lookup file '$lookup_file'\n";
552          }          }
553    
554          my $max_rowid = OpenIsis::maxRowid( $db );  print STDERR "reading ./import_xml/$type.xml\n";
555    
556          print STDERR "Reading database: $isis_db [$max_rowid rows]\n";          # extract just type basic
557            my $type_base = $type;
558            $type_base =~ s/_.+$//g;
559    
560          my $path = $database;                   # was $isis_db          $config=XMLin("./import_xml/$type.xml", forcearray => [ $type2tag{$type_base}, 'config', 'format' ], forcecontent => 1);
561    
562            # output current progress indicator
563          my $last_p = 0;          my $last_p = 0;
564            sub progress {
565                    return if (! $show_progress);
566                    my $current = shift;
567                    my $total = shift || 1;
568                    my $p = int($current * 100 / $total);
569                    if ($p != $last_p) {
570                            printf STDERR ("%5d / %5d [%-51s] %-2d %% \r",$current,$total,"=" x ($p/2).">", $p );
571                            $last_p = $p;
572                    }
573            }
574    
575            my $fake_dir = 1;
576            sub fakeprogress {
577                    return if (! $show_progress);
578                    my $current = shift @_;
579    
580                    my @ind = ('-','\\','|','/','-','\\','|','/', '-');
581    
582                    $last_p += $fake_dir;
583                    $fake_dir = -$fake_dir if ($last_p > 1000 || $last_p < 0);
584                    if ($last_p % 10 == 0) {
585                            printf STDERR ("%5d / %5s [%-51s]\r",$current,"?"," " x ($last_p/20).$ind[($last_p/20) % $#ind]);
586                    }
587            }
588    
589            # now read database
590    print STDERR "using: $type...\n";
591    
592            # erase cache for tags by order in this database
593            delete $cache->{tags_by_order};
594    
595            if ($type_base eq "isis") {
596    
597                    my $isis_db = $cfg -> val($database, 'isis_db') || die "$database doesn't have 'isis_db' defined!";
598    
599                    $import2cp = Text::Iconv->new($config->{isis_codepage},$codepage);
600                    my $db = OpenIsis::open( $isis_db );
601    
602                    # check if .txt database for OpenIsis is zero length,
603                    # if so, erase it and re-open database
604                    sub check_txt_db {
605                            my $isis_db = shift || die "need isis database name";
606                            my $reopen = 0;
607    
608                            if (-e $isis_db.".TXT") {
609                                    print STDERR "WARNING: removing $isis_db.TXT OpenIsis database...\n";
610                                    unlink $isis_db.".TXT" || warn "FATAL: unlink error on '$isis_db.TXT': $!";
611                                    $reopen++;
612                            }
613                            if (-e $isis_db.".PTR") {
614                                    print STDERR "WARNING: removing $isis_db.PTR OpenIsis database...\n";
615                                    unlink $isis_db.".PTR" || warn "FATAL: unlink error on '$isis_db.PTR': $!";
616                                    $reopen++;
617                            }
618                            return OpenIsis::open( $isis_db ) if ($reopen);
619                    }
620    
621                    # EOF error
622                    if ($db == -1) {
623                            $db = check_txt_db($isis_db);
624                            if ($db == -1) {
625                                    print STDERR "FATAL: OpenIsis can't open zero size file $isis_db\n";
626                                    next;
627                            }
628                    }
629    
630                    # OpenIsis::ERR_BADF
631                    if ($db == -4) {
632                            print STDERR "FATAL: OpenIsis can't find file $isis_db\n";
633                            next;
634                    # OpenIsis::ERR_IO
635                    } elsif ($db == -5) {
636                            print STDERR "FATAL: OpenIsis can't access file $isis_db\n";
637                            next;
638                    } elsif ($db < 0) {
639                            print STDERR "FATAL: OpenIsis unknown error $db with file $isis_db\n";
640                            next;
641                    }
642    
643                    my $max_rowid = OpenIsis::maxRowid( $db );
644    
645                    # if 0 records, try to rease isis .txt database
646                    if ($max_rowid == 0) {
647                            # force removal of database
648                            $db = check_txt_db($isis_db);
649                            $max_rowid = OpenIsis::maxRowid( $db );
650                    }
651    
652                    print STDERR "Reading database: $isis_db [$max_rowid rows]\n";
653    
654                    my $path = $database;
655    
656  #       { my $row_id = 4514;                  for (my $row_id = 1; $row_id <= $max_rowid; $row_id++ ) {
657  # FIX                          my $row = OpenIsis::read( $db, $row_id );
658          for (my $row_id = 1; $row_id <= $max_rowid; $row_id++ ) {                          if ($row && $row->{mfn}) {
659                  my $row = OpenIsis::read( $db, $row_id );          
660                  if ($row && $row->{mfn}) {                                  progress($row->{mfn}, $max_rowid);
661  #print STDERR "mfn: ",$row->{mfn},"\n";  
662                          # output current process indicator                                  my $swishpath = $path."#".int($row->{mfn});
663                          my $p = int($row->{mfn} * 100 / $max_rowid);  
664                          if ($p != $last_p) {                                  if (my $xml = data2xml($type_base,$row,$add_xml,$cfg,$database)) {
665                                  printf STDERR ("%5d / %5d [%-51s] %-2d %% \r",$row->{mfn},$max_rowid,"=" x ($p/2).">", $p ) if (! $opts{q});                                          $xml = $cp2utf->convert($xml);
666                                  $last_p = $p;                                          use bytes;      # as opposed to chars
667                          }                                          print "Path-Name: $swishpath\n";
668                                            print "Content-Length: ".(length($xml)+1)."\n";
669                          if (my $xml = isis2xml($row,$add_xml)) {                                          print "Document-Type: XML\n\n$xml\n";
670  #print STDERR "--ret-->$xml\n";                                  }
671                                  print "Path-Name: $path#".int($row->{mfn})."\n";                          }
672                    }
673                    # for this to work with current version of OpenIsis (0.9.0)
674                    # you might need my patch from
675                    # http://www.rot13.org/~dpavlin/projects/openisis-0.9.0-perl_close.diff
676                    OpenIsis::close($db);
677                    print STDERR "\n";
678    
679            } elsif ($type_base eq "excel") {
680                    use Spreadsheet::ParseExcel;
681                    use Spreadsheet::ParseExcel::Utility qw(int2col);
682                    
683                    $import2cp = Text::Iconv->new($config->{excel_codepage},$codepage);
684                    my $excel_file = $cfg -> val($database, 'excel_file') || die "$database doesn't have 'excel_file' defined!";
685    
686                    my $sheet = x($config->{sheet}) || die "no sheet in $type.xml";
687                    my $start_row = x($config->{start_row}) - 1 || die "no start_row in $type.xml";
688    
689                    my $oBook = Spreadsheet::ParseExcel::Workbook->Parse($excel_file) || die "can't open Excel file '$excel_file'";
690    
691                    my $sheet_nr = 0;
692                    foreach my $oWks (@{$oBook->{Worksheet}}) {
693                            #print STDERR "-- SHEET $sheet_nr:", $oWks->{Name}, "\n";
694                            last if ($oWks->{Name} eq $sheet);
695                            $sheet_nr++;
696                    }
697    
698                    my $oWorksheet = $oBook->{Worksheet}[$sheet_nr];
699            
700                    print STDERR "using sheet: ",$oWorksheet->{Name},"\n";
701                    defined ($oWorksheet) || die "can't find sheet '$sheet' in $excel_file";
702                    my $end_row = x($config->{end_row}) || $oWorksheet->{MaxRow};
703    
704                    for(my $iR = $start_row ; defined $end_row && $iR <= $end_row ; $iR++) {
705                            my $row;
706                            for(my $iC = $oWorksheet->{MinCol} ; defined $oWorksheet->{MaxCol} && $iC <= $oWorksheet->{MaxCol} ; $iC++) {
707                                    my $cell = $oWorksheet->{Cells}[$iR][$iC];
708                                    if ($cell) {
709                                            $row->{int2col($iC)} = $cell->Value;
710                                    }
711                            }
712    
713                            progress($iR, $end_row);
714    
715    #                       print "row[$iR/$end_row] ";
716    #                       foreach (keys %{$row}) {
717    #                               print "$_: ",$row->{$_},"\t";
718    #                       }
719    #                       print "\n";
720    
721                            my $swishpath = $database."#".$iR;
722    
723                            next if (! $row);
724    
725                            if (my $xml = data2xml($type_base,$row,$add_xml,$cfg,$database)) {
726                                    $xml = $cp2utf->convert($xml);
727                                    use bytes;      # as opposed to chars
728                                    print "Path-Name: $swishpath\n";
729                                  print "Content-Length: ".(length($xml)+1)."\n";                                  print "Content-Length: ".(length($xml)+1)."\n";
730                                  print "Document-Type: XML\n\n$xml\n";                                  print "Document-Type: XML\n\n$xml\n";
731                          }                          }
732                  }                  }
733            } elsif ($type_base eq "marc") {
734    
735                    use MARC;
736                    
737                    $import2cp = Text::Iconv->new($config->{marc_codepage},$codepage);
738                    my $marc_file = $cfg -> val($database, 'marc_file') || die "$database doesn't have 'marc_file' defined!";
739    
740                    # optional argument is format
741                    my $format = x($config->{format}) || 'usmarc';
742    
743                    print STDERR "Reading MARC file '$marc_file'\n";
744    
745                    my $marc = new MARC;
746                    my $nr = $marc->openmarc({
747                                    file=>$marc_file, format=>$format
748                            }) || die "Can't open MARC file '$marc_file'";
749    
750                    my $i=0;        # record nr.
751    
752                    my $rec;
753    
754                    while ($marc->nextmarc(1)) {
755    
756                            # XXX
757                            fakeprogress($i++);
758    
759                            my $swishpath = $database."#".$i;
760    
761                            if (my $xml = data2xml($type_base,$marc,$add_xml,$cfg,$database)) {
762                                    $xml = $cp2utf->convert($xml);
763                                    use bytes;      # as opposed to chars
764                                    print "Path-Name: $swishpath\n";
765                                    print "Content-Length: ".(length($xml)+1)."\n";
766                                    print "Document-Type: XML\n\n$xml\n";
767                            }
768                    }
769            } elsif ($type_base eq "feed") {
770    
771                    $import2cp = Text::Iconv->new($config->{feed_codepage},$codepage);
772                    my $prog = x($config->{prog}) || die "$database doesn't have 'prog' defined!";
773    
774                    print STDERR "Reading feed from program '$prog'\n";
775    
776                    open(FEED,"feeds/$prog |") || die "can't start $prog: $!";
777    
778                    my $i=1;        # record nr.
779    
780                    my $data;
781                    my $line=1;
782    
783                    while (<FEED>) {
784                            chomp;
785    
786                            if (/^$/) {
787                                    my $swishpath = $database."#".$i++;
788    
789                                    if (my $xml = data2xml($type_base,$data,$add_xml,$cfg,$database)) {
790                                            $xml = $cp2utf->convert($xml);
791                                            use bytes;      # as opposed to chars
792                                            print "Path-Name: $swishpath\n";
793                                            print "Content-Length: ".(length($xml)+1)."\n";
794                                            print "Document-Type: XML\n\n$xml\n";
795                                    }
796                                    $line = 1;
797                                    $data = {};
798                                    next;
799                            }
800    
801                            $line = $1 if (s/^(\d+):\s*//);
802                            $data->{$line++} = $_;
803    
804                            fakeprogress($i);
805    
806                    }
807                    # close lookup
808                    untie %lhash if (%lhash);
809          }          }
         print STDERR "\n";  
810  }  }
811    
812  # call this to commit index  # call this to commit index
# Line 289  __END__ Line 818  __END__
818    
819  =head1 NAME  =head1 NAME
820    
821  isis2xml.pl - read isis file and dump XML  all2xml.pl - read various file formats and dump XML for SWISH-E
822    
823  =head1 DESCRIPTION  =head1 DESCRIPTION
824    
825  This command will read ISIS data file using OpenIsis perl module and  This command will read ISIS data file using OpenIsis perl module, MARC
826  create XML file for usage with I<SWISH-E>  records using MARC module and optionally Micro$oft Excel files to
827  indexer. Dispite it's name, this script B<isn't general xml generator>  create one XML file for usage with I<SWISH-E> indexer. Dispite it's name,
828  from isis files (isis allready has something like that). Output of this  this script B<isn't general xml generator> from isis files (isis allready
829  script is tailor-made for SWISH-E.  has something like that). Output of this script is tailor-made for SWISH-E.
830    
831    =head1 BUGS
832    
833    Documentation is really lacking. However, in true Open Source spirit, source
834    is best documentation. I even made considerable effort to comment parts
835    which are not intuitively clear, so...
836    
837  =head1 AUTHOR  =head1 AUTHOR
838    

Legend:
Removed from v.32  
changed lines
  Added in v.182

  ViewVC Help
Powered by ViewVC 1.1.26