diff --git a/lib/clixon/clixon_xml_io.h b/lib/clixon/clixon_xml_io.h index 07f80982..c44a5668 100644 --- a/lib/clixon/clixon_xml_io.h +++ b/lib/clixon/clixon_xml_io.h @@ -43,10 +43,15 @@ /* * 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 xml_print(FILE *f, cxobj *xn); 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 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); diff --git a/lib/src/clixon_xml_io.c b/lib/src/clixon_xml_io.c index d1972db8..186173e7 100644 --- a/lib/src/clixon_xml_io.c +++ b/lib/src/clixon_xml_io.c @@ -73,6 +73,8 @@ #include "clixon_xml_sort.h" #include "clixon_xml_nsctx.h" #include "clixon_xml_parse.h" +#include "clixon_netconf_lib.h" +#include "clixon_xml_default.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 *------------------------------------------------------------------------*/ +/*! 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 "<>&" * * @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] 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 Callback to make print function * @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 -1 Error - * @see clixon_xml2cbuf * One can use clixon_xml2cbuf to get common code, but using fprintf is * 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 -xml2file_recurse(FILE *f, - cxobj *x, - int level, - int pretty, - char *prefix, - clicon_output_cb *fn, - int autocliext) +xml2file_recurse(FILE *f, + cxobj *x, + int level, + int pretty, + char *prefix, + clicon_output_cb *fn, + int autocliext, + withdefaults_type wdef) { - int retval = -1; - char *name; - char *namespace; - cxobj *xc; - int hasbody; - int haselement; - char *val; - char *encstr = NULL; /* xml encoded string */ - int exist = 0; - yang_stmt *y; - int level1; + int retval = -1; + char *name; + char *namespace; + cxobj *xc; + int hasbody; + int haselement; + char *val; + char *encstr = NULL; /* xml encoded string */ + int exist = 0; + yang_stmt *y; + int level1; + int tag = 0; + int ret; if (x == NULL) goto ok; level1 = level*PRETTYPRINT_INDENT; if (prefix) level1 -= strlen(prefix); - if (autocliext && - (y = xml_spec(x)) != NULL){ - if (yang_extension_value(y, "hide-show", CLIXON_AUTOCLI_NS, &exist, NULL) < 0) + if ((y = xml_spec(x)) != NULL){ + if (autocliext){ + 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; - if (exist) + if (ret == 0) goto ok; } name = xml_name(x); @@ -160,6 +268,8 @@ xml2file_recurse(FILE *f, if (namespace) (*fn)(f, "%s:", namespace); (*fn)(f, "%s", name); + if (tag) /* If default and WITHDEFAULTS_REPORT_ALL_TAGGED */ + (*fn)(f, " wd:default=\"true\""); hasbody = 0; haselement = 0; xc = NULL; @@ -167,7 +277,7 @@ xml2file_recurse(FILE *f, while ((xc = xml_child_each(x, xc, -1)) != NULL) { switch (xml_type(xc)){ 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; break; case CX_BODY: @@ -188,13 +298,31 @@ xml2file_recurse(FILE *f, else{ (*fn)(f, ">"); if (pretty && hasbody == 0){ - (*fn)(f, "\n"); + (*fn)(f, "\n"); } xc = NULL; while ((xc = xml_child_each(x, xc, -1)) != NULL) { - if (xml_type(xc) != CX_ATTR) - if (xml2file_recurse(f, xc, level+1, pretty, prefix, fn, autocliext) <0) + cxobj *xa = NULL; + 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; + 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 && prefix) @@ -223,21 +351,73 @@ xml2file_recurse(FILE *f, /*! Print an XML tree structure to an output stream and encode chars "<>&" * - * @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, + * Extended version with with-defaults + * 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 + * @param[in] wdef With-defaults parameter, default is WITHDEFAULTS_REPORT_ALL + * @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. */ 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, cxobj *xn, int level, @@ -247,31 +427,14 @@ clixon_xml2file(FILE *f, int skiptop, int autocliext) { - 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) < 0) - goto done; - } - else { - if (xml2file_recurse(f, xn, level, pretty, prefix, fn, autocliext) < 0) - goto done; - } - retval = 0; - done: - return retval; + return clixon_xml2file1(f, xn, level, pretty, prefix, fn, skiptop, autocliext, 0); } /*! Print an XML tree structure to an output stream * * Utility function eg in gdb. For code, use clixon_xml2file * @param[in] f UNIX output stream - * @param[in] xn clicon xml tree + * @param[in] xn clixon xml tree * @see clixon_xml2cbuf * @see clixon_xml2cbuf_cb print using a callback */ @@ -279,7 +442,7 @@ int xml_print(FILE *f, 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 @@ -335,28 +498,46 @@ xml_dump(FILE *f, * @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] 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 -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 -clixon_xml2cbuf1(cbuf *cb, - cxobj *x, - int level, - int pretty, - char *prefix, - int32_t depth) +xml2cbuf_recurse(cbuf *cb, + cxobj *x, + int level, + int pretty, + char *prefix, + int32_t depth, + withdefaults_type wdef) { - int retval = -1; - cxobj *xc; - char *name; - int hasbody; - int haselement; - char *namespace; - char *val; - int level1; + int retval = -1; + cxobj *xc; + char *name; + int hasbody; + int haselement; + char *namespace; + char *val; + int level1; + yang_stmt *y; + int tag = 0; + int ret; if (depth == 0) 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; if (prefix) level1 -= strlen(prefix); @@ -390,6 +571,8 @@ clixon_xml2cbuf1(cbuf *cb, cbuf_append_str(cb, ":"); } cbuf_append_str(cb, name); + if (tag) /* If default and WITHDEFAULTS_REPORT_ALL_TAGGED */ + cbuf_append_str(cb, " wd:default=\"true\""); hasbody = 0; haselement = 0; xc = NULL; @@ -397,7 +580,7 @@ clixon_xml2cbuf1(cbuf *cb, while ((xc = xml_child_each(x, xc, -1)) != NULL) switch (xml_type(xc)){ 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; break; case CX_BODY: @@ -418,9 +601,29 @@ clixon_xml2cbuf1(cbuf *cb, cbuf_append_str(cb, "\n"); xc = NULL; while ((xc = xml_child_each(x, xc, -1)) != NULL) - if (xml_type(xc) != CX_ATTR) - if (clixon_xml2cbuf1(cb, xc, level+1, pretty, prefix, depth-1) < 0) + if (xml_type(xc) != CX_ATTR){ + 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; + if (xa){ + if (xml_purge(xa) < 0) + goto done; + } + } if (pretty && hasbody == 0){ if (prefix) cprintf(cb, "%s", prefix); @@ -446,6 +649,57 @@ clixon_xml2cbuf1(cbuf *cb, 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 "<>&" * * @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] 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] skiptop 0: Include top object 1: Skip top-object, only children, * @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) + * 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 + * @see clixon_xml2file to file, which is faster + * @see clixon_xml2cbuf1 for extended version with wdef */ int clixon_xml2cbuf(cbuf *cb, @@ -476,28 +731,13 @@ clixon_xml2cbuf(cbuf *cb, int32_t depth, int skiptop) { - int retval = -1; - 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; + return clixon_xml2cbuf1(cb, xn, level, pretty, prefix, depth, skiptop, 0); } /*! Print actual xml tree datastructures (not xml), mainly for debugging * * @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 */ int @@ -540,7 +780,7 @@ xmltree2cbuf(cbuf *cb, /*! Common internal xml parsing function string to parse-tree * * 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] yspec Yang specification (only if bind is TOP or CONFIG) * @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. * 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: 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 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. * @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 @@ -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 * - * @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] yspec Yang specification, or NULL * @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. * @param[in] yb How to bind yang to XML top-level when parsing * @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 * @param[out] xerr Reason for failure (yang assignment not made) * @param[in] format Format string for stdarg according to printf(3) @@ -927,7 +1167,7 @@ xml_diff_keys(cbuf *cb, return 0; } -/*! Print one line of context around diff +/*! Print one line of context around diff */ static int xml_diff_context(cbuf *cb, @@ -1027,7 +1267,7 @@ xml_diff2cbuf_ordered_by_user(cbuf *cb, * @param[in] x0 First XML tree * @param[in] x1 Second XML tree * @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 -1 Error * @cod @@ -1103,7 +1343,7 @@ xml_diff2cbuf(cbuf *cb, if (xml_diff2cbuf_ordered_by_user(cb, x0, x1, x0c, x1c, yc0, level, skiptop) < 0) 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 */ xi = x0c;