/[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 21 by dpavlin, Sun Feb 23 00:00:51 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
36    
37    Text::Iconv->raise_error(0);     # Conversion errors don't raise exceptions
38    
39  #die "usage: $0 -d [database_dir] -m [database1,database2] " if (! %opts);  # 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  #print Dumper($config->{indexer});  # decode isis/excel or other import codepage
50  #print "-" x 70,"\n";  my $import2cp;
51    
52  Text::Iconv->raise_error(1);     # Conversion errors raise exceptions  # outgoing xml must be in UTF-8
53    my $cp2utf = Text::Iconv->new($codepage,'UTF-8');
54    
55  #my $isis_codepage = Text::Iconv->new($config->{isis_codepage},'UTF8');  # mapping between data type and tag which specify
56  #my $index_codepage = Text::Iconv->new($config->{isis_codepage},$config->{index_codepage});  # format in XML file
57  my $isis_codepage;  my %type2tag = (
58  my $index_codepage;          'isis' => 'isis',
59  my $cludge_codepage = Text::Iconv->new('UTF8','ISO8859-1');          'excel' => 'column',
60  my $xml_codepage;          '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 62  sub isis2xml { Line 80  sub isis2xml {
80    
81          my %field_usage;        # counter for usage of each field          my %field_usage;        # counter for usage of each field
82    
83          foreach my $field (keys %{$config->{indexer}}) {          # sort subrouting using order="" attribute
84            sub by_order {
85                    return 0 if (! $config->{indexer}->{$a}->{order});
86                    return 0 if (! $config->{indexer}->{$b}->{order});
87    
88                    return $config->{indexer}->{$a}->{order} <=>
89                            $config->{indexer}->{$b}->{order} ;
90            }
91    
92            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;
101    
102                    my ($swish,$display);
103    
104                    my $tag = $type2tag{$type} || die "can't find which tag to use for type $type";
105                    foreach my $x (@{$config->{indexer}->{$field}->{$tag}}) {
106    
107                  foreach my $x (@{$config->{indexer}->{$field}->{isis}}) {                          my $format = x($x->{content});
108                            my $delimiter = x($x->{delimiter}) || ' ';
109    
110                            my $repeat_off = 0;             # repeatable offset
111    
                         my $format = $x->{content};  
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                          # FIX: this is ugly, UGLY, cludge string is returned                          # what will separate last line from this one?
118                          # in UTF8 encoding , but as if source charset                          if ($display_data && $x->{append} && $x->{append} eq "1") {
119                          # is ISO8859-1 and not some other. This break other                                  $line_delimiter = ' ';
120                          # character encodings, so we convert it first                          } elsif ($display_data) {
121                          # back to ISO8859-1                                  $line_delimiter = '<br/>';
                         $format = $cludge_codepage->convert($format);  
   
                         my ($swish,$display) = parse_format($format,$row);  
 #print STDERR "s: $swish\nd: $display\n" if ($swish);  
   
 #print STDERR "swish: $swish<-- display: $display<--\n";  
   
                         # filter="name" ; filter this field through  
                         # filter/[name].pm  
                         my $filter;  
                         if ($x->{filter}) {  
                                 $filter = "filter/".$x->{filter}.".pm";  
                                 require $filter;  
122                          }                          }
123                          # type="swish" ; field for swish  
124                          if ($s && $swish) {                          # init vars so that we go into while...
125                            ($swish,$display) = (1,1);
126    
127                            # while because of repeatable fields
128                            while ($swish || $display) {
129                                    ($swish,$display) = parse_format($type, $format,$row,$repeat_off++,$import2cp);
130                                    if ($repeat_off > 1000) {
131                                            print STDERR "loop (more than 1000 repeatable fields) deteced in $row, $format\n";
132                                            last;
133                                    }
134                                    
135                                    # filter="name" ; filter this field through
136                                    # filter/[name].pm
137                                    my $filter = $x->{filter};
138                                  if ($filter) {                                  if ($filter) {
139                                          $swish_data .= join(" ",&filter($swish));                                          require "filter/".$filter.".pm";
140                                  } else {                                  }
141                                          $swish_data .= $swish if ($s && $swish);                                  # type="swish" ; field for swish
142                                    if ($s && $swish) {
143                                            if ($filter) {
144                                                    no strict 'refs';
145                                                    $swish_data .= join(" ",&$filter($swish));
146                                            } else {
147                                                    $swish_data .= $swish;
148                                            }
149                                  }                                  }
                         }  
150    
151                          # type="display" ; field for display                                  # type="display" ; field for display
152                          if ($d && $display) {                                  if ($d && $display) {
153                                  if ($filter) {                                          if ($line_delimiter && $display_data) {
154                                          $display_data .= join(" ",&filter($display));                                                  $display_data .= $line_delimiter;
155                                  } else {                                                  undef $line_delimiter;
156                                          $display_data .= $display;                                          }
157                                            if ($filter) {
158                                                    no strict 'refs';
159                                                    $display_data .= join($delimiter,&$filter($display));
160                                            } else {
161                                                    if ($display_data) {
162                                                            $display_data .= $delimiter.$display;
163                                                    } else {
164                                                            $display_data .= $display;
165                                                    }
166                                            }
167                                  }                                  }
168                          }                                                  
169                                                                            # type="index" ; insert into index
170                          # type="index" ; insert into index                                  if ($i && $display) {
171                          if ($i && $display) {                                          my $index_data = $display;
172                                  my $index_data = $index_codepage->convert($display) || $display;                                          if ($filter) {
173                                  if ($filter) {                                                  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 {
178                                                    $index->insert($field, $index_data, $path);
179                                          }                                          }
                                 } else {  
                                         $index->insert($field, $index_data, $db_dir);  
180                                  }                                  }
181                          }                          }
182                  }                  }
183    
184                    # now try to parse variables from configuration file
185                    foreach my $x (@{$config->{indexer}->{$field}->{'config'}}) {
186    
187                            my $delimiter = x($x->{delimiter}) || ' ';
188                            my $val = $cfg->val($database, x($x->{content}));
189    
190                            my ($s,$d,$i) = (1,1,0);        # swish, display default
191                            $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                            if ($val) {
196                                    $display_data .= $delimiter.$val if ($d);
197                                    $swish_data .= $val if ($s);
198                                    $index->insert($field, $val, $path) if ($i);
199                            }
200    
201                    }
202    
203    
 #print STDERR "s_d: $swish_data\nd_d: $display_data\n" if ($swish_data);  
204                  if ($display_data) {                  if ($display_data) {
                         $display_data = $isis_codepage->convert($display_data) || die "Can't convert '$display_data' !";  
                         # FIX: this is removed and replaced by html tag.  
                         #$xml .= xmlify($field."_display", $display_data);  
205    
206                          if ($field eq "headline") {                          if ($field eq "headline") {
207                                  $xml .= xmlify("headline", $display_data);                                  $xml .= xmlify("headline", $display_data);
# Line 151  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);
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 173  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 187  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},'UTF8');  
         $index_codepage = Text::Iconv->new($config->{isis_codepage},$config->{index_codepage});  
         $xml_codepage = Text::Iconv->new($cfg->val($database,'xml_codepage'),'UTF8');  
   
         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 $row_id = 4514;                  my $isis_db = $cfg -> val($database, 'isis_db') || die "$database doesn't have 'isis_db' defined!";
313  # FIX  
314          for (my $row_id = 1; $row_id <= $max_rowid; $row_id++ ) {                  $import2cp = Text::Iconv->new($config->{isis_codepage},$codepage);
315                  my $row = OpenIsis::read( $db, $row_id );                  my $db = OpenIsis::open( $isis_db );
316                  if ($row && $row->{mfn}) {  
317  #print STDERR "mfn: ",$row->{mfn},"\n";                  my $max_rowid = OpenIsis::maxRowid( $db );
318                          # output current process indicator  
319                          my $p = int($row->{mfn} * 100 / $max_rowid);                  print STDERR "Reading database: $isis_db [$max_rowid rows]\n";
320                          if ($p != $last_p) {  
321                                  printf STDERR ("%5d / %5d [%-51s] %-2d %% \r",$row->{mfn},$max_rowid,"=" x ($p/2).">", $p ) if (! $opts{q});                  my $path = $database;
322                                  $last_p = $p;  
323                    for (my $row_id = 1; $row_id <= $max_rowid; $row_id++ ) {
324                            my $row = OpenIsis::read( $db, $row_id );
325                            if ($row && $row->{mfn}) {
326            
327                                    progress($row->{mfn}, $max_rowid);
328    
329                                    my $swishpath = $path."#".int($row->{mfn});
330    
331                                    if (my $xml = data2xml($type_base,$row,$add_xml,$cfg,$database)) {
332                                            $xml = $cp2utf->convert($xml);
333                                            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                          if (my $xml = isis2xml($row,$add_xml)) {                  my $oWorksheet = $oBook->{Worksheet}[$sheet_nr];
362  #print STDERR "--ret-->$xml\n";          
363                                  print "Path-Name: $path#".int($row->{mfn})."\n";                  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";                                  print "Content-Length: ".(length($xml)+1)."\n";
393                                  print "Document-Type: XML\n\n$xml\n";                                  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                    my $marc = new MARC;
409                    my $nr = $marc->openmarc({
410                                    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";
429                                    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 250  __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.21  
changed lines
  Added in v.90

  ViewVC Help
Powered by ViewVC 1.1.26