More XPath function support
* `count`, `name`, `contains`, `not`, as defined in [xpath 1.0](https://www.w3.org/TR/xpath-10) * `deref`, `derived-from` and `derived-from-or-self` from RFC7950 Section 10. * in particular in augment/when statements * Improved error handling * Verification of XPath functions is done at startup when yang modules are loaded, not when XPaths are evaluated. * Separation of "not found" and "not implemented" XPath functions * Both give a fatal error (backend does not start).
This commit is contained in:
parent
2994d2f9a9
commit
21ac47915b
14 changed files with 715 additions and 132 deletions
|
|
@ -217,7 +217,6 @@ nodetest_eval(cxobj *x,
|
|||
int localonly)
|
||||
{
|
||||
int retval = 0; /* NB: no match is default (not error) */
|
||||
char *fn;
|
||||
|
||||
if (xs->xs_type == XP_NODE){
|
||||
if (localonly)
|
||||
|
|
@ -226,11 +225,14 @@ nodetest_eval(cxobj *x,
|
|||
retval = nodetest_eval_node(x, xs, nsc);
|
||||
}
|
||||
else if (xs->xs_type == XP_NODE_FN){
|
||||
fn = xs->xs_s0;
|
||||
if (strcmp(fn, "node")==0)
|
||||
retval = 1;
|
||||
else if (strcmp(fn, "text")==0)
|
||||
switch (xs->xs_int){
|
||||
case XPATHFN_NODE:
|
||||
case XPATHFN_TEXT:
|
||||
retval = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* note, retval set by previous statement */
|
||||
return retval;
|
||||
|
|
@ -332,27 +334,21 @@ xp_eval_step(xp_ctx *xc0,
|
|||
xc->xc_descendant = 0;
|
||||
}
|
||||
else{
|
||||
if (nodetest->xs_type==XP_NODE_FN &&
|
||||
nodetest->xs_s0 &&
|
||||
strcmp(nodetest->xs_s0, "current")==0){
|
||||
if (cxvec_append(xc->xc_initial, &vec, &veclen) < 0)
|
||||
for (i=0; i<xc->xc_size; i++){
|
||||
xv = xc->xc_nodeset[i];
|
||||
x = NULL;
|
||||
if ((ret = xpath_optimize_check(xs, xv, &vec, &veclen)) < 0)
|
||||
goto done;
|
||||
}
|
||||
else for (i=0; i<xc->xc_size; i++){
|
||||
xv = xc->xc_nodeset[i];
|
||||
x = NULL;
|
||||
if ((ret = xpath_optimize_check(xs, xv, &vec, &veclen)) < 0)
|
||||
goto done;
|
||||
if (ret == 0){/* regular code, no optimization made */
|
||||
while ((x = xml_child_each(xv, x, CX_ELMNT)) != NULL) {
|
||||
/* xs->xs_c0 is nodetest */
|
||||
if (nodetest == NULL || nodetest_eval(x, nodetest, nsc, localonly) == 1){
|
||||
if (cxvec_append(x, &vec, &veclen) < 0)
|
||||
goto done;
|
||||
}
|
||||
if (ret == 0){/* regular code, no optimization made */
|
||||
while ((x = xml_child_each(xv, x, CX_ELMNT)) != NULL) {
|
||||
/* xs->xs_c0 is nodetest */
|
||||
if (nodetest == NULL || nodetest_eval(x, nodetest, nsc, localonly) == 1){
|
||||
if (cxvec_append(x, &vec, &veclen) < 0)
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ctx_nodeset_replace(xc, vec, veclen);
|
||||
break;
|
||||
|
|
@ -974,20 +970,51 @@ xp_eval(xp_ctx *xc,
|
|||
break;
|
||||
case XP_PRIME_FN:
|
||||
if (xs->xs_s0){
|
||||
if (strcmp(xs->xs_s0, "contains") == 0){
|
||||
if (xp_function_contains(xc, xs->xs_c0, nsc, localonly, xrp) < 0)
|
||||
switch (xs->xs_int){
|
||||
case XPATHFN_CURRENT:
|
||||
if (xp_function_current(xc, xs->xs_c0, nsc, localonly, xrp) < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
else if (strcmp(xs->xs_s0, "derived-from") == 0){
|
||||
break;
|
||||
case XPATHFN_DEREF:
|
||||
if (xp_function_deref(xc, xs->xs_c0, nsc, localonly, xrp) < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
break;
|
||||
case XPATHFN_DERIVED_FROM:
|
||||
if (xp_function_derived_from(xc, xs->xs_c0, nsc, localonly, 0, xrp) < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
else if (strcmp(xs->xs_s0, "derived-from-or-self") == 0){
|
||||
break;
|
||||
case XPATHFN_DERIVED_FROM_OR_SELF:
|
||||
if (xp_function_derived_from(xc, xs->xs_c0, nsc, localonly, 1, xrp) < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
break;
|
||||
case XPATHFN_COUNT:
|
||||
if (xp_function_count(xc, xs->xs_c0, nsc, localonly, xrp) < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
break;
|
||||
case XPATHFN_NAME:
|
||||
if (xp_function_name(xc, xs->xs_c0, nsc, localonly, xrp) < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
break;
|
||||
case XPATHFN_CONTAINS:
|
||||
if (xp_function_contains(xc, xs->xs_c0, nsc, localonly, xrp) < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
break;
|
||||
case XPATHFN_NOT:
|
||||
if (xp_function_not(xc, xs->xs_c0, nsc, localonly, xrp) < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
break;
|
||||
default:
|
||||
clicon_err(OE_XML, EFAULT, "XPATH function not implemented: %s", xs->xs_s0);
|
||||
goto done;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -1014,6 +1041,10 @@ xp_eval(xp_ctx *xc,
|
|||
case XP_UNION:
|
||||
break;
|
||||
case XP_PATHEXPR:
|
||||
if (xs->xs_c1)
|
||||
use_xr0++;
|
||||
break;
|
||||
case XP_FILTEREXPR:
|
||||
break;
|
||||
case XP_LOCPATH:
|
||||
break;
|
||||
|
|
@ -1098,7 +1129,14 @@ xp_eval(xp_ctx *xc,
|
|||
break;
|
||||
}
|
||||
xc->xc_descendant = 0;
|
||||
assert(xr0||xr1||xr2);
|
||||
#if 0
|
||||
assert(xr0||xr1||xr2); /* for debugging */
|
||||
#else
|
||||
if (xr0 == NULL && xr1 == NULL && xr2 == NULL){
|
||||
clicon_err(OE_XML, EFAULT, "Internal error: no result produced");
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
if (xr2){
|
||||
*xrp = xr2;
|
||||
xr2 = NULL;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue