data tree CHANGE lyd_attr -> lyd_meta
Also generic tree structures prepared.
diff --git a/src/common.h b/src/common.h
index a556e5a..bcc2426 100644
--- a/src/common.h
+++ b/src/common.h
@@ -237,6 +237,7 @@
#define LY_VCODE_DUPCASE LYVE_DATA, "Data for both cases \"%s\" and \"%s\" exist."
#define LY_VCODE_NOIFF LYVE_DATA, "Data are disabled by \"%s\" schema node if-feature."
#define LY_VCODE_INSTATE LYVE_DATA, "Invalid state data node \"%s\" found."
+#define LY_VCODE_NOKEY LYVE_DATA, "List instance is missing its key \"%s\"."
/******************************************************************************
* Context
diff --git a/src/parser_xml.c b/src/parser_xml.c
index f5c8cb8..28238bf 100644
--- a/src/parser_xml.c
+++ b/src/parser_xml.c
@@ -47,7 +47,7 @@
#define LYD_PARSER_BUFSIZE 4078
char path[LYD_PARSER_BUFSIZE]; /**< buffer for the generated path */
struct ly_set incomplete_type_validation; /**< set of nodes validated with LY_EINCOMPLETE result */
- struct ly_set incomplete_type_validation_attrs; /**< set of attributes validated with LY_EINCOMPLETE result */
+ struct ly_set incomplete_type_validation_meta; /**< set of metdata validated with LY_EINCOMPLETE result */
struct ly_set when_check; /**< set of nodes with "when" conditions */
};
@@ -133,7 +133,7 @@
}
static LY_ERR
-lydxml_attributes(struct lyd_xml_ctx *ctx, struct ly_set *attrs_data, const struct lysc_node *sparent, struct lyd_attr **attr)
+lydxml_metadata(struct lyd_xml_ctx *ctx, struct ly_set *attrs_data, const struct lysc_node *sparent, struct lyd_meta **meta)
{
LY_ERR ret = LY_EVALID, rc;
const struct lyxml_ns *ns;
@@ -146,7 +146,7 @@
/* in XML, all attributes must be prefixed
* TODO exception for NETCONF filters which are supposed to map to the ietf-netconf without prefix */
if (ctx->options & LYD_OPT_STRICT) {
- LOGVAL(ctx->ctx, LY_VLOG_LINE, &ctx->line, LYVE_REFERENCE, "Missing mandatory prefix for XML attribute \"%.*s\".",
+ LOGVAL(ctx->ctx, LY_VLOG_LINE, &ctx->line, LYVE_REFERENCE, "Missing mandatory prefix for XML metadata \"%.*s\".",
attr_data->name_len, attr_data->name);
}
skip_attr:
@@ -169,17 +169,17 @@
/* module is not implemented or not present in the schema */
if (ctx->options & LYD_OPT_STRICT) {
LOGVAL(ctx->ctx, LY_VLOG_LINE, &ctx->line, LYVE_REFERENCE,
- "Unknown (or not implemented) YANG module with namespace \"%s\" for attribute \"%.*s%s%.*s\".",
+ "Unknown (or not implemented) YANG module with namespace \"%s\" for metadata \"%.*s%s%.*s\".",
ns, attr_data->prefix_len, attr_data->prefix, attr_data->prefix_len ? ":" : "", attr_data->name_len,
attr_data->name);
}
goto skip_attr;
}
- rc = lyd_create_attr(NULL, attr, mod, attr_data->name, attr_data->name_len, attr_data->value,
+ rc = lyd_create_meta(NULL, meta, mod, attr_data->name, attr_data->name_len, attr_data->value,
attr_data->value_len, &attr_data->dynamic, lydxml_resolve_prefix, ctx, LYD_XML, sparent);
if (rc == LY_EINCOMPLETE) {
- ly_set_add(&ctx->incomplete_type_validation_attrs, attr, LY_SET_OPT_USEASLIST);
+ ly_set_add(&ctx->incomplete_type_validation_meta, meta, LY_SET_OPT_USEASLIST);
} else if (rc) {
ret = rc;
goto cleanup;
@@ -200,7 +200,7 @@
}
/**
- * @brief Parse XML elements as children YANG data node of the specified parent node.
+ * @brief Parse XML elements as YANG data node children the specified parent node.
*
* @param[in] ctx XML YANG data parser context.
* @param[in] parent Parent node where the children are inserted. NULL in case of parsing top-level elements.
@@ -209,14 +209,14 @@
* @return LY_ERR value.
*/
static LY_ERR
-lydxml_nodes(struct lyd_xml_ctx *ctx, struct lyd_node_inner *parent, const char **data, struct lyd_node **first)
+lydxml_data_r(struct lyd_xml_ctx *ctx, struct lyd_node_inner *parent, const char **data, struct lyd_node **first)
{
LY_ERR ret = LY_SUCCESS;
const char *prefix, *name;
size_t prefix_len, name_len;
struct ly_set attrs_data = {0};
const struct lyxml_ns *ns;
- struct lyd_attr *attr = NULL, *attr2;
+ struct lyd_meta *meta = NULL, *meta2;
const struct lysc_node *snode;
struct lys_module *mod;
unsigned int parents_count = ctx->elements.count;
@@ -271,9 +271,9 @@
return LY_EVALID;
}
- /* create actual attributes so that prefixes are available in the context */
+ /* create actual metadata so that prefixes are available in the context */
if (attrs_data.count) {
- LY_CHECK_GOTO(ret = lydxml_attributes(ctx, &attrs_data, snode, &attr), cleanup);
+ LY_CHECK_GOTO(ret = lydxml_metadata(ctx, &attrs_data, snode, &meta), cleanup);
}
if (snode->nodetype & (LYS_ACTION | LYS_NOTIF)) {
@@ -344,7 +344,13 @@
/* process children */
if (ctx->status == LYXML_ELEMENT && parents_count != ctx->elements.count) {
- ret = lydxml_nodes(ctx, (struct lyd_node_inner *)cur, data, lyd_node_children_p(cur));
+ ret = lydxml_data_r(ctx, (struct lyd_node_inner *)cur, data, lyd_node_children_p(cur));
+ LY_CHECK_GOTO(ret, cleanup);
+ }
+
+ if (snode->nodetype == LYS_LIST) {
+ /* check all keys exist */
+ ret = lyd_parse_check_keys(cur);
LY_CHECK_GOTO(ret, cleanup);
}
@@ -426,18 +432,18 @@
/* node is valid */
cur->flags &= ~LYD_NEW;
}
- LY_LIST_FOR(attr, attr2) {
- if (!strcmp(attr2->name, "default") && !strcmp(attr2->annotation->module->name, "ietf-netconf-with-defaults")
- && attr2->value.boolean) {
+ LY_LIST_FOR(meta, meta2) {
+ if (!strcmp(meta2->name, "default") && !strcmp(meta2->annotation->module->name, "ietf-netconf-with-defaults")
+ && meta2->value.boolean) {
/* node is default according to the metadata */
cur->flags |= LYD_DEFAULT;
}
}
- /* add attributes */
- assert(!cur->attr);
- cur->attr = attr;
- attr = NULL;
+ /* add metdata */
+ assert(!cur->meta);
+ cur->meta = meta;
+ meta = NULL;
/* insert */
lyd_insert_node((struct lyd_node *)parent, first, cur);
@@ -450,7 +456,7 @@
cleanup:
free(buffer);
- lyd_free_attr(ctx->ctx, attr, 1);
+ lyd_free_meta(ctx->ctx, meta, 1);
lyd_free_tree(cur);
for (unsigned int u = 0; u < attrs_data.count; ++u) {
if (((struct attr_data_s*)attrs_data.objs[u])->dynamic) {
@@ -466,7 +472,7 @@
}
LY_ERR
-lyd_parse_xml(struct ly_ctx *ctx, const char *data, int options, struct lyd_node **tree)
+lyd_parse_xml_data(struct ly_ctx *ctx, const char *data, int options, struct lyd_node **tree)
{
LY_ERR ret = LY_SUCCESS;
struct lyd_xml_ctx xmlctx = {0};
@@ -482,7 +488,7 @@
*tree = NULL;
/* parse XML data */
- ret = lydxml_nodes(&xmlctx, NULL, &data, tree);
+ ret = lydxml_data_r(&xmlctx, NULL, &data, tree);
LY_CHECK_GOTO(ret, cleanup);
if (!(options & LYD_OPT_PARSE_ONLY)) {
@@ -514,7 +520,7 @@
/* finish incompletely validated terminal values/attributes and when conditions */
ret = lyd_validate_unres(tree, &xmlctx.when_check, &xmlctx.incomplete_type_validation,
- &xmlctx.incomplete_type_validation_attrs, LYD_XML, lydxml_resolve_prefix, ctx);
+ &xmlctx.incomplete_type_validation_meta, LYD_XML, lydxml_resolve_prefix, ctx);
LY_CHECK_GOTO(ret, cleanup);
/* perform final validation that assumes the data tree is final */
@@ -526,10 +532,10 @@
cleanup:
/* there should be no unresolved types stored */
assert(!(options & LYD_OPT_PARSE_ONLY) || (!xmlctx.incomplete_type_validation.count
- && !xmlctx.incomplete_type_validation_attrs.count && !xmlctx.when_check.count));
+ && !xmlctx.incomplete_type_validation_meta.count && !xmlctx.when_check.count));
ly_set_erase(&xmlctx.incomplete_type_validation, NULL);
- ly_set_erase(&xmlctx.incomplete_type_validation_attrs, NULL);
+ ly_set_erase(&xmlctx.incomplete_type_validation_meta, NULL);
ly_set_erase(&xmlctx.when_check, NULL);
lyxml_context_clear((struct lyxml_context *)&xmlctx);
if (ret) {
@@ -538,3 +544,90 @@
}
return ret;
}
+
+static LY_ERR
+lydxml_rpc(struct lyd_xml_ctx *ctx, const char **data, struct ly_attr **attr)
+{
+ const char *prefix, *name;
+ size_t prefix_len, name_len;
+ struct ly_set attrs_data = {0};
+ const struct lyxml_ns *ns;
+
+ LY_CHECK_RET(lyxml_get_element((struct lyxml_context *)ctx, data, &prefix, &prefix_len, &name, &name_len));
+ if (ly_strncmp("rpc", name, name_len)) {
+ /* not an rpc */
+ return LY_ENOT;
+ }
+
+ if (ctx->status == LYXML_ATTRIBUTE) {
+ LY_CHECK_RET(lydxml_attributes_parse(ctx, data, &attrs_data));
+ }
+
+ ns = lyxml_ns_get((struct lyxml_context *)ctx, prefix, prefix_len);
+ if (!ns || strcmp(ns->uri, "urn:ietf:params:xml:ns:netconf:base:1.0")) {
+ /* wrong namespace */
+ return LY_ENOT;
+ }
+
+ /* all fine, just parse the rest of the attributes */
+ if (attrs_data.count) {
+ /* TODO parse into generic attribute structure, that will also be returned */
+ //LY_CHECK_RET(lydxml_attributes(ctx, &attrs_data, NULL, meta));
+ }
+
+ return LY_SUCCESS;
+}
+
+static LY_ERR
+lydxml_action(struct lyd_xml_ctx *ctx, const char **data)
+{
+ /* TODO */
+ return LY_ENOT;
+}
+
+LY_ERR
+lyd_parse_xml_rpc(struct ly_ctx *ctx, const char *data, struct lyd_node **tree, struct ly_attr **attr,
+ struct lyd_node **op)
+{
+ LY_ERR ret = LY_SUCCESS;
+ const char *data_p;
+ struct lyd_xml_ctx xmlctx = {0};
+
+ xmlctx.ctx = ctx;
+ xmlctx.line = 1;
+
+ /* init */
+ *tree = NULL;
+ data_p = data;
+
+ /* parse optional "rpc" element */
+ ret = lydxml_rpc(&xmlctx, &data_p, attr);
+ if (ret == LY_ENOT) {
+ /* reset data, nothing parsed */
+ data_p = data;
+ } else if (ret) {
+ goto cleanup;
+ } else {
+ /* successfully parsed */
+ data = data_p;
+
+ /* parse optional "action" element */
+ ret = lydxml_action(&xmlctx, &data_p);
+ if (ret == LY_ENOT) {
+ data_p = data;
+ } else if (ret) {
+ goto cleanup;
+ }
+ }
+
+ /* parse the rest of data tree normally */
+ ret = lydxml_data_r(&xmlctx, NULL, &data_p, tree);
+ LY_CHECK_GOTO(ret, cleanup);
+
+cleanup:
+ if (ret) {
+ lyd_free_all(*tree);
+ *tree = NULL;
+ }
+ return ret;
+}
diff --git a/src/printer_xml.c b/src/printer_xml.c
index 1dce096..44e8ff4 100644
--- a/src/printer_xml.c
+++ b/src/printer_xml.c
@@ -79,18 +79,18 @@
xml_print_ns(struct xmlpr_ctx *ctx, const struct lyd_node *node)
{
struct lyd_node *next, *cur, *child;
- struct lyd_attr *attr;
+ struct lyd_meta *meta;
struct mlist *mlist = NULL, *miter;
const struct lys_module *wdmod = NULL;
- /* add node attribute modules */
- for (attr = node->attr; attr; attr = attr->next) {
+ /* add node metadata modules */
+ for (meta = node->meta; meta; meta = meta->next) {
if (!strcmp(node->schema->name, "filter") &&
(!strcmp(node->schema->module->name, "ietf-netconf") ||
!strcmp(node->schema->module->name, "notifications"))) {
/* exception for NETCONF's filter attributes */
continue;
- } else if (modlist_add(&mlist, attr->annotation->module)) {
+ } else if (modlist_add(&mlist, meta->annotation->module)) {
goto print;
}
}
@@ -123,14 +123,14 @@
LY_LIST_FOR(((struct lyd_node_inner*)node)->child, child) {
LYD_TREE_DFS_BEGIN(child, next, cur) {
- for (attr = cur->attr; attr; attr = attr->next) {
+ for (meta = cur->meta; meta; meta = meta->next) {
if (!strcmp(cur->schema->name, "filter") &&
(!strcmp(cur->schema->module->name, "ietf-netconf") ||
!strcmp(cur->schema->module->name, "notifications"))) {
/* exception for NETCONF's filter attributes */
continue;
} else {
- /* TODO annotations r = modlist_add(&mlist, lys_main_module(attr->annotation->module)); */
+ /* TODO annotations r = modlist_add(&mlist, lys_main_module(meta->annotation->module)); */
}
}
LYD_TREE_DFS_END(child, next, cur)}
@@ -169,9 +169,9 @@
* TODO
*/
static LY_ERR
-xml_print_attrs(struct xmlpr_ctx *ctx, const struct lyd_node *node)
+xml_print_meta(struct xmlpr_ctx *ctx, const struct lyd_node *node)
{
- struct lyd_attr *attr;
+ struct lyd_meta *meta;
const struct lys_module *wdmod = NULL;
#if 0
const char **prefs, **nss;
@@ -205,8 +205,8 @@
rpc_filter = 1;
}
#endif
- for (attr = node->attr; attr; attr = attr->next) {
- const char *value = attr->value.realtype->plugin->print(&attr->value, LYD_XML, xml_print_get_prefix, &ns_list, &dynamic);
+ for (meta = node->meta; meta; meta = meta->next) {
+ const char *value = meta->value.realtype->plugin->print(&meta->value, LYD_XML, xml_print_get_prefix, &ns_list, &dynamic);
/* print namespaces connected with the values's prefixes */
for (u = 0; u < ns_list.count; ++u) {
@@ -218,9 +218,9 @@
#if 0
if (rpc_filter) {
/* exception for NETCONF's filter's attributes */
- if (!strcmp(attr->name, "select")) {
+ if (!strcmp(meta->name, "select")) {
/* xpath content, we have to convert the JSON format into XML first */
- xml_expr = transform_json2xml(node->schema->module, attr->value_str, 0, &prefs, &nss, &ns_count);
+ xml_expr = transform_json2xml(node->schema->module, meta->value_str, 0, &prefs, &nss, &ns_count);
if (!xml_expr) {
/* error */
return EXIT_FAILURE;
@@ -232,10 +232,10 @@
free(prefs);
free(nss);
}
- ly_print(out, " %s=\"", attr->name);
+ ly_print(out, " %s=\"", meta->name);
} else {
#endif
- ly_print(ctx->out, " %s:%s=\"", attr->annotation->module->prefix, attr->name);
+ ly_print(ctx->out, " %s:%s=\"", meta->annotation->module->prefix, meta->name);
#if 0
}
#endif
@@ -276,7 +276,7 @@
ctx->toplevel = 0;
}
- LY_CHECK_RET(xml_print_attrs(ctx, node));
+ LY_CHECK_RET(xml_print_meta(ctx, node));
return LY_SUCCESS;
}
diff --git a/src/tree.h b/src/tree.h
index 0f02120..bf86260 100644
--- a/src/tree.h
+++ b/src/tree.h
@@ -15,6 +15,8 @@
#ifndef LY_TREE_H_
#define LY_TREE_H_
+#include "tree_data.h"
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -117,6 +119,33 @@
(ELEM) = (NEXT))
/**
+ * @brief Generic tree node structure.
+ */
+struct ly_node {
+ LYD_FORMAT format;
+ union {
+ struct {
+ const struct lysc_node *schema;
+ struct lyd_meta *meta;
+ } sch;
+ struct {
+ const char *name;
+ struct ly_attr *attr;
+ } xml;
+ };
+ const char *value;
+};
+
+/**
+ * @brief Generic attribute structure.
+ */
+struct ly_attr {
+ struct ly_attr *next;
+ const char *name;
+ const char *value;
+};
+
+/**
* @brief YANG built-in types
*/
typedef enum
@@ -149,36 +178,6 @@
*/
extern const char* ly_data_type2str[LY_DATA_TYPE_COUNT];
-/**
- * @brief Callback provided by the data/schema parsers to type plugins to resolve (format-specific) mapping between prefixes used
- * in the value strings to the YANG schemas.
- *
- * Reverse function to ly_clb_get_prefix.
- *
- * XML uses XML namespaces, JSON uses schema names as prefixes, YIN/YANG uses prefixes of the imports.
- *
- * @param[in] ctx libyang context to find the schema.
- * @param[in] prefix Prefix found in the value string
- * @param[in] prefix_len Length of the @p prefix.
- * @param[in] private Internal data needed by the callback.
- * @return Pointer to the YANG schema identified by the provided prefix or NULL if no mapping found.
- */
-typedef const struct lys_module *(*ly_clb_resolve_prefix)(struct ly_ctx *ctx, const char *prefix, size_t prefix_len, void *private);
-
-/**
- * @brief Callback provided by the data/schema printers to type plugins to resolve (format-specific) mapping between YANG module of a data object
- * to prefixes used in the value strings.
- *
- * Reverse function to ly_clb_resolve_prefix.
- *
- * XML uses XML namespaces, JSON uses schema names as prefixes, YIN/YANG uses prefixes of the imports.
- *
- * @param[in] mod YANG module of the object.
- * @param[in] private Internal data needed by the callback.
- * @return String representing prefix for the object of the given YANG module @p mod.
- */
-typedef const char *(*ly_clb_get_prefix)(const struct lys_module *mod, void *private);
-
/** @} */
#ifdef __cplusplus
diff --git a/src/tree_data.c b/src/tree_data.c
index 9ab42ef..634ede6 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -112,7 +112,7 @@
}
LY_ERR
-lyd_value_parse_attr(struct ly_ctx *ctx, struct lyd_attr *attr, const char *value, size_t value_len, int *dynamic,
+lyd_value_parse_meta(struct ly_ctx *ctx, struct lyd_meta *meta, const char *value, size_t value_len, int *dynamic,
int second, ly_clb_resolve_prefix get_prefix, void *parser, LYD_FORMAT format,
const struct lysc_node *ctx_snode, const struct lyd_node *tree)
{
@@ -122,15 +122,15 @@
int options = LY_TYPE_OPTS_STORE | (second ? LY_TYPE_OPTS_SECOND_CALL : 0) |
(dynamic && *dynamic ? LY_TYPE_OPTS_DYNAMIC : 0) | (tree ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA);
- assert(ctx && attr && ((tree && attr->parent) || ctx_snode));
+ assert(ctx && meta && ((tree && meta->parent) || ctx_snode));
- ant = attr->annotation->data;
+ ant = meta->annotation->data;
if (!second) {
- attr->value.realtype = ant->type;
+ meta->value.realtype = ant->type;
}
ret = ant->type->plugin->store(ctx, ant->type, value, value_len, options, get_prefix, parser, format,
- tree ? (void *)attr->parent : (void *)ctx_snode, tree, &attr->value, NULL, &err);
+ tree ? (void *)meta->parent : (void *)ctx_snode, tree, &meta->value, NULL, &err);
if (ret && (ret != LY_EINCOMPLETE)) {
if (err) {
ly_err_print(err);
@@ -262,11 +262,11 @@
}
API const char *
-lyd_attr2str(const struct lyd_attr *attr, int *dynamic)
+lyd_meta2str(const struct lyd_meta *meta, int *dynamic)
{
- LY_CHECK_ARG_RET(attr ? attr->parent->schema->module->ctx : NULL, attr, dynamic, NULL);
+ LY_CHECK_ARG_RET(meta ? meta->parent->schema->module->ctx : NULL, meta, dynamic, NULL);
- return attr->value.realtype->plugin->print(&attr->value, LYD_JSON, json_print_get_prefix, NULL, dynamic);
+ return meta->value.realtype->plugin->print(&meta->value, LYD_JSON, json_print_get_prefix, NULL, dynamic);
}
API struct lyd_node *
@@ -306,7 +306,7 @@
switch (format) {
case LYD_XML:
- lyd_parse_xml(ctx, data, options, &result);
+ lyd_parse_xml_data(ctx, data, options, &result);
break;
#if 0
case LYD_JSON:
@@ -818,6 +818,8 @@
/**
* @brief Insert node after a sibling.
*
+ * Handles inserting into NP containers and key-less lists.
+ *
* @param[in] sibling Sibling to insert after.
* @param[in] node Node to insert.
*/
@@ -845,11 +847,15 @@
}
node->parent = sibling->parent;
- if (!(node->flags & LYD_DEFAULT)) {
- /* remove default flags from NP containers */
- for (par = node->parent; par && (par->flags & LYD_DEFAULT); par = par->parent) {
+ for (par = node->parent; par; par = par->parent) {
+ if ((par->flags & LYD_DEFAULT) && !(node->flags & LYD_DEFAULT)) {
+ /* remove default flags from NP containers */
par->flags &= ~LYD_DEFAULT;
}
+ if ((par->schema->nodetype == LYS_LIST) && (par->schema->flags & LYS_KEYLESS)) {
+ /* rehash key-less list */
+ lyd_hash((struct lyd_node *)par);
+ }
}
/* insert into hash table */
@@ -859,6 +865,8 @@
/**
* @brief Insert node before a sibling.
*
+ * Handles inserting into NP containers and key-less lists.
+ *
* @param[in] sibling Sibling to insert before.
* @param[in] node Node to insert.
*/
@@ -882,11 +890,15 @@
}
node->parent = sibling->parent;
- if (!(node->flags & LYD_DEFAULT)) {
- /* remove default flags from NP containers */
- for (par = node->parent; par && (par->flags & LYD_DEFAULT); par = par->parent) {
+ for (par = node->parent; par; par = par->parent) {
+ if ((par->flags & LYD_DEFAULT) && !(node->flags & LYD_DEFAULT)) {
+ /* remove default flags from NP containers */
par->flags &= ~LYD_DEFAULT;
}
+ if ((par->schema->nodetype == LYS_LIST) && (par->schema->flags & LYS_KEYLESS)) {
+ /* rehash key-less list */
+ lyd_hash((struct lyd_node *)par);
+ }
}
/* insert into hash table */
@@ -896,6 +908,8 @@
/**
* @brief Insert node as the last child of a parent.
*
+ * Handles inserting into NP containers and key-less lists.
+ *
* @param[in] parent Parent to insert into.
* @param[in] node Node to insert.
*/
@@ -918,11 +932,15 @@
}
node->parent = par;
- if (!(node->flags & LYD_DEFAULT)) {
- /* remove default flags from NP containers */
- for (; par && (par->flags & LYD_DEFAULT); par = par->parent) {
+ for (; par; par = par->parent) {
+ if ((par->flags & LYD_DEFAULT) && !(node->flags & LYD_DEFAULT)) {
+ /* remove default flags from NP containers */
par->flags &= ~LYD_DEFAULT;
}
+ if ((par->schema->nodetype == LYS_LIST) && (par->schema->flags & LYS_KEYLESS)) {
+ /* rehash key-less list */
+ lyd_hash((struct lyd_node *)par);
+ }
}
/* insert into hash table */
@@ -933,6 +951,8 @@
lyd_insert_node(struct lyd_node *parent, struct lyd_node **first_sibling, struct lyd_node *node)
{
struct lyd_node *anchor;
+ const struct lysc_node *skey = NULL;
+ int has_keys;
assert((parent || first_sibling) && node && node->hash);
@@ -951,6 +971,24 @@
} else {
lyd_insert_last_node(parent, node);
}
+
+ /* hash list if all its keys were added */
+ assert(parent->schema->nodetype == LYS_LIST);
+ anchor = (struct lyd_node *)lyd_node_children(parent);
+ has_keys = 1;
+ while ((skey = lys_getnext(skey, parent->schema, NULL, 0)) && (skey->flags & LYS_KEY)) {
+ if (!anchor || (anchor->schema != skey)) {
+ /* key missing */
+ has_keys = 0;
+ break;
+ }
+
+ anchor = anchor->next;
+ }
+ if (has_keys) {
+ lyd_hash(parent);
+ }
+
} else {
/* last child */
lyd_insert_last_node(parent, node);
@@ -1236,16 +1274,16 @@
}
LY_ERR
-lyd_create_attr(struct lyd_node *parent, struct lyd_attr **attr, const struct lys_module *mod, const char *name,
+lyd_create_meta(struct lyd_node *parent, struct lyd_meta **meta, const struct lys_module *mod, const char *name,
size_t name_len, const char *value, size_t value_len, int *dynamic, ly_clb_resolve_prefix get_prefix,
void *prefix_data, LYD_FORMAT format, const struct lysc_node *ctx_snode)
{
LY_ERR ret;
struct lysc_ext_instance *ant = NULL;
- struct lyd_attr *at, *last;
+ struct lyd_meta *mt, *last;
uint32_t v;
- assert((parent || attr) && mod);
+ assert((parent || meta) && mod);
LY_ARRAY_FOR(mod->compiled->exts, v) {
if (mod->compiled->exts[v].def->plugin == lyext_plugins_internal[LYEXT_PLUGIN_INTERNAL_ANNOTATION].plugin &&
@@ -1262,28 +1300,28 @@
return LY_EINVAL;
}
- at = calloc(1, sizeof *at);
- LY_CHECK_ERR_RET(!at, LOGMEM(mod->ctx), LY_EMEM);
- at->parent = parent;
- at->annotation = ant;
- ret = lyd_value_parse_attr(mod->ctx, at, value, value_len, dynamic, 0, get_prefix, prefix_data, format, ctx_snode, NULL);
+ mt = calloc(1, sizeof *mt);
+ LY_CHECK_ERR_RET(!mt, LOGMEM(mod->ctx), LY_EMEM);
+ mt->parent = parent;
+ mt->annotation = ant;
+ ret = lyd_value_parse_meta(mod->ctx, mt, value, value_len, dynamic, 0, get_prefix, prefix_data, format, ctx_snode, NULL);
if ((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE)) {
- free(at);
+ free(mt);
return ret;
}
- at->name = lydict_insert(mod->ctx, name, name_len);
+ mt->name = lydict_insert(mod->ctx, name, name_len);
/* insert as the last attribute */
if (parent) {
- if (parent->attr) {
- for (last = parent->attr; last->next; last = last->next);
- last->next = at;
+ if (parent->meta) {
+ for (last = parent->meta; last->next; last = last->next);
+ last->next = mt;
} else {
- parent->attr = at;
+ parent->meta = mt;
}
- } else if (*attr) {
- for (last = *attr; last->next; last = last->next);
- last->next = at;
+ } else if (*meta) {
+ for (last = *meta; last->next; last = last->next);
+ last->next = mt;
}
/* remove default flags from NP containers */
@@ -1292,8 +1330,8 @@
parent = (struct lyd_node *)parent->parent;
}
- if (attr) {
- *attr = at;
+ if (meta) {
+ *meta = mt;
}
return ret;
}
diff --git a/src/tree_data.h b/src/tree_data.h
index 8621539..34ddd46 100644
--- a/src/tree_data.h
+++ b/src/tree_data.h
@@ -207,21 +207,21 @@
};
/**
- * @brief Attribute structure.
+ * @brief Metadata structure.
*
- * The structure provides information about attributes of a data element. Such attributes must map to
+ * The structure provides information about metadata of a data element. Such attributes must map to
* annotations as specified in RFC 7952. The only exception is the filter type (in NETCONF get operations)
* and edit-config's operation attributes. In XML, they are represented as standard XML attributes. In JSON,
* they are represented as JSON elements starting with the '@' character (for more information, see the
* YANG metadata RFC.
*
*/
-struct lyd_attr {
- struct lyd_node *parent; /**< data node where the attribute is placed */
- struct lyd_attr *next; /**< pointer to the next attribute of the same element */
- struct lysc_ext_instance *annotation; /**< pointer to the attribute/annotation's definition */
- const char *name; /**< attribute name */
- struct lyd_value value; /**< attribute's value representation */
+struct lyd_meta {
+ struct lyd_node *parent; /**< data node where the metadata is placed */
+ struct lyd_meta *next; /**< pointer to the next metadata of the same element */
+ struct lysc_ext_instance *annotation; /**< pointer to the annotation's definition */
+ const char *name; /**< metadata name */
+ struct lyd_value value; /**< metadata value representation */
};
@@ -258,6 +258,36 @@
/** @} */
/**
+ * @brief Callback provided by the data/schema parsers to type plugins to resolve (format-specific) mapping between prefixes used
+ * in the value strings to the YANG schemas.
+ *
+ * Reverse function to ly_clb_get_prefix.
+ *
+ * XML uses XML namespaces, JSON uses schema names as prefixes, YIN/YANG uses prefixes of the imports.
+ *
+ * @param[in] ctx libyang context to find the schema.
+ * @param[in] prefix Prefix found in the value string
+ * @param[in] prefix_len Length of the @p prefix.
+ * @param[in] private Internal data needed by the callback.
+ * @return Pointer to the YANG schema identified by the provided prefix or NULL if no mapping found.
+ */
+typedef const struct lys_module *(*ly_clb_resolve_prefix)(struct ly_ctx *ctx, const char *prefix, size_t prefix_len, void *private);
+
+/**
+ * @brief Callback provided by the data/schema printers to type plugins to resolve (format-specific) mapping between YANG module of a data object
+ * to prefixes used in the value strings.
+ *
+ * Reverse function to ly_clb_resolve_prefix.
+ *
+ * XML uses XML namespaces, JSON uses schema names as prefixes, YIN/YANG uses prefixes of the imports.
+ *
+ * @param[in] mod YANG module of the object.
+ * @param[in] private Internal data needed by the callback.
+ * @return String representing prefix for the object of the given YANG module @p mod.
+ */
+typedef const char *(*ly_clb_get_prefix)(const struct lys_module *mod, void *private);
+
+/**
* @brief Generic structure for a data node.
*/
struct lyd_node {
@@ -274,7 +304,7 @@
never NULL. If there is no sibling node, pointer points to the node
itself. In case of the first node, this pointer points to the last
node in the list. */
- struct lyd_attr *attr; /**< pointer to the list of attributes of this node */
+ struct lyd_meta *meta; /**< pointer to the list of metadata of this node */
#ifdef LY_ENABLED_LYD_PRIV
void *priv; /**< private user data, not used by libyang */
@@ -297,7 +327,7 @@
never NULL. If there is no sibling node, pointer points to the node
itself. In case of the first node, this pointer points to the last
node in the list. */
- struct lyd_attr *attr; /**< pointer to the list of attributes of this node */
+ struct lyd_meta *meta; /**< pointer to the list of metadata of this node */
#ifdef LY_ENABLED_LYD_PRIV
void *priv; /**< private user data, not used by libyang */
@@ -324,7 +354,7 @@
never NULL. If there is no sibling node, pointer points to the node
itself. In case of the first node, this pointer points to the last
node in the list. */
- struct lyd_attr *attr; /**< pointer to the list of attributes of this node */
+ struct lyd_meta *meta; /**< pointer to the list of metadata of this node */
#ifdef LY_ENABLED_LYD_PRIV
void *priv; /**< private user data, not used by libyang */
@@ -349,7 +379,7 @@
never NULL. If there is no sibling node, pointer points to the node
itself. In case of the first node, this pointer points to the last
node in the list. */
- struct lyd_attr *attr; /**< pointer to the list of attributes of this node */
+ struct lyd_meta *meta; /**< pointer to the list of attributes of this node */
#ifdef LY_ENABLED_LYD_PRIV
void *priv; /**< private user data, not used by libyang */
@@ -374,16 +404,13 @@
* Default parser behavior:
* - complete input file is always parsed. In case of XML, even not well-formed XML document (multiple top-level
* elements) is parsed in its entirety,
- * - parser silently ignores data without matching schema node definition. If the caller wants to stop
- * parsing in case of presence of unknown data, the #LYD_OPT_STRICT can be used. The strict mode is useful for
- * NETCONF servers, since NETCONF clients should always send data according to the capabilities announced by the server.
- * On the other hand, the default non-strict mode is useful for clients receiving data from NETCONF server since
- * clients are not required to understand everything the server does. Of course, the optimal strategy for clients is
- * to use filtering to get only the required data. Having an unknown element of the known namespace is always an error.
+ * - parser silently ignores data without matching schema node definition,
+ * - list instances are checked whether they have all the keys, error is raised if not.
*
* Default parser validation behavior:
* - the provided data are expected to provide complete datastore content (both the configuration and state data)
* and performs data validation according to all YANG rules, specifics follow,
+ * - list instances are expected to have all the keys (it is not checked),
* - instantiated (status) obsolete data print a warning,
* - all types are fully resolved (leafref/instance-identifier targets, unions) and must be valid (lists have
* all the keys, leaf(-lists) correct values),
@@ -401,8 +428,6 @@
\<get\> operation. */
#define LYD_OPT_GETCONFIG LYD_OPT_PARSE_ONLY | LYD_OPT_NO_STATE /**< Data content from a NETCONF reply message to
the NETCONF \<get-config\> operation. */
-#define LYD_OPT_EDIT LYD_OPT_PARSE_ONLY | LYD_OPT_NO_STATE | LYD_OPT_EMPTY_INST /**< Content of
- the NETCONF \<edit-config\>'s config element. */
#define LYD_OPT_PARSE_ONLY 0x0001 /**< Data will be only parsed and no validation will be performed. When statements
are kept unevaluated, union types may not be fully resolved, if-feature
@@ -412,8 +437,7 @@
data are not valid, using this flag may lead to some unexpected behavior!
This flag can be used only with #LYD_OPT_PARSE_ONLY. */
#define LYD_OPT_STRICT 0x0004 /**< Instead of silently ignoring data without schema definition raise an error. */
-#define LYD_OPT_EMPTY_INST 0x0008 /**< Allow leaf/leaf-list instances without values and lists without keys. */
-#define LYD_OPT_NO_STATE 0x0010 /**< Forbid state data in the parsed data. */
+#define LYD_OPT_NO_STATE 0x0008 /**< Forbid state data in the parsed data. */
#define LYD_OPT_MASK 0xFFFF /**< Mask for all the parser options. */
@@ -696,14 +720,14 @@
void lyd_free_tree(struct lyd_node *node);
/**
- * @brief Destroy data attribute.
+ * @brief Destroy metadata.
*
- * @param[in] ctx Context where the attribute was created.
- * @param[in] attr Attribute to destroy
- * @param[in] recursive Zero to destroy only the attribute (the attribute list is corrected),
- * non-zero to destroy also all the subsequent attributes in the list.
+ * @param[in] ctx Context where the metadata was created.
+ * @param[in] meta Metadata to destroy
+ * @param[in] recursive Zero to destroy only the metadata (the metadata list is corrected),
+ * non-zero to destroy also all the subsequent metadata in the list.
*/
-void lyd_free_attr(struct ly_ctx *ctx, struct lyd_attr *attr, int recursive);
+void lyd_free_meta(struct ly_ctx *ctx, struct lyd_meta *meta, int recursive);
/**
* @brief Check type restrictions applicable to the particular leaf/leaf-list with the given string @p value.
@@ -837,13 +861,13 @@
const char *lyd_value2str(const struct lyd_node_term *node, int *dynamic);
/**
- * @brief Get string value of an attribute \p attr.
+ * @brief Get string value of a metadata \p meta.
*
- * @param[in] attr Attribute with the value.
+ * @param[in] meta Metadata with the value.
* @param[out] dynamic Whether the string value was dynmically allocated.
- * @return String value of @p attr, if @p dynamic, needs to be freed.
+ * @return String value of @p meta, if @p dynamic, needs to be freed.
*/
-const char *lyd_attr2str(const struct lyd_attr *attr, int *dynamic);
+const char *lyd_meta2str(const struct lyd_meta *meta, int *dynamic);
/**
* @brief Types of the different data paths.
diff --git a/src/tree_data_free.c b/src/tree_data_free.c
index aea9f7b..7aa63ae 100644
--- a/src/tree_data_free.c
+++ b/src/tree_data_free.c
@@ -43,45 +43,45 @@
}
API void
-lyd_free_attr(struct ly_ctx *ctx, struct lyd_attr *attr, int recursive)
+lyd_free_meta(struct ly_ctx *ctx, struct lyd_meta *meta, int recursive)
{
- struct lyd_attr *iter;
+ struct lyd_meta *iter;
LY_CHECK_ARG_RET(NULL, ctx, );
- if (!attr) {
+ if (!meta) {
return;
}
- if (attr->parent) {
- if (attr->parent->attr == attr) {
+ if (meta->parent) {
+ if (meta->parent->meta == meta) {
if (recursive) {
- attr->parent->attr = NULL;
+ meta->parent->meta = NULL;
} else {
- attr->parent->attr = attr->next;
+ meta->parent->meta = meta->next;
}
} else {
- for (iter = attr->parent->attr; iter->next != attr; iter = iter->next);
+ for (iter = meta->parent->meta; iter->next != meta; iter = iter->next);
if (iter->next) {
if (recursive) {
iter->next = NULL;
} else {
- iter->next = attr->next;
+ iter->next = meta->next;
}
}
}
}
if (!recursive) {
- attr->next = NULL;
+ meta->next = NULL;
}
- for(iter = attr; iter; ) {
- attr = iter;
+ for(iter = meta; iter; ) {
+ meta = iter;
iter = iter->next;
- FREE_STRING(ctx, attr->name);
- attr->value.realtype->plugin->free(ctx, &attr->value);
- free(attr);
+ FREE_STRING(ctx, meta->name);
+ meta->value.realtype->plugin->free(ctx, &meta->value);
+ free(meta);
}
}
@@ -129,8 +129,8 @@
((struct lysc_node_leaf*)node->schema)->type->plugin->free(ctx, &((struct lyd_node_term*)node)->value);
}
- /* free the node's attributes */
- lyd_free_attr(ctx, node->attr, 1);
+ /* free the node's metadata */
+ lyd_free_meta(ctx, node->meta, 1);
/* unlink only the nodes from the first level, nodes in subtree are freed all, so no unlink is needed */
if (top) {
diff --git a/src/tree_data_helpers.c b/src/tree_data_helpers.c
index 38e0d3d..90f5736 100644
--- a/src/tree_data_helpers.c
+++ b/src/tree_data_helpers.c
@@ -124,3 +124,24 @@
return mod;
}
+
+LY_ERR
+lyd_parse_check_keys(struct lyd_node *node)
+{
+ const struct lysc_node *skey = NULL;
+ const struct lyd_node *key;
+
+ assert(node->schema->nodetype == LYS_LIST);
+
+ key = lyd_node_children(node);
+ while ((skey = lys_getnext(skey, node->schema, NULL, 0)) && (skey->flags & LYS_KEY)) {
+ if (!key || (key->schema != skey)) {
+ LOGVAL(node->schema->module->ctx, LY_VLOG_LYD, node, LY_VCODE_NOKEY, skey->name);
+ return LY_EVALID;
+ }
+
+ key = key->next;
+ }
+
+ return LY_SUCCESS;
+}
diff --git a/src/tree_data_internal.h b/src/tree_data_internal.h
index 4600c3e..2d92f2e 100644
--- a/src/tree_data_internal.h
+++ b/src/tree_data_internal.h
@@ -124,8 +124,9 @@
/**
* @brief Insert a node into parent/siblings. In case a key is being inserted into a list, the correct position
- * is found and inserted into. Also, in case we are inserting into top-level siblings, insert it as
- * the last sibling of all the module data siblings. Otherwise it is inserted at the very last place.
+ * is found, inserted into, and if it is the last key, parent list hash is calculated. Also, in case we are inserting
+ * into top-level siblings, insert it as the last sibling of all the module data siblings. Otherwise it is inserted at
+ * the very last place.
*
* @param[in] parent Parent to insert into, NULL for top-level sibling.
* @param[in,out] first_sibling First sibling, NULL if no top-level sibling exist yet. Can be also NULL if @p parent is set.
@@ -137,8 +138,8 @@
* @brief Create and insert an attribute (last) into a parent.
*
* @param[in] parent Parent of the attribute, can be NULL.
- * @param[in,out] attr Attribute list to add at its end if @p parent is NULL, returned created attribute.
- * @param[in] mod Attribute module (with the annotation definition).
+ * @param[in,out] meta Metadata list to add at its end if @p parent is NULL, returned created attribute.
+ * @param[in] mod Metadata module (with the annotation definition).
* @param[in] name Attribute name.
* @param[in] name_len Length of @p name, must be set correctly.
* @param[in] value String value to be parsed.
@@ -152,7 +153,7 @@
* @return LY_EINCOMPLETE in case data tree is needed to finish the validation.
* @return LY_ERR value if an error occurred.
*/
-LY_ERR lyd_create_attr(struct lyd_node *parent, struct lyd_attr **attr, const struct lys_module *mod, const char *name,
+LY_ERR lyd_create_meta(struct lyd_node *parent, struct lyd_meta **meta, const struct lys_module *mod, const char *name,
size_t name_len, const char *value, size_t value_len, int *dynamic, ly_clb_resolve_prefix get_prefix,
void *prefix_data, LYD_FORMAT format, const struct lysc_node *ctx_snode);
@@ -178,10 +179,10 @@
ly_clb_resolve_prefix get_prefix, void *parser, LYD_FORMAT format, const struct lyd_node *tree);
/**
- * @brief Validate, canonize and store the given @p value into the attribute according to the metadata annotation type's rules.
+ * @brief Validate, canonize and store the given @p value into the metadata according to the annotation type's rules.
*
* @param[in] ctx libyang context.
- * @param[in] attr Data attribute for the @p value.
+ * @param[in] meta Metadata for the @p value.
* @param[in] value String value to be parsed, must not be NULL.
* @param[in] value_len Length of the give @p value, must be set correctly.
* @param[in,out] dynamic Flag if @p value is dynamically allocated, is adjusted when @p value is consumed.
@@ -197,7 +198,7 @@
* @return LY_EINCOMPLETE in case the @p trees is not provided and it was needed to finish the validation.
* @return LY_ERR value if an error occurred.
*/
-LY_ERR lyd_value_parse_attr(struct ly_ctx *ctx, struct lyd_attr *attr, const char *value, size_t value_len, int *dynamic,
+LY_ERR lyd_value_parse_meta(struct ly_ctx *ctx, struct lyd_meta *meta, const char *value, size_t value_len, int *dynamic,
int second, ly_clb_resolve_prefix get_prefix, void *parser, LYD_FORMAT format,
const struct lysc_node *ctx_snode, const struct lyd_node *tree);
@@ -205,12 +206,31 @@
* @brief Parse XML string as YANG data tree.
*
* @param[in] ctx libyang context
- * @param[in] data Pointer to the XML string representation of the YANG data to parse.
+ * @param[in] data Pointer to the XML data to parse.
* @param[in] options @ref dataparseroptions
* @param[out] tree Parsed data tree. Note that NULL can be a valid result.
- * @reutn LY_ERR value.
+ * @return LY_ERR value.
*/
-LY_ERR lyd_parse_xml(struct ly_ctx *ctx, const char *data, int options, struct lyd_node **tree);
+LY_ERR lyd_parse_xml_data(struct ly_ctx *ctx, const char *data, int options, struct lyd_node **tree);
+
+/**
+ * @brief Parse XML string as YANG RPC/action invocation.
+ *
+ * Optional \<rpc\> envelope element, if present, is [checked](https://tools.ietf.org/html/rfc6241#section-4.1) and all
+ * its XML attributes returned. In that case an RPC is expected to be parsed.
+ *
+ * Can be followed by optional \<action\> envelope element, which is also
+ * [checked](https://tools.ietf.org/html/rfc7950#section-7.15.2) and then an action is expected to be parsed.
+ *
+ * @param[in] ctx libyang context.
+ * @param[in] data Pointer to the XML data to parse.
+ * @param[out] tree Parsed RPC/action data tree.
+ * @param[out] attr Any found attributes on the rpc envelope.
+ * @param[out] op Pointer to the actual operation. Useful mainly for action.
+ * @return LY_ERR value.
+ */
+LY_ERR lyd_parse_xml_rpc(struct ly_ctx *ctx, const char *data, struct lyd_node **tree, struct ly_attr **attr,
+ struct lyd_node **op);
/**
* @defgroup datahash Data nodes hash manipulation
@@ -310,4 +330,12 @@
*/
const struct lys_module *lyd_data_next_module(struct lyd_node **next, struct lyd_node **first);
+/**
+ * @brief Check that a list has all its keys.
+ *
+ * @param[in] node List to check.
+ * @return LY_ERR value.
+ */
+LY_ERR lyd_parse_check_keys(struct lyd_node *node);
+
#endif /* LY_TREE_DATA_INTERNAL_H_ */
diff --git a/src/validation.c b/src/validation.c
index 5aee11f..b8168dd 100644
--- a/src/validation.c
+++ b/src/validation.c
@@ -125,7 +125,7 @@
}
LY_ERR
-lyd_validate_unres(struct lyd_node **tree, struct ly_set *node_when, struct ly_set *node_types, struct ly_set *attr_types,
+lyd_validate_unres(struct lyd_node **tree, struct ly_set *node_when, struct ly_set *node_types, struct ly_set *meta_types,
LYD_FORMAT format, ly_clb_resolve_prefix get_prefix_clb, void *parser_data)
{
LY_ERR ret = LY_SUCCESS;
@@ -196,21 +196,21 @@
} while (u);
}
- if (attr_types && attr_types->count) {
- /* ... and attribute values */
- u = attr_types->count;
+ if (meta_types && meta_types->count) {
+ /* ... and metadata values */
+ u = meta_types->count;
do {
--u;
- struct lyd_attr *attr = (struct lyd_attr *)attr_types->objs[u];
+ struct lyd_meta *meta = (struct lyd_meta *)meta_types->objs[u];
- /* validate and store the value of the node */
- ret = lyd_value_parse_attr(attr->parent->schema->module->ctx, attr, attr->value.original,
- strlen(attr->value.original), 0, 1, get_prefix_clb, parser_data, format, NULL, *tree);
+ /* validate and store the value of the metadata */
+ ret = lyd_value_parse_meta(meta->parent->schema->module->ctx, meta, meta->value.original,
+ strlen(meta->value.original), 0, 1, get_prefix_clb, parser_data, format, NULL, *tree);
LY_CHECK_RET(ret);
/* remove this attr from the set */
- ly_set_rm_index(attr_types, u, NULL);
+ ly_set_rm_index(meta_types, u, NULL);
} while (u);
}
@@ -948,8 +948,8 @@
LY_ERR ret = LY_SUCCESS;
struct lyd_node *first, *next, *node, **first2;
const struct lys_module *mod;
- const struct lyd_attr *attr;
- struct ly_set type_check = {0}, type_attr_check = {0}, when_check = {0};
+ const struct lyd_meta *meta;
+ struct ly_set type_check = {0}, type_meta_check = {0}, when_check = {0};
uint32_t i = 0;
LY_CHECK_ARG_RET(NULL, tree, *tree || ctx || (modules && mod_count), LY_EINVAL);
@@ -989,9 +989,9 @@
LYD_TREE_DFS_BEGIN(first, next, node) {
/* skip added default nodes */
if ((node->flags & (LYD_DEFAULT | LYD_NEW)) != (LYD_DEFAULT | LYD_NEW)) {
- LY_LIST_FOR(node->attr, attr) {
- /* attribute type resolution */
- ly_set_add(&type_attr_check, (void *)attr, LY_SET_OPT_USEASLIST);
+ LY_LIST_FOR(node->meta, meta) {
+ /* metadata type resolution */
+ ly_set_add(&type_meta_check, (void *)meta, LY_SET_OPT_USEASLIST);
}
if (node->schema->nodetype & LYD_NODE_TERM) {
@@ -1019,7 +1019,7 @@
}
/* finish incompletely validated terminal values/attributes and when conditions */
- ret = lyd_validate_unres(tree, &when_check, &type_check, &type_attr_check, LYD_JSON, lydjson_resolve_prefix, NULL);
+ ret = lyd_validate_unres(tree, &when_check, &type_check, &type_meta_check, LYD_JSON, lydjson_resolve_prefix, NULL);
LY_CHECK_GOTO(ret, cleanup);
/* perform final validation that assumes the data tree is final */
@@ -1029,7 +1029,7 @@
cleanup:
ly_set_erase(&type_check, NULL);
- ly_set_erase(&type_attr_check, NULL);
+ ly_set_erase(&type_meta_check, NULL);
ly_set_erase(&when_check, NULL);
return ret;
}
diff --git a/src/validation.h b/src/validation.h
index a99a1e5..a84999e 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -26,13 +26,13 @@
* @param[in,out] tree Data tree, is updated if some nodes are autodeleted.
* @param[in] node_when Set with nodes with "when" conditions, can be NULL.
* @param[in] node_types Set with nodes with unresolved types, can be NULL
- * @param[in] attr_types Set with attributes with unresolved types, can be NULL.
+ * @param[in] meta_types Set with metdata with unresolved types, can be NULL.
* @param[in] format Format of the unresolved data.
* @param[in] get_prefix_clb Format-specific getter to resolve prefixes.
* @param[in] parser_data Parser's data for @p get_prefix_clb.
* @return LY_ERR value.
*/
-LY_ERR lyd_validate_unres(struct lyd_node **tree, struct ly_set *node_when, struct ly_set *node_types, struct ly_set *attr_types,
+LY_ERR lyd_validate_unres(struct lyd_node **tree, struct ly_set *node_when, struct ly_set *node_types, struct ly_set *meta_types,
LYD_FORMAT format, ly_clb_resolve_prefix get_prefix_clb, void *parser_data);
/**
diff --git a/src/xpath.c b/src/xpath.c
index 7a5f430..f9a8009 100644
--- a/src/xpath.c
+++ b/src/xpath.c
@@ -214,9 +214,9 @@
}
}
break;
- case LYXP_NODE_ATTR:
- LOGDBG(LY_LDGXPATH, "\t%d (pos %u): ATTR %s = %s", i + 1, item->pos, set->val.attrs[i].attr->name,
- set->val.attrs[i].attr->value);
+ case LYXP_NODE_META:
+ LOGDBG(LY_LDGXPATH, "\t%d (pos %u): META %s = %s", i + 1, item->pos, set->val.meta[i].meta->name,
+ set->val.meta[i].meta->value);
break;
}
}
@@ -515,8 +515,8 @@
case LYXP_NODE_ELEM:
case LYXP_NODE_TEXT:
return cast_string_elem(set->val.nodes[0].node, 0, set->root_type, str);
- case LYXP_NODE_ATTR:
- *str = (char *)lyd_attr2str(set->val.attrs[0].attr, &dynamic);
+ case LYXP_NODE_META:
+ *str = (char *)lyd_meta2str(set->val.meta[0].meta, &dynamic);
if (!dynamic) {
*str = strdup(*str);
if (!*str) {
@@ -1397,8 +1397,8 @@
if (!set->val.nodes[i].pos) {
tmp_node = NULL;
switch (set->val.nodes[i].type) {
- case LYXP_NODE_ATTR:
- tmp_node = set->val.attrs[i].attr->parent;
+ case LYXP_NODE_META:
+ tmp_node = set->val.meta[i].meta->parent;
if (!tmp_node) {
LOGINT_RET(root->schema->module->ctx);
}
@@ -1421,22 +1421,22 @@
}
/**
- * @brief Get unique @p attr position in the parent attributes.
+ * @brief Get unique @p meta position in the parent metadata.
*
- * @param[in] attr Attr to use.
- * @return Attribute position.
+ * @param[in] meta Metadata to use.
+ * @return Metadata position.
*/
static uint16_t
-get_attr_pos(struct lyd_attr *attr)
+get_meta_pos(struct lyd_meta *meta)
{
uint16_t pos = 0;
- struct lyd_attr *attr2;
+ struct lyd_meta *meta2;
- for (attr2 = attr->parent->attr; attr2 && (attr2 != attr); attr2 = attr2->next) {
+ for (meta2 = meta->parent->meta; meta2 && (meta2 != meta); meta2 = meta2->next) {
++pos;
}
- assert(attr2);
+ assert(meta2);
return pos;
}
@@ -1450,7 +1450,7 @@
static int
set_sort_compare(struct lyxp_set_node *item1, struct lyxp_set_node *item2)
{
- uint32_t attr_pos1 = 0, attr_pos2 = 0;
+ uint32_t meta_pos1 = 0, meta_pos2 = 0;
if (item1->pos < item2->pos) {
return -1;
@@ -1474,39 +1474,39 @@
}
}
- /* we need attr positions now */
- if (item1->type == LYXP_NODE_ATTR) {
- attr_pos1 = get_attr_pos((struct lyd_attr *)item1->node);
+ /* we need meta positions now */
+ if (item1->type == LYXP_NODE_META) {
+ meta_pos1 = get_meta_pos((struct lyd_meta *)item1->node);
}
- if (item2->type == LYXP_NODE_ATTR) {
- attr_pos2 = get_attr_pos((struct lyd_attr *)item2->node);
+ if (item2->type == LYXP_NODE_META) {
+ meta_pos2 = get_meta_pos((struct lyd_meta *)item2->node);
}
- /* 1st ROOT - 2nd ROOT, 1st ELEM - 2nd ELEM, 1st TEXT - 2nd TEXT, 1st ATTR - =pos= - 2nd ATTR */
+ /* 1st ROOT - 2nd ROOT, 1st ELEM - 2nd ELEM, 1st TEXT - 2nd TEXT, 1st META - =pos= - 2nd META */
/* check for duplicates */
if (item1->node == item2->node) {
- assert((item1->type == item2->type) && ((item1->type != LYXP_NODE_ATTR) || (attr_pos1 == attr_pos2)));
+ assert((item1->type == item2->type) && ((item1->type != LYXP_NODE_META) || (meta_pos1 == meta_pos2)));
return 0;
}
- /* 1st ELEM - 2nd TEXT, 1st ELEM - any pos - 2nd ATTR */
+ /* 1st ELEM - 2nd TEXT, 1st ELEM - any pos - 2nd META */
/* elem is always first, 2nd node is after it */
if (item1->type == LYXP_NODE_ELEM) {
assert(item2->type != LYXP_NODE_ELEM);
return -1;
}
- /* 1st TEXT - 2nd ELEM, 1st TEXT - any pos - 2nd ATTR, 1st ATTR - any pos - 2nd ELEM, 1st ATTR - >pos> - 2nd ATTR */
+ /* 1st TEXT - 2nd ELEM, 1st TEXT - any pos - 2nd META, 1st META - any pos - 2nd ELEM, 1st META - >pos> - 2nd META */
/* 2nd is before 1st */
if (((item1->type == LYXP_NODE_TEXT)
- && ((item2->type == LYXP_NODE_ELEM) || (item2->type == LYXP_NODE_ATTR)))
- || ((item1->type == LYXP_NODE_ATTR) && (item2->type == LYXP_NODE_ELEM))
- || (((item1->type == LYXP_NODE_ATTR) && (item2->type == LYXP_NODE_ATTR))
- && (attr_pos1 > attr_pos2))) {
+ && ((item2->type == LYXP_NODE_ELEM) || (item2->type == LYXP_NODE_META)))
+ || ((item1->type == LYXP_NODE_META) && (item2->type == LYXP_NODE_ELEM))
+ || (((item1->type == LYXP_NODE_META) && (item2->type == LYXP_NODE_META))
+ && (meta_pos1 > meta_pos2))) {
return 1;
}
- /* 1st ATTR - any pos - 2nd TEXT, 1st ATTR <pos< - 2nd ATTR */
+ /* 1st META - any pos - 2nd TEXT, 1st META <pos< - 2nd META */
/* 2nd is after 1st */
return -1;
}
@@ -3867,7 +3867,7 @@
{
const struct lyd_node *node;
struct lysc_node_leaf *sleaf;
- struct lyd_attr *attr = NULL;
+ struct lyd_meta *meta = NULL;
const char *val;
int i, dynamic;
LY_ERR rc = LY_SUCCESS;
@@ -3901,8 +3901,8 @@
case LYXP_NODE_TEXT:
node = set->val.nodes[0].node;
break;
- case LYXP_NODE_ATTR:
- node = set->val.attrs[0].attr->parent;
+ case LYXP_NODE_META:
+ node = set->val.meta[0].meta->parent;
break;
default:
/* nothing to do with roots */
@@ -3910,25 +3910,25 @@
return LY_SUCCESS;
}
- /* find lang attribute */
+ /* find lang metadata */
for (; node; node = (struct lyd_node *)node->parent) {
- for (attr = node->attr; attr; attr = attr->next) {
+ for (meta = node->meta; meta; meta = meta->next) {
/* annotations */
- if (attr->name && !strcmp(attr->name, "lang") && !strcmp(attr->annotation->module->name, "xml")) {
+ if (meta->name && !strcmp(meta->name, "lang") && !strcmp(meta->annotation->module->name, "xml")) {
break;
}
}
- if (attr) {
+ if (meta) {
break;
}
}
/* compare languages */
- if (!attr) {
+ if (!meta) {
set_fill_boolean(set, 0);
} else {
- val = lyd_attr2str(attr, &dynamic);
+ val = lyd_meta2str(meta, &dynamic);
for (i = 0; args[0]->val.str[i]; ++i) {
if (tolower(args[0]->val.str[i]) != tolower(val[i])) {
set_fill_boolean(set, 0);
@@ -4044,8 +4044,8 @@
case LYXP_NODE_ELEM:
set_fill_string(set, item->node->schema->name, strlen(item->node->schema->name));
break;
- case LYXP_NODE_ATTR:
- set_fill_string(set, ((struct lyd_attr *)item->node)->name, strlen(((struct lyd_attr *)item->node)->name));
+ case LYXP_NODE_META:
+ set_fill_string(set, ((struct lyd_meta *)item->node)->name, strlen(((struct lyd_meta *)item->node)->name));
break;
}
@@ -4119,9 +4119,9 @@
mod = item->node->schema->module;
name = item->node->schema->name;
break;
- case LYXP_NODE_ATTR:
- mod = ((struct lyd_attr *)item->node)->annotation->module;
- name = ((struct lyd_attr *)item->node)->name;
+ case LYXP_NODE_META:
+ mod = ((struct lyd_meta *)item->node)->annotation->module;
+ name = ((struct lyd_meta *)item->node)->name;
break;
}
@@ -4208,12 +4208,12 @@
set_fill_string(set, "", 0);
break;
case LYXP_NODE_ELEM:
- case LYXP_NODE_ATTR:
+ case LYXP_NODE_META:
if (item->type == LYXP_NODE_ELEM) {
mod = item->node->schema->module;
- } else { /* LYXP_NODE_ATTR */
+ } else { /* LYXP_NODE_META */
/* annotations */
- mod = ((struct lyd_attr *)item->node)->annotation->module;
+ mod = ((struct lyd_meta *)item->node)->annotation->module;
}
set_fill_string(set, mod->ns, strlen(mod->ns));
@@ -5001,7 +5001,7 @@
case LYXP_NODE_ROOT:
case LYXP_NODE_ROOT_CONFIG:
case LYXP_NODE_TEXT:
- case LYXP_NODE_ATTR:
+ case LYXP_NODE_META:
set_remove_node(set, i);
break;
}
@@ -5551,7 +5551,7 @@
rc = moveto_resolve_model(&qname, &qname_len, set, &moveto_mod);
LY_CHECK_RET(rc);
- /* replace the original nodes (and throws away all text and attr nodes, root is replaced by a child) */
+ /* replace the original nodes (and throws away all text and meta nodes, root is replaced by a child) */
rc = moveto_node(set, "*", 1);
LY_CHECK_RET(rc);
@@ -5735,7 +5735,7 @@
uint32_t i;
int replaced, all = 0;
const struct lys_module *moveto_mod;
- struct lyd_attr *sub;
+ struct lyd_meta *sub;
LY_ERR rc;
if (!set || (set->type == LYXP_SET_EMPTY)) {
@@ -5760,7 +5760,7 @@
/* only attributes of an elem (not dummy) can be in the result, skip all the rest;
* our attributes are always qualified */
if (set->val.nodes[i].type == LYXP_NODE_ELEM) {
- for (sub = set->val.nodes[i].node->attr; sub; sub = sub->next) {
+ for (sub = set->val.nodes[i].node->meta; sub; sub = sub->next) {
/* check "namespace" */
if (moveto_mod && (sub->annotation->module != moveto_mod)) {
@@ -5770,12 +5770,12 @@
if (all || (!strncmp(sub->name, qname, qname_len) && !sub->name[qname_len])) {
/* match */
if (!replaced) {
- set->val.attrs[i].attr = sub;
- set->val.attrs[i].type = LYXP_NODE_ATTR;
+ set->val.meta[i].meta = sub;
+ set->val.meta[i].type = LYXP_NODE_META;
/* pos does not change */
replaced = 1;
} else {
- set_insert_node(set, (struct lyd_node *)sub, set->val.nodes[i].pos, LYXP_NODE_ATTR, i + 1);
+ set_insert_node(set, (struct lyd_node *)sub, set->val.nodes[i].pos, LYXP_NODE_META, i + 1);
}
++i;
}
@@ -5850,7 +5850,7 @@
{
uint32_t i;
int replaced, all = 0;
- struct lyd_attr *sub;
+ struct lyd_meta *sub;
const struct lys_module *moveto_mod;
struct lyxp_set *set_all_desc = NULL;
LY_ERR rc;
@@ -5895,7 +5895,7 @@
/* only attributes of an elem can be in the result, skip all the rest,
* we have all attributes qualified in lyd tree */
if (set->val.nodes[i].type == LYXP_NODE_ELEM) {
- for (sub = set->val.nodes[i].node->attr; sub; sub = sub->next) {
+ for (sub = set->val.nodes[i].node->meta; sub; sub = sub->next) {
/* check "namespace" */
if (moveto_mod && (sub->annotation->module != moveto_mod)) {
continue;
@@ -5904,12 +5904,12 @@
if (all || (!strncmp(sub->name, qname, qname_len) && !sub->name[qname_len])) {
/* match */
if (!replaced) {
- set->val.attrs[i].attr = sub;
- set->val.attrs[i].type = LYXP_NODE_ATTR;
+ set->val.meta[i].meta = sub;
+ set->val.meta[i].type = LYXP_NODE_META;
/* pos does not change */
replaced = 1;
} else {
- set_insert_node(set, (struct lyd_node *)sub, set->val.attrs[i].pos, LYXP_NODE_ATTR, i + 1);
+ set_insert_node(set, (struct lyd_node *)sub, set->val.meta[i].pos, LYXP_NODE_META, i + 1);
}
++i;
}
@@ -6038,7 +6038,7 @@
set_insert_node(&ret_set, set->val.nodes[i].node, set->val.nodes[i].pos, set->val.nodes[i].type, ret_set.used);
/* do not touch attributes and text nodes */
- if ((set->val.nodes[i].type == LYXP_NODE_TEXT) || (set->val.nodes[i].type == LYXP_NODE_ATTR)) {
+ if ((set->val.nodes[i].type == LYXP_NODE_TEXT) || (set->val.nodes[i].type == LYXP_NODE_META)) {
continue;
}
@@ -6173,8 +6173,8 @@
new_node = (struct lyd_node *)node->parent;
} else if (set->val.nodes[i].type == LYXP_NODE_TEXT) {
new_node = node;
- } else if (set->val.nodes[i].type == LYXP_NODE_ATTR) {
- new_node = set->val.attrs[i].attr->parent;
+ } else if (set->val.nodes[i].type == LYXP_NODE_META) {
+ new_node = set->val.meta[i].meta->parent;
if (!new_node) {
LOGINT_RET(set->ctx);
}
diff --git a/src/xpath.h b/src/xpath.h
index d645920..117ca36 100644
--- a/src/xpath.h
+++ b/src/xpath.h
@@ -134,9 +134,9 @@
LYXP_NODE_ROOT_CONFIG, /* <running> data context, no state data (node value first top-level node) */
/* XML elements */
- LYXP_NODE_ELEM, /* XML element (most common) */
- LYXP_NODE_TEXT, /* XML text element (extremely specific use, unlikely to be ever needed) */
- LYXP_NODE_ATTR /* XML attribute (in YANG cannot happen, do not use for the context node) */
+ LYXP_NODE_ELEM, /* YANG data element (most common) */
+ LYXP_NODE_TEXT, /* YANG data text element (extremely specific use, unlikely to be ever needed) */
+ LYXP_NODE_META /* YANG metadata (do not use for the context node) */
};
/**
@@ -224,11 +224,11 @@
* >=3 - scnode is not in context because we are in a predicate and this scnode was used/will be used later */
int32_t in_ctx;
} *scnodes;
- struct lyxp_set_attr {
- struct lyd_attr *attr;
+ struct lyxp_set_meta {
+ struct lyd_meta *meta;
enum lyxp_node_type type;
- uint32_t pos; /* if node_type is LYXP_SET_NODE_ATTR, it is the parent node position */
- } *attrs;
+ uint32_t pos; /* if node_type is LYXP_SET_NODE_META, it is the parent node position */
+ } *meta;
char *str;
long double num;
int bool;
diff --git a/tests/src/test_parser_xml.c b/tests/src/test_parser_xml.c
index dcf6970..b5c3f4c 100644
--- a/tests/src/test_parser_xml.c
+++ b/tests/src/test_parser_xml.c
@@ -114,7 +114,7 @@
struct lyd_node *tree;
struct lyd_node_term *leaf;
- assert_int_equal(LY_SUCCESS, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_non_null(tree);
assert_int_equal(LYS_LEAF, tree->schema->nodetype);
assert_string_equal("foo", tree->schema->name);
@@ -131,7 +131,7 @@
/* make foo2 explicit */
data = "<foo2 xmlns=\"urn:tests:a\">default-val</foo2>";
- assert_int_equal(LY_SUCCESS, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_non_null(tree);
assert_int_equal(LYS_LEAF, tree->schema->nodetype);
assert_string_equal("foo2", tree->schema->name);
@@ -143,7 +143,7 @@
/* parse foo2 but make it implicit */
data = "<foo2 xmlns=\"urn:tests:a\" xmlns:wd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" wd:default=\"true\">default-val</foo2>";
- assert_int_equal(LY_SUCCESS, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_non_null(tree);
assert_int_equal(LYS_LEAF, tree->schema->nodetype);
assert_string_equal("foo2", tree->schema->name);
@@ -167,7 +167,7 @@
struct lyd_node *tree;
struct lyd_node_any *any;
- assert_int_equal(LY_SUCCESS, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_non_null(tree);
assert_int_equal(LYS_ANYDATA, tree->schema->nodetype);
assert_string_equal("any", tree->schema->name);
@@ -190,7 +190,7 @@
struct lyd_node_term *leaf;
/* check hashes */
- assert_int_equal(LY_SUCCESS, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_non_null(tree);
assert_int_equal(LYS_LIST, tree->schema->nodetype);
assert_string_equal("l1", tree->schema->name);
@@ -200,9 +200,27 @@
}
lyd_free_all(tree);
+ /* missing keys */
+ data = "<l1 xmlns=\"urn:tests:a\"><c>c</c><b>b</b></l1>";
+ assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ logbuf_assert("List instance is missing its key \"a\". /a:l1[b='b'][c='c']");
+
+ data = "<l1 xmlns=\"urn:tests:a\"><a>a</a></l1>";
+ assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ logbuf_assert("List instance is missing its key \"b\". /a:l1[a='a']");
+
+ data = "<l1 xmlns=\"urn:tests:a\"><b>b</b><a>a</a></l1>";
+ assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ logbuf_assert("List instance is missing its key \"c\". /a:l1[a='a'][b='b']");
+
+ /* key duplicate */
+ data = "<l1 xmlns=\"urn:tests:a\"><c>c</c><b>b</b><a>a</a><c>d</c></l1>";
+ assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ logbuf_assert("Duplicate instance of \"c\". /a:l1[a='a'][b='b'][c='d'][c='c']/c");
+
/* keys order */
data = "<l1 xmlns=\"urn:tests:a\"><d>d</d><a>a</a><c>c</c><b>b</b></l1>";
- assert_int_equal(LY_SUCCESS, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_non_null(tree);
assert_int_equal(LYS_LIST, tree->schema->nodetype);
assert_string_equal("l1", tree->schema->name);
@@ -219,7 +237,7 @@
lyd_free_all(tree);
data = "<l1 xmlns=\"urn:tests:a\"><c>c</c><b>b</b><a>a</a></l1>";
- assert_int_equal(LY_SUCCESS, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_non_null(tree);
assert_int_equal(LYS_LIST, tree->schema->nodetype);
assert_string_equal("l1", tree->schema->name);
@@ -234,7 +252,7 @@
logbuf_clean();
lyd_free_all(tree);
- assert_int_equal(LY_EVALID, lyd_parse_xml(ctx, data, LYD_OPT_STRICT, &tree));
+ assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_OPT_STRICT, &tree));
logbuf_assert("Invalid position of the key \"b\" in a list. Line number 1.");
*state = NULL;
@@ -249,7 +267,7 @@
struct lyd_node *tree;
struct lyd_node_inner *cont;
- assert_int_equal(LY_SUCCESS, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_non_null(tree);
assert_int_equal(LYS_CONTAINER, tree->schema->nodetype);
assert_string_equal("c", tree->schema->name);
@@ -258,7 +276,7 @@
lyd_free_all(tree);
data = "<cp xmlns=\"urn:tests:a\"/>";
- assert_int_equal(LY_SUCCESS, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_non_null(tree);
assert_int_equal(LYS_CONTAINER, tree->schema->nodetype);
assert_string_equal("cp", tree->schema->name);
diff --git a/tests/src/test_validation.c b/tests/src/test_validation.c
index 4d4c614..d81ea74 100644
--- a/tests/src/test_validation.c
+++ b/tests/src/test_validation.c
@@ -221,6 +221,12 @@
"leaf-list ll {"
"type string;"
"}"
+ "leaf-list ll2 {"
+ "type enumeration {"
+ "enum one;"
+ "enum two;"
+ "}"
+ "}"
"}"
"}";
const char *schema_f =
@@ -402,19 +408,19 @@
struct lyd_node *tree;
data = "<c xmlns=\"urn:tests:a\">hey</c>";
- assert_int_equal(LY_EVALID, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_null(tree);
logbuf_assert("When condition \"/cont/b = 'val_b'\" not satisfied. /a:c");
data = "<cont xmlns=\"urn:tests:a\"><b>val_b</b></cont><c xmlns=\"urn:tests:a\">hey</c>";
- assert_int_equal(LY_SUCCESS, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_non_null(tree);
assert_string_equal("c", tree->next->schema->name);
assert_int_equal(LYD_WHEN_TRUE, tree->next->flags);
lyd_free_all(tree);
data = "<cont xmlns=\"urn:tests:a\"><a>val</a><b>val_b</b></cont><c xmlns=\"urn:tests:a\">val_c</c>";
- assert_int_equal(LY_SUCCESS, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_non_null(tree);
assert_string_equal("a", lyd_node_children(tree)->schema->name);
assert_int_equal(LYD_WHEN_TRUE, lyd_node_children(tree)->flags);
@@ -434,22 +440,22 @@
struct lyd_node *tree;
data = "<d xmlns=\"urn:tests:b\"/>";
- assert_int_equal(LY_EVALID, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_null(tree);
logbuf_assert("Mandatory node \"choic\" instance does not exist. /b:choic");
data = "<l xmlns=\"urn:tests:b\">string</l><d xmlns=\"urn:tests:b\"/>";
- assert_int_equal(LY_EVALID, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_null(tree);
logbuf_assert("Mandatory node \"c\" instance does not exist. /b:c");
data = "<a xmlns=\"urn:tests:b\">string</a>";
- assert_int_equal(LY_EVALID, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_null(tree);
logbuf_assert("Mandatory node \"c\" instance does not exist. /b:c");
data = "<a xmlns=\"urn:tests:b\">string</a><c xmlns=\"urn:tests:b\">string2</c>";
- assert_int_equal(LY_SUCCESS, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_non_null(tree);
lyd_free_siblings(tree);
@@ -465,14 +471,14 @@
struct lyd_node *tree;
data = "<d xmlns=\"urn:tests:c\"/>";
- assert_int_equal(LY_EVALID, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_null(tree);
logbuf_assert("Too few \"l\" instances. /c:choic/b/l");
data =
"<l xmlns=\"urn:tests:c\">val1</l>"
"<l xmlns=\"urn:tests:c\">val2</l>";
- assert_int_equal(LY_EVALID, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_null(tree);
logbuf_assert("Too few \"l\" instances. /c:choic/b/l");
@@ -480,7 +486,7 @@
"<l xmlns=\"urn:tests:c\">val1</l>"
"<l xmlns=\"urn:tests:c\">val2</l>"
"<l xmlns=\"urn:tests:c\">val3</l>";
- assert_int_equal(LY_SUCCESS, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_non_null(tree);
lyd_free_siblings(tree);
@@ -493,7 +499,7 @@
"<lt xmlns=\"urn:tests:c\"><k>val3</k></lt>"
"<lt xmlns=\"urn:tests:c\"><k>val4</k></lt>"
"<lt xmlns=\"urn:tests:c\"><k>val5</k></lt>";
- assert_int_equal(LY_EVALID, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_null(tree);
logbuf_assert("Too many \"lt\" instances. /c:lt");
@@ -516,7 +522,7 @@
"<lt xmlns=\"urn:tests:d\">"
"<k>val2</k>"
"</lt>";
- assert_int_equal(LY_SUCCESS, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_non_null(tree);
lyd_free_siblings(tree);
@@ -529,7 +535,7 @@
"<k>val2</k>"
"<l1>not-same</l1>"
"</lt>";
- assert_int_equal(LY_SUCCESS, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_non_null(tree);
lyd_free_siblings(tree);
@@ -542,7 +548,7 @@
"<k>val2</k>"
"<l1>same</l1>"
"</lt>";
- assert_int_equal(LY_EVALID, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_null(tree);
logbuf_assert("Unique data leaf(s) \"l1\" not satisfied in \"/d:lt[k='val1']\" and \"/d:lt[k='val2']\". /d:lt[k='val2']");
@@ -580,7 +586,7 @@
"<k>val8</k>"
"<l1>8</l1>"
"</lt>";
- assert_int_equal(LY_SUCCESS, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_non_null(tree);
lyd_free_siblings(tree);
@@ -614,7 +620,7 @@
"<lt xmlns=\"urn:tests:d\">"
"<k>val8</k>"
"</lt>";
- assert_int_equal(LY_SUCCESS, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_non_null(tree);
lyd_free_siblings(tree);
@@ -648,7 +654,7 @@
"<k>val8</k>"
"<l1>8</l1>"
"</lt>";
- assert_int_equal(LY_EVALID, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_null(tree);
logbuf_assert("Unique data leaf(s) \"l1\" not satisfied in \"/d:lt[k='val7']\" and \"/d:lt[k='val2']\". /d:lt[k='val2']");
@@ -720,7 +726,7 @@
"<l3>3</l3>"
"</lt3>"
"</lt2>";
- assert_int_equal(LY_SUCCESS, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY | LYD_OPT_STRICT, &tree));
+ assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY | LYD_OPT_STRICT, &tree));
assert_non_null(tree);
lyd_free_siblings(tree);
@@ -781,7 +787,7 @@
"<l3>3</l3>"
"</lt3>"
"</lt2>";
- assert_int_equal(LY_EVALID, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_null(tree);
logbuf_assert("Unique data leaf(s) \"l3\" not satisfied in \"/d:lt2[k='val2']/lt3[kk='val3']\" and"
" \"/d:lt2[k='val2']/lt3[kk='val1']\". /d:lt2[k='val2']/lt3[kk='val1']");
@@ -822,7 +828,7 @@
"</cont>"
"<l4>5</l4>"
"</lt2>";
- assert_int_equal(LY_EVALID, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_null(tree);
logbuf_assert("Unique data leaf(s) \"cont/l2 l4\" not satisfied in \"/d:lt2[k='val4']\" and \"/d:lt2[k='val2']\". /d:lt2[k='val2']");
@@ -870,7 +876,7 @@
"<l5>3</l5>"
"<l6>3</l6>"
"</lt2>";
- assert_int_equal(LY_EVALID, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_null(tree);
logbuf_assert("Unique data leaf(s) \"l5 l6\" not satisfied in \"/d:lt2[k='val5']\" and \"/d:lt2[k='val3']\". /d:lt2[k='val3']");
@@ -886,51 +892,51 @@
struct lyd_node *tree;
data = "<d xmlns=\"urn:tests:e\">25</d><d xmlns=\"urn:tests:e\">50</d>";
- assert_int_equal(LY_EVALID, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_null(tree);
logbuf_assert("Duplicate instance of \"d\". /e:d");
data = "<lt xmlns=\"urn:tests:e\"><k>A</k></lt><lt xmlns=\"urn:tests:e\"><k>B</k></lt><lt xmlns=\"urn:tests:e\"><k>A</k></lt>";
- assert_int_equal(LY_EVALID, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_null(tree);
logbuf_assert("Duplicate instance of \"lt\". /e:lt[k='A']");
data = "<ll xmlns=\"urn:tests:e\">A</ll><ll xmlns=\"urn:tests:e\">B</ll><ll xmlns=\"urn:tests:e\">B</ll>";
- assert_int_equal(LY_EVALID, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_null(tree);
logbuf_assert("Duplicate instance of \"ll\". /e:ll[.='B']");
data = "<cont xmlns=\"urn:tests:e\"></cont><cont xmlns=\"urn:tests:e\"/>";
- assert_int_equal(LY_EVALID, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_null(tree);
logbuf_assert("Duplicate instance of \"cont\". /e:cont");
/* same tests again but using hashes */
data = "<cont xmlns=\"urn:tests:e\"><d>25</d><d>50</d><ll>1</ll><ll>2</ll><ll>3</ll><ll>4</ll></cont>";
- assert_int_equal(LY_EVALID, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_null(tree);
logbuf_assert("Duplicate instance of \"d\". /e:cont/d");
data = "<cont xmlns=\"urn:tests:e\"><ll>1</ll><ll>2</ll><ll>3</ll><ll>4</ll>"
"<lt><k>a</k></lt><lt><k>b</k></lt><lt><k>c</k></lt><lt><k>d</k></lt><lt><k>c</k></lt></cont>";
- assert_int_equal(LY_EVALID, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_null(tree);
logbuf_assert("Duplicate instance of \"lt\". /e:cont/lt[k='c']");
data = "<cont xmlns=\"urn:tests:e\"><ll>1</ll><ll>2</ll><ll>3</ll><ll>4</ll>"
"<ll>a</ll><ll>b</ll><ll>c</ll><ll>d</ll><ll>d</ll></cont>";
- assert_int_equal(LY_EVALID, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_null(tree);
logbuf_assert("Duplicate instance of \"ll\". /e:cont/ll[.='d']");
/* cases */
data = "<l xmlns=\"urn:tests:e\">a</l><l xmlns=\"urn:tests:e\">b</l><l xmlns=\"urn:tests:e\">c</l><l xmlns=\"urn:tests:e\">b</l>";
- assert_int_equal(LY_EVALID, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_null(tree);
logbuf_assert("Duplicate instance of \"l\". /e:l[.='b']");
data = "<l xmlns=\"urn:tests:e\">a</l><l xmlns=\"urn:tests:e\">b</l><l xmlns=\"urn:tests:e\">c</l><a xmlns=\"urn:tests:e\">aa</a>";
- assert_int_equal(LY_EVALID, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_null(tree);
logbuf_assert("Data for both cases \"a\" and \"b\" exist. /e:choic");
@@ -1106,7 +1112,7 @@
"<cont xmlns=\"urn:tests:g\">"
"<d>51</d>"
"</cont>";
- assert_int_equal(LY_EVALID, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_null(tree);
logbuf_assert("Data are disabled by \"cont\" schema node if-feature. /g:cont");
@@ -1125,7 +1131,7 @@
"<e>val</e>"
"</cont2>"
"</cont>";
- assert_int_equal(LY_EVALID, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_null(tree);
logbuf_assert("Data are disabled by \"cont2\" schema node if-feature. /g:cont/cont2");
@@ -1133,14 +1139,14 @@
"<cont xmlns=\"urn:tests:g\">"
"<a>val</a>"
"</cont>";
- assert_int_equal(LY_EVALID, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_null(tree);
logbuf_assert("Data are disabled by \"choic\" schema node if-feature. /g:cont/a");
/* enable f3 */
assert_int_equal(lys_feature_enable(mod, "f3"), LY_SUCCESS);
- assert_int_equal(LY_SUCCESS, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_non_null(tree);
lyd_free_siblings(tree);
@@ -1149,14 +1155,14 @@
"<cont xmlns=\"urn:tests:g\">"
"<l>val</l>"
"</cont>";
- assert_int_equal(LY_EVALID, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_null(tree);
logbuf_assert("Data are disabled by \"b\" schema node if-feature. /g:cont/l");
/* enable f2 */
assert_int_equal(lys_feature_enable(mod, "f2"), LY_SUCCESS);
- assert_int_equal(LY_SUCCESS, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+ assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
assert_non_null(tree);
lyd_free_siblings(tree);
@@ -1173,7 +1179,7 @@
"<e>val</e>"
"</cont2>"
"</cont>";
- assert_int_equal(LY_SUCCESS, lyd_parse_xml(ctx, data, LYD_OPT_PARSE_ONLY, &tree));
+ assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_OPT_PARSE_ONLY, &tree));
assert_non_null(tree);
assert_int_equal(LY_EVALID, lyd_validate(&tree, NULL, LYD_VALOPT_DATA_ONLY));
@@ -1207,15 +1213,15 @@
"<l>val</l>"
"</cont2>"
"</cont>";
- assert_int_equal(LY_EVALID, lyd_parse_xml(ctx, data, LYD_OPT_PARSE_ONLY | LYD_OPT_NO_STATE, &tree));
+ assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_OPT_PARSE_ONLY | LYD_OPT_NO_STATE, &tree));
assert_null(tree);
logbuf_assert("Invalid state data node \"cont2\" found. Line number 1.");
- assert_int_equal(LY_EVALID, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY | LYD_VALOPT_NO_STATE, &tree));
+ assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY | LYD_VALOPT_NO_STATE, &tree));
assert_null(tree);
logbuf_assert("Invalid state data node \"cont2\" found. /h:cont/cont2");
- assert_int_equal(LY_SUCCESS, lyd_parse_xml(ctx, data, LYD_OPT_PARSE_ONLY, &tree));
+ assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_OPT_PARSE_ONLY, &tree));
assert_non_null(tree);
assert_int_equal(LY_EVALID, lyd_validate(&tree, NULL, LYD_VALOPT_DATA_ONLY | LYD_VALOPT_NO_STATE));
@@ -1238,6 +1244,7 @@
cmocka_unit_test_teardown(test_defaults, teardown_s),
cmocka_unit_test_teardown(test_iffeature, teardown_s),
cmocka_unit_test_teardown(test_state, teardown_s),
+ //cmocka_unit_test_teardown(test_edit, teardown_s),
};
return cmocka_run_group_tests(tests, setup, teardown);
diff --git a/tools/lint/commands.c b/tools/lint/commands.c
index b397950..90affdd 100644
--- a/tools/lint/commands.c
+++ b/tools/lint/commands.c
@@ -809,8 +809,8 @@
options |= LYD_OPT_GET;
} else if (!strcmp(optarg, "getconfig")) {
options |= LYD_OPT_GETCONFIG;
- } else if (!strcmp(optarg, "edit")) {
- options |= LYD_OPT_EDIT;
+ /*} else if (!strcmp(optarg, "edit")) {
+ options |= LYD_OPT_EDIT;*/
} else {
fprintf(stderr, "Invalid parser option \"%s\".\n", optarg);
cmd_data_help();
diff --git a/tools/lint/main_ni.c b/tools/lint/main_ni.c
index 99e7ce2..bd52fc7 100644
--- a/tools/lint/main_ni.c
+++ b/tools/lint/main_ni.c
@@ -519,8 +519,8 @@
options_parser |= LYD_OPT_GET;
} else if (!strcmp(optarg, "getconfig")) {
options_parser |= LYD_OPT_GETCONFIG;
- } else if (!strcmp(optarg, "edit")) {
- options_parser |= LYD_OPT_EDIT;
+ /*} else if (!strcmp(optarg, "edit")) {
+ options_parser |= LYD_OPT_EDIT;*/
} else if (!strcmp(optarg, "data")) {
/* no options */
} else {