data parser CHANGE unify API with schema parser and use input handler
diff --git a/src/context.c b/src/context.c
index 62f3de7..a0f432c 100644
--- a/src/context.c
+++ b/src/context.c
@@ -27,6 +27,7 @@
 
 #include "common.h"
 #include "hash_table.h"
+#include "parser_data.h"
 #include "plugins_types.h"
 #include "set.h"
 #include "tree.h"
@@ -771,7 +772,7 @@
         root_bis = 0;
     }
 
-    if (lyd_validate(&root, NULL, LYD_VALOPT_DATA_ONLY)) {
+    if (lyd_validate(&root, NULL, LYD_VALIDATE_PRESENT)) {
         goto error;
     }
 
diff --git a/src/libyang.h b/src/libyang.h
index 18c5de5..14eb110 100644
--- a/src/libyang.h
+++ b/src/libyang.h
@@ -25,6 +25,7 @@
 #include "dict.h"
 #include "log.h"
 #include "parser.h"
+#include "parser_data.h"
 #include "parser_schema.h"
 #include "plugins_types.h"
 #include "printer.h"
diff --git a/src/lyb.h b/src/lyb.h
index e5bf309..5e14a03 100644
--- a/src/lyb.h
+++ b/src/lyb.h
@@ -39,7 +39,13 @@
 
     size_t byte_count;  /**< printed/parsed bytes */
     const struct ly_ctx *ctx;
-    int options;
+    union {
+        struct {
+            int parse_options;
+            int validate_options;
+        };
+        int print_options;
+    };
 
     /* LYB parser only */
     const char *data;
diff --git a/src/parser_data.h b/src/parser_data.h
new file mode 100644
index 0000000..cf48c7d
--- /dev/null
+++ b/src/parser_data.h
@@ -0,0 +1,290 @@
+/**
+ * @file parser_data.h
+ * @author Radek Krejci <rkrejci@cesnet.cz>
+ * @brief Data parsers for libyang
+ *
+ * Copyright (c) 2015-2020 CESNET, z.s.p.o.
+ *
+ * This source code is licensed under BSD 3-Clause License (the "License").
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://opensource.org/licenses/BSD-3-Clause
+ */
+
+#ifndef LY_PARSER_DATA_H_
+#define LY_PARSER_DATA_H_
+
+#include "tree_data.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct ly_in;
+
+/**
+ * @addtogroup datatree
+ * @{
+ */
+
+/**
+ * @defgroup dataparseroptions Data parser options
+ *
+ * Various options to change the data tree parsers behavior.
+ *
+ * Default parser behavior:
+ * - complete input file is always parsed. In case of XML, even not well-formed XML document (multiple top-level
+ * elements) is parsed in its entirety,
+ * - parser silently ignores data without matching schema node definition,
+ * - list instances are checked whether they have all the keys, error is raised if not.
+ *
+ * Default parser validation behavior:
+ * - the provided data are expected to provide complete datastore content (both the configuration and state data)
+ * and performs data validation according to all YANG rules, specifics follow,
+ * - list instances are expected to have all the keys (it is not checked),
+ * - instantiated (status) obsolete data print a warning,
+ * - all types are fully resolved (leafref/instance-identifier targets, unions) and must be valid (lists have
+ * all the keys, leaf(-lists) correct values),
+ * - when statements on existing nodes are evaluated, if not satisfied, a validation error is raised,
+ * - if-feature statements are evaluated,
+ * - invalid multiple data instances/data from several cases cause a validation error,
+ * - default values are added.
+ * @{
+ */
+/* note: keep the lower 16bits free for use by LYD_VALIDATE_ flags. They are not supposed to be combined together,
+ * but since they are used (as a separate parameter) together in some functions, we want to keep them in a separated
+ * range to be able detect that the caller put wrong flags into the parser/validate options parameter. */
+#define LYD_PARSE_ONLY      0x010000        /**< Data will be only parsed and no validation will be performed. When statements
+                                                 are kept unevaluated, union types may not be fully resolved, if-feature
+                                                 statements are not checked, and default values are not added (only the ones
+                                                 parsed are present). */
+#define LYD_PARSE_TRUSTED   0x020000        /**< Data are considered trusted so they will be parsed as validated. If the parsed
+                                                 data are not valid, using this flag may lead to some unexpected behavior!
+                                                 This flag can be used only with #LYD_OPT_PARSE_ONLY. */
+#define LYD_PARSE_STRICT    0x040000        /**< Instead of silently ignoring data without schema definition raise an error.
+                                                 Do not combine with #LYD_OPT_OPAQ. */
+#define LYD_PARSE_OPAQ      0x080000        /**< Instead of silently ignoring data without definition, parse them into
+                                                 an opaq node. Do not combine with #LYD_OPT_STRICT and use only for a generic
+                                                 YANG data tree (opaq Notifications, RPCs or actions are not allowed). */
+#define LYD_PARSE_NO_STATE  0x100000        /**< Forbid state data in the parsed data. */
+
+#define LYD_PARSE_LYB_MOD_UPDATE  0x200000  /**< Only for LYB format, allow parsing data printed using a specific module
+                                                 revision to be loaded even with a module with the same name but newer
+                                                 revision. */
+/** @} dataparseroptions */
+
+
+/**
+ * @defgroup datavalidationoptions Data validation options
+ * @ingroup datatree
+ *
+ * Various options to change data validation behaviour, both for the parser and separate validation.
+ *
+ * Default separate validation behavior:
+ * - the provided data are expected to provide complete datastore content (both the configuration and state data)
+ * and performs data validation according to all YANG rules, specifics follow,
+ * - instantiated (status) obsolete data print a warning,
+ * - all types are fully resolved (leafref/instance-identifier targets, unions) and must be valid (lists have
+ * all the keys, leaf(-lists) correct values),
+ * - when statements on existing nodes are evaluated. Depending on the previous when state (from previous validation
+ * or parsing), the node is silently auto-deleted if the state changed from true to false, otherwise a validation error
+ * is raised if it evaluates to false,
+ * - if-feature statements are evaluated,
+ * - data from several cases behave based on their previous state (from previous validation or parsing). If there existed
+ * already a case and another one was added, the previous one is silently auto-deleted. Otherwise (if data from 2 or
+ * more cases were created) a validation error is raised,
+ * - default values are added.
+ *
+ * @{
+ */
+#define LYD_VALIDATE_NO_STATE     0x0001    /**< Consider state data not allowed and raise an error if they are found. */
+#define LYD_VALIDATE_PRESENT      0x0002    /**< Validate only modules whose data actually exist. */
+//#define LYD_VALIDATE_DIFF         0x0004    /**< Flag only for validation, store all the data node changes performed by the validation
+//                                                 in a diff structure. */
+//#define LYD_VALIDATE_DATA_TEMPLATE 0x0008   /**< Data represents YANG data template. */
+
+/** @} datavalidationoptions */
+
+/**
+ * @defgroup datavalidateop Operation to validate
+ * @ingroup datatree
+ *
+ * Operation provided to lyd_validate_op() to validate. The operation cannot be determined automatically since RPC/action and a reply to it
+ * share the common top level node referencing the RPC/action schema node and may not have any input/output children to use for distinction.
+ */
+typedef enum {
+    LYD_VALIDATE_OP_RPC = 1,   /**< Validate RPC/action request (input parameters). */
+    LYD_VALIDATE_OP_REPLY,     /**< Validate RPC/action reply (output parameters). */
+    LYD_VALIDATE_OP_NOTIF      /**< Validate Notification operation. */
+} LYD_VALIDATE_OP;
+
+/** @} datavalidateop */
+
+/**
+ * @brief Parse (and validate) data from the input handler as a YANG data tree.
+ *
+ * @param[in] ctx Context to connect with the tree being built here.
+ * @param[in] in The input handle to provide the dumped data in the specified @p format to parse (and validate).
+ * @param[in] format Format of the input data to be parsed. Can be 0 to try to detect format from the input handler.
+ * @param[in] parse_options Options for parser, see @ref dataparseroptions.
+ * @param[in] validate_options Options for the validation phase, see @ref datavalidationoptions.
+ * @param[out] tree Resulting data tree built from the input data. Note that NULL can be a valid result as a representation of an empty YANG data tree.
+ * The returned data are expected to be freed using lyd_free_all().
+ * @return LY_SUCCESS in case of successful parsing (and validation).
+ * @reutnr LY_ERR value in case of error. Additional error information can be obtained from the context using ly_err* functions.
+ */
+LY_ERR lyd_parse_data(const struct ly_ctx *ctx, struct ly_in *in, LYD_FORMAT format, int parse_options, int validate_options, struct lyd_node **tree);
+
+/**
+ * @brief Parse (and validate) input data as a YANG data tree.
+ *
+ * Wrapper around lyd_parse_data() hiding work with the input handler.
+ *
+ * @param[in] ctx Context to connect with the tree being built here.
+ * @param[in] data The input data in the specified @p format to parse (and validate).
+ * @param[in] format Format of the input data to be parsed. Can be 0 to try to detect format from the input handler.
+ * @param[in] parse_options Options for parser, see @ref dataparseroptions.
+ * @param[in] validate_options Options for the validation phase, see @ref datavalidationoptions.
+ * @param[out] tree Resulting data tree built from the input data. Note that NULL can be a valid result as a representation of an empty YANG data tree.
+ * The returned data are expected to be freed using lyd_free_all().
+ * @return LY_SUCCESS in case of successful parsing (and validation).
+ * @reutnr LY_ERR value in case of error. Additional error information can be obtained from the context using ly_err* functions.
+ */
+LY_ERR lyd_parse_data_mem(const struct ly_ctx *ctx, const char *data, LYD_FORMAT format, int parse_options, int validate_options, struct lyd_node **tree);
+
+/**
+ * @brief Parse (and validate) input data as a YANG data tree.
+ *
+ * Wrapper around lyd_parse_data() hiding work with the input handler.
+ *
+ * @param[in] ctx Context to connect with the tree being built here.
+ * @param[in] fd File descriptor of a regular file (e.g. sockets are not supported) containing the input data in the specified @p format to parse (and validate).
+ * @param[in] format Format of the input data to be parsed. Can be 0 to try to detect format from the input handler.
+ * @param[in] parse_options Options for parser, see @ref dataparseroptions.
+ * @param[in] validate_options Options for the validation phase, see @ref datavalidationoptions.
+ * @param[out] tree Resulting data tree built from the input data. Note that NULL can be a valid result as a representation of an empty YANG data tree.
+ * The returned data are expected to be freed using lyd_free_all().
+ * @return LY_SUCCESS in case of successful parsing (and validation).
+ * @reutnr LY_ERR value in case of error. Additional error information can be obtained from the context using ly_err* functions.
+ */
+LY_ERR lyd_parse_data_fd(const struct ly_ctx *ctx, int fd, LYD_FORMAT format, int parse_options, int validate_options, struct lyd_node **tree);
+
+/**
+ * @brief Parse (and validate) input data as a YANG data tree.
+ *
+ * Wrapper around lyd_parse_data() hiding work with the input handler.
+ *
+ * @param[in] ctx Context to connect with the tree being built here.
+ * @param[in] path Path to the file with the input data in the specified @p format to parse (and validate).
+ * @param[in] format Format of the input data to be parsed. Can be 0 to try to detect format from the input handler.
+ * @param[in] parse_options Options for parser, see @ref dataparseroptions.
+ * @param[in] validate_options Options for the validation phase, see @ref datavalidationoptions.
+ * @param[out] tree Resulting data tree built from the input data. Note that NULL can be a valid result as a representation of an empty YANG data tree.
+ * The returned data are expected to be freed using lyd_free_all().
+ * @return LY_SUCCESS in case of successful parsing (and validation).
+ * @reutnr LY_ERR value in case of error. Additional error information can be obtained from the context using ly_err* functions.
+ */
+LY_ERR lyd_parse_data_path(const struct ly_ctx *ctx, const char *path, LYD_FORMAT format, int parse_options, int validate_options, struct lyd_node **tree);
+
+/**
+ * @brief Parse (and validate) data from the input handler as a YANG RPC/action invocation.
+ *
+ * In case o LYD_XML @p format, the \<rpc\> envelope element is accepted if present. It is [checked](https://tools.ietf.org/html/rfc6241#section-4.1), an opaq
+ * data node (lyd_node_opaq) is created and all its XML attributes are parsed and inserted into the node. As a content of the enveloper, an RPC data or
+ * \<action\> envelope element is expected. The \<action\> envelope element is also [checked](https://tools.ietf.org/html/rfc7950#section-7.15.2) and parsed as
+ * the \<rpc\> envelope. Inside the \<action\> envelope, only an action data are expected.
+ *
+ * @param[in] ctx Context to connect with the tree being built here.
+ * @param[in] in The input handle to provide the dumped data in the specified @p format to parse (and validate).
+ * @param[in] format Format of the input data to be parsed.
+ * @param[out] tree Resulting full RPC/action tree built from the input data. The returned data are expected to be freed using lyd_free_all().
+ * In contrast to YANG data tree, result of parsing RPC/action cannot be NULL until an error occurs.
+ * @param[out] op Optional pointer to the actual operation node inside the full action @p tree, useful only for action.
+ * @return LY_SUCCESS in case of successful parsing (and validation).
+ * @reutnr LY_ERR value in case of error. Additional error information can be obtained from the context using ly_err* functions.
+ */
+LY_ERR lyd_parse_rpc(const struct ly_ctx *ctx, struct ly_in *in, LYD_FORMAT format, struct lyd_node **tree, struct lyd_node **op);
+
+/**
+ * @brief Parse (and validate) data from the input handler as a YANG RPC/action reply.
+ *
+ * In case o LYD_XML @p format, the \<rpc-reply\> envelope element is accepted if present. It is [checked](https://tools.ietf.org/html/rfc6241#section-4.2), an opaq
+ * data node (lyd_node_opaq) is created and all its XML attributes are parsed and inserted into the node.
+ *
+ * The reply data are strictly expected to be related to the provided RPC/action @p request.
+ *
+ * @param[in] request The RPC/action tree (result of lyd_parse_rpc()) of the request for the reply being parsed.
+ * @param[in] in The input handle to provide the dumped data in the specified @p format to parse (and validate).
+ * @param[in] format Format of the input data to be parsed.
+ * @param[out] tree Resulting full RPC/action reply tree built from the input data. The returned data are expected to be freed using lyd_free_all().
+ * The reply tree always includes duplicated operation node (and its parents) of the @p request, so in contrast to YANG data tree,
+ * the result of parsing RPC/action reply cannot be NULL until an error occurs.
+ * @param[out] op Optional pointer to the actual operation node inside the full action reply @p tree, useful only for action.
+ * @return LY_SUCCESS in case of successful parsing (and validation).
+ * @reutnr LY_ERR value in case of error. Additional error information can be obtained from the request's context using ly_err* functions.
+ */
+LY_ERR lyd_parse_reply(const struct lyd_node *request, struct ly_in *in, LYD_FORMAT format, struct lyd_node **tree, struct lyd_node **op);
+
+/**
+ * @brief Parse XML string as YANG notification.
+ *
+ * In case o LYD_XML @p format, the \<notification\> envelope element in combination with the child \<eventTime\> element are accepted if present. They are
+ * [checked](https://tools.ietf.org/html/rfc5277#page-25), opaq data nodes (lyd_node_opaq) are created and all their XML attributes are parsed and inserted into the nodes.
+ *
+ * @param[in] ctx Context to connect with the tree being built here.
+ * @param[in] in The input handle to provide the dumped data in the specified @p format to parse (and validate).
+ * @param[in] format Format of the input data to be parsed.
+ * @param[out] tree Resulting full Notification tree built from the input data. The returned data are expected to be freed using lyd_free_all().
+ * In contrast to YANG data tree, result of parsing Notification cannot be NULL until an error occurs.
+ * @param[out] ntf Optional pointer to the actual notification node inside the full Notification @p tree, useful for nested notifications.
+ * @return LY_SUCCESS in case of successful parsing (and validation).
+ * @reutnr LY_ERR value in case of error. Additional error information can be obtained from the context using ly_err* functions.
+ */
+LY_ERR lyd_parse_notif(const struct ly_ctx *ctx, struct ly_in *in, LYD_FORMAT format, struct lyd_node **tree, struct lyd_node **ntf);
+
+/**
+ * @brief Fully validate a data tree.
+ *
+ * @param[in,out] tree Data tree to recursively validate. May be changed by validation.
+ * @param[in] ctx libyang context. Can be NULL if @p tree is set.
+ * @param[in] val_opts Validation options (@ref datavalidationoptions).
+ * @return LY_SUCCESS on success.
+ * @return LY_ERR error on error.
+ */
+LY_ERR lyd_validate(struct lyd_node **tree, const struct ly_ctx *ctx, int val_opts);
+
+/**
+ * @brief Fully validate a data tree.
+ *
+ * @param[in,out] tree Data tree to recursively validate. May be changed by validation.
+ * @param[in] modules Array of modules to validate.
+ * @param[in] mod_count Number of @p modules.
+ * @param[in] val_opts Validation options (@ref datavalidationoptions).
+ * @return LY_SUCCESS on success.
+ * @return LY_ERR error on error.
+ */
+LY_ERR lyd_validate_modules(struct lyd_node **tree, const struct lys_module **modules, int mod_count, int val_opts);
+
+/**
+ * @brief Validate an RPC/action, notification, or RPC/action reply.
+ *
+ * @param[in,out] op_tree Operation tree with any parents. It can point to the operation itself or any of
+ * its parents, only the operation subtree is actually validated.
+ * @param[in] tree Tree to be used for validating references from the operation subtree.
+ * @param[in] op Operation to validate (@ref datavalidateop), the given @p op_tree must correspond to this value. Note that
+ * it isn't possible to detect the operation simply from the @p op_tree since RPC/action and their reply share the same
+ * RPC/action data node and in case one of the input and output do not define any data node children, it is not passible
+ * to get know what is here given for validation and if it is really valid.
+ * @return LY_SUCCESS on success.
+ * @return LY_ERR error on error.
+ */
+LY_ERR lyd_validate_op(struct lyd_node *op_tree, const struct lyd_node *tree, LYD_VALIDATE_OP op);
+
+/** @} datatree */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LY_PARSER_DATA_H_ */
diff --git a/src/parser_internal.h b/src/parser_internal.h
index 9dc3c50..d90c504 100644
--- a/src/parser_internal.h
+++ b/src/parser_internal.h
@@ -19,6 +19,16 @@
 #include "tree_schema_internal.h"
 
 /**
+ * @brief Mask for checking LYD_PARSE_ options (@ref dataparseroptions)
+ */
+#define LYD_PARSE_OPTS_MASK    0xFFFF0000
+
+/**
+ * @brief Mask for checking LYD_VALIDATEP_ options (@ref datavalidationoptions)
+ */
+#define LYD_VALIDATE_OPTS_MASK 0x0000FFFF
+
+/**
  * @brief Parser input structure specifying where the data are read.
  */
 struct ly_in {
diff --git a/src/parser_lyb.c b/src/parser_lyb.c
index 74ff62b..d9366f8 100644
--- a/src/parser_lyb.c
+++ b/src/parser_lyb.c
@@ -25,6 +25,8 @@
 #include "context.h"
 #include "dict.h"
 #include "log.h"
+#include "parser_data.h"
+#include "parser_internal.h"
 #include "set.h"
 #include "tree.h"
 #include "tree_data_internal.h"
@@ -272,7 +274,7 @@
     if (rev) {
         sprintf(mod_rev, "%04u-%02u-%02u", ((rev & 0xFE00) >> 9) + 2000, (rev & 0x01E0) >> 5, rev & 0x001Fu);
         *mod = ly_ctx_get_module(lybctx->ctx, mod_name, mod_rev);
-        if ((lybctx->options & LYD_OPT_LYB_MOD_UPDATE) && !(*mod)) {
+        if ((lybctx->parse_options & LYD_PARSE_LYB_MOD_UPDATE) && !(*mod)) {
             /* try to use an updated module */
             *mod = ly_ctx_get_module_implemented(lybctx->ctx, mod_name);
             if (*mod && (!(*mod)->revision || (strcmp((*mod)->revision, mod_rev) < 0))) {
@@ -293,7 +295,7 @@
     }*/
 
     if (!*mod || !(*mod)->implemented) {
-        if (lybctx->options & LYD_OPT_STRICT) {
+        if (lybctx->parse_options & LYD_PARSE_STRICT) {
             if (!*mod) {
                 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid context for LYB data parsing, missing module \"%s%s%s\".",
                     mod_name, rev ? "@" : "", rev ? mod_rev : "");
@@ -571,7 +573,7 @@
 {
     LY_ERR ret = LY_SUCCESS;
 
-    if ((lybctx->options & LYD_OPT_NO_STATE) && (snode->flags & LYS_CONFIG_R)) {
+    if ((lybctx->parse_options & LYD_PARSE_NO_STATE) && (snode->flags & LYS_CONFIG_R)) {
         LOGVAL(lybctx->ctx, LY_VLOG_LYSC, snode, LY_VCODE_INNODE, "state", snode->name);
         return LY_EVALID;
     }
@@ -669,7 +671,7 @@
         }
     }
 
-    if (!sibling && (lybctx->options & LYD_OPT_STRICT)) {
+    if (!sibling && (lybctx->parse_options & LYD_PARSE_STRICT)) {
         if (mod) {
             LOGVAL(lybctx->ctx, LY_VLOG_NONE, NULL, LYVE_REFERENCE, "Failed to find matching hash for a top-level node"
                    " from \"%s\".", mod->name);
@@ -748,7 +750,7 @@
         LY_CHECK_GOTO(ret, cleanup);
     }
 
-     if (!snode && !(lybctx->options & LYD_OPT_OPAQ)) {
+     if (!snode && !(lybctx->parse_options & LYD_PARSE_OPAQ)) {
         /* unknown data, skip them */
         lyb_skip_subtree(lybctx);
         goto stop_subtree;
@@ -812,7 +814,7 @@
         }
         value = NULL;
         if (ret == LY_EINCOMPLETE) {
-            if (!(lybctx->options & LYD_OPT_PARSE_ONLY)) {
+            if (!(lybctx->parse_options & LYD_PARSE_ONLY)) {
                 ly_set_add(&lybctx->unres_node_type, node, LY_SET_OPT_USEASLIST);
             }
             ret = LY_SUCCESS;
@@ -830,14 +832,14 @@
             LY_CHECK_GOTO(ret, cleanup);
         }
 
-        if (!(lybctx->options & LYD_OPT_PARSE_ONLY)) {
+        if (!(lybctx->parse_options & LYD_PARSE_ONLY)) {
             /* new node validation, autodelete CANNOT occur, all nodes are new */
             ret = lyd_validate_new(lyd_node_children_p(node), snode, NULL);
             LY_CHECK_GOTO(ret, cleanup);
 
             /* add any missing default children */
             ret = lyd_validate_defaults_r((struct lyd_node_inner *)node, lyd_node_children_p(node), NULL, NULL,
-                                          &lybctx->unres_node_type, &lybctx->when_check, lybctx->options);
+                                          &lybctx->unres_node_type, &lybctx->when_check, lybctx->validate_options);
             LY_CHECK_GOTO(ret, cleanup);
         }
 
@@ -867,15 +869,15 @@
             prev_lo = ly_log_options(0);
 
             /* try to parse LYB into a data tree */
-            tree = lyd_parse_mem((struct ly_ctx *)lybctx->ctx, value, LYD_LYB,
-                                 LYD_OPT_PARSE_ONLY | LYD_OPT_OPAQ | LYD_OPT_STRICT);
-            ly_log_options(prev_lo);
-            if (!ly_errcode(lybctx->ctx)) {
+            if (lyd_parse_data_mem((struct ly_ctx *)lybctx->ctx, value, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_OPAQ | LYD_PARSE_STRICT, 0, &tree) == LY_SUCCESS) {
                 /* successfully parsed */
                 free(value);
                 value = (char *)tree;
                 value_type = LYD_ANYDATA_DATATREE;
             }
+
+            /* turn logging on again */
+            ly_log_options(prev_lo);
         }
 
         /* create node */
@@ -889,7 +891,7 @@
 
     /* add/correct flags */
     if (snode) {
-        lyd_parse_set_data_flags(node, &lybctx->when_check, &meta, lybctx->options);
+        lyd_parse_set_data_flags(node, &lybctx->when_check, &meta, lybctx->parse_options);
     }
 
     /* add metadata/attributes */
@@ -1018,16 +1020,20 @@
 }
 
 LY_ERR
-lyd_parse_lyb_data(struct ly_ctx *ctx, const char *data, int options, struct lyd_node **tree, int *parsed_bytes)
+lyd_parse_lyb_data(const struct ly_ctx *ctx, const char *data, int parse_options, int validate_options, struct lyd_node **tree, int *parsed_bytes)
 {
     LY_ERR ret = LY_SUCCESS;
     struct lyd_lyb_ctx lybctx = {0};
 
+    assert(!(parse_options & ~LYD_PARSE_OPTS_MASK));
+    assert(!(validate_options & ~LYD_VALIDATE_OPTS_MASK));
+
     *tree = NULL;
 
     lybctx.data = data;
     lybctx.ctx = ctx;
-    lybctx.options = options;
+    lybctx.parse_options = parse_options;
+    lybctx.validate_options = validate_options;
 
     /* read magic number */
     ret = lyb_parse_magic_number(&lybctx);
@@ -1071,14 +1077,14 @@
 }
 
 LY_ERR
-lyd_parse_lyb_rpc(struct ly_ctx *ctx, const char *data, struct lyd_node **tree, struct lyd_node **op, int *parsed_bytes)
+lyd_parse_lyb_rpc(const struct ly_ctx *ctx, const char *data, struct lyd_node **tree, struct lyd_node **op, int *parsed_bytes)
 {
     LY_ERR ret = LY_SUCCESS;
     struct lyd_lyb_ctx lybctx = {0};
 
     lybctx.data = data;
     lybctx.ctx = ctx;
-    lybctx.options = LYD_OPT_PARSE_ONLY | LYD_OPT_STRICT;
+    lybctx.parse_options = LYD_PARSE_ONLY | LYD_PARSE_STRICT;
     lybctx.int_opts = LYD_INTOPT_RPC;
 
     *tree = NULL;
@@ -1136,14 +1142,14 @@
 }
 
 LY_ERR
-lyd_parse_lyb_notif(struct ly_ctx *ctx, const char *data, struct lyd_node **tree, struct lyd_node **ntf, int *parsed_bytes)
+lyd_parse_lyb_notif(const struct ly_ctx *ctx, const char *data, struct lyd_node **tree, struct lyd_node **ntf, int *parsed_bytes)
 {
     LY_ERR ret = LY_SUCCESS;
     struct lyd_lyb_ctx lybctx = {0};
 
     lybctx.data = data;
     lybctx.ctx = ctx;
-    lybctx.options = LYD_OPT_PARSE_ONLY | LYD_OPT_STRICT;
+    lybctx.parse_options = LYD_PARSE_ONLY | LYD_PARSE_STRICT;
     lybctx.int_opts = LYD_INTOPT_NOTIF;
 
     *tree = NULL;
@@ -1201,7 +1207,7 @@
 }
 
 LY_ERR
-lyd_parse_lyb_reply(struct lyd_node *request, const char *data, struct lyd_node **tree, struct lyd_node **op,
+lyd_parse_lyb_reply(const struct lyd_node *request, const char *data, struct lyd_node **tree, struct lyd_node **op,
                     int *parsed_bytes)
 {
     LY_ERR ret = LY_SUCCESS;
@@ -1210,7 +1216,7 @@
 
     lybctx.data = data;
     lybctx.ctx = LYD_NODE_CTX(request);
-    lybctx.options = LYD_OPT_PARSE_ONLY | LYD_OPT_STRICT;
+    lybctx.parse_options = LYD_PARSE_ONLY | LYD_PARSE_STRICT;
     lybctx.int_opts = LYD_INTOPT_REPLY;
 
     *tree = NULL;
diff --git a/src/parser_xml.c b/src/parser_xml.c
index a50ee05..2aae751 100644
--- a/src/parser_xml.c
+++ b/src/parser_xml.c
@@ -20,6 +20,8 @@
 #include "common.h"
 #include "context.h"
 #include "log.h"
+#include "parser_data.h"
+#include "parser_internal.h"
 #include "set.h"
 #include "tree.h"
 #include "tree_data_internal.h"
@@ -313,7 +315,7 @@
     size_t pprefix_len, pname_len;
     struct lyxml_ctx *xmlctx = lydctx->xmlctx;
 
-    if ((lydctx->options & LYD_OPT_NO_STATE) && ((*snode)->flags & LYS_CONFIG_R)) {
+    if ((lydctx->options & LYD_PARSE_NO_STATE) && ((*snode)->flags & LYS_CONFIG_R)) {
         LOGVAL(xmlctx->ctx, LY_VLOG_LINE, &xmlctx->line, LY_VCODE_INNODE, "state", (*snode)->name);
         return LY_EVALID;
     }
@@ -346,7 +348,7 @@
         }
     }
 
-    if ((lydctx->options & LYD_OPT_OPAQ) && ((*snode)->nodetype & (LYD_NODE_TERM | LYS_LIST))) {
+    if ((lydctx->options & LYD_PARSE_OPAQ) && ((*snode)->nodetype & (LYD_NODE_TERM | LYS_LIST))) {
         /* backup parser */
         prev_status = xmlctx->status;
         pprefix = xmlctx->prefix;
@@ -444,13 +446,13 @@
         }
         mod = ly_ctx_get_module_implemented_ns(ctx, ns->uri);
         if (!mod) {
-            if (lydctx->options & LYD_OPT_STRICT) {
+            if (lydctx->options & LYD_PARSE_STRICT) {
                 LOGVAL(ctx, LY_VLOG_LINE, &xmlctx->line, LYVE_REFERENCE, "No module with namespace \"%s\" in the context.",
                        ns->uri);
                 ret = LY_EVALID;
                 goto cleanup;
             }
-            if (!(lydctx->options & LYD_OPT_OPAQ)) {
+            if (!(lydctx->options & LYD_PARSE_OPAQ)) {
                 /* skip element with children */
                 LY_CHECK_GOTO(ret = lydxml_data_skip(xmlctx), cleanup);
                 continue;
@@ -465,12 +467,12 @@
         if (mod && (!parent || parent->schema)) {
             snode = lys_find_child(parent ? parent->schema : NULL, mod, name, name_len, 0, getnext_opts);
             if (!snode) {
-                if (lydctx->options & LYD_OPT_STRICT) {
+                if (lydctx->options & LYD_PARSE_STRICT) {
                     LOGVAL(ctx, LY_VLOG_LINE, &xmlctx->line, LYVE_REFERENCE, "Element \"%.*s\" not found in the \"%s\" module.",
                         name_len, name, mod->name);
                     ret = LY_EVALID;
                     goto cleanup;
-                } else if (!(lydctx->options & LYD_OPT_OPAQ)) {
+                } else if (!(lydctx->options & LYD_PARSE_OPAQ)) {
                     /* skip element with children */
                     LY_CHECK_GOTO(ret = lydxml_data_skip(xmlctx), cleanup);
                     continue;
@@ -484,10 +486,10 @@
         /* create metadata/attributes */
         if (xmlctx->status == LYXML_ATTRIBUTE) {
             if (snode) {
-                ret = lydxml_metadata(xmlctx, snode, lydctx->options & LYD_OPT_STRICT, &lydctx->unres_meta_type, &meta);
+                ret = lydxml_metadata(xmlctx, snode, lydctx->options & LYD_PARSE_STRICT, &lydctx->unres_meta_type, &meta);
                 LY_CHECK_GOTO(ret, cleanup);
             } else {
-                assert(lydctx->options & LYD_OPT_OPAQ);
+                assert(lydctx->options & LYD_PARSE_OPAQ);
                 ret = lydxml_attrs(xmlctx, &attr);
                 LY_CHECK_GOTO(ret, cleanup);
             }
@@ -495,7 +497,7 @@
 
         assert(xmlctx->status == LYXML_ELEM_CONTENT);
         if (!snode) {
-            assert(lydctx->options & LYD_OPT_OPAQ);
+            assert(lydctx->options & LYD_PARSE_OPAQ);
 
             if (xmlctx->ws_only) {
                 /* ignore WS-only value */
@@ -525,7 +527,7 @@
             ret = lyd_create_term(snode, xmlctx->value, xmlctx->value_len, &xmlctx->dynamic, lydxml_resolve_prefix,
                                   xmlctx, LYD_XML, &cur);
             if (ret == LY_EINCOMPLETE) {
-                if (!(lydctx->options & LYD_OPT_PARSE_ONLY)) {
+                if (!(lydctx->options & LYD_PARSE_ONLY)) {
                     ly_set_add(&lydctx->unres_node_type, cur, LY_SET_OPT_USEASLIST);
                 }
             } else if (ret) {
@@ -536,7 +538,7 @@
                 /* check the key order, the anchor must always be the last child */
                 anchor = lyd_get_prev_key_anchor(parent->child, cur->schema);
                 if ((!anchor && parent->child) || (anchor && anchor->next)) {
-                    if (lydctx->options & LYD_OPT_STRICT) {
+                    if (lydctx->options & LYD_PARSE_STRICT) {
                         LOGVAL(ctx, LY_VLOG_LINE, &xmlctx->line, LYVE_DATA, "Invalid position of the key \"%s\" in a list.",
                                 cur->schema->name);
                         ret = LY_EVALID;
@@ -584,7 +586,7 @@
                 LY_CHECK_GOTO(ret = lyd_parse_check_keys(cur), cleanup);
             }
 
-            if (!(lydctx->options & LYD_OPT_PARSE_ONLY)) {
+            if (!(lydctx->options & LYD_PARSE_ONLY)) {
                 /* new node validation, autodelete CANNOT occur, all nodes are new */
                 ret = lyd_validate_new(lyd_node_children_p(cur), snode, NULL);
                 LY_CHECK_GOTO(ret, cleanup);
@@ -616,8 +618,8 @@
 
             /* parse any data tree with correct options */
             prev_opts = lydctx->options;
-            lydctx->options &= ~LYD_OPT_STRICT;
-            lydctx->options |= LYD_OPT_OPAQ;
+            lydctx->options &= ~LYD_PARSE_STRICT;
+            lydctx->options |= LYD_PARSE_OPAQ;
             anchor = NULL;
             ret = lydxml_data_r(lydctx, NULL, &anchor);
             lydctx->options = prev_opts;
@@ -674,7 +676,7 @@
 }
 
 LY_ERR
-lyd_parse_xml_data(const struct ly_ctx *ctx, const char *data, int options, struct lyd_node **tree)
+lyd_parse_xml_data(const struct ly_ctx *ctx, const char *data, int parse_options, int validate_options, struct lyd_node **tree)
 {
     LY_ERR ret = LY_SUCCESS;
     struct lyd_xml_ctx lydctx = {0};
@@ -682,18 +684,21 @@
     const struct lys_module *mod;
     struct lyd_node *first, *next, **first2;
 
+    assert(!(parse_options & ~LYD_PARSE_OPTS_MASK));
+    assert(!(validate_options & ~LYD_VALIDATE_OPTS_MASK));
+
     /* init context and tree */
     LY_CHECK_GOTO(ret = lyxml_ctx_new(ctx, data, &lydctx.xmlctx), cleanup);
-    lydctx.options = options;
+    lydctx.options = parse_options;
     *tree = NULL;
 
     /* parse XML data */
     LY_CHECK_GOTO(ret = lydxml_data_r(&lydctx, NULL, tree), cleanup);
 
-    if (!(options & LYD_OPT_PARSE_ONLY)) {
+    if (!(parse_options & LYD_PARSE_ONLY)) {
         next = *tree;
         while (1) {
-            if (options & LYD_VALOPT_DATA_ONLY) {
+            if (validate_options & LYD_VALIDATE_PRESENT) {
                 mod = lyd_data_next_module(&next, &first);
             } else {
                 mod = lyd_mod_next_module(next, NULL, 0, ctx, &i, &first);
@@ -712,8 +717,7 @@
             LY_CHECK_GOTO(ret = lyd_validate_new(first2, NULL, mod), cleanup);
 
             /* add all top-level defaults for this module */
-            ret = lyd_validate_defaults_r(NULL, first2, NULL, mod, &lydctx.unres_node_type, &lydctx.when_check,
-                                          options & LYD_VALOPT_MASK);
+            ret = lyd_validate_defaults_r(NULL, first2, NULL, mod, &lydctx.unres_node_type, &lydctx.when_check, validate_options);
             LY_CHECK_GOTO(ret, cleanup);
 
             /* finish incompletely validated terminal values/attributes and when conditions */
@@ -722,13 +726,13 @@
             LY_CHECK_GOTO(ret, cleanup);
 
             /* perform final validation that assumes the data tree is final */
-            LY_CHECK_GOTO(ret = lyd_validate_final_r(*first2, NULL, mod, options & LYD_VALOPT_MASK), cleanup);
+            LY_CHECK_GOTO(ret = lyd_validate_final_r(*first2, NULL, mod, validate_options, 0), cleanup);
         }
     }
 
 cleanup:
     /* there should be no unresolved types stored */
-    assert(!(options & LYD_OPT_PARSE_ONLY) || (!lydctx.unres_node_type.count && !lydctx.unres_meta_type.count
+    assert(!(parse_options & LYD_PARSE_ONLY) || (!lydctx.unres_node_type.count && !lydctx.unres_meta_type.count
            && !lydctx.when_check.count));
 
     ly_set_erase(&lydctx.unres_node_type, NULL);
@@ -810,7 +814,7 @@
 
     /* init */
     LY_CHECK_GOTO(ret = lyxml_ctx_new(ctx, data, &lydctx.xmlctx), cleanup);
-    lydctx.options = LYD_OPT_PARSE_ONLY | LYD_OPT_STRICT;
+    lydctx.options = LYD_PARSE_ONLY | LYD_PARSE_STRICT;
     lydctx.int_opts = LYD_INTOPT_RPC;
     *tree = NULL;
     if (op) {
@@ -994,7 +998,7 @@
 
     /* init */
     LY_CHECK_GOTO(ret = lyxml_ctx_new(ctx, data, &lydctx.xmlctx), cleanup);
-    lydctx.options = LYD_OPT_PARSE_ONLY | LYD_OPT_STRICT;
+    lydctx.options = LYD_PARSE_ONLY | LYD_PARSE_STRICT;
     lydctx.int_opts = LYD_INTOPT_NOTIF;
     *tree = NULL;
     if (ntf) {
@@ -1057,7 +1061,7 @@
 
     /* init */
     LY_CHECK_GOTO(ret = lyxml_ctx_new(LYD_NODE_CTX(request), data, &lydctx.xmlctx), cleanup);
-    lydctx.options = LYD_OPT_PARSE_ONLY | LYD_OPT_STRICT;
+    lydctx.options = LYD_PARSE_ONLY | LYD_PARSE_STRICT;
     lydctx.int_opts = LYD_INTOPT_REPLY;
     *tree = NULL;
     if (op) {
diff --git a/src/plugins_types.c b/src/plugins_types.c
index df43836..08d33b4 100644
--- a/src/plugins_types.c
+++ b/src/plugins_types.c
@@ -1652,7 +1652,7 @@
                 }
             }
         }
-    } else { /* LYD_JSON */
+    } else if (format == LYD_JSON) {
         /* only the first node or the node changing module is prefixed */
         struct lys_module *mod = NULL;
         LY_ARRAY_FOR(value->target, u) {
@@ -1704,6 +1704,10 @@
                 }
             }
         }
+    } else {
+        /* not supported format */
+        free(result);
+        return NULL;
     }
 
     *dynamic = 1;
diff --git a/src/printer.c b/src/printer.c
index be367d2..a4905c8 100644
--- a/src/printer.c
+++ b/src/printer.c
@@ -114,7 +114,7 @@
 {
     const struct lyd_node *next, *elem;
 
-    if (options & LYDP_WD_TRIM) {
+    if (options & LYD_PRINT_WD_TRIM) {
         /* do not print default nodes */
         if (node->flags & LYD_DEFAULT) {
             /* implicit default node/NP container with only default nodes */
@@ -125,7 +125,7 @@
                 return 0;
             }
         }
-    } else if ((node->flags & LYD_DEFAULT) && !(options & LYDP_WD_MASK) && !(node->schema->flags & LYS_CONFIG_R)) {
+    } else if ((node->flags & LYD_DEFAULT) && !(options & LYD_PRINT_WD_MASK) && !(node->schema->flags & LYS_CONFIG_R)) {
         /* LYDP_WD_EXPLICIT
          * - print only if it contains status data in its subtree */
         LYD_TREE_DFS_BEGIN(node, next, elem) {
@@ -137,7 +137,7 @@
             LYD_TREE_DFS_END(node, next, elem)
         }
         return 0;
-    } else if ((node->flags & LYD_DEFAULT) && (node->schema->nodetype == LYS_CONTAINER) && !(options & LYDP_KEEPEMPTYCONT)) {
+    } else if ((node->flags & LYD_DEFAULT) && (node->schema->nodetype == LYS_CONTAINER) && !(options & LYD_PRINT_KEEPEMPTYCONT)) {
         /* avoid empty default containers */
         LYD_TREE_DFS_BEGIN(node, next, elem) {
             if (elem->schema->nodetype != LYS_CONTAINER) {
diff --git a/src/printer_data.h b/src/printer_data.h
index 31cfc71..31da54e 100644
--- a/src/printer_data.h
+++ b/src/printer_data.h
@@ -35,23 +35,23 @@
  *
  * @{
  */
-#define LYDP_WITHSIBLINGS  0x01  /**< Flag for printing also the (following) sibling nodes of the data node. */
-#define LYDP_FORMAT        0x02  /**< Flag for formatted output. */
-#define LYDP_KEEPEMPTYCONT 0x04  /**< Preserve empty non-presence containers */
-#define LYDP_WD_MASK       0xF0  /**< Mask for with-defaults modes */
-#define LYDP_WD_EXPLICIT   0x00  /**< Explicit mode - print only data explicitly being present in the data tree.
-                                      Note that this is the default value when no WD option is specified. */
-#define LYDP_WD_TRIM       0x10  /**< Do not print the nodes with the value equal to their default value */
-#define LYDP_WD_ALL        0x20  /**< Include implicit default nodes */
-#define LYDP_WD_ALL_TAG    0x40  /**< Same as #LYDP_WD_ALL but also adds attribute 'default' with value 'true' to
-                                      all nodes that has its default value. The 'default' attribute has namespace:
-                                      urn:ietf:params:xml:ns:netconf:default:1.0 and thus the attributes are
-                                      printed only when the ietf-netconf-with-defaults module is present in libyang
-                                      context (but in that case this namespace is always printed). */
-#define LYDP_WD_IMPL_TAG   0x80  /**< Same as LYDP_WD_ALL_TAG but the attributes are added only to the nodes that
-                                      are not explicitly present in the original data tree despite their
-                                      value is equal to their default value.  There is the same limitation regarding
-                                      the presence of ietf-netconf-with-defaults module in libyang context. */
+#define LYD_PRINT_WITHSIBLINGS  0x01  /**< Flag for printing also the (following) sibling nodes of the data node. */
+#define LYD_PRINT_FORMAT        0x02  /**< Flag for formatted output. */
+#define LYD_PRINT_KEEPEMPTYCONT 0x04  /**< Preserve empty non-presence containers */
+#define LYD_PRINT_WD_MASK       0xF0  /**< Mask for with-defaults modes */
+#define LYD_PRINT_WD_EXPLICIT   0x00  /**< Explicit mode - print only data explicitly being present in the data tree.
+                                           Note that this is the default value when no WD option is specified. */
+#define LYD_PRINT_WD_TRIM       0x10  /**< Do not print the nodes with the value equal to their default value */
+#define LYD_PRINT_WD_ALL        0x20  /**< Include implicit default nodes */
+#define LYD_PRINT_WD_ALL_TAG    0x40  /**< Same as #LYDP_WD_ALL but also adds attribute 'default' with value 'true' to
+                                           all nodes that has its default value. The 'default' attribute has namespace:
+                                           urn:ietf:params:xml:ns:netconf:default:1.0 and thus the attributes are
+                                           printed only when the ietf-netconf-with-defaults module is present in libyang
+                                           context (but in that case this namespace is always printed). */
+#define LYD_PRINT_WD_IMPL_TAG   0x80  /**< Same as LYDP_WD_ALL_TAG but the attributes are added only to the nodes that
+                                           are not explicitly present in the original data tree despite their
+                                           value is equal to their default value.  There is the same limitation regarding
+                                           the presence of ietf-netconf-with-defaults module in libyang context. */
 /**
  * @}
  */
diff --git a/src/printer_lyb.c b/src/printer_lyb.c
index 411622b..dc03f61 100644
--- a/src/printer_lyb.c
+++ b/src/printer_lyb.c
@@ -27,6 +27,7 @@
 #include "context.h"
 #include "hash_table.h"
 #include "log.h"
+#include "parser_data.h"
 #include "printer.h"
 #include "printer_data.h"
 #include "printer_internal.h"
@@ -678,7 +679,7 @@
     if (anydata->value_type == LYD_ANYDATA_DATATREE) {
         /* print LYB data tree to memory */
         LY_CHECK_GOTO(ret = ly_out_new_memory(&buf, 0, &out2), cleanup);
-        LY_CHECK_GOTO(ret = lyb_print_data(out2, anydata->value.tree, LYDP_WITHSIBLINGS), cleanup);
+        LY_CHECK_GOTO(ret = lyb_print_data(out2, anydata->value.tree, LYD_PRINT_WITHSIBLINGS), cleanup);
 
         len = lyd_lyb_data_length(buf);
         assert(len != -1);
@@ -747,8 +748,8 @@
 
     /* with-defaults */
     if (node->schema->nodetype & LYD_NODE_TERM) {
-        if (((node->flags & LYD_DEFAULT) && (lybctx->options & (LYDP_WD_ALL_TAG | LYDP_WD_IMPL_TAG))) ||
-                ((lybctx->options & LYDP_WD_ALL_TAG) && ly_is_default(node))) {
+        if (((node->flags & LYD_DEFAULT) && (lybctx->print_options & (LYD_PRINT_WD_ALL_TAG | LYD_PRINT_WD_IMPL_TAG))) ||
+                ((lybctx->print_options & LYD_PRINT_WD_ALL_TAG) && ly_is_default(node))) {
             /* we have implicit OR explicit default node, print attribute only if context include with-defaults schema */
             wd_mod = ly_ctx_get_module_latest(node->schema->module->ctx, "ietf-netconf-with-defaults");
         }
@@ -1005,7 +1006,7 @@
     const struct lys_module *prev_mod = NULL;
     struct lyd_lyb_ctx lybctx = {0};
 
-    lybctx.options = options;
+    lybctx.print_options = options;
     if (root) {
         lybctx.ctx = LYD_NODE_CTX(root);
 
@@ -1033,7 +1034,7 @@
 
         LY_CHECK_GOTO(ret = lyb_print_subtree(out, root, &top_sibling_ht, &lybctx), cleanup);
 
-        if (!(options & LYDP_WITHSIBLINGS)) {
+        if (!(options & LYD_PRINT_WITHSIBLINGS)) {
             break;
         }
     }
diff --git a/src/printer_xml.c b/src/printer_xml.c
index d143ba7..7191d84 100644
--- a/src/printer_xml.c
+++ b/src/printer_xml.c
@@ -22,6 +22,7 @@
 #include "context.h"
 #include "dict.h"
 #include "log.h"
+#include "parser_data.h"
 #include "plugins_types.h"
 #include "printer.h"
 #include "printer_data.h"
@@ -142,8 +143,8 @@
 
     /* with-defaults */
     if (node->schema->nodetype & LYD_NODE_TERM) {
-        if (((node->flags & LYD_DEFAULT) && (ctx->options & (LYDP_WD_ALL_TAG | LYDP_WD_IMPL_TAG))) ||
-                ((ctx->options & LYDP_WD_ALL_TAG) && ly_is_default(node))) {
+        if (((node->flags & LYD_DEFAULT) && (ctx->options & (LYD_PRINT_WD_ALL_TAG | LYD_PRINT_WD_IMPL_TAG))) ||
+                ((ctx->options & LYD_PRINT_WD_ALL_TAG) && ly_is_default(node))) {
             /* we have implicit OR explicit default node, print attribute only if context include with-defaults schema */
             mod = ly_ctx_get_module_latest(node->schema->module->ctx, "ietf-netconf-with-defaults");
             if (mod) {
@@ -382,22 +383,22 @@
             prev_lo = ly_log_options(0);
 
             /* try to parse it into a data tree */
-            iter = lyd_parse_mem((struct ly_ctx *)LYD_NODE_CTX(node), any->value.mem, LYD_LYB,
-                                 LYD_OPT_PARSE_ONLY | LYD_OPT_OPAQ | LYD_OPT_STRICT);
-            ly_log_options(prev_lo);
-            if (!ly_errcode(LYD_NODE_CTX(node))) {
+            if (lyd_parse_data_mem((struct ly_ctx *)LYD_NODE_CTX(node), any->value.mem, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_OPAQ | LYD_PARSE_STRICT, 0, &iter) == LY_SUCCESS) {
                 /* successfully parsed */
                 free(any->value.mem);
                 any->value.tree = iter;
                 any->value_type = LYD_ANYDATA_DATATREE;
             }
+
+            /* turn loggin on again */
+            ly_log_options(prev_lo);
         }
 
         switch (any->value_type) {
         case LYD_ANYDATA_DATATREE:
             /* close opening tag and print data */
             prev_opts = ctx->options;
-            ctx->options &= ~LYDP_WITHSIBLINGS;
+            ctx->options &= ~LYD_PRINT_WITHSIBLINGS;
             LEVEL_INC;
 
             ly_print(ctx->out, ">%s", LEVEL ? "\n" : "");
@@ -558,14 +559,14 @@
     }
 
     ctx.out = out;
-    ctx.level = (options & LYDP_FORMAT ? 1 : 0);
+    ctx.level = (options & LYD_PRINT_FORMAT ? 1 : 0);
     ctx.options = options;
     ctx.ctx = LYD_NODE_CTX(root);
 
     /* content */
     LY_LIST_FOR(root, node) {
         LY_CHECK_RET(xml_print_node(&ctx, node));
-        if (!(options & LYDP_WITHSIBLINGS)) {
+        if (!(options & LYD_PRINT_WITHSIBLINGS)) {
             break;
         }
     }
diff --git a/src/tree_data.c b/src/tree_data.c
index eceaebf..b558038 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -34,6 +34,8 @@
 #include "dict.h"
 #include "hash_table.h"
 #include "log.h"
+#include "parser_data.h"
+#include "parser_internal.h"
 #include "path.h"
 #include "plugins_exts.h"
 #include "plugins_exts_metadata.h"
@@ -280,98 +282,14 @@
     return meta->value.realtype->plugin->print(&meta->value, LYD_JSON, json_print_get_prefix, NULL, dynamic);
 }
 
-API struct lyd_node *
-lyd_parse_mem(struct ly_ctx *ctx, const char *data, LYD_FORMAT format, int options)
+static LYD_FORMAT
+lyd_parse_get_format(struct ly_in *in, LYD_FORMAT format)
 {
-    struct lyd_node *result = NULL;
-#if 0
-    const char *yang_data_name = NULL;
-#endif
 
-    LY_CHECK_ARG_RET(ctx, ctx, NULL);
-
-    if ((options & LYD_OPT_PARSE_ONLY) && (options & LYD_VALOPT_MASK)) {
-        LOGERR(ctx, LY_EINVAL, "Passing validation flags with LYD_OPT_PARSE_ONLY is not allowed.");
-        return NULL;
-    }
-
-#if 0
-    if (options & LYD_OPT_RPCREPLY) {
-        /* first item in trees is mandatory - the RPC/action request */
-        LY_CHECK_ARG_RET(ctx, trees, LY_ARRAY_SIZE(trees) >= 1, NULL);
-        if (!trees[0] || trees[0]->parent || !(trees[0]->schema->nodetype & (LYS_ACTION | LYS_LIST | LYS_CONTAINER))) {
-            LOGERR(ctx, LY_EINVAL, "Data parser invalid argument trees - the first item in the array must be the RPC/action request when parsing %s.",
-                   lyd_parse_options_type2str(options));
-            return NULL;
-        }
-    }
-
-    if (options & LYD_OPT_DATA_TEMPLATE) {
-        yang_data_name = va_arg(ap, const char *);
-    }
-#endif
-
-    if (!format) {
-        /* TODO try to detect format from the content */
-    }
-
-    switch (format) {
-    case LYD_XML:
-        lyd_parse_xml_data(ctx, data, options, &result);
-        break;
-#if 0
-    case LYD_JSON:
-        lyd_parse_json(ctx, data, options, trees, &result);
-        break;
-#endif
-    case LYD_LYB:
-        lyd_parse_lyb_data(ctx, data, options, &result, NULL);
-        break;
-    case LYD_SCHEMA:
-        LOGINT(ctx);
-        break;
-    }
-
-    return result;
-}
-
-API struct lyd_node *
-lyd_parse_fd(struct ly_ctx *ctx, int fd, LYD_FORMAT format, int options)
-{
-    struct lyd_node *result;
-    size_t length;
-    char *addr;
-
-    LY_CHECK_ARG_RET(ctx, ctx, NULL);
-    if (fd < 0) {
-        LOGARG(ctx, fd);
-        return NULL;
-    }
-
-    LY_CHECK_RET(ly_mmap(ctx, fd, &length, (void **)&addr), NULL);
-    result = lyd_parse_mem(ctx, addr ? addr : "", format, options);
-    if (addr) {
-        ly_munmap(addr, length);
-    }
-
-    return result;
-}
-
-API struct lyd_node *
-lyd_parse_path(struct ly_ctx *ctx, const char *path, LYD_FORMAT format, int options)
-{
-    int fd;
-    struct lyd_node *result;
-    size_t len;
-
-    LY_CHECK_ARG_RET(ctx, ctx, path, NULL);
-
-    fd = open(path, O_RDONLY);
-    LY_CHECK_ERR_RET(fd == -1, LOGERR(ctx, LY_ESYS, "Opening file \"%s\" failed (%s).", path, strerror(errno)), NULL);
-
-    if (!format) {
+    if (!format && in->type == LY_IN_FILEPATH) {
         /* unknown format - try to detect it from filename's suffix */
-        len = strlen(path);
+        const char *path = in->method.fpath.filepath;
+        size_t len = strlen(path);
 
         /* ignore trailing whitespaces */
         for (; len > 0 && isspace(path[len - 1]); len--);
@@ -381,16 +299,157 @@
 #if 0
         } else if (len >= 6 && !strncmp(&path[len - 5], ".json", 5)) {
             format = LYD_JSON;
+#endif
         } else if (len >= 5 && !strncmp(&path[len - 4], ".lyb", 4)) {
             format = LYD_LYB;
-#endif
-        } /* else still unknown, try later to detect it from the content */
+        } /* else still unknown */
     }
 
-    result = lyd_parse_fd(ctx, fd, format, options);
-    close(fd);
+    return format;
+}
 
-    return result;
+API LY_ERR
+lyd_parse_data(const struct ly_ctx *ctx, struct ly_in *in, LYD_FORMAT format, int parse_options, int validate_options, struct lyd_node **tree)
+{
+    LY_CHECK_ARG_RET(ctx, ctx, in, tree, LY_EINVAL);
+    LY_CHECK_ARG_RET(ctx, !(parse_options & ~LYD_PARSE_OPTS_MASK), LY_EINVAL);
+    LY_CHECK_ARG_RET(ctx, !(validate_options & ~LYD_VALIDATE_OPTS_MASK), LY_EINVAL);
+
+    format = lyd_parse_get_format(in, format);
+    LY_CHECK_ARG_RET(ctx, format, LY_EINVAL);
+
+    LY_CHECK_ARG_RET(ctx, format, LY_EINVAL);
+
+    switch (format) {
+    case LYD_XML:
+        return lyd_parse_xml_data(ctx, in->current, parse_options, validate_options, tree);
+#if 0
+    case LYD_JSON:
+        return lyd_parse_json_data(ctx, in->current, parse_options, validate_options, tree);
+#endif
+    case LYD_LYB:
+        return lyd_parse_lyb_data(ctx, in->current, parse_options, validate_options, tree, NULL);
+    case LYD_SCHEMA:
+        LOGINT_RET(ctx);
+    }
+
+    /* TODO move here the top-level validation from parser_xml.c's lyd_parse_xml_data() and make
+     * it common for all the lyd_parse_*_data() functions */
+
+    LOGINT_RET(ctx);
+}
+
+API LY_ERR
+lyd_parse_data_mem(const struct ly_ctx *ctx, const char *data, LYD_FORMAT format, int parse_options, int validate_options, struct lyd_node **tree)
+{
+    LY_ERR ret;
+    struct ly_in *in;
+
+    LY_CHECK_RET(ly_in_new_memory(data, &in));
+    ret = lyd_parse_data(ctx, in, format, parse_options, validate_options, tree);
+
+    ly_in_free(in, 0);
+    return ret;
+}
+
+API LY_ERR
+lyd_parse_data_fd(const struct ly_ctx *ctx, int fd, LYD_FORMAT format, int parse_options, int validate_options, struct lyd_node **tree)
+{
+    LY_ERR ret;
+    struct ly_in *in;
+
+    LY_CHECK_RET(ly_in_new_fd(fd, &in));
+    ret = lyd_parse_data(ctx, in, format, parse_options, validate_options, tree);
+
+    ly_in_free(in, 0);
+    return ret;
+}
+
+API LY_ERR
+lyd_parse_data_path(const struct ly_ctx *ctx, const char *path, LYD_FORMAT format, int parse_options, int validate_options, struct lyd_node **tree)
+{
+    LY_ERR ret;
+    struct ly_in *in;
+
+    LY_CHECK_RET(ly_in_new_filepath(path, 0, &in));
+    ret = lyd_parse_data(ctx, in, format, parse_options, validate_options, tree);
+
+    ly_in_free(in, 0);
+    return ret;
+}
+
+
+API LY_ERR
+lyd_parse_rpc(const struct ly_ctx *ctx, struct ly_in *in, LYD_FORMAT format, struct lyd_node **tree, struct lyd_node **op)
+{
+    LY_CHECK_ARG_RET(ctx, ctx, in, tree, LY_EINVAL);
+
+    format = lyd_parse_get_format(in, format);
+    LY_CHECK_ARG_RET(ctx, format, LY_EINVAL);
+
+    switch (format) {
+    case LYD_XML:
+        return lyd_parse_xml_rpc(ctx, in->current, tree, op);
+#if 0
+    case LYD_JSON:
+        return lyd_parse_json_rpc(ctx, in->current, tree, op);
+#endif
+    case LYD_LYB:
+        return lyd_parse_lyb_rpc(ctx, in->current, tree, op, NULL);
+    case LYD_SCHEMA:
+        LOGINT_RET(ctx);
+    }
+
+    LOGINT_RET(ctx);
+}
+
+API LY_ERR
+lyd_parse_reply(const struct lyd_node *request, struct ly_in *in, LYD_FORMAT format, struct lyd_node **tree, struct lyd_node **op)
+{
+    LY_CHECK_ARG_RET(NULL, request, LY_EINVAL);
+    LY_CHECK_ARG_RET(LYD_NODE_CTX(request), in, tree, LY_EINVAL);
+
+    format = lyd_parse_get_format(in, format);
+    LY_CHECK_ARG_RET(LYD_NODE_CTX(request), format, LY_EINVAL);
+
+    switch (format) {
+    case LYD_XML:
+        return lyd_parse_xml_reply(request, in->current, tree, op);
+#if 0
+    case LYD_JSON:
+        return lyd_parse_json_reply(request, in->current, tree, op);
+#endif
+    case LYD_LYB:
+        return lyd_parse_lyb_reply(request, in->current, tree, op, NULL);
+    case LYD_SCHEMA:
+        LOGINT_RET(LYD_NODE_CTX(request));
+    }
+
+    LOGINT_RET(LYD_NODE_CTX(request));
+}
+
+API LY_ERR
+lyd_parse_notif(const struct ly_ctx *ctx, struct ly_in *in, LYD_FORMAT format, struct lyd_node **tree, struct lyd_node **ntf)
+{
+    LY_CHECK_ARG_RET(ctx, ctx, in, tree, LY_EINVAL);
+
+    format = lyd_parse_get_format(in, format);
+    LY_CHECK_ARG_RET(ctx, format, LY_EINVAL);
+
+    switch (format) {
+    case LYD_XML:
+        return lyd_parse_xml_notif(ctx, in->current, tree, ntf);
+#if 0
+    case LYD_JSON:
+        return lyd_parse_json_notif(ctx, in->current, tree, ntf);
+#endif
+    case LYD_LYB:
+        return lyd_parse_lyb_notif(ctx, in->current, tree, ntf, NULL);
+    case LYD_SCHEMA:
+        LOGINT_RET(ctx);
+    }
+
+    LOGINT_RET(ctx);
 }
 
 LY_ERR
diff --git a/src/tree_data.h b/src/tree_data.h
index ff040f9..f891c45 100644
--- a/src/tree_data.h
+++ b/src/tree_data.h
@@ -433,89 +433,6 @@
 };
 
 /**
- * @defgroup dataparseroptions Data parser options
- * @ingroup datatree
- *
- * Various options to change the data tree parsers behavior.
- *
- * Default parser behavior:
- * - complete input file is always parsed. In case of XML, even not well-formed XML document (multiple top-level
- * elements) is parsed in its entirety,
- * - parser silently ignores data without matching schema node definition,
- * - list instances are checked whether they have all the keys, error is raised if not.
- *
- * Default parser validation behavior:
- * - the provided data are expected to provide complete datastore content (both the configuration and state data)
- * and performs data validation according to all YANG rules, specifics follow,
- * - list instances are expected to have all the keys (it is not checked),
- * - instantiated (status) obsolete data print a warning,
- * - all types are fully resolved (leafref/instance-identifier targets, unions) and must be valid (lists have
- * all the keys, leaf(-lists) correct values),
- * - when statements on existing nodes are evaluated, if not satisfied, a validation error is raised,
- * - if-feature statements are evaluated,
- * - invalid multiple data instances/data from several cases cause a validation error,
- * - default values are added.
- * @{
- */
-
-#define LYD_OPT_PARSE_ONLY      0x0001  /**< Data will be only parsed and no validation will be performed. When statements
-                                             are kept unevaluated, union types may not be fully resolved, if-feature
-                                             statements are not checked, and default values are not added (only the ones
-                                             parsed are present). */
-#define LYD_OPT_TRUSTED         0x0002  /**< Data are considered trusted so they will be parsed as validated. If the parsed
-                                             data are not valid, using this flag may lead to some unexpected behavior!
-                                             This flag can be used only with #LYD_OPT_PARSE_ONLY. */
-#define LYD_OPT_STRICT          0x0004  /**< Instead of silently ignoring data without schema definition raise an error.
-                                             Do not combine with #LYD_OPT_OPAQ. */
-#define LYD_OPT_OPAQ            0x0008  /**< Instead of silently ignoring data without definition, parse them into
-                                             an opaq node. Do not combine with #LYD_OPT_STRICT. */
-#define LYD_OPT_NO_STATE        0x0010  /**< Forbid state data in the parsed data. */
-#define LYD_OPT_LYB_MOD_UPDATE  0x0020  /**< Only for LYB format, allow parsing data printed using a specific module
-                                             revision to be loaded even with a module with the same name but newer
-                                             revision. */
-
-#define LYD_OPT_MASK            0xFFFF  /**< Mask for all the parser options. */
-
-/** @} dataparseroptions */
-
-/**
- * @defgroup datavalidationoptions Data validation options
- * @ingroup datatree
- *
- * Various options to change data validation behaviour, both for the parser and separate validation.
- *
- * Default separate validation behavior:
- * - the provided data are expected to provide complete datastore content (both the configuration and state data)
- * and performs data validation according to all YANG rules, specifics follow,
- * - instantiated (status) obsolete data print a warning,
- * - all types are fully resolved (leafref/instance-identifier targets, unions) and must be valid (lists have
- * all the keys, leaf(-lists) correct values),
- * - when statements on existing nodes are evaluated. Depending on the previous when state (from previous validation
- * or parsing), the node is silently auto-deleted if the state changed from true to false, otherwise a validation error
- * is raised if it evaluates to false,
- * - if-feature statements are evaluated,
- * - data from several cases behave based on their previous state (from previous validation or parsing). If there existed
- * already a case and another one was added, the previous one is silently auto-deleted. Otherwise (if data from 2 or
- * more cases were created) a validation error is raised,
- * - default values are added.
- *
- * @{
- */
-
-#define LYD_VALOPT_NO_STATE     0x00010000 /**< Consider state data not allowed and raise an error if they are found. */
-#define LYD_VALOPT_DATA_ONLY    0x00020000 /**< Validate only modules whose data actually exist. */
-#define LYD_VALOPT_INPUT        0x00040000 /**< Validate RPC/action request (input parameters). */
-#define LYD_VALOPT_OUTPUT       0x00080000 /**< Validate RPC/action reply (output parameters). */
-
-#define LYD_VALOPT_MASK         0xFFFF0000 /**< Mask for all the validation options. */
-
-/** @} datavalidationoptions */
-
-//#define LYD_OPT_VAL_DIFF 0x40000 /**< Flag only for validation, store all the data node changes performed by the validation
-//                                      in a diff structure. */
-//#define LYD_OPT_DATA_TEMPLATE 0x1000000 /**< Data represents YANG data template. */
-
-/**
  * @defgroup children_options Children traversal options.
  * @ingroup datatree
  */
@@ -544,62 +461,6 @@
 const struct lys_module *lyd_owner_module(const struct lyd_node *node);
 
 /**
- * @brief Parse (and validate) data from memory.
- *
- * In case of LY_XML format, the data string is parsed completely. It means that when it contains
- * a non well-formed XML with multiple root elements, all those sibling XML trees are parsed. The
- * returned data node is a root of the first tree with other trees connected via the next pointer.
- * This behavior can be changed by #LYD_OPT_NOSIBLINGS option.
- *
- * @param[in] ctx Context to connect with the data tree being built here.
- * @param[in] data Serialized data in the specified format.
- * @param[in] format Format of the input data to be parsed.
- * @param[in] options Parser and validation options, see @ref parseroptions.
- * @return Pointer to the built data tree or NULL in case of empty \p data. To free the returned structure,
- *         use lyd_free_all().
- * @return NULL in case of error. The error information can be then obtained using ly_err* functions.
- */
-struct lyd_node *lyd_parse_mem(struct ly_ctx *ctx, const char *data, LYD_FORMAT format, int options);
-
-/**
- * @brief Read (and validate) data from the given file descriptor.
- *
- * \note Current implementation supports only reading data from standard (disk) file, not from sockets, pipes, etc.
- *
- * In case of LY_XML format, the file content is parsed completely. It means that when it contains
- * a non well-formed XML with multiple root elements, all those sibling XML trees are parsed. The
- * returned data node is a root of the first tree with other trees connected via the next pointer.
- * This behavior can be changed by #LYD_OPT_NOSIBLINGS option.
- *
- * @param[in] ctx Context to connect with the data tree being built here.
- * @param[in] fd The standard file descriptor of the file containing the data tree in the specified format.
- * @param[in] format Format of the input data to be parsed.
- * @param[in] options Parser options, see @ref parseroptions. \p format LYD_LYB uses #LYD_OPT_PARSE_ONLY implicitly.
- * @return Pointer to the built data tree or NULL in case of empty file. To free the returned structure,
- *         use lyd_free_all().
- * @return NULL in case of error. The error information can be then obtained using ly_err* functions.
- */
-struct lyd_node *lyd_parse_fd(struct ly_ctx *ctx, int fd, LYD_FORMAT format, int options);
-
-/**
- * @brief Read (and validate) data from the given file path.
- *
- * In case of LY_XML format, the file content is parsed completely. It means that when it contains
- * a non well-formed XML with multiple root elements, all those sibling XML trees are parsed. The
- * returned data node is a root of the first tree with other trees connected via the next pointer.
- * This behavior can be changed by #LYD_OPT_NOSIBLINGS option.
- *
- * @param[in] ctx Context to connect with the data tree being built here.
- * @param[in] path Path to the file containing the data tree in the specified format.
- * @param[in] format Format of the input data to be parsed.
- * @param[in] options Parser options, see @ref parseroptions. \p format LYD_LYB uses #LYD_OPT_PARSE_ONLY implicitly.
- * @return Pointer to the built data tree or NULL in case of empty file. To free the returned structure,
- *         use lyd_free_all().
- * @return NULL in case of error. The error information can be then obtained using ly_err* functions.
- */
-struct lyd_node *lyd_parse_path(struct ly_ctx *ctx, const char *path, LYD_FORMAT format, int options);
-
-/**
  * @brief Learn the length of LYB data.
  *
  * @param[in] data LYB data to examine.
@@ -609,44 +470,6 @@
 int lyd_lyb_data_length(const char *data);
 
 /**
- * @brief Fully validate a data tree.
- *
- * @param[in,out] tree Data tree to recursively validate. May be changed by validation.
- * @param[in] ctx libyang context. Can be NULL if @p tree is set.
- * @param[in] val_opts Validation options (@ref datavalidationoptions).
- * @return LY_SUCCESS on success.
- * @return LY_ERR error on error.
- */
-LY_ERR lyd_validate(struct lyd_node **tree, const struct ly_ctx *ctx, int val_opts);
-
-/**
- * @brief Fully validate a data tree.
- *
- * @param[in,out] tree Data tree to recursively validate. May be changed by validation.
- * @param[in] modules Array of modules to validate.
- * @param[in] mod_count Number of @p modules.
- * @param[in] val_opts Validation options (@ref datavalidationoptions).
- * @return LY_SUCCESS on success.
- * @return LY_ERR error on error.
- */
-LY_ERR lyd_validate_modules(struct lyd_node **tree, const struct lys_module **modules, int mod_count, int val_opts);
-
-/**
- * @brief Validate an RPC/action, notification, or RPC/action reply.
- *
- * @param[in,out] op_tree Operation tree with any parents. It can point to the operation itself or any of
- * its parents, only the operation subtree is actually validated.
- * @param[in] tree Tree to be used for validating references from the operation subtree.
- * @param[in] val_opts Specific validation option (@ref datavalidationoptions):
- *              0 - no validation option for validation notifications,
- *              ::LYD_VALOPT_INPUT - for validating RPC/action request (input),
- *              ::LYD_VALOPT_OUTPUT - for validatin RPC/action reply (output).
- * @return LY_SUCCESS on success.
- * @return LY_ERR error on error.
- */
-LY_ERR lyd_validate_op(struct lyd_node *op_tree, const struct lyd_node *tree, int val_opts);
-
-/**
  * @brief Create a new inner node in the data tree.
  *
  * @param[in] parent Parent node for the node being created. NULL in case of creating a top level element.
diff --git a/src/tree_data_helpers.c b/src/tree_data_helpers.c
index 36d540c..aa7fd63 100644
--- a/src/tree_data_helpers.c
+++ b/src/tree_data_helpers.c
@@ -22,6 +22,7 @@
 #include "hash_table.h"
 #include "log.h"
 #include "lyb.h"
+#include "parser_data.h"
 #include "set.h"
 #include "tree.h"
 #include "tree_data.h"
@@ -170,7 +171,7 @@
     struct lyd_meta *meta2, *prev_meta = NULL;
 
     if (!(node->schema->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) && node->schema->when) {
-        if (options & LYD_OPT_TRUSTED) {
+        if (options & LYD_PARSE_TRUSTED) {
             /* just set it to true */
             node->flags |= LYD_WHEN_TRUE;
         } else {
@@ -179,7 +180,7 @@
         }
     }
 
-    if (options & LYD_OPT_TRUSTED) {
+    if (options & LYD_PARSE_TRUSTED) {
         /* node is valid */
         node->flags &= ~LYD_NEW;
     }
diff --git a/src/tree_data_internal.h b/src/tree_data_internal.h
index 4c91bf5..a2a3769 100644
--- a/src/tree_data_internal.h
+++ b/src/tree_data_internal.h
@@ -294,20 +294,19 @@
  *
  * @param[in] ctx libyang context
  * @param[in] data Pointer to the XML data to parse.
- * @param[in] options @ref dataparseroptions
+ * @param[in] parse_options Options for parser, see @ref dataparseroptions.
+ * @param[in] validate_options Options for the validation phase, see @ref datavalidationoptions.
  * @param[out] tree Parsed data tree. Note that NULL can be a valid result.
  * @return LY_ERR value.
  */
-LY_ERR lyd_parse_xml_data(const struct ly_ctx *ctx, const char *data, int options, struct lyd_node **tree);
+LY_ERR lyd_parse_xml_data(const struct ly_ctx *ctx, const char *data, int parse_options, int validate_options, struct lyd_node **tree);
 
 /**
  * @brief Parse XML string as YANG RPC/action invocation.
  *
- * Optional \<rpc\> envelope element, if present, is [checked](https://tools.ietf.org/html/rfc6241#section-4.1) and all
- * its XML attributes parsed. In that case an RPC is expected to be parsed.
- *
- * Can be followed by optional \<action\> envelope element, which is also
- * [checked](https://tools.ietf.org/html/rfc7950#section-7.15.2) and then an action is expected to be parsed.
+ * Optional \<rpc\> envelope element is accepted if present. It is [checked](https://tools.ietf.org/html/rfc6241#section-4.1) and all
+ * its XML attributes are parsed. As a content of the enveloper, an RPC data or \<action\> envelope element is expected. The \<action\> envelope element is
+ * also [checked](https://tools.ietf.org/html/rfc7950#section-7.15.2) and then an action data is expected as a content of this envelope.
  *
  * @param[in] ctx libyang context.
  * @param[in] data Pointer to the XML data to parse.
@@ -350,12 +349,13 @@
  *
  * @param[in] ctx libyang context
  * @param[in] data Pointer to the input data to parse.
- * @param[in] options @ref dataparseroptions
+ * @param[in] parse_options Options for parser, see @ref dataparseroptions.
+ * @param[in] validate_options Options for the validation phase, see @ref datavalidationoptions.
  * @param[out] tree Parsed data tree. Note that NULL can be a valid result.
  * @param[out] parsed_bytes Optional number of parsed bytes.
  * @return LY_ERR value.
  */
-LY_ERR lyd_parse_lyb_data(struct ly_ctx *ctx, const char *data, int options, struct lyd_node **tree, int *parsed_bytes);
+LY_ERR lyd_parse_lyb_data(const struct ly_ctx *ctx, const char *data, int parse_options, int validate_options, struct lyd_node **tree, int *parsed_bytes);
 
 /**
  * @brief Parse binary data as YANG RPC/action invocation.
@@ -367,7 +367,7 @@
  * @param[out] parsed_bytes Optional number of parsed bytes.
  * @return LY_ERR value.
  */
-LY_ERR lyd_parse_lyb_rpc(struct ly_ctx *ctx, const char *data, struct lyd_node **tree, struct lyd_node **op,
+LY_ERR lyd_parse_lyb_rpc(const struct ly_ctx *ctx, const char *data, struct lyd_node **tree, struct lyd_node **op,
                          int *parsed_bytes);
 
 /**
@@ -380,7 +380,7 @@
  * @param[out] parsed_bytes Optional number of parsed bytes.
  * @return LY_ERR value.
  */
-LY_ERR lyd_parse_lyb_notif(struct ly_ctx *ctx, const char *data, struct lyd_node **tree, struct lyd_node **ntf,
+LY_ERR lyd_parse_lyb_notif(const struct ly_ctx *ctx, const char *data, struct lyd_node **tree, struct lyd_node **ntf,
                            int *parsed_bytes);
 
 /**
@@ -393,7 +393,7 @@
  * @param[out] parsed_bytes Optional number of parsed bytes.
  * @return LY_ERR value.
  */
-LY_ERR lyd_parse_lyb_reply(struct lyd_node *request, const char *data, struct lyd_node **tree, struct lyd_node **op,
+LY_ERR lyd_parse_lyb_reply(const struct lyd_node *request, const char *data, struct lyd_node **tree, struct lyd_node **op,
                            int *parsed_bytes);
 
 /**
diff --git a/src/validation.c b/src/validation.c
index 22919f0..f75dc04 100644
--- a/src/validation.c
+++ b/src/validation.c
@@ -22,6 +22,7 @@
 #include "config.h"
 #include "hash_table.h"
 #include "log.h"
+#include "parser_data.h"
 #include "plugins_types.h"
 #include "set.h"
 #include "tree.h"
@@ -739,17 +740,17 @@
 
 static LY_ERR
 lyd_validate_siblings_schema_r(const struct lyd_node *first, const struct lysc_node *sparent,
-                               const struct lysc_module *mod, int val_opts)
+                               const struct lysc_module *mod, int val_opts, LYD_VALIDATE_OP op)
 {
     const struct lysc_node *snode = NULL;
     struct lysc_node_list *slist;
     int getnext_opts;
 
-    getnext_opts = LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHCASE | (val_opts & LYD_VALOPT_OUTPUT ? LYS_GETNEXT_OUTPUT : 0);
+    getnext_opts = LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHCASE | (op == LYD_VALIDATE_OP_REPLY ? LYS_GETNEXT_OUTPUT : 0);
 
     /* disabled nodes are skipped by lys_getnext */
     while ((snode = lys_getnext(snode, sparent, mod, getnext_opts))) {
-        if ((val_opts & LYD_VALOPT_NO_STATE) && (snode->flags & LYS_CONFIG_R)) {
+        if ((val_opts & LYD_VALIDATE_NO_STATE) && (snode->flags & LYS_CONFIG_R)) {
             continue;
         }
 
@@ -775,7 +776,7 @@
 
         if (snode->nodetype & (LYS_CHOICE | LYS_CASE)) {
             /* go recursively for schema-only nodes */
-            LY_CHECK_RET(lyd_validate_siblings_schema_r(first, snode, mod, val_opts));
+            LY_CHECK_RET(lyd_validate_siblings_schema_r(first, snode, mod, val_opts, op));
         }
     }
 
@@ -799,7 +800,7 @@
 }
 
 static LY_ERR
-lyd_validate_must(const struct lyd_node *node, int val_opts)
+lyd_validate_must(const struct lyd_node *node, LYD_VALIDATE_OP op)
 {
     struct lyxp_set xp_set;
     struct lysc_must *musts;
@@ -828,9 +829,9 @@
         break;
     case LYS_RPC:
     case LYS_ACTION:
-        if (val_opts & LYD_VALOPT_INPUT) {
+        if (op == LYD_VALIDATE_OP_RPC) {
             musts = ((struct lysc_action *)node->schema)->input.musts;
-        } else if (val_opts & LYD_VALOPT_OUTPUT) {
+        } else if (op == LYD_VALIDATE_OP_REPLY) {
             musts = ((struct lysc_action *)node->schema)->output.musts;
         } else {
             LOGINT(LYD_NODE_CTX(node));
@@ -871,7 +872,7 @@
 }
 
 LY_ERR
-lyd_validate_final_r(struct lyd_node *first, const struct lysc_node *sparent, const struct lys_module *mod, int val_opts)
+lyd_validate_final_r(struct lyd_node *first, const struct lysc_node *sparent, const struct lys_module *mod, int val_opts, LYD_VALIDATE_OP op)
 {
     struct lyd_node *next, *node;
     const struct lysc_node *snode;
@@ -891,13 +892,13 @@
         }
 
         /* no state/input/output data */
-        if ((val_opts & LYD_VALOPT_NO_STATE) && (node->schema->flags & LYS_CONFIG_R)) {
+        if ((val_opts & LYD_VALIDATE_NO_STATE) && (node->schema->flags & LYS_CONFIG_R)) {
             LOGVAL(LYD_NODE_CTX(node), LY_VLOG_LYD, node, LY_VCODE_INNODE, "state", node->schema->name);
             return LY_EVALID;
-        } else if ((val_opts & LYD_VALOPT_INPUT) && (node->schema->flags & LYS_CONFIG_R)) {
+        } else if ((op == LYD_VALIDATE_OP_RPC) && (node->schema->flags & LYS_CONFIG_R)) {
             LOGVAL(LYD_NODE_CTX(node), LY_VLOG_LYD, node, LY_VCODE_INNODE, "output", node->schema->name);
             return LY_EVALID;
-        } else if ((val_opts & LYD_VALOPT_OUTPUT) && (node->schema->flags & LYS_CONFIG_W)) {
+        } else if ((op == LYD_VALIDATE_OP_REPLY) && (node->schema->flags & LYS_CONFIG_W)) {
             LOGVAL(LYD_NODE_CTX(node), LY_VLOG_LYD, node, LY_VCODE_INNODE, "input", node->schema->name);
             return LY_EVALID;
         }
@@ -912,17 +913,17 @@
         }
 
         /* node's musts */
-        LY_CHECK_RET(lyd_validate_must(node, val_opts));
+        LY_CHECK_RET(lyd_validate_must(node, op));
 
         /* node value including if-feature was checked by plugins */
     }
 
     /* validate schema-based restrictions */
-    LY_CHECK_RET(lyd_validate_siblings_schema_r(first, sparent, mod ? mod->compiled : NULL, val_opts));
+    LY_CHECK_RET(lyd_validate_siblings_schema_r(first, sparent, mod ? mod->compiled : NULL, val_opts, op));
 
     LY_LIST_FOR(first, node) {
         /* validate all children recursively */
-        LY_CHECK_RET(lyd_validate_final_r(lyd_node_children(node, 0), node->schema, NULL, val_opts));
+        LY_CHECK_RET(lyd_validate_final_r(lyd_node_children(node, 0), node->schema, NULL, val_opts, op));
 
         /* set default for containers */
         if ((node->schema->nodetype == LYS_CONTAINER) && !(node->schema->flags & LYS_PRESENCE)) {
@@ -957,7 +958,7 @@
     }
 
     while ((iter = lys_getnext(iter, sparent, mod ? mod->compiled : NULL, LYS_GETNEXT_WITHCHOICE))) {
-        if ((val_opts & LYD_VALOPT_NO_STATE) && (iter->flags & LYS_CONFIG_R)) {
+        if ((val_opts & LYD_VALIDATE_NO_STATE) && (iter->flags & LYS_CONFIG_R)) {
             continue;
         }
 
@@ -1035,9 +1036,12 @@
     return LY_SUCCESS;
 }
 
+/**
+ * @param[in] validate_options Options for the validation phase, see @ref datavalidationoptions.
+ */
 static LY_ERR
 lyd_validate_subtree(struct lyd_node *root, struct ly_set *type_check, struct ly_set *type_meta_check,
-                     struct ly_set *when_check, int val_opts)
+                     struct ly_set *when_check, int validate_options)
 {
     const struct lyd_meta *meta;
     struct lyd_node *next, *node;
@@ -1059,7 +1063,7 @@
 
                 /* add nested defaults */
                 LY_CHECK_RET(lyd_validate_defaults_r(node, lyd_node_children_p((struct lyd_node *)node), NULL, NULL, type_check,
-                                                     when_check, val_opts));
+                                                     when_check, validate_options));
             }
 
             if (!(node->schema->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) && node->schema->when) {
@@ -1086,14 +1090,9 @@
 
     LY_CHECK_ARG_RET(NULL, tree, *tree || ctx || (modules && mod_count), LY_EINVAL);
 
-    if (val_opts & ~LYD_VALOPT_MASK) {
-        LOGERR(ctx, LY_EINVAL, "Some invalid flags passed to validation.");
-        return LY_EINVAL;
-    }
-
     next = *tree;
     while (1) {
-        if (val_opts & LYD_VALOPT_DATA_ONLY) {
+        if (val_opts & LYD_VALIDATE_PRESENT) {
             mod = lyd_data_next_module(&next, &first);
         } else {
             mod = lyd_mod_next_module(next, modules, mod_count, ctx, &i, &first);
@@ -1124,7 +1123,7 @@
         LY_CHECK_GOTO(ret, cleanup);
 
         /* perform final validation that assumes the data tree is final */
-        LY_CHECK_GOTO(ret = lyd_validate_final_r(*first2, NULL, mod, val_opts), cleanup);
+        LY_CHECK_GOTO(ret = lyd_validate_final_r(*first2, NULL, mod, val_opts, 0), cleanup);
     }
 
 cleanup:
@@ -1189,31 +1188,31 @@
 }
 
 API LY_ERR
-lyd_validate_op(struct lyd_node *op_tree, const struct lyd_node *tree, int val_opts)
+lyd_validate_op(struct lyd_node *op_tree, const struct lyd_node *tree, LYD_VALIDATE_OP op)
 {
     LY_ERR ret;
-    struct lyd_node *tree_sibling, *op_node, *op, *op_parent;
+    struct lyd_node *tree_sibling, *op_subtree, *op_next, *op_node, *op_parent;
     struct ly_set type_check = {0}, type_meta_check = {0}, when_check = {0};
 
     LY_CHECK_ARG_RET(NULL, op_tree, !op_tree->parent, !tree || !tree->parent,
-                     !val_opts || (val_opts == LYD_VALOPT_INPUT) || (val_opts == LYD_VALOPT_OUTPUT), LY_EINVAL);
+                     (op == LYD_VALIDATE_OP_NOTIF) || (op == LYD_VALIDATE_OP_RPC) || (op == LYD_VALIDATE_OP_REPLY), LY_EINVAL);
 
     /* find the operation/notification */
-    LYD_TREE_DFS_BEGIN(op_tree, op_node, op) {
-        if ((val_opts & (LYD_VALOPT_INPUT | LYD_VALOPT_OUTPUT)) && (op->schema->nodetype & (LYS_RPC | LYS_ACTION))) {
+    LYD_TREE_DFS_BEGIN(op_tree, op_next, op_node) {
+        if ((op == LYD_VALIDATE_OP_RPC || op == LYD_VALIDATE_OP_REPLY) && (op_node->schema->nodetype & (LYS_RPC | LYS_ACTION))) {
             break;
-        } else if (!val_opts && (op->schema->nodetype == LYS_NOTIF)) {
+        } else if ((op == LYD_VALIDATE_OP_NOTIF) && (op_node->schema->nodetype == LYS_NOTIF)) {
             break;
         }
-        LYD_TREE_DFS_END(op_tree, op_node, op);
+        LYD_TREE_DFS_END(op_tree, op_next, op_node);
     }
-    if (val_opts & (LYD_VALOPT_INPUT | LYD_VALOPT_OUTPUT)) {
-        if (!(op->schema->nodetype & (LYS_RPC | LYS_ACTION))) {
+    if (op == LYD_VALIDATE_OP_RPC || op == LYD_VALIDATE_OP_REPLY) {
+        if (!(op_node->schema->nodetype & (LYS_RPC | LYS_ACTION))) {
             LOGERR(LYD_NODE_CTX(op_tree), LY_EINVAL, "No RPC/action to validate found.");
             return LY_EINVAL;
         }
     } else {
-        if (op->schema->nodetype != LYS_NOTIF) {
+        if (op_node->schema->nodetype != LYS_NOTIF) {
             LOGERR(LYD_NODE_CTX(op_tree), LY_EINVAL, "No notification to validate found.");
             return LY_EINVAL;
         }
@@ -1225,38 +1224,38 @@
     }
 
     /* merge op_tree into tree */
-    lyd_val_op_merge_find(op_tree, op, tree, &op_node, &tree_sibling);
-    op_parent = (struct lyd_node *)op_node->parent;
-    lyd_unlink_tree(op_node);
-    lyd_insert_node(NULL, (struct lyd_node **)&tree_sibling, op_node);
+    lyd_val_op_merge_find(op_tree, op_node, tree, &op_subtree, &tree_sibling);
+    op_parent = (struct lyd_node *)op_subtree->parent;
+    lyd_unlink_tree(op_subtree);
+    lyd_insert_node(NULL, (struct lyd_node **)&tree_sibling, op_subtree);
     if (!tree) {
         tree = tree_sibling;
     }
 
     /* prevalidate whole operation subtree */
-    LY_CHECK_GOTO(ret = lyd_validate_subtree(op, &type_check, &type_meta_check, &when_check, val_opts), cleanup);
+    LY_CHECK_GOTO(ret = lyd_validate_subtree(op_node, &type_check, &type_meta_check, &when_check, 0), cleanup);
 
     /* 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), cleanup);
 
     /* perform final validation of the operation/notification */
-    lyd_validate_obsolete(op);
-    if (lysc_node_is_disabled(op->schema, 1)) {
-        LOGVAL(LYD_NODE_CTX(op_tree), LY_VLOG_LYD, op, LY_VCODE_NOIFF, op->schema->name);
+    lyd_validate_obsolete(op_node);
+    if (lysc_node_is_disabled(op_node->schema, 1)) {
+        LOGVAL(LYD_NODE_CTX(op_tree), LY_VLOG_LYD, op_node, LY_VCODE_NOIFF, op_node->schema->name);
         ret = LY_EVALID;
         goto cleanup;
     }
-    LY_CHECK_GOTO(ret = lyd_validate_must(op, val_opts), cleanup);
+    LY_CHECK_GOTO(ret = lyd_validate_must(op_node, op), cleanup);
 
     /* final validation of all the descendants */
-    LY_CHECK_GOTO(ret = lyd_validate_final_r(lyd_node_children(op, 0), op->schema, NULL, val_opts), cleanup);
+    LY_CHECK_GOTO(ret = lyd_validate_final_r(lyd_node_children(op_node, 0), op_node->schema, NULL, 0, op), cleanup);
 
 cleanup:
     /* restore operation tree */
-    lyd_unlink_tree(op_node);
+    lyd_unlink_tree(op_subtree);
     if (op_parent) {
-        lyd_insert_node(op_parent, NULL, op_node);
+        lyd_insert_node(op_parent, NULL, op_subtree);
     }
 
     ly_set_erase(&type_check, NULL);
diff --git a/src/validation.h b/src/validation.h
index 734d17c..9c6d156 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -54,10 +54,11 @@
  * @param[in] sparent Schema parent of the siblings, NULL for top-level siblings.
  * @param[in] mod Module of the siblings, NULL for nested siblings.
  * @param[in] val_opts Validation options (@ref datavalidationoptions).
+ * @param[in] op Operation to validate (@ref datavalidateop) or 0 for data tree
  * @return LY_ERR value.
  */
 LY_ERR lyd_validate_final_r(struct lyd_node *first, const struct lysc_node *sparent, const struct lys_module *mod,
-                            int val_opts);
+                            int val_opts, LYD_VALIDATE_OP op);
 
 /**
  * @brief Check the existence and create any non-existing default siblings, recursively for the created nodes.
diff --git a/src/xpath.c b/src/xpath.c
index fae13dc..b14ee8c 100644
--- a/src/xpath.c
+++ b/src/xpath.c
@@ -33,6 +33,7 @@
 #include "context.h"
 #include "dict.h"
 #include "hash_table.h"
+#include "parser_data.h"
 #include "path.h"
 #include "plugins_types.h"
 #include "printer.h"
@@ -412,14 +413,13 @@
 
             if (any->value_type == LYD_ANYDATA_LYB) {
                 /* try to parse it into a data tree */
-                tree = lyd_parse_mem((struct ly_ctx *)LYD_NODE_CTX(node), any->value.mem, LYD_LYB,
-                                     LYD_OPT_PARSE_ONLY | LYD_OPT_STRICT);
-                if (!ly_errcode(LYD_NODE_CTX(node))) {
+                if (lyd_parse_data_mem((struct ly_ctx *)LYD_NODE_CTX(node), any->value.mem, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree) == LY_SUCCESS) {
                     /* successfully parsed */
                     free(any->value.mem);
                     any->value.tree = tree;
                     any->value_type = LYD_ANYDATA_DATATREE;
                 }
+                /* error is covered by the following switch where LYD_ANYDATA_LYB causes failure */
             }
 
             switch (any->value_type) {
@@ -431,7 +431,7 @@
                 break;
             case LYD_ANYDATA_DATATREE:
                 LY_CHECK_RET(ly_out_new_memory(&buf, 0, &out));
-                rc = lyd_print(out, any->value.tree, LYD_XML, LYDP_WITHSIBLINGS);
+                rc = lyd_print(out, any->value.tree, LYD_XML, LYD_PRINT_WITHSIBLINGS);
                 ly_out_free(out, NULL, 0);
                 LY_CHECK_RET(rc < 0, -rc);
                 break;
diff --git a/tests/utests/data/test_diff.c b/tests/utests/data/test_diff.c
index 5557dff..ad24800 100644
--- a/tests/utests/data/test_diff.c
+++ b/tests/utests/data/test_diff.c
@@ -255,7 +255,7 @@
     struct state *st = (*state);
     const char *xml = "<df xmlns=\"urn:libyang:tests:defaults\"><foo>42</foo></df>";
 
-    st->first = lyd_parse_mem(st->ctx, xml, LYD_XML, LYD_OPT_PARSE_ONLY);
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(st->ctx, xml, LYD_XML, LYD_PARSE_ONLY, 0, &st->first));
     assert_non_null(st->first);
     st->second = NULL;
 
@@ -279,17 +279,17 @@
                       "</df><hidden xmlns=\"urn:libyang:tests:defaults\">"
                         "<foo>42</foo><baz>42</baz></hidden>";
 
-    st->first = lyd_parse_mem(st->ctx, xml, LYD_XML, LYD_OPT_PARSE_ONLY);
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(st->ctx, xml, LYD_XML, LYD_PARSE_ONLY, 0, &st->first));
     assert_non_null(st->first);
-    st->second = lyd_parse_mem(st->ctx, xml, LYD_XML, LYD_OPT_PARSE_ONLY);
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(st->ctx, xml, LYD_XML, LYD_PARSE_ONLY, 0, &st->second));
     assert_non_null(st->second);
 
     assert_int_equal(lyd_diff(st->first, st->second, 0, &st->diff), LY_SUCCESS);
     assert_null(st->diff);
 
     assert_int_equal(lyd_diff_apply(&st->first, st->diff), LY_SUCCESS);
-    lyd_print_mem(&st->xml1, st->first, LYD_XML, LYDP_WITHSIBLINGS);
-    lyd_print_mem(&st->xml2, st->second, LYD_XML, LYDP_WITHSIBLINGS);
+    lyd_print_mem(&st->xml1, st->first, LYD_XML, LYD_PRINT_WITHSIBLINGS);
+    lyd_print_mem(&st->xml2, st->second, LYD_XML, LYD_PRINT_WITHSIBLINGS);
     assert_string_equal(st->xml1, st->xml2);
 }
 
@@ -306,13 +306,13 @@
         "</hidden>";
 
     st->first = NULL;
-    st->second = lyd_parse_mem(st->ctx, xml, LYD_XML, LYD_OPT_PARSE_ONLY);
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(st->ctx, xml, LYD_XML, LYD_PARSE_ONLY, 0, &st->second));
     assert_non_null(st->second);
 
     assert_int_equal(lyd_diff(st->first, st->second, 0, &st->diff), LY_SUCCESS);
 
     assert_non_null(st->diff);
-    lyd_print_mem(&st->xml, st->diff, LYD_XML, LYDP_WITHSIBLINGS);
+    lyd_print_mem(&st->xml, st->diff, LYD_XML, LYD_PRINT_WITHSIBLINGS);
     assert_string_equal(st->xml,
         "<df xmlns=\"urn:libyang:tests:defaults\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"create\">"
             "<foo>42</foo><b1_1>42</b1_1>"
@@ -323,8 +323,8 @@
     );
 
     assert_int_equal(lyd_diff_apply(&st->first, st->diff), LY_SUCCESS);
-    lyd_print_mem(&st->xml1, st->first, LYD_XML, LYDP_WITHSIBLINGS);
-    lyd_print_mem(&st->xml2, st->second, LYD_XML, LYDP_WITHSIBLINGS);
+    lyd_print_mem(&st->xml1, st->first, LYD_XML, LYD_PRINT_WITHSIBLINGS);
+    lyd_print_mem(&st->xml2, st->second, LYD_XML, LYD_PRINT_WITHSIBLINGS);
     assert_string_equal(st->xml1, st->xml2);
 }
 
@@ -337,14 +337,14 @@
                       "</df><hidden xmlns=\"urn:libyang:tests:defaults\">"
                         "<foo>42</foo><baz>42</baz></hidden>";
 
-    st->first = lyd_parse_mem(st->ctx, xml, LYD_XML, LYD_OPT_PARSE_ONLY);
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(st->ctx, xml, LYD_XML, LYD_PARSE_ONLY, 0, &st->first));
     assert_non_null(st->first);
     st->second = NULL;
 
     assert_int_equal(lyd_diff(st->first, st->second, 0, &st->diff), LY_SUCCESS);
 
     assert_non_null(st->diff);
-    lyd_print_mem(&st->xml, st->diff, LYD_XML, LYDP_WITHSIBLINGS);
+    lyd_print_mem(&st->xml, st->diff, LYD_XML, LYD_PRINT_WITHSIBLINGS);
     assert_string_equal(st->xml,
         "<df xmlns=\"urn:libyang:tests:defaults\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"delete\">"
             "<foo>42</foo><b1_1>42</b1_1>"
@@ -364,7 +364,7 @@
     struct state *st = (*state);
     const char *xml = "<df xmlns=\"urn:libyang:tests:defaults\"><foo>42</foo></df>";
 
-    st->first = lyd_parse_mem(st->ctx, xml, LYD_XML, LYD_OPT_PARSE_ONLY);
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(st->ctx, xml, LYD_XML, LYD_PARSE_ONLY, 0, &st->first));
     assert_non_null(st->first);
     st->second = NULL;
 
@@ -374,7 +374,7 @@
     assert_int_equal(lyd_diff(NULL, lyd_node_children(st->first, 0), 0, &st->diff), LY_SUCCESS);
 
     assert_non_null(st->diff);
-    lyd_print_mem(&st->xml, st->diff, LYD_XML, LYDP_WITHSIBLINGS);
+    lyd_print_mem(&st->xml, st->diff, LYD_XML, LYD_PRINT_WITHSIBLINGS);
     assert_string_equal(st->xml,
         "<df xmlns=\"urn:libyang:tests:defaults\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"none\">"
             "<foo yang:operation=\"create\">42</foo>"
@@ -386,7 +386,7 @@
     assert_int_equal(lyd_diff(lyd_node_children(st->first, 0), NULL, 0, &st->diff), LY_SUCCESS);
 
     assert_non_null(st->diff);
-    lyd_print_mem(&st->xml, st->diff, LYD_XML, LYDP_WITHSIBLINGS);
+    lyd_print_mem(&st->xml, st->diff, LYD_XML, LYD_PRINT_WITHSIBLINGS);
     assert_string_equal(st->xml,
         "<df xmlns=\"urn:libyang:tests:defaults\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"none\">"
             "<foo yang:operation=\"delete\">42</foo>"
@@ -410,15 +410,15 @@
             "<foo>41</foo><b1_1>42</b1_1>"
         "</df>";
 
-    st->first = lyd_parse_mem(st->ctx, xml1, LYD_XML, LYD_OPT_PARSE_ONLY);
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(st->ctx, xml1, LYD_XML, LYD_PARSE_ONLY, 0, &st->first));
     assert_non_null(st->first);
-    st->second = lyd_parse_mem(st->ctx, xml2, LYD_XML, LYD_OPT_PARSE_ONLY);
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(st->ctx, xml2, LYD_XML, LYD_PARSE_ONLY, 0, &st->second));
     assert_non_null(st->second);
 
     assert_int_equal(lyd_diff(st->first, st->second, 0, &st->diff), LY_SUCCESS);
 
     assert_non_null(st->diff);
-    lyd_print_mem(&st->xml, st->diff, LYD_XML, LYDP_WITHSIBLINGS);
+    lyd_print_mem(&st->xml, st->diff, LYD_XML, LYD_PRINT_WITHSIBLINGS);
     assert_string_equal(st->xml,
         "<df xmlns=\"urn:libyang:tests:defaults\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"none\">"
             "<foo yang:operation=\"replace\" yang:orig-value=\"42\">41</foo><b1_1 yang:operation=\"create\">42</b1_1>"
@@ -429,8 +429,8 @@
     );
 
     assert_int_equal(lyd_diff_apply(&st->first, st->diff), LY_SUCCESS);
-    lyd_print_mem(&st->xml1, st->first, LYD_XML, LYDP_WITHSIBLINGS);
-    lyd_print_mem(&st->xml2, st->second, LYD_XML, LYDP_WITHSIBLINGS);
+    lyd_print_mem(&st->xml1, st->first, LYD_XML, LYD_PRINT_WITHSIBLINGS);
+    lyd_print_mem(&st->xml2, st->second, LYD_XML, LYD_PRINT_WITHSIBLINGS);
     assert_string_equal(st->xml1, st->xml2);
 }
 
@@ -447,15 +447,15 @@
                          "<list><name>c</name><value>3</value></list>"
                        "</df>";
 
-    st->first = lyd_parse_mem(st->ctx, xml1, LYD_XML, LYD_OPT_PARSE_ONLY);
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(st->ctx, xml1, LYD_XML, LYD_PARSE_ONLY, 0, &st->first));
     assert_non_null(st->first);
-    st->second = lyd_parse_mem(st->ctx, xml2, LYD_XML, LYD_OPT_PARSE_ONLY);
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(st->ctx, xml2, LYD_XML, LYD_PARSE_ONLY, 0, &st->second));
     assert_non_null(st->second);
 
     assert_int_equal(lyd_diff(st->first, st->second, 0, &st->diff), LY_SUCCESS);
 
     assert_non_null(st->diff);
-    lyd_print_mem(&st->xml, st->diff, LYD_XML, LYDP_WITHSIBLINGS);
+    lyd_print_mem(&st->xml, st->diff, LYD_XML, LYD_PRINT_WITHSIBLINGS);
     assert_string_equal(st->xml,
         "<df xmlns=\"urn:libyang:tests:defaults\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"none\">"
             "<list yang:operation=\"delete\"><name>a</name><value>1</value></list>"
@@ -467,8 +467,8 @@
     );
 
     assert_int_equal(lyd_diff_apply(&st->first, st->diff), LY_SUCCESS);
-    lyd_print_mem(&st->xml1, st->first, LYD_XML, LYDP_WITHSIBLINGS);
-    lyd_print_mem(&st->xml2, st->second, LYD_XML, LYDP_WITHSIBLINGS);
+    lyd_print_mem(&st->xml1, st->first, LYD_XML, LYD_PRINT_WITHSIBLINGS);
+    lyd_print_mem(&st->xml2, st->second, LYD_XML, LYD_PRINT_WITHSIBLINGS);
     assert_string_equal(st->xml1, st->xml2);
 }
 
@@ -491,15 +491,15 @@
                          "<llist>5</llist>"
                        "</df>";
 
-    st->first = lyd_parse_mem(st->ctx, xml1, LYD_XML, LYD_OPT_PARSE_ONLY);
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(st->ctx, xml1, LYD_XML, LYD_PARSE_ONLY, 0, &st->first));
     assert_non_null(st->first);
-    st->second = lyd_parse_mem(st->ctx, xml2, LYD_XML, LYD_OPT_PARSE_ONLY);
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(st->ctx, xml2, LYD_XML, LYD_PARSE_ONLY, 0, &st->second));
     assert_non_null(st->second);
 
     assert_int_equal(lyd_diff(st->first, st->second, 0, &st->diff), LY_SUCCESS);
 
     assert_non_null(st->diff);
-    lyd_print_mem(&st->xml, st->diff, LYD_XML, LYDP_WITHSIBLINGS);
+    lyd_print_mem(&st->xml, st->diff, LYD_XML, LYD_PRINT_WITHSIBLINGS);
     assert_string_equal(st->xml,
         "<df xmlns=\"urn:libyang:tests:defaults\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"none\">"
             "<llist yang:operation=\"replace\" yang:orig-value=\"3\" yang:value=\"1\">4</llist>"
@@ -508,8 +508,8 @@
     );
 
     assert_int_equal(lyd_diff_apply(&st->first, st->diff), LY_SUCCESS);
-    lyd_print_mem(&st->xml1, st->first, LYD_XML, LYDP_WITHSIBLINGS);
-    lyd_print_mem(&st->xml2, st->second, LYD_XML, LYDP_WITHSIBLINGS);
+    lyd_print_mem(&st->xml1, st->first, LYD_XML, LYD_PRINT_WITHSIBLINGS);
+    lyd_print_mem(&st->xml2, st->second, LYD_XML, LYD_PRINT_WITHSIBLINGS);
     assert_string_equal(st->xml1, st->xml2);
 }
 
@@ -532,15 +532,15 @@
                          "<llist>3</llist>"
                        "</df>";
 
-    st->first = lyd_parse_mem(st->ctx, xml1, LYD_XML, LYD_OPT_PARSE_ONLY);
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(st->ctx, xml1, LYD_XML, LYD_PARSE_ONLY, 0, &st->first));
     assert_non_null(st->first);
-    st->second = lyd_parse_mem(st->ctx, xml2, LYD_XML, LYD_OPT_PARSE_ONLY);
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(st->ctx, xml2, LYD_XML, LYD_PARSE_ONLY, 0, &st->second));
     assert_non_null(st->second);
 
     assert_int_equal(lyd_diff(st->first, st->second, 0, &st->diff), LY_SUCCESS);
 
     assert_non_null(st->diff);
-    lyd_print_mem(&st->xml, st->diff, LYD_XML, LYDP_WITHSIBLINGS);
+    lyd_print_mem(&st->xml, st->diff, LYD_XML, LYD_PRINT_WITHSIBLINGS);
     assert_string_equal(st->xml,
         "<df xmlns=\"urn:libyang:tests:defaults\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"none\">"
             "<llist yang:operation=\"replace\" yang:orig-value=\"3\" yang:value=\"2\">4</llist>"
@@ -548,8 +548,8 @@
     );
 
     assert_int_equal(lyd_diff_apply(&st->first, st->diff), LY_SUCCESS);
-    lyd_print_mem(&st->xml1, st->first, LYD_XML, LYDP_WITHSIBLINGS);
-    lyd_print_mem(&st->xml2, st->second, LYD_XML, LYDP_WITHSIBLINGS);
+    lyd_print_mem(&st->xml1, st->first, LYD_XML, LYD_PRINT_WITHSIBLINGS);
+    lyd_print_mem(&st->xml2, st->second, LYD_XML, LYD_PRINT_WITHSIBLINGS);
     assert_string_equal(st->xml1, st->xml2);
 }
 
@@ -567,15 +567,15 @@
                          "<llist>1</llist>"
                        "</df>";
 
-    st->first = lyd_parse_mem(st->ctx, xml1, LYD_XML, LYD_OPT_PARSE_ONLY);
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(st->ctx, xml1, LYD_XML, LYD_PARSE_ONLY, 0, &st->first));
     assert_non_null(st->first);
-    st->second = lyd_parse_mem(st->ctx, xml2, LYD_XML, LYD_OPT_PARSE_ONLY);
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(st->ctx, xml2, LYD_XML, LYD_PARSE_ONLY, 0, &st->second));
     assert_non_null(st->second);
 
     assert_int_equal(lyd_diff(st->first, st->second, 0, &st->diff), LY_SUCCESS);
 
     assert_non_null(st->diff);
-    lyd_print_mem(&st->xml, st->diff, LYD_XML, LYDP_WITHSIBLINGS);
+    lyd_print_mem(&st->xml, st->diff, LYD_XML, LYD_PRINT_WITHSIBLINGS);
     assert_string_equal(st->xml,
         "<df xmlns=\"urn:libyang:tests:defaults\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"none\">"
             "<llist yang:operation=\"delete\" yang:orig-value=\"1\">2</llist>"
@@ -584,8 +584,8 @@
     );
 
     assert_int_equal(lyd_diff_apply(&st->first, st->diff), LY_SUCCESS);
-    lyd_print_mem(&st->xml1, st->first, LYD_XML, LYDP_WITHSIBLINGS);
-    lyd_print_mem(&st->xml2, st->second, LYD_XML, LYDP_WITHSIBLINGS);
+    lyd_print_mem(&st->xml1, st->first, LYD_XML, LYD_PRINT_WITHSIBLINGS);
+    lyd_print_mem(&st->xml2, st->second, LYD_XML, LYD_PRINT_WITHSIBLINGS);
     assert_string_equal(st->xml1, st->xml2);
 }
 
@@ -604,15 +604,15 @@
                          "<llist>1</llist>"
                        "</df>";
 
-    st->first = lyd_parse_mem(st->ctx, xml1, LYD_XML, LYD_OPT_PARSE_ONLY);
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(st->ctx, xml1, LYD_XML, LYD_PARSE_ONLY, 0, &st->first));
     assert_non_null(st->first);
-    st->second = lyd_parse_mem(st->ctx, xml2, LYD_XML, LYD_OPT_PARSE_ONLY);
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(st->ctx, xml2, LYD_XML, LYD_PARSE_ONLY, 0, &st->second));
     assert_non_null(st->second);
 
     assert_int_equal(lyd_diff(st->first, st->second, 0, &st->diff), LY_SUCCESS);
 
     assert_non_null(st->diff);
-    lyd_print_mem(&st->xml, st->diff, LYD_XML, LYDP_WITHSIBLINGS);
+    lyd_print_mem(&st->xml, st->diff, LYD_XML, LYD_PRINT_WITHSIBLINGS);
     assert_string_equal(st->xml,
         "<df xmlns=\"urn:libyang:tests:defaults\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"none\">"
             "<llist yang:operation=\"delete\" yang:orig-value=\"1\">2</llist>"
@@ -622,8 +622,8 @@
     );
 
     assert_int_equal(lyd_diff_apply(&st->first, st->diff), LY_SUCCESS);
-    lyd_print_mem(&st->xml1, st->first, LYD_XML, LYDP_WITHSIBLINGS);
-    lyd_print_mem(&st->xml2, st->second, LYD_XML, LYDP_WITHSIBLINGS);
+    lyd_print_mem(&st->xml1, st->first, LYD_XML, LYD_PRINT_WITHSIBLINGS);
+    lyd_print_mem(&st->xml2, st->second, LYD_XML, LYD_PRINT_WITHSIBLINGS);
     assert_string_equal(st->xml1, st->xml2);
 }
 
@@ -642,13 +642,13 @@
     st->first = NULL;
     assert_int_equal(lyd_validate_modules(&st->first, &mod, 1, 0), LY_SUCCESS);
     assert_ptr_not_equal(st->first, NULL);
-    st->second = lyd_parse_mem(st->ctx, xml, LYD_XML, LYD_VALOPT_DATA_ONLY);
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(st->ctx, xml, LYD_XML, 0, LYD_VALIDATE_PRESENT, &st->second));
     assert_non_null(st->second);
 
     assert_int_equal(lyd_diff(st->first, st->second, LYD_DIFF_WITHDEFAULTS, &st->diff), LY_SUCCESS);
 
     assert_non_null(st->diff);
-    lyd_print_mem(&st->xml, st->diff, LYD_XML, LYDP_WITHSIBLINGS);
+    lyd_print_mem(&st->xml, st->diff, LYD_XML, LYD_PRINT_WITHSIBLINGS);
     assert_string_equal(st->xml,
         "<df xmlns=\"urn:libyang:tests:defaults\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"none\">"
             "<foo yang:operation=\"replace\" yang:orig-default=\"true\" yang:orig-value=\"42\">41</foo>"
@@ -660,8 +660,8 @@
     );
 
     assert_int_equal(lyd_diff_apply(&st->first, st->diff), LY_SUCCESS);
-    lyd_print_mem(&st->xml1, st->first, LYD_XML, LYDP_WITHSIBLINGS);
-    lyd_print_mem(&st->xml2, st->second, LYD_XML, LYDP_WITHSIBLINGS);
+    lyd_print_mem(&st->xml1, st->first, LYD_XML, LYD_PRINT_WITHSIBLINGS);
+    lyd_print_mem(&st->xml2, st->second, LYD_XML, LYD_PRINT_WITHSIBLINGS);
     /* TODO just an ordering problem
     assert_string_equal(st->xml1, st->xml2);*/
 }
diff --git a/tests/utests/data/test_lyb.c b/tests/utests/data/test_lyb.c
index 37b9e5b..a46f3d6 100644
--- a/tests/utests/data/test_lyb.c
+++ b/tests/utests/data/test_lyb.c
@@ -260,13 +260,13 @@
     assert_non_null(ly_ctx_load_module(st->ctx, "ietf-ip", NULL));
     assert_non_null(ly_ctx_load_module(st->ctx, "iana-if-type", NULL));
 
-    st->dt1 = lyd_parse_mem(st->ctx, data_xml, LYD_XML, LYD_OPT_PARSE_ONLY);
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(st->ctx, data_xml, LYD_XML, LYD_PARSE_ONLY, 0, &st->dt1));
     assert_ptr_not_equal(st->dt1, NULL);
 
-    ret = lyd_print_mem(&st->mem, st->dt1, LYD_LYB, LYDP_WITHSIBLINGS);
+    ret = lyd_print_mem(&st->mem, st->dt1, LYD_LYB, LYD_PRINT_WITHSIBLINGS);
     assert_int_equal(ret, 0);
 
-    st->dt2 = lyd_parse_mem(st->ctx, st->mem, LYD_LYB, LYD_OPT_PARSE_ONLY | LYD_OPT_STRICT);
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(st->ctx, st->mem, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &st->dt2));
     assert_ptr_not_equal(st->dt2, NULL);
 
     check_data_tree(st->dt1, st->dt2);
@@ -307,13 +307,13 @@
     assert_non_null(lys_parse_mem(st->ctx, origin_yang, LYS_IN_YANG));
     lys_set_implemented(ly_ctx_get_module_latest(st->ctx, "ietf-origin"));
 
-    st->dt1 = lyd_parse_mem(st->ctx, data_xml, LYD_XML, LYD_OPT_PARSE_ONLY);
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(st->ctx, data_xml, LYD_XML, LYD_PARSE_ONLY, 0, &st->dt1));
     assert_ptr_not_equal(st->dt1, NULL);
 
-    ret = lyd_print_mem(&st->mem, st->dt1, LYD_LYB, LYDP_WITHSIBLINGS);
+    ret = lyd_print_mem(&st->mem, st->dt1, LYD_LYB, LYD_PRINT_WITHSIBLINGS);
     assert_int_equal(ret, 0);
 
-    st->dt2 = lyd_parse_mem(st->ctx, st->mem, LYD_LYB, LYD_OPT_PARSE_ONLY | LYD_OPT_STRICT);
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(st->ctx, st->mem, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &st->dt2));
     assert_ptr_not_equal(st->dt2, NULL);
 
     check_data_tree(st->dt1, st->dt2);
@@ -517,13 +517,13 @@
     assert_non_null(lys_parse_mem(st->ctx, links_yang, LYS_IN_YANG));
     assert_non_null(lys_parse_mem(st->ctx, statements_yang, LYS_IN_YANG));
 
-    st->dt1 = lyd_parse_mem(st->ctx, data_xml, LYD_XML, LYD_OPT_PARSE_ONLY);
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(st->ctx, data_xml, LYD_XML, LYD_PARSE_ONLY, 0, &st->dt1));
     assert_ptr_not_equal(st->dt1, NULL);
 
-    ret = lyd_print_mem(&st->mem, st->dt1, LYD_LYB, LYDP_WITHSIBLINGS);
+    ret = lyd_print_mem(&st->mem, st->dt1, LYD_LYB, LYD_PRINT_WITHSIBLINGS);
     assert_int_equal(ret, 0);
 
-    st->dt2 = lyd_parse_mem(st->ctx, st->mem, LYD_LYB, LYD_OPT_PARSE_ONLY | LYD_OPT_STRICT);
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(st->ctx, st->mem, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &st->dt2));
     assert_ptr_not_equal(st->dt2, NULL);
 
     check_data_tree(st->dt1, st->dt2);
diff --git a/tests/utests/data/test_merge.c b/tests/utests/data/test_merge.c
index da53069..0c77cea 100644
--- a/tests/utests/data/test_merge.c
+++ b/tests/utests/data/test_merge.c
@@ -74,7 +74,6 @@
 test_batch(void **state)
 {
     struct state *st = (*state);
-    LY_ERR ret;
     uint32_t i;
     char *str;
 
@@ -232,21 +231,25 @@
             "<namespace>urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults</namespace>"
         "</module>"
     "</modules-state>";
+    struct ly_in *in = NULL;
 
-    st->target = lyd_parse_mem(st->ctx, start, LYD_XML, LYD_OPT_PARSE_ONLY);
+    assert_int_equal(LY_SUCCESS, ly_in_new_memory(start, &in));
+    assert_int_equal(LY_SUCCESS, lyd_parse_data(st->ctx, in, LYD_XML, LYD_PARSE_ONLY, 0, &st->target));
     assert_non_null(st->target);
 
     for (i = 0; i < 11; ++i) {
-        st->source = lyd_parse_mem(st->ctx, data[i], LYD_XML, LYD_OPT_PARSE_ONLY);
+        ly_in_memory(in, data[i]);
+        assert_int_equal(LY_SUCCESS, lyd_parse_data(st->ctx, in, LYD_XML, LYD_PARSE_ONLY, 0, &st->source));
         assert_non_null(st->source);
 
-        ret = lyd_merge(&st->target, st->source, LYD_MERGE_DESTRUCT);
-        assert_int_equal(ret, LY_SUCCESS);
+        assert_int_equal(LY_SUCCESS, lyd_merge(&st->target, st->source, LYD_MERGE_DESTRUCT));
         st->source = NULL;
     }
 
     lyd_print_mem(&str, st->target, LYD_XML, 0);
     assert_string_equal(str, output_template);
+
+    ly_in_free(in, 0);
     free(str);
 }
 
@@ -271,18 +274,18 @@
 
     assert_non_null(lys_parse_mem(st->ctx, sch, LYS_IN_YANG));
 
-    st->source = lyd_parse_mem(st->ctx, src, LYD_XML, LYD_VALOPT_DATA_ONLY);
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(st->ctx, src, LYD_XML, 0, LYD_VALIDATE_PRESENT, &st->source));
     assert_non_null(st->source);
 
-    st->target = lyd_parse_mem(st->ctx, trg, LYD_XML, LYD_VALOPT_DATA_ONLY);
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(st->ctx, trg, LYD_XML, 0, LYD_VALIDATE_PRESENT, &st->target));
     assert_non_null(st->target);
 
     /* merge them */
     assert_int_equal(lyd_merge(&st->target, st->source, 0), LY_SUCCESS);
-    assert_int_equal(lyd_validate(&st->target, NULL, LYD_VALOPT_DATA_ONLY), LY_SUCCESS);
+    assert_int_equal(lyd_validate(&st->target, NULL, LYD_VALIDATE_PRESENT), LY_SUCCESS);
 
     /* check the result */
-    lyd_print_mem(&printed, st->target, LYD_XML, LYDP_WITHSIBLINGS);
+    lyd_print_mem(&printed, st->target, LYD_XML, LYD_PRINT_WITHSIBLINGS);
     assert_string_equal(printed, result);
     free(printed);
 }
@@ -313,18 +316,18 @@
 
     assert_non_null(lys_parse_mem(st->ctx, sch, LYS_IN_YANG));
 
-    st->source = lyd_parse_mem(st->ctx, src, LYD_XML, LYD_VALOPT_DATA_ONLY);
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(st->ctx, src, LYD_XML, 0, LYD_VALIDATE_PRESENT, &st->source));
     assert_non_null(st->source);
 
-    st->target = lyd_parse_mem(st->ctx, trg, LYD_XML, LYD_VALOPT_DATA_ONLY);
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(st->ctx, trg, LYD_XML, 0, LYD_VALIDATE_PRESENT, &st->target));
     assert_non_null(st->target);
 
     /* merge them */
     assert_int_equal(lyd_merge(&st->target, st->source, 0), LY_SUCCESS);
-    assert_int_equal(lyd_validate(&st->target, NULL, LYD_VALOPT_DATA_ONLY), LY_SUCCESS);
+    assert_int_equal(lyd_validate(&st->target, NULL, LYD_VALIDATE_PRESENT), LY_SUCCESS);
 
     /* check the result */
-    lyd_print_mem(&printed, st->target, LYD_XML, LYDP_WITHSIBLINGS);
+    lyd_print_mem(&printed, st->target, LYD_XML, LYD_PRINT_WITHSIBLINGS);
     assert_string_equal(printed, result);
     free(printed);
 }
@@ -383,18 +386,18 @@
 
     assert_non_null(lys_parse_mem(st->ctx, sch, LYS_IN_YANG));
 
-    st->source = lyd_parse_mem(st->ctx, src, LYD_XML, LYD_VALOPT_DATA_ONLY);
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(st->ctx, src, LYD_XML, 0, LYD_VALIDATE_PRESENT, &st->source));
     assert_non_null(st->source);
 
-    st->target = lyd_parse_mem(st->ctx, trg, LYD_XML, LYD_VALOPT_DATA_ONLY);
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(st->ctx, trg, LYD_XML, 0, LYD_VALIDATE_PRESENT, &st->target));
     assert_non_null(st->target);
 
     /* merge them */
     assert_int_equal(lyd_merge(&st->target, st->source, LYD_MERGE_EXPLICIT), LY_SUCCESS);
-    assert_int_equal(lyd_validate(&st->target, NULL, LYD_VALOPT_DATA_ONLY), LY_SUCCESS);
+    assert_int_equal(lyd_validate(&st->target, NULL, LYD_VALIDATE_PRESENT), LY_SUCCESS);
 
     /* check the result */
-    lyd_print_mem(&printed, st->target, LYD_XML, LYDP_WITHSIBLINGS);
+    lyd_print_mem(&printed, st->target, LYD_XML, LYD_PRINT_WITHSIBLINGS);
     assert_string_equal(printed, result);
     free(printed);
 }
@@ -462,18 +465,18 @@
 
     assert_non_null(lys_parse_mem(st->ctx, sch, LYS_IN_YANG));
 
-    st->source = lyd_parse_mem(st->ctx, src, LYD_XML, LYD_VALOPT_DATA_ONLY);
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(st->ctx, src, LYD_XML, 0, LYD_VALIDATE_PRESENT, &st->source));
     assert_non_null(st->source);
 
-    st->target = lyd_parse_mem(st->ctx, trg, LYD_XML, LYD_VALOPT_DATA_ONLY);
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(st->ctx, trg, LYD_XML, 0, LYD_VALIDATE_PRESENT, &st->target));
     assert_non_null(st->target);
 
     /* merge them */
     assert_int_equal(lyd_merge(&st->target, st->source, LYD_MERGE_EXPLICIT), LY_SUCCESS);
-    assert_int_equal(lyd_validate(&st->target, NULL, LYD_VALOPT_DATA_ONLY), LY_SUCCESS);
+    assert_int_equal(lyd_validate(&st->target, NULL, LYD_VALIDATE_PRESENT), LY_SUCCESS);
 
     /* check the result */
-    lyd_print_mem(&printed, st->target, LYD_XML, LYDP_WITHSIBLINGS);
+    lyd_print_mem(&printed, st->target, LYD_XML, LYD_PRINT_WITHSIBLINGS);
     assert_string_equal(printed, result);
     free(printed);
 }
@@ -520,18 +523,18 @@
 
     assert_non_null(lys_parse_mem(st->ctx, sch, LYS_IN_YANG));
 
-    st->source = lyd_parse_mem(st->ctx, src, LYD_XML, LYD_VALOPT_DATA_ONLY);
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(st->ctx, src, LYD_XML, 0, LYD_VALIDATE_PRESENT, &st->source));
     assert_non_null(st->source);
 
-    st->target = lyd_parse_mem(st->ctx, trg, LYD_XML, LYD_VALOPT_DATA_ONLY);
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(st->ctx, trg, LYD_XML, 0, LYD_VALIDATE_PRESENT, &st->target));
     assert_non_null(st->target);
 
     /* merge them */
     assert_int_equal(lyd_merge(&st->target, st->source, 0), LY_SUCCESS);
-    assert_int_equal(lyd_validate(&st->target, NULL, LYD_VALOPT_DATA_ONLY), LY_SUCCESS);
+    assert_int_equal(lyd_validate(&st->target, NULL, LYD_VALIDATE_PRESENT), LY_SUCCESS);
 
     /* check the result */
-    lyd_print_mem(&printed, st->target, LYD_XML, LYDP_WITHSIBLINGS);
+    lyd_print_mem(&printed, st->target, LYD_XML, LYD_PRINT_WITHSIBLINGS);
     assert_string_equal(printed, result);
     free(printed);
 }
@@ -563,13 +566,13 @@
 
     st->target = lyd_new_path(NULL, st->ctx, "/merge-dflt:top/c", "c_dflt", 0);
     assert_non_null(st->target);
-    assert_int_equal(lyd_validate(&(st->target), NULL, LYD_VALOPT_DATA_ONLY), LY_SUCCESS);
+    assert_int_equal(lyd_validate(&(st->target), NULL, LYD_VALIDATE_PRESENT), LY_SUCCESS);
 
     st->source = lyd_new_path(NULL, st->ctx, "/merge-dflt:top/a", "a_val", 0);
     assert_non_null(st->source);
     tmp = lyd_new_path(st->source, st->ctx, "/merge-dflt:top/b", "b_val", 0);
     assert_non_null(tmp);
-    assert_int_equal(lyd_validate(&(st->source), NULL, LYD_VALOPT_DATA_ONLY), LY_SUCCESS);
+    assert_int_equal(lyd_validate(&(st->source), NULL, LYD_VALIDATE_PRESENT), LY_SUCCESS);
 
     assert_int_equal(lyd_merge(&st->target, st->source, LYD_MERGE_DESTRUCT), LY_SUCCESS);
     st->source = NULL;
@@ -605,13 +608,13 @@
 
     st->target = lyd_new_path(NULL, st->ctx, "/merge-dflt:top/c", "c_dflt", 0);
     assert_non_null(st->target);
-    assert_int_equal(lyd_validate(&(st->target), NULL, LYD_VALOPT_DATA_ONLY), LY_SUCCESS);
+    assert_int_equal(lyd_validate(&(st->target), NULL, LYD_VALIDATE_PRESENT), LY_SUCCESS);
 
     st->source = lyd_new_path(NULL, st->ctx, "/merge-dflt:top/a", "a_val", 0);
     assert_non_null(st->source);
     tmp = lyd_new_path(st->source, st->ctx, "/merge-dflt:top/b", "b_val", 0);
     assert_non_null(tmp);
-    assert_int_equal(lyd_validate(&(st->source), NULL, LYD_VALOPT_DATA_ONLY), LY_SUCCESS);
+    assert_int_equal(lyd_validate(&(st->source), NULL, LYD_VALIDATE_PRESENT), LY_SUCCESS);
 
     assert_int_equal(lyd_merge(&st->target, st->source, LYD_MERGE_EXPLICIT), LY_SUCCESS);
 
@@ -642,16 +645,16 @@
 
     assert_non_null(lys_parse_mem(st->ctx, sch, LYS_IN_YANG));
 
-    st->target = lyd_parse_mem(st->ctx, trg, LYD_XML, LYD_VALOPT_DATA_ONLY);
-    assert_non_null(st->target);
-
-    st->source = lyd_parse_mem(st->ctx, src, LYD_XML, LYD_VALOPT_DATA_ONLY);
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(st->ctx, src, LYD_XML, 0, LYD_VALIDATE_PRESENT, &st->source));
     assert_non_null(st->source);
 
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(st->ctx, trg, LYD_XML, 0, LYD_VALIDATE_PRESENT, &st->target));
+    assert_non_null(st->target);
+
     assert_int_equal(lyd_merge(&st->target, st->source, LYD_MERGE_DESTRUCT), LY_SUCCESS);
     st->source = NULL;
 
-    lyd_print_mem(&prt, st->target, LYD_XML, LYDP_WITHSIBLINGS);
+    lyd_print_mem(&prt, st->target, LYD_XML, LYD_PRINT_WITHSIBLINGS);
     assert_string_equal(prt, res);
     free(prt);
 }
diff --git a/tests/utests/data/test_parser_xml.c b/tests/utests/data/test_parser_xml.c
index 18b54d4..20681b1 100644
--- a/tests/utests/data/test_parser_xml.c
+++ b/tests/utests/data/test_parser_xml.c
@@ -21,6 +21,7 @@
 #include <string.h>
 
 #include "context.h"
+#include "parser_data.h"
 #include "printer.h"
 #include "printer_data.h"
 #include "tests/config.h"
@@ -125,7 +126,7 @@
     struct lyd_node *tree;
     struct lyd_node_term *leaf;
 
-    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_non_null(tree);
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("foo", tree->schema->name);
@@ -142,7 +143,7 @@
 
     /* make foo2 explicit */
     data = "<foo2 xmlns=\"urn:tests:a\">default-val</foo2>";
-    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_non_null(tree);
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("foo2", tree->schema->name);
@@ -154,7 +155,7 @@
 
     /* parse foo2 but make it implicit */
     data = "<foo2 xmlns=\"urn:tests:a\" xmlns:wd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" wd:default=\"true\">default-val</foo2>";
-    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_non_null(tree);
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("foo2", tree->schema->name);
@@ -186,7 +187,7 @@
         "</element1>"
         "<element1a/>"
     "</any>";
-    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_non_null(tree);
     assert_int_equal(LYS_ANYDATA, tree->schema->nodetype);
     assert_string_equal("any", tree->schema->name);
@@ -219,7 +220,7 @@
     struct lyd_node_term *leaf;
 
     /* check hashes */
-    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_non_null(tree);
     assert_int_equal(LYS_LIST, tree->schema->nodetype);
     assert_string_equal("l1", tree->schema->name);
@@ -231,25 +232,25 @@
 
     /* missing keys */
     data = "<l1 xmlns=\"urn:tests:a\"><c>1</c><b>b</b></l1>";
-    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     logbuf_assert("List instance is missing its key \"a\". /a:l1[b='b'][c='1']");
 
     data = "<l1 xmlns=\"urn:tests:a\"><a>a</a></l1>";
-    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     logbuf_assert("List instance is missing its key \"b\". /a:l1[a='a']");
 
     data = "<l1 xmlns=\"urn:tests:a\"><b>b</b><a>a</a></l1>";
-    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     logbuf_assert("List instance is missing its key \"c\". /a:l1[a='a'][b='b']");
 
     /* key duplicate */
     data = "<l1 xmlns=\"urn:tests:a\"><c>1</c><b>b</b><a>a</a><c>1</c></l1>";
-    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     logbuf_assert("Duplicate instance of \"c\". /a:l1[a='a'][b='b'][c='1'][c='1']/c");
 
     /* keys order */
     data = "<l1 xmlns=\"urn:tests:a\"><d>d</d><a>a</a><c>1</c><b>b</b></l1>";
-    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_non_null(tree);
     assert_int_equal(LYS_LIST, tree->schema->nodetype);
     assert_string_equal("l1", tree->schema->name);
@@ -266,7 +267,7 @@
     lyd_free_all(tree);
 
     data = "<l1 xmlns=\"urn:tests:a\"><c>1</c><b>b</b><a>a</a></l1>";
-    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_non_null(tree);
     assert_int_equal(LYS_LIST, tree->schema->nodetype);
     assert_string_equal("l1", tree->schema->name);
@@ -281,7 +282,7 @@
     logbuf_clean();
     lyd_free_all(tree);
 
-    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_OPT_STRICT, &tree));
+    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_PARSE_STRICT, 0, &tree));
     logbuf_assert("Invalid position of the key \"b\" in a list. Line number 1.");
 
     *state = NULL;
@@ -296,7 +297,7 @@
     struct lyd_node *tree;
     struct lyd_node_inner *cont;
 
-    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_non_null(tree);
     assert_int_equal(LYS_CONTAINER, tree->schema->nodetype);
     assert_string_equal("c", tree->schema->name);
@@ -305,7 +306,7 @@
     lyd_free_all(tree);
 
     data = "<cp xmlns=\"urn:tests:a\"/>";
-    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_non_null(tree);
     assert_int_equal(LYS_CONTAINER, tree->schema->nodetype);
     assert_string_equal("cp", tree->schema->name);
@@ -330,12 +331,12 @@
 
     /* invalid value, no flags */
     data = "<foo3 xmlns=\"urn:tests:a\"/>";
-    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     logbuf_assert("Invalid empty uint32 value. /a:foo3");
     assert_null(tree);
 
     /* opaq flag */
-    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_OPT_OPAQ | LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_PARSE_OPAQ, LYD_VALIDATE_PRESENT, &tree));
     assert_non_null(tree);
     assert_null(tree->schema);
     assert_string_equal(((struct lyd_node_opaq *)tree)->name, "foo3");
@@ -348,12 +349,12 @@
 
     /* missing key, no flags */
     data = "<l1 xmlns=\"urn:tests:a\"><a>val_a</a><b>val_b</b><d>val_d</d></l1>";
