diff --git a/apps/backend/backend_plugin.c b/apps/backend/backend_plugin.c
index f9675a35..1f55099c 100644
--- a/apps/backend/backend_plugin.c
+++ b/apps/backend/backend_plugin.c
@@ -388,7 +388,7 @@ clixon_plugin_statedata_all(clicon_handle h,
if (xml_sort_recurse(x) < 0)
goto done;
/* Remove global defaults and empty non-presence containers */
- if (xml_defaults_nopresence(x, 1) < 0)
+ if (xml_defaults_nopresence(x, 2) < 0)
goto done;
if (xml_default_recurse(x, 1) < 0)
goto done;
diff --git a/lib/src/clixon_datastore_read.c b/lib/src/clixon_datastore_read.c
index 2c663c91..2b65e51c 100644
--- a/lib/src/clixon_datastore_read.c
+++ b/lib/src/clixon_datastore_read.c
@@ -890,7 +890,7 @@ xmldb_get_cache(clicon_handle h,
goto done;
}
/* Remove global defaults and empty non-presence containers */
- if (xml_defaults_nopresence(x0t, 1) < 0)
+ if (xml_defaults_nopresence(x0t, 2) < 0)
goto done;
if (yb != YB_NONE){
/* Add default global values */
@@ -1163,7 +1163,7 @@ xmldb_get0_clear(clicon_handle h,
if (x == NULL)
goto ok;
/* Remove global defaults and empty non-presence containers */
- if (xml_defaults_nopresence(x, 1) < 0)
+ if (xml_defaults_nopresence(x, 2) < 0)
goto done;
/* Clear XML tree of defaults */
if (xml_tree_prune_flagged(x, XML_FLAG_TRANSIENT, 1) < 0)
diff --git a/lib/src/clixon_datastore_write.c b/lib/src/clixon_datastore_write.c
index e05ea2fc..15c5bcb8 100644
--- a/lib/src/clixon_datastore_write.c
+++ b/lib/src/clixon_datastore_write.c
@@ -1258,7 +1258,7 @@ xmldb_put(clicon_handle h,
(void*)(XML_FLAG_NONE|XML_FLAG_MARK)) < 0)
goto done;
/* Remove global defaults and empty non-presence containers */
- if (xml_defaults_nopresence(x0, 1) < 0)
+ if (xml_defaults_nopresence(x0, 2) < 0)
goto done;
#if 0 /* debug */
if (xml_apply0(x0, -1, xml_sort_verify, NULL) < 0)
diff --git a/lib/src/clixon_xml_map.c b/lib/src/clixon_xml_map.c
index d5f6f00f..81b35129 100644
--- a/lib/src/clixon_xml_map.c
+++ b/lib/src/clixon_xml_map.c
@@ -1103,11 +1103,14 @@ xml_global_defaults(clicon_handle h,
/*! Recursively find empty nopresence containers and default leaves, optionally purge
*
* @param[in] xn XML tree
- * @param[in] purge Remove sub-nodes that is empty non-presence container or default leaf
+ * @param[in] purge 0: Dont remove any nodes
+ * 1: Remove config sub-nodes that are empty non-presence container or default leaf
+ * 2: Remove all sub-nodes that are empty non-presence container or default leaf
* @retval 1 Node is an (recursive) empty non-presence container or default leaf
* @retval 0 Other node
* @retval -1 Error
* @note xn is not itself removed if purge
+ * @note for purge=1 are removed only if config or no yang spec(!)
*/
int
xml_defaults_nopresence(cxobj *xn,
@@ -1117,9 +1120,11 @@ xml_defaults_nopresence(cxobj *xn,
cxobj *x;
cxobj *xprev;
yang_stmt *yn;
+ yang_stmt *y;
int rmx = 0; /* If set, remove this xn */
int ret;
enum rfc_6020 keyw;
+ int config = 0;
if ((yn = xml_spec(xn)) != NULL){
keyw = yang_keyword_get(yn);
@@ -1129,6 +1134,7 @@ xml_defaults_nopresence(cxobj *xn,
else if (keyw == Y_LEAF &&
xml_flag(xn, XML_FLAG_DEFAULT))
rmx = 1;
+ config = yang_config_ancestor(yn);
}
/* Loop thru children */
x = NULL;
@@ -1137,14 +1143,26 @@ xml_defaults_nopresence(cxobj *xn,
if ((ret = xml_defaults_nopresence(x, purge)) < 0)
goto done;
if (ret == 1){
- if (purge){
+ switch (purge){
+ case 1: /* config nodes only */
+ if (!config)
+ break;
+ if ((y = xml_spec(x)) != NULL &&
+ !yang_config(y))
+ break;
+ /* fall thru */
+ case 2: /* purge all nodes */
if (xml_purge(x) < 0)
goto done;
x = xprev;
+ break;
+ default:
+ break;
}
}
else if (rmx)
- rmx = 0;
+ /* May switch an empty non-presence container (rmx=1) to non-empty non-presence container (rmx=0) */
+ rmx = 0;
}
retval = rmx;
done:
diff --git a/test/test_yang_with_defaults.sh b/test/test_yang_with_defaults.sh
index 455fa9db..988c7326 100755
--- a/test/test_yang_with_defaults.sh
+++ b/test/test_yang_with_defaults.sh
@@ -249,8 +249,12 @@ expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" \
Data already exists; cannot create new resource\
"
# nothing to commit here, but just to verify
+
+new "2.3.3 (part 1) commit"
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "" ""
+
# verify no change
+new "2.3.3 (part 1) verify"
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" \
"" "" \
"\
@@ -272,9 +276,13 @@ expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" \
none " \
"" \
""
+
# commit change
+new "2.3.3 (part 2) commit"
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "" ""
+
# verify that the mtu value has changed
+new "2.3.3 (part 2) verify"
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" \
"" "" \
"\
@@ -296,9 +304,13 @@ expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" \
none" \
"" \
""
+
# commit delete
+new "2.3.3 (part 3) commit"
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "" ""
-# check thet the default mtu vale has been restored
+
+# check that the default mtu vale has been restored
+new "2.3.3 (part 3) verify"
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" \
"" "" \
"\
@@ -325,9 +337,13 @@ expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" \
error\
Data does not exist; cannot delete resource\
"
+
# nothing to commit
+new "2.3.3 (part 4) commit"
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "" ""
+
# verify that the configuration has not changed
+new "2.3.3 (part 4) verify"
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" \
"" "" \
"\
@@ -411,13 +427,15 @@ expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" \
"
-new "rfc8040 4.3. RESTCONF GET"
+new "rfc8040 4.3. RESTCONF GET json"
expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+json' $RCPROTO://localhost/restconf/data/example:interfaces)" \
0 \
"HTTP/$HVER 200" \
"Content-Type: application/yang-data+json" \
"Cache-Control: no-cache" \
'{"example:interfaces":{"interface":\[{"name":"eth0","mtu":8192,"status":"ok"},{"name":"eth1","mtu":1500,"status":"ok"},{"name":"eth2","mtu":9000,"status":"not feeling so good"},{"name":"eth3","mtu":1500,"status":"waking up"}\]}}'
+
+new "rfc8040 4.3. RESTCONF GET xml"
expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' $RCPROTO://localhost/restconf/data/example:interfaces)" \
0 \
"HTTP/$HVER 200" \
@@ -425,13 +443,15 @@ expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' $RCPR
"Cache-Control: no-cache" \
'eth08192oketh11500oketh29000not feeling so goodeth31500waking up'
-new "rfc8040 B.3.9. RESTCONF with-defaults parameter = report-all"
+new "rfc8040 B.3.9. RESTCONF with-defaults parameter = report-all json"
expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+json' $RCPROTO://localhost/restconf/data/example:interfaces/interface=eth1?with-defaults=report-all)" \
0 \
"HTTP/$HVER 200" \
"Content-Type: application/yang-data+json" \
"Cache-Control: no-cache" \
'{"example:interface":\[{"name":"eth1","mtu":1500,"status":"ok"}\]}'
+
+new "rfc8040 B.3.9. RESTCONF with-defaults parameter = report-all xml"
expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' $RCPROTO://localhost/restconf/data/example:interfaces/interface=eth1?with-defaults=report-all)" \
0 \
"HTTP/$HVER 200" \
@@ -439,7 +459,7 @@ expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' $RCPR
"Cache-Control: no-cache" \
'eth11500ok'
-new "rfc8040 B.3.9. RESTONF with-defaults parameter = explicit"
+new "rfc8040 B.3.9. RESTONF with-defaults parameter = explicit "
expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+json' $RCPROTO://localhost/restconf/data/example:interfaces/interface=eth1?with-defaults=explicit)" \
0 \
"HTTP/$HVER 200" \