types CHANGE redesign storing canonical values

Canonical values are not available for all the types and the type's
printer should be used to get string representation instead of trying to
get string value directly from the lyd_value. So, the canonical value is
now much more hidden in lyd_value structure. On the other hand, there is
newly available original string representation of the value (some of the
types already needed it), which is always present no matter of the
value's type.
diff --git a/Doxyfile.in b/Doxyfile.in
index 2288465..869013f 100644
--- a/Doxyfile.in
+++ b/Doxyfile.in
@@ -785,6 +785,7 @@
 			 ./src/context.h \
 			 ./src/tree.h \
                          ./src/tree_schema.h \
+                         ./src/plugins_types.h \
                          ./src/plugins_exts.h \
                          ./src/tree_data.h \
                          ./src/log.h \
diff --git a/src/libyang.h b/src/libyang.h
index 26fa65d..eba8008 100644
--- a/src/libyang.h
+++ b/src/libyang.h
@@ -118,6 +118,17 @@
  * The lists are structures connected via a `next` pointer. Iterating over the siblings can be simply done by ::LY_LIST_FOR macro.
  */
 
+/**
+ * @page howtoplugins Plugins
+ *
+ * libyang supports several types of plugins to better support generic features of YANG that need some specific code for
+ * their specific instances in YANG schemas. This is the case of YANG types, which are derived from YANG built-in types
+ * (which are implemented by libyang), but the description of the derived type can specify some additional requirements or
+ * restriction that cannot be implemented generically and some special code is needed. The second case for libyang plugins
+ * are YANG extensions. For YANG extensions, most of the specification stays in their description (e.g. allowed substatements
+ * or place of the extension instanciation) and libyang is not able to process such a text in a generic way. In both cases,
+ * libyang provides API to provide functionality implementing the specifics of each type or extension.
+ */
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/parser_xml.c b/src/parser_xml.c
index d967fe9..e0a0623 100644
--- a/src/parser_xml.c
+++ b/src/parser_xml.c
@@ -570,7 +570,7 @@
                 result_trees = lyd_trees_new(1, *result);
             }
             /* validate and store the value of the node */
-            ret = lyd_value_parse(node, node->value.canonized, node->value.canonized ? strlen(node->value.canonized) : 0, 0, 1,
+            ret = lyd_value_parse(node, node->value.original, strlen(node->value.original), 0, 1,
                                   lydxml_resolve_prefix, ctx, LYD_XML, result_trees);
             lyd_trees_free(result_trees, 0);
             if (ret) {
@@ -589,7 +589,7 @@
                 result_trees = lyd_trees_new(1, *result);
             }
             /* validate and store the value of the node */
-            ret = lyd_value_parse_attr(attr, attr->value.canonized, attr->value.canonized ? strlen(attr->value.canonized) : 0, 0, 1,
+            ret = lyd_value_parse_attr(attr, attr->value.original, strlen(attr->value.original), 0, 1,
                                        lydxml_resolve_prefix, ctx, LYD_XML, result_trees);
             lyd_trees_free(result_trees, 0);
             if (ret) {
diff --git a/src/plugins_types.c b/src/plugins_types.c
index bae918b..78047a3 100644
--- a/src/plugins_types.c
+++ b/src/plugins_types.c
@@ -37,7 +37,7 @@
 static LY_ERR
 ly_type_compare_canonical(const struct lyd_value *val1, const struct lyd_value *val2)
 {
-    if (val1 == val2 || !strcmp(val1->canonized, val2->canonized)) {
+    if (val1 == val2 || !strcmp(val1->canonical_cache, val2->canonical_cache)) {
         return LY_SUCCESS;
     }
 
@@ -54,19 +54,37 @@
                         ly_clb_get_prefix UNUSED(get_prefix), void *UNUSED(printer), int *dynamic)
 {
     *dynamic = 0;
-    return (char*)value->canonized;
+    return (char*)value->canonical_cache;
 }
 
 /**
- * @brief Generic duplication callback of the canonized value only.
+ * @brief Generic duplication callback of the original value only.
+ *
+ * Implementation of the ly_type_dup_clb.
+ */
+static LY_ERR
+ly_type_dup_original(struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
+{
+    dup->canonical_cache = original->canonical_cache;
+    dup->original = (void*)lydict_insert(ctx, original->original, strlen(original->original));
+    if (dup->original) {
+        return LY_SUCCESS;
+    } else {
+        return LY_EINT;
+    }
+}
+
+/**
+ * @brief Generic duplication callback of the canonized and original values only.
  *
  * Implementation of the ly_type_dup_clb.
  */
 static LY_ERR
 ly_type_dup_canonical(struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
 {
-    dup->canonized = lydict_insert(ctx, original->canonized, strlen(original->canonized));
-    if (dup->canonized) {
+    ly_type_dup_original(ctx, original, dup);
+    dup->canonical_cache = (void*)lydict_insert(ctx, original->canonical_cache, strlen(original->canonical_cache));
+    if (dup->canonical_cache) {
         return LY_SUCCESS;
     } else {
         return LY_EINT;
@@ -74,6 +92,18 @@
 }
 
 /**
+ * @brief Free original value in lyd_value.
+ *
+ * Implementation of the ly_type_free_clb.
+ */
+static void
+ly_type_free_original(struct ly_ctx *ctx, struct lyd_value *value)
+{
+    lydict_remove(ctx, value->original);
+    value->original = NULL;
+}
+
+/**
  * @brief Free canonized value in lyd_value.
  *
  * Implementation of the ly_type_free_clb.
@@ -81,8 +111,9 @@
 static void
 ly_type_free_canonical(struct ly_ctx *ctx, struct lyd_value *value)
 {
-    lydict_remove(ctx, value->canonized);
-    value->canonized = NULL;
+    ly_type_free_original(ctx, value);
+    lydict_remove(ctx, value->canonical_cache);
+    value->canonical_cache = NULL;
 }
 
 API LY_ERR
@@ -349,7 +380,7 @@
 }
 
 API LY_ERR
-ly_type_validate_range(LY_DATA_TYPE basetype, struct lysc_range *range, int64_t value, const char *canonized, struct ly_err_item **err)
+ly_type_validate_range(LY_DATA_TYPE basetype, struct lysc_range *range, int64_t value, const char *strval, struct ly_err_item **err)
 {
     unsigned int u;
     char *errmsg = NULL;
@@ -362,7 +393,7 @@
                     errmsg = strdup(range->emsg);
                 } else {
                     asprintf(&errmsg, "%s \"%s\" does not satisfy the %s constraint.",
-                           (basetype == LY_TYPE_BINARY || basetype == LY_TYPE_STRING) ? "Length" : "Value", canonized,
+                           (basetype == LY_TYPE_BINARY || basetype == LY_TYPE_STRING) ? "Length" : "Value", strval,
                            (basetype == LY_TYPE_BINARY || basetype == LY_TYPE_STRING) ? "length" : "range");
                 }
                 goto error;
@@ -375,7 +406,7 @@
                     errmsg = strdup(range->emsg);
                 } else {
                     asprintf(&errmsg, "%s \"%s\" does not satisfy the %s constraint.",
-                           (basetype == LY_TYPE_BINARY || basetype == LY_TYPE_STRING) ? "Length" : "Value", canonized,
+                           (basetype == LY_TYPE_BINARY || basetype == LY_TYPE_STRING) ? "Length" : "Value", strval,
                            (basetype == LY_TYPE_BINARY || basetype == LY_TYPE_STRING) ? "length" : "range");
                 }
                 goto error;
@@ -386,7 +417,7 @@
                 if (range->emsg) {
                     errmsg = strdup(range->emsg);
                 } else {
-                    asprintf(&errmsg, "Value \"%s\" does not satisfy the range constraint.", canonized);
+                    asprintf(&errmsg, "Value \"%s\" does not satisfy the range constraint.", strval);
                 }
                 goto error;
             } else if (value < range->parts[u].max_64) {
@@ -397,7 +428,7 @@
                 if (range->emsg) {
                     errmsg = strdup(range->emsg);
                 } else {
-                    asprintf(&errmsg, "Value \"%s\" does not satisfy the range constraint.", canonized);
+                    asprintf(&errmsg, "Value \"%s\" does not satisfy the range constraint.", strval);
                 }
                 goto error;
             }
@@ -412,23 +443,39 @@
 }
 
 static void
-ly_type_store_canonized(struct ly_ctx *ctx, int options, const char *value, struct lyd_value *storage, const char **canonized)
+ly_type_store_strval(struct ly_ctx *ctx, int options, const char *orig, const char *value,
+                     struct lyd_value *storage, const char **canonized)
 {
     if (options & LY_TYPE_OPTS_CANONIZE) {
-store_canonized:
         *canonized = value;
     }
-    if ((options & LY_TYPE_OPTS_STORE) && !storage->canonized) {
+    if (options & LY_TYPE_OPTS_STORE) {
+        storage->original = orig;
         if (options & LY_TYPE_OPTS_CANONIZE) {
-            /* already stored outside the storage */
-            storage->canonized = lydict_insert(ctx, value, strlen(value));
+            /* already stored outside the storage in canonized, so we have to add instance in dictionary */
+            storage->canonical_cache = (void*)lydict_insert(ctx, value, strlen(value));
         } else {
-            canonized = &storage->canonized;
-            goto store_canonized;
+            storage->canonical_cache = (void*)value;
         }
     }
 }
-
+#if 0
+static void
+ly_type_store_canonized(struct ly_ctx *ctx, int options, const char *value, struct lyd_value *storage, const char **canonized)
+{
+    if (options & LY_TYPE_OPTS_CANONIZE) {
+        *canonized = value;
+    }
+    if (options & LY_TYPE_OPTS_STORE) {
+        if (options & LY_TYPE_OPTS_CANONIZE) {
+            /* already stored outside the storage in canonized, so we have to add instance in dictionary */
+            storage->canonical_cache = (void*)lydict_insert(ctx, value, strlen(value));
+        } else {
+            storage->canonical_cache = (void*)value;
+        }
+    }
+}
+#endif
 /**
  * @brief Validate, canonize and store value of the YANG built-in signed integer types.
  *
@@ -468,6 +515,7 @@
         LOGINT(NULL);
         return LY_EINVAL;
     }
+
     asprintf(&str, "%"PRId64, i);
 
     /* range of the number */
@@ -476,15 +524,16 @@
     }
 
     if (options & (LY_TYPE_OPTS_CANONIZE | LY_TYPE_OPTS_STORE)) {
-        ly_type_store_canonized(ctx, options, lydict_insert_zc(ctx, str), storage, canonized);
-    } else {
-        free(str);
+        if (options & LY_TYPE_OPTS_STORE) {
+            storage->int64 = i;
+            ly_type_store_strval(ctx, options, lydict_insert(ctx, value_len ? value : "", value_len),
+                                 lydict_insert_zc(ctx, str), storage, canonized);
+        } else {
+            ly_type_store_strval(ctx, options, NULL, lydict_insert_zc(ctx, str), storage, canonized);
+        }
+        str = NULL;
     }
-
-    if (options & LY_TYPE_OPTS_STORE) {
-        storage->int64 = i;
-    }
-
+    free(str);
     if (options & LY_TYPE_OPTS_DYNAMIC) {
         free((char*)value);
     }
@@ -540,6 +589,7 @@
         LOGINT(NULL);
         return LY_EINVAL;
     }
+
     asprintf(&str, "%"PRIu64, u);
 
     /* range of the number */
@@ -548,15 +598,16 @@
     }
 
     if (options & (LY_TYPE_OPTS_CANONIZE | LY_TYPE_OPTS_STORE)) {
-        ly_type_store_canonized(ctx, options, lydict_insert_zc(ctx, str), storage, canonized);
-    } else {
-        free(str);
+        if (options & LY_TYPE_OPTS_STORE) {
+            storage->int64 = u;
+            ly_type_store_strval(ctx, options, lydict_insert(ctx, value_len ? value : "", value_len),
+                                 lydict_insert_zc(ctx, str), storage, canonized);
+        } else {
+            ly_type_store_strval(ctx, options, NULL, lydict_insert_zc(ctx, str), storage, canonized);
+        }
+        str = NULL;
     }
-
-    if (options & LY_TYPE_OPTS_STORE) {
-        storage->uint64 = u;
-    }
-
+    free(str);
     if (options & LY_TYPE_OPTS_DYNAMIC) {
         free((char*)value);
     }
@@ -634,13 +685,14 @@
     }
 
     if (options & (LY_TYPE_OPTS_CANONIZE | LY_TYPE_OPTS_STORE)) {
-        ly_type_store_canonized(ctx, options, lydict_insert(ctx, buf, strlen(buf)), storage, canonized);
+        if (options & LY_TYPE_OPTS_STORE) {
+            storage->dec64 = d;
+            ly_type_store_strval(ctx, options, lydict_insert(ctx, value_len ? value : "", value_len),
+                                 lydict_insert(ctx, buf, strlen(buf)), storage, canonized);
+        } else {
+            ly_type_store_strval(ctx, options, NULL, lydict_insert(ctx, buf, strlen(buf)), storage, canonized);
+        }
     }
-
-    if (options & LY_TYPE_OPTS_STORE) {
-        storage->dec64 = d;
-    }
-
     if (options & LY_TYPE_OPTS_DYNAMIC) {
         free((char*)value);
     }
@@ -739,16 +791,18 @@
     }
 
     if (options & (LY_TYPE_OPTS_CANONIZE | LY_TYPE_OPTS_STORE)) {
+        const char *c;
         if (start != 0 || (value_len && stop != value_len - 1)) {
-            ly_type_store_canonized(ctx, options, lydict_insert_zc(ctx, strndup(&value[start], stop + 1 - start)), storage, canonized);
-        } else if (options & LY_TYPE_OPTS_DYNAMIC) {
-            ly_type_store_canonized(ctx, options, lydict_insert_zc(ctx, (char*)value), storage, canonized);
-            value = NULL;
+            c = lydict_insert_zc(ctx, strndup(&value[start], stop + 1 - start));
         } else {
-            ly_type_store_canonized(ctx, options, lydict_insert(ctx, value_len ? value : "", value_len), storage, canonized);
+            c = lydict_insert(ctx, value_len ? value : "", value_len);
+        }
+        if (options & LY_TYPE_OPTS_STORE) {
+            ly_type_store_strval(ctx, options, lydict_insert(ctx, value_len ? value : "", value_len), c, storage, canonized);
+        } else {
+            ly_type_store_strval(ctx, options, NULL, c, storage, canonized);
         }
     }