-    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     logbuf_assert("List instance is missing its key \"c\". /a:l1[a='val_a'][b='val_b']");
     assert_null(tree);
 
     /* opaq flag */
-    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_OPT_OPAQ | LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_PARSE_OPAQ , LYD_VALIDATE_PRESENT, &tree));
     assert_non_null(tree);
     assert_null(tree->schema);
     assert_string_equal(((struct lyd_node_opaq *)tree)->name, "l1");
@@ -366,12 +367,12 @@
 
     /* invalid key, no flags */
     data = "<l1 xmlns=\"urn:tests:a\"><a>val_a</a><b>val_b</b><c>val_c</c></l1>";
-    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     logbuf_assert("Invalid int16 value \"val_c\". /a:l1/c");
     assert_null(tree);
 
     /* opaq flag */
-    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_OPT_OPAQ | LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_PARSE_OPAQ, LYD_VALIDATE_PRESENT, &tree));
     assert_non_null(tree);
     assert_null(tree->schema);
     assert_string_equal(((struct lyd_node_opaq *)tree)->name, "l1");
@@ -383,8 +384,7 @@
     lyd_free_all(tree);
 
     /* opaq flag and fail */
-    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, "<a xmlns=\"ns\"><b>x</b><c xml:id=\"D\">1</c></a>",
-            LYD_OPT_OPAQ | LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, "<a xmlns=\"ns\"><b>x</b><c xml:id=\"D\">1</c></a>", LYD_PARSE_OPAQ, LYD_VALIDATE_PRESENT, &tree));
     assert_null(tree);
 
     ly_out_free(out, NULL, 1);
