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").