xml parser & printer FEATURE support for special filter attrs
Fixes #1619
diff --git a/src/parser_xml.c b/src/parser_xml.c
index a827ab7..fd2f856 100644
--- a/src/parser_xml.c
+++ b/src/parser_xml.c
@@ -67,30 +67,60 @@
free(ctx);
}
+/**
+ * @brief Parse and create XML metadata.
+ *
+ * @param[in] lydctx XML data parser context.
+ * @param[in] parent_exts Extension instances of the parent node.
+ * @param[out] meta List of created metadata instances.
+ * @return LY_ERR value.
+ */
static LY_ERR
-lydxml_metadata(struct lyd_xml_ctx *lydctx, struct lyd_meta **meta)
+lydxml_metadata(struct lyd_xml_ctx *lydctx, struct lysc_ext_instance *parent_exts, struct lyd_meta **meta)
{
LY_ERR ret = LY_SUCCESS;
const struct lyxml_ns *ns;
struct lys_module *mod;
const char *name;
size_t name_len;
+ LY_ARRAY_COUNT_TYPE u;
+ ly_bool filter_attrs = 0;
struct lyxml_ctx *xmlctx = lydctx->xmlctx;
*meta = NULL;
+ /* check for NETCONF filter unqualified attributes */
+ LY_ARRAY_FOR(parent_exts, u) {
+ if (!strcmp(parent_exts[u].def->name, "get-filter-element-attributes") &&
+ !strcmp(parent_exts[u].def->module->name, "ietf-netconf")) {
+ filter_attrs = 1;
+ break;
+ }
+ }
+
while (xmlctx->status == LYXML_ATTRIBUTE) {
if (!xmlctx->prefix_len) {
- /* in XML, all attributes must be prefixed
- * TODO exception for NETCONF filters which are supposed to map to the ietf-netconf without prefix */
+ /* in XML all attributes must be prefixed except NETCONF filter ones marked by an extension */
+ if (filter_attrs && (!ly_strncmp("type", xmlctx->name, xmlctx->name_len) ||
+ !ly_strncmp("select", xmlctx->name, xmlctx->name_len))) {
+ mod = ly_ctx_get_module_implemented(xmlctx->ctx, "ietf-netconf");
+ if (!mod) {
+ LOGVAL(xmlctx->ctx, LYVE_REFERENCE,
+ "Missing (or not implemented) YANG module \"ietf-netconf\" for special filter attributes.");
+ ret = LY_ENOTFOUND;
+ goto cleanup;
+ }
+ goto create_meta;
+ }
+
if (lydctx->parse_opts & LYD_PARSE_STRICT) {
- ret = LY_EVALID;
LOGVAL(xmlctx->ctx, LYVE_REFERENCE, "Missing mandatory prefix for XML metadata \"%.*s\".",
(int)xmlctx->name_len, xmlctx->name);
+ ret = LY_EVALID;
goto cleanup;
}
-skip_attr:
+ /* skip attr */
LY_CHECK_GOTO(ret = lyxml_ctx_next(xmlctx), cleanup);
assert(xmlctx->status == LYXML_ATTR_CONTENT);
LY_CHECK_GOTO(ret = lyxml_ctx_next(xmlctx), cleanup);
@@ -100,25 +130,32 @@
/* get namespace of the attribute to find its annotation definition */
ns = lyxml_ns_get(&xmlctx->ns, xmlctx->prefix, xmlctx->prefix_len);
if (!ns) {
- ret = LY_ENOTFOUND;
/* unknown namespace, XML error */
LOGVAL(xmlctx->ctx, LYVE_REFERENCE, "Unknown XML prefix \"%.*s\".", (int)xmlctx->prefix_len, xmlctx->prefix);
+ ret = LY_ENOTFOUND;
goto cleanup;
}
+
+ /* get the module with metadata definition */
mod = ly_ctx_get_module_implemented_ns(xmlctx->ctx, ns->uri);
if (!mod) {
- /* module is not implemented or not present in the schema */
if (lydctx->parse_opts & LYD_PARSE_STRICT) {
- ret = LY_ENOTFOUND;
LOGVAL(xmlctx->ctx, LYVE_REFERENCE,
"Unknown (or not implemented) YANG module with namespace \"%s\" for metadata \"%.*s%s%.*s\".",
ns->uri, (int)xmlctx->prefix_len, xmlctx->prefix, xmlctx->prefix_len ? ":" : "",
(int)xmlctx->name_len, xmlctx->name);
+ ret = LY_ENOTFOUND;
goto cleanup;
}
- goto skip_attr;
+
+ /* skip attr */
+ LY_CHECK_GOTO(ret = lyxml_ctx_next(xmlctx), cleanup);
+ assert(xmlctx->status == LYXML_ATTR_CONTENT);
+ LY_CHECK_GOTO(ret = lyxml_ctx_next(xmlctx), cleanup);
+ continue;
}
+create_meta:
/* remember meta name and get its content */
name = xmlctx->name;
name_len = xmlctx->name_len;
@@ -489,7 +526,7 @@
/* create metadata/attributes */
if (xmlctx->status == LYXML_ATTRIBUTE) {
if (snode) {
- ret = lydxml_metadata(lydctx, &meta);
+ ret = lydxml_metadata(lydctx, snode->exts, &meta);
LY_CHECK_GOTO(ret, error);
} else {
assert(lydctx->parse_opts & LYD_PARSE_OPAQ);