From ba5b5c3952f7de974f75162c99de51b5f572a078 Mon Sep 17 00:00:00 2001 From: Miika Turkia Date: Sun, 29 Sep 2013 15:44:38 +0300 Subject: [PATCH] Initial code to import CSV log files This patch implements basic functionality to import CSV formatted log profiles to Subsurface. The import includes time, depth and temperature from AP Logviewer based on one sample log file I have received. It is assumed that dive time is the first parameter and depth second. Temperature is given as a parameter from C source (hard coded currently to field 15) but we should have a GUI implemented for selecting the wanted fields. The two different sample logs of CSV dive log export I have received use tabulator as field separator. I assume the possible GUI should have option for the FS as well to be given as parameter to the XSLT. [Dirk Hohndel: small fix to the error string malloc] Signed-off-by: Miika Turkia Signed-off-by: Dirk Hohndel --- file.c | 39 +++++++++++++++- parse-xml.c | 23 +++++++++- xslt/csv2xml.xslt | 110 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 169 insertions(+), 3 deletions(-) create mode 100644 xslt/csv2xml.xslt diff --git a/file.c b/file.c index 70eb79ad4..53b03330c 100644 --- a/file.c +++ b/file.c @@ -97,6 +97,36 @@ static int try_to_open_zip(const char *filename, struct memblock *mem, char **er return success; } +static int try_to_xslt_open_csv(const char *filename, struct memblock *mem, char **error) +{ + char *buf; + + if (readfile(filename, mem) < 0) { + if (error) { + int len = strlen(_("Failed to read '%s'")) + strlen(filename); + *error = malloc(len); + snprintf(*error, len, _("Failed to read '%s'"), filename); + } + + return 1; + } + + /* Surround the CSV file content with XML tags to enable XSLT + * parsing + */ + buf = realloc(mem->buffer, mem->size + strlen("")); + if (buf != NULL) { + memmove(buf + 5, mem->buffer, mem->size); + memcpy(buf, "", 5); + memcpy(mem->buffer + mem->size + 5, "", 7); + mem->buffer = buf; + mem->size += strlen(""); + } else + return 1; + + return 0; +} + static int try_to_open_db(const char *filename, struct memblock *mem, char **error) { return parse_dm4_buffer(filename, mem->buffer, mem->size, &dive_table, error); @@ -229,6 +259,10 @@ static int open_by_filename(const char *filename, const char *fmt, struct memblo if (!strcasecmp(fmt, "SDE") || !strcasecmp(fmt, "ZIP") || !strcasecmp(fmt, "DLD")) return try_to_open_zip(filename, mem, error); + /* CSV files */ + if (!strcasecmp(fmt, "CSV")) + return try_to_xslt_open_csv(filename, mem, error); + #if ONCE_COCHRAN_IS_SUPPORTED /* Truly nasty intentionally obfuscated Cochran Anal software */ if (!strcasecmp(fmt, "CAN")) @@ -266,8 +300,9 @@ void parse_file(const char *filename, char **error) return; if (error) { - *error = malloc(1024); - snprintf(*error, 1024, _("Failed to read '%s'"), filename); + int len = strlen(_("Failed to read '%s'")) + strlen(filename); + *error = malloc(len); + snprintf(*error, len, _("Failed to read '%s'"), filename); } return; diff --git a/parse-xml.c b/parse-xml.c index 370388f4f..195eafeb9 100644 --- a/parse-xml.c +++ b/parse-xml.c @@ -1915,6 +1915,7 @@ static struct xslt_files { { "UDDF", "uddf.xslt" }, { "profile", "udcf.xslt" }, { "Divinglog", "DivingLog.xslt" }, + { "csv", "csv2xml.xslt" }, { NULL, } }; @@ -1925,6 +1926,7 @@ static xmlDoc *test_xslt_transforms(xmlDoc *doc, char **error) xsltStylesheetPtr xslt = NULL; xmlNode *root_element = xmlDocGetRootElement(doc); char *attribute; + char *params[3]; while ((info->root) && (strcasecmp(root_element->name, info->root) != 0)) { info++; @@ -1946,9 +1948,28 @@ static xmlDoc *test_xslt_transforms(xmlDoc *doc, char **error) parser_error(error, _("Can't open stylesheet (%s)/%s"), xslt_path, info->file); return doc; } - transformed = xsltApplyStylesheet(xslt, doc, NULL); + + /* + * params is only used for CSV import, but it does not + * hurt if we supply unused parameters for other + * transforms as well. + * + * We should have a GUI set the parameters but currently + * we just have PoC how parameters would be handled. + * + * (Field 9 is temperature for XP5 import, field 15 + * is temperature for AP Logviewer. + */ + + params[0] = strdup("tempField"); + params[1] = strdup("15"); + params[2] = NULL; + + transformed = xsltApplyStylesheet(xslt, doc, (const char **)params); xmlFreeDoc(doc); xsltFreeStylesheet(xslt); + free(params[0]); + free(params[1]); return transformed; } return doc; diff --git a/xslt/csv2xml.xslt b/xslt/csv2xml.xslt new file mode 100644 index 000000000..faa9e9605 --- /dev/null +++ b/xslt/csv2xml.xslt @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +