X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Fods-reader.c;h=77da78ca51a3cff610b509e7bcd04cae9bc261e6;hb=415dbf964ef32c89d6283a19487a6eb188f32ed2;hp=170c005739b9eed6070465743d20ac4de521bab9;hpb=eb17696132c78cc38f92d993c78f9dce63e0faa9;p=pspp diff --git a/src/data/ods-reader.c b/src/data/ods-reader.c index 170c005739..77da78ca51 100644 --- a/src/data/ods-reader.c +++ b/src/data/ods-reader.c @@ -33,7 +33,8 @@ #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"); @@ -87,6 +88,8 @@ enum reader_state struct ods_reader { + struct spreadsheet spreadsheet; + xmlTextReaderPtr xtr; enum reader_state state; @@ -333,63 +336,114 @@ convert_xml_to_value (struct ccase *c, const struct variable *var, } -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; - struct ods_reader *r = xzalloc (sizeof *r); + 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 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; + + 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; - if ( gri->cell_range ) + 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; } } @@ -402,8 +456,8 @@ ods_open_reader (struct spreadsheet_read_info *gri, struct dictionary **dict) } 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; @@ -430,11 +484,11 @@ ods_open_reader (struct spreadsheet_read_info *gri, struct dictionary **dict) 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))) { @@ -483,7 +537,7 @@ ods_open_reader (struct spreadsheet_read_info *gri, struct dictionary **dict) { 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) @@ -513,7 +567,7 @@ ods_open_reader (struct spreadsheet_read_info *gri, struct dictionary **dict) } /* 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 ) @@ -521,7 +575,7 @@ ods_open_reader (struct spreadsheet_read_info *gri, struct dictionary **dict) 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); @@ -545,7 +599,7 @@ ods_open_reader (struct spreadsheet_read_info *gri, struct dictionary **dict) if ( n_var_specs == 0 ) { msg (MW, _("Selected sheet or range of spreadsheet `%s' is empty."), - gri->file_name); + spreadsheet->file_name); goto error; } @@ -560,7 +614,7 @@ ods_open_reader (struct spreadsheet_read_info *gri, struct dictionary **dict) 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 ) { @@ -580,7 +634,7 @@ ods_open_reader (struct spreadsheet_read_info *gri, struct dictionary **dict) error: - zip_reader_destroy (zreader); + // zip_reader_destroy (zreader); for ( i = 0 ; i < n_var_specs ; ++i ) { @@ -592,7 +646,8 @@ ods_open_reader (struct spreadsheet_read_info *gri, struct dictionary **dict) free (var_spec); - dict_destroy (r->dict); + dict_destroy (r->spreadsheet.dict); + r->spreadsheet.dict = NULL; ods_file_casereader_destroy (NULL, r); @@ -619,7 +674,6 @@ ods_file_casereader_read (struct casereader *reader UNUSED, void *r_) return r->first_case; } - if ( r->state > STATE_INIT) { c = case_create (r->proto);