/[webpac]/trunk/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 /trunk/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 90 by dpavlin, Sun Jul 13 13:22:50 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    
13  $|=1;  $|=1;
14    
# Line 17  die "FATAL: can't find configuration fil Line 18  die "FATAL: can't find configuration fil
18    
19  my $config;  my $config;
20    
21  use index_DBI;  # there is no other, right now ;-)  #use index_DBI;         # default DBI module for index
22    use index_DBI_cache;    # faster DBI module using memory cache
23  my $index = new index_DBI();    # open index  my $index;
24    
25  my %opts;  my %opts;
26    
# Line 31  my %opts; Line 32  my %opts;
32    
33  getopts('d:m:qs', \%opts);  getopts('d:m:qs', \%opts);
34    
35  my $db_dir;  my $path;       # this is name of database
   
 #die "usage: $0 -d [database_dir] -m [database1,database2] " if (! %opts);  
36    
37  #print Dumper($config->{indexer});  Text::Iconv->raise_error(0);     # Conversion errors don't raise exceptions
 #print "-" x 70,"\n";  
38    
39  Text::Iconv->raise_error(1);     # Conversion errors raise exceptions  # this is encoding of all files on disk, including import_xml/*.xml file and
40    # filter/*.pm files! It will be used to store strings in perl internally!
41    my $codepage = 'ISO-8859-2';
42    
43    my $utf2cp = Text::Iconv->new('UTF-8',$codepage);
44    # this function will convert data from XML files to local encoding
45    sub x {
46            return $utf2cp->convert($_[0]);
47    }
48    
49  my $isis_codepage;  # decode isis/excel or other import codepage
50  my $index_codepage;  my $import2cp;
 my $cludge_codepage = Text::Iconv->new('UTF8','ISO8859-1');  
 my $xml_codepage;  
