* Fixed: [when condition error under augment in restconf #227](https://github.com/clicon/clixon/issues/227)

* As part of this fix added custom constant XML_PARENT_CANDIDATE
This commit is contained in:
Olof hagsand 2021-05-25 15:21:45 +02:00
parent 5b39418e92
commit 1ef7a280d7
8 changed files with 178 additions and 31 deletions

View file

@ -205,7 +205,7 @@ check_body_namespace(cxobj *x0,
/*! Check yang when condition between a new xml x1 and old x0
*
* check if there is a when condition. First try it on the new request (x1), then on the
* Check if there is a when condition. First try it on the new request (x1), then on the
* existing (x0).
* @param[in] x0p Parent of x0
* @param[in] x1 XML tree which modifies base
@ -226,9 +226,9 @@ check_when_condition(cxobj *x0p,
char *xpath = NULL;
cvec *nsc = NULL;
int nr;
cxobj *x1p;
yang_stmt *y = NULL;
cbuf *cberr = NULL;
cxobj *x1p;
if ((y = y0) != NULL ||
(y = (yang_stmt*)xml_spec(x1)) != NULL){
@ -272,7 +272,7 @@ check_when_condition(cxobj *x0p,
* @param[in] h Clicon handle
* @param[in] x0 Base xml tree (can be NULL in add scenarios)
* @param[in] x0p Parent of x0
* @param[in] x0t
* @param[in] x0t Top level of existing tree, eg needed for NACM rules
* @param[in] x1 XML tree which modifies base
* @param[in] x1t Request root node (nacm needs this)
* @param[in] y0 Yang spec corresponding to xml-node x0. NULL if x0 is NULL
@ -662,7 +662,9 @@ text_modify(clicon_handle h,
if ((x0 = xml_new(x1name, NULL, CX_ELMNT)) == NULL)
goto done;
xml_spec_set(x0, y0);
#ifdef XML_PARENT_CANDIDATE
xml_parent_candidate_set(x0, x0p);
#endif
changed++;
/* Get namespace from x1
* Check if namespace exists in x0 parent
@ -730,8 +732,8 @@ text_modify(clicon_handle h,
x1c = NULL;
i = 0;
while ((x1c = xml_child_each(x1, x1c, CX_ELMNT)) != NULL) {
x1cname = xml_name(x1c);
x0c = x0vec[i++];
x1cname = xml_name(x1c);
yc = yang_find_datanode(y0, x1cname);
if ((ret = text_modify(h, x0c, x0, x0t, x1c, x1t,
yc, op,
@ -742,6 +744,9 @@ text_modify(clicon_handle h,
goto fail;
}
if (changed){
#ifdef XML_PARENT_CANDIDATE
xml_parent_candidate_set(x0, NULL);
#endif
if (xml_insert(x0p, x0, insert, keystr, nscx1) < 0)
goto done;
}
@ -786,7 +791,7 @@ text_modify(clicon_handle h,
/*! Modify a top-level base tree x0 with modification tree x1
* @param[in] h Clicon handle
* @param[in] x0 Base xml tree (can be NULL in add scenarios)
* @param[in] x0t
* @param[in] x0t Top level of existing tree, eg needed for NACM rules
* @param[in] x1 XML tree which modifies base
* @param[in] x1t Request root node (nacm needs this)
* @param[in] yspec Top-level yang spec (if y is NULL)

View file

@ -166,6 +166,9 @@ struct xml{
char *x_prefix; /* namespace localname N, called prefix */
uint16_t x_flags; /* Flags according to XML_FLAG_* */
struct xml *x_up; /* parent node in hierarchy if any */
#ifdef XML_PARENT_CANDIDATE
struct xml *x_up_candidate; /* Candidate parent node for special cases (when+xpath) */
#endif
int _x_vector_i; /* internal use: xml_child_each */
int _x_i; /* internal use for sorting:
see xml_enumerate and xml_cmp */
@ -196,6 +199,9 @@ struct xmlbody{
char *xb_prefix; /* namespace localname N, called prefix */
uint16_t xb_flags; /* Flags according to XML_FLAG_* */
struct xml *xb_up; /* parent node in hierarchy if any */
#ifdef XML_PARENT_CANDIDATE
struct xml *xb_up_candidate; /* Candidate parent node for special cases (when+xpath) */
#endif
int _xb_vector_i; /* internal use: xml_child_each */
int _xb_i; /* internal use for sorting:
see xml_enumerate and xml_cmp */
@ -251,6 +257,7 @@ xml_stats_one(cxobj *x,
{
size_t sz = 0;
if (x->x_name)
sz += strlen(x->x_name) + 1;
if (x->x_prefix)
@ -587,6 +594,34 @@ xml_parent_set(cxobj *xn,
return 0;
}
#ifdef XML_PARENT_CANDIDATE
/*! Get candidate parent of xnode
* @param[in] xn xml node
* @retval parent xml node
*/
cxobj*
xml_parent_candidate(cxobj *xn)
{
if (xn == NULL) {
return NULL;
}
return xn->x_up_candidate;
}
/*! Set candidate parent of xml node
* @param[in] xn xml node
* @param[in] parent pointer to candidate parent xml node
* @retval 0 OK
*/
int
xml_parent_candidate_set(cxobj *xn,
cxobj *parent)
{
xn->x_up_candidate = parent;
return 0;
}
#endif /* XML_PARENT_CANDIDATE */
/*! Get xml node flags, used for internal algorithms
* @param[in] xn xml node
* @retval flag Flag value(s), see XML_FLAG_MARK et al
@ -1420,8 +1455,7 @@ xml_child_rm(cxobj *xp,
* @param[in] xc xml child node to be removed
* @retval 0 OK
* @retval -1 Error
* @note you should not remove xchild in loop (unless yoy keep track of xprev)
*
* @note you should not remove xchild in loop (unless you keep track of xprev)
* @see xml_child_rm Remove a child of a node
*/
int

View file

@ -392,7 +392,12 @@ xp_eval_step(xp_ctx *xc0,
xc->xc_nodeset = NULL;
for (i=0; i<veclen; i++){
x = vec[i];
if ((xp = xml_parent(x)) != NULL)
if ((xp = xml_parent(x)) != NULL
#ifdef XML_PARENT_CANDIDATE
/* Also check "candidate" parent for special when use-case */
|| (xp = xml_parent_candidate(x)) != NULL
#endif /* XML_PARENT_CANDIDATE */
)
if (cxvec_append(xp, &xc->xc_nodeset, &xc->xc_size) < 0)
goto done;
}
@ -979,8 +984,13 @@ xp_eval(xp_ctx *xc,
case XP_ABSPATH:
/* Set context node to top node, and nodeset to that node only */
x = xc->xc_node;
#ifdef XML_PARENT_CANDIDATE
while (xml_parent(x) != NULL || xml_parent_candidate(x) != NULL)
x = xml_parent(x)?xml_parent(x):xml_parent_candidate(x);
#else
while (xml_parent(x) != NULL)
x = xml_parent(x);
#endif
xc->xc_node = x;
xc->xc_nodeset[0] = x;
xc->xc_size=1;