/* PSPP - a program for statistical analysis.
- Copyright (C) 2011 Free Software Foundation, Inc.
+ Copyright (C) 2011, 2012 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#if !ODF_READ_SUPPORT
struct casereader *
-ods_open_reader (struct spreadsheet_read_info *gri, struct dictionary **dict)
+ods_open_reader (const struct spreadsheet_read_options *opts,
+ struct dictionary **dict)
{
msg (ME, _("Support for %s files was not compiled into this installation of PSPP"), "OpenDocument");
struct ods_reader
{
+ struct spreadsheet spreadsheet;
+
xmlTextReaderPtr xtr;
enum reader_state state;
text =
xmv->value ? CHAR_CAST (const char *, xmv->value) : CHAR_CAST (const char *, xmv->text);
- data_in (ss_cstr (text), "UTF-8",
- fmt->type,
- v,
- var_get_width (var),
- "UTF-8");
+ free (data_in (ss_cstr (text), "UTF-8",
+ fmt->type,
+ v,
+ var_get_width (var),
+ "UTF-8"));
}
}
-struct casereader *
-ods_open_reader (struct spreadsheet_read_info *gri, struct dictionary **dict)
+/* Try to find out how many sheets there are in the "workbook" */
+static int
+get_sheet_count (struct zip_reader *zreader)
{
- int ret = 0;
- xmlChar *type = NULL;
- unsigned long int vstart = 0;
- casenumber n_cases = CASENUMBER_MAX;
- int i;
- struct var_spec *var_spec = NULL;
- int n_var_specs = 0;
+ xmlTextReaderPtr mxtr;
+ struct zip_member *meta = NULL;
+ meta = zip_member_open (zreader, "meta.xml");
+
+ if ( meta == NULL)
+ return -1;
+
+ mxtr = xmlReaderForIO ((xmlInputReadCallback) zip_member_read,
+ (xmlInputCloseCallback) zip_member_finish,
+ meta, NULL, NULL, XML_PARSE_RECOVER);
+
+ while (1 == xmlTextReaderRead (mxtr))
+ {
+ xmlChar *name = xmlTextReaderName (mxtr);
+ if ( 0 == xmlStrcmp (name, _xml("meta:document-statistic")))
+ {
+ xmlChar *attr = xmlTextReaderGetAttribute (mxtr, _xml ("meta:table-count"));
+
+ if ( attr != NULL)
+ {
+ int s = _xmlchar_to_int (attr);
+ return s;
+ }
+ }
+ }
+ return -1;
+}
- struct ods_reader *r = xzalloc (sizeof *r);
+struct spreadsheet *ods_probe (const char *filename, bool report_errors)
+{
+ struct ods_reader *r;
+ struct string errs;
+ xmlTextReaderPtr xtr ;
+ int sheet_count;
struct zip_member *content = NULL;
- struct zip_reader *zreader ;
- xmlChar *val_string = NULL;
- r->read_names = gri->read_names;
- ds_init_empty (&r->ods_errs);
+ struct zip_reader *zreader = NULL;
- zreader = zip_reader_create (gri->file_name, &r->ods_errs);
+ ds_init_empty (&errs);
- if ( NULL == zreader)
- {
- msg (ME, _("Error opening `%s' for reading as a OpenDocument spreadsheet file: %s."),
- gri->file_name, ds_cstr (&r->ods_errs));
+ zreader = zip_reader_create (filename, &errs);
- goto error;
- }
+ if (zreader == NULL)
+ return NULL;
content = zip_member_open (zreader, "content.xml");
- if ( NULL == content)
- {
- msg (ME, _("Could not extract OpenDocument spreadsheet from file `%s': %s."),
- gri->file_name, ds_cstr (&r->ods_errs));
- goto error;
- }
+ if ( content == NULL)
+ goto error;
zip_member_ref (content);
- r->xtr = xmlReaderForIO ((xmlInputReadCallback) zip_member_read,
+ sheet_count = get_sheet_count (zreader);
+
+ xtr = xmlReaderForIO ((xmlInputReadCallback) zip_member_read,
(xmlInputCloseCallback) zip_member_finish,
content, NULL, NULL, XML_PARSE_RECOVER);
- if ( r->xtr == NULL)
- {
- goto error;
- }
+ if ( xtr == NULL)
+ goto error;
+
+ r = xzalloc (sizeof *r);
+ r->xtr = xtr;
+ r->spreadsheet.type = SPREADSHEET_ODS;
+ r->spreadsheet.n_sheets = sheet_count;
- if ( gri->cell_range )
+ ds_destroy (&errs);
+
+ r->spreadsheet.file_name = filename;
+ return &r->spreadsheet;
+
+ error:
+ zip_reader_destroy (zreader);
+ ds_destroy (&errs);
+ return NULL;
+}
+
+struct casereader *
+ods_make_reader (struct spreadsheet *spreadsheet,
+ const struct spreadsheet_read_options *opts)
+{
+ intf ret = 0;
+ xmlChar *type = NULL;
+ unsigned long int vstart = 0;
+ casenumber n_cases = CASENUMBER_MAX;
+ int i;
+ struct var_spec *var_spec = NULL;
+ int n_var_specs = 0;
+
+ struct ods_reader *r = (struct ods_reader *) spreadsheet;
+ xmlChar *val_string = NULL;
+
+ assert (r);
+ r->read_names = opts->read_names;
+ ds_init_empty (&r->ods_errs);
+
+ if ( opts->cell_range )
{
- if ( ! convert_cell_ref (gri->cell_range,
+ if ( ! convert_cell_ref (opts->cell_range,
&r->start_col, &r->start_row,
&r->stop_col, &r->stop_row))
{
msg (SE, _("Invalid cell range `%s'"),
- gri->cell_range);
+ opts->cell_range);
goto error;
}
}
}
r->state = STATE_INIT;
- r->target_sheet = BAD_CAST gri->sheet_name;
- r->target_sheet_index = gri->sheet_index;
+ r->target_sheet = BAD_CAST opts->sheet_name;
+ r->target_sheet_index = opts->sheet_index;
r->row = r->col = -1;
r->sheet_index = 0;
if (ret < 1)
{
msg (MW, _("Selected sheet or range of spreadsheet `%s' is empty."),
- gri->file_name);
+ spreadsheet->file_name);
goto error;
}
- if ( gri->read_names)
+ if ( opts->read_names)
{
while (1 == (ret = xmlTextReaderRead (r->xtr)))
{
var_spec = xrealloc (var_spec, sizeof (*var_spec) * (idx + 1));
/* xrealloc (unlike realloc) doesn't initialise its memory to 0 */
- memset (var_spec + n_var_specs * sizeof (*var_spec),
+ memset (var_spec + n_var_specs,
0,
(n_var_specs - idx + 1) * sizeof (*var_spec));
n_var_specs = idx + 1;
{
int idx;
process_node (r);
- if ( r->row >= r->start_row + 1 + gri->read_names)
+ if ( r->row >= r->start_row + 1 + opts->read_names)
break;
if ( r->col < r->start_col)
}
/* Create the dictionary and populate it */
- *dict = r->dict = dict_create (
+ r->spreadsheet.dict = r->dict = dict_create (
CHAR_CAST (const char *, xmlTextReaderConstEncoding (r->xtr)));
for (i = 0 ; i < n_var_specs ; ++i )
struct fmt_spec fmt;
struct variable *var = NULL;
char *name = dict_make_unique_var_name (r->dict, var_spec[i].name, &vstart);
- int width = xmv_to_width (&var_spec[i].firstval, gri->asw);
+ int width = xmv_to_width (&var_spec[i].firstval, opts->asw);
dict_create_var (r->dict, name, width);
free (name);
if ( n_var_specs == 0 )
{
msg (MW, _("Selected sheet or range of spreadsheet `%s' is empty."),
- gri->file_name);
+ spreadsheet->file_name);
goto error;
}
convert_xml_to_value (r->first_case, var, &var_spec[i].firstval);
}
- zip_reader_destroy (zreader);
+ // zip_reader_destroy (zreader);
for ( i = 0 ; i < n_var_specs ; ++i )
{
error:
- zip_reader_destroy (zreader);
+ // zip_reader_destroy (zreader);
for ( i = 0 ; i < n_var_specs ; ++i )
{
free (var_spec);
+ dict_destroy (r->spreadsheet.dict);
+ r->spreadsheet.dict = NULL;
+ ods_file_casereader_destroy (NULL, r);
+
+
return NULL;
}
return r->first_case;
}
-
if ( r->state > STATE_INIT)
{
c = case_create (r->proto);