51    
52  my $XML_CHARSET = 'UTF8';  # outgoing xml must be in UTF-8
53    my $cp2utf = Text::Iconv->new($codepage,'UTF-8');
54    
55    # mapping between data type and tag which specify
56    # format in XML file
57    my %type2tag = (
58            'isis' => 'isis',
59            'excel' => 'column',
60            'marc' => 'marc',
61            'feed' => 'feed'
62    );
63    
64  sub isis2xml {  sub data2xml {
65    
66          use xmlify;          use xmlify;
67    
68            my $type = shift @_;
69          my $row = shift @_;          my $row = shift @_;
70          my $add_xml = shift @_;          my $add_xml = shift @_;
71            # needed to read values from configuration file
72            my $cfg = shift @_;
73            my $database = shift @_;
74    
75          my $xml;          my $xml;
76    
# Line 74  sub isis2xml { Line 91  sub isis2xml {
91    
92          foreach my $field (sort by_order keys %{$config->{indexer}}) {          foreach my $field (sort by_order keys %{$config->{indexer}}) {
93    
94                    $field=x($field);
95    
96                  $field_usage{$field}++;                  $field_usage{$field}++;
97    
98                  my $swish_data = "";                  my $swish_data = "";
99                  my $display_data = "";                  my $display_data = "";
100                  my $line_delimiter = "";                  my $line_delimiter;
101    
102                  foreach my $x (@{$config->{indexer}->{$field}->{isis}}) {                  my ($swish,$display);
103    
104                          my $format = $x->{content};                  my $tag = $type2tag{$type} || die "can't find which tag to use for type $type";
105                          my $delimiter = $x->{delimiter} || ' ';                  foreach my $x (@{$config->{indexer}->{$field}->{$tag}}) {
106    
107                          # FIX: this is ugly, UGLY, cludge string is returned                          my $format = x($x->{content});
108                          # in UTF8 encoding , but as if source charset                          my $delimiter = x($x->{delimiter}) || ' ';
                         # is ISO8859-1 and not some other. This break other  
                         # character encodings, so we convert it first  
                         # back to ISO8859-1  
                         $format = $xml_codepage->convert($format);  
                         $delimiter = $xml_codepage->convert($delimiter) if ($delimiter);  
109    
110                          my $isis_i = 0;         # isis repeatable offset                          my $repeat_off = 0;             # repeatable offset
111    
112                          my ($s,$d,$i) = (1,1,0);        # swish, display default                          my ($s,$d,$i) = (1,1,0);        # swish, display default
113                          $s = 0 if (lc($x->{type}) eq "display");                          $s = 0 if (lc($x->{type}) eq "display");
114                          $d = 0 if (lc($x->{type}) eq "swish");                          $d = 0 if (lc($x->{type}) eq "swish");
115                          ($s,$d,$i) = (0,0,1) if (lc($x->{type}) eq "index");                          ($s,$d,$i) = (0,0,1) if (lc($x->{type}) eq "index");
 #print STDERR "## s: $s d: $d i: $i ## $format ##\n";    
116    
117                          $display_data .= $line_delimiter if ($display_data && $display_data !~ /$line_delimiter$/);                          # what will separate last line from this one?
118                            if ($display_data && $x->{append} && $x->{append} eq "1") {
119                                    $line_delimiter = ' ';
120                            } elsif ($display_data) {
121                                    $line_delimiter = '<br/>';
122                            }
123    
124                          my ($swish,$display) = (1,1);                          # init vars so that we go into while...
125                            ($swish,$display) = (1,1);
126    
127                            # while because of repeatable fields
128                          while ($swish || $display) {                          while ($swish || $display) {
129                                  ($swish,$display) = parse_format($format,$row,$isis_i++);                                  ($swish,$display) = parse_format($type, $format,$row,$repeat_off++,$import2cp);
130  #print STDERR "s: $swish\nd: $display\n" if ($swish);                                  if ($repeat_off > 1000) {
131                                            print STDERR "loop (more than 1000 repeatable fields) deteced in $row, $format\n";
132  #print STDERR "swish: $swish<-- display: $display<--\n";                                          last;
133                                    }
134                                    
135                                  # filter="name" ; filter this field through                                  # filter="name" ; filter this field through
136                                  # filter/[name].pm                                  # filter/[name].pm
137                                  my $filter = $x->{filter};                                  my $filter = $x->{filter};
# Line 120  sub isis2xml { Line 141  sub isis2xml {
141                                  # type="swish" ; field for swish                                  # type="swish" ; field for swish
142                                  if ($s && $swish) {                                  if ($s && $swish) {
143                                          if ($filter) {                                          if ($filter) {
 #print STDERR "using filter '$filter'\n";  
144                                                  no strict 'refs';                                                  no strict 'refs';
145                                                  $swish_data .= join(" ",&$filter($swish));                                                  $swish_data .= join(" ",&$filter($swish));
146                                          } else {                                          } else {
# Line 130  sub isis2xml { Line 150  sub isis2xml {
150    
151                                  # type="display" ; field for display                                  # type="display" ; field for display
152                                  if ($d && $display) {                                  if ($d && $display) {
153                                            if ($line_delimiter && $display_data) {
154                                                    $display_data .= $line_delimiter;
155                                                    undef $line_delimiter;
156                                            }
157                                          if ($filter) {                                          if ($filter) {
158                                                  no strict 'refs';                                                  no strict 'refs';
159                                                  $display_data .= join($delimiter,&$filter($display));                                                  $display_data .= join($delimiter,&$filter($display));
# Line 144  sub isis2xml { Line 168  sub isis2xml {
168                                                                                                    
169                                  # type="index" ; insert into index                                  # type="index" ; insert into index
170                                  if ($i && $display) {                                  if ($i && $display) {
171                                          my $index_data = $index_codepage->convert($display) || $display;                                          my $index_data = $display;
172                                          if ($filter) {                                          if ($filter) {
173                                                  no strict 'refs';                                                  no strict 'refs';
174                                                  foreach my $d (&$filter($index_data)) {                                                  foreach my $d (&$filter($index_data)) {
175                                                          $index->insert($field, $d, $db_dir);                                                          $index->insert($field, $d, $path);
176                                                  }                                                  }
177                                          } else {                                          } else {
178                                                  $index->insert($field, $index_data, $db_dir);                                                  $index->insert($field, $index_data, $path);
179                                          }                                          }
180                                  }                                  }
181                          }                          }
                         if ($x->{append}) {  
                                 $line_delimiter = ' ';  
                         } else {  
                                 $line_delimiter = '<br/>';  
                         }  
182                  }                  }
183    
184                    # now try to parse variables from configuration file
185                    foreach my $x (@{$config->{indexer}->{$field}->{'config'}}) {
186    
187  #print STDERR "s_d: $swish_data\nd_d: $display_data\n" if ($swish_data);                          my $delimiter = x($x->{delimiter}) || ' ';
188                  if ($display_data) {                          my $val = $cfg->val($database, x($x->{content}));
189    
190                          # remove last <br>                          my ($s,$d,$i) = (1,1,0);        # swish, display default
191                          $display_data =~ s/$line_delimiter$//;                          $s = 0 if (lc($x->{type}) eq "display");
192                            $d = 0 if (lc($x->{type}) eq "swish");
193                            ($s,$d,$i) = (0,0,1) if (lc($x->{type}) eq "index");
194    
195                          $display_data = $isis_codepage->convert($display_data) || die "Can't convert '$display_data' !";                          if ($val) {
196                          # FIX: this is removed and replaced by html tag.                                  $display_data .= $delimiter.$val if ($d);
197                          #$xml .= xmlify($field."_display", $display_data);                                  $swish_data .= $val if ($s);
198                                    $index->insert($field, $val, $path) if ($i);
199                            }
200    
201                    }
202    
203    
204                    if ($display_data) {
205    
206                          if ($field eq "headline") {                          if ($field eq "headline") {
207                                  $xml .= xmlify("headline", $display_data);                                  $xml .= xmlify("headline", $display_data);
# Line 189  sub isis2xml { Line 219  sub isis2xml {
219                                          print STDERR "WARNING: field '$field' doesn't have 'name' attribute!";                                          print STDERR "WARNING: field '$field' doesn't have 'name' attribute!";
220                                  }                                  }
221                                  if ($field_name) {                                  if ($field_name) {
222                                          $html .= $xml_codepage->convert($field_name);                                          $html .= x($field_name);
 #                                       $html .= "-->".$field_name."<--";  
223                                  }                                  }
224                                  $html .= $display_data."###\n";                                  $html .= $display_data."###\n";
225                          }                          }
226                  }                  }
227                  if ($swish_data) {                  if ($swish_data) {
                         my $i = Text::Iconv->new($config->{isis_codepage},'ISO8859-2');  
228                          # remove extra spaces                          # remove extra spaces
229                          $swish_data =~ s/ +/ /g;                          $swish_data =~ s/ +/ /g;
230                          $swish_data =~ s/ +$//g;                          $swish_data =~ s/ +$//g;
231    
232                          $swish_data = $i->convert($swish_data);                          $xml .= xmlify($field."_swish", unac_string($codepage,$swish_data));
                         $xml .= xmlify($field."_swish",unac_string('ISO8859-2',$swish_data));  
                         #$swish_data = $isis_codepage->convert($swish_data)."##" || $swish_data;  
                         #$xml .= xmlify($field."_swish",unac_string($config->{isis_codepage},$swish_data));  
233                  }                  }
234    
235    
# Line 212  sub isis2xml { Line 237  sub isis2xml {
237    
238          # dump formatted output in <html>          # dump formatted output in <html>
239          if ($html) {          if ($html) {
240                  $xml .= xmlify("html",$html);                  #$xml .= xmlify("html",$html);
241                    $xml .= "<html><![CDATA[ $html ]]></html>";
242          }          }
243                    
244          if ($xml) {          if ($xml) {
 #print STDERR "x: $xml\n";  
245                  $xml .= $add_xml if ($add_xml);                  $xml .= $add_xml if ($add_xml);
246                  return "<xml>\n$xml</xml>\n";                  return "<xml>\n$xml</xml>\n";
247          } else {          } else {
# Line 226  sub isis2xml { Line 251  sub isis2xml {
251    
252  ##########################################################################  ##########################################################################
253    
254    # read configuration for this script
255  my $cfg = new Config::IniFiles( -file => $config_file );  my $cfg = new Config::IniFiles( -file => $config_file );
256    
257    # read global.conf configuration
258    my $cfg_global = new Config::IniFiles( -file => 'global.conf' );
259    
260    # open index
261    $index = new index_DBI(
262                    $cfg_global->val('global', 'dbi_dbd'),
263                    $cfg_global->val('global', 'dbi_dsn'),
264                    $cfg_global->val('global', 'dbi_user'),
265                    $cfg_global->val('global', 'dbi_passwd') || '',
266            );
267    
268  foreach my $database ($cfg->Sections) {  foreach my $database ($cfg->Sections) {
269    
270          my $isis_db = $cfg -> val($database, 'isis_db');          my $type = lc($cfg -> val($database, 'type')) || die "$database doesn't have 'type' defined";
271          my $type = $cfg -> val($database, 'type');          my $add_xml = $cfg -> val($database, 'xml');    # optional
         my $add_xml = $cfg -> val($database, 'xml');  
   
         # read configuration for this type  
         $config=XMLin("./import_xml/$type.xml", forcearray => [ 'isis' ], forcecontent => 1);  
         $isis_codepage = Text::Iconv->new($config->{isis_codepage},$XML_CHARSET);  
         $index_codepage = Text::Iconv->new($config->{isis_codepage},$config->{index_codepage});  
         $xml_codepage = Text::Iconv->new($cfg->val($database,'xml_codepage'),$XML_CHARSET);  
   
         my $db = OpenIsis::open( $isis_db );  
         if (0) {  
 #       # FIX  
 #       if (! $db ) {  
                 print STDERR "WARNING: can't open '$isis_db'\n";  
                 next ;  
         }  
272    
273          my $max_rowid = OpenIsis::maxRowid( $db );  print STDERR "reading ./import_xml/$type.xml\n";
274    
275          print STDERR "Reading database: $isis_db [$max_rowid rows]\n";          # extract just type basic
276            my $type_base = $type;
277            $type_base =~ s/_.+$//g;
278    
279          my $path = $database;                   # was $isis_db          $config=XMLin("./import_xml/$type.xml", forcearray => [ $type2tag{$type_base}, 'config' ], forcecontent => 1);
280    
281            # output current progress indicator
282          my $last_p = 0;          my $last_p = 0;
283            sub progress {
284                    #return if (! $opts{q});        # FIXME
285                    my $current = shift;
286                    my $total = shift || 1;
287                    my $p = int($current * 100 / $total);
288                    if ($p != $last_p) {
289                            printf STDERR ("%5d / %5d [%-51s] %-2d %% \r",$current,$total,"=" x ($p/2).">", $p );
290                            $last_p = $p;
291                    }
292            }
293    
294            my $fake_dir = 1;
295            sub fakeprogress {
296                    my $current = shift @_;
297    
298                    my @ind = ('-','\\','|','/','-','\\','|','/', '-');
299    
300                    $last_p += $fake_dir;
301                    $fake_dir = -$fake_dir if ($last_p > 1000 || $last_p < 0);
302                    if ($last_p % 10 == 0) {
303                            printf STDERR ("%5d / %5s [%-51s]\r",$current,"?"," " x ($last_p/20).$ind[($last_p/20) % $#ind]);
304                    }
305            }
306    
307            # now read database
308    print STDERR "using: $type...\n";
309    
310            if ($type_base eq "isis") {
311    
312                    my $isis_db = $cfg -> val($database, 'isis_db') || die "$database doesn't have 'isis_db' defined!";
313    
314                    $import2cp = Text::Iconv->new($config->{isis_codepage},$codepage);
315                    my $db = OpenIsis::open( $isis_db );
316    
317                    my $max_rowid = OpenIsis::maxRowid( $db );
318    
319                    print STDERR "Reading database: $isis_db [$max_rowid rows]\n";
320    
321                    my $path = $database;
322    
323  #       { my $row_id = 4514;                  for (my $row_id = 1; $row_id <= $max_rowid; $row_id++ ) {
324  # FIX                          my $row = OpenIsis::read( $db, $row_id );
325          for (my $row_id = 1; $row_id <= $max_rowid; $row_id++ ) {                          if ($row && $row->{mfn}) {
326                  my $row = OpenIsis::read( $db, $row_id );          
327                  if ($row && $row->{mfn}) {                                  progress($row->{mfn}, $max_rowid);
328  #print STDERR "mfn: ",$row->{mfn},"\n";  
329                          # output current process indicator                                  my $swishpath = $path."#".int($row->{mfn});
330                          my $p = int($row->{mfn} * 100 / $max_rowid);  
331                          if ($p != $last_p) {                                  if (my $xml = data2xml($type_base,$row,$add_xml,$cfg,$database)) {
332                                  printf STDERR ("%5d / %5d [%-51s] %-2d %% \r",$row->{mfn},$max_rowid,"=" x ($p/2).">", $p ) if (! $opts{q});                                          $xml = $cp2utf->convert($xml);
333                                  $last_p = $p;                                          use bytes;      # as opposed to chars
334                                            print "Path-Name: $swishpath\n";
335                                            print "Content-Length: ".(length($xml)+1)."\n";
336                                            print "Document-Type: XML\n\n$xml\n";
337                                    }
338                            }
339                    }
340                    print STDERR "\n";
341    
342            } elsif ($type_base eq "excel") {
343                    use Spreadsheet::ParseExcel;
344                    use Spreadsheet::ParseExcel::Utility qw(int2col);
345                    
346                    $import2cp = Text::Iconv->new($config->{excel_codepage},$codepage);
347                    my $excel_file = $cfg -> val($database, 'excel_file') || die "$database doesn't have 'excel_file' defined!";
348    
349                    my $sheet = x($config->{sheet}) || die "no sheet in $type.xml";
350                    my $start_row = x($config->{start_row}) - 1 || die "no start_row in $type.xml";
351    
352                    my $oBook = Spreadsheet::ParseExcel::Workbook->Parse($excel_file) || die "can't open Excel file '$excel_file'";
353    
354                    my $sheet_nr = 0;
355                    foreach my $oWks (@{$oBook->{Worksheet}}) {
356                            #print STDERR "-- SHEET $sheet_nr:", $oWks->{Name}, "\n";
357                            last if ($oWks->{Name} eq $sheet);
358                            $sheet_nr++;
359                    }
360    
361                    my $oWorksheet = $oBook->{Worksheet}[$sheet_nr];
362            
363                    print STDERR "using sheet: ",$oWorksheet->{Name},"\n";
364                    defined ($oWorksheet) || die "can't find sheet '$sheet' in $excel_file";
365                    my $end_row = x($config->{end_row}) || $oWorksheet->{MaxRow};
366    
367                    for(my $iR = $start_row ; defined $end_row && $iR <= $end_row ; $iR++) {
368                            my $row;
369                            for(my $iC = $oWorksheet->{MinCol} ; defined $oWorksheet->{MaxCol} && $iC <= $oWorksheet->{MaxCol} ; $iC++) {
370                                    my $cell = $oWorksheet->{Cells}[$iR][$iC];
371                                    if ($cell) {
372                                            $row->{int2col($iC)} = $cell->Value;
373                                    }
374                            }
375    
376                            progress($iR, $end_row);
377    
378    #                       print "row[$iR/$end_row] ";
379    #                       foreach (keys %{$row}) {
380    #                               print "$_: ",$row->{$_},"\t";
381    #                       }
382    #                       print "\n";
383    
384                            my $swishpath = $database."#".$iR;
385    
386                            next if (! $row);
387    
388                            if (my $xml = data2xml($type_base,$row,$add_xml,$cfg,$database)) {
389                                    $xml = $cp2utf->convert($xml);
390                                    use bytes;      # as opposed to chars
391                                    print "Path-Name: $swishpath\n";
392                                    print "Content-Length: ".(length($xml)+1)."\n";
393                                    print "Document-Type: XML\n\n$xml\n";
394                          }                          }
395                    }
396            } elsif ($type_base eq "marc") {
397    
398                    use MARC;
399                    
400                    $import2cp = Text::Iconv->new($config->{marc_codepage},$codepage);
401                    my $marc_file = $cfg -> val($database, 'marc_file') || die "$database doesn't have 'marc_file' defined!";
402    
403                    # optional argument is format
404                    my $format = x($config->{format}) || 'usmarc';
405    
406                    print STDERR "Reading MARC file '$marc_file'\n";
407    
408                          if (my $xml = isis2xml($row,$add_xml)) {                  my $marc = new MARC;
409  #print STDERR "--ret-->$xml\n";                  my $nr = $marc->openmarc({
410                                  print "Path-Name: $path#".int($row->{mfn})."\n";                                  file=>$marc_file, format=>$format
411                            }) || die "Can't open MARC file '$marc_file'";
412    
413                    my $i=0;        # record nr.
414    
415                    my $rec;
416    
417                    while ($marc->nextmarc(1)) {
418    
419                            # XXX
420                            fakeprogress($i++);
421    
422                            my $swishpath = $database."#".$i;
423    
424                            if (my $xml = data2xml($type_base,$marc,$add_xml,$cfg,$database)) {
425                                    $xml = $cp2utf->convert($xml);
426                                    use bytes;      # as opposed to chars
427                                    print "Path-Name: $swishpath\n";
428                                  print "Content-Length: ".(length($xml)+1)."\n";                                  print "Content-Length: ".(length($xml)+1)."\n";
429                                  print "Document-Type: XML\n\n$xml\n";                                  print "Document-Type: XML\n\n$xml\n";
430                          }                          }
431                  }                  }
432            } elsif ($type_base eq "feed") {
433    
434                    $import2cp = Text::Iconv->new($config->{feed_codepage},$codepage);
435                    my $prog = x($config->{prog}) || die "$database doesn't have 'prog' defined!";
436    
437                    print STDERR "Reading feed from program '$prog'\n";
438    
439                    open(FEED,"feeds/$prog |") || die "can't start $prog: $!";
440    
441                    my $i=1;        # record nr.
442    
443                    my $data;
444                    my $line=1;
445    
446                    while (<FEED>) {
447                            chomp;
448    
449                            if (/^$/) {
450                                    my $swishpath = $database."#".$i++;
451    
452                                    if (my $xml = data2xml($type_base,$data,$add_xml,$cfg,$database)) {
453                                            $xml = $cp2utf->convert($xml);
454                                            use bytes;      # as opposed to chars
455                                            print "Path-Name: $swishpath\n";
456                                            print "Content-Length: ".(length($xml)+1)."\n";
457                                            print "Document-Type: XML\n\n$xml\n";
458                                    }
459                                    $line = 1;
460                                    $data = {};
461                                    next;
462                            }
463    
464                            $line = $1 if (s/^(\d+):\s*//);
465                            $data->{$line++} = $_;
466    
467                            fakeprogress($i);
468    
469                    }
470          }          }
         print STDERR "\n";  
471  }  }
472    
473  # call this to commit index  # call this to commit index
# Line 289  __END__ Line 479  __END__
479    
480  =head1 NAME  =head1 NAME
481    
482  isis2xml.pl - read isis file and dump XML  all2xml.pl - read various file formats and dump XML for SWISH-E
483    
484  =head1 DESCRIPTION  =head1 DESCRIPTION
485    
486  This command will read ISIS data file using OpenIsis perl module and  This command will read ISIS data file using OpenIsis perl module, MARC
487  create XML file for usage with I<SWISH-E>  records using MARC module and optionally Micro$oft Excel files to
488  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,
489  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
490  script is tailor-made for SWISH-E.  has something like that). Output of this script is tailor-made for SWISH-E.
491    
492    =head1 BUGS
493    
494    Documentation is really lacking. However, in true Open Source spirit, source
495    is best documentation. I even made considerable effort to comment parts
496    which are not intuitively clear, so...
497    
498  =head1 AUTHOR  =head1 AUTHOR
499    

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

  ViewVC Help
Powered by ViewVC 1.1.26