From: Linus Torvalds Date: Thu, 1 Sep 2011 18:22:05 +0000 (-0700) Subject: xml parsing: start traversing properties too X-Git-Url: http://git.tdb.fi/?p=ext%2Fsubsurface.git;a=commitdiff_plain;h=da4edbcce81a9a90e414bc6281183df154019b0c xml parsing: start traversing properties too This requires us to change the way we match things up, because now we can have things like dives.dive.sample.event.time and dives.dive.sample.time and they are different things (that "sample.event.time" is a 'time' property of the 'event'). Now, this is always going to be ambiguous, since our linearized name of the xml doesn't really care whether it's a xml node "child" or a "property", but quite frankly, I don't care. XML just isn't worth the pain. In fact, maybe this ambiguity can end up being a good thing. We will parse these two different lines of XML the same way: 10.8 and the attribute approach seems to be the nicer one. Maybe I'll use that for the output format. Signed-off-by: Linus Torvalds --- diff --git a/parse-xml.c b/parse-xml.c index 58d446d..5ac36a1 100644 --- a/parse-xml.c +++ b/parse-xml.c @@ -33,26 +33,30 @@ static void record_dive(struct dive *dive) dive_table.nr = nr+1; } -static void nonmatch(const char *type, const char *fullname, const char *name, char *buffer) +static void start_match(const char *type, const char *name, char *buffer) { - if (verbose > 1) - printf("Unable to match %s '(%.*s)%s' (%s)\n", type, - (int) (name - fullname), fullname, name, - buffer); - free(buffer); + if (verbose > 2) + printf("Matching %s '%s' (%s)\n", + type, name, buffer); } -static const char *last_part(const char *name) +static void nonmatch(const char *type, const char *name, char *buffer) { - const char *p = strrchr(name, '.'); - return p ? p+1 : name; + if (verbose > 1) + printf("Unable to match %s '%s' (%s)\n", + type, name, buffer); + free(buffer); } typedef void (*matchfn_t)(char *buffer, void *); -static int match(const char *pattern, const char *name, matchfn_t fn, char *buf, void *data) +static int match(const char *pattern, int plen, + const char *name, int nlen, + matchfn_t fn, char *buf, void *data) { - if (strcasecmp(pattern, name)) + if (plen > nlen) + return 0; + if (memcmp(pattern, name + nlen - plen, plen)) return 0; fn(buf, data); return 1; @@ -300,67 +304,72 @@ static void ignore(char *buffer, void *_time) { } +#define MATCH(pattern, fn, dest) \ + match(pattern, strlen(pattern), name, len, fn, buf, dest) + /* We're in samples - try to convert the random xml value to something useful */ static void try_to_fill_sample(struct sample *sample, const char *name, char *buf) { - const char *last = last_part(name); + int len = strlen(name); - if (match("pressure", last, pressure, buf, &sample->tankpressure)) + start_match("sample", name, buf); + if (MATCH(".sample.pressure", pressure, &sample->tankpressure)) return; - if (match("cylpress", last, pressure, buf, &sample->tankpressure)) + if (MATCH(".sample.cylpress", pressure, &sample->tankpressure)) return; - if (match("depth", last, depth, buf, &sample->depth)) + if (MATCH(".sample.depth", depth, &sample->depth)) return; - if (match("temperature", last, temperature, buf, &sample->temperature)) + if (MATCH(".sample.temperature", temperature, &sample->temperature)) return; - if (match("sampletime", last, sampletime, buf, &sample->time)) + if (MATCH(".sample.sampletime", sampletime, &sample->time)) return; - if (match("time", last, sampletime, buf, &sample->time)) + if (MATCH(".sample.time", sampletime, &sample->time)) return; - nonmatch("sample", name, last, buf); + nonmatch("sample", name, buf); } /* We're in the top-level dive xml. Try to convert whatever value to a dive value */ static void try_to_fill_dive(struct dive *dive, const char *name, char *buf) { - const char *last = last_part(name); + int len = strlen(name); - if (match("date", last, divedate, buf, &dive->when)) + start_match("dive", name, buf); + if (MATCH(".date", divedate, &dive->when)) return; - if (match("time", last, divetime, buf, &dive->when)) + if (MATCH(".time", divetime, &dive->when)) return; - if (match("datetime", last, divedatetime, buf, &dive->when)) + if (MATCH(".datetime", divedatetime, &dive->when)) return; - if (match("maxdepth", last, depth, buf, &dive->maxdepth)) + if (MATCH(".maxdepth", depth, &dive->maxdepth)) return; - if (match("meandepth", last, depth, buf, &dive->meandepth)) + if (MATCH(".meandepth", depth, &dive->meandepth)) return; - if (match("divetime", last, duration, buf, &dive->duration)) + if (MATCH(".divetime", duration, &dive->duration)) return; - if (match("divetimesec", last, duration, buf, &dive->duration)) + if (MATCH(".divetimesec", duration, &dive->duration)) return; - if (match("surfacetime", last, duration, buf, &dive->surfacetime)) + if (MATCH(".surfacetime", duration, &dive->surfacetime)) return; - if (match("airtemp", last, temperature, buf, &dive->airtemp)) + if (MATCH(".airtemp", temperature, &dive->airtemp)) return; - if (match("watertemp", last, temperature, buf, &dive->watertemp)) + if (MATCH(".watertemp", temperature, &dive->watertemp)) return; - if (match("cylinderstartpressure", last, pressure, buf, &dive->beginning_pressure)) + if (MATCH(".cylinderstartpressure", pressure, &dive->beginning_pressure)) return; - if (match("cylinderendpressure", last, pressure, buf, &dive->end_pressure)) + if (MATCH(".cylinderendpressure", pressure, &dive->end_pressure)) return; - if (match("divenumber", last, ignore, buf, NULL)) + if (MATCH(".divenumber", ignore, NULL)) return; - if (match("diveseries", last, ignore, buf, NULL)) + if (MATCH(".diveseries", ignore, NULL)) return; - if (match("number", last, ignore, buf, NULL)) + if (MATCH(".number", ignore, NULL)) return; - if (match("size", last, ignore, buf, NULL)) + if (MATCH(".size", ignore, NULL)) return; - if (match("fingerprint", last, ignore, buf, NULL)) + if (MATCH(".fingerprint", ignore, NULL)) return; - nonmatch("dive", name, last, buf); + nonmatch("dive", name, buf); } static unsigned int dive_size(int samples) @@ -538,15 +547,32 @@ static void visit_one_node(xmlNode *node) entry(name, len, content); } -static void traverse(xmlNode *node) +static void traverse(xmlNode *root); + +static void traverse_properties(xmlNode *node) +{ + xmlAttr *p; + + for (p = node->properties; p; p = p->next) + traverse(p->children); +} + +static void visit(xmlNode *n) +{ + visit_one_node(n); + traverse_properties(n); + traverse(n->children); +} + +static void traverse(xmlNode *root) { xmlNode *n; - for (n = node; n; n = n->next) { + for (n = root; n; n = n->next) { /* XML from libdivecomputer: 'dive' per new dive */ if (!strcmp(n->name, "dive")) { dive_start(); - traverse(n->children); + visit(n); dive_end(); continue; } @@ -559,14 +585,13 @@ static void traverse(xmlNode *node) */ if (!strcasecmp(n->name, "sample")) { sample_start(); - traverse(n->children); + visit(n); sample_end(); continue; } /* Anything else - just visit it and recurse */ - visit_one_node(n); - traverse(n->children); + visit(n); } }