* Strict namespace setting can be a problem when upgrading existing database files, such as startup-db or persistent running-db, or any other saved XML file.

* For backward compatibility, load of startup and running set CLICON_XML_NS_STRICT to false temporarily.
* Added three-valued return values for several validate functions where -1 is fatal error, 0 is validation failed and 1 is validation OK.
  * This includes: `xmldb_put`, `xml_yang_validate_all`, `xml_yang_validate_add`, `xml_yang_validate_rpc`, `api_path2xml`, `api_path2xpath`
* Added new xml functions for specific types: `xml_child_nr_notype`, `xml_child_nr_notype`, `xml_child_i_type`, `xml_find_type`.
This commit is contained in:
Olof hagsand 2019-01-02 15:18:29 +01:00
parent 861300d6c0
commit 0baebc93fd
71 changed files with 2679 additions and 1573 deletions

View file

@ -62,6 +62,8 @@
#include "clixon_log.h"
#include "clixon_yang.h"
#include "clixon_xml.h"
#include "clixon_options.h" /* xml_spec_populate */
#include "clixon_xml_map.h" /* xml_spec_populate */
#include "clixon_xml_sort.h"
#include "clixon_xml_parse.h"
@ -133,9 +135,9 @@ struct xml{
* or rpc if no xmlns attribute specifies namespace.
* This is loose semantics of finding namespaces.
* And it is wrong, but is the way Clixon originally was written."
* @see CLICON_XML_NS_ITERATE clixon configure option
* @see CLICON_XML_NS_STRICT clixon configure option
*/
int _CLICON_XML_NS_ITERATE = 0;
int _CLICON_XML_NS_STRICT = 1;
/* Mapping between xml type <--> string */
static const map_str2int xsmap[] = {
@ -226,8 +228,7 @@ xml_prefix_set(cxobj *xn,
return 0;
}
/*! Given an xml tree return URI namespace: default or localname given
/*! Given an xml tree return URI namespace recursively : default or localname given
*
* Given an XML tree and a prefix (or NULL) return URI namespace.
* @param[in] x XML tree
@ -235,7 +236,7 @@ xml_prefix_set(cxobj *xn,
* @param[out] namespace URI namespace (or NULL). Note pointer into xml tree
* @retval 0 OK
* @retval -1 Error
* @see xmlns_check XXX coordinate
* @see xmlns_check XXX can these be merged?
*/
int
xml2ns(cxobj *x,
@ -246,9 +247,9 @@ xml2ns(cxobj *x,
char *ns;
cxobj *xp;
if (prefix != NULL) /* xmlns:<prefix> */
if (prefix != NULL) /* xmlns:<prefix>="<uri>" */
ns = xml_find_type_value(x, "xmlns", prefix, CX_ATTR);
else /* default ns */
else /* xmlns="<uri>" */
ns = xml_find_type_value(x, NULL, "xmlns", CX_ATTR);
/* namespace not found, try parent */
@ -270,6 +271,40 @@ xml2ns(cxobj *x,
return retval;
}
/*! Add a namespace attribute to an XML node, either default or specific prefix
* @param[in] x XML tree
* @param[in] prefix prefix/ns localname. If NULL then set default xmlns
* @param[out] namespace URI namespace (or NULL). Will be copied
* @retval 0 OK
* @retval -1 Error
* @see xml2ns
*/
int
xmlns_set(cxobj *x,
char *prefix,
char *namespace)
{
int retval = -1;
cxobj *xa;
if (prefix != NULL){ /* xmlns:<prefix>="<uri>" */
if ((xa = xml_new(prefix, x, NULL)) == NULL)
goto done;
if (xml_prefix_set(xa, "xmlns") < 0)
goto done;
}
else{ /* xmlns="<uri>" */
if ((xa = xml_new("xmlns", x, NULL)) == NULL)
goto done;
xml_type_set(xa, CX_ATTR);
}
if (xml_value_set(xa, namespace) < 0)
goto done;
retval = 0;
done:
return retval;
}
/*! See if xmlns:[<localname>=]<uri> exists, if so return <uri>
*
* @param[in] xn XML node
@ -483,6 +518,8 @@ xml_type_set(cxobj *xn,
/*! Get number of children
* @param[in] xn xml node
* @retval number of children in XML tree
* @see xml_child_nr_type
* @see xml_child_nr_notype
*/
int
xml_child_nr(cxobj *xn)
@ -490,10 +527,33 @@ xml_child_nr(cxobj *xn)
return xn->x_childvec_len;
}
/*! Get number of children of EXCEPT specific type
* @param[in] xn xml node
* @param[in] type XML type or -1 for all
* @retval number of typed children in XML tree (except type)
* @see xml_child_nr
* @see xml_child_nr_type
*/
int
xml_child_nr_notype(cxobj *xn,
enum cxobj_type type)
{
cxobj *x = NULL;
int nr = 0;
while ((x = xml_child_each(xn, x, -1)) != NULL) {
if (xml_type(x) != type)
nr++;
}
return nr;
}
/*! Get number of children of specific type
* @param[in] xn xml node
* @param[in] type XML type or -1 for all
* @retval number of typed children in XML tree
* @see xml_child_nr
* @see xml_child_nr_notype
*/
int
xml_child_nr_type(cxobj *xn,
@ -521,6 +581,28 @@ xml_child_i(cxobj *xn,
return NULL;
}
/*! Get a specific child of a specific type
* @param[in] xn xml node
* @param[in] i the number of the child of specific type
* @param[in] type Child type
* @retval child in XML tree, or NULL if no such child, or empty child
* @see xml_child_i
*/
cxobj *
xml_child_i_type(cxobj *xn,
int i,
enum cxobj_type type)
{
cxobj *x = NULL;
int it = 0;
while ((x = xml_child_each(xn, x, type)) != NULL) {
if (x->x_type == type && (i == it++))
return x;
}
return NULL;
}
/*! Set specific child
* @param[in] xn xml node
* @param[in] i the number of the child, eg order in children vector
@ -938,7 +1020,7 @@ xml_body_get(cxobj *xt)
return NULL;
}
/*! Find and return the value of an xml child of specific type
/*! Find and return the value of an xml child of specific type given prefix and name
*
* The value can be of an attribute only
* @param[in] xt xml tree node
@ -950,6 +1032,7 @@ xml_body_get(cxobj *xt)
* char *str = xml_find_type_value(x, "prefix", "name", CX_ATTR);
* @endcode
* @note, make a copy of the return value to use it properly
* @see xml_find_type return the xml object
* @see xml_find_value where a body can be found as well
*/
char *
@ -957,6 +1040,32 @@ xml_find_type_value(cxobj *xt,
char *prefix,
char *name,
enum cxobj_type type)
{
cxobj *x;
if ((x = xml_find_type(xt, prefix, name, type)) != NULL)
return xml_value(x);
return NULL;
}
/*! Find and return the xml child of specific type given prefix and name
*
* The value can be of an attribute only
* @param[in] xt xml tree node
* @param[in] prefix Prefix (namespace local name) or NULL
* @param[in] name name of xml tree node (eg attr name or "body")
* @retval val Pointer to the name string
* @retval NULL No such node or no value in node
* @code
* cxobj *x = xml_find_type(x, "prefix", "name", CX_ATTR);
* @endcode
* @see xml_find_value where a body can be found as well
*/
cxobj *
xml_find_type(cxobj *xt,
char *prefix,
char *name,
enum cxobj_type type)
{
cxobj *x = NULL;
int pmatch; /* prefix match */
@ -969,7 +1078,7 @@ xml_find_type_value(cxobj *xt,
else
pmatch = 1;
if (pmatch && strcmp(name, xml_name(x)) == 0)
return xml_value(x);
return x;
}
return NULL;
}
@ -1397,6 +1506,8 @@ _xml_parse(const char *str,
goto done;
/* Sort the complete tree after parsing */
if (yspec){
if (xml_apply0(xt, CX_ELMNT, xml_spec_populate, yspec) < 0)
goto done;
if (xml_apply0(xt, CX_ELMNT, xml_sort, NULL) < 0)
goto done;
if (xml_apply0(xt, -1, xml_sort_verify, NULL) < 0)
@ -1592,7 +1703,7 @@ xml_parse_va(cxobj **xtop,
return retval;
}
/*! Copy single xml node without copying children
/*! Copy single xml node frm x0 to x1 without copying children
*/
int
xml_copy_one(cxobj *x0,