Revert "REVERT to version 0.2.55."

This reverts commit a5835e9bb0a9a958f6e6a2c871acc5b16158f16d.

Conflicts:
	CMakeLists.txt
	src/resolve.c
	src/tree_schema.c
diff --git a/src/common.h b/src/common.h
index 41e3c1f..cb09fec 100644
--- a/src/common.h
+++ b/src/common.h
@@ -99,8 +99,8 @@
     LYE_ENUM_WS,
     LYE_BITS_DUPVAL,
     LYE_BITS_DUPNAME,
-    LYE_INPREF,
-    LYE_INPREF_LEN,
+    LYE_INMOD,
+    LYE_INMOD_LEN,
     LYE_KEY_NLEAF,
     LYE_KEY_TYPE,
     LYE_KEY_CONFIG,
@@ -165,7 +165,7 @@
  * correcting theit ref_count -> do not touch them. Prefixes of
  * the namespaces are import prefixes of the modules. Output
  * parameters are optional, but either all 3 are set or none
- * of them is. Logs directly.
+ * of them are. Logs directly.
  *
  * @param[in] module Module with imports to use.
  * @param[in] expr JSON expression.
diff --git a/src/log.c b/src/log.c
index 77ff9b5..9321194 100644
--- a/src/log.c
+++ b/src/log.c
@@ -78,8 +78,8 @@
 /* LYE_ENUM_WS */      "The enum name \"%s\" includes invalid leading or trailing whitespaces.",
 /* LYE_BITS_DUPVAL */  "The position \"%d\" of \"%s\" bits has already been used to another named bit.",
 /* LYE_BITS_DUPNAME */ "The bit name \"%s\" has already been assigned to another bit.",
-/* LYE_INPREF */       "Prefix in \"%s\" refers to an unknown module.",
-/* LYE_INPREF_LEN */   "Prefix \"%.*s\" refers to an unknown module.",
+/* LYE_INMOD */        "Module name in \"%s\" refers to an unknown module.",
+/* LYE_INMOD_LEN */    "Module name \"%.*s\" refers to an unknown module.",
 /* LYE_KEY_NLEAF */    "Key \"%s\" is not a leaf.",
 /* LYE_KEY_TYPE */     "Key \"%s\" must not be the built-in type \"empty\".",
 /* LYE_KEY_CONFIG */   "The \"config\" value of the \"%s\" key differs from its list config value.",
diff --git a/src/parser.c b/src/parser.c
index 3248879..b08a7fc 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -590,7 +590,11 @@
 
         if (!strcmp(node->value_str, "true")) {
             node->value.bool = 1;
-        } /* else false, so keep it zero */
+        } else if (strcmp(node->value_str, "false")) {
+            LOGVAL(LYE_INVAL, line, node->value_str, node->schema->name);
+            return EXIT_FAILURE;
+        }
+        /* else stays 0 */
         break;
 
     case LY_TYPE_DEC64:
