X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=src%2Fdata%2Fods-reader.c;h=77da78ca51a3cff610b509e7bcd04cae9bc261e6;hb=415dbf964ef32c89d6283a19487a6eb188f32ed2;hp=097c245d179403380e755ceae9e6d66962921886;hpb=4785da39b9cb392c0a6a2c38a8abac199a72d615;p=pspp diff --git a/src/data/ods-reader.c b/src/data/ods-reader.c index 097c245d17..77da78ca51 100644 --- a/src/data/ods-reader.c +++ b/src/data/ods-reader.c @@ -33,7 +33,7 @@ #if !ODF_READ_SUPPORT struct casereader * -ods_open_reader (const struct spreadsheet_read_info *gri, struct spreadsheet_read_options *opts, +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"); @@ -88,6 +88,8 @@ enum reader_state struct ods_reader { + struct spreadsheet spreadsheet; + xmlTextReaderPtr xtr; enum reader_state state; @@ -334,55 +336,105 @@ convert_xml_to_value (struct ccase *c, const struct variable *var, } -struct casereader * -ods_open_reader (const struct spreadsheet_read_info *gri, struct spreadsheet_read_options *opts, - 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); - struct ods_reader *r = xzalloc (sizeof *r); + 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; + + 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 ) { @@ -432,11 +484,11 @@ ods_open_reader (const struct spreadsheet_read_info *gri, struct spreadsheet_rea 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))) { @@ -485,7 +537,7 @@ ods_open_reader (const struct spreadsheet_read_info *gri, struct spreadsheet_rea { 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) @@ -515,7 +567,7 @@ ods_open_reader (const struct spreadsheet_read_info *gri, struct spreadsheet_rea } /* 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 ) @@ -523,7 +575,7 @@ ods_open_reader (const struct spreadsheet_read_info *gri, struct spreadsheet_rea 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); @@ -547,7 +599,7 @@ ods_open_reader (const struct spreadsheet_read_info *gri, struct spreadsheet_rea if ( n_var_specs == 0 ) { msg (MW, _("Selected sheet or range of spreadsheet `%s' is empty."), - gri->file_name); + spreadsheet->file_name); goto error; } @@ -562,7 +614,7 @@ ods_open_reader (const struct spreadsheet_read_info *gri, struct spreadsheet_rea 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 ) { @@ -582,7 +634,7 @@ ods_open_reader (const struct spreadsheet_read_info *gri, struct spreadsheet_rea error: - zip_reader_destroy (zreader); + // zip_reader_destroy (zreader); for ( i = 0 ; i < n_var_specs ; ++i ) { @@ -594,7 +646,8 @@ ods_open_reader (const struct spreadsheet_read_info *gri, struct spreadsheet_rea free (var_spec); - dict_destroy (r->dict); + dict_destroy (r->spreadsheet.dict); + r->spreadsheet.dict = NULL; ods_file_casereader_destroy (NULL, r); @@ -621,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);