diff --git a/tests/utests/data/test_printer_xml.c b/tests/utests/data/test_printer_xml.c
index b1df7ab..e972808 100644
--- a/tests/utests/data/test_printer_xml.c
+++ b/tests/utests/data/test_printer_xml.c
@@ -22,6 +22,7 @@
 #include <string.h>
 
 #include "context.h"
+#include "parser_data.h"
 #include "printer.h"
 #include "printer_data.h"
 #include "tests/config.h"
@@ -185,7 +186,7 @@
 
     data = "<int8 xmlns=\"urn:tests:types\">\n 15 \t\n  </int8>";
     result = "<int8 xmlns=\"urn:tests:types\">15</int8>";
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(s->ctx, data, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_true((len = lyd_print(out, tree, LYD_XML, 0)) >= 0);
     assert_int_equal(len, strlen(printed));
     assert_string_equal(printed, result);
@@ -209,7 +210,7 @@
     assert_int_equal(LY_SUCCESS, ly_out_new_memory(&printed, 0, &out));
 
     data = "<any xmlns=\"urn:tests:types\"><somexml xmlns:x=\"url:x\" xmlns=\"example.com\"><x:x/></somexml></any>";
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(s->ctx, data, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_true((len = lyd_print(out, tree, LYD_XML, 0)) >= 0);
     assert_int_equal(len, strlen(printed));
     /* canonized */
@@ -219,7 +220,7 @@
     lyd_free_all(tree);
 
     data = "<any xmlns=\"urn:tests:types\"/>";
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(s->ctx, data, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_true((len = lyd_print(out, tree, LYD_XML, 0)) >= 0);
     assert_int_equal(len, strlen(printed));
     assert_string_equal(printed, data);
@@ -235,7 +236,7 @@
                 "</defs:elem1>"
             "</cont>"
         "</any>";
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(s->ctx, data, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree));
     /* cont should be normally parsed */
     assert_string_equal(tree->schema->name, "any");
     assert_int_equal(((struct lyd_node_any *)tree)->value_type, LYD_ANYDATA_DATATREE);
@@ -279,20 +280,20 @@
 
     /* standard default value */
     data = "<c xmlns=\"urn:defaults\">aa</c>";
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(s->ctx, data, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree));
 
-    assert_true((len = lyd_print(out, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_TRIM)) >= 0);
+    assert_true((len = lyd_print(out, tree, LYD_XML, LYD_PRINT_WITHSIBLINGS | LYD_PRINT_WD_TRIM)) >= 0);
     assert_int_equal(len, strlen(printed));
     assert_string_equal(printed, data);
     ly_out_reset(out);
 
-    assert_true((len = lyd_print(out, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_ALL)) >= 0);
+    assert_true((len = lyd_print(out, tree, LYD_XML, LYD_PRINT_WITHSIBLINGS | LYD_PRINT_WD_ALL)) >= 0);
     assert_int_equal(len, strlen(printed));
     data = "<c xmlns=\"urn:defaults\">aa</c><a xmlns=\"urn:defaults\" xmlns:d=\"urn:defaults\">/d:b</a>";
     assert_string_equal(printed, data);
     ly_out_reset(out);
 
-    assert_true((len = lyd_print(out, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_ALL_TAG)) >= 0);
+    assert_true((len = lyd_print(out, tree, LYD_XML, LYD_PRINT_WITHSIBLINGS | LYD_PRINT_WD_ALL_TAG)) >= 0);
     assert_int_equal(len, strlen(printed));
     data = "<c xmlns=\"urn:defaults\">aa</c>"
         "<a xmlns=\"urn:defaults\" xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\""
@@ -300,7 +301,7 @@
     assert_string_equal(printed, data);
     ly_out_reset(out);
 
-    assert_true((len = lyd_print(out, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_IMPL_TAG)) >= 0);
+    assert_true((len = lyd_print(out, tree, LYD_XML, LYD_PRINT_WITHSIBLINGS | LYD_PRINT_WD_IMPL_TAG)) >= 0);
     assert_int_equal(len, strlen(printed));
     data = "<c xmlns=\"urn:defaults\">aa</c>"
         "<a xmlns=\"urn:defaults\" xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\""
@@ -312,24 +313,24 @@
 
     /* string value equal to the default but default is an unresolved instance-identifier, so they are not considered equal */
     data = "<c xmlns=\"urn:defaults\">aa</c><a xmlns=\"urn:defaults\">/d:b</a>";
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(s->ctx, data, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree));
 
