diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-09-01 11:22:05 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-09-01 11:22:05 -0700 |
commit | da4edbcce81a9a90e414bc6281183df154019b0c (patch) | |
tree | 5f5e97372e5c678039c4a45a3a3d74098f435c3e /parse-xml.c | |
parent | 4350a75b9455387c0da36b9b52349a858d8fca9c (diff) | |
download | subsurface-da4edbcce81a9a90e414bc6281183df154019b0c.tar.gz |
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:
<dive><sample><time>50</time><depth>10.8</depth></sample></dive>
<dive><sample time="50" depth="10.8"></sample></dive>
and the attribute approach seems to be the nicer one. Maybe I'll use
that for the output format.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'parse-xml.c')
-rw-r--r-- | parse-xml.c | 113 |
1 files changed, 69 insertions, 44 deletions
diff --git a/parse-xml.c b/parse-xml.c index 58d446db0..5ac36a152 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); } } |