-
     if (options & LY_TYPE_OPTS_DYNAMIC) {
         free((char*)value);
     }
@@ -793,14 +847,12 @@
     LY_CHECK_RET(ly_type_validate_patterns(type_str->patterns, value, value_len, err));
 
     if (options & (LY_TYPE_OPTS_CANONIZE | LY_TYPE_OPTS_STORE)) {
-        if (options & LY_TYPE_OPTS_DYNAMIC) {
-            ly_type_store_canonized(ctx, options, lydict_insert_zc(ctx, (char*)value), storage, canonized);
-            value = NULL;
-        } else {
-            ly_type_store_canonized(ctx, options, lydict_insert(ctx, value_len ? value : "", value_len), storage, canonized);
-        }
+        /* NOTE: despite the pointer is used in storage twice (original and canonical_cache), it is stored in dictionary
+         * just once. This works even without storage - the string is returned as canonized. In case both options are used,
+         * ly_type_store_strval() increases reference count in dictionary for canonized. */
+        const char *str = lydict_insert(ctx, value_len ? value : "", value_len);
+        ly_type_store_strval(ctx, options, str, str, storage, canonized);
     }
-
     if (options & LY_TYPE_OPTS_DYNAMIC) {
         free((char*)value);
     }
@@ -930,8 +982,7 @@
             buf = NULL;
         }
 
