json list->array
This commit is contained in:
parent
a0b7d28bd1
commit
831ab1be30
1 changed files with 67 additions and 50 deletions
|
|
@ -19,7 +19,8 @@
|
||||||
<http://www.gnu.org/licenses/>.
|
<http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
* JSON support functions.
|
* JSON support functions.
|
||||||
|
* JSON syntax is according to:
|
||||||
|
* http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
@ -46,12 +47,17 @@
|
||||||
|
|
||||||
#define JSON_INDENT 2 /* maybe we should set this programmatically? */
|
#define JSON_INDENT 2 /* maybe we should set this programmatically? */
|
||||||
|
|
||||||
enum list_element_type{
|
/* Let xml2json_cbuf_vec() return json array: [a,b].
|
||||||
NO_LIST=0,
|
ALternative is to create a pseudo-object and return that: {top:{a,b}}
|
||||||
FIRST_LIST,
|
*/
|
||||||
MIDDLE_LIST,
|
#define VEC_ARRAY 1
|
||||||
LAST_LIST,
|
|
||||||
BODY_LIST
|
enum array_element_type{
|
||||||
|
NO_ARRAY=0,
|
||||||
|
FIRST_ARRAY,
|
||||||
|
MIDDLE_ARRAY,
|
||||||
|
LAST_ARRAY,
|
||||||
|
BODY_ARRAY
|
||||||
};
|
};
|
||||||
|
|
||||||
enum childtype{
|
enum childtype{
|
||||||
|
|
@ -99,39 +105,39 @@ childtype2str(enum childtype lt)
|
||||||
}
|
}
|
||||||
|
|
||||||
static char*
|
static char*
|
||||||
listtype2str(enum list_element_type lt)
|
arraytype2str(enum array_element_type lt)
|
||||||
{
|
{
|
||||||
switch(lt){
|
switch(lt){
|
||||||
case NO_LIST:
|
case NO_ARRAY:
|
||||||
return "no";
|
return "no";
|
||||||
break;
|
break;
|
||||||
case FIRST_LIST:
|
case FIRST_ARRAY:
|
||||||
return "first";
|
return "first";
|
||||||
break;
|
break;
|
||||||
case MIDDLE_LIST:
|
case MIDDLE_ARRAY:
|
||||||
return "middle";
|
return "middle";
|
||||||
break;
|
break;
|
||||||
case LAST_LIST:
|
case LAST_ARRAY:
|
||||||
return "last";
|
return "last";
|
||||||
break;
|
break;
|
||||||
case BODY_LIST:
|
case BODY_ARRAY:
|
||||||
return "body";
|
return "body";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum list_element_type
|
static enum array_element_type
|
||||||
list_eval(cxobj *xprev,
|
array_eval(cxobj *xprev,
|
||||||
cxobj *x,
|
cxobj *x,
|
||||||
cxobj *xnext)
|
cxobj *xnext)
|
||||||
{
|
{
|
||||||
enum list_element_type list = NO_LIST;
|
enum array_element_type array = NO_ARRAY;
|
||||||
int eqprev=0;
|
int eqprev=0;
|
||||||
int eqnext=0;
|
int eqnext=0;
|
||||||
|
|
||||||
if (xml_type(x)!=CX_ELMNT){
|
if (xml_type(x)!=CX_ELMNT){
|
||||||
list=BODY_LIST;
|
array=BODY_ARRAY;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (xnext &&
|
if (xnext &&
|
||||||
|
|
@ -143,29 +149,29 @@ list_eval(cxobj *xprev,
|
||||||
strcmp(xml_name(x),xml_name(xprev))==0)
|
strcmp(xml_name(x),xml_name(xprev))==0)
|
||||||
eqprev++;
|
eqprev++;
|
||||||
if (eqprev && eqnext)
|
if (eqprev && eqnext)
|
||||||
list = MIDDLE_LIST;
|
array = MIDDLE_ARRAY;
|
||||||
else if (eqprev)
|
else if (eqprev)
|
||||||
list = LAST_LIST;
|
array = LAST_ARRAY;
|
||||||
else if (eqnext)
|
else if (eqnext)
|
||||||
list = FIRST_LIST;
|
array = FIRST_ARRAY;
|
||||||
else
|
else
|
||||||
list = NO_LIST;
|
array = NO_ARRAY;
|
||||||
done:
|
done:
|
||||||
return list;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Do the actual work of translating XML to JSON
|
/*! Do the actual work of translating XML to JSON
|
||||||
* @param[out] cb Cligen text buffer containing json on exit
|
* @param[out] cb Cligen text buffer containing json on exit
|
||||||
* @param[in] x XML tree structure containing XML to translate
|
* @param[in] x XML tree structure containing XML to translate
|
||||||
* @param[in] listtype Does x occur in a list (of its parent) and how?
|
* @param[in] arraytype Does x occur in a array (of its parent) and how?
|
||||||
* @param[in] level Indentation level
|
* @param[in] level Indentation level
|
||||||
* @param[in] pretty Pretty-print output (2 means debug)
|
* @param[in] pretty Pretty-print output (2 means debug)
|
||||||
*
|
*
|
||||||
* The following matrix explains how the mapping is done.
|
* The following matrix explains how the mapping is done.
|
||||||
* You need to understand what listtype means (no/first/middle/last)
|
* You need to understand what arraytype means (no/first/middle/last)
|
||||||
* and what childtype is (null,body,any)
|
* and what childtype is (null,body,any)
|
||||||
+---------+--------------+--------------+--------------+
|
+---------+--------------+--------------+--------------+
|
||||||
|list,leaf| null | body | any |
|
|array,leaf| null | body | any |
|
||||||
+---------+--------------+--------------+--------------+
|
+---------+--------------+--------------+--------------+
|
||||||
|no | <a/> |<a>1</a> |<a><b/></a> |
|
|no | <a/> |<a>1</a> |<a><b/></a> |
|
||||||
| | | | |
|
| | | | |
|
||||||
|
|
@ -191,7 +197,7 @@ list_eval(cxobj *xprev,
|
||||||
static int
|
static int
|
||||||
xml2json1_cbuf(cbuf *cb,
|
xml2json1_cbuf(cbuf *cb,
|
||||||
cxobj *x,
|
cxobj *x,
|
||||||
enum list_element_type listtype,
|
enum array_element_type arraytype,
|
||||||
int level,
|
int level,
|
||||||
int pretty)
|
int pretty)
|
||||||
{
|
{
|
||||||
|
|
@ -202,15 +208,15 @@ xml2json1_cbuf(cbuf *cb,
|
||||||
|
|
||||||
childt = childtype(x);
|
childt = childtype(x);
|
||||||
if (pretty==2)
|
if (pretty==2)
|
||||||
cprintf(cb, "#%s_list, %s_child ",
|
cprintf(cb, "#%s_array, %s_child ",
|
||||||
listtype2str(listtype),
|
arraytype2str(arraytype),
|
||||||
childtype2str(childt));
|
childtype2str(childt));
|
||||||
switch(listtype){
|
switch(arraytype){
|
||||||
case BODY_LIST:
|
case BODY_ARRAY:
|
||||||
assert(xml_value(x));
|
assert(xml_value(x));
|
||||||
cprintf(cb, "\"%s\"", xml_value(x));
|
cprintf(cb, "\"%s\"", xml_value(x));
|
||||||
break;
|
break;
|
||||||
case NO_LIST:
|
case NO_ARRAY:
|
||||||
cprintf(cb, "%*s\"%s\": ",
|
cprintf(cb, "%*s\"%s\": ",
|
||||||
pretty?(level*JSON_INDENT):0, "",
|
pretty?(level*JSON_INDENT):0, "",
|
||||||
xml_name(x));
|
xml_name(x));
|
||||||
|
|
@ -227,7 +233,7 @@ xml2json1_cbuf(cbuf *cb,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FIRST_LIST:
|
case FIRST_ARRAY:
|
||||||
cprintf(cb, "%*s\"%s\": ",
|
cprintf(cb, "%*s\"%s\": ",
|
||||||
pretty?(level*JSON_INDENT):0, "",
|
pretty?(level*JSON_INDENT):0, "",
|
||||||
xml_name(x));
|
xml_name(x));
|
||||||
|
|
@ -248,8 +254,8 @@ xml2json1_cbuf(cbuf *cb,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MIDDLE_LIST:
|
case MIDDLE_ARRAY:
|
||||||
case LAST_LIST:
|
case LAST_ARRAY:
|
||||||
level++;
|
level++;
|
||||||
cprintf(cb, "%*s",
|
cprintf(cb, "%*s",
|
||||||
pretty?(level*JSON_INDENT):0, "");
|
pretty?(level*JSON_INDENT):0, "");
|
||||||
|
|
@ -270,23 +276,23 @@ xml2json1_cbuf(cbuf *cb,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
for (i=0; i<xml_child_nr(x); i++){
|
for (i=0; i<xml_child_nr(x); i++){
|
||||||
enum list_element_type xc_listtype;
|
enum array_element_type xc_arraytype;
|
||||||
xc = xml_child_i(x, i);
|
xc = xml_child_i(x, i);
|
||||||
xc_listtype = list_eval(i?xml_child_i(x,i-1):NULL,
|
xc_arraytype = array_eval(i?xml_child_i(x,i-1):NULL,
|
||||||
xc,
|
xc,
|
||||||
xml_child_i(x, i+1));
|
xml_child_i(x, i+1));
|
||||||
if (xml2json1_cbuf(cb,
|
if (xml2json1_cbuf(cb,
|
||||||
xc,
|
xc,
|
||||||
xc_listtype,
|
xc_arraytype,
|
||||||
level+1, pretty) < 0)
|
level+1, pretty) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (i<xml_child_nr(x)-1)
|
if (i<xml_child_nr(x)-1)
|
||||||
cprintf(cb, ",%s", pretty?"\n":"");
|
cprintf(cb, ",%s", pretty?"\n":"");
|
||||||
}
|
}
|
||||||
switch (listtype){
|
switch (arraytype){
|
||||||
case BODY_LIST:
|
case BODY_ARRAY:
|
||||||
break;
|
break;
|
||||||
case NO_LIST:
|
case NO_ARRAY:
|
||||||
switch (childt){
|
switch (childt){
|
||||||
case NULL_CHILD:
|
case NULL_CHILD:
|
||||||
case BODY_CHILD:
|
case BODY_CHILD:
|
||||||
|
|
@ -301,8 +307,8 @@ xml2json1_cbuf(cbuf *cb,
|
||||||
}
|
}
|
||||||
level--;
|
level--;
|
||||||
break;
|
break;
|
||||||
case FIRST_LIST:
|
case FIRST_ARRAY:
|
||||||
case MIDDLE_LIST:
|
case MIDDLE_ARRAY:
|
||||||
switch (childt){
|
switch (childt){
|
||||||
case NULL_CHILD:
|
case NULL_CHILD:
|
||||||
case BODY_CHILD:
|
case BODY_CHILD:
|
||||||
|
|
@ -317,7 +323,7 @@ xml2json1_cbuf(cbuf *cb,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case LAST_LIST:
|
case LAST_ARRAY:
|
||||||
switch (childt){
|
switch (childt){
|
||||||
case NULL_CHILD:
|
case NULL_CHILD:
|
||||||
case BODY_CHILD:
|
case BODY_CHILD:
|
||||||
|
|
@ -376,7 +382,7 @@ xml2json_cbuf(cbuf *cb,
|
||||||
cprintf(cb, "{");
|
cprintf(cb, "{");
|
||||||
if (xml2json1_cbuf(cb,
|
if (xml2json1_cbuf(cb,
|
||||||
x,
|
x,
|
||||||
NO_LIST,
|
NO_ARRAY,
|
||||||
level+1, pretty) < 0)
|
level+1, pretty) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (pretty)
|
if (pretty)
|
||||||
|
|
@ -401,26 +407,31 @@ xml2json_cbuf_vec(cbuf *cb,
|
||||||
int level = 0;
|
int level = 0;
|
||||||
int i;
|
int i;
|
||||||
cxobj *xc;
|
cxobj *xc;
|
||||||
enum list_element_type listtype;
|
enum array_element_type arraytype;
|
||||||
|
|
||||||
|
#ifdef VEC_ARRAY
|
||||||
|
cprintf(cb, "[%s", pretty?"\n":" ");
|
||||||
|
level++;
|
||||||
|
#else /* pseudo object */
|
||||||
/* Note: We add a pseudo-object on top of the vector.
|
/* Note: We add a pseudo-object on top of the vector.
|
||||||
* This object is list_element_type == NO_LIST in xml2json1_cbuf
|
* This object is array_element_type == NO_ARRAY in xml2json1_cbuf
|
||||||
* and child_type == ANY_CHILD
|
* and child_type == ANY_CHILD
|
||||||
*/
|
*/
|
||||||
cprintf(cb, "{%s",
|
cprintf(cb, "{%s",
|
||||||
pretty?"\n":" ");
|
pretty?"\n":" ");
|
||||||
level++;
|
level++;
|
||||||
cprintf(cb, "%*s\"top\": ", /* NO_LIST */
|
cprintf(cb, "%*s\"top\": ", /* NO_ARRAY */
|
||||||
pretty?(level*JSON_INDENT):0, "");
|
pretty?(level*JSON_INDENT):0, "");
|
||||||
cprintf(cb, "{%s", pretty?"\n":""); /* ANY_CHILD */
|
cprintf(cb, "{%s", pretty?"\n":""); /* ANY_CHILD */
|
||||||
|
#endif
|
||||||
for (i=0; i<veclen; i++){
|
for (i=0; i<veclen; i++){
|
||||||
xc = vec[i];
|
xc = vec[i];
|
||||||
listtype = list_eval(i?vec[i-1]:NULL,
|
arraytype = array_eval(i?vec[i-1]:NULL,
|
||||||
xc,
|
xc,
|
||||||
i<veclen-1?vec[i+1]:NULL);
|
i<veclen-1?vec[i+1]:NULL);
|
||||||
if (xml2json1_cbuf(cb,
|
if (xml2json1_cbuf(cb,
|
||||||
xc,
|
xc,
|
||||||
listtype,
|
arraytype,
|
||||||
level, pretty) < 0)
|
level, pretty) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (i<veclen-1){
|
if (i<veclen-1){
|
||||||
|
|
@ -430,12 +441,18 @@ xml2json_cbuf_vec(cbuf *cb,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
level--;
|
level--;
|
||||||
|
#ifdef VEC_ARRAY
|
||||||
|
cprintf(cb, "%s]%s",
|
||||||
|
pretty?"\n":"",
|
||||||
|
pretty?"\n":""); /* top object */
|
||||||
|
#else /* pseudo object */
|
||||||
cprintf(cb, "%s%*s}",
|
cprintf(cb, "%s%*s}",
|
||||||
pretty?"\n":"",
|
pretty?"\n":"",
|
||||||
pretty?(level*JSON_INDENT):0, "");
|
pretty?(level*JSON_INDENT):0, "");
|
||||||
cprintf(cb, "%s}%s",
|
cprintf(cb, "%s}%s",
|
||||||
pretty?"\n":"",
|
pretty?"\n":"",
|
||||||
pretty?"\n":""); /* top object */
|
pretty?"\n":""); /* top object */
|
||||||
|
#endif
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
return retval;
|
return retval;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue