xml->json translation revisited

This commit is contained in:
Olof hagsand 2016-09-28 21:12:38 +02:00
parent 3443dbd33f
commit 1c061aaf26
2 changed files with 122 additions and 74 deletions

View file

@ -28,7 +28,8 @@
*/ */
int json_parse_str(char *str, cxobj **xt); int json_parse_str(char *str, cxobj **xt);
int xml2json_cbuf(cbuf *cb, cxobj *x, int pretty); int xml2json_cbuf(cbuf *cb, cxobj *x, int pretty);
int xml2json_cbuf_vec(cbuf *cb, cxobj **vec, size_t veclen, int pretty); int xml2json_cbuf_vec(cbuf *cb, cxobj **vec, size_t veclen, int pretty);
int xml2json(FILE *f, cxobj *x, int pretty); int xml2json(FILE *f, cxobj *x, int pretty);
int xml2json_vec(FILE *f, cxobj **vec, size_t veclen, int pretty);
#endif /* _CLIXON_JSON_H */ #endif /* _CLIXON_JSON_H */

View file

@ -139,35 +139,23 @@ enum list_element_type{
}; };
static enum list_element_type static enum list_element_type
list_eval(cxobj *x) list_eval(cxobj *xprev,
cxobj *x,
cxobj *xnext)
{ {
enum list_element_type list = LIST_NO; enum list_element_type list = LIST_NO;
cxobj *xp;
cxobj *xprev=NULL;
cxobj *xnext=NULL;
int i;
int eqprev=0; int eqprev=0;
int eqnext=0; int eqnext=0;
assert(xml_type(x)==CX_ELMNT); assert(xml_type(x)==CX_ELMNT);
if ((xp = xml_parent(x)) == NULL) if (xnext &&
goto done; xml_type(xnext)==CX_ELMNT &&
for (i=0; i<xml_child_nr(xp); i++) strcmp(xml_name(x),xml_name(xnext))==0)
if (x == xml_child_i(xp, i))
break;
assert(i<xml_child_nr(xp));
if (i < xml_child_nr(xp)-1){
xnext = xml_child_i(xp, i+1);
if (xml_type(xnext)==CX_ELMNT &&
strcmp(xml_name(x),xml_name(xnext))==0)
eqnext++; eqnext++;
} if (xprev &&
if (i){ xml_type(xprev)==CX_ELMNT &&
xprev = xml_child_i(xp, i-1); strcmp(xml_name(x),xml_name(xprev))==0)
if (xml_type(xprev)==CX_ELMNT && eqprev++;
strcmp(xml_name(x),xml_name(xprev))==0)
eqprev++;
}
if (eqprev && eqnext) if (eqprev && eqnext)
list = LIST_MIDDLE; list = LIST_MIDDLE;
else if (eqprev) else if (eqprev)
@ -176,7 +164,7 @@ list_eval(cxobj *x)
list = LIST_FIRST; list = LIST_FIRST;
else else
list = LIST_NO; list = LIST_NO;
done: // done:
return list; return list;
} }
@ -188,7 +176,9 @@ list_eval(cxobj *x)
*/ */
static int static int
xml2json1_cbuf(cbuf *cb, xml2json1_cbuf(cbuf *cb,
cxobj *xprev,
cxobj *x, cxobj *x,
cxobj *xnext,
int level, int level,
int pretty) int pretty)
{ {
@ -205,25 +195,29 @@ xml2json1_cbuf(cbuf *cb,
cprintf(cb, "null"); cprintf(cb, "null");
break; break;
case CX_ELMNT: case CX_ELMNT:
list = list_eval(x); list = list_eval(xprev, x, xnext);
switch (list){ switch (list){
case LIST_NO: case LIST_NO:
cprintf(cb, "%*s\"%s\": ", cprintf(cb, "%*s\"%s\": ",
pretty?(level*JSON_INDENT):0, "", pretty?(level*JSON_INDENT):0, "",
xml_name(x)); xml_name(x));
if (!tleaf(x)) if (!tleaf(x)){
cprintf(cb, "{%s", if (xml_child_nr(x))
pretty?"\n":""); cprintf(cb, "{%s",
pretty?"\n":"");
else
cprintf(cb, "null");
}
break; break;
case LIST_FIRST: case LIST_FIRST:
cprintf(cb, "%*s\"%s\": [%s", cprintf(cb, "%*s\"%s\": [%s%*s",
pretty?(level*JSON_INDENT):0, "", pretty?(level*JSON_INDENT):0, "",
xml_name(x), xml_name(x),
pretty?"\n":""); pretty?"\n":"",
pretty?((level+1)*JSON_INDENT):0, "");
level++;
if (!tleaf(x)){ if (!tleaf(x)){
level++; cprintf(cb, "{%s",
cprintf(cb, "%*s{%s",
pretty?(level*JSON_INDENT):0, "",
pretty?"\n":""); pretty?"\n":"");
} }
break; break;
@ -233,38 +227,51 @@ xml2json1_cbuf(cbuf *cb,
cprintf(cb, "%*s", cprintf(cb, "%*s",
pretty?(level*JSON_INDENT):0, ""); pretty?(level*JSON_INDENT):0, "");
if (!tleaf(x)) if (!tleaf(x))
cprintf(cb, "{%s", cprintf(cb, "{ %s", pretty?"\n":"");
pretty?"\n":"");
break; break;
default: default:
break; break;
} }
for (i=0; i<xml_child_nr(x); i++){ for (i=0; i<xml_child_nr(x); i++){
xc = xml_child_i(x, i); xc = xml_child_i(x, i);
if (xml2json1_cbuf(cb, xc, level+1, pretty) < 0) if (xml2json1_cbuf(cb,
i?xml_child_i(x,i-1):NULL,
xc,
xml_child_i(x, i+1),
level+1, pretty) < 0)
goto done; goto done;
if (i<xml_child_nr(x)-1){ if (i<xml_child_nr(x)-1){
cprintf(cb, ","); cprintf(cb, ",");
cprintf(cb, "%s", pretty?"\n":""); if (pretty)
cprintf(cb, "\n");
} }
} }
switch (list){ switch (list){
case LIST_NO: case LIST_NO:
if (!tleaf(x)){ if (!tleaf(x)){
if (pretty) if (xml_child_nr(x)){
cprintf(cb, "%*s}\n", if (pretty)
(level*JSON_INDENT), ""); cprintf(cb, "\n%*s}",
else (level*JSON_INDENT), "");
cprintf(cb, "}"); else
cprintf(cb, "}");
}
}
break;
case LIST_FIRST:
if (!tleaf(x)){
cprintf(cb, "%s%*s}",
pretty?"\n":"",
pretty?(level*JSON_INDENT):0, "");
} }
break; break;
case LIST_MIDDLE: case LIST_MIDDLE:
case LIST_FIRST: if (!tleaf(x))
if (pretty) cprintf(cb, "%s%*s}%s%*s",
cprintf(cb, "\n%*s}", pretty?"\n":"",
(level*JSON_INDENT), ""); pretty?(level*JSON_INDENT):0, "",
else pretty?"\n":"",
cprintf(cb, "}"); pretty?(level*JSON_INDENT):0, "");
break; break;
case LIST_LAST: case LIST_LAST:
if (!tleaf(x)){ if (!tleaf(x)){
@ -275,9 +282,11 @@ xml2json1_cbuf(cbuf *cb,
cprintf(cb, "}"); cprintf(cb, "}");
level--; level--;
} }
cprintf(cb, "%*s]%s", else
pretty?(level*JSON_INDENT):0,"", if (pretty)
pretty?"\n":""); cprintf(cb, "\n");
cprintf(cb, "%*s]",
pretty?((level-1)*JSON_INDENT):0,"");
break; break;
default: default:
break; break;
@ -317,14 +326,20 @@ xml2json_cbuf(cbuf *cb,
int retval = 1; int retval = 1;
int level = 0; int level = 0;
cprintf(cb, "%*s{%s", if (pretty)
pretty?(level*JSON_INDENT):0,"", cprintf(cb, "%*s{\n", level*JSON_INDENT,"");
pretty?"\n":""); else
if (xml2json1_cbuf(cb, x, level+1, pretty) < 0) cprintf(cb, "{");
if (xml2json1_cbuf(cb,
NULL,
x,
NULL,
level+1, pretty) < 0)
goto done; goto done;
cprintf(cb, "%*s}%s", if (pretty)
pretty?(level*JSON_INDENT):0,"", cprintf(cb, "\n%*s}\n", level*JSON_INDENT,"");
pretty?"\n":""); else
cprintf(cb, "}");
retval = 0; retval = 0;
done: done:
return retval; return retval;
@ -339,32 +354,41 @@ xml2json_cbuf_vec(cbuf *cb,
size_t veclen, size_t veclen,
int pretty) int pretty)
{ {
int retval = 1; int retval = -1;
int level = 0; int level = 0;
int i; int i;
cxobj *xc; cxobj *xc;
cprintf(cb, "%*s{%s", if (pretty)
pretty?(level*JSON_INDENT):0,"", cprintf(cb, "%*s[\n",
pretty?"\n":""); level*JSON_INDENT,"");
else
cprintf(cb, "[");
level++;
for (i=0; i<veclen; i++){ for (i=0; i<veclen; i++){
xc = vec[i]; xc = vec[i];
if (xml2json1_cbuf(cb, xc, level, pretty) < 0) if (xml2json1_cbuf(cb,
i?vec[i-1]:NULL,
xc,
i<veclen-1?vec[i+1]:NULL,
level, pretty) < 0)
goto done; goto done;
if (i<veclen-1){ if (i<veclen-1){
if (xml_type(xc)==CX_BODY) cprintf(cb, ",");
cprintf(cb, "},{"); if (pretty)
else cprintf(cb, "\n");
cprintf(cb, ",");
cprintf(cb, "%s", pretty?"\n":"");
} }
} }
cprintf(cb, "%*s}%s", level--;
pretty?(level*JSON_INDENT):0,"", if (pretty)
pretty?"\n":""); cprintf(cb, "\n%*s]\n",
level*JSON_INDENT,"");
else
cprintf(cb, "]");
retval = 0; retval = 0;
done: done:
return retval; return retval;
} }
/*! Translate from xml tree to JSON and print to file /*! Translate from xml tree to JSON and print to file
@ -381,9 +405,9 @@ xml2json_cbuf_vec(cbuf *cb,
* @endcode * @endcode
*/ */
int int
xml2json(FILE *f, xml2json(FILE *f,
cxobj *x, cxobj *x,
int pretty) int pretty)
{ {
int retval = 1; int retval = 1;
cbuf *cb = NULL; cbuf *cb = NULL;
@ -402,6 +426,29 @@ xml2json(FILE *f,
return retval; return retval;
} }
int
xml2json_vec(FILE *f,
cxobj **vec,
size_t veclen,
int pretty)
{
int retval = 1;
cbuf *cb = NULL;
if ((cb = cbuf_new()) ==NULL){
clicon_err(OE_XML, errno, "cbuf_new");
goto done;
}
if (xml2json_cbuf_vec(cb, vec, veclen, pretty) < 0)
goto done;
fprintf(f, "%s", cbuf_get(cb));
retval = 0;
done:
if (cb)
cbuf_free(cb);
return retval;
}
/*! Parse a string containing JSON and return an XML tree /*! Parse a string containing JSON and return an XML tree
* @param[in] str Input string containing JSON * @param[in] str Input string containing JSON
* @param[in] name Log string, typically filename * @param[in] name Log string, typically filename