-    assert_true((len = lyd_print(out, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_TRIM)) >= 0);
+    assert_true((len = lyd_print(out, tree, LYD_XML, LYD_PRINT_WITHSIBLINGS | LYD_PRINT_WD_TRIM)) >= 0);
     assert_int_equal(len, strlen(printed));
     assert_string_equal(printed, data);
     ly_out_reset(out);
 
-    assert_true((len = lyd_print(out, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_ALL)) >= 0);
+    assert_true((len = lyd_print(out, tree, LYD_XML, LYD_PRINT_WITHSIBLINGS | LYD_PRINT_WD_ALL)) >= 0);
     assert_int_equal(len, strlen(printed));
     assert_string_equal(printed, data);
     ly_out_reset(out);
 
-    assert_true((len = lyd_print(out, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_ALL_TAG)) >= 0);
+    assert_true((len = lyd_print(out, tree, LYD_XML, LYD_PRINT_WITHSIBLINGS | LYD_PRINT_WD_ALL_TAG)) >= 0);
     assert_int_equal(len, strlen(printed));
     assert_string_equal(printed, data);
     ly_out_reset(out);
 
-    assert_true((len = lyd_print(out, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_IMPL_TAG)) >= 0);
+    assert_true((len = lyd_print(out, tree, LYD_XML, LYD_PRINT_WITHSIBLINGS | LYD_PRINT_WD_IMPL_TAG)) >= 0);
     assert_int_equal(len, strlen(printed));
     assert_string_equal(printed, data);
     ly_out_reset(out);
@@ -338,21 +339,21 @@
 
     /* instance-identifier value equal to the default, should be considered equal */
     data = "<c xmlns=\"urn:defaults\">aa</c><a xmlns=\"urn:defaults\" xmlns:d=\"urn:defaults\">/d:b</a><b xmlns=\"urn:defaults\">val</b>";
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(s->ctx, data, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree));
 
-    assert_true((len = lyd_print(out, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_TRIM)) >= 0);
+    assert_true((len = lyd_print(out, tree, LYD_XML, LYD_PRINT_WITHSIBLINGS | LYD_PRINT_WD_TRIM)) >= 0);
     assert_int_equal(len, strlen(printed));
     data = "<c xmlns=\"urn:defaults\">aa</c><b xmlns=\"urn:defaults\">val</b>";
     assert_string_equal(printed, data);
     ly_out_reset(out);
 
-    assert_true((len = lyd_print(out, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_ALL)) >= 0);
+    assert_true((len = lyd_print(out, tree, LYD_XML, LYD_PRINT_WITHSIBLINGS | LYD_PRINT_WD_ALL)) >= 0);
     assert_int_equal(len, strlen(printed));
     data = "<c xmlns=\"urn:defaults\">aa</c><a xmlns=\"urn:defaults\" xmlns:d=\"urn:defaults\">/d:b</a><b xmlns=\"urn:defaults\">val</b>";
     assert_string_equal(printed, data);
     ly_out_reset(out);
 
-    assert_true((len = lyd_print(out, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_ALL_TAG)) >= 0);
+    assert_true((len = lyd_print(out, tree, LYD_XML, LYD_PRINT_WITHSIBLINGS | LYD_PRINT_WD_ALL_TAG)) >= 0);
     assert_int_equal(len, strlen(printed));
     data = "<c xmlns=\"urn:defaults\">aa</c>"
         "<a xmlns=\"urn:defaults\" xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\""
@@ -361,7 +362,7 @@
     assert_string_equal(printed, data);
     ly_out_reset(out);
 
-    assert_true((len = lyd_print(out, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_IMPL_TAG)) >= 0);
+    assert_true((len = lyd_print(out, tree, LYD_XML, LYD_PRINT_WITHSIBLINGS | LYD_PRINT_WD_IMPL_TAG)) >= 0);
     assert_int_equal(len, strlen(printed));
     data = "<c xmlns=\"urn:defaults\">aa</c><a xmlns=\"urn:defaults\" xmlns:d=\"urn:defaults\">/d:b</a><b xmlns=\"urn:defaults\">val</b>";
     assert_string_equal(printed, data);
diff --git a/tests/utests/data/test_tree_data.c b/tests/utests/data/test_tree_data.c
index 9c38db0..31f0488 100644
--- a/tests/utests/data/test_tree_data.c
+++ b/tests/utests/data/test_tree_data.c
@@ -111,8 +111,8 @@
 
     assert_int_equal(LY_SUCCESS, lyd_compare(NULL, NULL, 0));
 
-    assert_non_null(tree1 = lyd_parse_mem(ctx, data1, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    assert_non_null(tree2 = lyd_parse_mem(ctx, data2, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data1, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree1));
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data2, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree2));
     assert_int_equal(LY_SUCCESS, lyd_compare(tree1, tree2, 0));
     assert_int_equal(LY_ENOT, lyd_compare(tree1, tree2, LYD_COMPARE_FULL_RECURSION));
     assert_int_equal(LY_ENOT, lyd_compare(((struct lyd_node_inner*)tree1)->child, tree2, 0));
@@ -121,8 +121,8 @@
 
     data1 = "<l2 xmlns=\"urn:tests:a\"><c><x>a</x></c></l2><l2 xmlns=\"urn:tests:a\"><c><x>b</x></c></l2>";
     data2 = "<l2 xmlns=\"urn:tests:a\"><c><x>b</x></c></l2>";
-    assert_non_null(tree1 = lyd_parse_mem(ctx, data1, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    assert_non_null(tree2 = lyd_parse_mem(ctx, data2, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data1, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree1));
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data2, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree2));
     assert_int_equal(LY_ENOT, lyd_compare(tree1, tree2, 0));
     assert_int_equal(LY_SUCCESS, lyd_compare(tree1->next, tree2, 0));
     lyd_free_all(tree1);
@@ -130,8 +130,8 @@
 
     data1 = "<ll xmlns=\"urn:tests:a\">a</ll><ll xmlns=\"urn:tests:a\">b</ll>";
     data2 = "<ll xmlns=\"urn:tests:a\">b</ll>";
-    assert_non_null(tree1 = lyd_parse_mem(ctx, data1, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    assert_non_null(tree2 = lyd_parse_mem(ctx, data2, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data1, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree1));
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data2, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree2));
     assert_int_equal(LY_ENOT, lyd_compare(tree1, tree2, 0));
     assert_int_equal(LY_ENOT, lyd_compare(NULL, tree2, 0));
     assert_int_equal(LY_ENOT, lyd_compare(tree1, NULL, 0));
@@ -141,8 +141,8 @@
 
     data1 = "<c xmlns=\"urn:tests:a\"><x>x</x></c>";
     data2 = "<c xmlns=\"urn:tests:a\"><x>y</x></c>";
-    assert_non_null(tree1 = lyd_parse_mem(ctx, data1, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    assert_non_null(tree2 = lyd_parse_mem(ctx, data2, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data1, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree1));
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data2, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree2));
     assert_int_equal(LY_SUCCESS, lyd_compare(tree1, tree2, 0));
     assert_int_equal(LY_ENOT, lyd_compare(tree1, tree2, LYD_COMPARE_FULL_RECURSION));
     lyd_free_all(tree1);
@@ -150,8 +150,8 @@
 
     data1 = "<c xmlns=\"urn:tests:a\"><x>x</x></c>";
     data2 = "<c xmlns=\"urn:tests:a\"><x>x</x><x>y</x></c>";
-    assert_non_null(tree1 = lyd_parse_mem(ctx, data1, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    assert_non_null(tree2 = lyd_parse_mem(ctx, data2, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data1, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree1));
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data2, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree2));
     assert_int_equal(LY_SUCCESS, lyd_compare(tree1, tree2, 0));
     assert_int_equal(LY_ENOT, lyd_compare(tree1, tree2, LYD_COMPARE_FULL_RECURSION));
     lyd_free_all(tree1);
@@ -159,12 +159,12 @@
 
     data1 = "<any xmlns=\"urn:tests:a\"><x>x</x></any>";
     data2 = "<any xmlns=\"urn:tests:a\"><x>x</x><x>y</x></any>";
-    assert_non_null(tree1 = lyd_parse_mem(ctx, data1, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    assert_non_null(tree2 = lyd_parse_mem(ctx, data2, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data1, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree1));
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data2, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree2));
     assert_int_equal(LY_ENOT, lyd_compare(tree1, tree2, 0));
     lyd_free_all(tree1);
     data1 = "<any xmlns=\"urn:tests:a\"><x>x</x><x>y</x></any>";
-    assert_non_null(tree1 = lyd_parse_mem(ctx, data1, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data1, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree1));
     assert_int_equal(LY_SUCCESS, lyd_compare(tree1, tree2, 0));
     lyd_free_all(tree1);
     lyd_free_all(tree2);
@@ -181,7 +181,7 @@
     const char *result;
     const char *data = "<l1 xmlns=\"urn:tests:a\"><a>a</a><b>b</b><c>x</c></l1>";
 
-    assert_non_null(tree1 = lyd_parse_mem(ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree1));
     assert_non_null(tree2 = lyd_dup(tree1, NULL, LYD_DUP_RECURSIVE));
     assert_int_equal(LY_SUCCESS, lyd_compare(tree1, tree2, LYD_COMPARE_FULL_RECURSION));
     lyd_free_all(tree1);
@@ -189,43 +189,43 @@
 
     data = "<l1 xmlns=\"urn:tests:a\"><a>a</a><b>b</b><c>x</c></l1>";
     result = "<l1 xmlns=\"urn:tests:a\"><a>a</a><b>b</b></l1>";
-    assert_non_null(tree1 = lyd_parse_mem(ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree1));
     assert_non_null(tree2 = lyd_dup(tree1, NULL, 0));
     lyd_free_all(tree1);
-    assert_non_null(tree1 = lyd_parse_mem(ctx, result, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, result, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree1));
     assert_int_equal(LY_SUCCESS, lyd_compare(tree1, tree2, LYD_COMPARE_FULL_RECURSION));
     lyd_free_all(tree1);
     lyd_free_all(tree2);
 
     data = "<l2 xmlns=\"urn:tests:a\"><c><x>a</x></c></l2><l2 xmlns=\"urn:tests:a\"><c><x>b</x></c></l2>";
     result = "<l2 xmlns=\"urn:tests:a\"><c><x>a</x></c></l2>";
-    assert_non_null(tree1 = lyd_parse_mem(ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree1));
     assert_non_null(tree2 = lyd_dup(tree1, NULL, LYD_DUP_WITH_SIBLINGS | LYD_DUP_RECURSIVE));
     assert_int_equal(LY_SUCCESS, lyd_compare(tree1, tree2, LYD_COMPARE_FULL_RECURSION));
     lyd_free_all(tree2);
     assert_non_null(tree2 = lyd_dup(tree1, NULL, LYD_DUP_RECURSIVE));
     lyd_free_all(tree1);
-    assert_non_null(tree1 = lyd_parse_mem(ctx, result, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, result, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree1));
     assert_int_equal(LY_SUCCESS, lyd_compare(tree1, tree2, LYD_COMPARE_FULL_RECURSION));
     lyd_free_all(tree2);
 
     assert_non_null(tree2 = lyd_dup(tree1, NULL, 0));
     lyd_free_all(tree1);
     result = "<l2 xmlns=\"urn:tests:a\"/>";
-    assert_non_null(tree1 = lyd_parse_mem(ctx, result, LYD_XML, LYD_OPT_PARSE_ONLY));
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, result, LYD_XML, LYD_PARSE_ONLY, 0, &tree1));
     assert_int_equal(LY_SUCCESS, lyd_compare(tree1, tree2, LYD_COMPARE_FULL_RECURSION));
     lyd_free_all(tree1);
     lyd_free_all(tree2);
 
     data = "<any xmlns=\"urn:tests:a\"><c><a>a</a></c></any>";
-    assert_non_null(tree1 = lyd_parse_mem(ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree1));
     assert_non_null(tree2 = lyd_dup(tree1, NULL, 0));
     assert_int_equal(LY_SUCCESS, lyd_compare(tree1, tree2, LYD_COMPARE_FULL_RECURSION));
     lyd_free_all(tree1);
     lyd_free_all(tree2);
 
     data = "<l2 xmlns=\"urn:tests:a\"><c><x>b</x></c></l2>";
-    assert_non_null(tree1 = lyd_parse_mem(ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree1));
     assert_non_null(tree2 = lyd_dup(((struct lyd_node_inner*)((struct lyd_node_inner*)tree1)->child)->child, NULL, LYD_DUP_WITH_PARENTS));
     assert_string_equal("x", tree2->schema->name);
     assert_non_null(tree2->parent);
@@ -234,7 +234,7 @@
     lyd_free_all(tree2);
 
     data = "<l1 xmlns=\"urn:tests:a\"><a>a</a><b>b</b><c>c</c></l1>";
-    assert_non_null(tree1 = lyd_parse_mem(ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree1));
     assert_non_null(tree2 = lyd_dup(((struct lyd_node_inner*)tree1)->child->prev, NULL, LYD_DUP_WITH_PARENTS));
     assert_string_equal("c", tree2->schema->name);
     assert_non_null(tree2->parent);
@@ -243,7 +243,7 @@
     lyd_free_all(tree2);
 
     data = "<l2 xmlns=\"urn:tests:a\"><c><x>b</x></c></l2>";
-    assert_non_null(tree1 = lyd_parse_mem(ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree1));
     assert_non_null(tree2 = lyd_dup(tree1, NULL, 0));
     assert_non_null(lyd_dup(((struct lyd_node_inner*)((struct lyd_node_inner*)tree1)->child)->child,
                             (struct lyd_node_inner*)tree2, LYD_DUP_WITH_PARENTS));
@@ -253,7 +253,7 @@
 
     /* invalid */
     data = "<l1 xmlns=\"urn:tests:a\"><a>a</a><b>b</b><c>c</c></l1><l2 xmlns=\"urn:tests:a\"><c><x>b</x></c></l2>";
-    assert_non_null(tree1 = lyd_parse_mem(ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree1));
     assert_null(lyd_dup(((struct lyd_node_inner*)tree1)->child->prev, (struct lyd_node_inner*)tree1->next, LYD_DUP_WITH_PARENTS));
     lyd_free_all(tree1);
 
diff --git a/tests/utests/data/test_types.c b/tests/utests/data/test_types.c
index 47dd5e4..39268e1 100644
--- a/tests/utests/data/test_types.c
+++ b/tests/utests/data/test_types.c
@@ -150,20 +150,32 @@
 #   define logbuf_assert(str)
 #endif
 
+#define TEST_DATA(DATA, RETCODE, ERRMSG) \
+    logbuf_clean(); \
+    if (!in) { \
+        assert_int_equal(LY_SUCCESS, ly_in_new_memory(DATA, &in)); \
+    } else { \
+        ly_in_memory(in, DATA); \
+    } \
+    assert_int_equal(RETCODE, lyd_parse_data(s->ctx, in, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree)); \
+    if (!RETCODE) { \
+        logbuf_assert(ERRMSG); \
+    }
+
+
 static void
 test_int(void **state)
 {
     struct state_s *s = (struct state_s*)(*state);
     s->func = test_int;
 
+    struct ly_in *in = NULL;
     struct lyd_node *tree;
     struct lyd_node_term *leaf;
     struct lyd_value value = {0};
 
-    const char *data = "<int8 xmlns=\"urn:tests:types\">\n 15 \t\n  </int8>";
-
     /* valid data */
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<int8 xmlns=\"urn:tests:types\">\n 15 \t\n  </int8>", LY_SUCCESS, "");
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("int8", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
@@ -179,31 +191,16 @@
     lyd_free_all(tree);
 
     /* invalid range */
-    data = "<int8 xmlns=\"urn:tests:types\">1</int8>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Value \"1\" does not satisfy the range constraint. /types:int8");
-
-    data = "<int16 xmlns=\"urn:tests:types\">100</int16>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Value \"100\" does not satisfy the range constraint. /types:int16");
+    TEST_DATA("<int8 xmlns=\"urn:tests:types\">1</int8>", LY_EVALID, "Value \"1\" does not satisfy the range constraint. /types:int8");
+    TEST_DATA("<int16 xmlns=\"urn:tests:types\">100</int16>", LY_EVALID, "Value \"100\" does not satisfy the range constraint. /types:int16");
 
     /* invalid value */
-    data = "<int32 xmlns=\"urn:tests:types\">0x01</int32>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid int32 value \"0x01\". /types:int32");
+    TEST_DATA("<int32 xmlns=\"urn:tests:types\">0x01</int32>", LY_EVALID, "Invalid int32 value \"0x01\". /types:int32");
+    TEST_DATA("<int64 xmlns=\"urn:tests:types\"></int64>", LY_EVALID, "Invalid empty int64 value. /types:int64");
+    TEST_DATA("<int64 xmlns=\"urn:tests:types\">   </int64>", LY_EVALID, "Invalid empty int64 value. /types:int64");
+    TEST_DATA("<int64 xmlns=\"urn:tests:types\">-10  xxx</int64>", LY_EVALID, "Invalid int64 value \"-10  xxx\". /types:int64");
 
-    data = "<int64 xmlns=\"urn:tests:types\"></int64>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid empty int64 value. /types:int64");
-
-    data = "<int64 xmlns=\"urn:tests:types\">   </int64>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid empty int64 value. /types:int64");
-
-    data = "<int64 xmlns=\"urn:tests:types\">-10  xxx</int64>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid int64 value \"-10  xxx\". /types:int64");
-
+    ly_in_free(in, 0);
     s->func = NULL;
 }
 
@@ -213,14 +210,13 @@
     struct state_s *s = (struct state_s*)(*state);
     s->func = test_uint;
 
+    struct ly_in *in = NULL;
     struct lyd_node *tree;
     struct lyd_node_term *leaf;
     struct lyd_value value = {0};
 
-    const char *data = "<uint8 xmlns=\"urn:tests:types\">\n 150 \t\n  </uint8>";
-
     /* valid data */
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<uint8 xmlns=\"urn:tests:types\">\n 150 \t\n  </uint8>", LY_SUCCESS, "");
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("uint8", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
@@ -236,31 +232,16 @@
     lyd_free_all(tree);
 
     /* invalid range */
-    data = "<uint8 xmlns=\"urn:tests:types\">\n 15 \t\n  </uint8>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Value \"15\" does not satisfy the range constraint. /types:uint8");
-
-    data = "<uint16 xmlns=\"urn:tests:types\">\n 1500 \t\n  </uint16>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Value \"1500\" does not satisfy the range constraint. /types:uint16");
+    TEST_DATA("<uint8 xmlns=\"urn:tests:types\">\n 15 \t\n  </uint8>", LY_EVALID, "Value \"15\" does not satisfy the range constraint. /types:uint8");
+    TEST_DATA("<uint16 xmlns=\"urn:tests:types\">\n 1500 \t\n  </uint16>", LY_EVALID, "Value \"1500\" does not satisfy the range constraint. /types:uint16");
 
     /* invalid value */
-    data = "<uint32 xmlns=\"urn:tests:types\">-10</uint32>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Value \"-10\" is out of uint32's min/max bounds. /types:uint32");
+    TEST_DATA("<uint32 xmlns=\"urn:tests:types\">-10</uint32>", LY_EVALID, "Value \"-10\" is out of uint32's min/max bounds. /types:uint32");
+    TEST_DATA("<uint64 xmlns=\"urn:tests:types\"/>", LY_EVALID, "Invalid empty uint64 value. /types:uint64");
+    TEST_DATA("<uint64 xmlns=\"urn:tests:types\">   </uint64>", LY_EVALID, "Invalid empty uint64 value. /types:uint64");
+    TEST_DATA("<uint64 xmlns=\"urn:tests:types\">10  xxx</uint64>", LY_EVALID, "Invalid uint64 value \"10  xxx\". /types:uint64");
 
-    data = "<uint64 xmlns=\"urn:tests:types\"/>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid empty uint64 value. /types:uint64");
-
-    data = "<uint64 xmlns=\"urn:tests:types\">   </uint64>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid empty uint64 value. /types:uint64");
-
-    data = "<uint64 xmlns=\"urn:tests:types\">10  xxx</uint64>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid uint64 value \"10  xxx\". /types:uint64");
-
+    ly_in_free(in, 0);
     s->func = NULL;
 }
 
@@ -270,14 +251,13 @@
     struct state_s *s = (struct state_s*)(*state);
     s->func = test_dec64;
 
+    struct ly_in *in = NULL;
     struct lyd_node *tree;
     struct lyd_node_term *leaf;
     struct lyd_value value = {0};
 
-    const char *data = "<dec64 xmlns=\"urn:tests:types\">\n +8 \t\n  </dec64>";
-
     /* valid data */
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<dec64 xmlns=\"urn:tests:types\">\n +8 \t\n  </dec64>", LY_SUCCESS, "");
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("dec64", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
@@ -292,8 +272,7 @@
     memset(&value, 0, sizeof value);
     lyd_free_all(tree);
 
-    data = "<dec64 xmlns=\"urn:tests:types\">8.00</dec64>";
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<dec64 xmlns=\"urn:tests:types\">8.00</dec64>", LY_SUCCESS, "");
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("dec64", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
@@ -301,8 +280,7 @@
     assert_int_equal(80, leaf->value.dec64);
     lyd_free_all(tree);
 
-    data = "<dec64-norestr xmlns=\"urn:tests:types\">-9.223372036854775808</dec64-norestr>";
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<dec64-norestr xmlns=\"urn:tests:types\">-9.223372036854775808</dec64-norestr>", LY_SUCCESS, "");
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("dec64-norestr", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
@@ -310,8 +288,7 @@
     assert_int_equal(INT64_C(-9223372036854775807) - INT64_C(1), leaf->value.dec64);
     lyd_free_all(tree);
 
-    data = "<dec64-norestr xmlns=\"urn:tests:types\">9.223372036854775807</dec64-norestr>";
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<dec64-norestr xmlns=\"urn:tests:types\">9.223372036854775807</dec64-norestr>", LY_SUCCESS, "");
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("dec64-norestr", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
@@ -320,35 +297,17 @@
     lyd_free_all(tree);
 
     /* invalid range */
-    data = "<dec64 xmlns=\"urn:tests:types\">\n 15 \t\n  </dec64>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Value \"15.0\" does not satisfy the range constraint. /types:dec64");
-
-    data = "<dec64 xmlns=\"urn:tests:types\">\n 0 \t\n  </dec64>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Value \"0.0\" does not satisfy the range constraint. /types:dec64");
+    TEST_DATA("<dec64 xmlns=\"urn:tests:types\">\n 15 \t\n  </dec64>", LY_EVALID, "Value \"15.0\" does not satisfy the range constraint. /types:dec64");
+    TEST_DATA("<dec64 xmlns=\"urn:tests:types\">\n 0 \t\n  </dec64>", LY_EVALID, "Value \"0.0\" does not satisfy the range constraint. /types:dec64");
 
     /* invalid value */
