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

@ -30,5 +30,6 @@ int json_parse_str(char *str, cxobj **xt);
int xml2json_cbuf(cbuf *cb, cxobj *x, 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_vec(FILE *f, cxobj **vec, size_t veclen, int pretty);
#endif /* _CLIXON_JSON_H */

View file

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