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>
This commit is contained in:
Linus Torvalds 2011-09-01 11:22:05 -07:00
parent 4350a75b94
commit da4edbcce8

View file

@ -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);
}
}