-    data = "<dec64 xmlns=\"urn:tests:types\">xxx</dec64>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid 1. character of decimal64 value \"xxx\". /types:dec64");
+    TEST_DATA("<dec64 xmlns=\"urn:tests:types\">xxx</dec64>", LY_EVALID, "Invalid 1. character of decimal64 value \"xxx\". /types:dec64");
+    TEST_DATA("<dec64 xmlns=\"urn:tests:types\"/>", LY_EVALID, "Invalid empty decimal64 value. /types:dec64");
+    TEST_DATA("<dec64 xmlns=\"urn:tests:types\">   </dec64>", LY_EVALID, "Invalid empty decimal64 value. /types:dec64");
+    TEST_DATA("<dec64 xmlns=\"urn:tests:types\">8.5  xxx</dec64>", LY_EVALID, "Invalid 6. character of decimal64 value \"8.5  xxx\". /types:dec64");
+    TEST_DATA("<dec64 xmlns=\"urn:tests:types\">8.55  xxx</dec64>", LY_EVALID, "Value \"8.55\" of decimal64 type exceeds defined number (1) of fraction digits. /types:dec64");
 
-    data = "<dec64 xmlns=\"urn:tests:types\"/>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid empty decimal64 value. /types:dec64");
-
-    data = "<dec64 xmlns=\"urn:tests:types\">   </dec64>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid empty decimal64 value. /types:dec64");
-
-    data = "<dec64 xmlns=\"urn:tests:types\">8.5  xxx</dec64>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid 6. character of decimal64 value \"8.5  xxx\". /types:dec64");
-
-    data = "<dec64 xmlns=\"urn:tests:types\">8.55  xxx</dec64>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Value \"8.55\" of decimal64 type exceeds defined number (1) of fraction digits. /types:dec64");
-
+    ly_in_free(in, 0);
     s->func = NULL;
 }
 
@@ -358,13 +317,12 @@
     struct state_s *s = (struct state_s*)(*state);
     s->func = test_string;
 
+    struct ly_in *in = NULL;
     struct lyd_node *tree;
     struct lyd_node_term *leaf;
 
-    const char *data = "<str xmlns=\"urn:tests:types\">teststring</str>";
-
     /* valid data */
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<str xmlns=\"urn:tests:types\">teststring</str>", LY_SUCCESS, "");
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("str", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
@@ -372,37 +330,24 @@
     lyd_free_all(tree);
 
     /* multibyte characters (€ encodes as 3-byte UTF8 character, length restriction is 2-5) */
-    data = "<str-utf8 xmlns=\"urn:tests:types\">€€</str-utf8>";
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<str-utf8 xmlns=\"urn:tests:types\">€€</str-utf8>", LY_SUCCESS, "");
     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.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, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Length \"1\" does not satisfy the length constraint. /types:str-utf8");
-    data = "<str-utf8 xmlns=\"urn:tests:types\">€€€€€€</str-utf8>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Length \"6\" does not satisfy the length constraint. /types:str-utf8");
-    data = "<str-utf8 xmlns=\"urn:tests:types\">€€x</str-utf8>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("String \"€€x\" does not conform to the pattern \"€*\". /types:str-utf8");
+    TEST_DATA("<str-utf8 xmlns=\"urn:tests:types\">€</str-utf8>", LY_EVALID, "Length \"1\" does not satisfy the length constraint. /types:str-utf8");
+    TEST_DATA("<str-utf8 xmlns=\"urn:tests:types\">€€€€€€</str-utf8>", LY_EVALID, "Length \"6\" does not satisfy the length constraint. /types:str-utf8");
+    TEST_DATA("<str-utf8 xmlns=\"urn:tests:types\">€€x</str-utf8>", LY_EVALID, "String \"€€x\" does not conform to the pattern \"€*\". /types:str-utf8");
 
     /* invalid length */
-    data = "<str xmlns=\"urn:tests:types\">short</str>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Length \"5\" does not satisfy the length constraint. /types:str");
-
-    data = "<str xmlns=\"urn:tests:types\">tooooo long</str>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Length \"11\" does not satisfy the length constraint. /types:str");
+    TEST_DATA("<str xmlns=\"urn:tests:types\">short</str>", LY_EVALID, "Length \"5\" does not satisfy the length constraint. /types:str");
+    TEST_DATA("<str xmlns=\"urn:tests:types\">tooooo long</str>", LY_EVALID, "Length \"11\" does not satisfy the length constraint. /types:str");
 
     /* invalid pattern */
-    data = "<str xmlns=\"urn:tests:types\">string15</str>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("String \"string15\" does not conform to the pattern \"[a-z ]*\". /types:str");
+    TEST_DATA("<str xmlns=\"urn:tests:types\">string15</str>", LY_EVALID, "String \"string15\" does not conform to the pattern \"[a-z ]*\". /types:str");
 
+    ly_in_free(in, 0);
     s->func = NULL;
 }
 
@@ -412,14 +357,13 @@
     struct state_s *s = (struct state_s*)(*state);
     s->func = test_bits;
 
+    struct ly_in *in = NULL;
     struct lyd_node *tree;
     struct lyd_node_term *leaf;
     struct lyd_value value = {0};
 
-    const char *data = "<bits xmlns=\"urn:tests:types\">\n two    \t\nzero\n  </bits>";
-
     /* valid data */
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<bits xmlns=\"urn:tests:types\">\n two    \t\nzero\n  </bits>", LY_SUCCESS, "");
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("bits", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
@@ -438,8 +382,7 @@
     memset(&value, 0, sizeof value);
     lyd_free_all(tree);
 
-    data = "<bits xmlns=\"urn:tests:types\">zero  two</bits>";
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<bits xmlns=\"urn:tests:types\">zero  two</bits>", LY_SUCCESS, "");
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("bits", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
@@ -447,13 +390,11 @@
     lyd_free_all(tree);
 
     /* disabled feature */
-    data = "<bits xmlns=\"urn:tests:types\"> \t one \n\t </bits>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Bit \"one\" is disabled by its 1. if-feature condition. /types:bits");
+    TEST_DATA("<bits xmlns=\"urn:tests:types\"> \t one \n\t </bits>", LY_EVALID, "Bit \"one\" is disabled by its 1. if-feature condition. /types:bits");
 
     /* enable that feature */
     assert_int_equal(LY_SUCCESS, lys_feature_enable(ly_ctx_get_module(s->ctx, "types", NULL), "f"));
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<bits xmlns=\"urn:tests:types\"> \t one \n\t </bits>", LY_SUCCESS, "");
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("bits", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
@@ -470,15 +411,12 @@
     lyd_free_all(tree);
 
     /* multiple instances of the bit */
-    data = "<bits xmlns=\"urn:tests:types\">one zero one</bits>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Bit \"one\" used multiple times. /types:bits");
+    TEST_DATA("<bits xmlns=\"urn:tests:types\">one zero one</bits>", LY_EVALID, "Bit \"one\" used multiple times. /types:bits");
 
     /* invalid bit value */
-    data = "<bits xmlns=\"urn:tests:types\">one xero one</bits>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid bit value \"xero\". /types:bits");
+    TEST_DATA("<bits xmlns=\"urn:tests:types\">one xero one</bits>", LY_EVALID, "Invalid bit value \"xero\". /types:bits");
 
+    ly_in_free(in, 0);
     s->func = NULL;
 }
 
@@ -488,14 +426,13 @@
     struct state_s *s = (struct state_s*)(*state);
     s->func = test_enums;
 
+    struct ly_in *in = NULL;
     struct lyd_node *tree;
     struct lyd_node_term *leaf;
     struct lyd_value value = {0};
 
-    const char *data = "<enums xmlns=\"urn:tests:types\">white</enums>";
-
     /* valid data */
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<enums xmlns=\"urn:tests:types\">white</enums>", LY_SUCCESS, "");
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("enums", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
@@ -510,13 +447,12 @@
     lyd_free_all(tree);
 
     /* disabled feature */
-    data = "<enums xmlns=\"urn:tests:types\">yellow</enums>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Enumeration \"yellow\" is disabled by its 1. if-feature condition. /types:enums");
+    TEST_DATA("<enums xmlns=\"urn:tests:types\">yellow</enums>", LY_EVALID,
+              "Enumeration \"yellow\" is disabled by its 1. if-feature condition. /types:enums");
 
     /* enable that feature */
     assert_int_equal(LY_SUCCESS, lys_feature_enable(ly_ctx_get_module(s->ctx, "types", NULL), "f"));
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<enums xmlns=\"urn:tests:types\">yellow</enums>", LY_SUCCESS, "");
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("enums", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
@@ -524,18 +460,13 @@
     lyd_free_all(tree);
 
     /* leading/trailing whitespaces are not valid */
-    data = "<enums xmlns=\"urn:tests:types\"> white</enums>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid enumeration value \" white\". /types:enums");
-    data = "<enums xmlns=\"urn:tests:types\">white\n</enums>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid enumeration value \"white\n\". /types:enums");
+    TEST_DATA("<enums xmlns=\"urn:tests:types\"> white</enums>", LY_EVALID, "Invalid enumeration value \" white\". /types:enums");
+    TEST_DATA("<enums xmlns=\"urn:tests:types\">white\n</enums>", LY_EVALID, "Invalid enumeration value \"white\n\". /types:enums");
 
     /* invalid enumeration value */
-    data = "<enums xmlns=\"urn:tests:types\">black</enums>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid enumeration value \"black\". /types:enums");
+    TEST_DATA("<enums xmlns=\"urn:tests:types\">black</enums>", LY_EVALID, "Invalid enumeration value \"black\". /types:enums");
 
+    ly_in_free(in, 0);
     s->func = NULL;
 }
 
@@ -545,15 +476,13 @@
     struct state_s *s = (struct state_s*)(*state);
     s->func = test_binary;
 
+    struct ly_in *in = NULL;
     struct lyd_node *tree;
     struct lyd_node_term *leaf;
     struct lyd_value value = {0};
 
-    const char *data = "<binary xmlns=\"urn:tests:types\">\n   aGVs\nbG8=  \t\n  </binary>"
-                       "<binary-norestr xmlns=\"urn:tests:types\">TQ==</binary-norestr>";
-
     /* valid data (hello) */
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<binary xmlns=\"urn:tests:types\">\n   aGVs\nbG8=  \t\n  </binary><binary-norestr xmlns=\"urn:tests:types\">TQ==</binary-norestr>", LY_SUCCESS, "");
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("binary", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
@@ -572,22 +501,19 @@
     lyd_free_all(tree);
 
     /* no data */
-    data = "<binary-norestr xmlns=\"urn:tests:types\">\n    \t\n  </binary-norestr>";
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<binary-norestr xmlns=\"urn:tests:types\">\n    \t\n  </binary-norestr>", LY_SUCCESS, "");
     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.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, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<binary-norestr xmlns=\"urn:tests:types\"></binary-norestr>", LY_SUCCESS, "");
     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.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, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<binary-norestr xmlns=\"urn:tests:types\"/>", LY_SUCCESS, "");
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("binary-norestr", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
@@ -595,26 +521,24 @@
     lyd_free_all(tree);
 
     /* invalid base64 character */
-    data = "<binary-norestr xmlns=\"urn:tests:types\">a@bcd=</binary-norestr>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid Base64 character (@). /types:binary-norestr");
+    TEST_DATA("<binary-norestr xmlns=\"urn:tests:types\">a@bcd=</binary-norestr>", LY_EVALID,
+              "Invalid Base64 character (@). /types:binary-norestr");
 
     /* missing data */
-    data = "<binary-norestr xmlns=\"urn:tests:types\">aGVsbG8</binary-norestr>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Base64 encoded value length must be divisible by 4. /types:binary-norestr");
-    data = "<binary-norestr xmlns=\"urn:tests:types\">VsbG8=</binary-norestr>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Base64 encoded value length must be divisible by 4. /types:binary-norestr");
+    TEST_DATA("<binary-norestr xmlns=\"urn:tests:types\">aGVsbG8</binary-norestr>", LY_EVALID,
+              "Base64 encoded value length must be divisible by 4. /types:binary-norestr");
+    TEST_DATA("<binary-norestr xmlns=\"urn:tests:types\">VsbG8=</binary-norestr>", LY_EVALID,
+              "Base64 encoded value length must be divisible by 4. /types:binary-norestr");
 
     /* invalid binary length */
-    data = "<binary xmlns=\"urn:tests:types\">aGVsbG93b3JsZA==</binary>"; /* helloworld */
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("This base64 value must be of length 5. /types:binary");
-    data = "<binary xmlns=\"urn:tests:types\">TQ==</binary>"; /* M */
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("This base64 value must be of length 5. /types:binary");
+    /* helloworld */
+    TEST_DATA("<binary xmlns=\"urn:tests:types\">aGVsbG93b3JsZA==</binary>", LY_EVALID,
+              "This base64 value must be of length 5. /types:binary");
+    /* M */
+    TEST_DATA("<binary xmlns=\"urn:tests:types\">TQ==</binary>", LY_EVALID,
+              "This base64 value must be of length 5. /types:binary");
 
+    ly_in_free(in, 0);
     s->func = NULL;
 }
 
@@ -624,13 +548,12 @@
     struct state_s *s = (struct state_s*)(*state);
     s->func = test_boolean;
 
+    struct ly_in *in = NULL;
     struct lyd_node *tree;
     struct lyd_node_term *leaf;
 
-    const char *data = "<bool xmlns=\"urn:tests:types\">true</bool>";
-
     /* valid data */
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<bool xmlns=\"urn:tests:types\">true</bool>", LY_SUCCESS, "");
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("bool", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
@@ -638,8 +561,7 @@
     assert_int_equal(1, leaf->value.boolean);
     lyd_free_all(tree);
 
-    data = "<bool xmlns=\"urn:tests:types\">false</bool>";
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<bool xmlns=\"urn:tests:types\">false</bool>", LY_SUCCESS, "");
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("bool", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
@@ -647,8 +569,7 @@
     assert_int_equal(0, leaf->value.boolean);
     lyd_free_all(tree);
 
-    data = "<tbool xmlns=\"urn:tests:types\">false</tbool>";
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<tbool xmlns=\"urn:tests:types\">false</tbool>", LY_SUCCESS, "");
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("tbool", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
@@ -657,14 +578,10 @@
     lyd_free_all(tree);
 
     /* invalid value */
-    data = "<bool xmlns=\"urn:tests:types\">unsure</bool>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid boolean value \"unsure\". /types:bool");
+    TEST_DATA("<bool xmlns=\"urn:tests:types\">unsure</bool>", LY_EVALID, "Invalid boolean value \"unsure\". /types:bool");
+    TEST_DATA("<bool xmlns=\"urn:tests:types\"> true</bool>", LY_EVALID, "Invalid boolean value \" true\". /types:bool");
 
-    data = "<bool xmlns=\"urn:tests:types\"> true</bool>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid boolean value \" true\". /types:bool");
-
+    ly_in_free(in, 0);
     s->func = NULL;
 }
 
@@ -674,29 +591,27 @@
     struct state_s *s = (struct state_s*)(*state);
     s->func = test_empty;
 
+    struct ly_in *in = NULL;
     struct lyd_node *tree;
     struct lyd_node_term *leaf;
 
-    const char *data = "<empty xmlns=\"urn:tests:types\"></empty>";
-
     /* valid data */
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+
+    TEST_DATA("<empty xmlns=\"urn:tests:types\"></empty>", LY_SUCCESS, "");
     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.canonical_cache);
     lyd_free_all(tree);
 
-    data = "<empty xmlns=\"urn:tests:types\"/>";
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<empty xmlns=\"urn:tests:types\"/>", LY_SUCCESS, "");
     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.canonical_cache);
     lyd_free_all(tree);
 
-    data = "<tempty xmlns=\"urn:tests:types\"/>";
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<tempty xmlns=\"urn:tests:types\"/>", LY_SUCCESS, "");
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("tempty", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
@@ -704,14 +619,10 @@
     lyd_free_all(tree);
 
     /* invalid value */
-    data = "<empty xmlns=\"urn:tests:types\">x</empty>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid empty value \"x\". /types:empty");
+    TEST_DATA("<empty xmlns=\"urn:tests:types\">x</empty>", LY_EVALID, "Invalid empty value \"x\". /types:empty");
+    TEST_DATA("<empty xmlns=\"urn:tests:types\"> </empty>", LY_EVALID, "Invalid empty value \" \". /types:empty");
 
-    data = "<empty xmlns=\"urn:tests:types\"> </empty>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid empty value \" \". /types:empty");
-
+    ly_in_free(in, 0);
     s->func = NULL;
 }
 
@@ -741,14 +652,13 @@
     struct state_s *s = (struct state_s*)(*state);
     s->func = test_identityref;
 
+    struct ly_in *in = NULL;
     struct lyd_node *tree;
     struct lyd_node_term *leaf;
     struct lyd_value value = {0};
 
-    const char *data = "<ident xmlns=\"urn:tests:types\">gigabit-ethernet</ident>";
-
     /* valid data */
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<ident xmlns=\"urn:tests:types\">gigabit-ethernet</ident>", LY_SUCCESS, "");
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("ident", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
@@ -763,8 +673,7 @@
     value.realtype->plugin->free(s->ctx, &value);
     lyd_free_all(tree);
 
-    data = "<ident xmlns=\"urn:tests:types\" xmlns:x=\"urn:tests:defs\">x:fast-ethernet</ident>";
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<ident xmlns=\"urn:tests:types\" xmlns:x=\"urn:tests:defs\">x:fast-ethernet</ident>", LY_SUCCESS, "");
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("ident", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
@@ -773,22 +682,16 @@
     lyd_free_all(tree);
 
     /* invalid value */
-    data = "<ident xmlns=\"urn:tests:types\">fast-ethernet</ident>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid identityref \"fast-ethernet\" value - identity not found. /types:ident");
+    TEST_DATA("<ident xmlns=\"urn:tests:types\">fast-ethernet</ident>", LY_EVALID,
+              "Invalid identityref \"fast-ethernet\" value - identity not found. /types:ident");
+    TEST_DATA("<ident xmlns=\"urn:tests:types\" xmlns:x=\"urn:tests:defs\">x:slow-ethernet</ident>", LY_EVALID,
+              "Invalid identityref \"x:slow-ethernet\" value - identity not found. /types:ident");
+    TEST_DATA("<ident xmlns=\"urn:tests:types\" xmlns:x=\"urn:tests:defs\">x:crypto-alg</ident>", LY_EVALID,
+              "Invalid identityref \"x:crypto-alg\" value - identity not accepted by the type specification. /types:ident");
+    TEST_DATA("<ident xmlns=\"urn:tests:types\" xmlns:x=\"urn:tests:unknown\">x:fast-ethernet</ident>", LY_EVALID,
+              "Invalid identityref \"x:fast-ethernet\" value - unable to map prefix to YANG schema. /types:ident");
 
-    data = "<ident xmlns=\"urn:tests:types\" xmlns:x=\"urn:tests:defs\">x:slow-ethernet</ident>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid identityref \"x:slow-ethernet\" value - identity not found. /types:ident");
-
-    data = "<ident xmlns=\"urn:tests:types\" xmlns:x=\"urn:tests:defs\">x:crypto-alg</ident>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid identityref \"x:crypto-alg\" value - identity not accepted by the type specification. /types:ident");
-
-    data = "<ident xmlns=\"urn:tests:types\" xmlns:x=\"urn:tests:unknown\">x:fast-ethernet</ident>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid identityref \"x:fast-ethernet\" value - unable to map prefix to YANG schema. /types:ident");
-
+    ly_in_free(in, 0);
     s->func = NULL;
 }
 
@@ -809,15 +712,15 @@
     struct state_s *s = (struct state_s*)(*state);
     s->func = test_instanceid;
 
+    struct ly_in *in = NULL;
     struct lyd_node *tree;
     const struct lyd_node_term *leaf;
     struct lyd_value value = {0};
-
-    const char *data = "<cont xmlns=\"urn:tests:types\"><leaftarget/></cont>"
-            "<xdf:inst xmlns:xdf=\"urn:tests:types\">/xdf:cont/xdf:leaftarget</xdf:inst>";
+    const char *data;
 
     /* valid data */
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<cont xmlns=\"urn:tests:types\"><leaftarget/></cont>"
+              "<xdf:inst xmlns:xdf=\"urn:tests:types\">/xdf:cont/xdf:leaftarget</xdf:inst>", LY_SUCCESS, "");
     tree = tree->prev;
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("inst", tree->schema->name);
@@ -840,9 +743,8 @@
     value.realtype->plugin->free(s->ctx, &value);
     lyd_free_all(tree);
 
-    data = "<list xmlns=\"urn:tests:types\"><id>a</id></list><list xmlns=\"urn:tests:types\"><id>b</id></list>"
-           "<xdf:inst xmlns:xdf=\"urn:tests:types\">/xdf:list[xdf:id='b']/xdf:id</xdf:inst>";
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<list xmlns=\"urn:tests:types\"><id>a</id></list><list xmlns=\"urn:tests:types\"><id>b</id></list>"
+              "<xdf:inst xmlns:xdf=\"urn:tests:types\">/xdf:list[xdf:id='b']/xdf:id</xdf:inst>", LY_SUCCESS, "");
     tree = tree->prev->prev;
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("inst", tree->schema->name);
@@ -850,9 +752,8 @@
     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>"
-           "<xdf:inst xmlns:xdf=\"urn:tests:types\">/xdf:leaflisttarget[.='1']</xdf:inst>";
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<leaflisttarget xmlns=\"urn:tests:types\">1</leaflisttarget><leaflisttarget xmlns=\"urn:tests:types\">2</leaflisttarget>"
+              "<xdf:inst xmlns:xdf=\"urn:tests:types\">/xdf:leaflisttarget[.='1']</xdf:inst>", LY_SUCCESS, "");
     tree = tree->prev->prev;
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("inst", tree->schema->name);
@@ -860,11 +761,10 @@
     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>"
+    TEST_DATA("<list_inst xmlns=\"urn:tests:types\"><id xmlns:b=\"urn:tests:types\">/b:leaflisttarget[.='a']</id><value>x</value></list_inst>"
            "<list_inst xmlns=\"urn:tests:types\"><id xmlns:b=\"urn:tests:types\">/b:leaflisttarget[.='b']</id><value>y</value></list_inst>"
            "<leaflisttarget xmlns=\"urn:tests:types\">a</leaflisttarget><leaflisttarget xmlns=\"urn:tests:types\">b</leaflisttarget>"
-           "<a:inst xmlns:a=\"urn:tests:types\">/a:list_inst[a:id=\"/a:leaflisttarget[.='b']\"]/a:value</a:inst>";
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+           "<a:inst xmlns:a=\"urn:tests:types\">/a:list_inst[a:id=\"/a:leaflisttarget[.='b']\"]/a:value</a:inst>", LY_SUCCESS, "");
     tree = tree->prev->prev;
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("inst", tree->schema->name);
@@ -890,9 +790,8 @@
     value.realtype->plugin->free(s->ctx, &value);
     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>"
-           "<xdf:inst xmlns:xdf=\"urn:tests:types\">/xdf:list[xdf:id='b']/xdf:value</xdf:inst>";
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<list xmlns=\"urn:tests:types\"><id>a</id></list><list xmlns=\"urn:tests:types\"><id>b</id><value>x</value></list>"
+              "<xdf:inst xmlns:xdf=\"urn:tests:types\">/xdf:list[xdf:id='b']/xdf:value</xdf:inst>", LY_SUCCESS, "");
     tree = tree->prev->prev;
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("inst", tree->schema->name);
@@ -900,11 +799,10 @@
     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>"
-           "<list_inst xmlns=\"urn:tests:types\"><id xmlns:b=\"urn:tests:types\">/b:leaflisttarget[.='b']</id><value>y</value></list_inst>"
-           "<leaflisttarget xmlns=\"urn:tests:types\">a</leaflisttarget><leaflisttarget xmlns=\"urn:tests:types\">b</leaflisttarget>"
-           "<a:inst xmlns:a=\"urn:tests:types\">/a:list_inst[a:id=\"/a:leaflisttarget[.='a']\"]/a:value</a:inst>";
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<list_inst xmlns=\"urn:tests:types\"><id xmlns:b=\"urn:tests:types\">/b:leaflisttarget[.='a']</id><value>x</value></list_inst>"
+              "<list_inst xmlns=\"urn:tests:types\"><id xmlns:b=\"urn:tests:types\">/b:leaflisttarget[.='b']</id><value>y</value></list_inst>"
+              "<leaflisttarget xmlns=\"urn:tests:types\">a</leaflisttarget><leaflisttarget xmlns=\"urn:tests:types\">b</leaflisttarget>"
+              "<a:inst xmlns:a=\"urn:tests:types\">/a:list_inst[a:id=\"/a:leaflisttarget[.='a']\"]/a:value</a:inst>", LY_SUCCESS, "");
     tree = tree->prev->prev;
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("inst", tree->schema->name);
@@ -912,10 +810,9 @@
     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>"
-           "<list_ident xmlns=\"urn:tests:types\"><id xmlns:dfs=\"urn:tests:defs\">dfs:fast-ethernet</id><value>y</value></list_ident>"
-           "<a:inst xmlns:a=\"urn:tests:types\" xmlns:d=\"urn:tests:defs\">/a:list_ident[a:id='d:fast-ethernet']/a:value</a:inst>";
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<list_ident xmlns=\"urn:tests:types\"><id xmlns:dfs=\"urn:tests:defs\">dfs:ethernet</id><value>x</value></list_ident>"
+              "<list_ident xmlns=\"urn:tests:types\"><id xmlns:dfs=\"urn:tests:defs\">dfs:fast-ethernet</id><value>y</value></list_ident>"
+              "<a:inst xmlns:a=\"urn:tests:types\" xmlns:d=\"urn:tests:defs\">/a:list_ident[a:id='d:fast-ethernet']/a:value</a:inst>", LY_SUCCESS, "");
     tree = tree->prev->prev;
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("inst", tree->schema->name);
@@ -923,10 +820,9 @@
     assert_null(leaf->value.canonical_cache);
     lyd_free_all(tree);
 
-    data = "<list2 xmlns=\"urn:tests:types\"><id>types:xxx</id><value>x</value></list2>"
-           "<list2 xmlns=\"urn:tests:types\"><id>a:xxx</id><value>y</value></list2>"
-           "<a:inst xmlns:a=\"urn:tests:types\">/a:list2[a:id='a:xxx'][a:value='y']/a:value</a:inst>";
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<list2 xmlns=\"urn:tests:types\"><id>types:xxx</id><value>x</value></list2>"
+              "<list2 xmlns=\"urn:tests:types\"><id>a:xxx</id><value>y</value></list2>"
+              "<a:inst xmlns:a=\"urn:tests:types\">/a:list2[a:id='a:xxx'][a:value='y']/a:value</a:inst>", LY_SUCCESS, "");
     tree = tree->prev->prev;
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("inst", tree->schema->name);
@@ -934,10 +830,9 @@
     assert_null(leaf->value.canonical_cache);
     lyd_free_all(tree);
 
-    data = "<list xmlns=\"urn:tests:types\"><id>types:xxx</id><value>x</value></list>"
-           "<list xmlns=\"urn:tests:types\"><id>a:xxx</id><value>y</value></list>"
-           "<a:inst xmlns:a=\"urn:tests:types\">/a:list[a:id='a:xxx']/a:value</a:inst>";
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<list xmlns=\"urn:tests:types\"><id>types:xxx</id><value>x</value></list>"
+              "<list xmlns=\"urn:tests:types\"><id>a:xxx</id><value>y</value></list>"
+              "<a:inst xmlns:a=\"urn:tests:types\">/a:list[a:id='a:xxx']/a:value</a:inst>", LY_SUCCESS, "");
     tree = tree->prev->prev;
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("inst", tree->schema->name);
@@ -945,11 +840,10 @@
     assert_null(leaf->value.canonical_cache);
     lyd_free_all(tree);
 
-    data = "<list2 xmlns=\"urn:tests:types\"><id>a</id><value>a</value></list2>"
-           "<list2 xmlns=\"urn:tests:types\"><id>c</id><value>b</value></list2>"
-           "<list2 xmlns=\"urn:tests:types\"><id>a</id><value>b</value></list2>"
-           "<a:inst xmlns:a=\"urn:tests:types\">/a:list2[a:id='a'][a:value='b']/a:id</a:inst>";
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<list2 xmlns=\"urn:tests:types\"><id>a</id><value>a</value></list2>"
+              "<list2 xmlns=\"urn:tests:types\"><id>c</id><value>b</value></list2>"
+              "<list2 xmlns=\"urn:tests:types\"><id>a</id><value>b</value></list2>"
+              "<a:inst xmlns:a=\"urn:tests:types\">/a:list2[a:id='a'][a:value='b']/a:id</a:inst>", LY_SUCCESS, "");
     leaf = (const struct lyd_node_term*)tree->prev->prev;
     assert_int_equal(LYS_LEAF, leaf->schema->nodetype);
     assert_string_equal("inst", leaf->schema->name);
@@ -960,141 +854,94 @@
     lyd_free_all(tree);
 
     /* invalid value */
-    data = "<list xmlns=\"urn:tests:types\"><id>a</id></list><list xmlns=\"urn:tests:types\"><id>b</id><value>x</value></list>"
-           "<xdf:inst xmlns:xdf=\"urn:tests:types\">/xdf:list[2]/xdf:value</xdf:inst>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid instance-identifier \"/xdf:list[2]/xdf:value\" value - semantic error. /types:inst");
+    TEST_DATA("<list xmlns=\"urn:tests:types\"><id>a</id></list><list xmlns=\"urn:tests:types\"><id>b</id><value>x</value></list>"
+              "<xdf:inst xmlns:xdf=\"urn:tests:types\">/xdf:list[2]/xdf:value</xdf:inst>", LY_EVALID,
+              "Invalid instance-identifier \"/xdf:list[2]/xdf:value\" value - semantic error. /types:inst");
+    TEST_DATA("<t:inst xmlns:t=\"urn:tests:types\">/t:cont/t:1leaftarget</t:inst>", LY_EVALID,
+              "Invalid instance-identifier \"/t:cont/t:1leaftarget\" value - syntax error. /types:inst");
+    TEST_DATA("<t:inst xmlns:t=\"urn:tests:types\">/t:cont:t:1leaftarget</t:inst>", LY_EVALID,
+              "Invalid instance-identifier \"/t:cont:t:1leaftarget\" value - syntax error. /types:inst");
+    TEST_DATA("<t:inst xmlns:t=\"urn:tests:types\">/t:cont/t:invalid/t:path</t:inst>", LY_EVALID,
+              "Invalid instance-identifier \"/t:cont/t:invalid/t:path\" value - semantic error. /types:inst");
+    TEST_DATA("<inst xmlns=\"urn:tests:types\" xmlns:t=\"urn:tests:invalid\">/t:cont/t:leaftarget</inst>", LY_EVALID,
+              "Invalid instance-identifier \"/t:cont/t:leaftarget\" value - semantic error. /types:inst");
+    TEST_DATA("<inst xmlns=\"urn:tests:types\">/cont/leaftarget</inst>", LY_EVALID,
+              "Invalid instance-identifier \"/cont/leaftarget\" value - syntax error. /types:inst");
 
