Added witddefaults parameter to xml2file and xml2cbuf
This commit is contained in:
parent
dff3b25c34
commit
b3ea6b550d
2 changed files with 349 additions and 104 deletions
|
|
@ -43,10 +43,15 @@
|
||||||
/*
|
/*
|
||||||
* Prototypes
|
* Prototypes
|
||||||
*/
|
*/
|
||||||
|
int clixon_xml2file1(FILE *f, cxobj *xn, int level, int pretty, char *prefix,
|
||||||
|
clicon_output_cb *fn, int skiptop, int autocliext, withdefaults_type wdef);
|
||||||
int clixon_xml2file(FILE *f, cxobj *xn, int level, int pretty, char *prefix, clicon_output_cb *fn, int skiptop, int autocliext);
|
int clixon_xml2file(FILE *f, cxobj *xn, int level, int pretty, char *prefix, clicon_output_cb *fn, int skiptop, int autocliext);
|
||||||
int xml_print(FILE *f, cxobj *xn);
|
int xml_print(FILE *f, cxobj *xn);
|
||||||
int xml_dump(FILE *f, cxobj *x);
|
int xml_dump(FILE *f, cxobj *x);
|
||||||
int clixon_xml2cbuf(cbuf *cb, cxobj *x, int level, int prettyprint, char *prefix, int32_t depth, int skiptop);
|
int clixon_xml2cbuf1(cbuf *cb, cxobj *x, int level, int prettyprint, char *prefix,
|
||||||
|
int32_t depth, int skiptop, withdefaults_type wdef);
|
||||||
|
int clixon_xml2cbuf(cbuf *cb, cxobj *x, int level, int prettyprint, char *prefix, int32_t depth,
|
||||||
|
int skiptop);
|
||||||
int xmltree2cbuf(cbuf *cb, cxobj *x, int level);
|
int xmltree2cbuf(cbuf *cb, cxobj *x, int level);
|
||||||
int clixon_xml_parse_file(FILE *f, yang_bind yb, yang_stmt *yspec, cxobj **xt, cxobj **xerr);
|
int clixon_xml_parse_file(FILE *f, yang_bind yb, yang_stmt *yspec, cxobj **xt, cxobj **xerr);
|
||||||
int clixon_xml_parse_string(const char *str, yang_bind yb, yang_stmt *yspec, cxobj **xt, cxobj **xerr);
|
int clixon_xml_parse_string(const char *str, yang_bind yb, yang_stmt *yspec, cxobj **xt, cxobj **xerr);
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,8 @@
|
||||||
#include "clixon_xml_sort.h"
|
#include "clixon_xml_sort.h"
|
||||||
#include "clixon_xml_nsctx.h"
|
#include "clixon_xml_nsctx.h"
|
||||||
#include "clixon_xml_parse.h"
|
#include "clixon_xml_parse.h"
|
||||||
|
#include "clixon_netconf_lib.h"
|
||||||
|
#include "clixon_xml_default.h"
|
||||||
#include "clixon_xml_io.h"
|
#include "clixon_xml_io.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -88,53 +90,159 @@ static int xml_diff2cbuf(cbuf *cb, cxobj *x0, cxobj *x1, int level, int skiptop)
|
||||||
* XML printing functions. Output a parse tree to file, string cligen buf
|
* XML printing functions. Output a parse tree to file, string cligen buf
|
||||||
*------------------------------------------------------------------------*/
|
*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*! For xml2 output: compute with-defaults: if object should be printed or not
|
||||||
|
*
|
||||||
|
* @param[in] x Clixon xml tree
|
||||||
|
* @param[in] wdef With-defaults parameter, default is WITHDEFAULTS_REPORT_ALL
|
||||||
|
* @param[out] tag If set, use XML tag to mark value (WITHDEFAULTS_REPORT_ALL_TAGGED)
|
||||||
|
* @retval 1 Keep it
|
||||||
|
* @retval 0 Remove it
|
||||||
|
* @retval -1 Error
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
xml2output_wdef(cxobj *x,
|
||||||
|
withdefaults_type wdef,
|
||||||
|
int *tag)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
int keep = 1;
|
||||||
|
cg_var *cv;
|
||||||
|
char *yv = NULL;
|
||||||
|
char *body;
|
||||||
|
cxobj *xc;
|
||||||
|
yang_stmt *y;
|
||||||
|
int ret;
|
||||||
|
int config;
|
||||||
|
|
||||||
|
if ((y = xml_spec(x)) == NULL)
|
||||||
|
goto ok;
|
||||||
|
switch (wdef){
|
||||||
|
case WITHDEFAULTS_EXPLICIT:
|
||||||
|
case WITHDEFAULTS_TRIM:
|
||||||
|
/* inline of xml_defaults_nopresence()
|
||||||
|
and xml_flag_state_default_value()
|
||||||
|
*/
|
||||||
|
switch(yang_keyword_get(y)){
|
||||||
|
case Y_CONTAINER:
|
||||||
|
if (yang_find(y, Y_PRESENCE, NULL) == NULL){
|
||||||
|
keep = 0;
|
||||||
|
/* Loop thru children */
|
||||||
|
xc = NULL;
|
||||||
|
while ((xc = xml_child_each(x, xc, CX_ELMNT)) != NULL) {
|
||||||
|
if ((ret = xml2output_wdef(xc, wdef, NULL)) < 0)
|
||||||
|
goto done;
|
||||||
|
if (ret == 1)
|
||||||
|
keep = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Y_LEAF:
|
||||||
|
config = yang_config_ancestor(y);
|
||||||
|
if (xml_flag(x, XML_FLAG_DEFAULT)) {
|
||||||
|
/* RFC 6243: Any value set by the NETCONF server [eg: state-data] that is not the schema
|
||||||
|
defined default value is also considered explicitly set data.*/
|
||||||
|
if (!config && wdef == WITHDEFAULTS_EXPLICIT)
|
||||||
|
;
|
||||||
|
else
|
||||||
|
keep = 0;
|
||||||
|
}
|
||||||
|
else if (wdef == WITHDEFAULTS_TRIM &&
|
||||||
|
(cv = yang_cv_get(y)) != NULL &&
|
||||||
|
(body = xml_body(x)) != NULL){
|
||||||
|
if ((yv = cv2str_dup(cv)) == NULL)
|
||||||
|
goto done;
|
||||||
|
if (body && strcmp(body, yv) == 0)
|
||||||
|
keep = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WITHDEFAULTS_REPORT_ALL_TAGGED:
|
||||||
|
if (tag && yang_keyword_get(y) == Y_LEAF){
|
||||||
|
if (xml_flag(x, XML_FLAG_DEFAULT))
|
||||||
|
*tag = 1;
|
||||||
|
else if ((cv = yang_cv_get(y)) != NULL &&
|
||||||
|
(body = xml_body(x)) != NULL){
|
||||||
|
if ((yv = cv2str_dup(cv)) == NULL)
|
||||||
|
goto done;
|
||||||
|
if (body && strcmp(body, yv) == 0)
|
||||||
|
*tag = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ok:
|
||||||
|
retval = keep;
|
||||||
|
done:
|
||||||
|
if (yv)
|
||||||
|
free(yv);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Print an XML tree structure to an output stream and encode chars "<>&"
|
/*! Print an XML tree structure to an output stream and encode chars "<>&"
|
||||||
*
|
*
|
||||||
* @param[in] f UNIX output stream
|
* @param[in] f UNIX output stream
|
||||||
* @param[in] xn Clicon xml tree
|
* @param[in] x Clixon xml tree
|
||||||
* @param[in] level How many spaces to insert before each line
|
* @param[in] level How many spaces to insert before each line
|
||||||
* @param[in] pretty Insert \n and spaces to make the xml more readable.
|
* @param[in] pretty Insert \n and spaces to make the xml more readable.
|
||||||
* @param[in] prefix Add string to beginning of each line (if pretty)
|
* @param[in] prefix Add string to beginning of each line (if pretty)
|
||||||
* @param[in] fn Callback to make print function
|
* @param[in] fn Callback to make print function
|
||||||
* @param[in] autocliext How to handle autocli extensions: 0: ignore 1: follow
|
* @param[in] autocliext How to handle autocli extensions: 0: ignore 1: follow
|
||||||
|
* @param[in] wdef With-defaults parameter, default is WITHDEFAULTS_REPORT_ALL
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
* @see clixon_xml2cbuf
|
|
||||||
* One can use clixon_xml2cbuf to get common code, but using fprintf is
|
* One can use clixon_xml2cbuf to get common code, but using fprintf is
|
||||||
* much faster than using cbuf and then printing that,...
|
* much faster than using cbuf and then printing that,...
|
||||||
*
|
* wdef changes the output as follows:
|
||||||
|
* - WITHDEFAULTS_REPORT_ALL - keep as-is
|
||||||
|
* - WITHDEFAULTS_TRIM - remove defaults + equal value, and no-presence
|
||||||
|
* - WITHDEFAULTS_EXPLICIT - remove defaults and no-presence
|
||||||
|
* - WITHDEFAULTS_REPORT_ALL_TAGGED
|
||||||
|
* @see xml2cbuf_recurse same with cbuf
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
xml2file_recurse(FILE *f,
|
xml2file_recurse(FILE *f,
|
||||||
cxobj *x,
|
cxobj *x,
|
||||||
int level,
|
int level,
|
||||||
int pretty,
|
int pretty,
|
||||||
char *prefix,
|
char *prefix,
|
||||||
clicon_output_cb *fn,
|
clicon_output_cb *fn,
|
||||||
int autocliext)
|
int autocliext,
|
||||||
|
withdefaults_type wdef)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
char *name;
|
char *name;
|
||||||
char *namespace;
|
char *namespace;
|
||||||
cxobj *xc;
|
cxobj *xc;
|
||||||
int hasbody;
|
int hasbody;
|
||||||
int haselement;
|
int haselement;
|
||||||
char *val;
|
char *val;
|
||||||
char *encstr = NULL; /* xml encoded string */
|
char *encstr = NULL; /* xml encoded string */
|
||||||
int exist = 0;
|
int exist = 0;
|
||||||
yang_stmt *y;
|
yang_stmt *y;
|
||||||
int level1;
|
int level1;
|
||||||
|
int tag = 0;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (x == NULL)
|
if (x == NULL)
|
||||||
goto ok;
|
goto ok;
|
||||||
level1 = level*PRETTYPRINT_INDENT;
|
level1 = level*PRETTYPRINT_INDENT;
|
||||||
if (prefix)
|
if (prefix)
|
||||||
level1 -= strlen(prefix);
|
level1 -= strlen(prefix);
|
||||||
if (autocliext &&
|
if ((y = xml_spec(x)) != NULL){
|
||||||
(y = xml_spec(x)) != NULL){
|
if (autocliext){
|
||||||
if (yang_extension_value(y, "hide-show", CLIXON_AUTOCLI_NS, &exist, NULL) < 0)
|
if (yang_extension_value(y, "hide-show", CLIXON_AUTOCLI_NS, &exist, NULL) < 0)
|
||||||
|
goto done;
|
||||||
|
if (exist)
|
||||||
|
goto ok;
|
||||||
|
}
|
||||||
|
if ((ret = xml2output_wdef(x, wdef, &tag)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (exist)
|
if (ret == 0)
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
name = xml_name(x);
|
name = xml_name(x);
|
||||||
|
|
@ -160,6 +268,8 @@ xml2file_recurse(FILE *f,
|
||||||
if (namespace)
|
if (namespace)
|
||||||
(*fn)(f, "%s:", namespace);
|
(*fn)(f, "%s:", namespace);
|
||||||
(*fn)(f, "%s", name);
|
(*fn)(f, "%s", name);
|
||||||
|
if (tag) /* If default and WITHDEFAULTS_REPORT_ALL_TAGGED */
|
||||||
|
(*fn)(f, " wd:default=\"true\"");
|
||||||
hasbody = 0;
|
hasbody = 0;
|
||||||
haselement = 0;
|
haselement = 0;
|
||||||
xc = NULL;
|
xc = NULL;
|
||||||
|
|
@ -167,7 +277,7 @@ xml2file_recurse(FILE *f,
|
||||||
while ((xc = xml_child_each(x, xc, -1)) != NULL) {
|
while ((xc = xml_child_each(x, xc, -1)) != NULL) {
|
||||||
switch (xml_type(xc)){
|
switch (xml_type(xc)){
|
||||||
case CX_ATTR:
|
case CX_ATTR:
|
||||||
if (xml2file_recurse(f, xc, level+1, pretty, prefix, fn, autocliext) <0)
|
if (xml2file_recurse(f, xc, level+1, pretty, prefix, fn, autocliext, wdef) <0)
|
||||||
goto done;
|
goto done;
|
||||||
break;
|
break;
|
||||||
case CX_BODY:
|
case CX_BODY:
|
||||||
|
|
@ -188,13 +298,31 @@ xml2file_recurse(FILE *f,
|
||||||
else{
|
else{
|
||||||
(*fn)(f, ">");
|
(*fn)(f, ">");
|
||||||
if (pretty && hasbody == 0){
|
if (pretty && hasbody == 0){
|
||||||
(*fn)(f, "\n");
|
(*fn)(f, "\n");
|
||||||
}
|
}
|
||||||
xc = NULL;
|
xc = NULL;
|
||||||
while ((xc = xml_child_each(x, xc, -1)) != NULL) {
|
while ((xc = xml_child_each(x, xc, -1)) != NULL) {
|
||||||
if (xml_type(xc) != CX_ATTR)
|
cxobj *xa = NULL;
|
||||||
if (xml2file_recurse(f, xc, level+1, pretty, prefix, fn, autocliext) <0)
|
char *ns = NULL;
|
||||||
|
|
||||||
|
if (wdef == WITHDEFAULTS_REPORT_ALL_TAGGED &&
|
||||||
|
y == NULL &&
|
||||||
|
xml_spec(xc) != NULL){
|
||||||
|
if (xml2ns(xc, IETF_NETCONF_WITH_DEFAULTS_ATTR_PREFIX, &ns) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
if (ns == NULL){
|
||||||
|
if (xmlns_set(xc, IETF_NETCONF_WITH_DEFAULTS_ATTR_PREFIX, IETF_NETCONF_WITH_DEFAULTS_ATTR_NAMESPACE) < 0)
|
||||||
|
goto done;
|
||||||
|
xa = xml_find_type(xc, IETF_NETCONF_WITH_DEFAULTS_ATTR_PREFIX, IETF_NETCONF_WITH_DEFAULTS_ATTR_NAMESPACE, CX_ATTR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (xml_type(xc) != CX_ATTR)
|
||||||
|
if (xml2file_recurse(f, xc, level+1, pretty, prefix, fn, autocliext, wdef) <0)
|
||||||
|
goto done;
|
||||||
|
if (xa){
|
||||||
|
if (xml_purge(xa) < 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (pretty && hasbody==0){
|
if (pretty && hasbody==0){
|
||||||
if (pretty && prefix)
|
if (pretty && prefix)
|
||||||
|
|
@ -223,21 +351,73 @@ xml2file_recurse(FILE *f,
|
||||||
|
|
||||||
/*! Print an XML tree structure to an output stream and encode chars "<>&"
|
/*! Print an XML tree structure to an output stream and encode chars "<>&"
|
||||||
*
|
*
|
||||||
* @param[in] f Output file
|
* Extended version with with-defaults
|
||||||
* @param[in] xn XML tree
|
* Assume xn being in REPORT_ALL state, modify default values according to wdef
|
||||||
* @param[in] level How many spaces to insert before each line
|
* @param[in] f Output file
|
||||||
* @param[in] pretty Insert \n and spaces to make the xml more readable.
|
* @param[in] xn XML tree
|
||||||
* @param[in] prefix Add string to beginning of each line (if pretty)
|
* @param[in] level How many spaces to insert before each line
|
||||||
* @param[in] fn File print function (if NULL, use fprintf)
|
* @param[in] pretty Insert \n and spaces to make the xml more readable.
|
||||||
* @param[in] skiptop 0: Include top object 1: Skip top-object, only children,
|
* @param[in] prefix Add string to beginning of each line (if pretty)
|
||||||
|
* @param[in] fn File print function (if NULL, use fprintf)
|
||||||
|
* @param[in] skiptop 0: Include top object 1: Skip top-object, only children,
|
||||||
* @param[in] autocliext How to handle autocli extensions: 0: ignore 1: follow
|
* @param[in] autocliext How to handle autocli extensions: 0: ignore 1: follow
|
||||||
* @retval 0 OK
|
* @param[in] wdef With-defaults parameter, default is WITHDEFAULTS_REPORT_ALL
|
||||||
* @retval -1 Error
|
* @retval 0 OK
|
||||||
|
* @retval -1 Error
|
||||||
* @see clixon_xml2cbuf print to a cbuf string
|
* @see clixon_xml2cbuf print to a cbuf string
|
||||||
* @note There is a slight "layer violation" with the autocli parameter: it should normally be set
|
* @note There is a slight "layer violation" with the autocli parameter: it should normally be set
|
||||||
* for CLI calls, but not for others.
|
* for CLI calls, but not for others.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
|
clixon_xml2file1(FILE *f,
|
||||||
|
cxobj *xn,
|
||||||
|
int level,
|
||||||
|
int pretty,
|
||||||
|
char *prefix,
|
||||||
|
clicon_output_cb *fn,
|
||||||
|
int skiptop,
|
||||||
|
int autocliext,
|
||||||
|
withdefaults_type wdef)
|
||||||
|
{
|
||||||
|
int retval = 1;
|
||||||
|
cxobj *xc;
|
||||||
|
|
||||||
|
if (fn == NULL)
|
||||||
|
fn = fprintf;
|
||||||
|
if (skiptop){
|
||||||
|
xc = NULL;
|
||||||
|
while ((xc = xml_child_each(xn, xc, CX_ELMNT)) != NULL)
|
||||||
|
if (xml2file_recurse(f, xc, level, pretty, prefix, fn, autocliext, wdef) < 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (xml2file_recurse(f, xn, level, pretty, prefix, fn, autocliext, wdef) < 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Print an XML tree structure to an output stream and encode chars "<>&"
|
||||||
|
*
|
||||||
|
* Assume xn being in REPORT_ALL state, modify default values according to wdef
|
||||||
|
* @param[in] f Output file
|
||||||
|
* @param[in] xn XML tree
|
||||||
|
* @param[in] level How many spaces to insert before each line
|
||||||
|
* @param[in] pretty Insert \n and spaces to make the xml more readable.
|
||||||
|
* @param[in] prefix Add string to beginning of each line (if pretty)
|
||||||
|
* @param[in] fn File print function (if NULL, use fprintf)
|
||||||
|
* @param[in] skiptop 0: Include top object 1: Skip top-object, only children,
|
||||||
|
* @param[in] autocliext How to handle autocli extensions: 0: ignore 1: follow
|
||||||
|
* @retval 0 OK
|
||||||
|
* @retval -1 Error
|
||||||
|
* @see clixon_xml2cbuf print to a cbuf string
|
||||||
|
* @note There is a slight "layer violation" with the autocli parameter: it should normally be set
|
||||||
|
* for CLI calls, but not for others.
|
||||||
|
* @see clixon_xml2file1 for extended version with wdef
|
||||||
|
*/
|
||||||
|
int
|
||||||
clixon_xml2file(FILE *f,
|
clixon_xml2file(FILE *f,
|
||||||
cxobj *xn,
|
cxobj *xn,
|
||||||
int level,
|
int level,
|
||||||
|
|
@ -247,31 +427,14 @@ clixon_xml2file(FILE *f,
|
||||||
int skiptop,
|
int skiptop,
|
||||||
int autocliext)
|
int autocliext)
|
||||||
{
|
{
|
||||||
int retval = 1;
|
return clixon_xml2file1(f, xn, level, pretty, prefix, fn, skiptop, autocliext, 0);
|
||||||
cxobj *xc;
|
|
||||||
|
|
||||||
if (fn == NULL)
|
|
||||||
fn = fprintf;
|
|
||||||
if (skiptop){
|
|
||||||
xc = NULL;
|
|
||||||
while ((xc = xml_child_each(xn, xc, CX_ELMNT)) != NULL)
|
|
||||||
if (xml2file_recurse(f, xc, level, pretty, prefix, fn, autocliext) < 0)
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (xml2file_recurse(f, xn, level, pretty, prefix, fn, autocliext) < 0)
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
retval = 0;
|
|
||||||
done:
|
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Print an XML tree structure to an output stream
|
/*! Print an XML tree structure to an output stream
|
||||||
*
|
*
|
||||||
* Utility function eg in gdb. For code, use clixon_xml2file
|
* Utility function eg in gdb. For code, use clixon_xml2file
|
||||||
* @param[in] f UNIX output stream
|
* @param[in] f UNIX output stream
|
||||||
* @param[in] xn clicon xml tree
|
* @param[in] xn clixon xml tree
|
||||||
* @see clixon_xml2cbuf
|
* @see clixon_xml2cbuf
|
||||||
* @see clixon_xml2cbuf_cb print using a callback
|
* @see clixon_xml2cbuf_cb print using a callback
|
||||||
*/
|
*/
|
||||||
|
|
@ -279,7 +442,7 @@ int
|
||||||
xml_print(FILE *f,
|
xml_print(FILE *f,
|
||||||
cxobj *x)
|
cxobj *x)
|
||||||
{
|
{
|
||||||
return xml2file_recurse(f, x, 0, 1, NULL, fprintf, 0);
|
return xml2file_recurse(f, x, 0, 1, NULL, fprintf, 0, WITHDEFAULTS_REPORT_ALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Dump cxobj structure with pointers and flags for debugging, internal function
|
/*! Dump cxobj structure with pointers and flags for debugging, internal function
|
||||||
|
|
@ -335,28 +498,46 @@ xml_dump(FILE *f,
|
||||||
* @param[in] pretty Insert \n and spaces to make the xml more readable.
|
* @param[in] pretty Insert \n and spaces to make the xml more readable.
|
||||||
* @param[in] prefix Add string to beginning of each line (if pretty)
|
* @param[in] prefix Add string to beginning of each line (if pretty)
|
||||||
* @param[in] depth Limit levels of child resources: -1 is all, 0 is none, 1 is node itself
|
* @param[in] depth Limit levels of child resources: -1 is all, 0 is none, 1 is node itself
|
||||||
|
* @param[in] wdef With-defaults parameter, default is WITHDEFAULTS_REPORT_ALL
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
|
* wdef changes the output as follows:
|
||||||
|
* - WITHDEFAULTS_REPORT_ALL - keep as-is
|
||||||
|
* - WITHDEFAULTS_TRIM - remove defaults + equal value, and no-presence
|
||||||
|
* - WITHDEFAULTS_EXPLICIT - remove defaults and no-presence
|
||||||
|
* - WITHDEFAULTS_REPORT_ALL_TAGGED
|
||||||
|
* @see xml2file_recurse same with FILE
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
clixon_xml2cbuf1(cbuf *cb,
|
xml2cbuf_recurse(cbuf *cb,
|
||||||
cxobj *x,
|
cxobj *x,
|
||||||
int level,
|
int level,
|
||||||
int pretty,
|
int pretty,
|
||||||
char *prefix,
|
char *prefix,
|
||||||
int32_t depth)
|
int32_t depth,
|
||||||
|
withdefaults_type wdef)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
cxobj *xc;
|
cxobj *xc;
|
||||||
char *name;
|
char *name;
|
||||||
int hasbody;
|
int hasbody;
|
||||||
int haselement;
|
int haselement;
|
||||||
char *namespace;
|
char *namespace;
|
||||||
char *val;
|
char *val;
|
||||||
int level1;
|
int level1;
|
||||||
|
yang_stmt *y;
|
||||||
|
int tag = 0;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (depth == 0)
|
if (depth == 0)
|
||||||
goto ok;
|
goto ok;
|
||||||
|
if ((y = xml_spec(x)) != NULL){
|
||||||
|
/* with-defaults: if object should be printed or not */
|
||||||
|
if ((ret = xml2output_wdef(x, wdef, &tag)) < 0)
|
||||||
|
goto done;
|
||||||
|
if (ret == 0)
|
||||||
|
goto ok;
|
||||||
|
}
|
||||||
level1 = level*PRETTYPRINT_INDENT;
|
level1 = level*PRETTYPRINT_INDENT;
|
||||||
if (prefix)
|
if (prefix)
|
||||||
level1 -= strlen(prefix);
|
level1 -= strlen(prefix);
|
||||||
|
|
@ -390,6 +571,8 @@ clixon_xml2cbuf1(cbuf *cb,
|
||||||
cbuf_append_str(cb, ":");
|
cbuf_append_str(cb, ":");
|
||||||
}
|
}
|
||||||
cbuf_append_str(cb, name);
|
cbuf_append_str(cb, name);
|
||||||
|
if (tag) /* If default and WITHDEFAULTS_REPORT_ALL_TAGGED */
|
||||||
|
cbuf_append_str(cb, " wd:default=\"true\"");
|
||||||
hasbody = 0;
|
hasbody = 0;
|
||||||
haselement = 0;
|
haselement = 0;
|
||||||
xc = NULL;
|
xc = NULL;
|
||||||
|
|
@ -397,7 +580,7 @@ clixon_xml2cbuf1(cbuf *cb,
|
||||||
while ((xc = xml_child_each(x, xc, -1)) != NULL)
|
while ((xc = xml_child_each(x, xc, -1)) != NULL)
|
||||||
switch (xml_type(xc)){
|
switch (xml_type(xc)){
|
||||||
case CX_ATTR:
|
case CX_ATTR:
|
||||||
if (clixon_xml2cbuf1(cb, xc, level+1, pretty, prefix, -1) < 0)
|
if (xml2cbuf_recurse(cb, xc, level+1, pretty, prefix, -1, wdef) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
break;
|
break;
|
||||||
case CX_BODY:
|
case CX_BODY:
|
||||||
|
|
@ -418,9 +601,29 @@ clixon_xml2cbuf1(cbuf *cb,
|
||||||
cbuf_append_str(cb, "\n");
|
cbuf_append_str(cb, "\n");
|
||||||
xc = NULL;
|
xc = NULL;
|
||||||
while ((xc = xml_child_each(x, xc, -1)) != NULL)
|
while ((xc = xml_child_each(x, xc, -1)) != NULL)
|
||||||
if (xml_type(xc) != CX_ATTR)
|
if (xml_type(xc) != CX_ATTR){
|
||||||
if (clixon_xml2cbuf1(cb, xc, level+1, pretty, prefix, depth-1) < 0)
|
cxobj *xa = NULL;
|
||||||
|
char *ns = NULL;
|
||||||
|
|
||||||
|
/* If tagged withdefaults */
|
||||||
|
if (wdef == WITHDEFAULTS_REPORT_ALL_TAGGED &&
|
||||||
|
y == NULL &&
|
||||||
|
xml_spec(xc) != NULL){
|
||||||
|
if (xml2ns(xc, IETF_NETCONF_WITH_DEFAULTS_ATTR_PREFIX, &ns) < 0)
|
||||||
|
goto done;
|
||||||
|
if (ns == NULL){
|
||||||
|
if (xmlns_set(xc, IETF_NETCONF_WITH_DEFAULTS_ATTR_PREFIX, IETF_NETCONF_WITH_DEFAULTS_ATTR_NAMESPACE) < 0)
|
||||||
|
goto done;
|
||||||
|
xa = xml_find_type(xc, IETF_NETCONF_WITH_DEFAULTS_ATTR_PREFIX, IETF_NETCONF_WITH_DEFAULTS_ATTR_NAMESPACE, CX_ATTR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (xml2cbuf_recurse(cb, xc, level+1, pretty, prefix, depth-1, wdef) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
if (xa){
|
||||||
|
if (xml_purge(xa) < 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (pretty && hasbody == 0){
|
if (pretty && hasbody == 0){
|
||||||
if (prefix)
|
if (prefix)
|
||||||
cprintf(cb, "%s", prefix);
|
cprintf(cb, "%s", prefix);
|
||||||
|
|
@ -446,6 +649,57 @@ clixon_xml2cbuf1(cbuf *cb,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Print an XML tree structure to a cligen buffer and encode chars "<>&"
|
||||||
|
*
|
||||||
|
* Extended version with with-defaults
|
||||||
|
* @param[in,out] cb Cligen buffer to write to
|
||||||
|
* @param[in] xn Top-level xml object
|
||||||
|
* @param[in] level Indentation level for pretty
|
||||||
|
* @param[in] pretty Insert \n and spaces to make the xml more readable.
|
||||||
|
* @param[in] prefix Add string to beginning of each line (or NULL) (if pretty)
|
||||||
|
* @param[in] depth Limit levels of child resources: -1: all, 0: none, 1: node itself
|
||||||
|
* @param[in] skiptop 0: Include top object 1: Skip top-object, only children,
|
||||||
|
* @param[in] wdef With-defaults parameter, default is WITHDEFAULTS_REPORT_ALL
|
||||||
|
* @retval 0 OK
|
||||||
|
* @retval -1 Error
|
||||||
|
* Depth is used in NACM
|
||||||
|
* @code
|
||||||
|
* cbuf *cb = cbuf_new();
|
||||||
|
* if (clixon_xml2cbuf(cb, xn, 0, 1, NULL, -1, 0, 0) < 0)
|
||||||
|
* goto err;
|
||||||
|
* fprintf(stderr, "%s", cbuf_get(cb));
|
||||||
|
* cbuf_free(cb);
|
||||||
|
* @endcode
|
||||||
|
* @see clixon_xml2file to file, which is faster
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
clixon_xml2cbuf1(cbuf *cb,
|
||||||
|
cxobj *xn,
|
||||||
|
int level,
|
||||||
|
int pretty,
|
||||||
|
char *prefix,
|
||||||
|
int32_t depth,
|
||||||
|
int skiptop,
|
||||||
|
withdefaults_type wdef)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
cxobj *xc;
|
||||||
|
|
||||||
|
if (skiptop){
|
||||||
|
xc = NULL;
|
||||||
|
while ((xc = xml_child_each(xn, xc, CX_ELMNT)) != NULL)
|
||||||
|
if (xml2cbuf_recurse(cb, xc, level, pretty, prefix, depth, wdef) < 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (xml2cbuf_recurse(cb, xn, level, pretty, prefix, depth, wdef) < 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Print an XML tree structure to a cligen buffer and encode chars "<>&"
|
/*! Print an XML tree structure to a cligen buffer and encode chars "<>&"
|
||||||
*
|
*
|
||||||
* @param[in,out] cb Cligen buffer to write to
|
* @param[in,out] cb Cligen buffer to write to
|
||||||
|
|
@ -454,18 +708,19 @@ clixon_xml2cbuf1(cbuf *cb,
|
||||||
* @param[in] pretty Insert \n and spaces to make the xml more readable.
|
* @param[in] pretty Insert \n and spaces to make the xml more readable.
|
||||||
* @param[in] prefix Add string to beginning of each line (or NULL) (if pretty)
|
* @param[in] prefix Add string to beginning of each line (or NULL) (if pretty)
|
||||||
* @param[in] depth Limit levels of child resources: -1: all, 0: none, 1: node itself
|
* @param[in] depth Limit levels of child resources: -1: all, 0: none, 1: node itself
|
||||||
* @param[in] skiptop 0: Include top object 1: Skip top-object, only children,
|
* @param[in] skiptop 0: Include top object 1: Skip top-object, only children,
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
* Depth is used in NACM
|
* Depth is used in NACM
|
||||||
* @code
|
* @code
|
||||||
* cbuf *cb = cbuf_new();
|
* cbuf *cb = cbuf_new();
|
||||||
* if (clixon_xml2cbuf(cb, xn, 0, 1, NULL, -1, 0) < 0)
|
* if (clixon_xml2cbuf(cb, xn, 0, 1, NULL, -1, 0, 0) < 0)
|
||||||
* goto err;
|
* goto err;
|
||||||
* fprintf(stderr, "%s", cbuf_get(cb));
|
* fprintf(stderr, "%s", cbuf_get(cb));
|
||||||
* cbuf_free(cb);
|
* cbuf_free(cb);
|
||||||
* @endcode
|
* @endcode
|
||||||
* @see clixon_xml2file
|
* @see clixon_xml2file to file, which is faster
|
||||||
|
* @see clixon_xml2cbuf1 for extended version with wdef
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
clixon_xml2cbuf(cbuf *cb,
|
clixon_xml2cbuf(cbuf *cb,
|
||||||
|
|
@ -476,28 +731,13 @@ clixon_xml2cbuf(cbuf *cb,
|
||||||
int32_t depth,
|
int32_t depth,
|
||||||
int skiptop)
|
int skiptop)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
return clixon_xml2cbuf1(cb, xn, level, pretty, prefix, depth, skiptop, 0);
|
||||||
cxobj *xc;
|
|
||||||
|
|
||||||
if (skiptop){
|
|
||||||
xc = NULL;
|
|
||||||
while ((xc = xml_child_each(xn, xc, CX_ELMNT)) != NULL)
|
|
||||||
if (clixon_xml2cbuf1(cb, xc, level, pretty, prefix, depth) < 0)
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (clixon_xml2cbuf1(cb, xn, level, pretty, prefix, depth) < 0)
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
retval = 0;
|
|
||||||
done:
|
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Print actual xml tree datastructures (not xml), mainly for debugging
|
/*! Print actual xml tree datastructures (not xml), mainly for debugging
|
||||||
*
|
*
|
||||||
* @param[in,out] cb Cligen buffer to write to
|
* @param[in,out] cb Cligen buffer to write to
|
||||||
* @param[in] xn Clicon xml tree
|
* @param[in] xn Clixon xml tree
|
||||||
* @param[in] level Indentation level
|
* @param[in] level Indentation level
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
|
|
@ -540,7 +780,7 @@ xmltree2cbuf(cbuf *cb,
|
||||||
/*! Common internal xml parsing function string to parse-tree
|
/*! Common internal xml parsing function string to parse-tree
|
||||||
*
|
*
|
||||||
* Given a string containing XML, parse into existing XML tree and return
|
* Given a string containing XML, parse into existing XML tree and return
|
||||||
* @param[in] str Pointer to string containing XML definition.
|
* @param[in] str Pointer to string containing XML definition.
|
||||||
* @param[in] yb How to bind yang to XML top-level when parsing
|
* @param[in] yb How to bind yang to XML top-level when parsing
|
||||||
* @param[in] yspec Yang specification (only if bind is TOP or CONFIG)
|
* @param[in] yspec Yang specification (only if bind is TOP or CONFIG)
|
||||||
* @param[in,out] xtop Top of XML parse tree. Assume created. Holds new tree.
|
* @param[in,out] xtop Top of XML parse tree. Assume created. Holds new tree.
|
||||||
|
|
@ -556,9 +796,9 @@ xmltree2cbuf(cbuf *cb,
|
||||||
* A well-formed document ... contains one or more elements.
|
* A well-formed document ... contains one or more elements.
|
||||||
* But in clixon one can invoke a parser on a sub-part of a document where it makes sense to accept
|
* But in clixon one can invoke a parser on a sub-part of a document where it makes sense to accept
|
||||||
* an empty XML. For example where an empty config: <config></config> is parsed.
|
* an empty XML. For example where an empty config: <config></config> is parsed.
|
||||||
* In other cases, such as receiving netconf ]]>]]> it should represent a complete document and
|
* In other cases, such as receiving netconf ]]>]]> it should represent a complete document and
|
||||||
* therefore not well-formed.
|
* therefore not well-formed.
|
||||||
* Therefore checking for empty XML must be done by a calling function which knows wether the
|
* Therefore checking for empty XML must be done by a calling function which knows wether the
|
||||||
* the XML represents a full document or not.
|
* the XML represents a full document or not.
|
||||||
* @note may be called recursively, some yang-bind (eg rpc) semantic checks may trigger error message
|
* @note may be called recursively, some yang-bind (eg rpc) semantic checks may trigger error message
|
||||||
* @note yang-binding over schema mount-points do not work, you need to make a separate bind call
|
* @note yang-binding over schema mount-points do not work, you need to make a separate bind call
|
||||||
|
|
@ -766,7 +1006,7 @@ clixon_xml_parse_file(FILE *fp,
|
||||||
|
|
||||||
/*! Read an XML definition from string and parse it into a parse-tree, advanced API
|
/*! Read an XML definition from string and parse it into a parse-tree, advanced API
|
||||||
*
|
*
|
||||||
* @param[in] str String containing XML definition.
|
* @param[in] str String containing XML definition.
|
||||||
* @param[in] yb How to bind yang to XML top-level when parsing
|
* @param[in] yb How to bind yang to XML top-level when parsing
|
||||||
* @param[in] yspec Yang specification, or NULL
|
* @param[in] yspec Yang specification, or NULL
|
||||||
* @param[in,out] xt Pointer to XML parse tree. If empty will be created.
|
* @param[in,out] xt Pointer to XML parse tree. If empty will be created.
|
||||||
|
|
@ -817,7 +1057,7 @@ clixon_xml_parse_string(const char *str,
|
||||||
* Utility function using stdarg instead of static string.
|
* Utility function using stdarg instead of static string.
|
||||||
* @param[in] yb How to bind yang to XML top-level when parsing
|
* @param[in] yb How to bind yang to XML top-level when parsing
|
||||||
* @param[in] yspec Yang specification, or NULL
|
* @param[in] yspec Yang specification, or NULL
|
||||||
* @param[in,out] xtop Top of XML parse tree. If it is NULL, top element
|
* @param[in,out] xtop Top of XML parse tree. If it is NULL, top element
|
||||||
* called 'top' will be created. Call xml_free() after use
|
* called 'top' will be created. Call xml_free() after use
|
||||||
* @param[out] xerr Reason for failure (yang assignment not made)
|
* @param[out] xerr Reason for failure (yang assignment not made)
|
||||||
* @param[in] format Format string for stdarg according to printf(3)
|
* @param[in] format Format string for stdarg according to printf(3)
|
||||||
|
|
@ -927,7 +1167,7 @@ xml_diff_keys(cbuf *cb,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Print one line of context around diff
|
/*! Print one line of context around diff
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
xml_diff_context(cbuf *cb,
|
xml_diff_context(cbuf *cb,
|
||||||
|
|
@ -1027,7 +1267,7 @@ xml_diff2cbuf_ordered_by_user(cbuf *cb,
|
||||||
* @param[in] x0 First XML tree
|
* @param[in] x0 First XML tree
|
||||||
* @param[in] x1 Second XML tree
|
* @param[in] x1 Second XML tree
|
||||||
* @param[in] level How many spaces to insert before each line
|
* @param[in] level How many spaces to insert before each line
|
||||||
* @param[in] skiptop 0: Include top object 1: Skip top-object, only children,
|
* @param[in] skiptop 0: Include top object 1: Skip top-object, only children,
|
||||||
* @retval 0 Ok
|
* @retval 0 Ok
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
* @cod
|
* @cod
|
||||||
|
|
@ -1103,7 +1343,7 @@ xml_diff2cbuf(cbuf *cb,
|
||||||
if (xml_diff2cbuf_ordered_by_user(cb, x0, x1, x0c, x1c, yc0,
|
if (xml_diff2cbuf_ordered_by_user(cb, x0, x1, x0c, x1c, yc0,
|
||||||
level, skiptop) < 0)
|
level, skiptop) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* Add all in x0 marked as DELETE in x0vec
|
/* Add all in x0 marked as DELETE in x0vec
|
||||||
* Flags can remain: XXX should apply to all
|
* Flags can remain: XXX should apply to all
|
||||||
*/
|
*/
|
||||||
xi = x0c;
|
xi = x0c;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue