* Added XPATH functions position
This commit is contained in:
parent
8f81eb1c66
commit
fab261cb53
13 changed files with 98 additions and 23 deletions
|
|
@ -27,6 +27,10 @@
|
|||
|
||||
## 4.9.0 Expected: 15 Dec 2020
|
||||
|
||||
### Minor changes
|
||||
|
||||
* Added XPATH functions `position`
|
||||
|
||||
## 4.8.0
|
||||
18 October 2020
|
||||
|
||||
|
|
|
|||
|
|
@ -534,7 +534,7 @@ from_client_get_config(clicon_handle h,
|
|||
}
|
||||
if (ret == 0){
|
||||
if (netconf_bad_attribute(cbret, "application",
|
||||
"<bad-attribute>depth</bad-attribute>", "Unrecognized value of depth attribute") < 0)
|
||||
"depth", "Unrecognized value of depth attribute") < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
|
|
@ -1044,6 +1044,7 @@ from_client_get(clicon_handle h,
|
|||
int i;
|
||||
cxobj *xerr = NULL;
|
||||
int ret;
|
||||
char *reason = NULL;
|
||||
|
||||
clicon_debug(1, "%s", __FUNCTION__);
|
||||
username = clicon_username_get(h);
|
||||
|
|
@ -1074,14 +1075,13 @@ from_client_get(clicon_handle h,
|
|||
content = netconf_content_str2int(attr);
|
||||
/* Clixon extensions: depth */
|
||||
if ((attr = xml_find_value(xe, "depth")) != NULL){
|
||||
char *reason = NULL;
|
||||
if ((ret = parse_int32(attr, &depth, &reason)) < 0){
|
||||
clicon_err(OE_XML, errno, "parse_int32");
|
||||
goto done;
|
||||
}
|
||||
if (ret == 0){
|
||||
if (netconf_bad_attribute(cbret, "application",
|
||||
"<bad-attribute>depth</bad-attribute>", "Unrecognized value of depth attribute") < 0)
|
||||
"depth", "Unrecognized value of depth attribute") < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
|
|
@ -1206,6 +1206,8 @@ from_client_get(clicon_handle h,
|
|||
retval = 0;
|
||||
done:
|
||||
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval);
|
||||
if (reason)
|
||||
free(reason);
|
||||
if (xerr)
|
||||
xml_free(xerr);
|
||||
if (xpath)
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ api_data_get2(clicon_handle h,
|
|||
clicon_debug(1, "%s content=%s", __FUNCTION__, attr);
|
||||
if ((int)(content = netconf_content_str2int(attr)) == -1){
|
||||
if (netconf_bad_attribute_xml(&xerr, "application",
|
||||
"<bad-attribute>content</bad-attribute>", "Unrecognized value of content attribute") < 0)
|
||||
"content", "Unrecognized value of content attribute") < 0)
|
||||
goto done;
|
||||
if ((xe = xpath_first(xerr, NULL, "rpc-error")) == NULL){
|
||||
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
|
||||
|
|
@ -181,7 +181,7 @@ api_data_get2(clicon_handle h,
|
|||
}
|
||||
if (ret==0){
|
||||
if (netconf_bad_attribute_xml(&xerr, "application",
|
||||
"<bad-attribute>depth</bad-attribute>", "Unrecognized value of depth attribute") < 0)
|
||||
"depth", "Unrecognized value of depth attribute") < 0)
|
||||
goto done;
|
||||
if ((xe = xpath_first(xerr, NULL, "rpc-error")) == NULL){
|
||||
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ struct xp_ctx{
|
|||
enum xp_objtype xc_type;
|
||||
cxobj **xc_nodeset; /* if type XT_NODESET */
|
||||
int xc_size; /* Length of nodeset */
|
||||
int xc_position;
|
||||
int xc_bool; /* if xc_type XT_BOOL */
|
||||
double xc_number; /* if xc_type XT_NUMBER */
|
||||
char *xc_string; /* if xc_type XT_STRING */
|
||||
|
|
|
|||
|
|
@ -274,7 +274,7 @@ netconf_missing_attribute(cbuf *cb,
|
|||
* out of range, pattern mismatch.
|
||||
* @param[out] cb CLIgen buf. Error XML is written in this buffer
|
||||
* @param[in] type Error type: "rpc", "application" or "protocol"
|
||||
* @param[in] info bad-attribute or bad-element xml
|
||||
* @param[in] info Attribute name
|
||||
* @param[in] message Error message (will be XML encoded)
|
||||
*/
|
||||
int
|
||||
|
|
@ -303,7 +303,7 @@ netconf_bad_attribute(cbuf *cb,
|
|||
* out of range, pattern mismatch.
|
||||
* @param[out] xret Error XML tree. Free with xml_free after use
|
||||
* @param[in] type Error type: "rpc", "application" or "protocol"
|
||||
* @param[in] info bad-attribute or bad-element xml
|
||||
* @param[in] info Attribute name
|
||||
* @param[in] message Error message (will be XML encoded)
|
||||
*/
|
||||
int
|
||||
|
|
@ -331,7 +331,7 @@ netconf_bad_attribute_xml(cxobj **xret,
|
|||
goto done;
|
||||
if (clixon_xml_parse_va(YB_NONE, NULL, &xerr, NULL, "<error-type>%s</error-type>"
|
||||
"<error-tag>bad-attribute</error-tag>"
|
||||
"<error-info>%s</error-info>"
|
||||
"<error-info><bad-attribute>%s</bad-attribute></error-info>"
|
||||
"<error-severity>error</error-severity>", type, info) < 0)
|
||||
goto done;
|
||||
if (message){
|
||||
|
|
@ -348,7 +348,6 @@ netconf_bad_attribute_xml(cxobj **xret,
|
|||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/*! Create Netconf unknown-attribute error XML tree according to RFC 6241 App A
|
||||
*
|
||||
* An unexpected attribute is present.
|
||||
|
|
|
|||
|
|
@ -494,6 +494,7 @@ xp_eval_predicate(xp_ctx *xc,
|
|||
xcc->xc_type = XT_NODESET;
|
||||
xcc->xc_initial = xc->xc_initial;
|
||||
xcc->xc_node = x;
|
||||
xcc->xc_position = i;
|
||||
/* For each node in the node-set to be filtered, the PredicateExpr is
|
||||
* evaluated with that node as the context node */
|
||||
if (cxvec_append(x, &xcc->xc_nodeset, &xcc->xc_size) < 0)
|
||||
|
|
@ -746,12 +747,35 @@ xp_relop(xp_ctx *xc1,
|
|||
xr->xc_bool = (xc1->xc_bool == xc2->xc_bool);
|
||||
break;
|
||||
case XT_NUMBER:
|
||||
switch(op){
|
||||
case XO_EQ:
|
||||
xr->xc_bool = (xc1->xc_number == xc2->xc_number);
|
||||
break;
|
||||
case XO_NE:
|
||||
xr->xc_bool = (xc1->xc_number != xc2->xc_number);
|
||||
break;
|
||||
case XO_GE:
|
||||
xr->xc_bool = (xc1->xc_number >= xc2->xc_number);
|
||||
break;
|
||||
case XO_LE:
|
||||
xr->xc_bool = (xc1->xc_number <= xc2->xc_number);
|
||||
break;
|
||||
case XO_LT:
|
||||
xr->xc_bool = (xc1->xc_number < xc2->xc_number);
|
||||
break;
|
||||
case XO_GT:
|
||||
xr->xc_bool = (xc1->xc_number > xc2->xc_number);
|
||||
break;
|
||||
default:
|
||||
clicon_err(OE_XML, 0, "Operator %s not supported for nodeset/nodeset comparison", clicon_int2str(xpopmap,op));
|
||||
goto done;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case XT_STRING:
|
||||
xr->xc_bool = (strcmp(xc1->xc_string, xc2->xc_string)==0);
|
||||
break;
|
||||
}
|
||||
} /* switch xc1 */
|
||||
}
|
||||
else if (xc1->xc_type != XT_NODESET &&
|
||||
xc2->xc_type != XT_NODESET){
|
||||
|
|
@ -991,6 +1015,11 @@ xp_eval(xp_ctx *xc,
|
|||
goto done;
|
||||
goto ok;
|
||||
break;
|
||||
case XPATHFN_POSITION:
|
||||
if (xp_function_position(xc, xs->xs_c0, nsc, localonly, xrp) < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
break;
|
||||
case XPATHFN_COUNT:
|
||||
if (xp_function_count(xc, xs->xs_c0, nsc, localonly, xrp) < 0)
|
||||
goto done;
|
||||
|
|
|
|||
|
|
@ -376,6 +376,41 @@ xp_function_derived_from(xp_ctx *xc,
|
|||
return retval;
|
||||
}
|
||||
|
||||
/*! Return a number equal to the context position from the expression evaluation context.
|
||||
*
|
||||
* Signature: number position(node-set)
|
||||
* @param[in] xc0 Incoming context
|
||||
* @param[in] xs XPATH node tree
|
||||
* @param[in] nsc XML Namespace context
|
||||
* @param[in] localonly Skip prefix and namespace tests (non-standard)
|
||||
* @param[out] xrp Resulting context
|
||||
* @retval 0 OK
|
||||
* @retval -1 Error
|
||||
*/
|
||||
int
|
||||
xp_function_position(xp_ctx *xc0,
|
||||
struct xpath_tree *xs,
|
||||
cvec *nsc,
|
||||
int localonly,
|
||||
xp_ctx **xrp)
|
||||
{
|
||||
int retval = -1;
|
||||
xp_ctx *xr = NULL;
|
||||
|
||||
if ((xr = malloc(sizeof(*xr))) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "malloc");
|
||||
goto done;
|
||||
}
|
||||
memset(xr, 0, sizeof(*xr));
|
||||
xr->xc_initial = xc0->xc_initial;
|
||||
xr->xc_type = XT_NUMBER;
|
||||
xr->xc_number = xc0->xc_position;
|
||||
*xrp = xr;
|
||||
retval = 0;
|
||||
done:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! The count function returns the number of nodes in the argument node-set.
|
||||
*
|
||||
* Signature: number count(node-set)
|
||||
|
|
@ -527,7 +562,7 @@ xp_function_contains(xp_ctx *xc,
|
|||
|
||||
/*! The not function returns true if its argument is false, and false otherwise.
|
||||
*
|
||||
* Signatire: boolean contains(boolean)
|
||||
* Signature: boolean not(boolean)
|
||||
*/
|
||||
int
|
||||
xp_function_not(xp_ctx *xc0,
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ enum clixon_xpath_function{
|
|||
XPATHFN_ENUM_VALUE, /* RFC 7950 10.5.1 NYI */
|
||||
XPATHFN_BIT_IS_SET, /* RFC 7950 10.6.1 NYI */
|
||||
XPATHFN_LAST, /* XPATH 1.0 4.1 NYI */
|
||||
XPATHFN_POSITION, /* XPATH 1.0 4.1 NYI */
|
||||
XPATHFN_POSITION, /* XPATH 1.0 4.1 */
|
||||
XPATHFN_COUNT, /* XPATH 1.0 4.1 */
|
||||
XPATHFN_ID, /* XPATH 1.0 4.1 NYI */
|
||||
XPATHFN_LOCAL_NAME, /* XPATH 1.0 4.1 NYI */
|
||||
|
|
@ -96,6 +96,7 @@ const char *xp_fnname_int2str(enum clixon_xpath_function code);
|
|||
int xp_function_current(xp_ctx *xc, struct xpath_tree *xs, cvec *nsc, int localonly, xp_ctx **xrp);
|
||||
int xp_function_deref(xp_ctx *xc, struct xpath_tree *xs, cvec *nsc, int localonly, xp_ctx **xrp);
|
||||
int xp_function_derived_from(xp_ctx *xc, struct xpath_tree *xs, cvec *nsc, int localonly, int self, xp_ctx **xrp);
|
||||
int xp_function_position(xp_ctx *xc, struct xpath_tree *xs, cvec *nsc, int localonly, xp_ctx **xrp);
|
||||
int xp_function_count(xp_ctx *xc, struct xpath_tree *xs, cvec *nsc, int localonly, xp_ctx **xrp);
|
||||
int xp_function_name(xp_ctx *xc, struct xpath_tree *xs, cvec *nsc, int localonly, xp_ctx **xrp);
|
||||
int xp_function_contains(xp_ctx *xc, struct xpath_tree *xs, cvec *nsc, int localonly, xp_ctx **xrp);
|
||||
|
|
|
|||
|
|
@ -235,7 +235,6 @@ xp_primary_function(clixon_xpath_yacc *xpy,
|
|||
case XPATHFN_ENUM_VALUE:
|
||||
case XPATHFN_BIT_IS_SET:
|
||||
case XPATHFN_LAST:
|
||||
case XPATHFN_POSITION:
|
||||
case XPATHFN_ID:
|
||||
case XPATHFN_LOCAL_NAME:
|
||||
case XPATHFN_NAMESPACE_URI:
|
||||
|
|
@ -269,6 +268,7 @@ xp_primary_function(clixon_xpath_yacc *xpy,
|
|||
case XPATHFN_DEREF:
|
||||
case XPATHFN_DERIVED_FROM:
|
||||
case XPATHFN_DERIVED_FROM_OR_SELF:
|
||||
case XPATHFN_POSITION:
|
||||
case XPATHFN_COUNT:
|
||||
case XPATHFN_NAME:
|
||||
case XPATHFN_CONTAINS:
|
||||
|
|
|
|||
|
|
@ -103,4 +103,12 @@ for cmd1 in $cmds; do
|
|||
println "Mem test $cmd1 done"
|
||||
done
|
||||
|
||||
if [ $err -eq 0 ]; then
|
||||
echo OK
|
||||
else
|
||||
echo -e "\e[31mError"
|
||||
echo -ne "\e[0m"
|
||||
exit -1
|
||||
fi
|
||||
|
||||
unset pattern
|
||||
|
|
|
|||
|
|
@ -98,8 +98,8 @@ done
|
|||
new "Openconfig test: $clixon_cli -1f $cfg -y $f show version ($m modules)"
|
||||
for f in $files; do
|
||||
if [ -n "$(head -1 $f|grep '^module')" ]; then
|
||||
new "$clixon_cli -1f $cfg -y $f show version"
|
||||
expectfn "$clixon_cli -1f $cfg -y $f show version" 0 "$version."
|
||||
new "$clixon_cli -D $DBG -1f $cfg -y $f show version"
|
||||
expectfn "$clixon_cli -D $DBG -1f $cfg -y $f show version" 0 "$version."
|
||||
fi
|
||||
|
||||
done
|
||||
|
|
|
|||
|
|
@ -301,7 +301,7 @@ new "add one entry (c) to leaf-list"
|
|||
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><y0 xmlns=\"urn:example:order\">c</y0></config></edit-config></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
|
||||
|
||||
new "add one entry (a) to leaf-list first (with no yang namespace - error)"
|
||||
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><y0 xmlns=\"urn:example:order\" yang:insert=\"first\">a</y0></config></edit-config></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><rpc-error><error-type>application</error-type><error-tag>bad-attribute</error-tag><error-info>insert</error-info><error-severity>error</error-severity><error-message>Unresolved attribute prefix (no namespace?)</error-message></rpc-error></rpc-reply>]]>]]>$"
|
||||
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><y0 xmlns=\"urn:example:order\" yang:insert=\"first\">a</y0></config></edit-config></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><rpc-error><error-type>application</error-type><error-tag>bad-attribute</error-tag><error-info><bad-attribute>insert</bad-attribute></error-info><error-severity>error</error-severity><error-message>Unresolved attribute prefix (no namespace?)</error-message></rpc-error></rpc-reply>]]>]]>$"
|
||||
|
||||
new "add one entry (b) to leaf-list first"
|
||||
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><y0 xmlns=\"urn:example:order\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:insert=\"first\">b</y0></config></edit-config></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
|
||||
|
|
@ -354,7 +354,7 @@ new "add one entry (key c) to list"
|
|||
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><y2 xmlns=\"urn:example:order\"><k>c</k><a>foo</a></y2></config></edit-config></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
|
||||
|
||||
new "add one entry (key a) to list first (with no yang namespace - error)"
|
||||
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><y2 xmlns=\"urn:example:order\" yang:insert=\"first\"><k>a</k><a>foo</a></y2></config></edit-config></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><rpc-error><error-type>application</error-type><error-tag>bad-attribute</error-tag><error-info>insert</error-info><error-severity>error</error-severity><error-message>Unresolved attribute prefix (no namespace?)</error-message></rpc-error></rpc-reply>]]>]]>$"
|
||||
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><y2 xmlns=\"urn:example:order\" yang:insert=\"first\"><k>a</k><a>foo</a></y2></config></edit-config></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><rpc-error><error-type>application</error-type><error-tag>bad-attribute</error-tag><error-info><bad-attribute>insert</bad-attribute></error-info><error-severity>error</error-severity><error-message>Unresolved attribute prefix (no namespace?)</error-message></rpc-error></rpc-reply>]]>]]>$"
|
||||
|
||||
new "add one entry (key b) to list first"
|
||||
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><y2 xmlns=\"urn:example:order\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:insert=\"first\"><k>b</k><a>bar</a></y2></config></edit-config></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
|
||||
|
|
|
|||
|
|
@ -1,10 +1,6 @@
|
|||
#!/usr/bin/env bash
|
||||
# Setup cligen and clixon
|
||||
|
||||
set -ux
|
||||
|
||||
#!/usr/bin/env bash
|
||||
set -eux # x
|
||||
set -eux
|
||||
|
||||
if [ $# -ne 3 ]; then
|
||||
echo "usage: $0 <release> <wwwuser> <with_restconf>"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue