tree data BUGFIX lyd_owner_module behavior now consistent

It is meant to return the owner module for both
data and opaque nodes. For node modules there
is a new function now.
diff --git a/src/log.c b/src/log.c
index a0d997f..6f38e17 100644
--- a/src/log.c
+++ b/src/log.c
@@ -764,7 +764,7 @@
 
     /* get module to print, if any */
     mod = snode->module;
-    prev_mod = (parent->schema) ? parent->schema->module : lyd_owner_module(parent);
+    prev_mod = lyd_node_module(parent);
     if (prev_mod == mod) {
         mod = NULL;
     }
diff --git a/src/parser_common.c b/src/parser_common.c
index 040318e..bdc8529 100644
--- a/src/parser_common.c
+++ b/src/parser_common.c
@@ -197,7 +197,7 @@
         assert(!iter->schema);
 
         /* get module */
-        mod = lyd_owner_module(iter);
+        mod = lyd_node_module(iter);
         if (!mod) {
             /* unknown module, no schema node */
             schema = NULL;
diff --git a/src/parser_json.c b/src/parser_json.c
index 1eaa160..af04a36 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -2056,7 +2056,7 @@
         assert(parent);
 
         /* parse "input" */
-        rc = lydjson_envelope(lydctx->jsonctx, "input", lyd_owner_module(parent)->name, 0, envp);
+        rc = lydjson_envelope(lydctx->jsonctx, "input", lyd_node_module(parent)->name, 0, envp);
         LY_CHECK_GOTO(rc, cleanup);
 
         int_opts = LYD_INTOPT_WITH_SIBLINGS | LYD_INTOPT_RPC | LYD_INTOPT_ACTION;
@@ -2071,7 +2071,7 @@
         assert(parent);
 
         /* parse "output" */
-        rc = lydjson_envelope(lydctx->jsonctx, "output", lyd_owner_module(parent)->name, 0, envp);
+        rc = lydjson_envelope(lydctx->jsonctx, "output", lyd_node_module(parent)->name, 0, envp);
         LY_CHECK_GOTO(rc, cleanup);
 
         int_opts = LYD_INTOPT_WITH_SIBLINGS | LYD_INTOPT_REPLY;
diff --git a/src/parser_xml.c b/src/parser_xml.c
index a117825..d6de91d 100644
--- a/src/parser_xml.c
+++ b/src/parser_xml.c
@@ -1944,7 +1944,7 @@
         assert(parent);
 
         /* parse "input" */
-        rc = lydxml_envelope(lydctx->xmlctx, "input", lyd_owner_module(parent)->ns, 0, envp);
+        rc = lydxml_envelope(lydctx->xmlctx, "input", lyd_node_module(parent)->ns, 0, envp);
         if (rc == LY_ENOT) {
             LOGVAL(ctx, LYVE_DATA, "Missing RESTCONF \"input\" object or in incorrect namespace.");
         }
@@ -1957,7 +1957,7 @@
         assert(parent);
 
         /* parse "output" */
-        rc = lydxml_envelope(lydctx->xmlctx, "output", lyd_owner_module(parent)->ns, 0, envp);
+        rc = lydxml_envelope(lydctx->xmlctx, "output", lyd_node_module(parent)->ns, 0, envp);
         if (rc == LY_ENOT) {
             LOGVAL(ctx, LYVE_DATA, "Missing RESTCONF \"output\" object or in incorrect namespace.");
         }
diff --git a/src/tree_data.c b/src/tree_data.c
index bbb58be..0da855e 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -2418,9 +2418,9 @@
             for (iter = node, i = 1; i < depth; iter = lyd_parent(iter), ++i) {}
 iter_print:
             /* get the module */
-            mod = iter->schema ? iter->schema->module : lyd_owner_module(iter);
+            mod = lyd_node_module(iter);
             parent = lyd_parent(iter);
-            prev_mod = (parent && parent->schema) ? parent->schema->module : lyd_owner_module(parent);
+            prev_mod = lyd_node_module(parent);
             if (prev_mod == mod) {
                 mod = NULL;
             }
@@ -2490,7 +2490,7 @@
         for (depth = 1; depth <= dnodes->count; ++depth) {
             /* current node */
             iter = dnodes->dnodes[depth - 1];
-            mod = iter->schema ? iter->schema->module : lyd_owner_module(iter);
+            mod = lyd_node_module(iter);
 
             /* parent */
             parent = (depth > 1) ? dnodes->dnodes[depth - 2] : NULL;
@@ -2499,7 +2499,7 @@
                     (!lysc_data_parent(iter->schema) && (LYD_CTX(iter) != LYD_CTX(parent))));
 
             /* get module to print, if any */
-            prev_mod = (parent && parent->schema) ? parent->schema->module : lyd_owner_module(parent);
+            prev_mod = lyd_node_module(parent);
             if (prev_mod == mod) {
                 mod = NULL;
             }
diff --git a/src/tree_data.h b/src/tree_data.h
index 124c784..3249e84 100644
--- a/src/tree_data.h
+++ b/src/tree_data.h
@@ -1072,6 +1072,14 @@
 LIBYANG_API_DECL const struct lys_module *lyd_owner_module(const struct lyd_node *node);
 
 /**
+ * @brief Get the module of a node. Useful mainly for opaque nodes.
+ *
+ * @param[in] node Node to examine.
+ * @return Module of the node.
+ */
+LIBYANG_API_DECL const struct lys_module *lyd_node_module(const struct lyd_node *node);
+
+/**
  * @brief Check whether a node value equals to its default one.
  *
  * @param[in] node Term node to test.
diff --git a/src/tree_data_common.c b/src/tree_data_common.c
index f2a37a2..d0d3602 100644
--- a/src/tree_data_common.c
+++ b/src/tree_data_common.c
@@ -300,7 +300,12 @@
         return NULL;
     }
 
+    while (!node->schema && node->parent) {
+        node = lyd_parent(node);
+    }
+
     if (!node->schema) {
+        /* top-level opaque node */
         opaq = (struct lyd_node_opaq *)node;
         switch (opaq->format) {
         case LY_VALUE_XML:
@@ -317,13 +322,46 @@
             return NULL;
         }
 
-        /* try a parent */
-        return lyd_owner_module(lyd_parent(node));
+        return NULL;
     }
 
     return lysc_owner_module(node->schema);
 }
 