diff --git a/src/parser_yin.c b/src/parser_yin.c
index 5ea60f1..28e14e7 100644
--- a/src/parser_yin.c
+++ b/src/parser_yin.c
@@ -466,7 +466,7 @@
               struct unres_schema *unres)
 {
 #define REGEX_ERR_LEN 128
-    const char *value, *delim, *name, *err_ptr;
+    const char *value, *name, *err_ptr;
     struct lyxml_elem *next, *node;
     struct lys_restr **restr;
     struct lys_type_bit bit;
@@ -476,17 +476,15 @@
     int64_t p, p_;
 
     GETVAL(value, yin, "name");
-
-    delim = strchr(value, ':');
-    if (delim) {
-        type->prefix = lydict_insert(module->ctx, value, delim - value);
-        delim++;
-        value += delim-value;
+    value = transform_expr_xml2json(module->ctx, value, yin, 1);
+    if (!value) {
+        goto error;
     }
+    type->module_name = value;
 
-    rc = resolve_superior_type(value, type->prefix, module, parent, &type->der);
+    rc = resolve_superior_type(value, type->module_name, module, parent, &type->der);
     if (rc == -1) {
-        LOGVAL(LYE_INPREF, LOGLINE(yin), type->prefix);
+        LOGVAL(LYE_INMOD, LOGLINE(yin), type->module_name);
         goto error;
     } else if (rc == EXIT_FAILURE) {
         /* HACK for unres */
@@ -924,7 +922,11 @@
                 }
 
                 GETVAL(value, node, "value");
-                type->info.lref.path = lydict_insert(module->ctx, value, 0);
+                /* store in the JSON format */
+                type->info.lref.path = transform_expr_xml2json(module->ctx, value, node, 1);
+                if (!type->info.lref.path) {
+                    goto error;
+                }
                 if (unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent, LOGLINE(yin)) == -1) {
                     goto error;
                 }
diff --git a/src/printer_info.c b/src/printer_info.c
index 01e30df..5ec0f7c 100644
--- a/src/printer_info.c
+++ b/src/printer_info.c
@@ -395,8 +395,8 @@
     }
     ly_print(out, "%-*s", INDENT_LEN, "Superior: ");
     if (type->der) {
-        if (type->prefix) {
-            ly_print(out, "%s:", type->prefix);
+        if (type->module_name) {
+            ly_print(out, "%s:", type->module_name);
         }
         ly_print(out, "%s\n", type->der->name);
     } else {
diff --git a/src/printer_tree.c b/src/printer_tree.c
index 6947593..aa2dc0a 100644
--- a/src/printer_tree.c
+++ b/src/printer_tree.c
@@ -178,8 +178,8 @@
 {
     if ((type->base == LY_TYPE_LEAFREF) && !type->der->module) {
         ly_print(out, "-> %s", type->info.lref.path);
-    } else if (type->prefix) {
-        ly_print(out, "%s:%s", type->prefix, type->der->name);
+    } else if (type->module_name) {
+        ly_print(out, "%s:%s", type->module_name, type->der->name);
     } else {
         ly_print(out, "%s", type->der->name);
     }
diff --git a/src/printer_yang.c b/src/printer_yang.c
index 09a56b7..6e413ff 100644
--- a/src/printer_yang.c
+++ b/src/printer_yang.c
@@ -236,9 +236,12 @@
 yang_print_type(struct lyout *out, int level, struct lys_module *module, struct lys_type *type)
 {
     int i;
+    const char *str;
 
-    if (type->prefix) {
-        ly_print(out, "%*stype %s:%s {\n", LEVEL, INDENT, type->prefix, type->der->name);
+    if (type->module_name) {
+        str = transform_expr_json2xml(module, type->module_name, NULL, NULL, NULL);
+        ly_print(out, "%*stype %s:%s {\n", LEVEL, INDENT, str, type->der->name);
+        lydict_remove(module->ctx, str);
     } else {
         ly_print(out, "%*stype %s {\n", LEVEL, INDENT, type->der->name);
     }
@@ -309,7 +312,9 @@
         }
         break;
     case LY_TYPE_LEAFREF:
-        ly_print(out, "%*spath \"%s\";\n", LEVEL, INDENT, type->info.lref.path);
+        str = transform_expr_json2xml(module, type->info.lref.path, NULL, NULL, NULL);
+        ly_print(out, "%*spath \"%s\";\n", LEVEL, INDENT, str);
+        lydict_remove(module->ctx, str);
         break;
     case LY_TYPE_STRING:
         if (type->info.str.length) {
diff --git a/src/resolve.c b/src/resolve.c
index 778a09b..ad2070a 100644
--- a/src/resolve.c
+++ b/src/resolve.c
@@ -31,6 +31,7 @@
 #include "resolve.h"
 #include "common.h"
 #include "xpath.h"
+#include "parser.h"
 #include "dict_private.h"
 #include "tree_internal.h"
 
@@ -1259,22 +1260,22 @@
  * @brief Resolve a typedef. Does not log.
  *
  * @param[in] name Typedef name.
- * @param[in] prefix Typedef name prefix.
- * @param[in] module The main module.
- * @param[in] parent The parent of the resolved type definition.
+ * @param[in] mod_name Typedef name module name.
+ * @param[in] module Main module.
+ * @param[in] parent Parent of the resolved type definition.
  * @param[out] ret Pointer to the resolved typedef. Can be NULL.
  *
  * @return EXIT_SUCCESS on success, EXIT_FAILURE on forward reference, -1 on error.
  */
 int
-resolve_superior_type(const char *name, const char *prefix, struct lys_module *module, struct lys_node *parent,
+resolve_superior_type(const char *name, const char *mod_name, struct lys_module *module, struct lys_node *parent,
                       struct lys_tpdf **ret)
 {
     int i, j;
     struct lys_tpdf *tpdf;
     int tpdf_size;
 
-    if (!prefix) {
+    if (!mod_name) {
         /* no prefix, try built-in types */
         for (i = 1; i < LY_DATA_TYPE_COUNT; i++) {
             if (!strcmp(ly_types[i].def->name, name)) {
@@ -1285,13 +1286,13 @@
             }
         }
     } else {
-        if (!strcmp(prefix, module->prefix)) {
+        if (!strcmp(mod_name, module->name)) {
             /* prefix refers to the current module, ignore it */
-            prefix = NULL;
+            mod_name = NULL;
         }
     }
 
-    if (!prefix && parent) {
+    if (!mod_name && parent) {
         /* search in local typedefs */
         while (parent) {
             switch (parent->nodetype) {
@@ -1342,9 +1343,9 @@
 
             parent = parent->parent;
         }
-    } else if (prefix) {
+    } else if (mod_name) {
         /* get module where to search */
-        module = resolve_prefixed_module(module, prefix, strlen(prefix));
+        module = ly_ctx_get_module(module->ctx, mod_name, NULL);
         if (!module) {
             return -1;
         }
@@ -1375,14 +1376,81 @@
     return EXIT_FAILURE;
 }
 
-/* logs directly */
+/**
+ * @brief Check the default \p value of the \p type. Logs directly.
+ *
+ * @param[in] type Type definition to use.
+ * @param[in] value Default value to check.
+ * @param[in] first Whether this is the first resolution try. Affects logging.
+ * @param[in] line Line in the input file.
+ *
+ * @return EXIT_SUCCESS on success, EXIT_FAILURE on forward reference, -1 on error.
+ */
 static int
-check_default(struct lys_type *type, const char *value)
+check_default(struct lys_type *type, const char *value, int first, uint32_t line)
 {
-    /* TODO - RFC 6020, sec. 7.3.4 */
-    (void)type;
-    (void)value;
-    return EXIT_SUCCESS;
+    struct lyd_node_leaf_list node;
+    struct lys_type *iter;
+    int ret = EXIT_SUCCESS, found;
+
+    /* dummy leaf */
+    node.value_str = value;
+    node.value_type = type->base;
+    node.schema = calloc(1, sizeof *node.schema);
+    node.schema->name = strdup("default");
+
+    if (type->base == LY_TYPE_UNION) {
+        found = 0;
+        iter = lyp_get_next_union_type(type, NULL, &found);
+        while (iter) {
+            node.value_type = iter->base;
+
+            /* special case with too much effort required and almost no added value */
+            if ((iter->base == LY_TYPE_IDENT) || (iter->base == LY_TYPE_INST)) {
+                LOGVAL(LYE_SPEC, line,
+                       "Union with \"instance-identifier\" or \"identityref\" and a default value is not supported!");
+                ret = -1;
+                goto finish;
+            }
+
+            if (!lyp_parse_value(&node, iter, 1, NULL, UINT_MAX)) {
+                break;
+            }
+
+            found = 0;
+            iter = lyp_get_next_union_type(type, iter, &found);
+        }
+
+        if (!iter) {
+            if (!first) {
+                LOGVAL(LYE_INVAL, line, node.value_str, "default");
+            }
+            ret = EXIT_FAILURE;
+            goto finish;
+        }
+
+    } else if (type->base == LY_TYPE_LEAFREF) {
+        if (!type->info.lref.target) {
+            ret = EXIT_FAILURE;
+            goto finish;
+        }
+        ret = check_default(&type->info.lref.target->type, value, first, line);
+
+    } else if ((type->base == LY_TYPE_INST) || (type->base == LY_TYPE_IDENT)) {
+        /* it was converted to JSON format before, nothing else sensible we can do */
+
+    } else {
+        ret = lyp_parse_value(&node, type, 1, NULL, (first ? UINT_MAX : line));
+    }
+
+finish:
+    if (node.value_type == LY_TYPE_BITS) {
+        free(node.value.bit);
+    }
+    free((char *)node.schema->name);
+    free(node.schema);
+
+    return ret;
 }
 
 /**
@@ -1555,7 +1623,7 @@
     if (prefix) {
         module = resolve_prefixed_module(uses->module, prefix, pref_len);
         if (!module) {
-            LOGVAL(LYE_INPREF_LEN, line, pref_len, prefix);
+            LOGVAL(LYE_INMOD_LEN, line, pref_len, prefix);
             return -1;
         }
         start = module->data;
@@ -1609,7 +1677,7 @@
         module = resolve_prefixed_module(module, prefix, pref_len);
         if (!module) {
             /* identity refers unknown data model */
-            LOGVAL(LYE_INPREF_LEN, line, pref_len, prefix);
+            LOGVAL(LYE_INMOD_LEN, line, pref_len, prefix);
             return -1;
         }
     } else {
@@ -1644,135 +1712,6 @@
 }
 
 /**
- * @brief Resolve (find) a valid sibling. Does not log.
- *
- * Valid child means a schema pointer to a node that is part of
- * the data meaning uses are skipped. Includes module comparison
- * (can handle augments). Module is adjusted based on the prefix.
- * Includes are also searched if siblings are top-level nodes.
- *
- * @param[in] mod Main module. Prefix is considered to be from this module.
- * @param[in] siblings Siblings to consider. They are first adjusted to
- *                     point to the first sibling.
- * @param[in] prefix Node prefix.
- * @param[in] pref_len Node prefix length.
- * @param[in] name Node name.
- * @param[in] nam_len Node name length.
- * @param[in] type ORed desired type of the node. 0 means any type.
- *                 Returns only schema data nodes (no uses, grouping, augment, choice, case).
- * @param[out] ret Pointer to the node of the desired type. Can be NULL.
- *
- * @return EXIT_SUCCESS on success, EXIT_FAILURE on forward reference, -1 on error.
- */
-int
-resolve_sibling(struct lys_module *mod, struct lys_node *siblings, const char *prefix, int pref_len, const char *name,
-                int nam_len, LYS_NODE type, struct lys_node **ret)
-{
-    struct lys_node *node, *old_siblings = NULL;
-    struct lys_module *prefix_mod, *cur_mod;
-    int in_submod;
-
-    assert(siblings && name);
-    assert(!(type & LYS_USES));
-
-    /* find the beginning */
-    while (siblings->prev->next) {
-        siblings = siblings->prev;
-    }
-
-    /* fill the name length in case the caller is so indifferent */
-    if (!nam_len) {
-        nam_len = strlen(name);
-    }
-
-    /* we start with the module itself, submodules come later */
-    in_submod = 0;
-
-    /* set prefix_mod correctly */
-    if (prefix) {
-        prefix_mod = resolve_prefixed_module(mod, prefix, pref_len);
-        if (!prefix_mod) {
-            return -1;
-        }
-        cur_mod = prefix_mod;
-        /* it is not our module */
-        if (cur_mod != mod) {
-            old_siblings = siblings;
-            siblings = cur_mod->data;
-        }
-    } else {
-        if (mod) {
-            prefix_mod = mod;
-        } else {
-            prefix_mod = siblings->module;
-        }
-        if (prefix_mod->type) {
-            prefix_mod = ((struct lys_submodule *)prefix_mod)->belongsto;
-        }
-        cur_mod = prefix_mod;
-    }
-
-    while (1) {
-        /* try to find the node */
-        node = NULL;
-        while ((node = lys_getnext(node, siblings->parent, cur_mod, 0))) {
-            if (!type || (node->nodetype & type)) {
-                /* module check */
-                if (!node->module->type) {
-                    if (cur_mod != node->module) {
-                        continue;
-                    }
-                } else {
-                    /* both are submodules */
-                    if (cur_mod->type) {
-                        if (cur_mod != node->module) {
-                            continue;
-                        }
-                    } else {
-                        if (cur_mod != ((struct lys_submodule *)node->module)->belongsto) {
-                            continue;
-                        }
-                    }
-                }
-
-                /* direct name check */
-                if (node->name == name || (!strncmp(node->name, name, nam_len) && !node->name[nam_len])) {
-                    if (ret) {
-                        *ret = node;
-                    }
-                    return EXIT_SUCCESS;
-                }
-            }
-        }
-
-        /* The original siblings may be valid,
-         * it's a special case when we're looking
-         * for a node from augment.
-         */
-        if (old_siblings) {
-            siblings = old_siblings;
-            old_siblings = NULL;
-            continue;
-        }
-
-        /* we're not top-level, search ended */
-        if (siblings->parent) {
-            break;
-        }
-
-        /* let's try the submodules */
-        if (in_submod == prefix_mod->inc_size) {
-            break;
-        }
-        cur_mod = (struct lys_module *)prefix_mod->inc[in_submod].submodule;
-        siblings = cur_mod->data;
-        ++in_submod;
-    }
-
-    return EXIT_FAILURE;
-}
-
-/**
  * @brief Resolve (find) a schema node based on a schema-nodeid. Does not log.
  *
  * node_type - LYS_AUGMENT (searches also RPCs and notifications)
@@ -2344,7 +2283,7 @@
         path += i;
 
         /* source (must be leaf) */
-        rc = resolve_sibling(mod, source_node->child, sour_pref, sour_pref_len, source, sour_len, LYS_LEAF, &src_node);
+        rc = lys_getsibling(mod, source_node->child, sour_pref, sour_pref_len, source, sour_len, LYS_LEAF, &src_node);
         if (rc) {
             if ((rc == -1) || !first) {
                 LOGVAL(LYE_NORESOLV, line, path-parsed);
@@ -2372,7 +2311,7 @@
             }
         }
         while (1) {
-            rc = resolve_sibling(mod, dst_node->child, dest_pref, dest_pref_len, dest, dest_len,
+            rc = lys_getsibling(mod, dst_node->child, dest_pref, dest_pref_len, dest, dest_len,
                                  LYS_CONTAINER | LYS_LIST | LYS_LEAF, &dst_node);
             if (rc) {
                 if ((rc == -1) || !first) {
@@ -2481,7 +2420,7 @@
             node = node->child;
         }
 
-        rc = resolve_sibling(mod, node, prefix, pref_len, name, nam_len, LYS_ANY & (~LYS_USES), &node);
+        rc = lys_getsibling(mod, node, prefix, pref_len, name, nam_len, 0, &node);
         if (rc) {
             if ((rc == -1) || !first) {
                 LOGVAL(LYE_NORESOLV, line, path);
@@ -3094,7 +3033,7 @@
         module = resolve_prefixed_module(module, basename, prefix_len);
         if (!module) {
             /* identity refers unknown data model */
-            LOGVAL(LYE_INPREF, line, basename);
+            LOGVAL(LYE_INMOD, line, basename);
             return -1;
         }
     } else {
@@ -3273,7 +3212,7 @@
             len = strlen(keys_str);
         }
 
-        rc = resolve_sibling(mod, list->child, NULL, 0, keys_str, len, LYS_LEAF, (struct lys_node **)&list->keys[i]);
+        rc = lys_getsibling(mod, list->child, NULL, 0, keys_str, len, LYS_LEAF, (struct lys_node **)&list->keys[i]);
         if (rc) {
             if ((rc == -1) || !first) {
                 LOGVAL(LYE_INRESOLV, line, "list keys", keys_str);
@@ -3551,9 +3490,9 @@
         stype = item;
 
         /* HACK type->der is temporarily its parent */
-        rc = resolve_superior_type(base_name, stype->prefix, mod, (struct lys_node *)stype->der, &stype->der);
+        rc = resolve_superior_type(base_name, stype->module_name, mod, (struct lys_node *)stype->der, &stype->der);
         if (rc == -1) {
-            LOGVAL(LYE_INPREF, line, stype->prefix);
+            LOGVAL(LYE_INMOD, line, stype->module_name);
         } else if (!rc) {
             stype->base = stype->der->type.base;
         }
@@ -3574,7 +3513,7 @@
         base_name = str_snode;
         stype = item;
 
-        rc = check_default(stype, base_name);
+        rc = check_default(stype, base_name, first, line);
         /* do not remove base_name (dflt), it's in a typedef */
         has_str = 0;
         break;
diff --git a/src/resolve.h b/src/resolve.h
index 710996a..1eb768a 100644
--- a/src/resolve.h
+++ b/src/resolve.h
@@ -107,9 +107,6 @@
 
 int resolve_unique(struct lys_node *parent, const char *uniq_str, struct lys_unique *uniq_s, int first, uint32_t line);
 
-int resolve_sibling(struct lys_module *mod, struct lys_node *siblings, const char *prefix, int pref_len,
-                    const char *name, int nam_len, LYS_NODE type, struct lys_node **ret);
-
 int resolve_schema_nodeid(const char *id, struct lys_node *start, struct lys_module *mod,
                           LYS_NODE node_type, struct lys_node **ret);
 
diff --git a/src/tree_data.c b/src/tree_data.c
index b17067b..b89d433 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -85,7 +85,7 @@
         siblings = parent->schema->child;
     }
 
-    if (resolve_sibling(module, siblings, NULL, 0, name, strlen(name), LYS_CONTAINER | LYS_LIST | LYS_NOTIF | LYS_RPC,
+    if (lys_getsibling(module, siblings, NULL, 0, name, strlen(name), LYS_CONTAINER | LYS_LIST | LYS_NOTIF | LYS_RPC,
             &snode) || !snode) {
         return NULL;
     }
@@ -131,7 +131,7 @@
         siblings = parent->schema->child;
     }
 
-    if (resolve_sibling(module, siblings, NULL, 0, name, strlen(name), LYS_LEAFLIST | LYS_LEAF, &snode)
+    if (lys_getsibling(module, siblings, NULL, 0, name, strlen(name), LYS_LEAFLIST | LYS_LEAF, &snode)
             || !snode) {
         return NULL;
     }
@@ -341,7 +341,7 @@
         siblings = parent->schema->child;
     }
 
-    if (resolve_sibling(module, siblings, NULL, 0, name, strlen(name), LYS_LEAFLIST | LYS_LEAF, &snode)
+    if (lys_getsibling(module, siblings, NULL, 0, name, strlen(name), LYS_LEAFLIST | LYS_LEAF, &snode)
             || !snode) {
         ly_errno = LY_EINVAL;
         return NULL;
@@ -416,7 +416,7 @@
         ctx = parent->schema->module->ctx;
     }
 
-    if (resolve_sibling(module, siblings, NULL, 0, name, strlen(name), LYS_ANYXML, &snode)
+    if (lys_getsibling(module, siblings, NULL, 0, name, strlen(name), LYS_ANYXML, &snode)
             || !snode) {
         return NULL;
     }
diff --git a/src/tree_data.h b/src/tree_data.h
index b387719..606724e 100644
--- a/src/tree_data.h
+++ b/src/tree_data.h
@@ -205,6 +205,7 @@
  * @param[in] module Module with the node being created.
  * @param[in] name Schema node name of the new data node. The node can be #LYS_CONTAINER, #LYS_LIST,
  * #LYS_INPUT, #LYS_OUTPUT, #LYS_NOTIF, or #LYS_RPC.
+ * @return New node, NULL on error.
  */
 struct lyd_node *lyd_new(struct lyd_node *parent, struct lys_module *module, const char *name);
 
@@ -217,6 +218,7 @@
  * @param[in] type Type of the value provided in the \p value parameter. Cannot be #LY_TYPE_DER, #LY_TYPE_UNION,
  * or #LY_TYPE_INST.
  * @param[in] value Value of the node being created. Can be NULL only if \p type is #LY_TYPE_EMPTY.
+ * @return New node, NULL on error.
  */
 struct lyd_node *lyd_new_leaf_val(struct lyd_node *parent, struct lys_module *module, const char *name,
                                   LY_DATA_TYPE type, lyd_val value);
@@ -234,6 +236,7 @@
  * #LY_TYPE_UNION in this case.
  * @param[in] val_str String form of the value of the node being created. Can be NULL only if \p type is
  * #LY_TYPE_EMPTY.
+ * @return New node, NULL on error.
  */
 struct lyd_node *lyd_new_leaf_str(struct lyd_node *parent, struct lys_module *module, const char *name,
                                   LY_DATA_TYPE type, const char *val_str);
@@ -245,6 +248,7 @@
  * @param[in] module Module with the node being created.
  * @param[in] name Schema node name of the new data node.
  * @param[in] val_xml Value of the node being created. Must be a well-formed XML.
+ * @return New node, NULL on error.
  */
 struct lyd_node *lyd_new_anyxml(struct lyd_node *parent, struct lys_module *module, const char *name,
                                 const char *val_xml);
diff --git a/src/tree_internal.h b/src/tree_internal.h
index 51fd2b6..231a16e 100644
--- a/src/tree_internal.h
+++ b/src/tree_internal.h
@@ -123,29 +123,6 @@
 int lys_node_addchild(struct lys_node *parent, struct lys_module *module, struct lys_node *child);
 
 /**
- * @brief Get next schema tree (sibling) node element that can be instanciated in a data tree.
- *
- * lys_getnext() is supposed to be called sequentially. In the first call, the \p last parameter is usually NULL
- * and function starts returning i) the first \p parent child or ii) the first top level element of the \p module.
- * Consequent calls suppose to provide the previously returned node as the \p last parameter and still the same
- * \p parent and \p module parameters.
- *
- * The function does not traverse via RPCs and Notifications.
- *
- * @param[in] last Previously returned schema tree node, or NULL in case of the first call.
- * @param[in] parent Parent of the subtree where the function starts processing
- * @param[in] module In case of iterating on top level elements, the \p parent is NULL and module must be specified.
- * @param[in] option 1 to include the choice schema nodes into the result set.
- * @return Next schema tree node that can be instanciated in a data tree, NULL in case there is no such element
- */
-struct lys_node *lys_getnext(struct lys_node *last, struct lys_node *parent, struct lys_module *module, int options);
-
-/**
- * @brief option for lys_getnext() to allow returning the choice nodes.
- */
-#define LYS_GETNEXT_WITHCHOICE  0x01
-
-/**
  * @brief Find a valid grouping definition relative to a node.
  *
  * Valid definition means a sibling of \p start or a sibling of any of \p start 's parents.
@@ -265,6 +242,29 @@
 struct lyd_node *lyd_attr_parent(struct lyd_node *root, struct lyd_attr *attr);
 
 /**
+ * @brief Find a specific sibling. Does not log.
+ *
+ * Includes module comparison (can handle augments). Module is adjusted
+ * based on the \p mod_name. Includes are also searched if siblings are
+ * top-level nodes.
+ *
+ * @param[in] mod Main module. Prefix is considered to be from this module.
+ * @param[in] siblings Siblings to consider. They are first adjusted to
+ *                     point to the first sibling.
+ * @param[in] mod_name Module name.
+ * @param[in] mod_name_len Module name length.
+ * @param[in] name Node name.
+ * @param[in] nam_len Node name length.
+ * @param[in] type ORed desired type of the node. 0 means any type.
+ *                 Does not return groupings, uses, and augments (but returns augment nodes).
+ * @param[out] ret Pointer to the node of the desired type. Can be NULL.
+ *
+ * @return EXIT_SUCCESS on success, EXIT_FAILURE on forward reference, -1 on error.
+ */
+int lys_getsibling(struct lys_module *mod, struct lys_node *siblings, const char *mod_name, int mod_name_len,
+                   const char *name, int nam_len, LYS_NODE type, struct lys_node **ret);
+
+/**
  * @brief Compare 2 data nodes if they are the same from the YANG point of view.
  *
  * - containers are the same if they are defined by the same schema tree node
diff --git a/src/tree_schema.c b/src/tree_schema.c
index 51e2cd3..4645fef 100644
--- a/src/tree_schema.c
+++ b/src/tree_schema.c
@@ -85,7 +85,118 @@
     goto check;
 }
 
-struct lys_node *
+int
+lys_getsibling(struct lys_module *mod, struct lys_node *siblings, const char *mod_name, int mod_name_len,
+               const char *name, int nam_len, LYS_NODE type, struct lys_node **ret)
+{
+    struct lys_node *node, *old_siblings = NULL;
+    struct lys_module *prefix_mod, *cur_mod;
+    int in_submod;
+    char *module_name;
+
+    assert(siblings && name);
+    assert(!(type & (LYS_AUGMENT | LYS_USES | LYS_GROUPING)));
+
+    /* find the beginning */
+    while (siblings->prev->next) {
+        siblings = siblings->prev;
+    }
+
+    /* fill the name length in case the caller is so indifferent */
+    if (!nam_len) {
+        nam_len = strlen(name);
+    }
+
+    /* we start with the module itself, submodules come later */
+    in_submod = 0;
+
+    /* set prefix_mod correctly */
+    if (mod_name) {
+        module_name = strndup(mod_name, mod_name_len);
+        prefix_mod = ly_ctx_get_module(siblings->module->ctx, module_name, NULL);
+        free(module_name);
+        if (!prefix_mod) {
+            return -1;
+        }
+        cur_mod = prefix_mod;
+        /* it is not our module */
+        if (cur_mod != mod) {
+            old_siblings = siblings;
+            siblings = cur_mod->data;
+        }
+    } else {
+        if (mod) {
+            prefix_mod = mod;
+        } else {
+            prefix_mod = siblings->module;
+        }
+        if (prefix_mod->type) {
+            prefix_mod = ((struct lys_submodule *)prefix_mod)->belongsto;
+        }
+        cur_mod = prefix_mod;
+    }
+
+    while (1) {
+        /* try to find the node */
+        node = NULL;
+        while ((node = lys_getnext(node, siblings->parent, cur_mod, LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHCASE))) {
+            if (!type || (node->nodetype & type)) {
+                /* module check */
+                if (!node->module->type) {
+                    if (cur_mod != node->module) {
+                        continue;
+                    }
+                } else {
+                    /* both are submodules */
+                    if (cur_mod->type) {
+                        if (cur_mod != node->module) {
+                            continue;
+                        }
+                    } else {
+                        if (cur_mod != ((struct lys_submodule *)node->module)->belongsto) {
+                            continue;
+                        }
+                    }
+                }
+
+                /* direct name check */
+                if ((node->name == name) || (!strncmp(node->name, name, nam_len) && !node->name[nam_len])) {
+                    if (ret) {
+                        *ret = node;
+                    }
+                    return EXIT_SUCCESS;
+                }
+            }
+        }
+
+        /* The original siblings may be valid,
+         * it's a special case when we're looking
+         * for a node from an augment.
+         */
+        if (old_siblings) {
+            siblings = old_siblings;
+            old_siblings = NULL;
+            continue;
+        }
+
+        /* we're not top-level, search ended */
+        if (siblings->parent) {
+            break;
+        }
+
+        /* let's try the submodules */
+        if (in_submod == prefix_mod->inc_size) {
+            break;
+        }
+        cur_mod = (struct lys_module *)prefix_mod->inc[in_submod].submodule;
+        siblings = cur_mod->data;
+        ++in_submod;
+    }
+
+    return EXIT_FAILURE;
+}
+
+API struct lys_node *
 lys_getnext(struct lys_node *last, struct lys_node *parent, struct lys_module *module, int options)
 {
     struct lys_node *next;
@@ -123,10 +234,14 @@
     }
 
     switch (next->nodetype) {
-    case LYS_USES:
     case LYS_CASE:
+        if (options & LYS_GETNEXT_WITHCASE) {
+            return next;
+        }
+        /* fallthrough */
     case LYS_INPUT:
     case LYS_OUTPUT:
+    case LYS_USES:
         /* go into */
         next = next->child;
         goto repeat;
@@ -1035,7 +1150,7 @@
 {
     int i;
 
-    new->prefix = lydict_insert(mod->ctx, old->prefix, 0);
+    new->module_name = lydict_insert(mod->ctx, old->module_name, 0);
     new->base = old->base;
     new->der = old->der;
 
@@ -1165,7 +1280,7 @@
         return;
     }
 
-    lydict_remove(ctx, type->prefix);
+    lydict_remove(ctx, type->module_name);
 
     switch (type->base) {
     case LY_TYPE_BINARY:
@@ -2074,7 +2189,7 @@
         }
 
         if (choice_orig->dflt) {
-            rc = resolve_sibling(choice->module, choice->child, NULL, 0, choice_orig->dflt->name, 0, LYS_ANYXML
+            rc = lys_getsibling(choice->module, choice->child, NULL, 0, choice_orig->dflt->name, 0, LYS_ANYXML
                                          | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST
                                          | LYS_LIST, &choice->dflt);
             if (rc) {
@@ -2149,8 +2264,8 @@
             /* we managed to resolve it before, resolve it again manually */
             if (list_orig->keys[0]) {
                 for (i = 0; i < list->keys_size; ++i) {
-                    rc = resolve_sibling(list->module, list->child, NULL, 0, list_orig->keys[i]->name, 0, LYS_LEAF,
-                                         (struct lys_node **)&list->keys[i]);
+                    rc = lys_getsibling(list->module, list->child, NULL, 0, list_orig->keys[i]->name, 0, LYS_LEAF,
+                                        (struct lys_node **)&list->keys[i]);
                     if (rc) {
                         if (rc == EXIT_FAILURE) {
                             LOGINT;
diff --git a/src/tree_schema.h b/src/tree_schema.h
index 7fdeb40..41abd66 100644
--- a/src/tree_schema.h
+++ b/src/tree_schema.h
@@ -357,7 +357,7 @@
  * @brief YANG type structure providing information from the schema
  */
 struct lys_type {
-    const char *prefix;              /**< prefix for the type referenced in der pointer*/
+    const char *module_name;         /**< module name of the type referenced in der pointer*/
     LY_DATA_TYPE base;               /**< base type */
     struct lys_tpdf *der;            /**< pointer to the superior typedef. If NULL,
                                           structure provides information about one of the built-in types */
@@ -1292,6 +1292,29 @@
 struct lys_feature *lys_is_disabled(struct lys_node *node, int recursive);
 
 /**
+ * @brief Get next schema tree (sibling) node element that can be instanciated in a data tree. Returned node can
+ * be from an augment.
+ *
+ * lys_getnext() is supposed to be called sequentially. In the first call, the \p last parameter is usually NULL
+ * and function starts returning i) the first \p parent child or ii) the first top level element of the \p module.
+ * Consequent calls suppose to provide the previously returned node as the \p last parameter and still the same
+ * \p parent and \p module parameters.
+ *
+ * @param[in] last Previously returned schema tree node, or NULL in case of the first call.
+ * @param[in] parent Parent of the subtree where the function starts processing
+ * @param[in] module In case of iterating on top level elements, the \p parent is NULL and module must be specified.
+ * @param[in] options 1 for including choice, 2 for case schema nodes in the result set.
+ * @return Next schema tree node that can be instanciated in a data tree, NULL in case there is no such element
+ */
+struct lys_node *lys_getnext(struct lys_node *last, struct lys_node *parent, struct lys_module *module, int options);
+
+/**
+ * @brief options for lys_getnext() to allow returning choice and case nodes.
+ */
+#define LYS_GETNEXT_WITHCHOICE   0x01
+#define LYS_GETNEXT_WITHCASE     0x02
+
+/**
  * @brief Return parent node in the schema tree.
  *
  * In case of augmenting node, it returns the target tree node where the augmenting