-    data =  "<t:inst xmlns:t=\"urn:tests:types\">/t:cont/t:1leaftarget</t:inst>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid instance-identifier \"/t:cont/t:1leaftarget\" value - syntax error. /types:inst");
-
-    data =  "<t:inst xmlns:t=\"urn:tests:types\">/t:cont:t:1leaftarget</t:inst>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid instance-identifier \"/t:cont:t:1leaftarget\" value - syntax error. /types:inst");
-
-    data =  "<t:inst xmlns:t=\"urn:tests:types\">/t:cont/t:invalid/t:path</t:inst>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid instance-identifier \"/t:cont/t:invalid/t:path\" value - semantic error. /types:inst");
-
-    data =  "<inst xmlns=\"urn:tests:types\" xmlns:t=\"urn:tests:invalid\">/t:cont/t:leaftarget</inst>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid instance-identifier \"/t:cont/t:leaftarget\" value - semantic error. /types:inst");
-
-    data =  "<inst xmlns=\"urn:tests:types\">/cont/leaftarget</inst>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid instance-identifier \"/cont/leaftarget\" value - syntax error. /types:inst");
-
-    data =  "<cont xmlns=\"urn:tests:types\"/><t:inst xmlns:t=\"urn:tests:types\">/t:cont/t:leaftarget</t:inst>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
     /* instance-identifier is here in JSON format because it is already in internal representation without original prefixes */
-    logbuf_assert("Invalid instance-identifier \"/types:cont/leaftarget\" value - required instance not found. /types:inst");
+    TEST_DATA( "<cont xmlns=\"urn:tests:types\"/><t:inst xmlns:t=\"urn:tests:types\">/t:cont/t:leaftarget</t:inst>", LY_EVALID, "Invalid instance-identifier \"/types:cont/leaftarget\" value - required instance not found. /types:inst");
 
-    data =  "<t:inst xmlns:t=\"urn:tests:types\">/t:cont/t:leaftarget</t:inst>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
     /* instance-identifier is here in JSON format because it is already in internal representation without original prefixes */
-    logbuf_assert("Invalid instance-identifier \"/types:cont/leaftarget\" value - required instance not found. /types:inst");
+    TEST_DATA( "<t:inst xmlns:t=\"urn:tests:types\">/t:cont/t:leaftarget</t:inst>", LY_EVALID, "Invalid instance-identifier \"/types:cont/leaftarget\" value - required instance not found. /types:inst");
 
-    data =  "<leaflisttarget xmlns=\"urn:tests:types\">x</leaflisttarget><t:inst xmlns:t=\"urn:tests:types\">/t:leaflisttarget[1</t:inst>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid instance-identifier \"/t:leaflisttarget[1\" value - syntax error. /types:inst");
-
-    data =  "<cont xmlns=\"urn:tests:types\"/><t:inst xmlns:t=\"urn:tests:types\">/t:cont[1]</t:inst>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid instance-identifier \"/t:cont[1]\" value - semantic error. /types:inst");
-
-    data =  "<cont xmlns=\"urn:tests:types\"/><t:inst xmlns:t=\"urn:tests:types\">[1]</t:inst>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid instance-identifier \"[1]\" value - syntax error. /types:inst");
-
-    data =  "<cont xmlns=\"urn:tests:types\"><leaflisttarget>1</leaflisttarget></cont><t:inst xmlns:t=\"urn:tests:types\">/t:cont/t:leaflisttarget[id='1']</t:inst>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid instance-identifier \"/t:cont/t:leaflisttarget[id='1']\" value - syntax error. /types:inst");
-
-    data =  "<cont xmlns=\"urn:tests:types\"><leaflisttarget>1</leaflisttarget></cont>"
-        "<t:inst xmlns:t=\"urn:tests:types\">/t:cont/t:leaflisttarget[t:id='1']</t:inst>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid instance-identifier \"/t:cont/t:leaflisttarget[t:id='1']\" value - semantic error. /types:inst");
-
-    data =  "<cont xmlns=\"urn:tests:types\"><leaflisttarget>1</leaflisttarget><leaflisttarget>2</leaflisttarget></cont>"
-            "<t:inst xmlns:t=\"urn:tests:types\">/t:cont/t:leaflisttarget[4]</t:inst>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid instance-identifier \"/t:cont/t:leaflisttarget[4]\" value - semantic error. /types:inst");
-
-    data =  "<t:inst-noreq xmlns:t=\"urn:tests:types\">/t:cont/t:leaflisttarget[6]</t:inst-noreq>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid instance-identifier \"/t:cont/t:leaflisttarget[6]\" value - semantic error. /types:inst-noreq");
-
-    data =  "<cont xmlns=\"urn:tests:types\"><listtarget><id>1</id><value>x</value></listtarget></cont>"
-            "<t:inst xmlns:t=\"urn:tests:types\">/t:cont/t:listtarget[t:value='x']</t:inst>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid instance-identifier \"/t:cont/t:listtarget[t:value='x']\" value - semantic error. /types:inst");
+    TEST_DATA("<leaflisttarget xmlns=\"urn:tests:types\">x</leaflisttarget><t:inst xmlns:t=\"urn:tests:types\">/t:leaflisttarget[1</t:inst>", LY_EVALID,
+              "Invalid instance-identifier \"/t:leaflisttarget[1\" value - syntax error. /types:inst");
+    TEST_DATA("<cont xmlns=\"urn:tests:types\"/><t:inst xmlns:t=\"urn:tests:types\">/t:cont[1]</t:inst>", LY_EVALID,
+              "Invalid instance-identifier \"/t:cont[1]\" value - semantic error. /types:inst");
+    TEST_DATA("<cont xmlns=\"urn:tests:types\"/><t:inst xmlns:t=\"urn:tests:types\">[1]</t:inst>", LY_EVALID,
+              "Invalid instance-identifier \"[1]\" value - syntax error. /types:inst");
+    TEST_DATA("<cont xmlns=\"urn:tests:types\"><leaflisttarget>1</leaflisttarget></cont><t:inst xmlns:t=\"urn:tests:types\">/t:cont/t:leaflisttarget[id='1']</t:inst>", LY_EVALID,
+              "Invalid instance-identifier \"/t:cont/t:leaflisttarget[id='1']\" value - syntax error. /types:inst");
+    TEST_DATA("<cont xmlns=\"urn:tests:types\"><leaflisttarget>1</leaflisttarget></cont>"
+              "<t:inst xmlns:t=\"urn:tests:types\">/t:cont/t:leaflisttarget[t:id='1']</t:inst>", LY_EVALID,
+              "Invalid instance-identifier \"/t:cont/t:leaflisttarget[t:id='1']\" value - semantic error. /types:inst");
+    TEST_DATA("<cont xmlns=\"urn:tests:types\"><leaflisttarget>1</leaflisttarget><leaflisttarget>2</leaflisttarget></cont>"
+              "<t:inst xmlns:t=\"urn:tests:types\">/t:cont/t:leaflisttarget[4]</t:inst>", LY_EVALID,
+              "Invalid instance-identifier \"/t:cont/t:leaflisttarget[4]\" value - semantic error. /types:inst");
+    TEST_DATA("<t:inst-noreq xmlns:t=\"urn:tests:types\">/t:cont/t:leaflisttarget[6]</t:inst-noreq>", LY_EVALID,
+              "Invalid instance-identifier \"/t:cont/t:leaflisttarget[6]\" value - semantic error. /types:inst-noreq");
+    TEST_DATA("<cont xmlns=\"urn:tests:types\"><listtarget><id>1</id><value>x</value></listtarget></cont>"
+              "<t:inst xmlns:t=\"urn:tests:types\">/t:cont/t:listtarget[t:value='x']</t:inst>", LY_EVALID,
+              "Invalid instance-identifier \"/t:cont/t:listtarget[t:value='x']\" value - semantic error. /types:inst");
     logbuf_clean();
-    data =  "<t:inst-noreq xmlns:t=\"urn:tests:types\">/t:cont/t:listtarget[t:value='x']</t:inst-noreq>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid instance-identifier \"/t:cont/t:listtarget[t:value='x']\" value - semantic error. /types:inst-noreq");
-    data =  "<t:inst-noreq xmlns:t=\"urn:tests:types\">/t:cont/t:listtarget[t:x='x']</t:inst-noreq>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid instance-identifier \"/t:cont/t:listtarget[t:x='x']\" value - semantic error. /types:inst-noreq");
 
-    data =  "<cont xmlns=\"urn:tests:types\"><listtarget><id>1</id><value>x</value></listtarget></cont>"
-            "<t:inst xmlns:t=\"urn:tests:types\">/t:cont/t:listtarget[.='x']</t:inst>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid instance-identifier \"/t:cont/t:listtarget[.='x']\" value - semantic error. /types:inst");
+    TEST_DATA("<t:inst-noreq xmlns:t=\"urn:tests:types\">/t:cont/t:listtarget[t:value='x']</t:inst-noreq>", LY_EVALID,
+              "Invalid instance-identifier \"/t:cont/t:listtarget[t:value='x']\" value - semantic error. /types:inst-noreq");
+    TEST_DATA("<t:inst-noreq xmlns:t=\"urn:tests:types\">/t:cont/t:listtarget[t:x='x']</t:inst-noreq>", LY_EVALID,
+              "Invalid instance-identifier \"/t:cont/t:listtarget[t:x='x']\" value - semantic error. /types:inst-noreq");
+    TEST_DATA("<cont xmlns=\"urn:tests:types\"><listtarget><id>1</id><value>x</value></listtarget></cont>"
+              "<t:inst xmlns:t=\"urn:tests:types\">/t:cont/t:listtarget[.='x']</t:inst>", LY_EVALID,
+              "Invalid instance-identifier \"/t:cont/t:listtarget[.='x']\" value - semantic error. /types:inst");
 
-    data =  "<cont xmlns=\"urn:tests:types\"><leaflisttarget>1</leaflisttarget></cont>"
-            "<t:inst xmlns:t=\"urn:tests:types\">/t:cont/t:leaflisttarget[.='2']</t:inst>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
     /* instance-identifier is here in JSON format because it is already in internal representation without original prefixes */
-    logbuf_assert("Invalid instance-identifier \"/types:cont/leaflisttarget[.='2']\" value - required instance not found. /types:inst");
+    TEST_DATA("<cont xmlns=\"urn:tests:types\"><leaflisttarget>1</leaflisttarget></cont>"
+              "<t:inst xmlns:t=\"urn:tests:types\">/t:cont/t:leaflisttarget[.='2']</t:inst>", LY_EVALID,
+              "Invalid instance-identifier \"/types:cont/leaflisttarget[.='2']\" value - required instance not found. /types:inst");
+    TEST_DATA("<cont xmlns=\"urn:tests:types\"><leaflisttarget>1</leaflisttarget></cont>"
+              "<t:inst xmlns:t=\"urn:tests:types\">/t:cont/t:leaflisttarget[.='x']</t:inst>", LY_EVALID,
+              "Invalid instance-identifier \"/t:cont/t:leaflisttarget[.='x']\" value - semantic error. /types:inst");
+    TEST_DATA("<cont xmlns=\"urn:tests:types\"><listtarget><id>1</id><value>x</value></listtarget></cont>"
+              "<t:inst xmlns:t=\"urn:tests:types\">/t:cont/t:listtarget[t:id='x']</t:inst>", LY_EVALID,
+              "Invalid instance-identifier \"/t:cont/t:listtarget[t:id='x']\" value - semantic error. /types:inst");
 
-    data =  "<cont xmlns=\"urn:tests:types\"><leaflisttarget>1</leaflisttarget></cont>"
-            "<t:inst xmlns:t=\"urn:tests:types\">/t:cont/t:leaflisttarget[.='x']</t:inst>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid instance-identifier \"/t:cont/t:leaflisttarget[.='x']\" value - semantic error. /types:inst");
-
-    data =  "<cont xmlns=\"urn:tests:types\"><listtarget><id>1</id><value>x</value></listtarget></cont>"
-            "<t:inst xmlns:t=\"urn:tests:types\">/t:cont/t:listtarget[t:id='x']</t:inst>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid instance-identifier \"/t:cont/t:listtarget[t:id='x']\" value - semantic error. /types:inst");
-
-    data =  "<cont xmlns=\"urn:tests:types\"><listtarget><id>1</id><value>x</value></listtarget></cont>"
-            "<t:inst xmlns:t=\"urn:tests:types\">/t:cont/t:listtarget[t:id='2']</t:inst>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
     /* instance-identifier is here in JSON format because it is already in internal representation without original prefixes */
-    logbuf_assert("Invalid instance-identifier \"/types:cont/listtarget[id='2']\" value - required instance not found. /types:inst");
-
-    data = "<leaflisttarget xmlns=\"urn:tests:types\">a</leaflisttarget>"
-           "<leaflisttarget xmlns=\"urn:tests:types\">b</leaflisttarget>"
-           "<a:inst xmlns:a=\"urn:tests:types\">/a:leaflisttarget[1][2]</a:inst>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid instance-identifier \"/a:leaflisttarget[1][2]\" value - syntax error. /types:inst");
-
-    data = "<leaflisttarget xmlns=\"urn:tests:types\">a</leaflisttarget>"
-           "<leaflisttarget xmlns=\"urn:tests:types\">b</leaflisttarget>"
-           "<a:inst xmlns:a=\"urn:tests:types\">/a:leaflisttarget[.='a'][.='b']</a:inst>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid instance-identifier \"/a:leaflisttarget[.='a'][.='b']\" value - syntax error. /types:inst");
-
-    data = "<list xmlns=\"urn:tests:types\"><id>a</id><value>x</value></list>"
-           "<list xmlns=\"urn:tests:types\"><id>b</id><value>y</value></list>"
-           "<a:inst xmlns:a=\"urn:tests:types\">/a:list[a:id='a'][a:id='b']/a:value</a:inst>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid instance-identifier \"/a:list[a:id='a'][a:id='b']/a:value\" value - syntax error. /types:inst");
-
-    data = "<list2 xmlns=\"urn:tests:types\"><id>a</id><value>x</value></list2>"
-           "<list2 xmlns=\"urn:tests:types\"><id>b</id><value>y</value></list2>"
-           "<a:inst xmlns:a=\"urn:tests:types\">/a:list2[a:id='a']/a:value</a:inst>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid instance-identifier \"/a:list2[a:id='a']/a:value\" value - semantic error. /types:inst");
+    TEST_DATA("<cont xmlns=\"urn:tests:types\"><listtarget><id>1</id><value>x</value></listtarget></cont>"
+              "<t:inst xmlns:t=\"urn:tests:types\">/t:cont/t:listtarget[t:id='2']</t:inst>", LY_EVALID,
+              "Invalid instance-identifier \"/types:cont/listtarget[id='2']\" value - required instance not found. /types:inst");
+    TEST_DATA("<leaflisttarget xmlns=\"urn:tests:types\">a</leaflisttarget>"
+              "<leaflisttarget xmlns=\"urn:tests:types\">b</leaflisttarget>"
+              "<a:inst xmlns:a=\"urn:tests:types\">/a:leaflisttarget[1][2]</a:inst>", LY_EVALID,
+              "Invalid instance-identifier \"/a:leaflisttarget[1][2]\" value - syntax error. /types:inst");
+    TEST_DATA("<leaflisttarget xmlns=\"urn:tests:types\">a</leaflisttarget>"
+              "<leaflisttarget xmlns=\"urn:tests:types\">b</leaflisttarget>"
+              "<a:inst xmlns:a=\"urn:tests:types\">/a:leaflisttarget[.='a'][.='b']</a:inst>", LY_EVALID,
+              "Invalid instance-identifier \"/a:leaflisttarget[.='a'][.='b']\" value - syntax error. /types:inst");
+    TEST_DATA("<list xmlns=\"urn:tests:types\"><id>a</id><value>x</value></list>"
+              "<list xmlns=\"urn:tests:types\"><id>b</id><value>y</value></list>"
+              "<a:inst xmlns:a=\"urn:tests:types\">/a:list[a:id='a'][a:id='b']/a:value</a:inst>", LY_EVALID,
+              "Invalid instance-identifier \"/a:list[a:id='a'][a:id='b']/a:value\" value - syntax error. /types:inst");
+    TEST_DATA("<list2 xmlns=\"urn:tests:types\"><id>a</id><value>x</value></list2>"
+              "<list2 xmlns=\"urn:tests:types\"><id>b</id><value>y</value></list2>"
+              "<a:inst xmlns:a=\"urn:tests:types\">/a:list2[a:id='a']/a:value</a:inst>", LY_EVALID,
+              "Invalid instance-identifier \"/a:list2[a:id='a']/a:value\" value - semantic error. /types:inst");
 
     /* check for validting instance-identifier with a complete data tree */
-    data = "<list2 xmlns=\"urn:tests:types\"><id>a</id><value>a</value></list2>"
-           "<list2 xmlns=\"urn:tests:types\"><id>c</id><value>b</value></list2>"
-           "<leaflisttarget xmlns=\"urn:tests:types\">a</leaflisttarget>"
-           "<leaflisttarget xmlns=\"urn:tests:types\">b</leaflisttarget>"
-           "<a:inst xmlns:a=\"urn:tests:types\">/a:list2[a:id='a'][a:value='a']/a:id</a:inst>";
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<list2 xmlns=\"urn:tests:types\"><id>a</id><value>a</value></list2>"
+              "<list2 xmlns=\"urn:tests:types\"><id>c</id><value>b</value></list2>"
+              "<leaflisttarget xmlns=\"urn:tests:types\">a</leaflisttarget>"
+              "<leaflisttarget xmlns=\"urn:tests:types\">b</leaflisttarget>"
+              "<a:inst xmlns:a=\"urn:tests:types\">/a:list2[a:id='a'][a:value='a']/a:id</a:inst>", LY_SUCCESS, "");
+
     /* key-predicate */
     data = "/a:list2[a:id='a'][a:value='b']/a:id";
     assert_int_equal(LY_ENOTFOUND, lyd_value_validate(s->ctx, (const struct lyd_node_term*)tree->prev->prev, data, strlen(data),
@@ -1111,11 +958,13 @@
                                                    test_instanceid_getprefix, tree->schema->module, LYD_XML, tree));
     logbuf_assert("Invalid instance-identifier \"/a:list_keyless[4]\" value - instance not found. /");
 
-    data = "<leaflisttarget xmlns=\"urn:tests:types\">b</leaflisttarget>"
-           "<inst xmlns=\"urn:tests:types\">/a:leaflisttarget[1]</inst>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid instance-identifier \"/a:leaflisttarget[1]\" value - semantic error. /types:inst");
-    lyd_free_siblings(tree);
+    lyd_free_all(tree);
+
+    TEST_DATA("<leaflisttarget xmlns=\"urn:tests:types\">b</leaflisttarget>"
+            "<inst xmlns=\"urn:tests:types\">/a:leaflisttarget[1]</inst>", LY_EVALID,
+            "Invalid instance-identifier \"/a:leaflisttarget[1]\" value - semantic error. /types:inst");
+
+    ly_in_free(in, 0);
 
     s->func = NULL;
 }
@@ -1126,6 +975,7 @@
     struct state_s *s = (struct state_s*)(*state);
     s->func = test_leafref;
 
+    struct ly_in *in = NULL;
     struct lyd_node *tree;
     struct lyd_node_term *leaf;
 
@@ -1139,14 +989,11 @@
                 "leaf lr3 {type leafref {path \"/t:list[t:id=current ( )/../../x/x]/t:targets\";}}"
             "}}}";
 
-    const char *data = "<leaflisttarget xmlns=\"urn:tests:types\">x</leaflisttarget><leaflisttarget xmlns=\"urn:tests:types\">y</leaflisttarget>"
-            "<lref xmlns=\"urn:tests:types\">y</lref>";
-
     /* additional schema */
     assert_non_null(lys_parse_mem(s->ctx, schema, LYS_IN_YANG));
 
     /* valid data */
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<leaflisttarget xmlns=\"urn:tests:types\">x</leaflisttarget><leaflisttarget xmlns=\"urn:tests:types\">y</leaflisttarget><lref xmlns=\"urn:tests:types\">y</lref>", LY_SUCCESS, "");
     tree = tree->prev->prev;
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("lref", tree->schema->name);
@@ -1155,10 +1002,9 @@
     assert_int_equal(LY_TYPE_STRING, leaf->value.realtype->plugin->type);
     lyd_free_all(tree);
 
-    data = "<list xmlns=\"urn:tests:types\"><id>x</id><targets>a</targets><targets>b</targets></list>"
-           "<list xmlns=\"urn:tests:types\"><id>y</id><targets>x</targets><targets>y</targets></list>"
-           "<str-norestr xmlns=\"urn:tests:types\">y</str-norestr><lref2 xmlns=\"urn:tests:types\">y</lref2>";
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<list xmlns=\"urn:tests:types\"><id>x</id><targets>a</targets><targets>b</targets></list>"
+              "<list xmlns=\"urn:tests:types\"><id>y</id><targets>x</targets><targets>y</targets></list>"
+              "<str-norestr xmlns=\"urn:tests:types\">y</str-norestr><lref2 xmlns=\"urn:tests:types\">y</lref2>", LY_SUCCESS, "");
     tree = tree->prev->prev;
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("lref2", tree->schema->name);
@@ -1166,9 +1012,8 @@
     assert_string_equal("y", leaf->value.canonical_cache);
     lyd_free_all(tree);
 
-    data = "<str-norestr xmlns=\"urn:tests:types\">y</str-norestr>"
-           "<c xmlns=\"urn:tests:leafrefs\"><l><id>x</id><value>x</value><lr1>y</lr1></l></c>";
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<str-norestr xmlns=\"urn:tests:types\">y</str-norestr>"
+              "<c xmlns=\"urn:tests:leafrefs\"><l><id>x</id><value>x</value><lr1>y</lr1></l></c>", LY_SUCCESS, "");
     tree = tree->prev;
     assert_int_equal(LYS_CONTAINER, tree->schema->nodetype);
     leaf = (struct lyd_node_term*)(lyd_node_children(lyd_node_children(tree, 0), 0)->prev);
@@ -1177,10 +1022,9 @@
     assert_string_equal("y", leaf->value.canonical_cache);
     lyd_free_all(tree);
 
-    data = "<str-norestr xmlns=\"urn:tests:types\">y</str-norestr>"
-           "<c xmlns=\"urn:tests:leafrefs\"><l><id>y</id><value>y</value></l>"
-              "<l><id>x</id><value>x</value><lr2>y</lr2></l></c>";
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<str-norestr xmlns=\"urn:tests:types\">y</str-norestr>"
+              "<c xmlns=\"urn:tests:leafrefs\"><l><id>y</id><value>y</value></l>"
+              "<l><id>x</id><value>x</value><lr2>y</lr2></l></c>", LY_SUCCESS, "");
     tree = tree->prev;
     assert_int_equal(LYS_CONTAINER, tree->schema->nodetype);
     leaf = (struct lyd_node_term*)(lyd_node_children(lyd_node_children(tree, 0)->prev->prev, 0)->prev);
@@ -1189,11 +1033,10 @@
     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>"
-           "<list xmlns=\"urn:tests:types\"><id>y</id><targets>c</targets><targets>d</targets></list>"
-           "<c xmlns=\"urn:tests:leafrefs\"><x><x>y</x></x>"
-              "<l><id>x</id><value>x</value><lr3>c</lr3></l></c>";
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<list xmlns=\"urn:tests:types\"><id>x</id><targets>a</targets><targets>b</targets></list>"
+              "<list xmlns=\"urn:tests:types\"><id>y</id><targets>c</targets><targets>d</targets></list>"
+              "<c xmlns=\"urn:tests:leafrefs\"><x><x>y</x></x>"
+              "<l><id>x</id><value>x</value><lr3>c</lr3></l></c>", LY_SUCCESS, "");
     tree = tree->prev;
     assert_int_equal(LYS_CONTAINER, tree->schema->nodetype);
     leaf = (struct lyd_node_term*)(lyd_node_children(lyd_node_children(tree, 0)->prev, 0)->prev);
@@ -1203,43 +1046,33 @@
     lyd_free_all(tree);
 
     /* invalid value */
-    data =  "<leaflisttarget xmlns=\"urn:tests:types\">x</leaflisttarget>"
-            "<lref xmlns=\"urn:tests:types\">y</lref>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid leafref value \"y\" - no target instance \"/leaflisttarget\" with the same value. /types:lref");
+    TEST_DATA("<leaflisttarget xmlns=\"urn:tests:types\">x</leaflisttarget><lref xmlns=\"urn:tests:types\">y</lref>", LY_EVALID,
+              "Invalid leafref value \"y\" - no target instance \"/leaflisttarget\" with the same value. /types:lref");
 
-    data = "<list xmlns=\"urn:tests:types\"><id>x</id><targets>a</targets><targets>b</targets></list>"
-           "<list xmlns=\"urn:tests:types\"><id>y</id><targets>x</targets><targets>y</targets></list>"
-           "<str-norestr xmlns=\"urn:tests:types\">y</str-norestr><lref2 xmlns=\"urn:tests:types\">b</lref2>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid leafref value \"b\" - no target instance \"../list[id = current()/../str-norestr]/targets\" with"
-        " the same value. /types:lref2");
+    TEST_DATA("<list xmlns=\"urn:tests:types\"><id>x</id><targets>a</targets><targets>b</targets></list>"
+              "<list xmlns=\"urn:tests:types\"><id>y</id><targets>x</targets><targets>y</targets></list>"
+              "<str-norestr xmlns=\"urn:tests:types\">y</str-norestr><lref2 xmlns=\"urn:tests:types\">b</lref2>", LY_EVALID,
+              "Invalid leafref value \"b\" - no target instance \"../list[id = current()/../str-norestr]/targets\" with the same value. /types:lref2");
 
-    data = "<list xmlns=\"urn:tests:types\"><id>x</id><targets>a</targets><targets>b</targets></list>"
-           "<list xmlns=\"urn:tests:types\"><id>y</id><targets>x</targets><targets>y</targets></list>"
-           "<lref2 xmlns=\"urn:tests:types\">b</lref2>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid leafref value \"b\" - no target instance \"../list[id = current()/../str-norestr]/targets\""
-        " with the same value. /types:lref2");
+    TEST_DATA("<list xmlns=\"urn:tests:types\"><id>x</id><targets>a</targets><targets>b</targets></list>"
+              "<list xmlns=\"urn:tests:types\"><id>y</id><targets>x</targets><targets>y</targets></list>"
+              "<lref2 xmlns=\"urn:tests:types\">b</lref2>", LY_EVALID,
+              "Invalid leafref value \"b\" - no target instance \"../list[id = current()/../str-norestr]/targets\" with the same value. /types:lref2");
 
-    data = "<str-norestr xmlns=\"urn:tests:types\">y</str-norestr><lref2 xmlns=\"urn:tests:types\">b</lref2>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid leafref value \"b\" - no target instance \"../list[id = current()/../str-norestr]/targets\""
-        " with the same value. /types:lref2");
+    TEST_DATA("<str-norestr xmlns=\"urn:tests:types\">y</str-norestr><lref2 xmlns=\"urn:tests:types\">b</lref2>", LY_EVALID,
+              "Invalid leafref value \"b\" - no target instance \"../list[id = current()/../str-norestr]/targets\" with the same value. /types:lref2");
 
-    data = "<str-norestr xmlns=\"urn:tests:types\">y</str-norestr>"
-            "<c xmlns=\"urn:tests:leafrefs\"><l><id>x</id><value>x</value><lr1>a</lr1></l></c>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid leafref value \"a\" - no target instance \"../../../t:str-norestr\" with the same value."
-        " /leafrefs:c/l[id='x'][value='x']/lr1");
+    TEST_DATA("<str-norestr xmlns=\"urn:tests:types\">y</str-norestr>"
+            "<c xmlns=\"urn:tests:leafrefs\"><l><id>x</id><value>x</value><lr1>a</lr1></l></c>", LY_EVALID,
+            "Invalid leafref value \"a\" - no target instance \"../../../t:str-norestr\" with the same value. /leafrefs:c/l[id='x'][value='x']/lr1");
 
-    data = "<str-norestr xmlns=\"urn:tests:types\">z</str-norestr>"
-            "<c xmlns=\"urn:tests:leafrefs\"><l><id>y</id><value>y</value></l>"
-              "<l><id>x</id><value>x</value><lr2>z</lr2></l></c>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid leafref value \"z\" - no target instance \"../../l[id=current()/../../../t:str-norestr]"
-        "[value=current()/../../../t:str-norestr]/value\" with the same value. /leafrefs:c/l[id='x'][value='x']/lr2");
+    TEST_DATA("<str-norestr xmlns=\"urn:tests:types\">z</str-norestr>"
+              "<c xmlns=\"urn:tests:leafrefs\"><l><id>y</id><value>y</value></l>"
+              "<l><id>x</id><value>x</value><lr2>z</lr2></l></c>", LY_EVALID,
+              "Invalid leafref value \"z\" - no target instance \"../../l[id=current()/../../../t:str-norestr]"
+              "[value=current()/../../../t:str-norestr]/value\" with the same value. /leafrefs:c/l[id='x'][value='x']/lr2");
 
+    ly_in_free(in, 0);
     s->func = NULL;
 }
 
@@ -1249,6 +1082,7 @@
     struct state_s *s = (struct state_s*)(*state);
     s->func = test_union;
 
+    struct ly_in *in = NULL;
     struct lyd_node *tree;
     struct lyd_node_term *leaf;
     struct lyd_value value = {0};
@@ -1265,11 +1099,8 @@
      * }
      */
 
-    const char *data = "<int8 xmlns=\"urn:tests:types\">12</int8>"
-            "<un1 xmlns=\"urn:tests:types\">12</un1>";
-
     /* valid data */
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<int8 xmlns=\"urn:tests:types\">12</int8><un1 xmlns=\"urn:tests:types\">12</un1>", LY_SUCCESS, "");
     tree = tree->next;
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("un1", tree->schema->name);
@@ -1295,9 +1126,7 @@
     value.realtype->plugin->free(s->ctx, &value);
     lyd_free_all(tree);
 
-    data = "<int8 xmlns=\"urn:tests:types\">12</int8>"
-           "<un1 xmlns=\"urn:tests:types\">2</un1>";
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<int8 xmlns=\"urn:tests:types\">12</int8><un1 xmlns=\"urn:tests:types\">2</un1>", LY_SUCCESS, "");
     tree = tree->next;
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("un1", tree->schema->name);
@@ -1310,8 +1139,7 @@
     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>";
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<un1 xmlns=\"urn:tests:types\" xmlns:x=\"urn:tests:defs\">x:fast-ethernet</un1>", LY_SUCCESS, "");
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("un1", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
@@ -1336,8 +1164,7 @@
     value.realtype->plugin->free(s->ctx, &value);
     lyd_free_all(tree);
 
-    data = "<un1 xmlns=\"urn:tests:types\" xmlns:d=\"urn:tests:defs\">d:superfast-ethernet</un1>";
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<un1 xmlns=\"urn:tests:types\" xmlns:d=\"urn:tests:defs\">d:superfast-ethernet</un1>", LY_SUCCESS, "");
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("un1", tree->schema->name);
     leaf = (struct lyd_node_term*)tree;
@@ -1349,9 +1176,8 @@
     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>"
-           "<un1 xmlns=\"urn:tests:types\" xmlns:a=\"urn:tests:types\">/a:leaflisttarget[.='y']</un1>";
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<leaflisttarget xmlns=\"urn:tests:types\">x</leaflisttarget><leaflisttarget xmlns=\"urn:tests:types\">y</leaflisttarget>"
+            "<un1 xmlns=\"urn:tests:types\" xmlns:a=\"urn:tests:types\">/a:leaflisttarget[.='y']</un1>", LY_SUCCESS, "");
     tree = tree->prev->prev;
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("un1", tree->schema->name);
@@ -1364,9 +1190,8 @@
     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>"
-           "<un1 xmlns=\"urn:tests:types\" xmlns:a=\"urn:tests:types\">/a:leaflisttarget[3]</un1>";
-    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
+    TEST_DATA("<leaflisttarget xmlns=\"urn:tests:types\">x</leaflisttarget><leaflisttarget xmlns=\"urn:tests:types\">y</leaflisttarget>"
+              "<un1 xmlns=\"urn:tests:types\" xmlns:a=\"urn:tests:types\">/a:leaflisttarget[3]</un1>", LY_SUCCESS, "");
     tree = tree->prev->prev;
     assert_int_equal(LYS_LEAF, tree->schema->nodetype);
     assert_string_equal("un1", tree->schema->name);
