libyang REFACTOR prefix format always decides the callback (#1169)

So the callback is no longer needed as a parameter.
Also, union no longer uses its own prefix mappings
but instead uses the original format and copies any
required prefix data.
diff --git a/src/common.h b/src/common.h
index f7faa86..eb1cbf6 100644
--- a/src/common.h
+++ b/src/common.h
@@ -459,22 +459,6 @@
                                    const char **value, size_t *value_len, const char **errmsg);
 
 /**
- * @brief ly_get_prefix_clb implementation for JSON. For its simplicity, this implementation is used
- * internally for various purposes.
- *
- * Implemented in printer_json.c
- */
-const char *json_print_get_prefix(const struct lys_module *mod, void *private);
-
-/**
- * @brief ly_type_resolve_prefix implementation for JSON. For its simplicity, this implementation is used
- * internally for various purposes.
- *
- * Implemented in parser_json.c
- */
-const struct lys_module *lydjson_resolve_prefix(const struct ly_ctx *ctx, const char *prefix, size_t prefix_len, void *parser);
-
-/**
  * @brief mmap(2) wrapper to map input files into memory to unify parsing.
  *
  * The address space is allocate only for reading.
diff --git a/src/context.c b/src/context.c
index bb7a432..e7b4773 100644
--- a/src/context.c
+++ b/src/context.c
@@ -560,7 +560,7 @@
     /* compile */
     oper = output ? LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT;
     ret = ly_path_compile(ctx, NULL, ctx_node, exp, LY_PATH_LREF_FALSE, oper, LY_PATH_TARGET_MANY,
-                          lydjson_resolve_prefix, NULL, LYD_JSON, &p);
+                          LY_PREF_JSON, NULL, &p);
     LY_CHECK_GOTO(ret, cleanup);
 
     /* get last node */
diff --git a/src/lyb.h b/src/lyb.h
index 000fab3..1928ba5 100644
--- a/src/lyb.h
+++ b/src/lyb.h
@@ -71,7 +71,6 @@
 
     /* callbacks */
     lyd_ctx_free_clb free;           /* destructor */
-    ly_resolve_prefix_clb resolve_prefix;
 
     struct lylyb_ctx *lybctx;      /* lyb format context */
 };
