xpath BUGFIX support for unprefixed identities
diff --git a/src/xpath.c b/src/xpath.c
index 9edf3d0..f32af4e 100644
--- a/src/xpath.c
+++ b/src/xpath.c
@@ -4098,6 +4098,51 @@
return ret;
}
+/**
+ * @brief Get the module of an identity used in derived-from(-or-self)() functions.
+ *
+ * @param[in,out] qname Qualified node name. If includes prefix, it is skipped.
+ * @param[in,out] qname_len Length of @p qname, is updated accordingly.
+ * @param[in] set Set with general XPath context.
+ * @param[out] mod Module of the identity.
+ * @return LY_ERR
+ */
+static LY_ERR
+xpath_derived_ident_module(const char **qname, uint32_t *qname_len, const struct lyxp_set *set,
+ const struct lys_module **mod)
+{
+ LY_CHECK_RET(moveto_resolve_model(qname, qname_len, set, mod));
+ if (*mod) {
+ /* prefixed identity */
+ return LY_SUCCESS;
+ }
+
+ switch (set->format) {
+ case LY_VALUE_SCHEMA:
+ case LY_VALUE_SCHEMA_RESOLVED:
+ /* current module */
+ *mod = set->cur_mod;
+ break;
+ case LY_VALUE_CANON:
+ case LY_VALUE_JSON:
+ case LY_VALUE_LYB:
+ case LY_VALUE_STR_NS:
+ /* inherit parent (context node) module */
+ if (set->cur_scnode) {
+ *mod = set->cur_scnode->module;
+ } else {
+ *mod = set->cur_mod;
+ }
+ break;
+ case LY_VALUE_XML:
+ /* all identifiers need to be prefixed */
+ LOGVAL(set->ctx, LYVE_DATA, "Non-prefixed identity \"%.*s\" in XML xpath found.", (int)*qname_len, *qname);
+ return LY_EVALID;
+ }
+
+ return LY_SUCCESS;
+}
+
static LY_ERR
xpath_derived_(struct lyxp_set **args, struct lyxp_set *set, uint32_t options, ly_bool self_match, const char *func)
{
@@ -4147,12 +4192,8 @@
/* parse the identity */
id_name = args[1]->val.str;
id_len = strlen(id_name);
- rc = moveto_resolve_model(&id_name, &id_len, set, &mod);
+ rc = xpath_derived_ident_module(&id_name, &id_len, set, &mod);
LY_CHECK_RET(rc);
- if (!mod) {
- LOGVAL(set->ctx, LYVE_XPATH, "Identity \"%.*s\" without a prefix.", (int)id_len, id_name);
- return LY_EVALID;
- }
/* find the identity */
found = 0;
diff --git a/tests/utests/data/test_validation.c b/tests/utests/data/test_validation.c
index 17fd078..d80438a 100644
--- a/tests/utests/data/test_validation.c
+++ b/tests/utests/data/test_validation.c
@@ -164,6 +164,37 @@
}
static void
+test_unprefixed_ident(void **state)
+{
+ struct lyd_node *tree;
+ const char *schema =
+ "module a {\n"
+ " namespace urn:tests:a;\n"
+ " prefix a;\n"
+ " yang-version 1.1;\n"
+ "\n"
+ " identity d3 {base d2;}\n"
+ " identity d2 {base d1;}\n"
+ " identity d1;\n"
+ "\n"
+ " leaf a {type identityref {base d1;}}\n"
+ " leaf b {type string; must \"derived-from-or-self(/a, 'd2')\";}\n"
+ " leaf c {type string; when \"derived-from(/a, 'd2')\";}\n"
+ "}";
+
+ UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
+
+ CHECK_PARSE_LYD_PARAM("<b xmlns=\"urn:tests:a\">hey</b>", LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
+ CHECK_LOG_CTX("Must condition \"derived-from-or-self(/a, 'd2')\" not satisfied.", "/a:b", 0);
+
+ CHECK_PARSE_LYD_PARAM("<c xmlns=\"urn:tests:a\">hey</c>", LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
+ CHECK_LOG_CTX("When condition \"derived-from(/a, 'd2')\" not satisfied.", "/a:c", 0);
+
+ LYD_TREE_CREATE("<a xmlns=\"urn:tests:a\">d3</a><b xmlns=\"urn:tests:a\">b-val</b><c xmlns=\"urn:tests:a\">c-val</c>", tree);
+ lyd_free_all(tree);
+}
+
+static void
test_mandatory(void **state)
{
struct lyd_node *tree;
@@ -1523,6 +1554,7 @@
UTEST(test_mandatory),
UTEST(test_mandatory_when),
UTEST(test_type_incomplete_when),
+ UTEST(test_unprefixed_ident),
UTEST(test_minmax),
UTEST(test_unique),
UTEST(test_unique_nested),