xpath UPDATE clarify when opaque nodes are considered
diff --git a/src/tree_data.h b/src/tree_data.h
index 2c3066d..124c784 100644
--- a/src/tree_data.h
+++ b/src/tree_data.h
@@ -2436,6 +2436,8 @@
* `leaf-list[.=...]`, these instances are found using hashes with constant (*O(1)*) complexity
* (unless they are defined in top-level). Other predicates can still follow the aforementioned ones.
*
+ * Opaque nodes are part of the evaluation.
+ *
* @param[in] ctx_node XPath context node.
* @param[in] xpath [XPath](@ref howtoXPath) to select in JSON format. It must evaluate into a node set.
* @param[out] set Set of found data nodes. In case the result is a number, a string, or a boolean,
@@ -2586,6 +2588,8 @@
* Always works in constant (*O(1)*) complexity. To be exact, it is *O(n)* where *n* is the depth
* of the path used.
*
+ * Opaque nodes are NEVER found/traversed.
+ *
* @param[in] ctx_node Path context node.
* @param[in] path [Path](@ref howtoXPath) to find.
* @param[in] output Whether to search in RPC/action output nodes or in input nodes.
diff --git a/src/xpath.c b/src/xpath.c
index 459e618..4f5bffb 100644
--- a/src/xpath.c
+++ b/src/xpath.c
@@ -5671,6 +5671,8 @@
moveto_node_check(const struct lyd_node *node, enum lyxp_node_type node_type, const struct lyxp_set *set,
const char *node_name, const struct lys_module *moveto_mod, uint32_t options)
{
+ const struct lysc_node *schema;
+
if ((node_type == LYXP_NODE_ROOT_CONFIG) || (node_type == LYXP_NODE_ROOT)) {
assert(node_type == set->root_type);
@@ -5684,39 +5686,40 @@
return LY_ENOT;
}
- if (!node->schema) {
- /* opaque node never matches */
+ /* get schema node even of an opaque node */
+ schema = lyd_node_schema(node);
+ if (!schema) {
+ /* unknown opaque node never matches */
return LY_ENOT;
}
/* module check */
if (moveto_mod) {
- if ((set->ctx == LYD_CTX(node)) && (node->schema->module != moveto_mod)) {
+ if ((set->ctx == LYD_CTX(node)) && (schema->module != moveto_mod)) {
return LY_ENOT;
- } else if ((set->ctx != LYD_CTX(node)) && strcmp(node->schema->module->name, moveto_mod->name)) {
+ } else if ((set->ctx != LYD_CTX(node)) && strcmp(schema->module->name, moveto_mod->name)) {
return LY_ENOT;
}
}
/* context check */
- if ((set->root_type == LYXP_NODE_ROOT_CONFIG) && (node->schema->flags & LYS_CONFIG_R)) {
+ if ((set->root_type == LYXP_NODE_ROOT_CONFIG) && (schema->flags & LYS_CONFIG_R)) {
return LY_EINVAL;
- } else if (set->context_op && (node->schema->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) &&
- (node->schema != set->context_op)) {
+ } else if (set->context_op && (schema->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) && (schema != set->context_op)) {
return LY_EINVAL;
}
/* name check */
if (node_name) {
- if ((set->ctx == LYD_CTX(node)) && (node->schema->name != node_name)) {
+ if ((set->ctx == LYD_CTX(node)) && (schema->name != node_name)) {
return LY_ENOT;
- } else if ((set->ctx != LYD_CTX(node)) && strcmp(node->schema->name, node_name)) {
+ } else if ((set->ctx != LYD_CTX(node)) && strcmp(schema->name, node_name)) {
return LY_ENOT;
}
}
/* when check, accept the context node because it should only be the path ".", we have checked the when is valid before */
- if (!(options & LYXP_IGNORE_WHEN) && lysc_has_when(node->schema) && !(node->flags & LYD_WHEN_TRUE) &&
+ if (!(options & LYXP_IGNORE_WHEN) && lysc_has_when(schema) && !(node->flags & LYD_WHEN_TRUE) &&
(node != set->cur_node)) {
return LY_EINCOMPLETE;
}
diff --git a/src/xpath.h b/src/xpath.h
index 96f7419..6c46c14 100644
--- a/src/xpath.h
+++ b/src/xpath.h
@@ -327,6 +327,8 @@
* @brief Evaluate an XPath expression on data. Be careful when using this function, the result can often
* be confusing without thorough understanding of XPath evaluation rules defined in RFC 7950.
*
+ * Traverses (valid) opaque nodes in the evaluation.
+ *
* @param[in] ctx libyang context to use.
* @param[in] exp Parsed XPath expression to be evaluated.
* @param[in] cur_mod Current module for the expression (where it was "instantiated").