+LIBYANG_API_DEF const struct lys_module *
+lyd_node_module(const struct lyd_node *node)
+{
+    const struct lyd_node_opaq *opaq;
+
+    while (node) {
+        /* data node */
+        if (node->schema) {
+            return node->schema->module;
+        }
+
+        /* opaque node */
+        opaq = (struct lyd_node_opaq *)node;
+        switch (opaq->format) {
+        case LY_VALUE_XML:
+            if (opaq->name.module_ns) {
+                return ly_ctx_get_module_implemented_ns(LYD_CTX(node), opaq->name.module_ns);
+            }
+            break;
+        case LY_VALUE_JSON:
+            if (opaq->name.module_name) {
+                return ly_ctx_get_module_implemented(LYD_CTX(node), opaq->name.module_name);
+            }
+            break;
+        default:
+            break;
+        }
+
+        node = lyd_parent(node);
+    }
+
+    return NULL;
+}
+
 void
 lyd_first_module_sibling(struct lyd_node **node, const struct lys_module *mod)
 {
@@ -1072,7 +1110,7 @@
         for (iter = node; lyd_parent(iter) != prev_iter; iter = lyd_parent(iter)) {}
 
         /* get module */
-        mod = lyd_owner_module(iter);
+        mod = lyd_node_module(iter);
         if (!mod) {
             /* unknown module, no schema node */
             schema = NULL;
diff --git a/src/xpath.c b/src/xpath.c
index 4f5bffb..1c1056b 100644
--- a/src/xpath.c
+++ b/src/xpath.c
@@ -4502,7 +4502,7 @@
 xpath_name(struct lyxp_set **args, uint32_t arg_count, struct lyxp_set *set, uint32_t options)
 {
     struct lyxp_set_node *item;
-    struct lys_module *mod = NULL;
+    const struct lys_module *mod = NULL;
     char *str;
     const char *name = NULL;
 
@@ -4548,8 +4548,8 @@
         /* keep NULL */
         break;
     case LYXP_NODE_ELEM:
-        mod = item->node->schema->module;
-        name = item->node->schema->name;
+        mod = lyd_node_module(item->node);
+        name = LYD_NAME(item->node);
         break;
     case LYXP_NODE_META:
         mod = ((struct lyd_meta *)item->node)->annotation->module;
@@ -4584,7 +4584,7 @@
 xpath_namespace_uri(struct lyxp_set **args, uint32_t arg_count, struct lyxp_set *set, uint32_t options)
 {
     struct lyxp_set_node *item;
-    struct lys_module *mod;
+    const struct lys_module *mod;
 
     /* suppress unused variable warning */
     (void)options;
@@ -4634,7 +4634,7 @@
     case LYXP_NODE_ELEM:
     case LYXP_NODE_META:
         if (item->type == LYXP_NODE_ELEM) {
-            mod = item->node->schema->module;
+            mod = lyd_node_module(item->node);
         } else { /* LYXP_NODE_META */
             /* annotations */
             mod = ((struct lyd_meta *)item->node)->annotation->module;