-        ly_type_store_canonized(ctx, options, can, storage, canonized);
-        can = NULL;
+        ly_type_store_strval(ctx, options, lydict_insert(ctx, value_len ? value : "", value_len), can, storage, canonized);
 
         if (options & LY_TYPE_OPTS_STORE) {
             /* store data */
@@ -1037,18 +1088,15 @@
     /* validation done */
 
     if (options & (LY_TYPE_OPTS_CANONIZE | LY_TYPE_OPTS_STORE)) {
-        if (options & LY_TYPE_OPTS_DYNAMIC) {
-            ly_type_store_canonized(ctx, options, lydict_insert_zc(ctx, (char*)value), storage, canonized);
-            value = NULL;
-        } else {
-            ly_type_store_canonized(ctx, options, lydict_insert(ctx, value_len ? value : "", value_len), storage, canonized);
+        /* NOTE: despite the pointer is used in storage twice (original and canonical_cache), it is stored in dictionary
+         * just once. This works even without storage - the string is returned as canonized. In case both options are used,
+         * ly_type_store_strval() increases reference count in dictionary for canonized. */
+        const char *str = lydict_insert(ctx, value_len ? value : "", value_len);
+        if (options & LY_TYPE_OPTS_STORE) {
+            storage->enum_item = &type_enum->enums[u];
         }
+        ly_type_store_strval(ctx, options, str, str, storage, canonized);
     }
-
-    if (options & LY_TYPE_OPTS_STORE) {
-        storage->enum_item = &type_enum->enums[u];
-    }
-
     if (options & LY_TYPE_OPTS_DYNAMIC) {
         free((char*)value);
     }
@@ -1070,7 +1118,7 @@
 ly_type_dup_enum(struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
 {
     dup->enum_item = original->enum_item;
-    return ly_type_dup_canonical(ctx, original, dup);
+    return ly_type_dup_original(ctx, original, dup);
 }
 
 /**
@@ -1102,18 +1150,15 @@
     }
 
     if (options & (LY_TYPE_OPTS_CANONIZE | LY_TYPE_OPTS_STORE)) {
-        if (options & LY_TYPE_OPTS_DYNAMIC) {
-            ly_type_store_canonized(ctx, options, lydict_insert_zc(ctx, (char*)value), storage, canonized);
-            value = NULL;
-        } else {
-            ly_type_store_canonized(ctx, options, lydict_insert(ctx, value, value_len), storage, canonized);
+        /* NOTE: despite the pointer is used in storage twice (original and canonical_cache), it is stored in dictionary
+         * just once. This works even without storage - the string is returned as canonized. In case both options are used,
+         * ly_type_store_strval() increases reference count in dictionary for canonized. */
+        const char *str = lydict_insert(ctx, value_len ? value : "", value_len);
+        if (options & LY_TYPE_OPTS_STORE) {
+            storage->boolean = i;
         }
+        ly_type_store_strval(ctx, options, str, str, storage, canonized);
     }
-
-    if (options & LY_TYPE_OPTS_STORE) {
-        storage->boolean = i;
-    }
-
     if (options & LY_TYPE_OPTS_DYNAMIC) {
         free((char*)value);
     }
@@ -1121,6 +1166,17 @@
     return LY_SUCCESS;
 }
 
+/* @brief Duplication callback of the boolean values.
+ *
+ * Implementation of the ly_type_dup_clb.
+ */
+static LY_ERR
+ly_type_dup_boolean(struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
+{
+    dup->int64 = original->int64;
+    return ly_type_dup_original(ctx, original, dup);
+}
+
 /**
  * @brief Validate and store value of the YANG built-in empty type.
  *
@@ -1144,7 +1200,11 @@
     }
 
     if (options & (LY_TYPE_OPTS_CANONIZE | LY_TYPE_OPTS_STORE)) {
-        ly_type_store_canonized(ctx, options, lydict_insert(ctx, "", 0), storage, canonized);
+        /* NOTE: despite the pointer is used in storage twice (original and canonical_cache), it is stored in dictionary
+         * just once. This works even without storage - the string is returned as canonized. In case both options are used,
+         * ly_type_store_strval() increases reference count in dictionary for canonized. */
+        const char *str = lydict_insert(ctx, "", 0);
+        ly_type_store_strval(ctx, options, str, str, storage, canonized);
     }
 
     return LY_SUCCESS;
@@ -1249,14 +1309,14 @@
     }
 
     if (options & LY_TYPE_OPTS_CANONIZE) {
-        /* identityref does not have a canonical form - to make it clear, the canonized form is represented as NULL
-         * to make the caller print it always via callback printer */
+        /* identityref does not have a canonical form - to make it clear, the canonized form is represented as NULL */
         *canonized = NULL;
     }
 
     if (options & LY_TYPE_OPTS_STORE) {
         storage->ident = ident;
-        storage->canonized = NULL;
+        storage->canonical_cache = NULL;
+        storage->original = lydict_insert(ctx, value, value_len);
     }
 
     if (options & LY_TYPE_OPTS_DYNAMIC) {
@@ -1551,13 +1611,9 @@
     *err = NULL;
 
     if ((options & LY_TYPE_OPTS_SCHEMA) && (options & LY_TYPE_OPTS_INCOMPLETE_DATA)) {
+        /* we have incomplete schema tree, so we are actually just storing the original value for future validation */
         if (options & LY_TYPE_OPTS_STORE) {
-            if (options & LY_TYPE_OPTS_DYNAMIC) {
-                ly_type_store_canonized(ctx, options, lydict_insert_zc(ctx, (char*)value), storage, NULL);
-                value = NULL;
-            } else {
-                ly_type_store_canonized(ctx, options, lydict_insert(ctx, value_len ? value : "", value_len), storage, NULL);
-            }
+            storage->original = lydict_insert(ctx, value_len ? value : "", value_len);
         }
         goto cleanup;
     }
@@ -1853,31 +1909,27 @@
         }
     }
 
