xml2json again
This commit is contained in:
parent
1c061aaf26
commit
a0b7d28bd1
1 changed files with 271 additions and 220 deletions
|
|
@ -18,76 +18,8 @@
|
||||||
along with CLIXON; see the file LICENSE. If not, see
|
along with CLIXON; see the file LICENSE. If not, see
|
||||||
<http://www.gnu.org/licenses/>.
|
<http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
* For unit testing compile with -_MAIN:
|
|
||||||
*
|
|
||||||
* JSON support functions.
|
* JSON support functions.
|
||||||
|
|
||||||
curl -G http://localhost/api/data/sender/userid=a4315f60-e890-4f8f-9a0b-eb53d4da2d3a
|
|
||||||
|
|
||||||
[{
|
|
||||||
"sender": {
|
|
||||||
"name": "dk-ore",
|
|
||||||
"userid": "a4315f60-e890-4f8f-9a0b-eb53d4da2d3a",
|
|
||||||
"ipv4_daddr": "109.105.110.78",
|
|
||||||
"template": "nordunet",
|
|
||||||
"version": "0",
|
|
||||||
"description": "Nutanix ORE",
|
|
||||||
"start": "true",
|
|
||||||
"udp_dport": "43713",
|
|
||||||
"debug": "0",
|
|
||||||
"proto": "udp"
|
|
||||||
}
|
|
||||||
|
|
||||||
is translated into this:
|
|
||||||
[
|
|
||||||
{"sender":
|
|
||||||
["name":"dk-ore",
|
|
||||||
"userid":"a4315f60-e890-4f8f-9a0b-eb53d4da2d3a",
|
|
||||||
"ipv4_daddr":"109.105.110.78",
|
|
||||||
"template":"nordunet",
|
|
||||||
"version":"0",
|
|
||||||
"description":"Nutanix ORE",
|
|
||||||
"start":"true",
|
|
||||||
"udp_dport":"43713",
|
|
||||||
"debug":"0",
|
|
||||||
"proto":"udp"}
|
|
||||||
,
|
|
||||||
{"name":"dk-uni",
|
|
||||||
|
|
||||||
|
|
||||||
-------------------------
|
|
||||||
|
|
||||||
<t>
|
|
||||||
<sender>
|
|
||||||
<name>hunerik</name>
|
|
||||||
</sender>
|
|
||||||
<sender>
|
|
||||||
<name>foo</name>
|
|
||||||
</sender>
|
|
||||||
</t>
|
|
||||||
|
|
||||||
{ "t":
|
|
||||||
{
|
|
||||||
"sender": {
|
|
||||||
"name": "hunerik"
|
|
||||||
},
|
|
||||||
"sender": {
|
|
||||||
"name": "foo"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
"t": {
|
|
||||||
"sender": [
|
|
||||||
{ "name": "hunerik" },
|
|
||||||
{ "name": "foo" }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
OK, still something wrong with grafana plots
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
@ -112,42 +44,96 @@ OK, still something wrong with grafana plots
|
||||||
#include "clixon_json.h"
|
#include "clixon_json.h"
|
||||||
#include "clixon_json_parse.h"
|
#include "clixon_json_parse.h"
|
||||||
|
|
||||||
#define JSON_INDENT 3 /* maybe we should set this programmatically? */
|
#define JSON_INDENT 2 /* maybe we should set this programmatically? */
|
||||||
|
|
||||||
/*! x is element and has eactly one child which in turn has none
|
|
||||||
* Clone from clixon_xml_map.c
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
tleaf(cxobj *x)
|
|
||||||
{
|
|
||||||
cxobj *c;
|
|
||||||
|
|
||||||
if (xml_type(x) != CX_ELMNT)
|
|
||||||
return 0;
|
|
||||||
if (xml_child_nr(x) != 1)
|
|
||||||
return 0;
|
|
||||||
c = xml_child_i(x, 0);
|
|
||||||
return (xml_child_nr(c) == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
enum list_element_type{
|
enum list_element_type{
|
||||||
LIST_NO,
|
NO_LIST=0,
|
||||||
LIST_FIRST,
|
FIRST_LIST,
|
||||||
LIST_MIDDLE,
|
MIDDLE_LIST,
|
||||||
LIST_LAST
|
LAST_LIST,
|
||||||
|
BODY_LIST
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum childtype{
|
||||||
|
NULL_CHILD=0, /* eg <a/> no children */
|
||||||
|
BODY_CHILD, /* eg one child which is a body, eg <a>1</a> */
|
||||||
|
ANY_CHILD, /* eg <a><b/></a> or <a><b/><c/></a> */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*! x is element and has exactly one child which in turn has none
|
||||||
|
* Clone from clixon_xml_map.c
|
||||||
|
*/
|
||||||
|
static enum childtype
|
||||||
|
childtype(cxobj *x)
|
||||||
|
{
|
||||||
|
cxobj *xc1; /* the only child of x */
|
||||||
|
|
||||||
|
if (xml_type(x) != CX_ELMNT)
|
||||||
|
return -1; /* n/a */
|
||||||
|
if (xml_child_nr(x) == 0)
|
||||||
|
return NULL_CHILD;
|
||||||
|
if (xml_child_nr(x) > 1)
|
||||||
|
return ANY_CHILD;
|
||||||
|
xc1 = xml_child_i(x, 0); /* From here exactly one child */
|
||||||
|
if (xml_child_nr(xc1) == 0 && xml_type(xc1)==CX_BODY)
|
||||||
|
return BODY_CHILD;
|
||||||
|
else
|
||||||
|
return ANY_CHILD;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char*
|
||||||
|
childtype2str(enum childtype lt)
|
||||||
|
{
|
||||||
|
switch(lt){
|
||||||
|
case NULL_CHILD:
|
||||||
|
return "null";
|
||||||
|
break;
|
||||||
|
case BODY_CHILD:
|
||||||
|
return "body";
|
||||||
|
break;
|
||||||
|
case ANY_CHILD:
|
||||||
|
return "any";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
static char*
|
||||||
|
listtype2str(enum list_element_type lt)
|
||||||
|
{
|
||||||
|
switch(lt){
|
||||||
|
case NO_LIST:
|
||||||
|
return "no";
|
||||||
|
break;
|
||||||
|
case FIRST_LIST:
|
||||||
|
return "first";
|
||||||
|
break;
|
||||||
|
case MIDDLE_LIST:
|
||||||
|
return "middle";
|
||||||
|
break;
|
||||||
|
case LAST_LIST:
|
||||||
|
return "last";
|
||||||
|
break;
|
||||||
|
case BODY_LIST:
|
||||||
|
return "body";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
static enum list_element_type
|
static enum list_element_type
|
||||||
list_eval(cxobj *xprev,
|
list_eval(cxobj *xprev,
|
||||||
cxobj *x,
|
cxobj *x,
|
||||||
cxobj *xnext)
|
cxobj *xnext)
|
||||||
{
|
{
|
||||||
enum list_element_type list = LIST_NO;
|
enum list_element_type list = NO_LIST;
|
||||||
int eqprev=0;
|
int eqprev=0;
|
||||||
int eqnext=0;
|
int eqnext=0;
|
||||||
|
|
||||||
assert(xml_type(x)==CX_ELMNT);
|
if (xml_type(x)!=CX_ELMNT){
|
||||||
|
list=BODY_LIST;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
if (xnext &&
|
if (xnext &&
|
||||||
xml_type(xnext)==CX_ELMNT &&
|
xml_type(xnext)==CX_ELMNT &&
|
||||||
strcmp(xml_name(x),xml_name(xnext))==0)
|
strcmp(xml_name(x),xml_name(xnext))==0)
|
||||||
|
|
@ -157,141 +143,199 @@ 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 = LIST_MIDDLE;
|
list = MIDDLE_LIST;
|
||||||
else if (eqprev)
|
else if (eqprev)
|
||||||
list = LIST_LAST;
|
list = LAST_LIST;
|
||||||
else if (eqnext)
|
else if (eqnext)
|
||||||
list = LIST_FIRST;
|
list = FIRST_LIST;
|
||||||
else
|
else
|
||||||
list = LIST_NO;
|
list = NO_LIST;
|
||||||
// done:
|
done:
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*! Do the actual work of translating XML to JSON
|
||||||
* @param[in] pretty set if the output should be pretty-printed
|
* @param[out] cb Cligen text buffer containing json on exit
|
||||||
* List only if adjacent,
|
* @param[in] x XML tree structure containing XML to translate
|
||||||
* ie <a>1</a><a>2</a><b>3</b> -> {"a":[1,2],"b":3}
|
* @param[in] listtype Does x occur in a list (of its parent) and how?
|
||||||
* ie <a>1</a><b>3</b><a>2</a> -> {"a":1,"b":3,"a":2}
|
* @param[in] level Indentation level
|
||||||
|
* @param[in] pretty Pretty-print output (2 means debug)
|
||||||
|
*
|
||||||
|
* The following matrix explains how the mapping is done.
|
||||||
|
* You need to understand what listtype means (no/first/middle/last)
|
||||||
|
* and what childtype is (null,body,any)
|
||||||
|
+---------+--------------+--------------+--------------+
|
||||||
|
|list,leaf| null | body | any |
|
||||||
|
+---------+--------------+--------------+--------------+
|
||||||
|
|no | <a/> |<a>1</a> |<a><b/></a> |
|
||||||
|
| | | | |
|
||||||
|
| json: |\ta:null |\ta: |\ta:{\n |
|
||||||
|
| | | |\n} |
|
||||||
|
+---------+--------------+--------------+--------------+
|
||||||
|
|first |<a/><a.. |<a>1</a><a.. |<a><b/></a><a.|
|
||||||
|
| | | | |
|
||||||
|
| json: |\ta:[\n\tnull |\ta:[\n\t |\ta:[\n\t{\n |
|
||||||
|
| | | |\n\t} |
|
||||||
|
+---------+--------------+--------------+--------------+
|
||||||
|
|middle |..a><a/><a.. |.a><a>1</a><a.| |
|
||||||
|
| | | | |
|
||||||
|
| json: |\tnull |\t |\t{a |
|
||||||
|
| | | |\n\t} |
|
||||||
|
+---------+--------------+--------------+--------------+
|
||||||
|
|last |..a></a> |..a><a>1</a> | |
|
||||||
|
| | | | |
|
||||||
|
| json: |\tnull |\t |\t{a |
|
||||||
|
| |\n\t] |\n\t] |\n\t}\t] |
|
||||||
|
+---------+--------------+--------------+--------------+
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
xml2json1_cbuf(cbuf *cb,
|
xml2json1_cbuf(cbuf *cb,
|
||||||
cxobj *xprev,
|
|
||||||
cxobj *x,
|
cxobj *x,
|
||||||
cxobj *xnext,
|
enum list_element_type listtype,
|
||||||
int level,
|
int level,
|
||||||
int pretty)
|
int pretty)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
int i;
|
int i;
|
||||||
cxobj *xc;
|
cxobj *xc;
|
||||||
enum list_element_type list;
|
enum childtype childt;
|
||||||
|
|
||||||
switch(xml_type(x)){
|
childt = childtype(x);
|
||||||
case CX_BODY:
|
if (pretty==2)
|
||||||
if (xml_value(x))
|
cprintf(cb, "#%s_list, %s_child ",
|
||||||
|
listtype2str(listtype),
|
||||||
|
childtype2str(childt));
|
||||||
|
switch(listtype){
|
||||||
|
case BODY_LIST:
|
||||||
|
assert(xml_value(x));
|
||||||
cprintf(cb, "\"%s\"", xml_value(x));
|
cprintf(cb, "\"%s\"", xml_value(x));
|
||||||
else
|
|
||||||
cprintf(cb, "null");
|
|
||||||
break;
|
break;
|
||||||
case CX_ELMNT:
|
case NO_LIST:
|
||||||
list = list_eval(xprev, x, xnext);
|
|
||||||
switch (list){
|
|
||||||
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)){
|
switch (childt){
|
||||||
if (xml_child_nr(x))
|
case NULL_CHILD:
|
||||||
cprintf(cb, "{%s",
|
|
||||||
pretty?"\n":"");
|
|
||||||
else
|
|
||||||
cprintf(cb, "null");
|
cprintf(cb, "null");
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case LIST_FIRST:
|
case BODY_CHILD:
|
||||||
cprintf(cb, "%*s\"%s\": [%s%*s",
|
|
||||||
pretty?(level*JSON_INDENT):0, "",
|
|
||||||
xml_name(x),
|
|
||||||
pretty?"\n":"",
|
|
||||||
pretty?((level+1)*JSON_INDENT):0, "");
|
|
||||||
level++;
|
|
||||||
if (!tleaf(x)){
|
|
||||||
cprintf(cb, "{%s",
|
|
||||||
pretty?"\n":"");
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case LIST_MIDDLE:
|
case ANY_CHILD:
|
||||||
case LIST_LAST:
|
|
||||||
level++;
|
|
||||||
cprintf(cb, "%*s",
|
|
||||||
pretty?(level*JSON_INDENT):0, "");
|
|
||||||
if (!tleaf(x))
|
|
||||||
cprintf(cb, "{%s", pretty?"\n":"");
|
cprintf(cb, "{%s", pretty?"\n":"");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
for (i=0; i<xml_child_nr(x); i++){
|
|
||||||
xc = xml_child_i(x, i);
|
|
||||||
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, ",");
|
|
||||||
if (pretty)
|
|
||||||
cprintf(cb, "\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
switch (list){
|
|
||||||
case LIST_NO:
|
|
||||||
if (!tleaf(x)){
|
|
||||||
if (xml_child_nr(x)){
|
|
||||||
if (pretty)
|
|
||||||
cprintf(cb, "\n%*s}",
|
|
||||||
(level*JSON_INDENT), "");
|
|
||||||
else
|
|
||||||
cprintf(cb, "}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case LIST_FIRST:
|
case FIRST_LIST:
|
||||||
if (!tleaf(x)){
|
cprintf(cb, "%*s\"%s\": ",
|
||||||
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?(level*JSON_INDENT):0, "",
|
||||||
|
xml_name(x));
|
||||||
|
level++;
|
||||||
|
cprintf(cb, "[%s%*s",
|
||||||
pretty?"\n":"",
|
pretty?"\n":"",
|
||||||
pretty?(level*JSON_INDENT):0, "");
|
pretty?(level*JSON_INDENT):0, "");
|
||||||
|
switch (childt){
|
||||||
|
case NULL_CHILD:
|
||||||
|
cprintf(cb, "null");
|
||||||
break;
|
break;
|
||||||
case LIST_LAST:
|
case BODY_CHILD:
|
||||||
if (!tleaf(x)){
|
break;
|
||||||
if (pretty)
|
case ANY_CHILD:
|
||||||
cprintf(cb, "\n%*s}\n",
|
cprintf(cb, "{%s", pretty?"\n":"");
|
||||||
(level*JSON_INDENT), "");
|
|
||||||
else
|
|
||||||
cprintf(cb, "}");
|
|
||||||
level--;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
if (pretty)
|
|
||||||
cprintf(cb, "\n");
|
|
||||||
cprintf(cb, "%*s]",
|
|
||||||
pretty?((level-1)*JSON_INDENT):0,"");
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case MIDDLE_LIST:
|
||||||
|
case LAST_LIST:
|
||||||
|
level++;
|
||||||
|
cprintf(cb, "%*s",
|
||||||
|
pretty?(level*JSON_INDENT):0, "");
|
||||||
|
switch (childt){
|
||||||
|
case NULL_CHILD:
|
||||||
|
cprintf(cb, "null");
|
||||||
|
break;
|
||||||
|
case BODY_CHILD:
|
||||||
|
break;
|
||||||
|
case ANY_CHILD:
|
||||||
|
cprintf(cb, "{ %s", pretty?"\n":"");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (i=0; i<xml_child_nr(x); i++){
|
||||||
|
enum list_element_type xc_listtype;
|
||||||
|
xc = xml_child_i(x, i);
|
||||||
|
xc_listtype = list_eval(i?xml_child_i(x,i-1):NULL,
|
||||||
|
xc,
|
||||||
|
xml_child_i(x, i+1));
|
||||||
|
if (xml2json1_cbuf(cb,
|
||||||
|
xc,
|
||||||
|
xc_listtype,
|
||||||
|
level+1, pretty) < 0)
|
||||||
|
goto done;
|
||||||
|
if (i<xml_child_nr(x)-1)
|
||||||
|
cprintf(cb, ",%s", pretty?"\n":"");
|
||||||
|
}
|
||||||
|
switch (listtype){
|
||||||
|
case BODY_LIST:
|
||||||
|
break;
|
||||||
|
case NO_LIST:
|
||||||
|
switch (childt){
|
||||||
|
case NULL_CHILD:
|
||||||
|
case BODY_CHILD:
|
||||||
|
break;
|
||||||
|
case ANY_CHILD:
|
||||||
|
cprintf(cb, "%s%*s}",
|
||||||
|
pretty?"\n":"",
|
||||||
|
pretty?(level*JSON_INDENT):0, "");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
level--;
|
||||||
|
break;
|
||||||
|
case FIRST_LIST:
|
||||||
|
case MIDDLE_LIST:
|
||||||
|
switch (childt){
|
||||||
|
case NULL_CHILD:
|
||||||
|
case BODY_CHILD:
|
||||||
|
break;
|
||||||
|
case ANY_CHILD:
|
||||||
|
cprintf(cb, "%s%*s}",
|
||||||
|
pretty?"\n":"",
|
||||||
|
pretty?(level*JSON_INDENT):0, "");
|
||||||
|
level--;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LAST_LIST:
|
||||||
|
switch (childt){
|
||||||
|
case NULL_CHILD:
|
||||||
|
case BODY_CHILD:
|
||||||
|
cprintf(cb, "%s",pretty?"\n":"");
|
||||||
|
break;
|
||||||
|
case ANY_CHILD:
|
||||||
|
cprintf(cb, "%s%*s}",
|
||||||
|
pretty?"\n":"",
|
||||||
|
pretty?(level*JSON_INDENT):0, "");
|
||||||
|
cprintf(cb, "%s",pretty?"\n":"");
|
||||||
|
level--;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cprintf(cb, "%*s]",
|
||||||
|
pretty?(level*JSON_INDENT):0,"");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -331,9 +375,8 @@ xml2json_cbuf(cbuf *cb,
|
||||||
else
|
else
|
||||||
cprintf(cb, "{");
|
cprintf(cb, "{");
|
||||||
if (xml2json1_cbuf(cb,
|
if (xml2json1_cbuf(cb,
|
||||||
NULL,
|
|
||||||
x,
|
x,
|
||||||
NULL,
|
NO_LIST,
|
||||||
level+1, pretty) < 0)
|
level+1, pretty) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (pretty)
|
if (pretty)
|
||||||
|
|
@ -345,8 +388,8 @@ xml2json_cbuf(cbuf *cb,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*! Translate a vectro of xml objects to xml by adding a top pseudo-object.
|
||||||
* @note can be a problem with vector since xml2json1_cbuf checks parents
|
* example: <b/><c/> --> <a><b/><c/></a> --> {"a" : {"b" : null,"c" : null}}
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
xml2json_cbuf_vec(cbuf *cb,
|
xml2json_cbuf_vec(cbuf *cb,
|
||||||
|
|
@ -358,19 +401,26 @@ xml2json_cbuf_vec(cbuf *cb,
|
||||||
int level = 0;
|
int level = 0;
|
||||||
int i;
|
int i;
|
||||||
cxobj *xc;
|
cxobj *xc;
|
||||||
|
enum list_element_type listtype;
|
||||||
|
|
||||||
if (pretty)
|
/* Note: We add a pseudo-object on top of the vector.
|
||||||
cprintf(cb, "%*s[\n",
|
* This object is list_element_type == NO_LIST in xml2json1_cbuf
|
||||||
level*JSON_INDENT,"");
|
* and child_type == ANY_CHILD
|
||||||
else
|
*/
|
||||||
cprintf(cb, "[");
|
cprintf(cb, "{%s",
|
||||||
|
pretty?"\n":" ");
|
||||||
level++;
|
level++;
|
||||||
|
cprintf(cb, "%*s\"top\": ", /* NO_LIST */
|
||||||
|
pretty?(level*JSON_INDENT):0, "");
|
||||||
|
cprintf(cb, "{%s", pretty?"\n":""); /* ANY_CHILD */
|
||||||
for (i=0; i<veclen; i++){
|
for (i=0; i<veclen; i++){
|
||||||
xc = vec[i];
|
xc = vec[i];
|
||||||
if (xml2json1_cbuf(cb,
|
listtype = list_eval(i?vec[i-1]:NULL,
|
||||||
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,
|
||||||
|
xc,
|
||||||
|
listtype,
|
||||||
level, pretty) < 0)
|
level, pretty) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (i<veclen-1){
|
if (i<veclen-1){
|
||||||
|
|
@ -380,11 +430,12 @@ xml2json_cbuf_vec(cbuf *cb,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
level--;
|
level--;
|
||||||
if (pretty)
|
cprintf(cb, "%s%*s}",
|
||||||
cprintf(cb, "\n%*s]\n",
|
pretty?"\n":"",
|
||||||
level*JSON_INDENT,"");
|
pretty?(level*JSON_INDENT):0, "");
|
||||||
else
|
cprintf(cb, "%s}%s",
|
||||||
cprintf(cb, "]");
|
pretty?"\n":"",
|
||||||
|
pretty?"\n":""); /* top object */
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
return retval;
|
return retval;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue