parser CHANGE attribute parsing fixed and refactored
diff --git a/src/parser_xml.c b/src/parser_xml.c
index 3308b1e..4adb985 100644
--- a/src/parser_xml.c
+++ b/src/parser_xml.c
@@ -3,7 +3,7 @@
* @author Radek Krejci <rkrejci@cesnet.cz>
* @brief XML data parser for libyang
*
- * Copyright (c) 2015 CESNET, z.s.p.o.
+ * Copyright (c) 2015 - 2017 CESNET, z.s.p.o.
*
* This source code is licensed under BSD 3-Clause License (the "License").
* You may not use this file except in compliance with the License.
@@ -106,14 +106,13 @@
struct lyd_node **act_notif)
{
const struct lys_module *mod = NULL;
- const struct lys_submodule *submod;
struct lyd_node *diter, *dlast;
struct lys_node *schema = NULL, *target;
struct lys_node_augment *aug;
struct lyd_attr *dattr, *dattr_iter;
struct lyxml_attr *attr;
struct lyxml_elem *child, *next;
- int i, j, havechildren, r, pos, editbits = 0, filterflag = 0;
+ int i, j, havechildren, r, editbits = 0, pos, filterflag = 0, found;
int ret = 0;
const char *str = NULL;
@@ -300,80 +299,41 @@
/* NETCONF filter's attributes, which we implement as non-standard annotations,
* they are unqualified (no namespace), but we know that we have internally defined
* them in the ietf-netconf module, so the same module as the filter node itself */
- mod = (*result)->schema->module;
+ str = (*result)->schema->module->ns;
filterflag = 1;
} else {
/* garbage */
goto attr_error;
}
- } else { /* regular annotation */
- /* first, get module where the annotation should be defined */
- mod = (struct lys_module*)ly_ctx_get_module_by_ns(ctx, attr->ns->value, NULL);
- if (!mod) {
- goto attr_error;
- }
- }
- /* then, find the appropriate annotation definition */
- submod = NULL;
- pos = lys_ext_instance_presence(&ctx->models.list[0]->extensions[0], mod->ext, mod->ext_size);
- while (pos != -1 && ((unsigned int)(pos + 1) < mod->ext_size)
- && !ly_strequal(mod->ext[pos]->arg_value, attr->name, 1)) {
- i = lys_ext_instance_presence(&ctx->models.list[0]->extensions[0], &mod->ext[pos + 1],
- mod->ext_size - (pos + 1));
- pos = (i == -1) ? -1 : pos + 1 + i;
- }
- /* try submodules */
- for (j = 0; pos == -1 && j < mod->inc_size; j++) {
- submod = mod->inc[j].submodule;
- pos = lys_ext_instance_presence(&ctx->models.list[0]->extensions[0], submod->ext, submod->ext_size);
- while (pos != -1 && ((unsigned int)(pos + 1) < submod->ext_size)
- && !ly_strequal(submod->ext[pos]->arg_value, attr->name, 1)) {
- i = lys_ext_instance_presence(&ctx->models.list[0]->extensions[0], &submod->ext[pos + 1],
- submod->ext_size - (pos + 1));
- pos = (i == -1) ? -1 : pos + 1 + i;
- }
- }
- if (pos == -1) {
- goto attr_error;
+ } else {
+ str = attr->ns->value;
}
- /* allocate and fill the data attribute structure */
- dattr = calloc(1, sizeof *dattr);
- if (!dattr) {
+ r = lyp_fill_attr(ctx, *result, str, NULL, attr->name, attr->value, xml, &dattr);
+ if (r == -1) {
goto error;
+ } else if (r == 1) {
+attr_error:
+ if (options & LYD_OPT_STRICT) {
+ LOGVAL(LYE_INMETA, LY_VLOG_LYD, *result, (attr->ns ? attr->ns->prefix : "<none>"), attr->name, attr->value);
+ goto error;
+ }
+
+ LOGWRN("Unknown \"%s:%s\" metadata with value \"%s\", ignoring.",
+ (attr->ns ? attr->ns->prefix : "<none>"), attr->name, attr->value);
+ continue;
}
- dattr->parent = (*result);
- dattr->next = NULL;
- dattr->annotation = submod ? (struct lys_ext_instance_complex *)submod->ext[pos] :
- (struct lys_ext_instance_complex *)mod->ext[pos];
- dattr->name = attr->name;
- attr->name = NULL;
- dattr->value_str = attr->value;
- attr->value = NULL;
-
- if (filterflag && !strcmp(dattr->name, "select")) {
- /* exception for XPath select in filter, which is supposed to be transformed
- * into JSON format to keep the information about namespaces */
+ /* special case of xpath in the value, we want to convert it to JSON */
+ if (filterflag && !strcmp(attr->name, "select")) {
dattr->value.string = transform_xml2json(ctx, dattr->value_str, xml, 0, 1);
if (!dattr->value.string) {
/* problem with resolving value as xpath */
- attr->value = dattr->value_str;
- free(dattr);
+ dattr->value.string = dattr->value_str;
goto error;
}
lydict_remove(ctx, dattr->value_str);
dattr->value_str = dattr->value.string;
- dattr->value_type = LY_TYPE_STRING;
- } else {
- /* the value is here converted to a JSON format if needed in case of LY_TYPE_IDENT and LY_TYPE_INST or to a
- * canonical form of the value */
- if (!lyp_parse_value(*((struct lys_type **)lys_ext_complex_get_substmt(LY_STMT_TYPE, dattr->annotation, NULL)),
- &dattr->value_str, xml, NULL, dattr, 1, 0)) {
- attr->value = dattr->value_str;
- free(dattr);
- goto error;
- }
}
/* insert into the data node */
@@ -384,103 +344,83 @@
dattr_iter->next = dattr;
}
continue;
-
-attr_error:
- if (options & LYD_OPT_STRICT) {
- LOGVAL(LYE_INATTR, LY_VLOG_LYD, (*result), attr->name, xml->name);
- LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "Unknown metadata (%s%s%s).",
- attr->ns ? attr->ns->prefix : "", attr->ns ? ":" : "", attr->name);
- goto error;
- } else {
- LOGWRN("Unknown metadata (%s%s%s) - skipping.",
- attr->ns ? attr->ns->prefix : "", attr->ns ? ":" : "", attr->name);
- continue;
- }
}
/* check insert attribute and its values */
if (options & LYD_OPT_EDIT) {
- /* 0x01 - insert attribute present
- * 0x02 - insert is relative (before or after)
- * 0x04 - value attribute present
- * 0x08 - key attribute present
- * 0x10 - operation attribute present
- * 0x20 - operation not allowing insert attribute (delete or remove)
- */
- for (dattr = (*result)->attr; dattr; dattr = dattr->next) {
- str = NULL;
- if (!strcmp(dattr->annotation->arg_value, "operation") &&
- !strcmp(dattr->annotation->module->name, "ietf-netconf")) {
- if (editbits & 0x10) {
- LOGVAL(LYE_TOOMANY, LY_VLOG_LYD, (*result), "operation attributes", xml->name);
- goto error;
- }
+ if (lyp_check_edit_attr(ctx, (*result)->attr, *result, &editbits)) {
+ goto error;
+ }
- editbits |= 0x10;
- if (dattr->value.enm->value >= 3) {
- /* delete or remove */
- editbits |= 0x20;
- }
- } else if (dattr->annotation->module == ctx->models.list[1] && /* internal YANG schema */
- !strcmp(dattr->annotation->arg_value, "insert")) {
- /* 'insert' attribute present */
- if (!(schema->flags & LYS_USERORDERED)) {
- /* ... but it is not expected */
- LOGVAL(LYE_INATTR, LY_VLOG_LYD, (*result), "insert", schema->name);
+ /* check correct filter extension attributes */
+ } else if (filterflag) {
+ found = 0; /* 0 - nothing, 1 - type subtree, 2 - type xpath, 3 - select, 4 - type xpath + select */
+ LY_TREE_FOR((*result)->attr, dattr_iter) {
+ if (!strcmp(dattr_iter->name, "type")) {
+ if ((found == 1) || (found == 2) || (found == 4)) {
+ LOGVAL(LYE_TOOMANY, LY_VLOG_LYD, (*result), "type", xml->name);
goto error;
}
- if (editbits & 0x01) {
- LOGVAL(LYE_TOOMANY, LY_VLOG_LYD, (*result), "insert attributes", xml->name);
- goto error;
- }
+ switch (dattr_iter->value.enm->value) {
+ case 0:
+ /* subtree */
+ if (found == 3) {
+ LOGVAL(LYE_INATTR, LY_VLOG_LYD, (*result), dattr_iter->name);
+ goto error;
+ }
- editbits |= 0x01;
- if (dattr->value.enm->value >= 2) {
- /* before or after */
- editbits |= 0x02;
- }
- str = dattr->name;
- } else if (dattr->annotation->module == ctx->models.list[1] && /* internal YANG schema */
- !strcmp(dattr->annotation->arg_value, "value")) {
- if (editbits & 0x04) {
- LOGVAL(LYE_TOOMANY, LY_VLOG_LYD, (*result), "value attributes", xml->name);
- goto error;
- } else if (schema->nodetype & LYS_LIST) {
- LOGVAL(LYE_INATTR, LY_VLOG_LYD, (*result), dattr->name, schema->name);
+ assert(!found);
+ found = 1;
+ break;
+ case 1:
+ /* xpath */
+ if (found == 3) {
+ found = 4;
+ } else {
+ assert(!found);
+ found = 2;
+ }
+ break;
+ default:
+ LOGINT;
goto error;
}
- editbits |= 0x04;
- str = dattr->name;
- } else if (dattr->annotation->module == ctx->models.list[1] && /* internal YANG schema */
- !strcmp(dattr->annotation->arg_value, "key")) {
- if (editbits & 0x08) {
- LOGVAL(LYE_TOOMANY, LY_VLOG_LYD, (*result), "key attributes", xml->name);
+ } else if (!strcmp(dattr_iter->name, "select")) {
+ switch (found) {
+ case 0:
+ found = 3;
+ break;
+ case 1:
+ LOGVAL(LYE_INATTR, LY_VLOG_LYD, (*result), dattr_iter->name);
goto error;
- } else if (schema->nodetype & LYS_LEAFLIST) {
- LOGVAL(LYE_INATTR, LY_VLOG_LYD, (*result), dattr->name, schema->name);
+ case 2:
+ found = 4;
+ break;
+ case 3:
+ case 4:
+ LOGVAL(LYE_TOOMANY, LY_VLOG_LYD, (*result), "select", xml->name);
+ goto error;
+ default:
+ LOGINT;
goto error;
}
- editbits |= 0x08;
- str = dattr->name;
}
}
- /* report errors */
- if (str && (!(schema->nodetype & (LYS_LEAFLIST | LYS_LIST)) || !(schema->flags & LYS_USERORDERED))) {
- /* moving attributes in wrong elements (not an user ordered list or not a list at all) */
- LOGVAL(LYE_INATTR, LY_VLOG_LYD, (*result), str, xml->name);
+ /* check if what we found is correct */
+ switch (found) {
+ case 1:
+ case 4:
+ /* ok */
+ break;
+ case 2:
+ LOGVAL(LYE_MISSATTR, LY_VLOG_LYD, (*result), "select", xml->name);
goto error;
- } else if (editbits == 3) {
- /* 0x01 | 0x02 - relative position, but value/key is missing */
- if (schema->nodetype & LYS_LIST) {
- LOGVAL(LYE_MISSATTR, LY_VLOG_LYD, (*result), "key", xml->name);
- } else { /* LYS_LEAFLIST */
- LOGVAL(LYE_MISSATTR, LY_VLOG_LYD, (*result), "value", xml->name);
- }
+ case 3:
+ LOGVAL(LYE_MISSATTR, LY_VLOG_LYD, (*result), "type", xml->name);
goto error;
- } else if ((editbits & (0x04 | 0x08)) && !(editbits & 0x02)) {
- /* key/value without relative position */
- LOGVAL(LYE_INATTR, LY_VLOG_LYD, (*result), (editbits & 0x04) ? "value" : "key", schema->name);
+ default:
+ LOGINT;
goto error;
}
}