-    if (options & LY_TYPE_OPTS_CANONIZE) {
-        /* instance-identifier does not have a canonical form (lexical representation in in XML and JSON are
-         * even different) - to make it clear, the canonized form is represented as NULL to make the caller
-         * print it always via callback printer */
-        *canonized = NULL;
-    }
-
     if (options & LY_TYPE_OPTS_STORE) {
         storage->target = target;
-
-        if ((options & LY_TYPE_OPTS_SCHEMA) && (options & LY_TYPE_OPTS_SECOND_CALL)) {
-            /* remove the dummy canonized value from the first call */
-            lydict_remove(ctx, storage->canonized);
+        if (!storage->original) {
+            /* it may be already present from the first call, in case this is the second */
+            storage->original = lydict_insert(ctx, value_len ? value : "", value_len);
         }
-        storage->canonized = NULL;
     }
 
 cleanup:
-    /* cleanup */
     LY_ARRAY_FOR(prefixes, u) {
         lydict_remove(ctx, prefixes[u].prefix);
     }
     LY_ARRAY_FREE(prefixes);
     ly_set_erase(&predicates, NULL);
 
+    if (options & LY_TYPE_OPTS_CANONIZE) {
+        /* instance-identifier does not have a canonical form (lexical representation in in XML and JSON are
+         * even different) - to make it clear, the canonized form is represented as NULL */
+        *canonized = NULL;
+    }
+
     if (options & LY_TYPE_OPTS_DYNAMIC) {
         free((char*)value);
     }
@@ -1964,10 +2016,10 @@
     unsigned int u, v;
     char *result = NULL;
 
-    if (!value->target && value->canonized) {
+    if (!value->target && value->canonical_cache) {
         /* value was not fully processed, but we have the original value so return it's copy */
         *dynamic = 1;
-        return strdup(value->canonized);
+        return strdup(value->canonical_cache);
     }
 
     if (format == LYD_XML) {
@@ -2107,9 +2159,7 @@
 {
     lyd_value_free_path(ctx, value->target);
     value->target = NULL;
-
-    /* for the case of LY_EINCOMPLETE result on schema tree */
-    ly_type_free_canonical(ctx, value);
+    ly_type_free_original(ctx, value);
 }
 
 /**
@@ -2431,20 +2481,16 @@
     unsigned int u;
     struct lysc_type_union *type_u = (struct lysc_type_union*)type;
     struct lyd_value_subvalue *subvalue;
-    int secondcall = 0;
     char *errmsg = NULL;
 
     if ((options & LY_TYPE_OPTS_SECOND_CALL) && (options & LY_TYPE_OPTS_STORE)) {
         subvalue = storage->subvalue;
-        /* standalone second_call flag - the options flag can be removed, but we need information
-         * about the second call to avoid rewriting the canonized value */
-        secondcall = 1;
 
         /* 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, trees, subvalue->value, NULL, err);
+                                                       context_node, trees, 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
@@ -2471,9 +2517,9 @@
         /* use the first usable sybtype to store the value */
         LY_ARRAY_FOR(type_u->types, u) {
             subvalue->value->realtype = type_u->types[u];
-            ret = type_u->types[u]->plugin->store(ctx, type_u->types[u], value, value_len, options & ~(LY_TYPE_OPTS_CANONIZE | LY_TYPE_OPTS_DYNAMIC),
+            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, trees, subvalue->value, NULL, err);
+                                                  context_node, trees, subvalue->value, canonized, err);
             if (ret == LY_SUCCESS || ret == LY_EINCOMPLETE) {
                 /* success (or not yet complete) */
                 break;
@@ -2486,22 +2532,15 @@
             asprintf(&errmsg, "Invalid union value \"%.*s\" - no matching subtype found.", (int)value_len, value);
             goto error;
         }
+
+        if ((options & LY_TYPE_OPTS_STORE) && !storage->original) {
+            storage->original = lydict_insert(ctx, value_len ? value : "", value_len);
+        }
     }
     /* success */
 
-    if (!secondcall) {
-        if (options & (LY_TYPE_OPTS_CANONIZE | LY_TYPE_OPTS_STORE)) {
-            if (options & LY_TYPE_OPTS_DYNAMIC) {
-                ly_type_store_canonized(ctx, options, lydict_insert_zc(ctx, (char*)value), storage, canonized);
-                value = NULL;
-            } else {
-                ly_type_store_canonized(ctx, options, lydict_insert(ctx, value_len ? value : "", value_len), storage, canonized);
-            }
-        }
-
-        if (options & LY_TYPE_OPTS_DYNAMIC) {
-            free((char*)value);
-        }
+    if (options & LY_TYPE_OPTS_DYNAMIC) {
+        free((char*)value);
     }
 
     if (options & LY_TYPE_OPTS_STORE) {
@@ -2557,7 +2596,7 @@
 static const char *
 ly_type_print_union(const struct lyd_value *value, LYD_FORMAT format, ly_clb_get_prefix get_prefix, void *printer, int *dynamic)
 {
-    return ly_type_print_canonical(value, format, get_prefix, printer, dynamic);
+    return value->subvalue->value->realtype->plugin->print(value->subvalue->value, format, get_prefix, printer, dynamic);
 }
 
 /* @brief Duplication callback of the union values.
@@ -2584,7 +2623,7 @@
     dup->subvalue->value->realtype = original->subvalue->value->realtype;
     dup->subvalue->value->realtype->plugin->duplicate(ctx, original->subvalue->value, dup->subvalue->value);
 
-    return ly_type_dup_canonical(ctx, original, dup);
+    return ly_type_dup_original(ctx, original, dup);
 }
 
 /**
@@ -2628,17 +2667,17 @@
     {.type = LY_TYPE_UINT64, .store = ly_type_store_uint, .compare = ly_type_compare_canonical, .print = ly_type_print_canonical,
      .duplicate = ly_type_dup_uint, .free = ly_type_free_canonical, .id = "libyang 2 - unsigned integer, version 1"},
     {.type = LY_TYPE_STRING, .store = ly_type_store_string, .compare = ly_type_compare_canonical, .print = ly_type_print_canonical,
-     .duplicate = ly_type_dup_canonical, .free = ly_type_free_canonical, .id = "libyang 2 - string, version 1"},
+     .duplicate = ly_type_dup_original, .free = ly_type_free_original, .id = "libyang 2 - string, version 1"},
     {.type = LY_TYPE_BITS, .store = ly_type_store_bits, .compare = ly_type_compare_canonical, .print = ly_type_print_canonical,
      .duplicate = ly_type_dup_bits, .free = ly_type_free_bits, .id = "libyang 2 - bits, version 1"},
     {.type = LY_TYPE_BOOL, .store = ly_type_store_boolean, .compare = ly_type_compare_canonical, .print = ly_type_print_canonical,
-     .duplicate = ly_type_dup_int, .free = ly_type_free_canonical, .id = "libyang 2 - boolean, version 1"},
+     .duplicate = ly_type_dup_boolean, .free = ly_type_free_original, .id = "libyang 2 - boolean, version 1"},
     {.type = LY_TYPE_DEC64, .store = ly_type_store_decimal64, .compare = ly_type_compare_canonical, .print = ly_type_print_canonical,
      .duplicate = ly_type_dup_decimal64, .free = ly_type_free_canonical, .id = "libyang 2 - decimal64, version 1"},
     {.type = LY_TYPE_EMPTY, .store = ly_type_store_empty, .compare = ly_type_compare_empty, .print = ly_type_print_canonical,
-     .duplicate = ly_type_dup_canonical, .free = ly_type_free_canonical, .id = "libyang 2 - empty, version 1"},
+     .duplicate = ly_type_dup_original, .free = ly_type_free_original, .id = "libyang 2 - empty, version 1"},
     {.type = LY_TYPE_ENUM, .store = ly_type_store_enum, .compare = ly_type_compare_canonical, .print = ly_type_print_canonical,
-     .duplicate = ly_type_dup_enum, .free = ly_type_free_canonical, .id = "libyang 2 - enumeration, version 1"},
+     .duplicate = ly_type_dup_enum, .free = ly_type_free_original, .id = "libyang 2 - enumeration, version 1"},
     {.type = LY_TYPE_IDENT, .store = ly_type_store_identityref, .compare = ly_type_compare_identityref, .print = ly_type_print_identityref,
      .duplicate = ly_type_dup_identityref, .free = ly_type_free_canonical, .id = "libyang 2 - identityref, version 1"},
     {.type = LY_TYPE_INST, .store = ly_type_store_instanceid, .compare = ly_type_compare_instanceid, .print = ly_type_print_instanceid,
diff --git a/src/plugins_types.h b/src/plugins_types.h
index f281e0b..1c4fcee 100644
--- a/src/plugins_types.h
+++ b/src/plugins_types.h
@@ -24,6 +24,52 @@
 #include "tree_data.h"
 
 /**
+ * @internal
+ * @page internals
+ *
+ * @section types Types Processing
+ *
+ * @subsection types_
+ */
+
+/**
+ * @defgroup types Plugins - Types
+ * @{
+ *
+ * Structures and functions to for libyang plugins implementing specific YANG types defined in YANG schemas
+ */
+
+/**
+ * @page howtoplugins
+ * @section Types
+ *
+ * YANG allows schemas to define new data types via *typedef* statement or even in leaf's/leaf-list's *type* statements.
+ * Such types are derived (directly or indirectly) from a set of [YANG built-in types](https://tools.ietf.org/html/rfc7950#section-4.2.4).
+ * libyang implements all handling of the data values of the YANG types via plugins. Internally, plugins for the built-in types
+ * and several others are implemented. Type plugin is supposed to
+ * - validate (and canonize) data value according to the type's restrictions,
+ * - store it as lyd_value,
+ * - print it,
+ * - compare two values (lyd_value) of the same type,
+ * - duplicate data in lyd_value and
+ * - free the connected data from lyd_value.
+ *
+ * All these functions are provided to libyang via a set of callback functions specified as lysc_type_plugin.
+ * All the callbacks are supposed to do not log directly via libyang logger. Instead, they return LY_ERR value and
+ * ly_err_item error structure(s) describing the detected error(s) (helper functions ly_err_new() and ly_err_free()
+ * are available).
+ *
+ * The main functionality is provided via ::ly_type_store_clb callback responsible for validating, canonizing and storing
+ * provided string representation of the value in specified format (XML and JSON supported). Valid value is stored in
+ * lyd_value structure - its union allows to store data as one of the predefined type or in a custom form behind
+ * lyd_value's ptr member (`void*`). The callback is also responsible for storing original string representation of the
+ * value as lyd_value::original. Optionally, the callback can utilize lyd_value::canonical_cache to store data for providing
+ * canonical string representation via the ::ly_type_print_clb callback. Canonical value cannot be available directly, since
+ * some types do not have/provide canonical value (respectively it may be multivalent according to the output format as
+ * in the case of instance-identifiers).
+ */
+
+/**
  * @brief Helper function for various plugin functions to generate error information structure.
  *
  * @param[in] level Error level of the error.
@@ -96,8 +142,6 @@
  *             If the @p canonized differs from the storage's canonized member, the canonized value is also stored here despite the
  *             LY_TYPE_OPTS_CANONIZE option.
  * @param[out] canonized If LY_TYPE_OPTS_CANONIZE option set, the canonized string stored in the @p ctx dictionary is returned via this parameter.
- *             This is usable mainly in the case the LY_TYPE_OPTS_STORE option is not set and the canonized value is needed outside the lyd_value
- *             structure, otherwise the canonized value is stored in the @p storage automatically.
  * @param[out] err Optionally provided error information in case of failure. If not provided to the caller, a generic error message is prepared instead.
  * The error structure can be created by ly_err_new().
  * @return LY_SUCCESS on success
@@ -176,6 +220,8 @@
 
 /**
  * @brief List of type plugins for built-in types.
+ *
+ * TODO hide behind some plugin getter
  */
 extern struct lysc_type_plugin ly_builtin_type_plugins[LY_DATA_TYPE_COUNT];
 
@@ -241,11 +287,11 @@
  * @param[in] basetype Base built-in type of the type with the range specified to get know if the @p range structure represents range or length restriction.
  * @param[in] range Range (length) restriction information.
  * @param[in] value Value to check. In case of basetypes using unsigned integer values, the value is actually cast to uint64_t.
- * @param[in] canonized Canonized @p value for error logging.
+ * @param[in] strval String representation of the @p value for error logging.
  * @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 *canonized, 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.
@@ -294,4 +340,6 @@
 struct lyd_value_prefix *ly_type_get_prefixes(struct ly_ctx *ctx, const char *value, size_t value_len,
                                               ly_clb_resolve_prefix get_prefix, void *parser);
 
+/**@} types */
+
 #endif /* LY_PLUGINS_TYPES_H_ */
diff --git a/src/tree_data.c b/src/tree_data.c
index e3f2b29..bc11889 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -108,8 +108,7 @@
 {
 
     if (str_len) {
-        int r = strncmp(refstr, str, str_len);
-        if (!r && !refstr[str_len]) {
+        if (!strncmp(refstr, str, str_len) && !refstr[str_len]) {
             return 0;
         } else {
             return 1;
@@ -148,7 +147,7 @@
             if (snode->nodetype == LYS_LIST) {
                 /* TODO handle value as keys of the list instance */
             } else if (snode->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
-                if (cmp_str(((struct lyd_node_term*)node)->value.canonized, value, value_len)) {
+                if (cmp_str(((struct lyd_node_term*)node)->value.original, value, value_len)) {
                     continue;
                 }
             } else {
diff --git a/src/tree_data.h b/src/tree_data.h
index d6babc2..589a3e0 100644
--- a/src/tree_data.h
+++ b/src/tree_data.h
@@ -145,14 +145,9 @@
  * @brief YANG data representation
  */
 struct lyd_value {
-    const char *canonized;          /**< Canonical string representation of value (for comparison, printing,...), canonized according to the
-                                         rules implemented in the type's canonization callback (if any). Note that not all the types
-                                         have a canonical representation, so this value can be even NULL (identityref or instance-identifiers
-                                         are built-in examples of such a case). The lyd_value::realtype's print callback provides possibility
-                                         to get correct string representation of the value for the specific data format. */
+    const char *original;           /**< Original string representation of the value. It is never NULL, but (canonical) string representation
+                                         of the value should be always obtained via the type's printer callback (lyd_value::realtype::plugin::print). */
     union {
-        const char *string;         /**< original, non-canonized string value. Useful for example for unions where the type (and therefore
-                                         the canonization rules) can change by changing value (e.g. leafref target) somewhere else. */
         int8_t boolean;              /**< 0 as false, 1 as true */
         int64_t dec64;               /**< decimal64: value = dec64 / 10^fraction-digits  */
         int8_t int8;                 /**< 8-bit signed integer */
@@ -198,13 +193,16 @@
     };  /**< 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. */
 
-    struct lysc_type *realtype; /**< pointer to the real type of the data stored in the value structure. This type can differ from the type
+    struct lysc_type *realtype;      /**< pointer to the real type of the data stored in the value structure. This type can differ from the type
                                           in the schema node of the data node since the type's store plugin can use other types/plugins for
                                           storing data. Speaking about built-in types, this is the case of leafref which stores data as its
                                           target type. In contrast, union type also use its subtype's callbacks, but inside an internal data
                                           lyd_value::subvalue structure, so here is the pointer to the union type.
                                           In general, this type is used to get free callback for this lyd_value structure, so it must reflect
                                           the type used to store data directly in the same lyd_value instance. */
+    void *canonical_cache;           /**< Generic cache for type plugins to store data necessary to print canonical value. It can be the canonical
+                                          value itself or anything else useful to print the canonical form of the value. Plugin is responsible for
+                                          freeing the cache in its free callback. */
 };
 
 /**
@@ -472,9 +470,10 @@
  * @param[in] name_len Optional length of the @p name argument in case it is not NULL-terminated string.
  * @param[in] nodetype Optional mask for the nodetype of the node to find, 0 is understood as all nodetypes.
  * @param[in] value Optional restriction for lyd_node_term nodes to select node with the specific value. Note that this
- * search restriction is limited to compare canonical representation of the type. Some of the types have no canonical
- * representation and 2 different strings can represent the same value (e.g. different prefixes of the same namespace in instance-identifiers).
- * In this case there is more advanced lyd_value_compare() to check if the values matches.
+ * search restriction is limited to compare original string representation of the @p first value. Some of the types have
+ * canonical representation defined so the same value can be represented by multiple lexical representation. In such a
+ * case the @p value not matching the original representation of @p first may still be the same.
+ * For such a case there is more advanced lyd_value_compare() to check if the values matches.
  * @param[in] value_len Optional length of the @p value argument in case it is not NULL-terminated string.
  * @return The sibling node of the @p first (or itself), satisfying the given restrictions.
  * @return NULL in case there is no node satisfying the restrictions.
diff --git a/src/tree_schema_compile.c b/src/tree_schema_compile.c
index d97328c..c241077 100644
--- a/src/tree_schema_compile.c
+++ b/src/tree_schema_compile.c
@@ -7048,7 +7048,7 @@
     for (u = 0; u < ctx.dflts.count; ++u) {
         struct ly_err_item *err = NULL;
         struct lysc_incomplete_dflt *r = ctx.dflts.objs[u];
-        ret = r->dflt->realtype->plugin->store(ctx.ctx, r->dflt->realtype, r->dflt->canonized, strlen(r->dflt->canonized),
+        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);
         if (err) {
diff --git a/tests/features/test_types.c b/tests/features/test_types.c
index 6fdf096..5d508d9 100644
--- a/tests/features/test_types.c
+++ b/tests/features/test_types.c
@@ -159,12 +159,12 @@
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("int8", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
-    assert_string_equal("15", leaf->value.canonized);
+    assert_string_equal("15", leaf->value.canonical_cache);
     assert_int_equal(15, leaf->value.int8);
 
     value.realtype = leaf->value.realtype;
     assert_int_equal(LY_SUCCESS, value.realtype->plugin->duplicate(s->ctx, &leaf->value, &value));
-    assert_string_equal(leaf->value.canonized, value.canonized);
+    assert_string_equal(leaf->value.canonical_cache, value.canonical_cache);
     assert_int_equal(15, value.int8);
     value.realtype->plugin->free(s->ctx, &value);
     memset(&value, 0, sizeof value);
@@ -216,12 +216,12 @@
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("uint8", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
-    assert_string_equal("150", leaf->value.canonized);
+    assert_string_equal("150", leaf->value.canonical_cache);
     assert_int_equal(150, leaf->value.uint8);
 
     value.realtype = leaf->value.realtype;
     assert_int_equal(LY_SUCCESS, value.realtype->plugin->duplicate(s->ctx, &leaf->value, &value));
-    assert_string_equal(leaf->value.canonized, value.canonized);
+    assert_string_equal(leaf->value.canonical_cache, value.canonical_cache);
     assert_int_equal(150, value.uint8);
     value.realtype->plugin->free(s->ctx, &value);
     memset(&value, 0, sizeof value);
@@ -273,12 +273,12 @@
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("dec64", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
-    assert_string_equal("8.0", leaf->value.canonized);
+    assert_string_equal("8.0", leaf->value.canonical_cache);
     assert_int_equal(80, leaf->value.dec64);
 
     value.realtype = leaf->value.realtype;
     assert_int_equal(LY_SUCCESS, value.realtype->plugin->duplicate(s->ctx, &leaf->value, &value));
-    assert_string_equal(leaf->value.canonized, value.canonized);
+    assert_string_equal(leaf->value.canonical_cache, value.canonical_cache);
     assert_int_equal(80, value.dec64);
     value.realtype->plugin->free(s->ctx, &value);
     memset(&value, 0, sizeof value);
@@ -289,7 +289,7 @@
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("dec64", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
-    assert_string_equal("8.0", leaf->value.canonized);
+    assert_string_equal("8.0", leaf->value.canonical_cache);
     assert_int_equal(80, leaf->value.dec64);
     lyd_free_all(tree);
 
@@ -298,7 +298,7 @@
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("dec64-norestr", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
-    assert_string_equal("-9.223372036854775808", leaf->value.canonized);
+    assert_string_equal("-9.223372036854775808", leaf->value.canonical_cache);
     assert_int_equal(INT64_C(-9223372036854775807) - INT64_C(1), leaf->value.dec64);
     lyd_free_all(tree);
 
@@ -307,7 +307,7 @@
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("dec64-norestr", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
-    assert_string_equal("9.223372036854775807", leaf->value.canonized);
+    assert_string_equal("9.223372036854775807", leaf->value.canonical_cache);
     assert_int_equal(INT64_C(9223372036854775807), leaf->value.dec64);
     lyd_free_all(tree);
 
@@ -360,7 +360,7 @@
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("str", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
-    assert_string_equal("teststring", leaf->value.canonized);
+    assert_string_equal("teststring", leaf->value.canonical_cache);
     lyd_free_all(tree);
 
     /* multibyte characters (€ encodes as 3-byte UTF8 character, length restriction is 2-5) */
@@ -369,7 +369,7 @@
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("str-utf8", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
-    assert_string_equal("€€", leaf->value.canonized);
+    assert_string_equal("€€", leaf->value.canonical_cache);
     lyd_free_all(tree);
     data = "<str-utf8 xmlns=\"urn:tests:types\">€</str-utf8>";
     assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, 0, NULL));
@@ -415,14 +415,14 @@
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("bits", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
-    assert_string_equal("zero two", leaf->value.canonized);
+    assert_string_equal("zero two", leaf->value.canonical_cache);
     assert_int_equal(2, LY_ARRAY_SIZE(leaf->value.bits_items));
     assert_string_equal("zero", leaf->value.bits_items[0]->name);
     assert_string_equal("two", leaf->value.bits_items[1]->name);
 
     value.realtype = leaf->value.realtype;
     assert_int_equal(LY_SUCCESS, value.realtype->plugin->duplicate(s->ctx, &leaf->value, &value));
-    assert_string_equal(leaf->value.canonized, value.canonized);
+    assert_string_equal(leaf->value.canonical_cache, value.canonical_cache);
     assert_int_equal(2, LY_ARRAY_SIZE(value.bits_items));
     assert_string_equal("zero", value.bits_items[0]->name);
     assert_string_equal("two", value.bits_items[1]->name);
@@ -435,7 +435,7 @@
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("bits", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
-    assert_string_equal("zero two", leaf->value.canonized);
+    assert_string_equal("zero two", leaf->value.canonical_cache);
     lyd_free_all(tree);
 
     /* disabled feature */
@@ -449,13 +449,13 @@
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("bits", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
-    assert_string_equal("one", leaf->value.canonized);
+    assert_string_equal("one", leaf->value.canonical_cache);
     assert_int_equal(1, LY_ARRAY_SIZE(leaf->value.bits_items));
     assert_string_equal("one", leaf->value.bits_items[0]->name);
 
     value.realtype = leaf->value.realtype;
     assert_int_equal(LY_SUCCESS, value.realtype->plugin->duplicate(s->ctx, &leaf->value, &value));
-    assert_string_equal(leaf->value.canonized, value.canonized);
+    assert_string_equal(leaf->value.canonical_cache, value.canonical_cache);
     assert_int_equal(1, LY_ARRAY_SIZE(value.bits_items));
     assert_string_equal("one", value.bits_items[0]->name);
     value.realtype->plugin->free(s->ctx, &value);
@@ -491,12 +491,12 @@
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("enums", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
-    assert_string_equal("white", leaf->value.canonized);
+    assert_string_equal("white", leaf->value.canonical_cache);
     assert_string_equal("white", leaf->value.enum_item->name);
 
     value.realtype = leaf->value.realtype;
     assert_int_equal(LY_SUCCESS, value.realtype->plugin->duplicate(s->ctx, &leaf->value, &value));
-    assert_string_equal(leaf->value.canonized, value.canonized);
+    assert_string_equal(leaf->value.canonical_cache, value.canonical_cache);
     assert_string_equal("white", value.enum_item->name);
     value.realtype->plugin->free(s->ctx, &value);
     lyd_free_all(tree);
@@ -512,7 +512,7 @@
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("enums", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
-    assert_string_equal("yellow", leaf->value.canonized);
+    assert_string_equal("yellow", leaf->value.canonical_cache);
     lyd_free_all(tree);
 
     /* leading/trailing whitespaces are not valid */
@@ -549,16 +549,16 @@
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("binary", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
-    assert_string_equal("aGVs\nbG8=", leaf->value.canonized);
+    assert_string_equal("aGVs\nbG8=", leaf->value.canonical_cache);
     assert_non_null(tree = tree->next);
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("binary-norestr", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
-    assert_string_equal("TQ==", leaf->value.canonized);
+    assert_string_equal("TQ==", leaf->value.canonical_cache);
 
     value.realtype = leaf->value.realtype;
     assert_int_equal(LY_SUCCESS, value.realtype->plugin->duplicate(s->ctx, &leaf->value, &value));
-    assert_string_equal(leaf->value.canonized, value.canonized);
+    assert_string_equal(leaf->value.canonical_cache, value.canonical_cache);
     value.realtype->plugin->free(s->ctx, &value);
     memset(&value, 0, sizeof value);
     lyd_free_all(tree);
@@ -569,21 +569,21 @@
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("binary-norestr", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
-    assert_string_equal("", leaf->value.canonized);
+    assert_string_equal("", leaf->value.canonical_cache);
     lyd_free_all(tree);
     data = "<binary-norestr xmlns=\"urn:tests:types\"></binary-norestr>";
     assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, 0, NULL));
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("binary-norestr", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
-    assert_string_equal("", leaf->value.canonized);
+    assert_string_equal("", leaf->value.canonical_cache);
     lyd_free_all(tree);
     data = "<binary-norestr xmlns=\"urn:tests:types\"/>";
     assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, 0, NULL));
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("binary-norestr", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
-    assert_string_equal("", leaf->value.canonized);
+    assert_string_equal("", leaf->value.canonical_cache);
     lyd_free_all(tree);
 
     /* invalid base64 character */
@@ -626,7 +626,7 @@
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("bool", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
-    assert_string_equal("true", leaf->value.canonized);
+    assert_string_equal("true", leaf->value.canonical_cache);
     assert_int_equal(1, leaf->value.boolean);
     lyd_free_all(tree);
 
@@ -635,7 +635,7 @@
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("bool", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
-    assert_string_equal("false", leaf->value.canonized);
+    assert_string_equal("false", leaf->value.canonical_cache);
     assert_int_equal(0, leaf->value.boolean);
     lyd_free_all(tree);
 
@@ -667,7 +667,7 @@
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("empty", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
-    assert_string_equal("", leaf->value.canonized);
+    assert_string_equal("", leaf->value.canonical_cache);
     lyd_free_all(tree);
 
     data = "<empty xmlns=\"urn:tests:types\"/>";
@@ -675,7 +675,7 @@
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("empty", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
-    assert_string_equal("", leaf->value.canonized);
+    assert_string_equal("", leaf->value.canonical_cache);
     lyd_free_all(tree);
 
     /* invalid value */
@@ -727,13 +727,13 @@
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("ident", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
-    assert_null(leaf->value.canonized);
+    assert_null(leaf->value.canonical_cache);
     assert_string_equal("gigabit-ethernet", leaf->value.ident->name);
     test_printed_value(&leaf->value, "t:gigabit-ethernet", LYD_XML, "t");
 
     value.realtype = leaf->value.realtype;
     assert_int_equal(LY_SUCCESS, value.realtype->plugin->duplicate(s->ctx, &leaf->value, &value));
-    assert_null(value.canonized);
+    assert_null(value.canonical_cache);
     assert_string_equal("gigabit-ethernet", value.ident->name);
     value.realtype->plugin->free(s->ctx, &value);
     lyd_free_all(tree);
@@ -743,7 +743,7 @@
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("ident", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
-    assert_null(leaf->value.canonized);
+    assert_null(leaf->value.canonical_cache);
     test_printed_value(&leaf->value, "d:fast-ethernet", LYD_XML, "d");
     lyd_free_all(tree);
 
@@ -798,7 +798,7 @@
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("inst", tree->schema->name);
     leaf = (const struct lyd_node_term*)tree;
-    assert_null(leaf->value.canonized);
+    assert_null(leaf->value.canonical_cache);
     assert_int_equal(2, LY_ARRAY_SIZE(leaf->value.target));
     assert_string_equal("cont", leaf->value.target[0].node->name);
     assert_null(leaf->value.target[0].predicates);
@@ -807,7 +807,7 @@
 
     value.realtype = leaf->value.realtype;
     assert_int_equal(LY_SUCCESS, value.realtype->plugin->duplicate(s->ctx, &leaf->value, &value));
-    assert_null(value.canonized);
+    assert_null(value.canonical_cache);
     assert_true(LY_ARRAY_SIZE(leaf->value.target) == LY_ARRAY_SIZE(value.target));
     assert_true(leaf->value.target[0].node == value.target[0].node);
     assert_true(leaf->value.target[0].predicates == value.target[0].predicates); /* NULL */
@@ -823,7 +823,7 @@
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("inst", tree->schema->name);
     leaf = (const struct lyd_node_term*)tree;
-    assert_null(leaf->value.canonized);
+    assert_null(leaf->value.canonical_cache);
     lyd_free_all(tree);
 
     data = "<leaflisttarget xmlns=\"urn:tests:types\">1</leaflisttarget><leaflisttarget xmlns=\"urn:tests:types\">2</leaflisttarget>"
@@ -833,7 +833,7 @@
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("inst", tree->schema->name);
     leaf = (const struct lyd_node_term*)tree;
-    assert_null(leaf->value.canonized);
+    assert_null(leaf->value.canonical_cache);
     lyd_free_all(tree);
 
     data = "<list xmlns=\"urn:tests:types\"><id>a</id></list><list xmlns=\"urn:tests:types\"><id>b</id><value>x</value></list>"
@@ -843,7 +843,7 @@
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("inst", tree->schema->name);
     leaf = (const struct lyd_node_term*)tree;
-    assert_null(leaf->value.canonized);
+    assert_null(leaf->value.canonical_cache);
     lyd_free_all(tree);
 
     data = "<list_inst xmlns=\"urn:tests:types\"><id xmlns:b=\"urn:tests:types\">/b:leaflisttarget[.='a']</id><value>x</value></list_inst>"
@@ -855,7 +855,7 @@
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("inst", tree->schema->name);
     leaf = (const struct lyd_node_term*)tree;
-    assert_null(leaf->value.canonized);
+    assert_null(leaf->value.canonical_cache);
     assert_int_equal(2, LY_ARRAY_SIZE(leaf->value.target));
     assert_string_equal("list_inst", leaf->value.target[0].node->name);
     assert_int_equal(1, LY_ARRAY_SIZE(leaf->value.target[0].predicates));
@@ -867,7 +867,7 @@
 
     value.realtype = leaf->value.realtype;
     assert_int_equal(LY_SUCCESS, value.realtype->plugin->duplicate(s->ctx, &leaf->value, &value));
-    assert_null(value.canonized);
+    assert_null(value.canonical_cache);
     assert_true(LY_ARRAY_SIZE(leaf->value.target) == LY_ARRAY_SIZE(value.target));
     assert_true(leaf->value.target[0].node == value.target[0].node);
     assert_true(LY_ARRAY_SIZE(leaf->value.target[0].predicates) == LY_ARRAY_SIZE(value.target[0].predicates));
@@ -885,7 +885,7 @@
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("inst", tree->schema->name);
     leaf = (const struct lyd_node_term*)tree;
-    assert_null(leaf->value.canonized);
+    assert_null(leaf->value.canonical_cache);
     lyd_free_all(tree);
 
     data = "<list_ident xmlns=\"urn:tests:types\"><id xmlns:dfs=\"urn:tests:defs\">dfs:ethernet</id><value>x</value></list_ident>"
@@ -896,7 +896,7 @@
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("inst", tree->schema->name);
     leaf = (const struct lyd_node_term*)tree;
-    assert_null(leaf->value.canonized);
+    assert_null(leaf->value.canonical_cache);
     lyd_free_all(tree);
 
     data = "<list2 xmlns=\"urn:tests:types\"><id>types:xxx</id><value>x</value></list2>"
@@ -907,7 +907,7 @@
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("inst", tree->schema->name);
     leaf = (const struct lyd_node_term*)tree;
-    assert_null(leaf->value.canonized);
+    assert_null(leaf->value.canonical_cache);
     lyd_free_all(tree);
 
     data = "<list xmlns=\"urn:tests:types\"><id>types:xxx</id><value>x</value></list>"
@@ -918,7 +918,7 @@
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("inst", tree->schema->name);
     leaf = (const struct lyd_node_term*)tree;
-    assert_null(leaf->value.canonized);
+    assert_null(leaf->value.canonical_cache);
     lyd_free_all(tree);
 
     data = "<list2 xmlns=\"urn:tests:types\"><id>a</id><value>a</value></list2>"
@@ -930,11 +930,11 @@
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("inst", tree->schema->name);
     leaf = (const struct lyd_node_term*)tree;
-    assert_null(leaf->value.canonized);
+    assert_null(leaf->value.canonical_cache);
     trees = lyd_trees_new(1, tree);
     assert_non_null(leaf = lyd_target(leaf->value.target, trees));
-    assert_string_equal("a", leaf->value.canonized);
-    assert_string_equal("b", ((struct lyd_node_term*)leaf->next)->value.canonized);
+    assert_string_equal("a", leaf->value.canonical_cache);
+    assert_string_equal("b", ((struct lyd_node_term*)leaf->next)->value.canonical_cache);
     lyd_trees_free(trees, 1);
 
     /* invalid value */
@@ -1139,7 +1139,7 @@
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("lref", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
-    assert_string_equal("y", leaf->value.canonized);
+    assert_string_equal("y", leaf->value.canonical_cache);
     assert_int_equal(LY_TYPE_STRING, leaf->value.realtype->plugin->type);
     lyd_free_all(tree);
 
@@ -1151,7 +1151,7 @@
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("lref2", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
-    assert_string_equal("y", leaf->value.canonized);
+    assert_string_equal("y", leaf->value.canonical_cache);
     lyd_free_all(tree);
 
     data = "<str-norestr xmlns=\"urn:tests:types\">y</str-norestr>"
@@ -1162,7 +1162,7 @@
     leaf = (struct lyd_node_term*)(lyd_node_children(lyd_node_children(tree))->prev);
     assert_int_equal(LYS_LEAF, leaf->schema->nodetype);
     assert_string_equal("lr1", leaf->schema->name);
-    assert_string_equal("y", leaf->value.canonized);
+    assert_string_equal("y", leaf->value.canonical_cache);
     lyd_free_all(tree);
 
     data = "<str-norestr xmlns=\"urn:tests:types\">y</str-norestr>"
@@ -1174,7 +1174,7 @@
     leaf = (struct lyd_node_term*)(lyd_node_children(lyd_node_children(tree)->prev)->prev);
     assert_int_equal(LYS_LEAF, leaf->schema->nodetype);
     assert_string_equal("lr2", leaf->schema->name);
-    assert_string_equal("y", leaf->value.canonized);
+    assert_string_equal("y", leaf->value.canonical_cache);
     lyd_free_all(tree);
 
     data = "<list xmlns=\"urn:tests:types\"><id>x</id><targets>a</targets><targets>b</targets></list>"
@@ -1187,7 +1187,7 @@
     leaf = (struct lyd_node_term*)(lyd_node_children(lyd_node_children(tree)->prev)->prev);
     assert_int_equal(LYS_LEAF, leaf->schema->nodetype);
     assert_string_equal("lr3", leaf->schema->name);
-    assert_string_equal("c", leaf->value.canonized);
+    assert_string_equal("c", leaf->value.canonical_cache);
     lyd_free_all(tree);
 
     /* invalid value */
@@ -1258,20 +1258,23 @@
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("un1", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
-    assert_string_equal("12", leaf->value.canonized);
+    assert_string_equal("12", leaf->value.original);
+    assert_null(leaf->value.canonical_cache);
     assert_null(leaf->value.subvalue->prefixes);
     assert_int_equal(LY_TYPE_UNION, leaf->value.realtype->basetype);
     assert_int_equal(LY_TYPE_INT8, leaf->value.subvalue->value->realtype->basetype);
+    assert_string_equal("12", leaf->value.subvalue->value->canonical_cache);
     assert_int_equal(12, leaf->value.subvalue->value->int8);
 
     test_printed_value(&leaf->value, "12", LYD_XML, NULL);
 
     value.realtype = leaf->value.realtype;
     assert_int_equal(LY_SUCCESS, value.realtype->plugin->duplicate(s->ctx, &leaf->value, &value));
-    assert_string_equal("12", value.canonized);
-    assert_string_equal("12", value.subvalue->value->canonized);
+    assert_string_equal("12", value.original);
+    assert_null(value.canonical_cache);
     assert_null(value.subvalue->prefixes);
     assert_int_equal(LY_TYPE_INT8, value.subvalue->value->realtype->basetype);
+    assert_string_equal("12", value.subvalue->value->canonical_cache);
     assert_int_equal(12, leaf->value.subvalue->value->int8);
     value.realtype->plugin->free(s->ctx, &value);
     lyd_free_all(tree);
@@ -1283,10 +1286,12 @@
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("un1", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
-    assert_string_equal("2", leaf->value.canonized);
+    assert_string_equal("2", leaf->value.original);
+    assert_null(leaf->value.canonical_cache);
     assert_null(leaf->value.subvalue->prefixes);
     assert_int_equal(LY_TYPE_UNION, leaf->value.realtype->basetype);
     assert_int_equal(LY_TYPE_STRING, leaf->value.subvalue->value->realtype->basetype);
+    assert_string_equal("2", leaf->value.subvalue->value->canonical_cache);
     lyd_free_all(tree);
 
     data = "<un1 xmlns=\"urn:tests:types\" xmlns:x=\"urn:tests:defs\">x:fast-ethernet</un1>";
@@ -1294,19 +1299,21 @@
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("un1", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
-    assert_string_equal("x:fast-ethernet", leaf->value.canonized);
+    assert_string_equal("x:fast-ethernet", leaf->value.original);
+    assert_null(leaf->value.canonical_cache);
     assert_non_null(leaf->value.subvalue->prefixes);
     assert_int_equal(LY_TYPE_UNION, leaf->value.realtype->basetype);
     assert_int_equal(LY_TYPE_IDENT, leaf->value.subvalue->value->realtype->basetype);
-    assert_null(leaf->value.subvalue->value->canonized);
+    assert_null(leaf->value.subvalue->value->canonical_cache); /* identityref does not have canonical form */
 
     test_printed_value(&leaf->value, "x:fast-ethernet", LYD_XML, "x");
     test_printed_value(leaf->value.subvalue->value, "d:fast-ethernet", LYD_XML, "d");
 
     value.realtype = leaf->value.realtype;
     assert_int_equal(LY_SUCCESS, value.realtype->plugin->duplicate(s->ctx, &leaf->value, &value));
-    assert_string_equal("x:fast-ethernet", value.canonized);
-    assert_null(value.subvalue->value->canonized);
+    assert_string_equal("x:fast-ethernet", value.original);
+    assert_null(value.canonical_cache);
+    assert_null(value.subvalue->value->canonical_cache);
     assert_non_null(value.subvalue->prefixes);
     assert_int_equal(LY_TYPE_IDENT, value.subvalue->value->realtype->basetype);
     assert_string_equal("fast-ethernet", value.subvalue->value->ident->name);
@@ -1318,11 +1325,12 @@
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("un1", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
-    assert_string_equal("d:superfast-ethernet", leaf->value.canonized);
+    assert_string_equal("d:superfast-ethernet", leaf->value.original);
+    assert_null(leaf->value.canonical_cache);
     assert_non_null(leaf->value.subvalue->prefixes);
     assert_int_equal(LY_TYPE_UNION, leaf->value.realtype->basetype);
     assert_int_equal(LY_TYPE_STRING, leaf->value.subvalue->value->realtype->basetype);
-    assert_string_equal("d:superfast-ethernet", leaf->value.subvalue->value->canonized);
+    assert_string_equal("d:superfast-ethernet", leaf->value.subvalue->value->canonical_cache);
     lyd_free_all(tree);
 
     data = "<leaflisttarget xmlns=\"urn:tests:types\">x</leaflisttarget><leaflisttarget xmlns=\"urn:tests:types\">y</leaflisttarget>"
@@ -1332,11 +1340,12 @@
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("un1", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
-    assert_string_equal("/a:leaflisttarget[2]", leaf->value.canonized);
+    assert_string_equal("/a:leaflisttarget[2]", leaf->value.original);
+    assert_null(leaf->value.canonical_cache);
     assert_non_null(leaf->value.subvalue->prefixes);
     assert_int_equal(LY_TYPE_UNION, leaf->value.realtype->basetype);
     assert_int_equal(LY_TYPE_INST, leaf->value.subvalue->value->realtype->basetype);
-    assert_null(leaf->value.subvalue->value->canonized);
+    assert_null(leaf->value.subvalue->value->canonical_cache); /* instance-identifier does not have canonical form */
     lyd_free_all(tree);
 
     data = "<leaflisttarget xmlns=\"urn:tests:types\">x</leaflisttarget><leaflisttarget xmlns=\"urn:tests:types\">y</leaflisttarget>"
@@ -1346,11 +1355,12 @@
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("un1", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
-    assert_string_equal("/a:leaflisttarget[3]", leaf->value.canonized);
+    assert_string_equal("/a:leaflisttarget[3]", leaf->value.original);
+    assert_null(leaf->value.canonical_cache);
     assert_non_null(leaf->value.subvalue->prefixes);
     assert_int_equal(LY_TYPE_UNION, leaf->value.realtype->basetype);
     assert_int_equal(LY_TYPE_STRING, leaf->value.subvalue->value->realtype->basetype);
-    assert_string_equal("/a:leaflisttarget[3]", leaf->value.subvalue->value->canonized);
+    assert_string_equal("/a:leaflisttarget[3]", leaf->value.subvalue->value->canonical_cache);
     lyd_free_all(tree);
 
     data = "<un1 xmlns=\"urn:tests:types\">123456789012345678901</un1>";
diff --git a/tests/src/test_parser_xml.c b/tests/src/test_parser_xml.c
index 39d5d5c..f5c7d31 100644
--- a/tests/src/test_parser_xml.c
+++ b/tests/src/test_parser_xml.c
@@ -115,7 +115,7 @@
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("foo", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
-    assert_string_equal("foo value", leaf->value.canonized);
+    assert_string_equal("foo value", leaf->value.original);
 
     lyd_free_all(tree);
     *state = NULL;
diff --git a/tests/src/test_tree_schema_compile.c b/tests/src/test_tree_schema_compile.c
index ea5608c..20b688b 100644
--- a/tests/src/test_tree_schema_compile.c
+++ b/tests/src/test_tree_schema_compile.c
@@ -578,7 +578,7 @@
     assert_non_null(l = (struct lysc_node_leaf*)mod->compiled->data);
     assert_string_equal("ref", l->name);
     assert_non_null(l->dflt);
-    assert_null(l->dflt->canonized);
+    assert_null(l->dflt->canonical_cache);
 
     /* invalid */
     assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa;leaf-list ll {type empty;}}", LYS_IN_YANG));
@@ -3149,6 +3149,7 @@
     assert_int_equal(0, dynamic);
     assert_int_equal(1, llist->dflts[0]->uint8);
 
+    /* instance-identifiers with NULL canonical_cach are changed to string types with a canonical_cache value equal to the original value */
     assert_non_null(mod = lys_parse_mem(ctx, "module q {yang-version 1.1; namespace urn:q;prefix q; import e {prefix e;}"
                                         "leaf q {type instance-identifier; default \"/e:d2\";}"
                                         "leaf-list ql {type instance-identifier; default \"/e:d\"; default \"/e:d2\";}}", LYS_IN_YANG));
@@ -3157,17 +3158,17 @@
                                   "deviation /q:ql { deviate replace {type string;}}}", LYS_IN_YANG));
     assert_non_null(leaf = (struct lysc_node_leaf*)mod->compiled->data);
     assert_int_equal(LY_TYPE_STRING, leaf->dflt->realtype->basetype);
-    assert_non_null(leaf->dflt->canonized);
-    assert_string_equal("/e:d2", leaf->dflt->canonized);
+    assert_non_null(leaf->dflt->canonical_cache);
+    assert_string_equal("/e:d2", leaf->dflt->canonical_cache);
     assert_non_null(llist = (struct lysc_node_leaflist*)leaf->next);
     assert_int_equal(2, LY_ARRAY_SIZE(llist->dflts));
     assert_int_equal(2, LY_ARRAY_SIZE(llist->dflts_mods));
     assert_ptr_equal(llist->dflts_mods[0], mod);
     assert_int_equal(LY_TYPE_STRING, llist->dflts[0]->realtype->basetype);
-    assert_string_equal("/e:d", llist->dflts[0]->canonized);
+    assert_string_equal("/e:d", llist->dflts[0]->canonical_cache);
     assert_ptr_equal(llist->dflts_mods[1], mod);
     assert_int_equal(LY_TYPE_STRING, llist->dflts[0]->realtype->basetype);
-    assert_string_equal("/e:d2", llist->dflts[1]->canonized);
+    assert_string_equal("/e:d2", llist->dflts[1]->canonical_cache);
 
     assert_non_null(mod = lys_parse_mem(ctx, "module r {yang-version 1.1; namespace urn:r;prefix r;"
                                         "typedef mytype {type uint8; default 200;}"