@@ -1379,10 +1204,9 @@
     assert_string_equal("/a:leaflisttarget[3]", leaf->value.subvalue->value->canonical_cache);
     lyd_free_all(tree);
 
-    data = "<un1 xmlns=\"urn:tests:types\">123456789012345678901</un1>";
-    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
-    logbuf_assert("Invalid union value \"123456789012345678901\" - no matching subtype found. /types:un1");
+    TEST_DATA("<un1 xmlns=\"urn:tests:types\">123456789012345678901</un1>", LY_EVALID, "Invalid union value \"123456789012345678901\" - no matching subtype found. /types:un1");
 
+    ly_in_free(in, 0);
     s->func = NULL;
 }
 
diff --git a/tests/utests/data/test_validation.c b/tests/utests/data/test_validation.c
index 39b8681..f80ce9f 100644
--- a/tests/utests/data/test_validation.c
+++ b/tests/utests/data/test_validation.c
@@ -21,6 +21,7 @@
 #include <string.h>
 
 #include "context.h"
+#include "parser_data.h"
 #include "printer.h"
 #include "printer_data.h"
 #include "tests/config.h"
@@ -476,19 +477,19 @@
     struct lyd_node *tree;
 
     data = "<c xmlns=\"urn:tests:a\">hey</c>";
-    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_null(tree);
     logbuf_assert("When condition \"/cont/b = 'val_b'\" not satisfied. /a:c");
 
     data = "<cont xmlns=\"urn:tests:a\"><b>val_b</b></cont><c xmlns=\"urn:tests:a\">hey</c>";
-    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_non_null(tree);
     assert_string_equal("c", tree->next->schema->name);
     assert_int_equal(LYD_WHEN_TRUE, tree->next->flags);
     lyd_free_all(tree);
 
     data = "<cont xmlns=\"urn:tests:a\"><a>val</a><b>val_b</b></cont><c xmlns=\"urn:tests:a\">val_c</c>";
-    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_non_null(tree);
     assert_string_equal("a", lyd_node_children(tree, 0)->schema->name);
     assert_int_equal(LYD_WHEN_TRUE, lyd_node_children(tree, 0)->flags);
@@ -508,22 +509,22 @@
     struct lyd_node *tree;
 
     data = "<d xmlns=\"urn:tests:b\"/>";
-    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_null(tree);
     logbuf_assert("Mandatory node \"choic\" instance does not exist. /b:choic");
 
     data = "<l xmlns=\"urn:tests:b\">string</l><d xmlns=\"urn:tests:b\"/>";
-    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_null(tree);
     logbuf_assert("Mandatory node \"c\" instance does not exist. /b:c");
 
     data = "<a xmlns=\"urn:tests:b\">string</a>";
-    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_null(tree);
     logbuf_assert("Mandatory node \"c\" instance does not exist. /b:c");
 
     data = "<a xmlns=\"urn:tests:b\">string</a><c xmlns=\"urn:tests:b\">string2</c>";
-    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_non_null(tree);
     lyd_free_siblings(tree);
 
@@ -539,14 +540,14 @@
     struct lyd_node *tree;
 
     data = "<d xmlns=\"urn:tests:c\"/>";
-    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_null(tree);
     logbuf_assert("Too few \"l\" instances. /c:choic/b/l");
 
     data =
     "<l xmlns=\"urn:tests:c\">val1</l>"
     "<l xmlns=\"urn:tests:c\">val2</l>";
-    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_null(tree);
     logbuf_assert("Too few \"l\" instances. /c:choic/b/l");
 
@@ -554,7 +555,7 @@
     "<l xmlns=\"urn:tests:c\">val1</l>"
     "<l xmlns=\"urn:tests:c\">val2</l>"
     "<l xmlns=\"urn:tests:c\">val3</l>";
-    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_non_null(tree);
     lyd_free_siblings(tree);
 
@@ -567,7 +568,7 @@
     "<lt xmlns=\"urn:tests:c\"><k>val3</k></lt>"
     "<lt xmlns=\"urn:tests:c\"><k>val4</k></lt>"
     "<lt xmlns=\"urn:tests:c\"><k>val5</k></lt>";
-    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_null(tree);
     logbuf_assert("Too many \"lt\" instances. /c:lt");
 
@@ -590,7 +591,7 @@
     "<lt xmlns=\"urn:tests:d\">"
         "<k>val2</k>"
     "</lt>";
-    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_non_null(tree);
     lyd_free_siblings(tree);
 
@@ -603,7 +604,7 @@
         "<k>val2</k>"
         "<l1>not-same</l1>"
     "</lt>";
-    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_non_null(tree);
     lyd_free_siblings(tree);
 
@@ -616,7 +617,7 @@
         "<k>val2</k>"
         "<l1>same</l1>"
     "</lt>";
-    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_null(tree);
     logbuf_assert("Unique data leaf(s) \"l1\" not satisfied in \"/d:lt[k='val1']\" and \"/d:lt[k='val2']\". /d:lt[k='val2']");
 
@@ -654,7 +655,7 @@
         "<k>val8</k>"
         "<l1>8</l1>"
     "</lt>";
-    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_non_null(tree);
     lyd_free_siblings(tree);
 
@@ -688,7 +689,7 @@
     "<lt xmlns=\"urn:tests:d\">"
         "<k>val8</k>"
     "</lt>";
-    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_non_null(tree);
     lyd_free_siblings(tree);
 
@@ -722,7 +723,7 @@
         "<k>val8</k>"
         "<l1>8</l1>"
     "</lt>";
-    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_null(tree);
     logbuf_assert("Unique data leaf(s) \"l1\" not satisfied in \"/d:lt[k='val7']\" and \"/d:lt[k='val2']\". /d:lt[k='val2']");
 
@@ -794,7 +795,7 @@
             "<l3>3</l3>"
         "</lt3>"
     "</lt2>";
-    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY | LYD_OPT_STRICT, &tree));
+    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &tree));
     assert_non_null(tree);
     lyd_free_siblings(tree);
 
@@ -855,7 +856,7 @@
             "<l3>3</l3>"
         "</lt3>"
     "</lt2>";
-    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_null(tree);
     logbuf_assert("Unique data leaf(s) \"l3\" not satisfied in \"/d:lt2[k='val2']/lt3[kk='val3']\" and"
                   " \"/d:lt2[k='val2']/lt3[kk='val1']\". /d:lt2[k='val2']/lt3[kk='val1']");
@@ -896,7 +897,7 @@
         "</cont>"
         "<l4>5</l4>"
     "</lt2>";
-    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_null(tree);
     logbuf_assert("Unique data leaf(s) \"cont/l2 l4\" not satisfied in \"/d:lt2[k='val4']\" and \"/d:lt2[k='val2']\". /d:lt2[k='val2']");
 
@@ -944,7 +945,7 @@
         "<l5>3</l5>"
         "<l6>3</l6>"
     "</lt2>";
-    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_null(tree);
     logbuf_assert("Unique data leaf(s) \"l5 l6\" not satisfied in \"/d:lt2[k='val5']\" and \"/d:lt2[k='val3']\". /d:lt2[k='val3']");
 
@@ -960,51 +961,51 @@
     struct lyd_node *tree;
 
     data = "<d xmlns=\"urn:tests:e\">25</d><d xmlns=\"urn:tests:e\">50</d>";
-    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_null(tree);
     logbuf_assert("Duplicate instance of \"d\". /e:d");
 
     data = "<lt xmlns=\"urn:tests:e\"><k>A</k></lt><lt xmlns=\"urn:tests:e\"><k>B</k></lt><lt xmlns=\"urn:tests:e\"><k>A</k></lt>";
-    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_null(tree);
     logbuf_assert("Duplicate instance of \"lt\". /e:lt[k='A']");
 
     data = "<ll xmlns=\"urn:tests:e\">A</ll><ll xmlns=\"urn:tests:e\">B</ll><ll xmlns=\"urn:tests:e\">B</ll>";
-    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_null(tree);
     logbuf_assert("Duplicate instance of \"ll\". /e:ll[.='B']");
 
     data = "<cont xmlns=\"urn:tests:e\"></cont><cont xmlns=\"urn:tests:e\"/>";
-    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_null(tree);
     logbuf_assert("Duplicate instance of \"cont\". /e:cont");
 
     /* same tests again but using hashes */
     data = "<cont xmlns=\"urn:tests:e\"><d>25</d><d>50</d><ll>1</ll><ll>2</ll><ll>3</ll><ll>4</ll></cont>";
-    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_null(tree);
     logbuf_assert("Duplicate instance of \"d\". /e:cont/d");
 
     data = "<cont xmlns=\"urn:tests:e\"><ll>1</ll><ll>2</ll><ll>3</ll><ll>4</ll>"
         "<lt><k>a</k></lt><lt><k>b</k></lt><lt><k>c</k></lt><lt><k>d</k></lt><lt><k>c</k></lt></cont>";
-    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_null(tree);
     logbuf_assert("Duplicate instance of \"lt\". /e:cont/lt[k='c']");
 
     data = "<cont xmlns=\"urn:tests:e\"><ll>1</ll><ll>2</ll><ll>3</ll><ll>4</ll>"
         "<ll>a</ll><ll>b</ll><ll>c</ll><ll>d</ll><ll>d</ll></cont>";
-    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_null(tree);
     logbuf_assert("Duplicate instance of \"ll\". /e:cont/ll[.='d']");
 
     /* cases */
     data = "<l xmlns=\"urn:tests:e\">a</l><l xmlns=\"urn:tests:e\">b</l><l xmlns=\"urn:tests:e\">c</l><l xmlns=\"urn:tests:e\">b</l>";
-    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_null(tree);
     logbuf_assert("Duplicate instance of \"l\". /e:l[.='b']");
 
     data = "<l xmlns=\"urn:tests:e\">a</l><l xmlns=\"urn:tests:e\">b</l><l xmlns=\"urn:tests:e\">c</l><a xmlns=\"urn:tests:e\">aa</a>";
-    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_null(tree);
     logbuf_assert("Data for both cases \"a\" and \"b\" exist. /e:choic");
 
@@ -1029,7 +1030,7 @@
     assert_non_null(tree);
 
     /* check all defaults exist */
-    lyd_print(out, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_IMPL_TAG);
+    lyd_print(out, tree, LYD_XML, LYD_PRINT_WITHSIBLINGS | LYD_PRINT_WD_IMPL_TAG);
     assert_string_equal(str,
         "<ll1 xmlns=\"urn:tests:f\" xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def1</ll1>"
         "<ll1 xmlns=\"urn:tests:f\" xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def2</ll1>"
@@ -1051,10 +1052,10 @@
     node = lyd_new_term(NULL, mod, "l", "value");
     assert_non_null(node);
     assert_int_equal(lyd_insert_sibling(tree, node), LY_SUCCESS);
-    assert_int_equal(lyd_validate(&tree, ctx, LYD_VALOPT_DATA_ONLY), LY_SUCCESS);
+    assert_int_equal(lyd_validate(&tree, ctx, LYD_VALIDATE_PRESENT), LY_SUCCESS);
 
     /* check data tree */
-    lyd_print(out, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_IMPL_TAG);
+    lyd_print(out, tree, LYD_XML, LYD_PRINT_WITHSIBLINGS | LYD_PRINT_WD_IMPL_TAG);
     assert_string_equal(str,
         "<d xmlns=\"urn:tests:f\" xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">15</d>"
         "<ll2 xmlns=\"urn:tests:f\" xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">dflt1</ll2>"
@@ -1077,10 +1078,10 @@
     node = lyd_new_term(NULL, mod, "ll2", "dflt2");
     assert_non_null(node);
     assert_int_equal(lyd_insert_sibling(tree, node), LY_SUCCESS);
-    assert_int_equal(lyd_validate(&tree, ctx, LYD_VALOPT_DATA_ONLY), LY_SUCCESS);
+    assert_int_equal(lyd_validate(&tree, ctx, LYD_VALIDATE_PRESENT), LY_SUCCESS);
 
     /* check data tree */
-    lyd_print(out, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_IMPL_TAG);
+    lyd_print(out, tree, LYD_XML, LYD_PRINT_WITHSIBLINGS | LYD_PRINT_WD_IMPL_TAG);
     assert_string_equal(str,
         "<cont xmlns=\"urn:tests:f\">"
             "<ll1 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def1</ll1>"
@@ -1100,10 +1101,10 @@
     assert_non_null(node);
     assert_int_equal(lyd_insert_before(tree, node), LY_SUCCESS);
     tree = tree->prev;
-    assert_int_equal(lyd_validate(&tree, ctx, LYD_VALOPT_DATA_ONLY), LY_SUCCESS);
+    assert_int_equal(lyd_validate(&tree, ctx, LYD_VALIDATE_PRESENT), LY_SUCCESS);
 
     /* check data tree */
-    lyd_print(out, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_IMPL_TAG);
+    lyd_print(out, tree, LYD_XML, LYD_PRINT_WITHSIBLINGS | LYD_PRINT_WD_IMPL_TAG);
     assert_string_equal(str,
         "<cont xmlns=\"urn:tests:f\">"
             "<ll1 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def1</ll1>"
@@ -1122,10 +1123,10 @@
     node = lyd_new_inner(NULL, mod, "cont");
     assert_non_null(node);
     assert_int_equal(lyd_insert_after(tree, node), LY_SUCCESS);
-    assert_int_equal(lyd_validate(&tree, ctx, LYD_VALOPT_DATA_ONLY), LY_SUCCESS);
+    assert_int_equal(lyd_validate(&tree, ctx, LYD_VALIDATE_PRESENT), LY_SUCCESS);
 
     /* check data tree */
-    lyd_print(out, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_IMPL_TAG);
+    lyd_print(out, tree, LYD_XML, LYD_PRINT_WITHSIBLINGS | LYD_PRINT_WD_IMPL_TAG);
     assert_string_equal(str,
         "<cont xmlns=\"urn:tests:f\">"
             "<ll1 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def1</ll1>"
@@ -1144,10 +1145,10 @@
     assert_non_null(lyd_new_term(tree, NULL, "ll1", "def3"));
     assert_non_null(lyd_new_term(tree, NULL, "d", "5"));
     assert_non_null(lyd_new_term(tree, NULL, "ll2", "non-dflt"));
-    assert_int_equal(lyd_validate(&tree, ctx, LYD_VALOPT_DATA_ONLY), LY_SUCCESS);
+    assert_int_equal(lyd_validate(&tree, ctx, LYD_VALIDATE_PRESENT), LY_SUCCESS);
 
     /* check data tree */
-    lyd_print(out, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_IMPL_TAG);
+    lyd_print(out, tree, LYD_XML, LYD_PRINT_WITHSIBLINGS | LYD_PRINT_WD_IMPL_TAG);
     assert_string_equal(str,
         "<cont xmlns=\"urn:tests:f\">"
             "<ll1>def3</ll1>"
@@ -1184,7 +1185,7 @@
     "<cont xmlns=\"urn:tests:g\">"
         "<d>51</d>"
     "</cont>";
-    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_null(tree);
     logbuf_assert("Data are disabled by \"cont\" schema node if-feature. /g:cont");
 
@@ -1203,7 +1204,7 @@
             "<e>val</e>"
         "</cont2>"
     "</cont>";
-    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_null(tree);
     logbuf_assert("Data are disabled by \"cont2\" schema node if-feature. /g:cont/cont2");
 
@@ -1211,14 +1212,14 @@
     "<cont xmlns=\"urn:tests:g\">"
         "<a>val</a>"
     "</cont>";
-    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_null(tree);
     logbuf_assert("Data are disabled by \"choic\" schema node if-feature. /g:cont/a");
 
     /* enable f3 */
     assert_int_equal(lys_feature_enable(mod, "f3"), LY_SUCCESS);
 
-    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_non_null(tree);
     lyd_free_siblings(tree);
 
@@ -1227,14 +1228,14 @@
     "<cont xmlns=\"urn:tests:g\">"
         "<l>val</l>"
     "</cont>";
-    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_null(tree);
     logbuf_assert("Data are disabled by \"b\" schema node if-feature. /g:cont/l");
 
     /* enable f2 */
     assert_int_equal(lys_feature_enable(mod, "f2"), LY_SUCCESS);
 
-    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_non_null(tree);
     lyd_free_siblings(tree);
 
@@ -1251,20 +1252,20 @@
             "<e>val</e>"
         "</cont2>"
     "</cont>";
-    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_OPT_PARSE_ONLY, &tree));
+    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_PARSE_ONLY, 0, &tree));
     assert_non_null(tree);
 
-    assert_int_equal(LY_EVALID, lyd_validate(&tree, NULL, LYD_VALOPT_DATA_ONLY));
+    assert_int_equal(LY_EVALID, lyd_validate(&tree, NULL, LYD_VALIDATE_PRESENT));
     logbuf_assert("Data are disabled by \"cont\" schema node if-feature. /g:cont");
 
     assert_int_equal(lys_feature_enable(mod, "f1"), LY_SUCCESS);
 
-    assert_int_equal(LY_EVALID, lyd_validate(&tree, NULL, LYD_VALOPT_DATA_ONLY));
+    assert_int_equal(LY_EVALID, lyd_validate(&tree, NULL, LYD_VALIDATE_PRESENT));
     logbuf_assert("Data are disabled by \"b\" schema node if-feature. /g:cont/l");
 
     assert_int_equal(lys_feature_enable(mod, "f2"), LY_SUCCESS);
 
-    assert_int_equal(LY_SUCCESS, lyd_validate(&tree, NULL, LYD_VALOPT_DATA_ONLY));
+    assert_int_equal(LY_SUCCESS, lyd_validate(&tree, NULL, LYD_VALIDATE_PRESENT));
 
     lyd_free_siblings(tree);
 
@@ -1285,18 +1286,18 @@
             "<l>val</l>"
         "</cont2>"
     "</cont>";
-    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_OPT_PARSE_ONLY | LYD_OPT_NO_STATE, &tree));
+    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_PARSE_ONLY | LYD_PARSE_NO_STATE, 0, &tree));
     assert_null(tree);
     logbuf_assert("Invalid state data node \"cont2\" found. Line number 1.");
 
-    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY | LYD_VALOPT_NO_STATE, &tree));
+    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT | LYD_VALIDATE_NO_STATE, &tree));
     assert_null(tree);
     logbuf_assert("Invalid state data node \"cont2\" found. /h:cont/cont2");
 
-    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_OPT_PARSE_ONLY, &tree));
+    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_PARSE_ONLY, 0, &tree));
     assert_non_null(tree);
 
-    assert_int_equal(LY_EVALID, lyd_validate(&tree, NULL, LYD_VALOPT_DATA_ONLY | LYD_VALOPT_NO_STATE));
+    assert_int_equal(LY_EVALID, lyd_validate(&tree, NULL, LYD_VALIDATE_PRESENT | LYD_VALIDATE_NO_STATE));
     logbuf_assert("Invalid state data node \"cont2\" found. /h:cont/cont2");
 
     lyd_free_siblings(tree);
@@ -1317,7 +1318,7 @@
         "<l>wrong</l>"
         "<l2>val</l2>"
     "</cont>";
-    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_null(tree);
     logbuf_assert("Must condition \"../l = 'right'\" not satisfied. /i:cont/l2");
 
@@ -1326,7 +1327,7 @@
         "<l>right</l>"
         "<l2>val</l2>"
     "</cont>";
-    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
+    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, 0, LYD_VALIDATE_PRESENT, &tree));
     assert_non_null(tree);
     lyd_free_tree(tree);
 
@@ -1355,7 +1356,7 @@
     assert_non_null(op_tree);
 
     /* missing leafref */
-    assert_int_equal(LY_EVALID, lyd_validate_op(op_tree, NULL, LYD_VALOPT_INPUT));
+    assert_int_equal(LY_EVALID, lyd_validate_op(op_tree, NULL, LYD_VALIDATE_OP_RPC));
     logbuf_assert("Invalid leafref value \"target\" - no target instance \"/lf3\" with the same value."
         " /j:cont/l1[k='val1']/act/lf2");
 
@@ -1364,11 +1365,11 @@
         "<lf1>not true</lf1>"
     "</cont>"
     "<lf3 xmlns=\"urn:tests:j\">target</lf3>";
-    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_OPT_PARSE_ONLY | LYD_OPT_TRUSTED, &tree));
+    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_PARSE_ONLY | LYD_PARSE_TRUSTED, 0, &tree));
     assert_non_null(tree);
 
     /* disabled if-feature */
-    assert_int_equal(LY_EVALID, lyd_validate_op(op_tree, tree, LYD_VALOPT_INPUT));
+    assert_int_equal(LY_EVALID, lyd_validate_op(op_tree, tree, LYD_VALIDATE_OP_RPC));
     logbuf_assert("Data are disabled by \"act\" schema node if-feature. /j:cont/l1[k='val1']/act");
 
     mod = ly_ctx_get_module_latest(ctx, "j");
@@ -1376,7 +1377,7 @@
     assert_int_equal(LY_SUCCESS, lys_feature_enable(mod, "feat1"));
 
     /* input must false */
-    assert_int_equal(LY_EVALID, lyd_validate_op(op_tree, tree, LYD_VALOPT_INPUT));
+    assert_int_equal(LY_EVALID, lyd_validate_op(op_tree, tree, LYD_VALIDATE_OP_RPC));
     logbuf_assert("Must condition \"../../lf1 = 'true'\" not satisfied. /j:cont/l1[k='val1']/act");
 
     lyd_free_siblings(tree);
@@ -1385,11 +1386,11 @@
         "<lf1>true</lf1>"
     "</cont>"
     "<lf3 xmlns=\"urn:tests:j\">target</lf3>";
-    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_OPT_PARSE_ONLY | LYD_OPT_TRUSTED, &tree));
+    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_PARSE_ONLY | LYD_PARSE_TRUSTED, 0, &tree));
     assert_non_null(tree);
 
     /* success */
-    assert_int_equal(LY_SUCCESS, lyd_validate_op(op_tree, tree, LYD_VALOPT_INPUT));
+    assert_int_equal(LY_SUCCESS, lyd_validate_op(op_tree, tree, LYD_VALIDATE_OP_RPC));
 
     lys_feature_disable(mod, "feat1");
     lyd_free_tree(op_tree);
@@ -1424,7 +1425,7 @@
     assert_non_null(op_tree);
 
     /* missing leafref */
-    assert_int_equal(LY_EVALID, lyd_validate_op(op_tree, NULL, LYD_VALOPT_OUTPUT));
+    assert_int_equal(LY_EVALID, lyd_validate_op(op_tree, NULL, LYD_VALIDATE_OP_REPLY));
     logbuf_assert("Invalid leafref value \"target\" - no target instance \"/lf4\" with the same value."
         " /j:cont/l1[k='val1']/act/lf2");
 
@@ -1433,11 +1434,11 @@
         "<lf1>not true</lf1>"
     "</cont>"
     "<lf4 xmlns=\"urn:tests:j\">target</lf4>";
-    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_OPT_PARSE_ONLY | LYD_OPT_TRUSTED, &tree));
+    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_PARSE_ONLY | LYD_PARSE_TRUSTED, 0, &tree));
     assert_non_null(tree);
 
     /* disabled if-feature */
-    assert_int_equal(LY_EVALID, lyd_validate_op(op_tree, tree, LYD_VALOPT_OUTPUT));
+    assert_int_equal(LY_EVALID, lyd_validate_op(op_tree, tree, LYD_VALIDATE_OP_REPLY));
     logbuf_assert("Data are disabled by \"act\" schema node if-feature. /j:cont/l1[k='val1']/act");
 
     mod = ly_ctx_get_module_latest(ctx, "j");
@@ -1445,7 +1446,7 @@
     assert_int_equal(LY_SUCCESS, lys_feature_enable(mod, "feat1"));
 
     /* input must false */
-    assert_int_equal(LY_EVALID, lyd_validate_op(op_tree, tree, LYD_VALOPT_OUTPUT));
+    assert_int_equal(LY_EVALID, lyd_validate_op(op_tree, tree, LYD_VALIDATE_OP_REPLY));
     logbuf_assert("Must condition \"../../lf1 = 'true2'\" not satisfied. /j:cont/l1[k='val1']/act");
 
     lyd_free_siblings(tree);
@@ -1454,11 +1455,11 @@
         "<lf1>true2</lf1>"
     "</cont>"
     "<lf4 xmlns=\"urn:tests:j\">target</lf4>";
-    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_OPT_PARSE_ONLY | LYD_OPT_TRUSTED, &tree));
+    assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_PARSE_ONLY | LYD_PARSE_TRUSTED, 0, &tree));
     assert_non_null(tree);
 
     /* success */
-    assert_int_equal(LY_SUCCESS, lyd_validate_op(op_tree, tree, LYD_VALOPT_OUTPUT));
+    assert_int_equal(LY_SUCCESS, lyd_validate_op(op_tree, tree, LYD_VALIDATE_OP_REPLY));
 
     lys_feature_disable(mod, "feat1");
     lyd_free_tree(op_tree);
diff --git a/tests/utests/test_xpath.c b/tests/utests/test_xpath.c
index a2264c6..32f0f8d 100644
--- a/tests/utests/test_xpath.c
+++ b/tests/utests/test_xpath.c
@@ -21,6 +21,7 @@
 #include <string.h>
 
 #include "context.h"
+#include "parser_data.h"
 #include "set.h"
 #include "tests/config.h"
 #include "tree_data.h"
@@ -222,7 +223,7 @@
     int dynamic;
     const char *val_str;
 
-    tree = lyd_parse_mem(ctx, data, LYD_XML, LYD_OPT_STRICT | LYD_VALOPT_DATA_ONLY);
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &tree));
     assert_non_null(tree);
 
     /* top-level, so hash table is not ultimately used but instances can be compared based on hashes */
@@ -326,7 +327,7 @@
     struct lyd_node *tree;
     struct ly_set *set;
 
-    tree = lyd_parse_mem(ctx, data, LYD_XML, LYD_OPT_STRICT | LYD_VALOPT_DATA_ONLY);
+    assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data, LYD_XML, LYD_PARSE_STRICT , LYD_VALIDATE_PRESENT, &tree));
     assert_non_null(tree);
 
     /* all top-level nodes from one module (default container as well) */
diff --git a/tools/lint/commands.c b/tools/lint/commands.c
index a456e47..fbafa1a 100644
--- a/tools/lint/commands.c
+++ b/tools/lint/commands.c
@@ -523,44 +523,19 @@
     return ret;
 }
 
-static LYD_FORMAT
-detect_data_format(char *filepath)
-{
-    size_t len;
-
-    /* detect input format according to file suffix */
-    len = strlen(filepath);
-    for (; isspace(filepath[len - 1]); len--, filepath[len] = '\0'); /* remove trailing whitespaces */
-    if (len >= 5 && !strcmp(&filepath[len - 4], ".xml")) {
-        return LYD_XML;
-#if 0
-    } else if (len >= 6 && !strcmp(&filepath[len - 5], ".json")) {
-        return LYD_JSON;
-    } else if (len >= 5 && !strcmp(&filepath[len - 4], ".lyb")) {
-        return LYD_LYB;
-#endif
-    } else {
-        return 0;
-    }
-}
-
 static int
 parse_data(char *filepath, int *options, const struct lyd_node *tree, const char *rpc_act_file,
            struct lyd_node **result)
 {
-    LYD_FORMAT informat = 0;
     struct lyd_node *data = NULL, *rpc_act = NULL;
     int opts = *options;
+    struct ly_in *in;
 
-    /* detect input format according to file suffix */
-    informat = detect_data_format(filepath);
-    if (!informat) {
-        fprintf(stderr, "Unable to resolve format of the input file, please add \".xml\", \".json\", or \".lyb\" suffix.\n");
+    if (ly_in_new_filepath(filepath, 0, &in)) {
+        fprintf(stderr, "Unable to open input YANG data file \"%s\".", filepath);
         return EXIT_FAILURE;
     }
 
-    ly_err_clean(ctx, NULL);
-
 #if 0
     if ((opts & LYD_OPT_TYPEMASK) == LYD_OPT_TYPEMASK) {
         /* automatically detect data type from the data top level */
@@ -671,11 +646,14 @@
             data = lyd_parse_path(ctx, filepath, informat, opts, rpc_act_file);
         } else {
 #endif
-            data = lyd_parse_path(ctx, filepath, informat, opts);
+
+            lyd_parse_data(ctx, in, 0, opts, 0, &data);
 #if 0
         }
     }
 #endif
+    ly_in_free(in, 0);
+
     lyd_free_all(rpc_act);
 
     if (ly_err_first(ctx)) {
@@ -698,7 +676,6 @@
     const char *out_path = NULL;
     struct lyd_node *data = NULL;
     struct lyd_node *tree = NULL;
-    const struct lyd_node **trees = NULL;
     LYD_FORMAT outformat = 0;
     struct ly_out *out = NULL;
     static struct option long_options[] = {
@@ -845,7 +822,7 @@
     }
 
     if (outformat) {
-        ret = lyd_print(out, data, outformat, LYDP_WITHSIBLINGS | LYDP_FORMAT | printopt);
+        ret = lyd_print(out, data, outformat, LYD_PRINT_WITHSIBLINGS | LYD_PRINT_FORMAT | printopt);
         ret = ret < 0 ? ret * (-1) : 0;
     }
 
diff --git a/tools/lint/main_ni.c b/tools/lint/main_ni.c
index d2109b2..202fff5 100644
--- a/tools/lint/main_ni.c
+++ b/tools/lint/main_ni.c
@@ -518,7 +518,7 @@
             break;
 #endif
         case 's':
-            options_parser |= LYD_OPT_STRICT;
+            options_parser |= LYD_PARSE_STRICT;
             break;
         case 't':
             if (!strcmp(optarg, "auto")) {
@@ -787,18 +787,19 @@
 
         /* prepare operational datastore when specified for RPC/Notification */
         if (oper_file) {
-            /* get the file format */
-            if (!get_fileformat(oper_file, NULL, &informat_d)) {
-                goto cleanup;
-            } else if (!informat_d) {
-                fprintf(stderr, "yanglint error: The operational data are expected in XML or JSON format.\n");
+            struct ly_in *in;
+            tree = NULL;
+
+            if (ly_in_new_filepath(oper_file, 0, &in)) {
+                fprintf(stderr, "yanglint error: Unable to open an operational data file \"%s\".\n", oper_file);
                 goto cleanup;
             }
-            tree = lyd_parse_path(ctx, oper_file, informat_d, LYD_OPT_PARSE_ONLY);
-            if (!tree) {
+            if (lyd_parse_data(ctx, in, 0, LYD_PARSE_ONLY, 0, &tree) || !tree) {
                 fprintf(stderr, "yanglint error: Failed to parse the operational datastore file for RPC/Notification validation.\n");
+                ly_in_free(in, 0);
                 goto cleanup;
             }
+            ly_in_free(in, 0);
         }
 
         for (data_item = data, data_prev = NULL; data_item; data_prev = data_item, data_item = data_item->next) {
@@ -964,10 +965,18 @@
 #else
             {
 #endif
-                data_item->tree = lyd_parse_path(ctx, data_item->filename, data_item->format, options_parser);
-            }
-            if (ly_err_first(ctx)) {
-                goto cleanup;
+                /* TODO optimize use of ly_in in the loop */
+                struct ly_in *in;
+                if (ly_in_new_filepath(data_item->filename, 0, &in)) {
+                    fprintf(stderr, "yanglint error: input data file \"%s\".\n", data_item->filename);
+                    goto cleanup;
+                }
+                if (lyd_parse_data(ctx, in, 0, options_parser, 0, &data_item->tree)) {
+                    fprintf(stderr, "yanglint error: Failed to parse input data file \"%s\".\n", data_item->filename);
+                    ly_in_free(in, 0);
+                    goto cleanup;
+                }
+                ly_in_free(in, 0);
             }
 #if 0
             if (merge && data != data_item) {
@@ -1058,7 +1067,7 @@
                     }
                 }
 #endif
-                lyd_print(out, data_item->tree, outformat_d, LYDP_WITHSIBLINGS | LYDP_FORMAT /* TODO defaults | options_dflt */);
+                lyd_print(out, data_item->tree, outformat_d, LYD_PRINT_WITHSIBLINGS | LYD_PRINT_FORMAT /* TODO defaults | options_dflt */);
 #if 0
                 if (envelope_s) {
                     if (data_item->type == LYD_OPT_RPC && data_item->tree->schema->nodetype != LYS_RPC) {