diff --git a/src/parser.c b/src/parser.c
index e84dc58..a54dce7 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -407,12 +407,11 @@
 
 LY_ERR
 lyd_parser_create_term(struct lyd_ctx *lydctx, const struct lysc_node *schema, const char *value, size_t value_len,
-                       int *dynamic, int value_hints, ly_resolve_prefix_clb get_prefix, void *prefix_data,
-                       LYD_FORMAT format, struct lyd_node **node)
+                       int *dynamic, int value_hints, LY_PREFIX_FORMAT format, void *prefix_data, struct lyd_node **node)
 {
     LY_ERR ret;
 
-    ret = lyd_create_term(schema, value, value_len, dynamic, value_hints, get_prefix, prefix_data, format, node);
+    ret = lyd_create_term(schema, value, value_len, dynamic, value_hints, format, prefix_data, node);
     if (ret == LY_EINCOMPLETE) {
         if (!(lydctx->parse_options & LYD_PARSE_ONLY)) {
             ly_set_add(&lydctx->unres_node_type, *node, LY_SET_OPT_USEASLIST);
@@ -425,10 +424,11 @@
 LY_ERR
 lyd_parser_create_meta(struct lyd_ctx *lydctx, struct lyd_node *parent, struct lyd_meta **meta, const struct lys_module *mod,
                        const char *name, size_t name_len, const char *value, size_t value_len, int *dynamic, int value_hints,
-                       ly_resolve_prefix_clb resolve_prefix, void *prefix_data, LYD_FORMAT format, const struct lysc_node *ctx_snode)
+                       LY_PREFIX_FORMAT format, void *prefix_data, const struct lysc_node *ctx_snode)
 {
     LY_ERR ret;
-    ret = lyd_create_meta(parent, meta, mod, name, name_len, value, value_len, dynamic, value_hints, resolve_prefix, prefix_data, format, ctx_snode);
+    ret = lyd_create_meta(parent, meta, mod, name, name_len, value, value_len, dynamic, value_hints, format, prefix_data,
+                          ctx_snode);
     if (ret == LY_EINCOMPLETE) {
         ly_set_add(&lydctx->unres_meta_type, *meta, LY_SET_OPT_USEASLIST);
         ret = LY_SUCCESS;
diff --git a/src/parser_internal.h b/src/parser_internal.h
index b2c4f15..2e60b06 100644
--- a/src/parser_internal.h
+++ b/src/parser_internal.h
@@ -16,6 +16,7 @@
 #define LY_PARSER_INTERNAL_H_
 
 #include "parser.h"
+#include "plugins_types.h"
 #include "tree_schema_internal.h"
 
 /**
@@ -24,11 +25,12 @@
 #define LYD_PARSE_OPTS_MASK    0xFFFF0000
 
 /**
- * @brief Mask for checking LYD_VALIDATEP_ options (@ref datavalidationoptions)
+ * @brief Mask for checking LYD_VALIDATE_ options (@ref datavalidationoptions)
  */
 #define LYD_VALIDATE_OPTS_MASK 0x0000FFFF
 
 struct lyd_ctx;
+
 /**
  * @brief Callback for lyd_ctx to free the structure
  *
@@ -53,7 +55,6 @@
 
     /* callbacks */
     lyd_ctx_free_clb free;             /* destructor */
-    ly_resolve_prefix_clb resolve_prefix;
 
     struct {
         const struct ly_ctx *ctx;
@@ -170,8 +171,7 @@
  * @param[in] value_hints Data parser's hint for the value's type.
  */
 LY_ERR lyd_parser_create_term(struct lyd_ctx *lydctx, const struct lysc_node *schema, const char *value, size_t value_len,
-                              int *dynamic, int value_hints, ly_resolve_prefix_clb get_prefix, void *prefix_data,
-                              LYD_FORMAT format, struct lyd_node **node);
+                              int *dynamic, int value_hints, LY_PREFIX_FORMAT format, void *prefix_data, struct lyd_node **node);
 
 /**
  * @brief Wrapper around lyd_create_meta() for data parsers.
@@ -179,8 +179,9 @@
  * @param[in] lydctx Data parser context.
  * @param[in] value_hints [Value hint](@ref lydvalueparseopts) from the parser regarding the value type.
  */
-LY_ERR lyd_parser_create_meta(struct lyd_ctx *lydctx, struct lyd_node *parent, struct lyd_meta **meta, const struct lys_module *mod,
-                              const char *name, size_t name_len, const char *value, size_t value_len, int *dynamic, int value_hints,
-                              ly_resolve_prefix_clb resolve_prefix, void *prefix_data, LYD_FORMAT format, const struct lysc_node *ctx_snode);
+LY_ERR lyd_parser_create_meta(struct lyd_ctx *lydctx, struct lyd_node *parent, struct lyd_meta **meta,
+                              const struct lys_module *mod, const char *name, size_t name_len, const char *value,
+                              size_t value_len, int *dynamic, int value_hints, LY_PREFIX_FORMAT format,
+                              void *prefix_data, const struct lysc_node *ctx_snode);
 
 #endif /* LY_PARSER_INTERNAL_H_ */
diff --git a/src/parser_json.c b/src/parser_json.c
index 6e3e91b..b52865e 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -47,7 +47,6 @@
 
     /* callbacks */
     lyd_ctx_free_clb free;           /* destructor */
-    ly_resolve_prefix_clb resolve_prefix;
 
     struct lyjson_ctx *jsonctx;    /**< JSON context */
 };
@@ -70,15 +69,6 @@
 }
 
 /**
- * @brief JSON implementation of ly_resolve_prefix_clb.
- */
-const struct lys_module *
-lydjson_resolve_prefix(const struct ly_ctx *ctx, const char *prefix, size_t prefix_len, void *UNUSED(parser))
-{
-    return ly_ctx_get_module_implemented2(ctx, prefix, prefix_len);
-}
-
-/**
  * @brief Parse JSON member-name as [\@][prefix:][name]
  *
  * \@ - metadata flag, maps to 1 in @p is_meta_p
@@ -407,7 +397,7 @@
                         goto cleanup;
                     }
 
-                    ret = _lys_value_validate(NULL, snode, jsonctx->value, jsonctx->value_len, lydjson_resolve_prefix, jsonctx, LYD_JSON);
+                    ret = _lys_value_validate(NULL, snode, jsonctx->value, jsonctx->value_len, LY_PREF_JSON, NULL);
                     LY_CHECK_GOTO(ret, cleanup);
 
                     /* key with a valid value, remove from the set */
@@ -520,8 +510,7 @@
                 break;
             }
 
-            if (_lys_value_validate(NULL, snode, jsonctx->value, jsonctx->value_len, lydjson_resolve_prefix, jsonctx,
-                    LYD_JSON)) {
+            if (_lys_value_validate(NULL, snode, jsonctx->value, jsonctx->value_len, LY_PREF_JSON, NULL)) {
                 ret = LY_ENOT;
             }
             break;
@@ -652,7 +641,7 @@
                     if (mod) {
                         ret = lyd_parser_create_meta((struct lyd_ctx*)lydctx, node, NULL, mod,
                                                      meta->name, strlen(meta->name), meta->value, ly_strlen(meta->value),
-                                                     &dynamic, meta->hint, lydjson_resolve_prefix, NULL, LYD_JSON, snode);
+                                                     &dynamic, meta->hint, LY_PREF_JSON, NULL, snode);
                         LY_CHECK_GOTO(ret, cleanup);
                     } else if (lydctx->parse_options & LYD_PARSE_STRICT) {
                         LOGVAL(lydctx->jsonctx->ctx, LY_VLOG_LYD, node, LYVE_REFERENCE,
@@ -832,8 +821,8 @@
         if (node->schema) {
             /* create metadata */
             meta = NULL;
-            ret = lyd_parser_create_meta((struct lyd_ctx*)lydctx, node, &meta, mod, name, name_len, lydctx->jsonctx->value, lydctx->jsonctx->value_len,
-                                         &lydctx->jsonctx->dynamic, 0, lydjson_resolve_prefix, lydctx->jsonctx, LYD_JSON, snode);
+            ret = lyd_parser_create_meta((struct lyd_ctx*)lydctx, node, &meta, mod, name, name_len, lydctx->jsonctx->value,
+                                         lydctx->jsonctx->value_len, &lydctx->jsonctx->dynamic, 0, LY_PREF_JSON, NULL, snode);
             LY_CHECK_GOTO(ret, cleanup);
 
             /* add/correct flags */
@@ -1109,7 +1098,7 @@
             /* create terminal node */
             ret = lyd_parser_create_term((struct lyd_ctx *)lydctx, snode, lydctx->jsonctx->value,
                                         lydctx->jsonctx->value_len, &lydctx->jsonctx->dynamic, type_hint,
-                                        lydjson_resolve_prefix, lydctx->jsonctx, LYD_JSON, node);
+                                        LY_PREF_JSON, NULL, node);
             LY_CHECK_RET(ret);
 
             /* move JSON parser */
@@ -1409,7 +1398,6 @@
     lydctx->parse_options = parse_options;
     lydctx->validate_options = validate_options;
     lydctx->free = lyd_json_ctx_free;
-    lydctx->resolve_prefix = lydjson_resolve_prefix;
 
     LY_CHECK_ERR_RET(ret = lyjson_ctx_new(ctx, in, &lydctx->jsonctx), free(lydctx), ret);
 
diff --git a/src/parser_lyb.c b/src/parser_lyb.c
index 3cd222e..80c4159 100644
--- a/src/parser_lyb.c
+++ b/src/parser_lyb.c
@@ -380,8 +380,8 @@
         dynamic = 1;
 
         /* create metadata */
-        ret = lyd_parser_create_meta((struct lyd_ctx*)lybctx, NULL, meta, mod, meta_name, strlen(meta_name), meta_value, ly_strlen(meta_value),
-                                     &dynamic, 0, lydjson_resolve_prefix, NULL, LYD_JSON, sparent);
+        ret = lyd_parser_create_meta((struct lyd_ctx *)lybctx, NULL, meta, mod, meta_name, strlen(meta_name), meta_value,
+                                     ly_strlen(meta_value), &dynamic, 0, LY_PREF_JSON, NULL, sparent);
 
         /* free strings */
         free(meta_name);
@@ -767,8 +767,8 @@
         dynamic = 1;
 
         /* create node */
-        ret = lyd_parser_create_term((struct lyd_ctx*)lybctx, snode, value, ly_strlen(value), &dynamic, 0,
-                                     lydjson_resolve_prefix, NULL, LYD_JSON, &node);
+        ret = lyd_parser_create_term((struct lyd_ctx *)lybctx, snode, value, ly_strlen(value), &dynamic, 0,
+                                     LY_PREF_JSON, NULL, &node);
         if (dynamic) {
             free(value);
             dynamic = 0;
diff --git a/src/parser_xml.c b/src/parser_xml.c
index c4bfb53..2e2180a 100644
--- a/src/parser_xml.c
+++ b/src/parser_xml.c
@@ -47,7 +47,6 @@
 
     /* callbacks */
     lyd_ctx_free_clb free;           /* destructor */
-    ly_resolve_prefix_clb resolve_prefix;
 
     struct lyxml_ctx *xmlctx;      /**< XML context */
 };
@@ -62,24 +61,6 @@
     free(ctx);
 }
 
-/**
- * @brief XML-parser's implementation of ly_type_resolve_prefix() callback to provide mapping between prefixes used
- * in the values to the schema via XML namespaces.
- */
-static const struct lys_module *
-lydxml_resolve_prefix(const struct ly_ctx *ctx, const char *prefix, size_t prefix_len, void *parser)
-{
-    const struct lyxml_ns *ns;
-    struct lyxml_ctx *xmlctx = (struct lyxml_ctx *)parser;
-
-    ns = lyxml_ns_get(xmlctx, prefix, prefix_len);
-    if (!ns) {
-        return NULL;
-    }
-
-    return ly_ctx_get_module_implemented_ns(ctx, ns->uri);
-}
-
 static LY_ERR
 lydxml_metadata(struct lyd_xml_ctx *lydctx, const struct lysc_node *sparent, struct lyd_meta **meta)
 {
@@ -110,7 +91,7 @@
         }
 
         /* get namespace of the attribute to find its annotation definition */
-        ns = lyxml_ns_get(xmlctx, xmlctx->prefix, xmlctx->prefix_len);
+        ns = lyxml_ns_get(&xmlctx->ns, xmlctx->prefix, xmlctx->prefix_len);
         if (!ns) {
             /* unknown namespace, XML error */
             LOGVAL(xmlctx->ctx, LY_VLOG_LINE, &xmlctx->line, LYVE_REFERENCE, "Unknown XML prefix \"%.*s\".",
@@ -137,8 +118,8 @@
         assert(xmlctx->status == LYXML_ATTR_CONTENT);
 
         /* create metadata */
-        ret = lyd_parser_create_meta((struct lyd_ctx*)lydctx, NULL, meta, mod, name, name_len, xmlctx->value, xmlctx->value_len,
-                                     &xmlctx->dynamic, 0, lydxml_resolve_prefix, xmlctx, LYD_XML, sparent);
+        ret = lyd_parser_create_meta((struct lyd_ctx *)lydctx, NULL, meta, mod, name, name_len, xmlctx->value,
+                                     xmlctx->value_len, &xmlctx->dynamic, 0, LY_PREF_XML, &xmlctx->ns, sparent);
         LY_CHECK_GOTO(ret, cleanup);
 
         /* next attribute */
@@ -172,7 +153,7 @@
         ns = NULL;
         if (xmlctx->prefix_len) {
             /* get namespace of the attribute */
-            ns = lyxml_ns_get(xmlctx, xmlctx->prefix, xmlctx->prefix_len);
+            ns = lyxml_ns_get(&xmlctx->ns, xmlctx->prefix, xmlctx->prefix_len);
             if (!ns) {
                 LOGVAL(xmlctx->ctx, LY_VLOG_LINE, &xmlctx->line, LYVE_REFERENCE, "Unknown XML prefix \"%.*s\".",
                        xmlctx->prefix_len, xmlctx->prefix);
@@ -257,7 +238,7 @@
         assert(xmlctx->status == LYXML_ELEM_CONTENT);
         if (i < key_set.count) {
             /* validate the value */
-            r = _lys_value_validate(NULL, snode, xmlctx->value, xmlctx->value_len, lydxml_resolve_prefix, xmlctx, LYD_XML);
+            r = _lys_value_validate(NULL, snode, xmlctx->value, xmlctx->value_len, LY_PREF_XML, xmlctx);
             if (!r) {
                 /* key with a valid value, remove from the set */
                 ly_set_rm_index(&key_set, i, NULL);
@@ -347,7 +328,7 @@
 
         if ((*snode)->nodetype & LYD_NODE_TERM) {
             /* value may not be valid in which case we parse it as an opaque node */
-            if (_lys_value_validate(NULL, *snode, xmlctx->value, xmlctx->value_len, lydxml_resolve_prefix, xmlctx, LYD_XML)) {
+            if (_lys_value_validate(NULL, *snode, xmlctx->value, xmlctx->value_len, LY_PREF_XML, &xmlctx->ns)) {
                 *snode = NULL;
             }
         } else {
@@ -416,7 +397,7 @@
     name_len = xmlctx->name_len;
 
     /* get the element module */
-    ns = lyxml_ns_get(xmlctx, prefix, prefix_len);
+    ns = lyxml_ns_get(&xmlctx->ns, prefix, prefix_len);
     if (!ns) {
         LOGVAL(ctx, LY_VLOG_LINE, &xmlctx->line, LYVE_REFERENCE, "Unknown XML prefix \"%.*s\".",
                prefix_len, prefix);
@@ -505,7 +486,7 @@
     } else if (snode->nodetype & LYD_NODE_TERM) {
         /* create node */
         LY_CHECK_GOTO(ret = lyd_parser_create_term((struct lyd_ctx*)lydctx, snode, xmlctx->value, xmlctx->value_len,
-                                        &xmlctx->dynamic, 0, lydxml_resolve_prefix, xmlctx, LYD_XML, &node), error);
+                                        &xmlctx->dynamic, 0, LY_PREF_XML, &xmlctx->ns, &node), error);
 
         if (parent && (node->schema->flags & LYS_KEY)) {
             /* check the key order, the anchor must never be a key */
@@ -651,7 +632,6 @@
     lydctx->parse_options = parse_options;
     lydctx->validate_options = validate_options;
     lydctx->free = lyd_xml_ctx_free;
-    lydctx->resolve_prefix = lydxml_resolve_prefix;
 
     /* parse XML data */
     while (lydctx->xmlctx->status == LYXML_ELEMENT) {
@@ -692,7 +672,7 @@
 
     prefix = xmlctx->prefix;
     prefix_len = xmlctx->prefix_len;
-    ns = lyxml_ns_get(xmlctx, prefix, prefix_len);
+    ns = lyxml_ns_get(&xmlctx->ns, prefix, prefix_len);
     if (!ns) {
         LOGVAL(xmlctx->ctx, LY_VLOG_LINE, &xmlctx->line, LYVE_REFERENCE, "Unknown XML prefix \"%.*s\".",
                prefix_len, prefix);
@@ -861,7 +841,7 @@
 
     prefix = xmlctx->prefix;
     prefix_len = xmlctx->prefix_len;
-    ns = lyxml_ns_get(xmlctx, prefix, prefix_len);
+    ns = lyxml_ns_get(&xmlctx->ns, prefix, prefix_len);
     if (!ns) {
         LOGVAL(xmlctx->ctx, LY_VLOG_LINE, &xmlctx->line, LYVE_REFERENCE, "Unknown XML prefix \"%.*s\".",
                prefix_len, prefix);
diff --git a/src/parser_yin.c b/src/parser_yin.c
index 6f75bda..5d461e6 100644
--- a/src/parser_yin.c
+++ b/src/parser_yin.c
@@ -69,7 +69,7 @@
         return LY_STMT_NONE;
     }
 
-    ns = lyxml_ns_get(ctx->xmlctx, prefix, prefix_len);
+    ns = lyxml_ns_get(&ctx->xmlctx->ns, prefix, prefix_len);
     if (ns) {
         if (!IS_YIN_NS(ns->uri)) {
             return LY_STMT_EXTENSION_INSTANCE;
@@ -2738,7 +2738,7 @@
 static const char *
 name2nsname(struct lys_yin_parser_ctx *ctx, const char *name, size_t name_len, const char *prefix, size_t prefix_len)
 {
-    const struct lyxml_ns *ns = lyxml_ns_get(ctx->xmlctx, prefix, prefix_len);
+    const struct lyxml_ns *ns = lyxml_ns_get(&ctx->xmlctx->ns, prefix, prefix_len);
     LY_CHECK_ERR_RET(!ns, LOGINT(ctx->xmlctx->ctx), NULL);
 
     if (!strcmp(ns->uri, YIN_NS_URI)) {
diff --git a/src/path.c b/src/path.c
index 36bb639..c2dad18 100644
--- a/src/path.c
+++ b/src/path.c
@@ -353,9 +353,8 @@
  * @param[in] expr Parsed path.
  * @param[in] tok_idx Index in @p expr.
  * @param[in] lref Lref option.
- * @param[in] resolve_prefix Callback for prefix resolution.
- * @param[in] prefix_data Data for @p resolve_prefix.
  * @param[in] format Format of the path.
+ * @param[in] prefix_data Format-specific data for resolving any prefixes (see ::ly_resolve_prefix).
  * @param[out] mod Resolved module.
  * @param[out] name Parsed node name.
  * @param[out] name_len Length of @p name.
@@ -364,8 +363,8 @@
 static LY_ERR
 ly_path_compile_prefix(const struct ly_ctx *ctx, const struct lysc_node *cur_node, const struct lys_module *cur_mod,
                        const struct lysc_node *prev_ctx_node, const struct lyxp_expr *expr, uint16_t tok_idx,
-                       uint8_t lref, ly_resolve_prefix_clb resolve_prefix, void *prefix_data, LYD_FORMAT format,
-                       const struct lys_module **mod, const char **name, size_t *name_len)
+                       uint8_t lref, LY_PREFIX_FORMAT format, void *prefix_data, const struct lys_module **mod,
+                       const char **name, size_t *name_len)
 {
     const char *ptr;
     size_t len;
@@ -378,7 +377,7 @@
 
     /* find next node module */
     if (ptr) {
-        *mod = resolve_prefix(ctx, expr->expr + expr->tok_pos[tok_idx], len, prefix_data);
+        *mod = ly_resolve_prefix(ctx, expr->expr + expr->tok_pos[tok_idx], len, format, prefix_data);
         if (!*mod) {
             LOGVAL_P(ctx, cur_node, LYVE_XPATH, "Prefix \"%.*s\" not found of a module in path.",
                      len, expr->expr + expr->tok_pos[tok_idx]);
@@ -392,17 +391,16 @@
         }
     } else {
         switch (format) {
-        case LYD_SCHEMA:
+        case LY_PREF_SCHEMA:
             *mod = cur_mod;
             break;
-        case LYD_JSON:
+        case LY_PREF_JSON:
             if (!prev_ctx_node) {
                 LOGINT_RET(ctx);
             }
             *mod = prev_ctx_node->module;
             break;
-        case LYD_XML:
-        case LYD_LYB:
+        case LY_PREF_XML:
             /* not really defined */
             LOGINT_RET(ctx);
         }
@@ -423,8 +421,8 @@
 LY_ERR
 ly_path_compile_predicate(const struct ly_ctx *ctx, const struct lysc_node *cur_node, const struct lys_module *cur_mod,
                           const struct lysc_node *ctx_node, const struct lyxp_expr *expr, uint16_t *tok_idx,
-                          ly_resolve_prefix_clb resolve_prefix, void *prefix_data, LYD_FORMAT format,
-                          struct ly_path_predicate **predicates, enum ly_path_pred_type *pred_type)
+                          LY_PREFIX_FORMAT format, void *prefix_data, struct ly_path_predicate **predicates,
+                          enum ly_path_pred_type *pred_type)
 {
     struct ly_path_predicate *p;
     const struct lysc_node *key;
@@ -456,7 +454,7 @@
         do {
             /* NameTest, find the key */
             LY_CHECK_RET(ly_path_compile_prefix(ctx, cur_node, cur_mod, ctx_node, expr, *tok_idx, LY_PATH_LREF_FALSE,
-                                                resolve_prefix, prefix_data, format, &mod, &name, &name_len));
+                                                format, prefix_data, &mod, &name, &name_len));
             key = lys_find_child(ctx_node, mod, name, name_len, 0, LYS_GETNEXT_NOSTATECHECK);
             if (!key) {
                 LOGVAL_P(ctx, cur_node, LYVE_XPATH, "Not found node \"%.*s\" in path.", name_len, name);
@@ -483,7 +481,7 @@
             /* Literal */
             assert(expr->tokens[*tok_idx] == LYXP_TOKEN_LITERAL);
             LY_CHECK_RET(lyd_value_store(&p->value, key, expr->expr + expr->tok_pos[*tok_idx] + 1,
-                                         expr->tok_len[*tok_idx] - 2, NULL, resolve_prefix, prefix_data, format));
+                                         expr->tok_len[*tok_idx] - 2, NULL, format, prefix_data));
             ++(*tok_idx);
 
             /* ']' */
@@ -526,7 +524,7 @@
         assert(expr->tokens[*tok_idx] == LYXP_TOKEN_LITERAL);
         /* store the value */
         LY_CHECK_RET(lyd_value_store(&p->value, ctx_node, expr->expr + expr->tok_pos[*tok_idx] + 1,
-                                     expr->tok_len[*tok_idx] - 2, NULL, resolve_prefix, prefix_data, format));
+                                     expr->tok_len[*tok_idx] - 2, NULL, format, prefix_data));
         ++(*tok_idx);
 
         /* ']' */
@@ -567,15 +565,13 @@
  * @param[in] cur_node Current (original context) node.
  * @param[in] expr Parsed path.
  * @param[in,out] tok_idx Index in @p expr, is adjusted for parsed tokens.
- * @param[in] resolve_prefix Callback for prefix resolution.
- * @param[in] prefix_data Data for @p resolve_prefix.
  * @param[in] format Format of the path.
+ * @param[in] prefix_data Format-specific data for resolving any prefixes (see ::ly_resolve_prefix).
  * @return LY_ERR value.
  */
 static LY_ERR
 ly_path_compile_predicate_leafref(const struct lysc_node *ctx_node, const struct lysc_node *cur_node,
-                                  const struct lyxp_expr *expr, uint16_t *tok_idx, ly_resolve_prefix_clb resolve_prefix,
-                                  void *prefix_data, LYD_FORMAT format)
+                                  const struct lyxp_expr *expr, uint16_t *tok_idx, LY_PREFIX_FORMAT format, void *prefix_data)
 {
     const struct lysc_node *key, *node, *node2;
     const struct lys_module *mod;
@@ -601,7 +597,7 @@
     do {
         /* NameTest, find the key */
         LY_CHECK_RET(ly_path_compile_prefix(cur_node->module->ctx, cur_node, cur_node->module, ctx_node, expr, *tok_idx,
-                                            LY_PATH_LREF_TRUE, resolve_prefix, prefix_data, format, &mod, &name, &name_len));
+                                            LY_PATH_LREF_TRUE, format, prefix_data, &mod, &name, &name_len));
         key = lys_find_child(ctx_node, mod, name, name_len, 0, LYS_GETNEXT_NOSTATECHECK);
         if (!key) {
             LOGVAL_P(cur_node->module->ctx, cur_node, LYVE_XPATH, "Not found node \"%.*s\" in path.", name_len, name);
@@ -660,7 +656,7 @@
             /* NameTest */
             assert(expr->tokens[*tok_idx] == LYXP_TOKEN_NAMETEST);
             LY_CHECK_RET(ly_path_compile_prefix(cur_node->module->ctx, cur_node, cur_node->module, node, expr, *tok_idx,
-                                                LY_PATH_LREF_TRUE, resolve_prefix, prefix_data, format, &mod, &name, &name_len));
+                                                LY_PATH_LREF_TRUE, format, prefix_data, &mod, &name, &name_len));
             node2 = lys_find_child(node, mod, name, name_len, 0, LYS_GETNEXT_NOSTATECHECK);
             if (!node2) {
                 LOGVAL_P(cur_node->module->ctx, cur_node, LYVE_XPATH, "Not found node \"%.*s\" in path.", name_len, name);
@@ -693,8 +689,8 @@
 
 LY_ERR
 ly_path_compile(const struct ly_ctx *ctx, const struct lys_module *cur_mod, const struct lysc_node *ctx_node,
-                const struct lyxp_expr *expr, uint8_t lref, uint8_t oper, uint8_t target,
-                ly_resolve_prefix_clb resolve_prefix, void *prefix_data, LYD_FORMAT format, struct ly_path **path)
+                const struct lyxp_expr *expr, uint8_t lref, uint8_t oper, uint8_t target, LY_PREFIX_FORMAT format,
+                void *prefix_data, struct ly_path **path)
 {
     LY_ERR ret = LY_SUCCESS;
     uint16_t tok_idx = 0;
@@ -760,8 +756,8 @@
         }
 
         /* get module and node name */
-        LY_CHECK_GOTO(ret = ly_path_compile_prefix(ctx, cur_node, cur_mod, ctx_node, expr, tok_idx, lref, resolve_prefix,
-                                                   prefix_data, format, &mod, &name, &name_len), cleanup);
+        LY_CHECK_GOTO(ret = ly_path_compile_prefix(ctx, cur_node, cur_mod, ctx_node, expr, tok_idx, lref, format,
+                                                   prefix_data, &mod, &name, &name_len), cleanup);
         ++tok_idx;
 
         /* find the next node */
@@ -779,10 +775,10 @@
 
         /* compile any predicates */
         if (lref == LY_PATH_LREF_TRUE) {
-            ret = ly_path_compile_predicate_leafref(ctx_node, cur_node, expr, &tok_idx, resolve_prefix, prefix_data, format);
+            ret = ly_path_compile_predicate_leafref(ctx_node, cur_node, expr, &tok_idx, format, prefix_data);
         } else {
-            ret = ly_path_compile_predicate(ctx, cur_node, cur_mod, ctx_node, expr, &tok_idx, resolve_prefix,
-                                            prefix_data, format, &p->predicates, &p->pred_type);
+            ret = ly_path_compile_predicate(ctx, cur_node, cur_mod, ctx_node, expr, &tok_idx, format, prefix_data,
+                                            &p->predicates, &p->pred_type);
         }
         LY_CHECK_GOTO(ret, cleanup);
     } while (!lyxp_next_token(NULL, expr, &tok_idx, LYXP_TOKEN_OPER_PATH));
diff --git a/src/path.h b/src/path.h
index 9faa0e1..11e2289 100644
--- a/src/path.h
+++ b/src/path.h
@@ -152,15 +152,14 @@
  * @param[in] lref Lref option (@ref path_lref_options).
  * @param[in] oper Oper option (@ref path_oper_options).
  * @param[in] target Target option (@ref path_target_options).
- * @param[in] resolve_prefix Callback for prefix resolution.
- * @param[in] prefix_data Data for @p resolve_prefix.
  * @param[in] format Format of the path.
+ * @param[in] prefix_data Format-specific data for resolving any prefixes (see ::ly_resolve_prefix).
  * @param[out] path Compiled path.
  * @return LY_ERR value.
  */
 LY_ERR ly_path_compile(const struct ly_ctx *ctx, const struct lys_module *cur_mod, const struct lysc_node *ctx_node,
                        const struct lyxp_expr *expr, uint8_t lref, uint8_t oper, uint8_t target,
-                       ly_resolve_prefix_clb resolve_prefix, void *prefix_data, LYD_FORMAT format, struct ly_path **path);
+                       LY_PREFIX_FORMAT format, void *prefix_data, struct ly_path **path);
 
 /**
  * @brief Compile predicate into ly_path_predicate structure. Only simple predicates (not leafref) are supported.
@@ -171,17 +170,16 @@
  * @param[in] ctx_node Context node, node for which the predicate is defined.
  * @param[in] expr Parsed path.
  * @param[in,out] tok_idx Index in @p expr, is adjusted for parsed tokens.
- * @param[in] resolve_prefix Callback for prefix resolution.
- * @param[in] prefix_data Data for @p resolve_prefix.
  * @param[in] format Format of the path.
+ * @param[in] prefix_data Format-specific data for resolving any prefixes (see ::ly_resolve_prefix).
  * @param[out] predicates Compiled predicates.
  * @param[out] pred_type Type of the compiled predicate(s).
  * @return LY_ERR value.
  */
 LY_ERR ly_path_compile_predicate(const struct ly_ctx *ctx, const struct lysc_node *cur_node, const struct lys_module *cur_mod,
                                  const struct lysc_node *ctx_node, const struct lyxp_expr *expr, uint16_t *tok_idx,
-                                 ly_resolve_prefix_clb resolve_prefix, void *prefix_data, LYD_FORMAT format,
-                                 struct ly_path_predicate **predicates, enum ly_path_pred_type *pred_type);
+                                 LY_PREFIX_FORMAT format, void *prefix_data, struct ly_path_predicate **predicates,
+                                 enum ly_path_pred_type *pred_type);
 
 /**
  * @brief Resolve at least partially the target defined by ly_path structure. Not supported for leafref!
diff --git a/src/plugins_types.c b/src/plugins_types.c
index e6e4e36..779a85e 100644
--- a/src/plugins_types.c
+++ b/src/plugins_types.c
@@ -36,6 +36,124 @@
 #include "xpath.h"
 
 /**
+ * @brief Find import prefix in imports.
+ */
+static const struct lys_module *
+ly_schema_resolve_prefix(const struct ly_ctx *UNUSED(ctx), const char *prefix, size_t prefix_len, void *data)
+{
+    return lys_module_find_prefix((const struct lys_module *)data, prefix, prefix_len);
+}
+
+/**
+ * @brief Find XML namespace prefix in XML namespaces, which are then mapped to modules.
+ */
+static const struct lys_module *
+ly_xml_resolve_prefix(const struct ly_ctx *ctx, const char *prefix, size_t prefix_len, void *data)
+{
+    const struct lyxml_ns *ns;
+    const struct ly_set *ns_set = data;
+
+    ns = lyxml_ns_get(ns_set, prefix, prefix_len);
+    if (!ns) {
+        return NULL;
+    }
+
+    return ly_ctx_get_module_implemented_ns(ctx, ns->uri);
+}
+
+/**
+ * @brief Find module name.
+ */
+static const struct lys_module *
+ly_json_resolve_prefix(const struct ly_ctx *ctx, const char *prefix, size_t prefix_len, void *UNUSED(parser))
+{
+    return ly_ctx_get_module_implemented2(ctx, prefix, prefix_len);
+}
+
+const struct lys_module *
+ly_resolve_prefix(const struct ly_ctx *ctx, const char *prefix, size_t prefix_len, LY_PREFIX_FORMAT format, void *prefix_data)
+{
+    const struct lys_module *mod;
+
+    switch (format) {
+    case LY_PREF_SCHEMA:
+        mod = ly_schema_resolve_prefix(ctx, prefix, prefix_len, prefix_data);
+        break;
+    case LY_PREF_XML:
+        mod = ly_xml_resolve_prefix(ctx, prefix, prefix_len, prefix_data);
+        break;
+    case LY_PREF_JSON:
+        mod = ly_json_resolve_prefix(ctx, prefix, prefix_len, prefix_data);
+        break;
+    }
+
+    return mod;
+}
+
+/**
+ * @brief Find module in import prefixes.
+ */
+static const char *
+ly_schema_get_prefix(const struct lys_module *mod, void *data)
+{
+    const struct lys_module *context_mod = data;
+    LY_ARRAY_COUNT_TYPE u;
+
+    if (context_mod == mod) {
+        return context_mod->prefix;
+    }
+    LY_ARRAY_FOR(context_mod->parsed->imports, u) {
+        if (context_mod->parsed->imports[u].module == mod) {
+            /* match */
+            return context_mod->parsed->imports[u].prefix;
+        }
+    }
+
+    return NULL;
+}
+
+/**
+ * @brief Simply return module local prefix. Also, store the module in a set.
+ */
+static const char *
+ly_xml_get_prefix(const struct lys_module *mod, void *data)
+{
+    struct ly_set *ns_list = data;
+
+    ly_set_add(ns_list, (void *)mod, 0);
+    return mod->prefix;
+}
+
+/**
+ * @brief Simply return module name.
+ */
+static const char *
+ly_json_get_prefix(const struct lys_module *mod, void *UNUSED(data))
+{
+    return mod->name;
+}
+
+const char *
+ly_get_prefix(const struct lys_module *mod, LY_PREFIX_FORMAT format, void *prefix_data)
+{
+    const char *prefix = NULL;
+
+    switch (format) {
+    case LY_PREF_SCHEMA:
+        prefix = ly_schema_get_prefix(mod, prefix_data);
+        break;
+    case LY_PREF_XML:
+        prefix = ly_xml_get_prefix(mod, prefix_data);
+        break;
+    case LY_PREF_JSON:
+        prefix = ly_json_get_prefix(mod, prefix_data);
+        break;
+    }
+
+    return prefix;
+}
+
+/**
  * @brief Generic comparison callback checking the canonical value.
  *
  * Implementation of the ly_type_compare_clb.
@@ -56,11 +174,11 @@
  * Implementation of the ly_type_print_clb.
  */
 static const char *
-ly_type_print_canonical(const struct lyd_value *value, LYD_FORMAT UNUSED(format),
-                        ly_get_prefix_clb UNUSED(get_prefix), void *UNUSED(printer), int *dynamic)
+ly_type_print_canonical(const struct lyd_value *value, LY_PREFIX_FORMAT UNUSED(format),
+                        void *UNUSED(prefix_data), int *dynamic)
 {
     *dynamic = 0;
-    return (char*)value->canonical_cache;
+    return (char *)value->canonical_cache;
 }
 
 /**
@@ -160,62 +278,6 @@
     }
 }
 
-API struct lyd_value_prefix *
-ly_type_get_prefixes(const struct ly_ctx *ctx, const char *value, size_t value_len, ly_resolve_prefix_clb resolve_prefix,
-                     void *parser)
-{
-    LY_ERR ret;
-    unsigned int c;
-    const char *start, *stop;
-    struct lyd_value_prefix *prefixes = NULL;
-    const struct lys_module *mod;
-    LY_ARRAY_COUNT_TYPE u;
-
-    for (stop = start = value; (size_t)(stop - value) < value_len; start = stop) {
-        size_t bytes;
-        ly_getutf8(&stop, &c, &bytes);
-        if (is_xmlqnamestartchar(c)) {
-            for (ly_getutf8(&stop, &c, &bytes);
-                    is_xmlqnamechar(c) && (size_t)(stop - value) < value_len;
-                    ly_getutf8(&stop, &c, &bytes));
-            stop = stop - bytes;
-            if (*stop == ':') {
-                /* we have a possible prefix */
-                struct lyd_value_prefix *p;
-                size_t len = stop - start;
-                mod = NULL;
-
-                LY_ARRAY_FOR(prefixes, u) {
-                    if (!ly_strncmp(prefixes[u].prefix, start, len)) {
-                        mod = prefixes[u].mod;
-                        break;
-                    }
-                }
-                if (!mod) {
-                    mod = resolve_prefix(ctx, start, len, parser);
-                    if (mod) {
-                        LY_ARRAY_NEW_GOTO(ctx, prefixes, p, ret, error);
-                        p->mod = mod;
-                        p->prefix = lydict_insert(ctx, start, len);
-                    }
-                } /* else the prefix already present */
-            }
-            stop = stop + bytes;
-        }
-    }
-
-    return prefixes;
-
-error:
-    LY_ARRAY_FOR(prefixes, u) {
-        lydict_remove(ctx, prefixes[u].prefix);
-    }
-    LY_ARRAY_FREE(prefixes);
-
-    (void)ret;
-    return NULL;
-}
-
 API LY_ERR
 ly_type_parse_uint(const char *datatype, int base, uint64_t max, const char *value, size_t value_len, uint64_t *ret,
                    struct ly_err_item **err)
@@ -524,9 +586,9 @@
  */
 static LY_ERR
 ly_type_store_int(const struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, int options,
-                  ly_resolve_prefix_clb UNUSED(resolve_prefix), void *UNUSED(parser), LYD_FORMAT UNUSED(format),
-                  const void *UNUSED(context_node), const struct lyd_node *UNUSED(tree),
-                  struct lyd_value *storage, const char **canonized, struct ly_err_item **err)
+                  LY_PREFIX_FORMAT UNUSED(format), void *UNUSED(prefix_data), const void *UNUSED(context_node),
+                  const struct lyd_node *UNUSED(tree), struct lyd_value *storage, const char **canonized,
+                  struct ly_err_item **err)
 {
     LY_ERR ret;
     int64_t i;
@@ -599,9 +661,9 @@
  */
 static LY_ERR
 ly_type_store_uint(const struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, int options,
-                   ly_resolve_prefix_clb UNUSED(resolve_prefix), void *UNUSED(parser), LYD_FORMAT UNUSED(format),
-                   const void *UNUSED(context_node), const struct lyd_node *UNUSED(tree),
-                   struct lyd_value *storage, const char **canonized, struct ly_err_item **err)
+                   LY_PREFIX_FORMAT UNUSED(format), void *UNUSED(prefix_data), const void *UNUSED(context_node),
+                   const struct lyd_node *UNUSED(tree), struct lyd_value *storage, const char **canonized,
+                   struct ly_err_item **err)
 {
     LY_ERR ret;
     uint64_t u;
@@ -673,9 +735,9 @@
  */
 static LY_ERR
 ly_type_store_decimal64(const struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, int options,
-                        ly_resolve_prefix_clb UNUSED(resolve_prefix), void *UNUSED(parser), LYD_FORMAT UNUSED(format),
-                        const void *UNUSED(context_node), const struct lyd_node *UNUSED(tree),
-                        struct lyd_value *storage, const char **canonized, struct ly_err_item **err)
+                        LY_PREFIX_FORMAT UNUSED(format), void *UNUSED(prefix_data), const void *UNUSED(context_node),
+                        const struct lyd_node *UNUSED(tree), struct lyd_value *storage, const char **canonized,
+                        struct ly_err_item **err)
 {
     int64_t d;
     struct lysc_type_dec* type_dec = (struct lysc_type_dec*)type;
@@ -757,9 +819,9 @@
  */
 static LY_ERR
 ly_type_store_binary(const struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, int options,
-                     ly_resolve_prefix_clb UNUSED(resolve_prefix), void *UNUSED(parser), LYD_FORMAT UNUSED(format),
-                     const void *UNUSED(context_node), const struct lyd_node *UNUSED(tree),
-                     struct lyd_value *storage, const char **canonized, struct ly_err_item **err)
+                     LY_PREFIX_FORMAT UNUSED(format), void *UNUSED(prefix_data), const void *UNUSED(context_node),
+                     const struct lyd_node *UNUSED(tree), struct lyd_value *storage, const char **canonized,
+                     struct ly_err_item **err)
 {
     size_t start = 0, stop = 0, count = 0, u, termination = 0;
     struct lysc_type_bin *type_bin = (struct lysc_type_bin *)type;
@@ -867,9 +929,9 @@
  */
 static LY_ERR
 ly_type_store_string(const struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, int options,
-                     ly_resolve_prefix_clb UNUSED(resolve_prefix), void *UNUSED(parser), LYD_FORMAT UNUSED(format),
-                     const void *UNUSED(context_node), const struct lyd_node *UNUSED(tree),
-                     struct lyd_value *storage, const char **canonized, struct ly_err_item **err)
+                     LY_PREFIX_FORMAT UNUSED(format), void *UNUSED(prefix_data), const void *UNUSED(context_node),
+                     const struct lyd_node *UNUSED(tree), struct lyd_value *storage, const char **canonized,
+                     struct ly_err_item **err)
 {
     struct lysc_type_str *type_str = (struct lysc_type_str *)type;
 
@@ -911,9 +973,9 @@
  */
 static LY_ERR
 ly_type_store_bits(const struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, int options,
-                   ly_resolve_prefix_clb UNUSED(resolve_prefix), void *UNUSED(parser), LYD_FORMAT UNUSED(format),
-                   const void *UNUSED(context_node), const struct lyd_node *UNUSED(tree),
-                   struct lyd_value *storage, const char **canonized, struct ly_err_item **err)
+                   LY_PREFIX_FORMAT UNUSED(format), void *UNUSED(prefix_data), const void *UNUSED(context_node),
+                   const struct lyd_node *UNUSED(tree), struct lyd_value *storage, const char **canonized,
+                   struct ly_err_item **err)
 {
     LY_ERR ret = LY_EVALID;
     size_t item_len;
@@ -1100,9 +1162,9 @@
  */
 static LY_ERR
 ly_type_store_enum(const struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, int options,
-                   ly_resolve_prefix_clb UNUSED(resolve_prefix), void *UNUSED(parser), LYD_FORMAT UNUSED(format),
-                   const void *UNUSED(context_node), const struct lyd_node *UNUSED(tree),
-                   struct lyd_value *storage, const char **canonized, struct ly_err_item **err)
+                   LY_PREFIX_FORMAT UNUSED(format), void *UNUSED(prefix_data), const void *UNUSED(context_node),
+                   const struct lyd_node *UNUSED(tree), struct lyd_value *storage, const char **canonized,
+                   struct ly_err_item **err)
 {
     LY_ARRAY_COUNT_TYPE u, v;
     char *errmsg = NULL;
@@ -1179,8 +1241,8 @@
  * Implementation of the ly_type_store_clb.
  */
 static LY_ERR
-ly_type_store_boolean(const struct ly_ctx *ctx, struct lysc_type *UNUSED(type), const char *value, size_t value_len, int options,
-                      ly_resolve_prefix_clb UNUSED(resolve_prefix), void *UNUSED(parser), LYD_FORMAT UNUSED(format),
+ly_type_store_boolean(const struct ly_ctx *ctx, struct lysc_type *UNUSED(type), const char *value, size_t value_len,
+                      int options, LY_PREFIX_FORMAT UNUSED(format), void *UNUSED(prefix_data),
                       const void *UNUSED(context_node), const struct lyd_node *UNUSED(tree),
                       struct lyd_value *storage, const char **canonized, struct ly_err_item **err)
 {
@@ -1240,7 +1302,7 @@
  */
 static LY_ERR
 ly_type_store_empty(const struct ly_ctx *ctx, struct lysc_type *UNUSED(type), const char *value, size_t value_len, int options,
-                    ly_resolve_prefix_clb UNUSED(resolve_prefix), void *UNUSED(parser), LYD_FORMAT UNUSED(format),
+                    LY_PREFIX_FORMAT UNUSED(format), void *UNUSED(prefix_data),
                     const void *UNUSED(context_node), const struct lyd_node *UNUSED(tree),
                     struct lyd_value *storage, const char **canonized, struct ly_err_item **err)
 {
@@ -1305,9 +1367,9 @@
  */
 static LY_ERR
 ly_type_store_identityref(const struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, int options,
-                          ly_resolve_prefix_clb resolve_prefix, void *parser, LYD_FORMAT UNUSED(format),
-                          const void *UNUSED(context_node), const struct lyd_node *UNUSED(tree),
-                          struct lyd_value *storage, const char **canonized, struct ly_err_item **err)
+                          LY_PREFIX_FORMAT format, void *prefix_data, const void *UNUSED(context_node),
+                          const struct lyd_node *UNUSED(tree),struct lyd_value *storage, const char **canonized,
+                          struct ly_err_item **err)
 {
     struct lysc_type_identityref *type_ident = (struct lysc_type_identityref *)type;
     const char *id_name, *prefix = value;
@@ -1338,7 +1400,7 @@
         goto error;
     }
 
-    mod = resolve_prefix(ctx, prefix, prefix_len, parser);
+    mod = ly_resolve_prefix(ctx, prefix, prefix_len, format, prefix_data);
     if (!mod) {
         erc = asprintf(&errmsg, "Invalid identityref \"%.*s\" value - unable to map prefix to YANG schema.", (int)value_len, value);
         goto error;
@@ -1426,12 +1488,12 @@
  * Implementation of the ly_type_print_clb.
  */
 static const char *
-ly_type_print_identityref(const struct lyd_value *value, LYD_FORMAT UNUSED(format), ly_get_prefix_clb get_prefix, void *printer, int *dynamic)
+ly_type_print_identityref(const struct lyd_value *value, LY_PREFIX_FORMAT format, void *prefix_data, int *dynamic)
 {
     char *result = NULL;
 
     *dynamic = 1;
-    if (asprintf(&result, "%s:%s", get_prefix(value->ident->module, printer), value->ident->name) == -1) {
+    if (asprintf(&result, "%s:%s", ly_get_prefix(value->ident->module, format, prefix_data), value->ident->name) == -1) {
         return NULL;
     } else {
         return result;
@@ -1450,41 +1512,18 @@
 }
 
 /**
- * @brief Helper function for ly_type_store_instanceid_parse_predicate_value() to provide prefix mapping for the
- * validation callbacks for the values used in instance-identifier predicates.
- *
- * Implementation of the ly_resolve_prefix_clb.
- */
-static const struct lys_module *
-ly_type_stored_prefixes_clb(const struct ly_ctx *UNUSED(ctx), const char *prefix, size_t prefix_len, void *private)
-{
-    struct lyd_value_prefix *prefixes = (struct lyd_value_prefix*)private;
-    LY_ARRAY_COUNT_TYPE u;
-
-    LY_ARRAY_FOR(prefixes, u) {
-        if (!ly_strncmp(prefixes[u].prefix, prefix, prefix_len)) {
-            return prefixes[u].mod;
-        }
-    }
-    return NULL;
-}
-
-/**
  * @brief Validate and store value of the YANG built-in instance-identifier type.
  *
  * Implementation of the ly_type_store_clb.
  */
 static LY_ERR
 ly_type_store_instanceid(const struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, int options,
-                         ly_resolve_prefix_clb resolve_prefix, void *parser, LYD_FORMAT format,
-                         const void *context_node, const struct lyd_node *tree, struct lyd_value *storage,
-                         const char **canonized, struct ly_err_item **err)
+                         LY_PREFIX_FORMAT format, void *prefix_data, const void *context_node, const struct lyd_node *tree,
+                         struct lyd_value *storage, const char **canonized, struct ly_err_item **err)
 {
     LY_ERR ret = LY_EVALID;
     struct lysc_type_instanceid *type_inst = (struct lysc_type_instanceid *)type;
     char *errmsg = NULL;
-    struct lyd_value_prefix *prefixes = NULL;
-    LY_ARRAY_COUNT_TYPE u;
     struct ly_path *path = NULL;
     struct ly_set predicates = {0};
     struct lyxp_expr *exp = NULL;
@@ -1506,12 +1545,11 @@
     }
 
     switch (format) {
-    case LYD_SCHEMA:
-    case LYD_XML:
+    case LY_PREF_SCHEMA:
+    case LY_PREF_XML:
         prefix_opt = LY_PATH_PREFIX_MANDATORY;
         break;
-    case LYD_JSON:
-    case LYD_LYB:
+    case LY_PREF_JSON:
         prefix_opt = LY_PATH_PREFIX_STRICT_INHERIT;
         break;
     }
@@ -1522,7 +1560,7 @@
             /* in error message we print the JSON format of the instance-identifier - in case of XML, it is not possible
              * to get the exactly same string as original, JSON is less demanding and still well readable/understandable. */
             int dynamic = 0;
-            const char *id = storage->realtype->plugin->print(storage, LYD_JSON, json_print_get_prefix, NULL, &dynamic);
+            const char *id = storage->realtype->plugin->print(storage, LY_PREF_JSON, NULL, &dynamic);
             erc = asprintf(&errmsg, "Invalid instance-identifier \"%s\" value - required instance not found.", id);
             if (dynamic) {
                 free((char*)id);
@@ -1535,9 +1573,6 @@
         return LY_SUCCESS;
     }
 
-    /* get all used prefixes */
-    prefixes = ly_type_get_prefixes(ctx, value, value_len, resolve_prefix, parser);
-
     /* parse the value */
     ret = ly_path_parse(ctx, ctx_scnode, value, value_len, LY_PATH_BEGIN_ABSOLUTE, LY_PATH_LREF_FALSE,
                         prefix_opt, LY_PATH_PRED_SIMPLE, &exp);
@@ -1548,8 +1583,7 @@
 
     /* resolve it on schema tree */
     ret = ly_path_compile(ctx, ctx_scnode->module, NULL, exp, LY_PATH_LREF_FALSE, lysc_is_output(ctx_scnode) ?
-                          LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT, LY_PATH_TARGET_SINGLE, ly_type_stored_prefixes_clb,
-                          prefixes, format, &path);
+                          LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT, LY_PATH_TARGET_SINGLE, format, prefix_data, &path);
     if (ret) {
         erc = asprintf(&errmsg, "Invalid instance-identifier \"%.*s\" value - semantic error.", (int)value_len, value);
         goto error;
@@ -1575,10 +1609,6 @@
     }
 
 cleanup:
-    LY_ARRAY_FOR(prefixes, u) {
-        lydict_remove(ctx, prefixes[u].prefix);
-    }
-    LY_ARRAY_FREE(prefixes);
     ly_set_erase(&predicates, NULL);
     lyxp_expr_free(ctx, exp);
     ly_path_free(ctx, path);
@@ -1600,10 +1630,6 @@
     }
 
 error:
-    LY_ARRAY_FOR(prefixes, u) {
-        lydict_remove(ctx, prefixes[u].prefix);
-    }
-    LY_ARRAY_FREE(prefixes);
     ly_set_erase(&predicates, NULL);
     lyxp_expr_free(ctx, exp);
     ly_path_free(ctx, path);
@@ -1682,8 +1708,7 @@
  * Implementation of the ly_type_print_clb.
  */
 static const char *
-ly_type_print_instanceid(const struct lyd_value *value, LYD_FORMAT format, ly_get_prefix_clb get_prefix, void *printer,
-                         int *dynamic)
+ly_type_print_instanceid(const struct lyd_value *value, LY_PREFIX_FORMAT format, void *prefix_data, int *dynamic)
 {
     LY_ARRAY_COUNT_TYPE u, v;
     char *result = NULL;
@@ -1694,10 +1719,11 @@
         return strdup(value->canonical_cache);
     }
 
-    if (format == LYD_XML) {
+    if ((format == LY_PREF_XML) || (format == LY_PREF_SCHEMA)) {
         /* everything is prefixed */
         LY_ARRAY_FOR(value->target, u) {
-            ly_strcat(&result, "/%s:%s", get_prefix(value->target[u].node->module, printer), value->target[u].node->name);
+            ly_strcat(&result, "/%s:%s", ly_get_prefix(value->target[u].node->module, format, prefix_data),
+                      value->target[u].node->name);
             LY_ARRAY_FOR(value->target[u].predicates, v) {
                 struct ly_path_predicate *pred = &value->target[u].predicates[v];
                 switch (value->target[u].pred_type) {
@@ -1711,12 +1737,13 @@
                 {
                     /* key-predicate */
                     int d = 0;
-                    const char *value = pred->value.realtype->plugin->print(&pred->value, format, get_prefix, printer, &d);
+                    const char *value = pred->value.realtype->plugin->print(&pred->value, format, prefix_data, &d);
                     char quot = '\'';
                     if (strchr(value, quot)) {
                         quot = '"';
                     }
-                    ly_strcat(&result, "[%s:%s=%c%s%c]", get_prefix(pred->key->module, printer), pred->key->name, quot, value, quot);
+                    ly_strcat(&result, "[%s:%s=%c%s%c]", ly_get_prefix(pred->key->module, format, prefix_data),
+                              pred->key->name, quot, value, quot);
                     if (d) {
                         free((char*)value);
                     }
@@ -1726,7 +1753,7 @@
                 {
                     /* leaf-list-predicate */
                     int d = 0;
-                    const char *value = pred->value.realtype->plugin->print(&pred->value, format, get_prefix, printer, &d);
+                    const char *value = pred->value.realtype->plugin->print(&pred->value, format, prefix_data, &d);
                     char quot = '\'';
                     if (strchr(value, quot)) {
                         quot = '"';
@@ -1740,13 +1767,13 @@
                 }
             }
         }
-    } else if (format == LYD_JSON) {
+    } else if (format == LY_PREF_JSON) {
         /* only the first node or the node changing module is prefixed */
         struct lys_module *mod = NULL;
         LY_ARRAY_FOR(value->target, u) {
             if (mod != value->target[u].node->module) {
                 mod = value->target[u].node->module;
-                ly_strcat(&result, "/%s:%s", get_prefix(mod, printer), value->target[u].node->name);
+                ly_strcat(&result, "/%s:%s", ly_get_prefix(mod, format, prefix_data), value->target[u].node->name);
             } else {
                 ly_strcat(&result, "/%s", value->target[u].node->name);
             }
@@ -1763,7 +1790,7 @@
                 {
                     /* key-predicate */
                     int d = 0;
-                    const char *value = pred->value.realtype->plugin->print(&pred->value, format, get_prefix, printer, &d);
+                    const char *value = pred->value.realtype->plugin->print(&pred->value, format, prefix_data, &d);
                     char quot = '\'';
                     if (strchr(value, quot)) {
                         quot = '"';
@@ -1778,7 +1805,7 @@
                 {
                     /* leaf-list-predicate */
                     int d = 0;
-                    const char *value = pred->value.realtype->plugin->print(&pred->value, format, get_prefix, printer, &d);
+                    const char *value = pred->value.realtype->plugin->print(&pred->value, format, prefix_data, &d);
                     char quot = '\'';
                     if (strchr(value, quot)) {
                         quot = '"';
@@ -1837,10 +1864,10 @@
     uint32_t i;
 
     /* find all target data instances */
-    ret = lyxp_eval(lref->path, LYD_SCHEMA, lref->path_context, node, LYXP_NODE_ELEM, tree, &set, 0);
+    ret = lyxp_eval(lref->path, LY_PREF_SCHEMA, lref->path_context, node, LYXP_NODE_ELEM, tree, &set, 0);
     if (ret) {
         ret = LY_ENOTFOUND;
-        val_str = lref->plugin->print(value, LYD_JSON, json_print_get_prefix, NULL, &dynamic);
+        val_str = lref->plugin->print(value, LY_PREF_JSON, NULL, &dynamic);
         if (asprintf(errmsg, "Invalid leafref value \"%s\" - XPath evaluation error.", val_str) == -1) {
             *errmsg = NULL;
             ret = LY_EMEM;
@@ -1863,7 +1890,7 @@
     }
     if (i == set.used) {
         ret = LY_ENOTFOUND;
-        val_str = lref->plugin->print(value, LYD_JSON, json_print_get_prefix, NULL, &dynamic);
+        val_str = lref->plugin->print(value, LY_PREF_JSON, NULL, &dynamic);
         if (asprintf(errmsg, "Invalid leafref value \"%s\" - no target instance \"%s\" with the same value.", val_str,
                      lref->path->expr) == -1) {
             *errmsg = NULL;
@@ -1894,13 +1921,12 @@
  */
 static LY_ERR
 ly_type_store_leafref(const struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, int options,
-                      ly_resolve_prefix_clb resolve_prefix, void *parser, LYD_FORMAT format,
-                      const void *context_node, const struct lyd_node *tree,
+                      LY_PREFIX_FORMAT format, void *prefix_data, const void *context_node, const struct lyd_node *tree,
                       struct lyd_value *storage, const char **canonized, struct ly_err_item **err)
 {
     LY_ERR ret = LY_SUCCESS;
     char *errmsg = NULL;
-    struct lysc_type_leafref *type_lr = (struct lysc_type_leafref*)type;
+    struct lysc_type_leafref *type_lr = (struct lysc_type_leafref *)type;
     int storage_dummy = 0;
     const char *orig = NULL;
     struct ly_path *p = NULL;
@@ -1952,9 +1978,8 @@
     }
 
     /* check value according to the real type of the leafref target */
-    ret = type_lr->realtype->plugin->store(ctx, type_lr->realtype, value, value_len, options,
-                                           resolve_prefix, parser, format, context_node, tree,
-                                           storage, canonized, err);
+    ret = type_lr->realtype->plugin->store(ctx, type_lr->realtype, value, value_len, options, format, prefix_data,
+                                           context_node, tree, storage, canonized, err);
     if (ret != LY_SUCCESS && ret != LY_EINCOMPLETE) {
         goto cleanup;
     }
@@ -2002,9 +2027,9 @@
  * Implementation of the ly_type_print_clb.
  */
 static const char *
-ly_type_print_leafref(const struct lyd_value *value, LYD_FORMAT format, ly_get_prefix_clb get_prefix, void *printer, int *dynamic)
+ly_type_print_leafref(const struct lyd_value *value, LY_PREFIX_FORMAT format, void *prefix_data, int *dynamic)
 {
-    return value->realtype->plugin->print(value, format, get_prefix, printer, dynamic);
+    return value->realtype->plugin->print(value, format, prefix_data, dynamic);
 }
 
 /* @brief Duplication callback of the leafref values.
@@ -2038,9 +2063,9 @@
  * @brief Answer if the type is suitable for the parser's hit (if any) in the specified format
  */
 LY_ERR
-type_check_parser_hint(LYD_FORMAT format, int hint, LY_DATA_TYPE type)
+type_check_parser_hint(LY_PREFIX_FORMAT format, int hint, LY_DATA_TYPE type)
 {
-    if (format == LYD_JSON && hint) {
+    if (format == LY_PREF_JSON && hint) {
         switch (type) {
         case LY_TYPE_UINT8:
         case LY_TYPE_UINT16:
@@ -2084,19 +2109,186 @@
 }
 
 /**
+ * @brief Free stored prefix data of a union.
+ *
+ * @param[in] format Format of the prefixes.
+ * @param[in] prefix_data Prefix data to free.
+ */
+static void
+ly_type_union_free_prefix_data(LY_PREFIX_FORMAT format, void *prefix_data)
+{
+    struct ly_set *ns_list;
+    uint32_t i;
+
+    switch (format) {
+    case LY_PREF_XML:
+        ns_list = prefix_data;
+        for (i = 0; i < ns_list->count; ++i) {
+            free(((struct lyxml_ns *)ns_list->objs[i])->prefix);
+            free(((struct lyxml_ns *)ns_list->objs[i])->uri);
+        }
+        ly_set_free(ns_list, free);
+        break;
+    case LY_PREF_SCHEMA:
+    case LY_PREF_JSON:
+        break;
+    }
+}
+
+/**
+ * @brief Store prefix data of a union.
+ *
+ * @param[in] ctx libyang context.
+ * @param[in] value Value string to be parsed.
+ * @param[in] value_len Length of the @p value string.
+ * @param[in] format Format of the prefixes in the value.
+ * @param[in] prefix_data Parser's data for get prefix.
+ * @return Created format-specific prefix data for prefix resolution callback.
+ */
+static void *
+ly_type_union_store_prefix_data(const struct ly_ctx *ctx, const char *value, size_t value_len, LY_PREFIX_FORMAT format,
+                                void *prefix_data)
+{
+    unsigned int c;
+    const char *start, *stop;
+    const struct lys_module *mod;
+    struct lyxml_ns *ns;
+    struct ly_set *ns_list;
+
+    switch (format) {
+    case LY_PREF_SCHEMA:
+        /* just remember the local module */
+        return prefix_data;
+    case LY_PREF_XML:
+        /* copy only referenced namespaces from the ns_set */
+        break;
+    case LY_PREF_JSON:
+        /* there should be no prefix data */
+        assert(!prefix_data);
+        return NULL;
+    }
+
+    /* XML only */
+    ns_list = ly_set_new();
+    LY_CHECK_ERR_RET(!ns_list, LOGMEM(ctx), NULL);
+
+    /* add all used prefixes */
+    for (stop = start = value; (size_t)(stop - value) < value_len; start = stop) {
+        size_t bytes;
+        ly_getutf8(&stop, &c, &bytes);
+        if (is_xmlqnamestartchar(c)) {
+            for (ly_getutf8(&stop, &c, &bytes);
+                    is_xmlqnamechar(c) && (size_t)(stop - value) < value_len;
+                    ly_getutf8(&stop, &c, &bytes));
+            stop = stop - bytes;
+            if (*stop == ':') {
+                /* we have a possible prefix */
+                size_t len = stop - start;
+
+                /* do we already have the prefix? */
+                mod = ly_resolve_prefix(ctx, start, len, format, ns_list);
+                if (!mod) {
+                    /* is it even defined? */
+                    mod = ly_resolve_prefix(ctx, start, len, format, prefix_data);
+                    if (mod) {
+                        /* store a new prefix - namespace pair */
+                        ns = calloc(1, sizeof *ns);
+                        LY_CHECK_ERR_GOTO(!ns, LOGMEM(ctx), error);
+                        ly_set_add(ns_list, ns, LY_SET_OPT_USEASLIST);
+
+                        ns->prefix = strndup(start, len);
+                        LY_CHECK_ERR_GOTO(!ns->prefix, LOGMEM(ctx), error);
+                        ns->uri = strdup(mod->ns);
+                        LY_CHECK_ERR_GOTO(!ns->uri, LOGMEM(ctx), error);
+                    }
+                } /* else the prefix already present */
+            }
+            stop = stop + bytes;
+        }
+    }
+
+    /* add default namespace */
+    mod = ly_resolve_prefix(ctx, NULL, 0, format, prefix_data);
+    if (mod) {
+        ns = calloc(1, sizeof *ns);
+        LY_CHECK_ERR_GOTO(!ns, LOGMEM(ctx), error);
+        ly_set_add(ns_list, ns, LY_SET_OPT_USEASLIST);
+
+        ns->uri = strdup(mod->ns);
+        LY_CHECK_ERR_GOTO(!ns->uri, LOGMEM(ctx), error);
+    }
+
+    return ns_list;
+
+error:
+    ly_type_union_free_prefix_data(LY_PREF_XML, ns_list);
+    return NULL;
+}
+
+/**
+ * @brief Duplicate prefix data of a union.
+ *
+ * @param[in] ctx libyang context.
+ * @param[in] format Format of the prefixes in the value.
+ * @param[in] prefix_data Prefix data to duplicate.
+ * @return Duplicated prefix data.
+ */
+static void *
+ly_type_union_dup_prefix_data(const struct ly_ctx *ctx, LY_PREFIX_FORMAT format, const void *prefix_data)
+{
+    struct lyxml_ns *ns;
+    struct ly_set *ns_list, *orig;
+    uint32_t i;
+
+    switch (format) {
+    case LY_PREF_SCHEMA:
+        return (void *)prefix_data;
+    case LY_PREF_XML:
+        break;
+    case LY_PREF_JSON:
+        assert(!prefix_data);
+        return NULL;
+    }
+
+    /* XML only */
+    ns_list = ly_set_new();
+    LY_CHECK_ERR_RET(!ns_list, LOGMEM(ctx), NULL);
+
+    /* copy all the namespaces */
+    orig = (struct ly_set *)prefix_data;
+    for (i = 0; i < orig->count; ++i) {
+        ns = calloc(1, sizeof *ns);
+        LY_CHECK_ERR_GOTO(!ns, LOGMEM(ctx), error);
+        ly_set_add(ns_list, ns, LY_SET_OPT_USEASLIST);
+
+        if (((struct lyxml_ns *)orig->objs[i])->prefix) {
+            ns->prefix = strdup(((struct lyxml_ns *)orig->objs[i])->prefix);
+            LY_CHECK_ERR_GOTO(!ns->prefix, LOGMEM(ctx), error);
+        }
+        ns->uri = strdup(((struct lyxml_ns *)orig->objs[i])->uri);
+        LY_CHECK_ERR_GOTO(!ns->uri, LOGMEM(ctx), error);
+    }
+
+    return ns_list;
+
+error:
+    ly_type_union_free_prefix_data(LY_PREF_XML, ns_list);
+    return NULL;
+}
+
+/**
  * @brief Validate, canonize and store value of the YANG built-in union type.
  *
  * Implementation of the ly_type_store_clb.
  */
 static LY_ERR
 ly_type_store_union(const struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, int options,
-                    ly_resolve_prefix_clb resolve_prefix, void *parser, LYD_FORMAT format,
-                    const void *context_node, const struct lyd_node *tree,
+                    LY_PREFIX_FORMAT format, void *prefix_data, const void *context_node, const struct lyd_node *tree,
                     struct lyd_value *storage, const char **canonized, struct ly_err_item **err)
 {
     LY_ERR ret = LY_SUCCESS;
     LY_ARRAY_COUNT_TYPE u;
-    struct lysc_type_union *type_u = (struct lysc_type_union*)type;
+    struct lysc_type_union *type_u = (struct lysc_type_union *)type;
     struct lyd_value_subvalue *subvalue;
     char *errmsg = NULL;
     int prev_lo;
@@ -2107,8 +2299,8 @@
         /* call the callback second time */
         ret = subvalue->value->realtype->plugin->store(ctx, subvalue->value->realtype, value, value_len,
                                                        options & ~(LY_TYPE_OPTS_CANONIZE | LY_TYPE_OPTS_DYNAMIC),
-                                                       ly_type_stored_prefixes_clb, subvalue->prefixes, format,
-                                                       context_node, tree, subvalue->value, canonized, err);
+                                                       subvalue->format, subvalue->prefix_data, context_node, tree,
+                                                       subvalue->value, canonized, err);
         if (ret) {
             /* second call failed, we have to try another subtype of the union.
              * Unfortunately, since the realtype can change (e.g. in leafref), we are not able to detect
@@ -2128,8 +2320,9 @@
         subvalue = calloc(1, sizeof *subvalue);
         subvalue->value = calloc(1, sizeof *subvalue->value);
 
-        /* store prefixes for later use */
-        subvalue->prefixes = ly_type_get_prefixes(ctx, value, value_len, resolve_prefix, parser);
+        /* store format-specific data for later prefix resolution */
+        subvalue->format = format;
+        subvalue->prefix_data = ly_type_union_store_prefix_data(ctx, value, value_len, format, prefix_data);
 
         /* remember the hint options */
         subvalue->parser_hint = options & LY_TYPE_PARSER_HINTS_MASK;
@@ -2147,8 +2340,8 @@
             /* turn logging off */
             prev_lo = ly_log_options(0);
             ret = type_u->types[u]->plugin->store(ctx, type_u->types[u], value, value_len, options & ~LY_TYPE_OPTS_DYNAMIC,
-                                                  ly_type_stored_prefixes_clb, subvalue->prefixes, format,
-                                                  context_node, tree, subvalue->value, canonized, err);
+                                                  subvalue->format, subvalue->prefix_data, context_node, tree, subvalue->value,
+                                                  canonized, err);
             /* restore logging */
             ly_log_options(prev_lo);
             if (ret == LY_SUCCESS || ret == LY_EINCOMPLETE) {
@@ -2167,11 +2360,11 @@
                 *err = ly_err_new(LY_LLERR, LY_EVALID, LYVE_DATA, errmsg, NULL, NULL);
                 ret = LY_EVALID;
             }
-            LY_ARRAY_FOR(subvalue->prefixes, u) {
-                lydict_remove(ctx, subvalue->prefixes[u].prefix);
-            }
-            LY_ARRAY_FREE(subvalue->prefixes);
+
+            /* free any stored information */
+            subvalue->value->realtype->plugin->free(ctx, subvalue->value);
             free(subvalue->value);
+            ly_type_union_free_prefix_data(subvalue->format, subvalue->prefix_data);
             free(subvalue);
             if ((options & LY_TYPE_OPTS_SECOND_CALL) && (options & LY_TYPE_OPTS_STORE)) {
                 storage->subvalue = NULL;
@@ -2186,17 +2379,15 @@
     /* success */
 
     if (options & LY_TYPE_OPTS_DYNAMIC) {
-        free((char*)value);
+        free((char *)value);
     }
 
     if (options & LY_TYPE_OPTS_STORE) {
         storage->subvalue = subvalue;
     } else {
-        LY_ARRAY_FOR(subvalue->prefixes, u) {
-            lydict_remove(ctx, subvalue->prefixes[u].prefix);
-        }
-        LY_ARRAY_FREE(subvalue->prefixes);
+        subvalue->value->realtype->plugin->free(ctx, subvalue->value);
         free(subvalue->value);
+        ly_type_union_free_prefix_data(subvalue->format, subvalue->prefix_data);
         free(subvalue);
     }
 
@@ -2223,9 +2414,9 @@
  * Implementation of the ly_type_print_clb.
  */
 static const char *
-ly_type_print_union(const struct lyd_value *value, LYD_FORMAT format, ly_get_prefix_clb get_prefix, void *printer, int *dynamic)
+ly_type_print_union(const struct lyd_value *value, LY_PREFIX_FORMAT format, void *prefix_data, int *dynamic)
 {
-    return value->subvalue->value->realtype->plugin->print(value->subvalue->value, format, get_prefix, printer, dynamic);
+    return value->subvalue->value->realtype->plugin->print(value->subvalue->value, format, prefix_data, dynamic);
 }
 
 /* @brief Duplication callback of the union values.
@@ -2235,18 +2426,11 @@
 static LY_ERR
 ly_type_dup_union(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
 {
-    LY_ARRAY_COUNT_TYPE u;
-
     dup->subvalue = calloc(1, sizeof *dup->subvalue);
     LY_CHECK_ERR_RET(!dup->subvalue, LOGMEM(ctx), LY_EMEM);
-    if (original->subvalue->prefixes) {
-        LY_ARRAY_CREATE_RET(ctx, dup->subvalue->prefixes, LY_ARRAY_COUNT(original->subvalue->prefixes), LY_EMEM);
-        LY_ARRAY_FOR(original->subvalue->prefixes, u) {
-            LY_ARRAY_INCREMENT(dup->subvalue->prefixes);
-            dup->subvalue->prefixes[u].mod = original->subvalue->prefixes[u].mod;
-            dup->subvalue->prefixes[u].prefix = lydict_insert(ctx, original->subvalue->prefixes[u].prefix, 0);
-        }
-    }
+    dup->subvalue->format = original->subvalue->format;
+    dup->subvalue->prefix_data = ly_type_union_dup_prefix_data(ctx, original->subvalue->format,
+                                                               original->subvalue->prefix_data);
     dup->subvalue->value = calloc(1, sizeof *dup->subvalue->value);
     LY_CHECK_ERR_RET(!dup->subvalue->value, LOGMEM(ctx), LY_EMEM);
     dup->subvalue->value->realtype = original->subvalue->value->realtype;
@@ -2263,16 +2447,11 @@
 static void
 ly_type_free_union(const struct ly_ctx *ctx, struct lyd_value *value)
 {
-    LY_ARRAY_COUNT_TYPE u;
-
     if (value->subvalue) {
         if (value->subvalue->value) {
             value->subvalue->value->realtype->plugin->free(ctx, value->subvalue->value);
-            LY_ARRAY_FOR(value->subvalue->prefixes, u) {
-                lydict_remove(ctx, value->subvalue->prefixes[u].prefix);
-            }
-            LY_ARRAY_FREE(value->subvalue->prefixes);
             free(value->subvalue->value);
+            ly_type_union_free_prefix_data(value->subvalue->format, value->subvalue->prefix_data);
         }
         free(value->subvalue);
         value->subvalue = NULL;
diff --git a/src/plugins_types.h b/src/plugins_types.h
index eaf449f..a0a187b 100644
--- a/src/plugins_types.h
+++ b/src/plugins_types.h
@@ -103,35 +103,35 @@
 void ly_err_free(void *ptr);
 
 /**
- * @brief Callback provided by the data/schema parsers to type plugins to resolve (format-specific) mapping between prefixes used
- * in the value strings to the YANG schemas.
+ * @brief Resolve format-specific prefixes to modules.
  *
- * Reverse function to ly_clb_get_prefix.
- *
- * XML uses XML namespaces, JSON uses schema names as prefixes, YIN/YANG uses prefixes of the imports.
- *
- * @param[in] ctx libyang context to find the schema.
- * @param[in] prefix Prefix found in the value string
- * @param[in] prefix_len Length of the @p prefix.
- * @param[in] private Internal data needed by the callback.
- * @return Pointer to the YANG schema identified by the provided prefix or NULL if no mapping found.
+ * @param[in] ctx libyang context.
+ * @param[in] prefix Prefix to resolve.
+ * @param[in] prefix_len Length of @p prefix.
+ * @param[in] format Format of the prefix.
+ * @param[in] prefix_data Format-specific data:
+ *      LY_PREF_SCHEMA  - const struct lys_module * (local module)
+ *      LY_PREF_XML     - const struct ly_set * (set with defined namespaces stored as ::lyxml_ns)
+ *      LY_PREF_JSON    - NULL
+ * @return Resolved prefix module,
+ * @return NULL otherwise.
  */
-typedef const struct lys_module *(*ly_clb_resolve_prefix)(const struct ly_ctx *ctx, const char *prefix, size_t prefix_len,
-                                                          void *private);
+const struct lys_module *ly_resolve_prefix(const struct ly_ctx *ctx, const char *prefix, size_t prefix_len,
+                                           LY_PREFIX_FORMAT format, void *prefix_data);
 
 /**
- * @brief Callback provided by the data/schema printers to type plugins to resolve (format-specific) mapping between YANG module of a data object
- * to prefixes used in the value strings.
+ * @brief Get format-specific prefix for a module.
  *
- * Reverse function to ly_clb_resolve_prefix.
- *
- * XML uses XML namespaces, JSON uses schema names as prefixes, YIN/YANG uses prefixes of the imports.
- *
- * @param[in] mod YANG module of the object.
- * @param[in] private Internal data needed by the callback.
- * @return String representing prefix for the object of the given YANG module @p mod.
+ * @param[in] mod Module whose prefix to get.
+ * @param[in] format Format of the prefix.
+ * @param[in] prefix_data Format-specific data:
+ *      LY_PREF_SCHEMA  - const struct lys_module * (local module)
+ *      LY_PREF_XML     - struct ly_set * (set of all returned modules as ::struct lys_module)
+ *      LY_PREF_JSON    - NULL
+ * @return Module prefix to print.
+ * @return NULL on error.
  */
-typedef const char *(*ly_clb_get_prefix)(const struct lys_module *mod, void *private);
+const char *ly_get_prefix(const struct lys_module *mod, LY_PREFIX_FORMAT format, void *prefix_data);
 
 /**
  * @defgroup plugintypeopts Options for type plugin callbacks. The same set of the options is passed to all the type's callbacks used together.
@@ -189,9 +189,8 @@
  *            It is never NULL, empty string is represented as "" with zero @p value_len.
  * @param[in] value_len Length (number of bytes) of the given \p value.
  * @param[in] options [Type plugin options](@ref plugintypeopts).
- * @param[in] resolve_prefix Parser-specific callback to resolve prefixes used in the value strings.
- * @param[in] parser Parser's data for @p resolve_prefix
  * @param[in] format Input format of the data.
+ * @param[in] prefix_data Format-specific data for resolving any prefixes (see ::ly_resolve_prefix).
  * @param[in] context_node The @p value's node for the case that the require-instance restriction is supposed to be resolved.
  *            This argument is a lys_node (in case LY_TYPE_OPTS_INCOMPLETE_DATA or LY_TYPE_OPTS_SCHEMA set in @p options)
  *            or lyd_node structure.
@@ -209,9 +208,9 @@
  * @return LY_ERR value if an error occurred and the value could not be canonized following the type's rules.
  */
 typedef LY_ERR (*ly_type_store_clb)(const struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len,
-                                    int options, ly_resolve_prefix_clb resolve_prefix, void *parser, LYD_FORMAT format,
-                                    const void *context_node, const struct lyd_node *tree,
-                                    struct lyd_value *storage, const char **canonized, struct ly_err_item **err);
+                                    int options, LY_PREFIX_FORMAT format, void *prefix_data, const void *context_node,
+                                    const struct lyd_node *tree, struct lyd_value *storage, const char **canonized,
+                                    struct ly_err_item **err);
 
 /**
  * @brief Callback for comparing 2 values of the same type.
@@ -235,16 +234,15 @@
  * @param[in] value Value to print.
  * @param[in] format Format in which the data are supposed to be printed.
  *            Only 2 formats are currently implemented: LYD_XML and LYD_JSON.
- * @param[in] get_prefix Callback to get prefix to use when printing objects supposed to be prefixed.
- * @param[in] printer Private data for the @p get_prefix callback.
+ * @param[in] prefix_data Format-specific data for getting any prefixes (see ::ly_get_prefix).
  * @param[out] dynamic Flag if the returned string is dynamically allocated. In such a case the caller is responsible
  *            for freeing it.
  * @return String with the value of @p value in specified @p format. According to the returned @p dynamic flag, caller
  *         can be responsible for freeing allocated memory.
  * @return NULL in case of error.
  */
-typedef const char *(*ly_type_print_clb)(const struct lyd_value *value, LYD_FORMAT format, ly_get_prefix_clb get_prefix,
-                                         void *printer, int *dynamic);
+typedef const char *(*ly_type_print_clb)(const struct lyd_value *value, LY_PREFIX_FORMAT format, void *prefix_data,
+                                         int *dynamic);
 
 /**
  * @brief Callback to duplicate data in data structure. Note that callback is even responsible for duplicating lyd_value::canonized.
@@ -359,7 +357,8 @@
  * @param[out] err Error information in case of failure. The error structure can be freed by ly_err_free().
  * @return LY_ERR value according to the result of the validation.
  */
-LY_ERR ly_type_validate_range(LY_DATA_TYPE basetype, struct lysc_range *range, int64_t value, const char *strval, struct ly_err_item **err);
+LY_ERR ly_type_validate_range(LY_DATA_TYPE basetype, struct lysc_range *range, int64_t value, const char *strval,
+                              struct ly_err_item **err);
 
 /**
  * @brief Data type validator for pattern-restricted string values.
@@ -389,19 +388,6 @@
 LY_ERR ly_type_find_leafref(const struct lysc_type_leafref *lref, const struct lyd_node *node, struct lyd_value *value,
                             const struct lyd_node *tree, struct lyd_node **target, char **errmsg);
 
-/**
- * @brief Helper function for type validation callbacks to prepare list of all possible prefixes used in the value string.
- *
- * @param[in] ctx libyang context.
- * @param[in] value Value string to be parsed.
- * @param[in] value_len Length of the @p value string.
- * @param[in] get_prefix Parser-specific getter to resolve prefixes used in the value strings.
- * @param[in] parser Parser's data for @p get_prefix.
- * @return Created [sized array](@ref sizedarrays) of prefix mappings, NULL in case of error.
- */
-struct lyd_value_prefix *ly_type_get_prefixes(const struct ly_ctx *ctx, const char *value, size_t value_len,
-                                              ly_resolve_prefix_clb get_prefix, void *parser);
-
 /** @} types */
 
 #ifdef __cplusplus
diff --git a/src/printer_data.c b/src/printer_data.c
index 7f6a84e..29dcc09 100644
--- a/src/printer_data.c
+++ b/src/printer_data.c
@@ -22,6 +22,7 @@
 #include "printer.h"
 #include "printer_internal.h"
 #include "tree_data.h"
+#include "tree_schema.h"
 
 static LY_ERR
 lyd_print_(struct ly_out *out, const struct lyd_node *root, LYD_FORMAT format, int options)
@@ -38,9 +39,9 @@
     case LYD_LYB:
         ret = lyb_print_data(out, root, options);
         break;
-    case LYD_SCHEMA:
-        LOGERR(out->ctx, LY_EINVAL, "Invalid output format.");
-        ret = LY_EINVAL;
+    case LYD_UNKNOWN:
+        LOGINT(root ? LYD_NODE_CTX(root) : NULL);
+        ret = LY_EINT;
         break;
     }
 
diff --git a/src/printer_json.c b/src/printer_json.c
index 171d30f..79824a1 100644
--- a/src/printer_json.c
+++ b/src/printer_json.c
@@ -57,17 +57,6 @@
 static LY_ERR json_print_node(struct jsonpr_ctx *ctx, const struct lyd_node *node);
 
 /**
- * @brief JSON mapping of YANG modules to prefixes in values.
- *
- * Implementation of ly_get_prefix_clb.
- */
-const char *
-json_print_get_prefix(const struct lys_module *mod, void *UNUSED(private))
-{
-    return mod->name;
-}
-
-/**
  * Compare 2 nodes, despite it is regular data node or an opaq node, and
  * decide if they corresponds to the same schema node.
  *
@@ -174,8 +163,8 @@
                 return NULL;
             }
             return mod->name;
-        case LYD_SCHEMA:
         case LYD_LYB:
+        case LYD_UNKNOWN:
             /* cannot be created */
             LOGINT(LYD_NODE_CTX(node));
         }
@@ -317,8 +306,8 @@
                 module_name = mod->name;
             }
             break;
-        case LYD_SCHEMA:
         case LYD_LYB:
+        case LYD_UNKNOWN:
             /* cannot be created */
             LOGINT_RET(ctx->ctx);
         }
@@ -345,7 +334,7 @@
 json_print_value(struct jsonpr_ctx *ctx, const struct lyd_value *val)
 {
     int dynamic = 0;
-    const char *value = val->realtype->plugin->print(val, LYD_JSON, json_print_get_prefix, NULL, &dynamic);
+    const char *value = val->realtype->plugin->print(val, LY_PREF_JSON, NULL, &dynamic);
 
     /* leafref is not supported */
     switch (val->realtype->basetype) {
diff --git a/src/printer_xml.c b/src/printer_xml.c
index d20bd0e..345776f 100644
--- a/src/printer_xml.c
+++ b/src/printer_xml.c
@@ -119,8 +119,8 @@
             }
         }
         break;
-    case LYD_SCHEMA:
     case LYD_LYB:
+    case LYD_UNKNOWN:
         /* cannot be created */
         LOGINT(ctx->ctx);
     }
@@ -129,20 +129,6 @@
 }
 
 /**
- * @brief XML mapping of YANG modules to prefixes in values.
- *
- * Implementation of ly_get_prefix_clb
- */
-static const char *
-xml_print_get_prefix(const struct lys_module *mod, void *private)
-{
-    struct ly_set *ns_list = (struct ly_set*)private;
-
-    ly_set_add(ns_list, (void*)mod, 0);
-    return mod->prefix;
-}
-
-/**
  * TODO
  */
 static void
@@ -181,7 +167,7 @@
     }
 #endif
     for (meta = node->meta; meta; meta = meta->next) {
-        const char *value = meta->value.realtype->plugin->print(&meta->value, LYD_XML, xml_print_get_prefix, &ns_list, &dynamic);
+        const char *value = meta->value.realtype->plugin->print(&meta->value, LY_PREF_XML, &ns_list, &dynamic);
 
         /* print namespaces connected with the value's prefixes */
         for (u = 0; u < ns_list.count; ++u) {
@@ -309,7 +295,7 @@
     const char *value;
 
     xml_print_node_open(ctx, (struct lyd_node *)node);
-    value = ((struct lysc_node_leaf *)node->schema)->type->plugin->print(&node->value, LYD_XML, xml_print_get_prefix, &ns_list, &dynamic);
+    value = ((struct lysc_node_leaf *)node->schema)->type->plugin->print(&node->value, LY_PREF_XML, &ns_list, &dynamic);
 
     /* print namespaces connected with the values's prefixes */
     for (u = 0; u < ns_list.count; ++u) {
diff --git a/src/printer_yang.c b/src/printer_yang.c
index 47ae071..f394111 100755
--- a/src/printer_yang.c
+++ b/src/printer_yang.c
@@ -935,7 +935,7 @@
     int dynamic;
     const char *str;
 
-    str = value->realtype->plugin->print(value, LYD_JSON, lys_get_prefix, (void*)value_mod, &dynamic);
+    str = value->realtype->plugin->print(value, LY_PREF_SCHEMA, (void *)value_mod, &dynamic);
     ypr_substmt(ctx, LYEXT_SUBSTMT_DEFAULT, 0, str, exts);
     if (dynamic) {
         free((void*)str);
diff --git a/src/tree_data.c b/src/tree_data.c
index 922d966..7e21f87 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -56,7 +56,7 @@
 
 LY_ERR
 lyd_value_parse(struct lyd_node_term *node, const char *value, size_t value_len, int *dynamic, int second, int value_hint,
-                ly_resolve_prefix_clb get_prefix, void *parser, LYD_FORMAT format, const struct lyd_node *tree)
+                LY_PREFIX_FORMAT format, void *prefix_data, const struct lyd_node *tree)
 {
     LY_ERR ret = LY_SUCCESS;
     struct ly_err_item *err = NULL;
@@ -72,7 +72,7 @@
     if (!second) {
         node->value.realtype = type;
     }
-    ret = type->plugin->store(ctx, type, value, value_len, options, get_prefix, parser, format,
+    ret = type->plugin->store(ctx, type, value, value_len, options, format, prefix_data,
                               tree ? (void *)node : (void *)node->schema, tree, &node->value, NULL, &err);
     if (ret && (ret != LY_EINCOMPLETE)) {
         if (err) {
@@ -96,7 +96,7 @@
 /* similar to lyd_value_parse except can be used just to store the value, hence also does not support a second call */
 LY_ERR
 lyd_value_store(struct lyd_value *val, const struct lysc_node *schema, const char *value, size_t value_len, int *dynamic,
-                ly_resolve_prefix_clb get_prefix, void *parser, LYD_FORMAT format)
+                LY_PREFIX_FORMAT format, void *prefix_data)
 {
     LY_ERR ret = LY_SUCCESS;
     struct ly_err_item *err = NULL;
@@ -109,7 +109,7 @@
     ctx = schema->module->ctx;
     type = ((struct lysc_node_leaf *)schema)->type;
     val->realtype = type;
-    ret = type->plugin->store(ctx, type, value, value_len, options, get_prefix, parser, format, (void *)schema, NULL,
+    ret = type->plugin->store(ctx, type, value, value_len, options, format, prefix_data, (void *)schema, NULL,
                               val, NULL, &err);
     if (ret == LY_EINCOMPLETE) {
         /* this is fine, we do not need it resolved */
@@ -128,8 +128,8 @@
 
 LY_ERR
 lyd_value_parse_meta(const struct ly_ctx *ctx, struct lyd_meta *meta, const char *value, size_t value_len, int *dynamic,
-                     int second, int value_hint, ly_resolve_prefix_clb get_prefix, void *parser, LYD_FORMAT format,
-                     const struct lysc_node *ctx_snode, const struct lyd_node *tree)
+                     int second, int value_hint, LY_PREFIX_FORMAT format, void *prefix_data, const struct lysc_node *ctx_snode,
+                     const struct lyd_node *tree)
 {
     LY_ERR ret = LY_SUCCESS;
     struct ly_err_item *err = NULL;
@@ -144,7 +144,7 @@
     if (!second) {
         meta->value.realtype = ant->type;
     }
-    ret = ant->type->plugin->store(ctx, ant->type, value, value_len, options, get_prefix, parser, format,
+    ret = ant->type->plugin->store(ctx, ant->type, value, value_len, options, format, prefix_data,
                                   tree ? (void *)meta->parent : (void *)ctx_snode, tree, &meta->value, NULL, &err);
     if (ret && (ret != LY_EINCOMPLETE)) {
         if (err) {
@@ -163,7 +163,7 @@
 
 LY_ERR
 _lys_value_validate(const struct ly_ctx *ctx, const struct lysc_node *node, const char *value, size_t value_len,
-                    ly_resolve_prefix_clb resolve_prefix, void *prefix_data, LYD_FORMAT format)
+                    LY_PREFIX_FORMAT format, void *prefix_data)
 {
     LY_ERR rc = LY_SUCCESS;
     struct ly_err_item *err = NULL;
@@ -179,7 +179,7 @@
     type = ((struct lysc_node_leaf*)node)->type;
     /* just validate, no storing of enything */
     rc = type->plugin->store(ctx ? ctx : node->module->ctx, type, value, value_len, LY_TYPE_OPTS_INCOMPLETE_DATA,
-                             resolve_prefix, prefix_data, format, node, NULL, NULL, NULL, &err);
+                             format, prefix_data, node, NULL, NULL, NULL, &err);
     if (rc == LY_EINCOMPLETE) {
         /* actually success since we do not provide the context tree and call validation with
          * LY_TYPE_OPTS_INCOMPLETE_DATA */
@@ -199,7 +199,7 @@
 API LY_ERR
 lys_value_validate(const struct ly_ctx *ctx, const struct lysc_node *node, const char *value, size_t value_len)
 {
-    return _lys_value_validate(ctx, node, value, value_len, lydjson_resolve_prefix, NULL, LYD_JSON);
+    return _lys_value_validate(ctx, node, value, value_len, LY_PREF_JSON, NULL);
 }
 
 API LY_ERR
@@ -215,9 +215,8 @@
     LY_CHECK_ARG_RET(ctx, node, value, LY_EINVAL);
 
     type = ((struct lysc_node_leaf*)node->schema)->type;
-    rc = type->plugin->store(ctx ? ctx : node->schema->module->ctx, type, value, value_len, options,
-                             lydjson_resolve_prefix, NULL, LYD_JSON, tree ? (void*)node : (void*)node->schema, tree,
-                             &val, NULL, &err);
+    rc = type->plugin->store(ctx ? ctx : node->schema->module->ctx, type, value, value_len, options, LY_PREF_JSON, NULL,
+                             tree ? (void*)node : (void*)node->schema, tree, &val, NULL, &err);
     if (rc == LY_EINCOMPLETE) {
         return rc;
     } else if (rc) {
@@ -253,8 +252,8 @@
 
     ctx = node->schema->module->ctx;
     type = ((struct lysc_node_leaf*)node->schema)->type;
-    rc = type->plugin->store(ctx, type, value, value_len, options, lydjson_resolve_prefix, NULL, LYD_JSON,
-                             (struct lyd_node *)node, tree, &data, NULL, &err);
+    rc = type->plugin->store(ctx, type, value, value_len, options, LY_PREF_JSON, NULL, (struct lyd_node *)node, tree, &data,
+                             NULL, &err);
     if (rc == LY_EINCOMPLETE) {
         ret = rc;
         /* continue with comparing, just remember what to return if storing is ok */
@@ -284,7 +283,7 @@
 {
     LY_CHECK_ARG_RET(node ? node->schema->module->ctx : NULL, node, dynamic, NULL);
 
-    return node->value.realtype->plugin->print(&node->value, LYD_JSON, json_print_get_prefix, NULL, dynamic);
+    return node->value.realtype->plugin->print(&node->value, LY_PREF_JSON, NULL, dynamic);
 }
 
 API const char *
@@ -292,7 +291,7 @@
 {
     LY_CHECK_ARG_RET(meta ? meta->parent->schema->module->ctx : NULL, meta, dynamic, NULL);
 
-    return meta->value.realtype->plugin->print(&meta->value, LYD_JSON, json_print_get_prefix, NULL, dynamic);
+    return meta->value.realtype->plugin->print(&meta->value, LY_PREF_JSON, NULL, dynamic);
 }
 
 static LYD_FORMAT
@@ -349,7 +348,7 @@
     case LYD_LYB:
         LY_CHECK_RET(lyd_parse_lyb_data(ctx, in, parse_options, validate_options, tree, &lydctx));
         break;
-    case LYD_SCHEMA:
+    case LYD_UNKNOWN:
         LOGINT_RET(ctx);
     }
 
@@ -384,8 +383,19 @@
             LY_CHECK_GOTO(ret, cleanup);
 
             /* finish incompletely validated terminal values/attributes and when conditions */
-            ret = lyd_validate_unres(tree, &lydctx->when_check, &lydctx->unres_node_type, &lydctx->unres_meta_type, LYD_XML,
-                                     lydctx->resolve_prefix, lydctx->data_ctx, NULL);
+            switch (format) {
+            case LYD_XML:
+                ret = lyd_validate_unres(tree, &lydctx->when_check, &lydctx->unres_node_type, &lydctx->unres_meta_type,
+                                         LY_PREF_XML, &((struct lyxml_ctx *)lydctx->data_ctx)->ns, NULL);
+                break;
+            case LYD_JSON:
+            case LYD_LYB:
+                ret = lyd_validate_unres(tree, &lydctx->when_check, &lydctx->unres_node_type, &lydctx->unres_meta_type,
+                                         LY_PREF_JSON, NULL, NULL);
+                break;
+            case LYD_UNKNOWN:
+                LOGINT_RET(ctx);
+            }
             LY_CHECK_GOTO(ret, cleanup);
 
             /* perform final validation that assumes the data tree is final */
@@ -468,8 +478,8 @@
         return lyd_parse_json_rpc(ctx, in, tree, op);
     case LYD_LYB:
         return lyd_parse_lyb_rpc(ctx, in, tree, op);
-    case LYD_SCHEMA:
-        LOGINT_RET(ctx);
+    case LYD_UNKNOWN:
+        break;
     }
 
     LOGINT_RET(ctx);
@@ -503,8 +513,8 @@
         return lyd_parse_json_reply(request, in, tree, op);
     case LYD_LYB:
         return lyd_parse_lyb_reply(request, in, tree, op);
-    case LYD_SCHEMA:
-        LOGINT_RET(LYD_NODE_CTX(request));
+    case LYD_UNKNOWN:
+        break;
     }
 
     LOGINT_RET(LYD_NODE_CTX(request));
@@ -536,8 +546,8 @@
         return lyd_parse_json_notif(ctx, in, tree, ntf);
     case LYD_LYB:
         return lyd_parse_lyb_notif(ctx, in, tree, ntf);
-    case LYD_SCHEMA:
-        LOGINT_RET(ctx);
+    case LYD_UNKNOWN:
+        break;
     }
 
     LOGINT_RET(ctx);
@@ -545,7 +555,7 @@
 
 LY_ERR
 lyd_create_term(const struct lysc_node *schema, const char *value, size_t value_len, int *dynamic, int value_hint,
-                ly_resolve_prefix_clb get_prefix, void *prefix_data, LYD_FORMAT format, struct lyd_node **node)
+                LY_PREFIX_FORMAT format, void *prefix_data, struct lyd_node **node)
 {
     LY_ERR ret;
     struct lyd_node_term *term;
@@ -559,7 +569,7 @@
     term->prev = (struct lyd_node *)term;
     term->flags = LYD_NEW;
 
-    ret = lyd_value_parse(term, value, value_len, dynamic, 0, value_hint, get_prefix, prefix_data, format, NULL);
+    ret = lyd_value_parse(term, value, value_len, dynamic, 0, value_hint, format, prefix_data, NULL);
     if (ret && (ret != LY_EINCOMPLETE)) {
         free(term);
         return ret;
@@ -669,7 +679,7 @@
 
     /* compile them */
     LY_CHECK_GOTO(ret = ly_path_compile_predicate(schema->module->ctx, NULL, NULL, schema, expr, &exp_idx,
-                                                  lydjson_resolve_prefix, NULL, LYD_JSON, &predicates, &pred_type), cleanup);
+                                                  LY_PREF_JSON, NULL, &predicates, &pred_type), cleanup);
 
     /* create the list node */
     LY_CHECK_GOTO(ret = lyd_create_list(schema, predicates, node), cleanup);
@@ -800,7 +810,7 @@
     for (key_s = lysc_node_children(schema, 0); key_s && (key_s->flags & LYS_KEY); key_s = key_s->next) {
         key_val = va_arg(ap, const char *);
 
-        rc = lyd_create_term(key_s, key_val, key_val ? strlen(key_val) : 0, NULL, 0, lydjson_resolve_prefix, NULL, LYD_JSON, &key);
+        rc = lyd_create_term(key_s, key_val, key_val ? strlen(key_val) : 0, NULL, 0, LY_PREF_JSON, NULL, &key);
         LY_CHECK_GOTO(rc && (rc != LY_EINCOMPLETE), cleanup);
         rc = LY_SUCCESS;
         lyd_insert_node(ret, NULL, key);
@@ -877,7 +887,7 @@
     schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYD_NODE_TERM, 0);
     LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "Term node \"%s\" not found.", name), LY_ENOTFOUND);
 
-    rc = lyd_create_term(schema, val_str, val_str ? strlen(val_str) : 0, NULL, 0, lydjson_resolve_prefix, NULL, LYD_JSON, &ret);
+    rc = lyd_create_term(schema, val_str, val_str ? strlen(val_str) : 0, NULL, 0, LY_PREF_JSON, NULL, &ret);
     LY_CHECK_RET(rc && (rc != LY_EINCOMPLETE), rc);
     if (parent) {
         lyd_insert_node(parent, NULL, ret);
@@ -1022,7 +1032,7 @@
     }
 
     LY_CHECK_RET(lyd_create_meta(parent, &ret, module, name, name_len, val_str, strlen(val_str), NULL, 0,
-                                 lydjson_resolve_prefix, NULL, LYD_JSON, parent->schema));
+                                 LY_PREF_JSON, NULL, parent->schema));
 
     if (meta) {
         *meta = ret;
@@ -1110,8 +1120,7 @@
     type = ((struct lysc_node_leaf *)term->schema)->type;
 
     /* parse the new value */
-    LY_CHECK_GOTO(ret = lyd_value_store(&val, term->schema, val_str, strlen(val_str), NULL, lydjson_resolve_prefix, NULL,
-                                        LYD_JSON), cleanup);
+    LY_CHECK_GOTO(ret = lyd_value_store(&val, term->schema, val_str, strlen(val_str), NULL, LY_PREF_JSON, NULL), cleanup);
 
     /* compare original and new value */
     if (type->plugin->compare(&t->value, &val)) {
@@ -1186,7 +1195,7 @@
 
     /* parse the new value into a new meta structure */
     LY_CHECK_GOTO(ret = lyd_create_meta(NULL, &m2, meta->annotation->module, meta->name, strlen(meta->name), val_str,
-                                        strlen(val_str), NULL, 0, lydjson_resolve_prefix, NULL, LYD_JSON, NULL), cleanup);
+                                        strlen(val_str), NULL, 0, LY_PREF_JSON, NULL, NULL), cleanup);
 
     /* compare original and new value */
     if (lyd_compare_meta(meta, m2)) {
@@ -1241,7 +1250,7 @@
     /* compile path */
     LY_CHECK_GOTO(ret = ly_path_compile(ctx, NULL, parent ? parent->schema : NULL, exp, LY_PATH_LREF_FALSE,
                                         options & LYD_NEWOPT_OUTPUT ? LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT,
-                                        LY_PATH_TARGET_MANY, lydjson_resolve_prefix, NULL, LYD_JSON, &p), cleanup);
+                                        LY_PATH_TARGET_MANY, LY_PREF_JSON, NULL, &p), cleanup);
 
     schema = p[LY_ARRAY_COUNT(p) - 1].node;
     if ((schema->nodetype == LYS_LIST) && (p[LY_ARRAY_COUNT(p) - 1].pred_type == LY_PATH_PREDTYPE_NONE)
@@ -1264,8 +1273,7 @@
             r = lys_value_validate(NULL, schema, value, strlen(value));
         }
         if (!r) {
-            LY_CHECK_GOTO(ret = lyd_value_store(&pred->value, schema, value, strlen(value), NULL, lydjson_resolve_prefix,
-                                                NULL, LYD_JSON), cleanup);
+            LY_CHECK_GOTO(ret = lyd_value_store(&pred->value, schema, value, strlen(value), NULL, LY_PREF_JSON, NULL), cleanup);
         } /* else we have opaq flag and the value is not valid, leavne no predicate and then create an opaque node */
     }
 
@@ -1345,13 +1353,12 @@
                 r = lys_value_validate(NULL, schema, value, strlen(value));
             }
             if (!r) {
-                LY_CHECK_GOTO(ret = lyd_create_term(schema, value, strlen(value), NULL, 0, lydjson_resolve_prefix, NULL,
-                                                    LYD_JSON, &node), cleanup);
+                LY_CHECK_GOTO(ret = lyd_create_term(schema, value, strlen(value), NULL, 0, LY_PREF_JSON, NULL, &node), cleanup);
             } else {
                 /* creating opaque leaf without value */
                 LY_CHECK_GOTO(ret = lyd_create_opaq(ctx, schema->name, strlen(schema->name), NULL, 0, NULL, 0,
-                                                    LYD_JSON, NULL, NULL, 0, schema->module->name, strlen(schema->module->name), &node),
-                              cleanup);
+                                                    LYD_JSON, NULL, NULL, 0, schema->module->name,
+                                                    strlen(schema->module->name), &node), cleanup);
             }
             break;
         case LYS_ANYDATA:
@@ -2133,8 +2140,8 @@
 
 LY_ERR
 lyd_create_meta(struct lyd_node *parent, struct lyd_meta **meta, const struct lys_module *mod, const char *name,
-                size_t name_len, const char *value, size_t value_len, int *dynamic, int value_hint, ly_resolve_prefix_clb resolve_prefix,
-                void *prefix_data, LYD_FORMAT format, const struct lysc_node *ctx_snode)
+                size_t name_len, const char *value, size_t value_len, int *dynamic, int value_hint, LY_PREFIX_FORMAT format,
+                void *prefix_data, const struct lysc_node *ctx_snode)
 {
     LY_ERR ret;
     struct lysc_ext_instance *ant = NULL;
@@ -2162,7 +2169,7 @@
     LY_CHECK_ERR_RET(!mt, LOGMEM(mod->ctx), LY_EMEM);
     mt->parent = parent;
     mt->annotation = ant;
-    ret = lyd_value_parse_meta(mod->ctx, mt, value, value_len, dynamic, 0, value_hint, resolve_prefix, prefix_data, format, ctx_snode, NULL);
+    ret = lyd_value_parse_meta(mod->ctx, mt, value, value_len, dynamic, 0, value_hint, format, prefix_data, ctx_snode, NULL);
     if ((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE)) {
         free(mt);
         return ret;
@@ -2314,8 +2321,8 @@
                 return LY_ENOT;
             }
             break;
-        case LYD_SCHEMA:
         case LYD_LYB:
+        case LYD_UNKNOWN:
             /* not allowed */
             LOGINT(LYD_NODE_CTX(node1));
             return LY_EINT;
@@ -3333,7 +3340,7 @@
         /* create a data node and find the instance */
         if (schema->nodetype == LYS_LEAFLIST) {
             /* target used attributes: schema, hash, value */
-            rc = lyd_create_term(schema, key_or_value, val_len, NULL, 0, lydjson_resolve_prefix, NULL, LYD_JSON, &target);
+            rc = lyd_create_term(schema, key_or_value, val_len, NULL, 0, LY_PREF_JSON, NULL, &target);
             LY_CHECK_RET(rc && (rc != LY_EINCOMPLETE), rc);
         } else {
             /* target used attributes: schema, hash, child (all keys) */
@@ -3368,7 +3375,7 @@
     LY_CHECK_ERR_GOTO(!exp, ret = LY_EINVAL, cleanup);
 
     /* evaluate expression */
-    ret = lyxp_eval(exp, LYD_JSON, ctx_node->schema->module, ctx_node, LYXP_NODE_ELEM, ctx_node, &xp_set, 0);
+    ret = lyxp_eval(exp, LY_PREF_JSON, ctx_node->schema->module, ctx_node, LYXP_NODE_ELEM, ctx_node, &xp_set, 0);
     LY_CHECK_GOTO(ret, cleanup);
 
     /* allocate return set */
diff --git a/src/tree_data.h b/src/tree_data.h
index 37bfa0c..4f261ef 100644
--- a/src/tree_data.h
+++ b/src/tree_data.h
@@ -140,16 +140,25 @@
 
 /**
  * @brief Data input/output formats supported by libyang [parser](@ref howtodataparsers) and
- * [printer](@ref howtodataprinters) functions. Also used for value prefix format (TODO link to prefix formats descriptions).
+ * [printer](@ref howtodataprinters) functions.
  */
 typedef enum {
-    LYD_SCHEMA = 0,      /**< invalid instance data format, value prefixes map to YANG import prefixes */
-    LYD_XML,             /**< XML instance data format, value prefixes map to XML namespace prefixes */
-    LYD_JSON,            /**< JSON instance data format, value prefixes map to module names */
-    LYD_LYB,             /**< LYB instance data format, invalid value prefix format (same as LYD_JSON) */
+    LYD_UNKNOWN = 0,     /**< unknown data format, invalid value */
+    LYD_XML,             /**< XML instance data format */
+    LYD_JSON,            /**< JSON instance data format */
+    LYD_LYB,             /**< LYB instance data format */
 } LYD_FORMAT;
 
 /**
+ * @brief All kinds of supported prefix mappings to modules.
+ */
+typedef enum {
+    LY_PREF_SCHEMA,          /**< value prefixes map to YANG import prefixes */
+    LY_PREF_XML,             /**< value prefixes map to XML namespace prefixes */
+    LY_PREF_JSON,            /**< value prefixes map to module names */
+} LY_PREFIX_FORMAT;
+
+/**
  * @brief List of possible value types stored in ::lyd_node_any.
  */
 typedef enum {
@@ -167,6 +176,24 @@
 /** @} */
 
 /**
+ * @brief Special lyd_value structure for union.
+ *
+ * Represents data with multiple types (union). Original value is stored in the main lyd_value:canonical_cache while
+ * the lyd_value_subvalue::value contains representation according to one of the union's types.
+ * The lyd_value_subvalue:prefixes provides (possible) mappings from prefixes in the original value to YANG modules.
+ * These prefixes are necessary to parse original value to the union's subtypes.
+ */
+struct lyd_value_subvalue {
+    struct lyd_value *value;     /**< representation of the value according to the selected union's subtype
+                                      (stored as lyd_value::realpath here, in subvalue structure */
+    LY_PREFIX_FORMAT format;     /**< Prefix format of the value. However, this information is also used to decide
+                                      whether a value is valid for the specific format or not on later validations
+                                      (instance-identifier in XML looks different than in JSON). */
+    void *prefix_data;           /**< Format-specific data for prefix resolution (see ::ly_resolve_prefix) */
+    int parser_hint;             /**< Hint options from the parser */
+};
+
+/**
  * @brief YANG data representation
  */
 struct lyd_value {
@@ -186,23 +213,8 @@
         struct lysc_type_bitenum_item *enum_item;  /**< pointer to the definition of the enumeration value */
         struct lysc_type_bitenum_item **bits_items; /**< list of set pointers to the specification of the set bits ([sized array](@ref sizedarrays)) */
         struct lysc_ident *ident;    /**< pointer to the schema definition of the identityref value */
-
-        struct lyd_value_subvalue {
-            struct lyd_value_prefix {
-                const char *prefix;           /**< prefix string used in the canonized string to identify the mod of the YANG schema */
-                const struct lys_module *mod; /**< YANG schema module identified by the prefix string */
-            } *prefixes;                 /**< list of mappings between prefix in canonized value to a YANG schema ([sized array](@ref sizedarrays)) */
-            struct lyd_value *value;     /**< representation of the value according to the selected union's subtype (stored as lyd_value::realpath
-                                              here, in subvalue structure */
-            int parser_hint;             /**< Hint options from the parser */
-        } *subvalue;                     /**< data to represent data with multiple types (union). Original value is stored in the main
-                                              lyd_value:canonical_cache while the lyd_value_subvalue::value contains representation according to the
-                                              one of the union's type. The lyd_value_subvalue:prefixes provides (possible) mappings from prefixes
-                                              in original value to YANG modules. These prefixes are necessary to parse original value to the union's
-                                              subtypes. */
-
-        struct ly_path *target;          /**< Instance-identifier's target path. */
-
+        struct ly_path *target;      /**< Instance-identifier target path. */
+        struct lyd_value_subvalue *subvalue; /** Union value with some metadata. */
         void *ptr;                   /**< generic data type structure used to store the data */
     };  /**< The union is just a list of shorthands to possible values stored by a type's plugin. libyang itself uses the lyd_value::realtype
              plugin's callbacks to work with the data. */
@@ -302,37 +314,6 @@
 /** @} */
 
 /**
- * @brief Callback provided by the data/schema parsers to type plugins to resolve (format-specific) mapping between prefixes used
- * in the value strings to the YANG schemas.
- *
- * Reverse function to ly_get_prefix_clb.
- *
- * XML uses XML namespaces, JSON uses schema names as prefixes, YIN/YANG uses prefixes of the imports.
- *
- * @param[in] ctx libyang context to find the schema.
- * @param[in] prefix Prefix found in the value string
- * @param[in] prefix_len Length of the @p prefix.
- * @param[in] private Internal data needed by the callback.
- * @return Pointer to the YANG schema identified by the provided prefix or NULL if no mapping found.
- */
-typedef const struct lys_module *(*ly_resolve_prefix_clb)(const struct ly_ctx *ctx, const char *prefix, size_t prefix_len,
-                                                          void *private);
-
-/**
- * @brief Callback provided by the data/schema printers to type plugins to resolve (format-specific) mapping between YANG module of a data object
- * to prefixes used in the value strings.
- *
- * Reverse function to ly_resolve_prefix_clb.
- *
- * XML uses XML namespaces, JSON uses schema names as prefixes, YIN/YANG uses prefixes of the imports.
- *
- * @param[in] mod YANG module of the object.
- * @param[in] private Internal data needed by the callback.
- * @return String representing prefix for the object of the given YANG module @p mod.
- */
-typedef const char *(*ly_get_prefix_clb)(const struct lys_module *mod, void *private);
-
-/**
  * @brief Generic structure for a data node.
  */
 struct lyd_node {
diff --git a/src/tree_data_internal.h b/src/tree_data_internal.h
index 5b7d5c6..290f40a 100644
--- a/src/tree_data_internal.h
+++ b/src/tree_data_internal.h
@@ -95,16 +95,15 @@
  * @param[in] value_len Length of @p value, must be set correctly.
  * @param[in,out] dynamic Flag if @p value is dynamically allocated, is adjusted when @p value is consumed.
  * @param[in] value_hint [Hint options](@ref lydvalueparseopts) from the parser regarding the value type.
- * @param[in] get_prefix Parser-specific getter to resolve prefixes used in the @p value string.
- * @param[in] prefix_data User data for @p get_prefix.
  * @param[in] format Input format of @p value.
+ * @param[in] prefix_data Format-specific data for resolving any prefixes (see ::ly_resolve_prefix).
  * @param[out] node Created node.
  * @return LY_SUCCESS on success.
  * @return LY_EINCOMPLETE in case data tree is needed to finish the validation.
  * @return LY_ERR value if an error occurred.
  */
 LY_ERR lyd_create_term(const struct lysc_node *schema, const char *value, size_t value_len, int *dynamic, int value_hint,
-                       ly_resolve_prefix_clb get_prefix, void *prefix_data, LYD_FORMAT format, struct lyd_node **node);
+                       LY_PREFIX_FORMAT format, void *prefix_data, struct lyd_node **node);
 
 /**
  * @brief Create a term (leaf/leaf-list) node from a parsed value by duplicating it.
@@ -182,8 +181,8 @@
  * @return LY_ERR value if an error occurred.
  */
 LY_ERR lyd_create_opaq(const struct ly_ctx *ctx, const char *name, size_t name_len, const char *value, size_t value_len,
-                       int *dynamic, int value_hint, LYD_FORMAT format, struct ly_prefix *val_prefs, const char *prefix, size_t pref_len,
-                       const char *module_key, size_t module_key_len, struct lyd_node **node);
+                       int *dynamic, int value_hint, LYD_FORMAT format, struct ly_prefix *val_prefs, const char *prefix,
+                       size_t pref_len, const char *module_key, size_t module_key_len, struct lyd_node **node);
 
 /**
  * @brief Check the existence and create any non-existing implicit siblings, recursively for the created nodes.
@@ -241,9 +240,8 @@
  * @param[in] value_len Length of @p value, must be set correctly.
  * @param[in,out] dynamic Flag if @p value is dynamically allocated, is adjusted when @p value is consumed.
  * @param[in] value_hint [Value hint](@ref lydvalueparseopts) from the parser regarding the value type.
- * @param[in] resolve_prefix Parser-specific getter to resolve prefixes used in the @p value string.
- * @param[in] prefix_data User data for @p get_prefix.
  * @param[in] format Input format of @p value.
+ * @param[in] prefix_data Format-specific data for resolving any prefixes (see ::ly_resolve_prefix).
  * @param[in] ctx_snode Context node for value resolution in schema.
  * @return LY_SUCCESS on success.
  * @return LY_EINCOMPLETE in case data tree is needed to finish the validation.
@@ -251,7 +249,7 @@
  */
 LY_ERR lyd_create_meta(struct lyd_node *parent, struct lyd_meta **meta, const struct lys_module *mod, const char *name,
                        size_t name_len, const char *value, size_t value_len, int *dynamic, int value_hint,
-                       ly_resolve_prefix_clb resolve_prefix, void *prefix_data, LYD_FORMAT format, const struct lysc_node *ctx_snode);
+                       LY_PREFIX_FORMAT format, void *prefix_data, const struct lysc_node *ctx_snode);
 
 /**
  * @brief Insert an attribute (last) into a parent
@@ -308,9 +306,8 @@
  * @param[in,out] dynamic Flag if @p value is dynamically allocated, is adjusted when @p value is consumed.
  * @param[in] second Flag for the second call after returning LY_EINCOMPLETE
  * @param[in] value_hint [Value hint](@ref lydvalueparseopts) from the parser.
- * @param[in] get_prefix Parser-specific getter to resolve prefixes used in the @p value string.
- * @param[in] parser Parser's data for @p get_prefix
  * @param[in] format Input format of @p value.
+ * @param[in] prefix_data Format-specific data for resolving any prefixes (see ::ly_resolve_prefix).
  * @param[in] tree Data tree (e.g. when validating RPC/Notification) where the required
  *            data instance (leafref target, instance-identifier) can be placed. NULL in case the data tree are not yet complete,
  *            then LY_EINCOMPLETE can be returned.
@@ -319,11 +316,11 @@
  * @return LY_ERR value if an error occurred.
  */
 LY_ERR lyd_value_parse(struct lyd_node_term *node, const char *value, size_t value_len, int *dynamic, int second, int value_hint,
-                       ly_resolve_prefix_clb get_prefix, void *parser, LYD_FORMAT format, const struct lyd_node *tree);
+                       LY_PREFIX_FORMAT format, void *prefix_data, const struct lyd_node *tree);
 
 /* similar to lyd_value_parse except can be used just to store the value, hence does also not support a second call */
 LY_ERR lyd_value_store(struct lyd_value *val, const struct lysc_node *schema, const char *value, size_t value_len,
-                       int *dynamic, ly_resolve_prefix_clb get_prefix, void *parser, LYD_FORMAT format);
+                       int *dynamic, LY_PREFIX_FORMAT format, void *prefix_data);
 
 /**
  * @brief Validate, canonize and store the given @p value into the metadata according to the annotation type's rules.
@@ -335,9 +332,8 @@
  * @param[in,out] dynamic Flag if @p value is dynamically allocated, is adjusted when @p value is consumed.
  * @param[in] second Flag for the second call after returning LY_EINCOMPLETE
  * @param[in] value_hint [Value hint](@ref lydvalueparseopts) from the parser.
- * @param[in] get_prefix Parser-specific getter to resolve prefixes used in the @p value string.
- * @param[in] parser Parser's data for @p get_prefix
  * @param[in] format Input format of the data.
+ * @param[in] prefix_data Format-specific data for resolving any prefixes (see ::ly_resolve_prefix).
  * @param[in] ctx_snode Context node for value resolution in schema.
  * @param[in] tree Data tree (e.g. when validating RPC/Notification) where the required
  *            data instance (leafref target, instance-identifier) can be placed. NULL in case the data tree are not yet complete,
@@ -347,12 +343,12 @@
  * @return LY_ERR value if an error occurred.
  */
 LY_ERR lyd_value_parse_meta(const struct ly_ctx *ctx, struct lyd_meta *meta, const char *value, size_t value_len,
-                            int *dynamic, int second, int value_hint, ly_resolve_prefix_clb get_prefix, void *parser,
-                            LYD_FORMAT format, const struct lysc_node *ctx_snode, const struct lyd_node *tree);
+                            int *dynamic, int second, int value_hint, LY_PREFIX_FORMAT format, void *prefix_data,
+                            const struct lysc_node *ctx_snode, const struct lyd_node *tree);
 
 /* generic function lys_value_validate */
 LY_ERR _lys_value_validate(const struct ly_ctx *ctx, const struct lysc_node *node, const char *value, size_t value_len,
-                           ly_clb_resolve_prefix resolve_prefix, void *prefix_data, LYD_FORMAT format);
+                           LY_PREFIX_FORMAT format, void *prefix_data);
 
 /**
  * @brief Parse XML string as YANG data tree.
diff --git a/src/tree_schema.c b/src/tree_schema.c
index fc73acf..fa9a8ee 100644
--- a/src/tree_schema.c
+++ b/src/tree_schema.c
@@ -309,7 +309,7 @@
     LY_CHECK_ERR_GOTO(!exp, ret = LY_EINVAL, cleanup);
 
     /* atomize expression */
-    ret = lyxp_atomize(exp, LYD_JSON, ctx_node->module, ctx_node, LYXP_NODE_ELEM, &xp_set, options);
+    ret = lyxp_atomize(exp, LY_PREF_JSON, ctx_node->module, ctx_node, LYXP_NODE_ELEM, &xp_set, options);
     LY_CHECK_GOTO(ret, cleanup);
 
     /* allocate return set */
@@ -353,7 +353,7 @@
     LY_CHECK_ERR_GOTO(!exp, ret = LY_EINVAL, cleanup);
 
     /* atomize expression */
-    ret = lyxp_atomize(exp, LYD_JSON, ctx_node->module, ctx_node, LYXP_NODE_ELEM, &xp_set, options);
+    ret = lyxp_atomize(exp, LY_PREF_JSON, ctx_node->module, ctx_node, LYXP_NODE_ELEM, &xp_set, options);
     LY_CHECK_GOTO(ret, cleanup);
 
     /* allocate return set */
diff --git a/src/tree_schema_compile.c b/src/tree_schema_compile.c
index e4f8ebd..ecdf200 100644
--- a/src/tree_schema_compile.c
+++ b/src/tree_schema_compile.c
@@ -3092,7 +3092,7 @@
         (*type)->dflt->realtype = (*type);
         ret = (*type)->plugin->store(ctx->ctx, (*type), dflt, strlen(dflt),
                                      LY_TYPE_OPTS_INCOMPLETE_DATA | LY_TYPE_OPTS_SCHEMA | LY_TYPE_OPTS_STORE,
-                                     lys_resolve_prefix, (void*)(*type)->dflt_mod, LYD_XML, NULL, NULL, (*type)->dflt, NULL, &err);
+                                     LY_PREF_SCHEMA, (*type)->dflt_mod, NULL, NULL, (*type)->dflt, NULL, &err);
         if (err) {
             ly_err_print(err);
             LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
@@ -3524,7 +3524,7 @@
         leaf->dflt->realtype = leaf->type;
         ret = leaf->type->plugin->store(ctx->ctx, leaf->type, leaf_p->dflt, strlen(leaf_p->dflt),
                                         LY_TYPE_OPTS_INCOMPLETE_DATA | LY_TYPE_OPTS_SCHEMA | LY_TYPE_OPTS_STORE,
-                                        lys_resolve_prefix, (void*)leaf->dflt_mod, LYD_XML, node, NULL, leaf->dflt, NULL, &err);
+                                        LY_PREF_SCHEMA, leaf->dflt_mod, node, NULL, leaf->dflt, NULL, &err);
         leaf->dflt->realtype->refcount++;
         if (err) {
             ly_err_print(err);
@@ -3598,7 +3598,7 @@
             llist->dflts[u]->realtype = llist->type;
             ret = llist->type->plugin->store(ctx->ctx, llist->type, llist_p->dflts[u], strlen(llist_p->dflts[u]),
                                              LY_TYPE_OPTS_INCOMPLETE_DATA | LY_TYPE_OPTS_SCHEMA | LY_TYPE_OPTS_STORE,
-                                             lys_resolve_prefix, (void*)llist->dflts_mods[u], LYD_XML, node, NULL, llist->dflts[u], NULL, &err);
+                                             LY_PREF_SCHEMA, llist->dflts_mods[u], node, NULL, llist->dflts[u], NULL, &err);
             llist->dflts[u]->realtype->refcount++;
             if (err) {
                 ly_err_print(err);
@@ -3623,7 +3623,8 @@
             for (v = u + 1; v < LY_ARRAY_COUNT(llist->dflts); ++v) {
                 if (!llist->type->plugin->compare(llist->dflts[u], llist->dflts[v])) {
                     int dynamic = 0;
-                    const char *val = llist->type->plugin->print(llist->dflts[v], LYD_XML, lys_get_prefix, llist->dflts_mods[v], &dynamic);
+                    const char *val = llist->type->plugin->print(llist->dflts[v], LY_PREF_SCHEMA, llist->dflts_mods[v],
+                                                                 &dynamic);
                     LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
                            "Configuration leaf-list has multiple defaults of the same value \"%s\".", val);
                     if (dynamic) {
@@ -4929,7 +4930,7 @@
                 leaf->dflt_mod = ctx->mod_def;
                 rc = leaf->type->plugin->store(ctx->ctx, leaf->type, rfn->dflts[0], strlen(rfn->dflts[0]),
                                                 LY_TYPE_OPTS_INCOMPLETE_DATA | LY_TYPE_OPTS_SCHEMA | LY_TYPE_OPTS_STORE,
-                                                lys_resolve_prefix, (void*)leaf->dflt_mod, LYD_XML, node, NULL, leaf->dflt, NULL, &err);
+                                                LY_PREF_SCHEMA, leaf->dflt_mod, node, NULL, leaf->dflt, NULL, &err);
                 leaf->dflt->realtype->refcount++;
                 if (err) {
                     ly_err_print(err);
@@ -4978,8 +4979,9 @@
                     llist->dflts[u] = calloc(1, sizeof *llist->dflts[u]);
                     llist->dflts[u]->realtype = llist->type;
                     rc = llist->type->plugin->store(ctx->ctx, llist->type, rfn->dflts[u], strlen(rfn->dflts[u]),
-                                                     LY_TYPE_OPTS_INCOMPLETE_DATA | LY_TYPE_OPTS_SCHEMA | LY_TYPE_OPTS_STORE,
-                                                     lys_resolve_prefix, (void*)llist->dflts_mods[u], LYD_XML, node, NULL, llist->dflts[u], NULL, &err);
+                                                    LY_TYPE_OPTS_INCOMPLETE_DATA | LY_TYPE_OPTS_SCHEMA | LY_TYPE_OPTS_STORE,
+                                                    LY_PREF_SCHEMA, llist->dflts_mods[u], node, NULL, llist->dflts[u],
+                                                    NULL, &err);
                     llist->dflts[u]->realtype->refcount++;
                     if (err) {
                         ly_err_print(err);
@@ -5666,8 +5668,8 @@
 #define DEV_CHECK_NONPRESENCE_VALUE(TYPE, COND, MEMBER, PROPERTY, VALUEMEMBER, VALUEMODMEMBER) \
     if (((TYPE)target)->MEMBER && (COND)) { \
         int dynamic_ = 0; const char *val_; \
-        val_ = ((TYPE)target)->VALUEMEMBER->realtype->plugin->print(((TYPE)target)->VALUEMEMBER, LYD_XML, \
-                                                                             lys_get_prefix, ((TYPE)target)->VALUEMODMEMBER, &dynamic_); \
+        val_ = ((TYPE)target)->VALUEMEMBER->realtype->plugin->print(((TYPE)target)->VALUEMEMBER, LY_PREF_SCHEMA, \
+                                                                             ((TYPE)target)->VALUEMODMEMBER, &dynamic_); \
         LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE, \
                "Invalid deviation adding \"%s\" property which already exists (with value \"%s\").", PROPERTY, val_); \
         if (dynamic_) {free((void*)val_);} \
@@ -5781,8 +5783,8 @@
                 llist->dflts[x] = calloc(1, sizeof *llist->dflts[x]);
                 llist->dflts[x]->realtype = llist->type;
                 rc = llist->type->plugin->store(ctx->ctx, llist->type, d->dflts[x - y], strlen(d->dflts[x - y]),
-                                                LY_TYPE_OPTS_INCOMPLETE_DATA | LY_TYPE_OPTS_SCHEMA | LY_TYPE_OPTS_STORE, lys_resolve_prefix,
-                                                (void*)llist->dflts_mods[x], LYD_XML, target, NULL, llist->dflts[x], NULL, &err);
+                                                LY_TYPE_OPTS_INCOMPLETE_DATA | LY_TYPE_OPTS_SCHEMA | LY_TYPE_OPTS_STORE,
+                                                LY_PREF_SCHEMA, llist->dflts_mods[x], target, NULL, llist->dflts[x], NULL, &err);
                 llist->dflts[x]->realtype->refcount++;
                 if (err) {
                     ly_err_print(err);
@@ -6035,7 +6037,7 @@
                                 dflt, "deleting", "default", d->dflts[0]);
 
             /* check that the values matches */
-            dflt = leaf->dflt->realtype->plugin->print(leaf->dflt, LYD_XML, lys_get_prefix, leaf->dflt_mod, &i);
+            dflt = leaf->dflt->realtype->plugin->print(leaf->dflt, LY_PREF_SCHEMA, leaf->dflt_mod, &i);
             if (strcmp(dflt, d->dflts[0])) {
                 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
                         "Invalid deviation deleting \"default\" property \"%s\" which does not match the target's property value \"%s\".",
@@ -6064,7 +6066,7 @@
             DEV_CHECK_PRESENCE(struct lysc_node_leaflist*, 0, dflts, "deleting", "default", d->dflts[0]);
             LY_ARRAY_FOR(d->dflts, x) {
                 LY_ARRAY_FOR(llist->dflts, y) {
-                    dflt = llist->type->plugin->print(llist->dflts[y], LYD_XML, lys_get_prefix, llist->dflts_mods[y], &i);
+                    dflt = llist->type->plugin->print(llist->dflts[y], LY_PREF_SCHEMA, llist->dflts_mods[y], &i);
                     if (!strcmp(dflt, d->dflts[x])) {
                         if (i) {
                             free((char*)dflt);
@@ -6365,16 +6367,16 @@
         if (target->nodetype & (LYS_RPC | LYS_ACTION)) {
             if (dev->flags & LYSC_OPT_RPC_INPUT) {
                 /* remove RPC's/action's input */
-                lysc_action_inout_free(ctx->ctx, &((struct lysc_action*)target)->input);
-                memset(&((struct lysc_action*)target)->input, 0, sizeof ((struct lysc_action*)target)->input);
-                FREE_ARRAY(ctx->ctx, ((struct lysc_action*)target)->input_exts, lysc_ext_instance_free);
-                ((struct lysc_action*)target)->input_exts = NULL;
+                lysc_action_inout_free(ctx->ctx, &((struct lysc_action *)target)->input);
+                memset(&((struct lysc_action *)target)->input, 0, sizeof ((struct lysc_action *)target)->input);
+                FREE_ARRAY(ctx->ctx, ((struct lysc_action *)target)->input_exts, lysc_ext_instance_free);
+                ((struct lysc_action *)target)->input_exts = NULL;
             } else if (dev->flags & LYSC_OPT_RPC_OUTPUT) {
                 /* remove RPC's/action's output */
-                lysc_action_inout_free(ctx->ctx, &((struct lysc_action*)target)->output);
-                memset(&((struct lysc_action*)target)->output, 0, sizeof ((struct lysc_action*)target)->output);
-                FREE_ARRAY(ctx->ctx, ((struct lysc_action*)target)->output_exts, lysc_ext_instance_free);
-                ((struct lysc_action*)target)->output_exts = NULL;
+                lysc_action_inout_free(ctx->ctx, &((struct lysc_action *)target)->output);
+                memset(&((struct lysc_action *)target)->output, 0, sizeof ((struct lysc_action *)target)->output);
+                FREE_ARRAY(ctx->ctx, ((struct lysc_action *)target)->output_exts, lysc_ext_instance_free);
+                ((struct lysc_action *)target)->output_exts = NULL;
             } else {
                 /* remove RPC/action */
                 REMOVE_NONDATA(rpcs, struct lysc_action, lysc_node_actions, lysc_action_free);
@@ -6416,11 +6418,11 @@
 
     /* check min-max compatibility */
     if (target->nodetype == LYS_LEAFLIST) {
-        min = ((struct lysc_node_leaflist*)target)->min;
-        max = ((struct lysc_node_leaflist*)target)->max;
+        min = ((struct lysc_node_leaflist *)target)->min;
+        max = ((struct lysc_node_leaflist *)target)->max;
     } else if (target->nodetype == LYS_LIST) {
-        min = ((struct lysc_node_list*)target)->min;
-        max = ((struct lysc_node_list*)target)->max;
+        min = ((struct lysc_node_list *)target)->min;
+        max = ((struct lysc_node_list *)target)->max;
     } else {
         min = max = 0;
     }
@@ -6436,7 +6438,7 @@
         leaf->dflt->realtype = leaf->type;
         rc = leaf->type->plugin->store(ctx->ctx, leaf->type, dflt, strlen(dflt),
                                         LY_TYPE_OPTS_INCOMPLETE_DATA | LY_TYPE_OPTS_SCHEMA | LY_TYPE_OPTS_STORE,
-                                        lys_resolve_prefix, (void*)leaf->dflt_mod, LYD_XML, target, NULL, leaf->dflt, NULL, &err);
+                                        LY_PREF_SCHEMA, leaf->dflt_mod, target, NULL, leaf->dflt, NULL, &err);
         leaf->dflt->realtype->refcount++;
         if (err) {
             ly_err_print(err);
@@ -6456,7 +6458,7 @@
         /* the leaf/leaf-list's type has changed, but there is still a default value for the previous type */
         int dynamic;
         if (target->nodetype == LYS_LEAF) {
-            dflt = leaf->dflt->realtype->plugin->print(leaf->dflt, LYD_XML, lys_get_prefix, leaf->dflt_mod, &dynamic);
+            dflt = leaf->dflt->realtype->plugin->print(leaf->dflt, LY_PREF_SCHEMA, leaf->dflt_mod, &dynamic);
 
             /* update the list of incomplete default values if needed */
             lysc_incomplete_dflts_remove(ctx, leaf->dflt);
@@ -6467,7 +6469,7 @@
             leaf->dflt->realtype = leaf->type;
             rc = leaf->type->plugin->store(ctx->ctx, leaf->type, dflt, strlen(dflt),
                                             LY_TYPE_OPTS_INCOMPLETE_DATA | LY_TYPE_OPTS_SCHEMA | LY_TYPE_OPTS_STORE,
-                                            lys_resolve_prefix, (void*)leaf->dflt_mod, LYD_XML, target, NULL, leaf->dflt, NULL, &err);
+                                            LY_PREF_SCHEMA, leaf->dflt_mod, target, NULL, leaf->dflt, NULL, &err);
             leaf->dflt->realtype->refcount++;
             if (err) {
                 ly_err_print(err);
@@ -6489,14 +6491,13 @@
             LY_CHECK_GOTO(rc, cleanup);
         } else { /* LYS_LEAFLIST */
             LY_ARRAY_FOR(llist->dflts, x) {
-                dflt = llist->dflts[x]->realtype->plugin->print(llist->dflts[x], LYD_XML, lys_get_prefix, llist->dflts_mods[x], &dynamic);
+                dflt = llist->dflts[x]->realtype->plugin->print(llist->dflts[x], LY_PREF_SCHEMA, llist->dflts_mods[x], &dynamic);
                 llist->dflts[x]->realtype->plugin->free(ctx->ctx, llist->dflts[x]);
                 lysc_type_free(ctx->ctx, llist->dflts[x]->realtype);
                 llist->dflts[x]->realtype = llist->type;
                 rc = llist->type->plugin->store(ctx->ctx, llist->type, dflt, strlen(dflt),
                                                 LY_TYPE_OPTS_INCOMPLETE_DATA | LY_TYPE_OPTS_SCHEMA | LY_TYPE_OPTS_STORE,
-                                                lys_resolve_prefix, (void*)llist->dflts_mods[x], LYD_XML, target, NULL,
-                                                llist->dflts[x], NULL, &err);
+                                                LY_PREF_SCHEMA, llist->dflts_mods[x], target, NULL, llist->dflts[x], NULL, &err);
                 llist->dflts[x]->realtype->refcount++;
                 if (err) {
                     ly_err_print(err);
@@ -6527,7 +6528,7 @@
         LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
                 "Invalid deviation combining default value and mandatory %s.", lys_nodetype2str(target->nodetype));
         goto cleanup;
-    } else if ((target->nodetype & LYS_CHOICE) && ((struct lysc_node_choice*)target)->dflt
+    } else if ((target->nodetype & LYS_CHOICE) && ((struct lysc_node_choice* )target)->dflt
             && (target->flags & LYS_MAND_TRUE)) {
         LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS, "Invalid deviation combining default case and mandatory choice.");
         goto cleanup;
@@ -6897,7 +6898,7 @@
         do {
             LY_ARRAY_FOR(node->when, u) {
                 when = node->when[u];
-                ret = lyxp_atomize(when->cond, LYD_SCHEMA, when->module, when->context,
+                ret = lyxp_atomize(when->cond, LY_PREF_SCHEMA, when->module, when->context,
                                 when->context ? LYXP_NODE_ELEM : LYXP_NODE_ROOT_CONFIG, &tmp_set, LYXP_SCNODE_SCHEMA);
                 if (ret != LY_SUCCESS) {
                     LOGVAL(set->ctx, LY_VLOG_LYSC, node, LYVE_SEMANTICS, "Invalid when condition \"%s\".", when->cond->expr);
@@ -7011,7 +7012,7 @@
 
     /* check "when" */
     LY_ARRAY_FOR(when, u) {
-        ret = lyxp_atomize(when[u]->cond, LYD_SCHEMA, when[u]->module, when[u]->context ? when[u]->context : node,
+        ret = lyxp_atomize(when[u]->cond, LY_PREF_SCHEMA, when[u]->module, when[u]->context ? when[u]->context : node,
                            when[u]->context ? LYXP_NODE_ELEM : LYXP_NODE_ROOT_CONFIG, &tmp_set, opts);
         if (ret != LY_SUCCESS) {
             LOGVAL(ctx->ctx, LY_VLOG_LYSC, node, LYVE_SEMANTICS, "Invalid when condition \"%s\".", when[u]->cond->expr);
@@ -7049,7 +7050,7 @@
 check_musts:
     /* check "must" */
     LY_ARRAY_FOR(musts, u) {
-        ret = lyxp_atomize(musts[u].cond, LYD_SCHEMA, musts[u].module, node, LYXP_NODE_ELEM, &tmp_set, opts);
+        ret = lyxp_atomize(musts[u].cond, LY_PREF_SCHEMA, musts[u].module, node, LYXP_NODE_ELEM, &tmp_set, opts);
         if (ret != LY_SUCCESS) {
             LOGVAL(ctx->ctx, LY_VLOG_LYSC, node, LYVE_SEMANTICS, "Invalid must restriction \"%s\".", musts[u].cond->expr);
             goto cleanup;
@@ -7095,7 +7096,7 @@
     /* try to find the target */
     LY_CHECK_RET(ly_path_compile(ctx->ctx, node->module, node, lref->path, LY_PATH_LREF_TRUE,
                                  lysc_is_output(node) ? LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT, LY_PATH_TARGET_MANY,
-                                 lys_resolve_prefix, lref->path_context, LYD_SCHEMA, &p));
+                                 LY_PREF_SCHEMA, lref->path_context, &p));
 
     /* get the target node */
     target = p[LY_ARRAY_COUNT(p) - 1].node;
@@ -7246,8 +7247,8 @@
         struct lysc_incomplete_dflt *r = ctx->dflts.objs[i];
         LY_ERR ret;
         ret = r->dflt->realtype->plugin->store(ctx->ctx, r->dflt->realtype, r->dflt->original, strlen(r->dflt->original),
-                                               LY_TYPE_OPTS_SCHEMA | LY_TYPE_OPTS_STORE | LY_TYPE_OPTS_SECOND_CALL, lys_resolve_prefix,
-                                               (void*)r->dflt_mod, LYD_XML, r->context_node, NULL, r->dflt, NULL, &err);
+                                               LY_TYPE_OPTS_SCHEMA | LY_TYPE_OPTS_STORE | LY_TYPE_OPTS_SECOND_CALL,
+                                               LY_PREF_SCHEMA, r->dflt_mod, r->context_node, NULL, r->dflt, NULL, &err);
         if (err) {
             ly_err_print(err);
             ctx->path[0] = '\0';
diff --git a/src/tree_schema_helpers.c b/src/tree_schema_helpers.c
index d6c92da..8500b55 100644
--- a/src/tree_schema_helpers.c
+++ b/src/tree_schema_helpers.c
@@ -1634,46 +1634,6 @@
     return LY_ARRAY_COUNT(ext);
 }
 
-/**
- * @brief Schema mapping of YANG modules to prefixes in values.
- *
- * Implementation of ly_get_prefix_clb. Inverse function to lys_resolve_prefix.
- *
- * In this case the @p mod is searched in the list of imports and the import's prefix
- * (not the module's itself) prefix is returned.
- */
-const char *
-lys_get_prefix(const struct lys_module *mod, void *private)
-{
-    struct lys_module *context_mod = (struct lys_module*)private;
-    LY_ARRAY_COUNT_TYPE u;
-
-    if (context_mod == mod) {
-        return context_mod->prefix;
-    }
-    LY_ARRAY_FOR(context_mod->parsed->imports, u) {
-        if (context_mod->parsed->imports[u].module == mod) {
-            /* match */
-            return context_mod->parsed->imports[u].prefix;
-        }
-    }
-
-    return NULL;
-}
-
-/**
- * @brief Schema mapping of prefix in values to YANG modules (imports).
- *
- * Implementation of ly_resolve_prefix_clb. Inverse function to lys_get_prefix().
- *
- * In this case the @p prefix is searched in the list of imports' prefixes (not the prefixes of the imported modules themselves).
- */
-const struct lys_module *
-lys_resolve_prefix(const struct ly_ctx *UNUSED(ctx), const char *prefix, size_t prefix_len, void *private)
-{
-    return lys_module_find_prefix((const struct lys_module*)private, prefix, prefix_len);
-}
-
 const struct lysc_node *
 lysc_data_parent(const struct lysc_node *schema)
 {
diff --git a/src/tree_schema_internal.h b/src/tree_schema_internal.h
index f6c7958..8e132b9 100644
--- a/src/tree_schema_internal.h
+++ b/src/tree_schema_internal.h
@@ -212,33 +212,6 @@
 LY_ERR lysp_check_identifierchar(struct lys_parser_ctx *ctx, unsigned int c, int first, int *prefix);
 
 /**
- * @brief Internal structure for lys_get_prefix().
- */
-struct lys_get_prefix_data {
-    const struct lys_module *context_mod;
-    struct ly_set prefixes;
-};
-
-/**
- * @brief Schema mapping of YANG modules to prefixes in values.
- *
- * Implementation of ly_get_prefix_clb. Inverse function to lys_resolve_prefix.
- *
- * In this case the @p mod is searched in the list of imports and the import's prefix
- * (not the module's itself) prefix is returned.
- */
-const char *lys_get_prefix(const struct lys_module *mod, void *private);
-
-/**
- * @brief Schema mapping of prefix in values to YANG modules (imports).
- *
- * Implementation of ly_resolve_prefix_clb. Inverse function to lys_get_prefix().
- *
- * In this case the @p prefix is searched in the list of imports' prefixes (not the prefixes of the imported modules themselves).
- */
-const struct lys_module *lys_resolve_prefix(const struct ly_ctx *ctx, const char *prefix, size_t prefix_len, void *private);
-
-/**
  * @brief Check the currently present prefixes in the module for collision with the new one.
  *
  * @param[in] ctx Context for logging.
diff --git a/src/validation.c b/src/validation.c
index 65c64e7..f278cc6 100644
--- a/src/validation.c
+++ b/src/validation.c
@@ -77,7 +77,7 @@
     }
 
     /* evaluate when */
-    ret = lyxp_eval(when->cond, LYD_SCHEMA, when->module, ctx_node, ctx_node ? LYXP_NODE_ELEM : LYXP_NODE_ROOT_CONFIG,
+    ret = lyxp_eval(when->cond, LY_PREF_SCHEMA, when->module, ctx_node, ctx_node ? LYXP_NODE_ELEM : LYXP_NODE_ROOT_CONFIG,
                     *tree, &xp_set, LYXP_SCHEMA);
     lyxp_set_cast(&xp_set, LYXP_SET_BOOLEAN);
 
@@ -111,7 +111,7 @@
 
 LY_ERR
 lyd_validate_unres(struct lyd_node **tree, struct ly_set *node_when, struct ly_set *node_types, struct ly_set *meta_types,
-                   LYD_FORMAT format, ly_resolve_prefix_clb get_prefix_clb, void *parser_data, struct lyd_node **diff)
+                   LY_PREFIX_FORMAT format, void *prefix_data, struct lyd_node **diff)
 {
     LY_ERR ret = LY_SUCCESS;
     uint32_t i;
@@ -172,8 +172,8 @@
             struct lyd_node_term *node = (struct lyd_node_term *)node_types->objs[i];
 
             /* validate and store the value of the node */
-            ret = lyd_value_parse(node, node->value.original, strlen(node->value.original), 0, 1, 0, get_prefix_clb,
-                                  parser_data, format, *tree);
+            ret = lyd_value_parse(node, node->value.original, strlen(node->value.original), 0, 1, 0, format,
+                                  prefix_data, *tree);
             LY_CHECK_RET(ret);
 
             /* remove this node from the set */
@@ -191,7 +191,7 @@
 
             /* validate and store the value of the metadata */
             ret = lyd_value_parse_meta(meta->parent->schema->module->ctx, meta, meta->value.original,
-                                       strlen(meta->value.original), 0, 1, 0, get_prefix_clb, parser_data, format, NULL, *tree);
+                                       strlen(meta->value.original), 0, 1, 0, format, prefix_data, NULL, *tree);
             LY_CHECK_RET(ret);
 
             /* remove this attr from the set */
@@ -741,7 +741,7 @@
                     }
 
                     /* get canonical string value */
-                    str = val->realtype->plugin->print(val, LYD_JSON, json_print_get_prefix, NULL, &dynamic);
+                    str = val->realtype->plugin->print(val, LY_PREF_JSON, NULL, &dynamic);
                     hash = dict_hash_multi(hash, str, strlen(str));
                     if (dynamic) {
                         free((char *)str);
@@ -928,7 +928,8 @@
         memset(&xp_set, 0, sizeof xp_set);
 
         /* evaluate must */
-        LY_CHECK_RET(lyxp_eval(musts[u].cond, LYD_SCHEMA, musts[u].module, node, LYXP_NODE_ELEM, tree, &xp_set, LYXP_SCHEMA));
+        LY_CHECK_RET(lyxp_eval(musts[u].cond, LY_PREF_SCHEMA, musts[u].module, node, LYXP_NODE_ELEM, tree, &xp_set,
+                               LYXP_SCHEMA));
 
         /* check the result */
         lyxp_set_cast(&xp_set, LYXP_SET_BOOLEAN);
@@ -1122,8 +1123,7 @@
         }
 
         /* finish incompletely validated terminal values/attributes and when conditions */
-        ret = lyd_validate_unres(tree, &when_check, &type_check, &type_meta_check, LYD_JSON, lydjson_resolve_prefix,
-                                 NULL, diff);
+        ret = lyd_validate_unres(tree, &when_check, &type_check, &type_meta_check, LY_PREF_JSON, NULL, diff);
         LY_CHECK_GOTO(ret, cleanup);
 
         /* perform final validation that assumes the data tree is final */
@@ -1254,7 +1254,7 @@
 
     /* finish incompletely validated terminal values/attributes and when conditions on the full tree */
     LY_CHECK_GOTO(ret = lyd_validate_unres((struct lyd_node **)&tree, &when_check, &type_check, &type_meta_check,
-                                           LYD_JSON, lydjson_resolve_prefix, NULL, diff), cleanup);
+                                           LY_PREF_JSON, NULL, diff), cleanup);
 
     /* perform final validation of the operation/notification */
     lyd_validate_obsolete(op_node);
diff --git a/src/validation.h b/src/validation.h
index 8b23e6f..f3404df 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -42,13 +42,12 @@
  * @param[in] node_types Set with nodes with unresolved types, can be NULL
  * @param[in] meta_types Set with metdata with unresolved types, can be NULL.
  * @param[in] format Format of the unresolved data.
- * @param[in] get_prefix_clb Format-specific getter to resolve prefixes.
- * @param[in] parser_data Parser's data for @p get_prefix_clb.
+ * @param[in] prefix_data Format-specific data for resolving any prefixes (see ::ly_resolve_prefix).
  * @param[in,out] diff Validation diff.
  * @return LY_ERR value.
  */
 LY_ERR lyd_validate_unres(struct lyd_node **tree, struct ly_set *node_when, struct ly_set *node_types, struct ly_set *meta_types,
-                          LYD_FORMAT format, ly_resolve_prefix_clb get_prefix_clb, void *parser_data, struct lyd_node **diff);
+                          LY_PREFIX_FORMAT format, void *prefix_data, struct lyd_node **diff);
 
 /**
  * @brief Validate new siblings. Specifically, check duplicated instances, autodelete default values and cases.
diff --git a/src/xml.c b/src/xml.c
index a3645c1..a92896c 100644
--- a/src/xml.c
+++ b/src/xml.c
@@ -197,13 +197,13 @@
 }
 
 const struct lyxml_ns *
-lyxml_ns_get(struct lyxml_ctx *xmlctx, const char *prefix, size_t prefix_len)
+lyxml_ns_get(const struct ly_set *ns_set, const char *prefix, size_t prefix_len)
 {
     unsigned int u;
     struct lyxml_ns *ns;
 
-    for (u = xmlctx->ns.count - 1; u + 1 > 0; --u) {
-        ns = (struct lyxml_ns *)xmlctx->ns.objs[u];
+    for (u = ns_set->count - 1; u + 1 > 0; --u) {
+        ns = (struct lyxml_ns *)ns_set->objs[u];
         if (prefix && prefix_len) {
             if (ns->prefix && !ly_strncmp(ns->prefix, prefix, prefix_len)) {
                 return ns;
@@ -1097,7 +1097,7 @@
             if (*stop == ':') {
                 /* we have a possible prefix */
                 len = stop - start;
-                ns = lyxml_ns_get(xmlctx, start, len);
+                ns = lyxml_ns_get(&xmlctx->ns, start, len);
                 if (ns) {
                     struct ly_prefix *p = NULL;
 
diff --git a/src/xml.h b/src/xml.h
index fef0bb5..cfc2d92 100644
--- a/src/xml.h
+++ b/src/xml.h
@@ -136,14 +136,14 @@
 /**
  * @brief Get a namespace record for the given prefix in the current context.
  *
- * @param[in] xmlctx XML context to work with.
+ * @param[in] ns_set Set with namespaces from the XML context.
  * @param[in] prefix Pointer to the namespace prefix as taken from lyxml_get_attribute() or lyxml_get_element().
  * Can be NULL for default namespace.
  * @param[in] prefix_len Length of the prefix string (since it is not NULL-terminated when returned from lyxml_get_attribute() or
  * lyxml_get_element()).
  * @return The namespace record or NULL if the record for the specified prefix not found.
  */
-const struct lyxml_ns *lyxml_ns_get(struct lyxml_ctx *xmlctx, const char *prefix, size_t prefix_len);
+const struct lyxml_ns *lyxml_ns_get(const struct ly_set *ns_set, const char *prefix, size_t prefix_len);
 
 /**
  * @brief Print the given @p text as XML string which replaces some of the characters which cannot appear in XML data.
diff --git a/src/xpath.c b/src/xpath.c
index b0a3d1b..a7ba0c0 100644
--- a/src/xpath.c
+++ b/src/xpath.c
@@ -1566,8 +1566,8 @@
 
     /* ignore errors, the value may not satisfy schema constraints */
     rc = type->plugin->store(src->ctx, type, str, strlen(str),
-                             LY_TYPE_OPTS_STORE | LY_TYPE_OPTS_INCOMPLETE_DATA | LY_TYPE_OPTS_DYNAMIC, NULL,
-                             NULL, LYD_JSON, NULL, NULL, &val, NULL, &err);
+                             LY_TYPE_OPTS_STORE | LY_TYPE_OPTS_INCOMPLETE_DATA | LY_TYPE_OPTS_DYNAMIC, LY_PREF_JSON,
+                             NULL, NULL, NULL, &val, NULL, &err);
     ly_err_free(err);
     if (rc) {
         /* invalid value */
@@ -1576,7 +1576,7 @@
     }
 
     /* storing successful, now print the canonical value */
-    str = (char *)type->plugin->print(&val, LYD_JSON, json_print_get_prefix, NULL, &dynamic);
+    str = (char *)type->plugin->print(&val, LY_PREF_JSON, NULL, &dynamic);
 
     /* use the canonized value */
     set_init(trg, src);
@@ -3333,8 +3333,8 @@
 
         type = ((struct lysc_node_leaf *)scnode)->type;
         if (type->basetype != LY_TYPE_IDENT) {
-            rc = type->plugin->store(set->ctx, type, value, strlen(value), LY_TYPE_OPTS_SCHEMA, lys_resolve_prefix,
-                                     (void *)set->local_mod, LYD_XML, NULL, NULL, NULL, NULL, &err);
+            rc = type->plugin->store(set->ctx, type, value, strlen(value), LY_TYPE_OPTS_SCHEMA, LY_PREF_SCHEMA,
+                                     (void *)set->local_mod, NULL, NULL, NULL, NULL, &err);
 
             if (err) {
                 LOGWRN(set->ctx, "Invalid value \"%s\" which does not fit the type (%s).", value, err->msg);
@@ -3697,14 +3697,8 @@
             oper = lysc_is_output((struct lysc_node *)sleaf) ? LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT;
 
             /* it was already evaluated on schema, it must succeed */
-            if (set->format == LYD_JSON) {
-                rc = ly_path_compile(set->ctx, sleaf->module, (struct lysc_node *)sleaf, lref->path, LY_PATH_LREF_TRUE,
-                                     oper, LY_PATH_TARGET_MANY, lydjson_resolve_prefix, NULL, LYD_JSON, &p);
-            } else {
-                assert(set->format == LYD_SCHEMA);
-                rc = ly_path_compile(set->ctx, sleaf->module, (struct lysc_node *)sleaf, lref->path, LY_PATH_LREF_TRUE,
-                                     oper, LY_PATH_TARGET_MANY, lys_resolve_prefix, lref->path_context, LYD_SCHEMA, &p);
-            }
+            rc = ly_path_compile(set->ctx, sleaf->module, (struct lysc_node *)sleaf, lref->path, LY_PATH_LREF_TRUE,
+                                 oper, LY_PATH_TARGET_MANY, set->format, lref->path_context, &p);
             assert(!rc);
 
             /* get the target node */
@@ -3816,8 +3810,8 @@
 
             /* store args[1] as ident */
             rc = val->realtype->plugin->store(set->ctx, val->realtype, args[1]->val.str, strlen(args[1]->val.str),
-                                              LY_TYPE_OPTS_STORE, lys_resolve_prefix, (void *)set->local_mod,
-                                              set->format, (struct lyd_node *)leaf, set->tree, &data, NULL, &err);
+                                              LY_TYPE_OPTS_STORE, set->format, (void *)set->local_mod,
+                                              (struct lyd_node *)leaf, set->tree, &data, NULL, &err);
         } else {
             meta = args[0]->val.meta[i].meta;
             val = &meta->value;
@@ -3828,8 +3822,8 @@
 
             /* store args[1] as ident */
             rc = val->realtype->plugin->store(set->ctx, val->realtype, args[1]->val.str, strlen(args[1]->val.str),
-                                              LY_TYPE_OPTS_STORE, lys_resolve_prefix, (void *)meta->annotation->module,
-                                              set->format, meta->parent, set->tree, &data, NULL, &err);
+                                              LY_TYPE_OPTS_STORE, set->format, (void *)meta->annotation->module,
+                                              meta->parent, set->tree, &data, NULL, &err);
         }
 
         if (err) {
@@ -4257,14 +4251,13 @@
 
     if (mod && name) {
         switch (set->format) {
-        case LYD_SCHEMA:
+        case LY_PREF_SCHEMA:
             rc = asprintf(&str, "%s:%s", lys_prefix_find_module(set->local_mod, mod), name);
             break;
-        case LYD_JSON:
+        case LY_PREF_JSON:
             rc = asprintf(&str, "%s:%s", mod->name, name);
             break;
-        case LYD_XML:
-        case LYD_LYB:
+        case LY_PREF_XML:
             LOGINT_RET(set->ctx);
         }
         LY_CHECK_ERR_RET(rc == -1, LOGMEM(set->ctx), LY_EMEM);
@@ -5286,20 +5279,7 @@
     if ((ptr = ly_strnchr(*qname, ':', *qname_len))) {
         /* specific module */
         pref_len = ptr - *qname;
-
-        switch (set->format) {
-        case LYD_SCHEMA:
-            /* schema, search all local module imports */
-            mod = lys_module_find_prefix(set->local_mod, *qname, pref_len);
-            break;
-        case LYD_JSON:
-            /* JSON data, search in context */
-            mod = ly_ctx_get_module_implemented2(set->ctx, *qname, pref_len);
-            break;
-        case LYD_XML:
-        case LYD_LYB:
-            LOGINT_RET(set->ctx);
-        }
+        mod = ly_resolve_prefix(set->ctx, *qname, pref_len, set->format, (void *)set->local_mod);
 
         /* check for errors and non-implemented modules, as they are not valid */
         if (!mod || !mod->implemented) {
@@ -6876,7 +6856,8 @@
  */
 static LY_ERR
 eval_name_test_try_compile_predicates(struct lyxp_expr *exp, uint16_t *tok_idx, const struct lysc_node *scnode,
-                                      LYD_FORMAT format, struct ly_path_predicate **predicates, enum ly_path_pred_type *pred_type)
+                                      LY_PREFIX_FORMAT format, struct ly_path_predicate **predicates,
+                                      enum ly_path_pred_type *pred_type)
 {
     LY_ERR ret = LY_SUCCESS;
     uint16_t key_count, e_idx, pred_idx = 0;
@@ -6941,20 +6922,8 @@
                                                 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_SIMPLE, &exp2), cleanup);
 
     /* compile */
-    switch (format) {
-    case LYD_SCHEMA:
-        ret = ly_path_compile_predicate(scnode->module->ctx, scnode, scnode->module, scnode, exp2, &pred_idx,
-                                        lys_resolve_prefix, scnode->module, LYD_SCHEMA, predicates, pred_type);
-        break;
-    case LYD_JSON:
-        ret = ly_path_compile_predicate(scnode->module->ctx, scnode, scnode->module, scnode, exp2, &pred_idx,
-                                        lydjson_resolve_prefix, NULL, LYD_JSON, predicates, pred_type);
-        break;
-    case LYD_XML:
-    case LYD_LYB:
-        ret = LY_EINT;
-        goto cleanup;
-    }
+    ret = ly_path_compile_predicate(scnode->module->ctx, scnode, scnode->module, scnode, exp2, &pred_idx,
+                                    format, scnode->module, predicates, pred_type);
     LY_CHECK_GOTO(ret, cleanup);
 
     /* success, the predicate must include all the needed information for hash-based search */
@@ -8366,7 +8335,7 @@
 }
 
 LY_ERR
-lyxp_eval(struct lyxp_expr *exp, LYD_FORMAT format, const struct lys_module *local_mod, const struct lyd_node *ctx_node,
+lyxp_eval(struct lyxp_expr *exp, LY_PREFIX_FORMAT format, const struct lys_module *local_mod, const struct lyd_node *ctx_node,
           enum lyxp_node_type ctx_node_type, const struct lyd_node *tree, struct lyxp_set *set, int options)
 {
     uint16_t tok_idx = 0;
@@ -8635,8 +8604,8 @@
 }
 
 LY_ERR
-lyxp_atomize(struct lyxp_expr *exp, LYD_FORMAT format, const struct lys_module *local_mod, const struct lysc_node *ctx_scnode,
-             enum lyxp_node_type ctx_scnode_type, struct lyxp_set *set, int options)
+lyxp_atomize(struct lyxp_expr *exp, LY_PREFIX_FORMAT format, const struct lys_module *local_mod,
+             const struct lysc_node *ctx_scnode, enum lyxp_node_type ctx_scnode_type, struct lyxp_set *set, int options)
 {
     struct ly_ctx *ctx;
     const struct lysc_node *real_ctx_scnode;
diff --git a/src/xpath.h b/src/xpath.h
index a79ea82..a5ea377 100644
--- a/src/xpath.h
+++ b/src/xpath.h
@@ -20,6 +20,7 @@
 
 #include "config.h"
 #include "log.h"
+#include "plugins_types.h"
 #include "tree_schema.h"
 
 struct ly_ctx;
@@ -259,7 +260,7 @@
     const struct lysc_node *context_op;
     const struct lys_module *local_mod;
     const struct lyd_node *tree;
-    LYD_FORMAT format;
+    LY_PREFIX_FORMAT format;
 };
 
 /**
@@ -289,8 +290,9 @@
  * @return LY_EINCOMPLETE for unresolved when,
  * @return LY_EINVAL, LY_EMEM, LY_EINT for other errors.
  */
-LY_ERR lyxp_eval(struct lyxp_expr *exp, LYD_FORMAT format, const struct lys_module *local_mod, const struct lyd_node *ctx_node,
-                 enum lyxp_node_type ctx_node_type, const struct lyd_node *tree, struct lyxp_set *set, int options);
+LY_ERR lyxp_eval(struct lyxp_expr *exp, LY_PREFIX_FORMAT format, const struct lys_module *local_mod,
+                 const struct lyd_node *ctx_node, enum lyxp_node_type ctx_node_type, const struct lyd_node *tree,
+                 struct lyxp_set *set, int options);
 
 #define LYXP_SCHEMA 0x01        /**< Apply data node access restrictions defined for 'when' and 'must' evaluation. */
 
@@ -308,8 +310,9 @@
  * @param[in] options Whether to apply some evaluation restrictions, one flag must always be used.
  * @return LY_ERR (same as lyxp_eval()).
  */
-LY_ERR lyxp_atomize(struct lyxp_expr *exp, LYD_FORMAT format, const struct lys_module *local_mod, const struct lysc_node *ctx_scnode,
-                    enum lyxp_node_type ctx_scnode_type, struct lyxp_set *set, int options);
+LY_ERR lyxp_atomize(struct lyxp_expr *exp, LY_PREFIX_FORMAT format, const struct lys_module *local_mod,
+                    const struct lysc_node *ctx_scnode, enum lyxp_node_type ctx_scnode_type, struct lyxp_set *set,
+                    int options);
 
 /* used only internally */
 #define LYXP_SCNODE_ALL 0x0E