parser UPDATE anydata is an inner node
diff --git a/src/parser_common.c b/src/parser_common.c
index 072a4e7..a5daeb7 100644
--- a/src/parser_common.c
+++ b/src/parser_common.c
@@ -88,22 +88,24 @@
         return LY_SUCCESS;
     }
 
-    if (!(int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_NOTIF | LYD_INTOPT_REPLY))) {
-        LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent %s \"%s\" node when not parsing any operation.",
-                lys_nodetype2str(iter->schema->nodetype), iter->schema->name);
-        return LY_EINVAL;
-    } else if ((iter->schema->nodetype == LYS_RPC) && !(int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_REPLY))) {
-        LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent RPC \"%s\" node when not parsing RPC nor rpc-reply.",
-                iter->schema->name);
-        return LY_EINVAL;
-    } else if ((iter->schema->nodetype == LYS_ACTION) && !(int_opts & (LYD_INTOPT_ACTION | LYD_INTOPT_REPLY))) {
-        LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent action \"%s\" node when not parsing action nor rpc-reply.",
-                iter->schema->name);
-        return LY_EINVAL;
-    } else if ((iter->schema->nodetype == LYS_NOTIF) && !(int_opts & LYD_INTOPT_NOTIF)) {
-        LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent notification \"%s\" node when not parsing a notification.",
-                iter->schema->name);
-        return LY_EINVAL;
+    if (!(int_opts & LYD_INTOPT_ANY)) {
+        if (!(int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_NOTIF | LYD_INTOPT_REPLY))) {
+            LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent %s \"%s\" node when not parsing any operation.",
+                    lys_nodetype2str(iter->schema->nodetype), iter->schema->name);
+            return LY_EINVAL;
+        } else if ((iter->schema->nodetype == LYS_RPC) && !(int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_REPLY))) {
+            LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent RPC \"%s\" node when not parsing RPC nor rpc-reply.",
+                    iter->schema->name);
+            return LY_EINVAL;
+        } else if ((iter->schema->nodetype == LYS_ACTION) && !(int_opts & (LYD_INTOPT_ACTION | LYD_INTOPT_REPLY))) {
+            LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent action \"%s\" node when not parsing action nor rpc-reply.",
+                    iter->schema->name);
+            return LY_EINVAL;
+        } else if ((iter->schema->nodetype == LYS_NOTIF) && !(int_opts & LYD_INTOPT_NOTIF)) {
+            LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent notification \"%s\" node when not parsing a notification.",
+                    iter->schema->name);
+            return LY_EINVAL;
+        }
     }
 
     *op = (struct lyd_node *)iter;
diff --git a/src/parser_internal.h b/src/parser_internal.h
index 4863145..458d297 100644
--- a/src/parser_internal.h
+++ b/src/parser_internal.h
@@ -227,17 +227,36 @@
  * @param[in] in Input structure.
  * @param[in] parse_opts Options for parser, see @ref dataparseroptions.
  * @param[in] val_opts Options for the validation phase, see @ref datavalidationoptions.
- * @param[in] data_type Expected data type of the data.
- * @param[out] envp Individual parsed envelopes tree, returned only by specific @p data_type and possibly even if
- * an error occurs later.
+ * @param[in] int_opts Internal data parser options.
  * @param[out] parsed Set to add all the parsed siblings into.
  * @param[out] subtree_sibling Set if ::LYD_PARSE_SUBTREE is used and another subtree is following in @p in.
  * @param[out] lydctx_p Data parser context to finish validation.
  * @return LY_ERR value.
  */
 LY_ERR lyd_parse_xml(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct lyd_node *parent,
+        struct lyd_node **first_p, struct ly_in *in, uint32_t parse_opts, uint32_t val_opts, uint32_t int_opts,
+        struct ly_set *parsed, ly_bool *subtree_sibling, struct lyd_ctx **lydctx_p);
+
+/**
+ * @brief Parse XML string as a NETCONF message.
+ *
+ * @param[in] ctx libyang context.
+ * @param[in] ext Optional extension instance to parse data following the schema tree specified in the extension instance
+ * @param[in] parent Parent to connect the parsed nodes to, if any.
+ * @param[in,out] first_p Pointer to the first top-level parsed node, used only if @p parent is NULL.
+ * @param[in] in Input structure.
+ * @param[in] parse_opts Options for parser, see @ref dataparseroptions.
+ * @param[in] val_opts Options for the validation phase, see @ref datavalidationoptions.
+ * @param[in] data_type Expected NETCONF data type of the data.
+ * @param[out] envp Individual parsed envelopes tree, may be returned possibly even on an error.
+ * @param[out] parsed Set to add all the parsed siblings into.
+ * @param[out] subtree_sibling Set if ::LYD_PARSE_SUBTREE is used and another subtree is following in @p in.
+ * @param[out] lydctx_p Data parser context to finish validation.
+ * @return LY_ERR value.
+ */
+LY_ERR lyd_parse_xml_netconf(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct lyd_node *parent,
         struct lyd_node **first_p, struct ly_in *in, uint32_t parse_opts, uint32_t val_opts, enum lyd_type data_type,
-        struct lyd_node **envp, struct ly_set *parsed, ly_bool *subtree_sibling, struct lyd_ctx **lydctx_p);
+        struct lyd_node **envp, struct ly_set *parsed, struct lyd_ctx **lydctx_p);
 
 /**
  * @brief Parse JSON string as a YANG data tree.
@@ -249,14 +268,14 @@
  * @param[in] in Input structure.
  * @param[in] parse_opts Options for parser, see @ref dataparseroptions.
  * @param[in] val_opts Options for the validation phase, see @ref datavalidationoptions.
- * @param[in] data_type Expected data type of the data.
+ * @param[in] int_opts Internal data parser options.
  * @param[out] parsed Set to add all the parsed siblings into.
  * @param[out] subtree_sibling Set if ::LYD_PARSE_SUBTREE is used and another subtree is following in @p in.
  * @param[out] lydctx_p Data parser context to finish validation.
  * @return LY_ERR value.
  */
 LY_ERR lyd_parse_json(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct lyd_node *parent,
-        struct lyd_node **first_p, struct ly_in *in, uint32_t parse_opts, uint32_t val_opts, enum lyd_type data_type,
+        struct lyd_node **first_p, struct ly_in *in, uint32_t parse_opts, uint32_t val_opts, uint32_t int_opts,
         struct ly_set *parsed, ly_bool *subtree_sibling, struct lyd_ctx **lydctx_p);
 
 /**
@@ -269,14 +288,14 @@
  * @param[in] in Input structure.
  * @param[in] parse_opts Options for parser, see @ref dataparseroptions.
  * @param[in] val_opts Options for the validation phase, see @ref datavalidationoptions.
- * @param[in] data_type Expected data type of the data.
+ * @param[in] int_opts Internal data parser options.
  * @param[out] parsed Set to add all the parsed siblings into.
  * @param[out] subtree_sibling Set if ::LYD_PARSE_SUBTREE is used and another subtree is following in @p in.
  * @param[out] lydctx_p Data parser context to finish validation.
  * @return LY_ERR value.
  */
 LY_ERR lyd_parse_lyb(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct lyd_node *parent,
-        struct lyd_node **first_p, struct ly_in *in, uint32_t parse_opts, uint32_t val_opts, enum lyd_type data_type,
+        struct lyd_node **first_p, struct ly_in *in, uint32_t parse_opts, uint32_t val_opts, uint32_t int_opts,
         struct ly_set *parsed, ly_bool *subtree_sibling, struct lyd_ctx **lydctx_p);
 
 /**
diff --git a/src/parser_json.c b/src/parser_json.c
index 341fd7e..d14151e 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -259,7 +259,7 @@
         if (parent->schema) {
             mod = parent->schema->module;
         }
-    } else {
+    } else if (!(lydctx->int_opts & LYD_INTOPT_ANY)) {
         LOGVAL(lydctx->jsonctx->ctx, LYVE_SYNTAX_JSON, "Top-level JSON object member \"%.*s\" must be namespace-qualified.",
                 (int)(is_attr ? name_len + 1 : name_len), is_attr ? name - 1 : name);
         ret = LY_EVALID;
@@ -1216,17 +1216,7 @@
                 (*status != LYJSON_NUMBER) && (*status != LYJSON_STRING) && (*status != LYJSON_FALSE) &&
                 (*status != LYJSON_TRUE) && (*status != LYJSON_NULL), LY_ENOT);
     } else {
-        LY_CHECK_RET((*status != LYJSON_OBJECT) && (*status != LYJSON_OBJECT_EMPTY) && (*status != LYJSON_ARRAY), LY_ENOT);
-    }
-
-    if ((snode->nodetype == LYS_ANYDATA) && (*status == LYJSON_ARRAY)) {
-        /* only special anydata [null] allowed, 2 more moves are needed */
-        LY_CHECK_RET(lyjson_ctx_next(lydctx->jsonctx, status));
-        LY_CHECK_RET(*status != LYJSON_NULL, LY_ENOT);
-        LY_CHECK_RET(lyjson_ctx_next(lydctx->jsonctx, status));
-        LY_CHECK_RET(*status != LYJSON_ARRAY_CLOSED, LY_ENOT);
-
-        return lyd_create_any(snode, "[null]", LYD_ANYDATA_JSON, 0, node);
+        LY_CHECK_RET((*status != LYJSON_OBJECT) && (*status != LYJSON_OBJECT_EMPTY), LY_ENOT);
     }
 
     /* create any node */
@@ -1597,7 +1587,7 @@
         case LYS_RPC:
         case LYS_ANYDATA:
         case LYS_ANYXML:
-            if (snode->nodetype & (LYS_LEAF | LYS_ANYXML)) {
+            if ((snode->nodetype == LYS_LEAF) || (snode->nodetype == LYS_ANYXML)) {
                 if (status == LYJSON_ARRAY) {
                     expected = "name/[null]";
                 } else {
@@ -1707,39 +1697,18 @@
 
 LY_ERR
 lyd_parse_json(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct lyd_node *parent,
-        struct lyd_node **first_p, struct ly_in *in, uint32_t parse_opts, uint32_t val_opts, enum lyd_type data_type,
+        struct lyd_node **first_p, struct ly_in *in, uint32_t parse_opts, uint32_t val_opts, uint32_t int_opts,
         struct ly_set *parsed, ly_bool *subtree_sibling, struct lyd_ctx **lydctx_p)
 {
     LY_ERR rc = LY_SUCCESS;
     struct lyd_json_ctx *lydctx = NULL;
     enum LYJSON_PARSER_STATUS status;
-    uint32_t int_opts = 0;
 
     rc = lyd_parse_json_init(ctx, in, parse_opts, val_opts, &lydctx, &status);
     LY_CHECK_GOTO(rc || status == LYJSON_END || status == LYJSON_OBJECT_EMPTY, cleanup);
 
     assert(status == LYJSON_OBJECT);
 
-    switch (data_type) {
-    case LYD_TYPE_DATA_YANG:
-        if (!(parse_opts & LYD_PARSE_SUBTREE)) {
-            int_opts = LYD_INTOPT_WITH_SIBLINGS;
-        }
-        break;
-    case LYD_TYPE_RPC_YANG:
-        int_opts = LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_NO_SIBLINGS;
-        break;
-    case LYD_TYPE_NOTIF_YANG:
-        int_opts = LYD_INTOPT_NOTIF | LYD_INTOPT_NO_SIBLINGS;
-        break;
-    case LYD_TYPE_REPLY_YANG:
-        int_opts = LYD_INTOPT_REPLY | LYD_INTOPT_NO_SIBLINGS;
-        break;
-    default:
-        LOGINT(ctx);
-        rc = LY_EINT;
-        goto cleanup;
-    }
     lydctx->int_opts = int_opts;
     lydctx->ext = ext;
 
diff --git a/src/parser_lyb.c b/src/parser_lyb.c
index 2201269..58e76b2 100644
--- a/src/parser_lyb.c
+++ b/src/parser_lyb.c
@@ -41,10 +41,6 @@
 #include "validation.h"
 #include "xml.h"
 
-static LY_ERR _lyd_parse_lyb(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct lyd_node *parent,
-        struct lyd_node **first_p, struct ly_in *in, uint32_t parse_opts, uint32_t val_opts, uint32_t int_opts,
-        struct ly_set *parsed, struct lyd_ctx **lydctx_p);
-
 static LY_ERR lyb_parse_siblings(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, struct lyd_node **first_p,
         struct ly_set *parsed);
 
@@ -908,46 +904,6 @@
 }
 
 /**
- * @brief Parse the context of anydata/anyxml node.
- *
- * @param[in] ctx libyang context.
- * @param[in] data LYB data to parse.
- * @param[out] tree Parsed tree.
- * @return LY_ERR value.
- */
-static LY_ERR
-lyb_parse_any_content(const struct ly_ctx *ctx, const char *data, struct lyd_node **tree)
-{
-    LY_ERR ret;
-    uint32_t prev_lo;
-    struct ly_in *in;
-    struct lyd_ctx *lydctx = NULL;
-
-    *tree = NULL;
-
-    LY_CHECK_RET(ly_in_new_memory(data, &in));
-
-    /* turn logging off */
-    prev_lo = ly_log_options(0);
-
-    ret = _lyd_parse_lyb(ctx, NULL, NULL, tree, in, LYD_PARSE_ONLY | LYD_PARSE_OPAQ | LYD_PARSE_STRICT, 0,
-            LYD_INTOPT_ANY | LYD_INTOPT_WITH_SIBLINGS, NULL, &lydctx);
-
-    /* turn logging on again */
-    ly_log_options(prev_lo);
-
-    ly_in_free(in, 0);
-    if (lydctx) {
-        lydctx->free(lydctx);
-    }
-    if (ret) {
-        lyd_free_siblings(*tree);
-        *tree = NULL;
-    }
-    return ret;
-}
-
-/**
  * @brief Insert new node to @p parsed set.
  *
  * Also if needed, correct @p first_p.
@@ -1243,9 +1199,11 @@
         struct lyd_node **first_p, struct ly_set *parsed)
 {
     LY_ERR ret;
-    struct lyd_node *node = NULL, *tree;
+    struct lyd_node *node = NULL, *tree = NULL;
     struct lyd_meta *meta = NULL;
     LYD_ANYDATA_VALUETYPE value_type;
+    struct ly_in *in;
+    struct lyd_ctx *lydctx = NULL;
     char *value = NULL;
     uint32_t flags;
     const struct ly_ctx *ctx = lybctx->lybctx->ctx;
@@ -1256,8 +1214,7 @@
 
     /* parse value type */
     lyb_read_number(&value_type, sizeof value_type, sizeof value_type, lybctx->lybctx);
-    if (value_type == LYD_ANYDATA_DATATREE) {
-        /* invalid situation */
+    if ((value_type == LYD_ANYDATA_DATATREE) || ((snode->nodetype == LYS_ANYDATA) && (value_type != LYD_ANYDATA_LYB))) {
         LOGINT(ctx);
         ret = LY_EINT;
         goto error;
@@ -1268,13 +1225,20 @@
     LY_CHECK_GOTO(ret, error);
 
     if (value_type == LYD_ANYDATA_LYB) {
-        /* try to parse LYB into a data tree */
-        if (!lyb_parse_any_content(ctx, value, &tree)) {
-            /* successfully parsed */
-            free(value);
-            value = (char *)tree;
-            value_type = LYD_ANYDATA_DATATREE;
+        /* parse LYB into a data tree */
+        LY_CHECK_RET(ly_in_new_memory(value, &in));
+        ret = lyd_parse_lyb(ctx, NULL, NULL, &tree, in, LYD_PARSE_ONLY | LYD_PARSE_OPAQ | LYD_PARSE_STRICT, 0,
+                LYD_INTOPT_ANY | LYD_INTOPT_WITH_SIBLINGS, NULL, NULL, &lydctx);
+        ly_in_free(in, 0);
+        if (lydctx) {
+            lydctx->free(lydctx);
         }
+        LY_CHECK_ERR_GOTO(ret, lyd_free_siblings(tree), error);
+
+        /* use the parsed tree as the value */
+        free(value);
+        value = (char *)tree;
+        value_type = LYD_ANYDATA_DATATREE;
     }
 
     /* create the node */
@@ -1672,10 +1636,10 @@
     return LY_SUCCESS;
 }
 
-static LY_ERR
-_lyd_parse_lyb(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct lyd_node *parent,
+LY_ERR
+lyd_parse_lyb(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct lyd_node *parent,
         struct lyd_node **first_p, struct ly_in *in, uint32_t parse_opts, uint32_t val_opts, uint32_t int_opts,
-        struct ly_set *parsed, struct lyd_ctx **lydctx_p)
+        struct ly_set *parsed, ly_bool *subtree_sibling, struct lyd_ctx **lydctx_p)
 {
     LY_ERR rc = LY_SUCCESS;
     struct lyd_lyb_ctx *lybctx;
@@ -1683,6 +1647,12 @@
     assert(!(parse_opts & ~LYD_PARSE_OPTS_MASK));
     assert(!(val_opts & ~LYD_VALIDATE_OPTS_MASK));
 
+    LY_CHECK_ARG_RET(ctx, !(parse_opts & LYD_PARSE_SUBTREE), LY_EINVAL);
+
+    if (subtree_sibling) {
+        *subtree_sibling = 0;
+    }
+
     lybctx = calloc(1, sizeof *lybctx);
     LY_CHECK_ERR_RET(!lybctx, LOGMEM(ctx), LY_EMEM);
     lybctx->lybctx = calloc(1, sizeof *lybctx->lybctx);
@@ -1742,42 +1712,6 @@
     return rc;
 }
 
-LY_ERR
-lyd_parse_lyb(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct lyd_node *parent,
-        struct lyd_node **first_p, struct ly_in *in, uint32_t parse_opts, uint32_t val_opts, enum lyd_type data_type,
-        struct ly_set *parsed, ly_bool *subtree_sibling, struct lyd_ctx **lydctx_p)
-{
-    uint32_t int_opts;
-
-    assert(!(parse_opts & ~LYD_PARSE_OPTS_MASK));
-    assert(!(val_opts & ~LYD_VALIDATE_OPTS_MASK));
-
-    LY_CHECK_ARG_RET(ctx, !(parse_opts & LYD_PARSE_SUBTREE), LY_EINVAL);
-
-    switch (data_type) {
-    case LYD_TYPE_DATA_YANG:
-        int_opts = LYD_INTOPT_WITH_SIBLINGS;
-        break;
-    case LYD_TYPE_RPC_YANG:
-        int_opts = LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_NO_SIBLINGS;
-        break;
-    case LYD_TYPE_NOTIF_YANG:
-        int_opts = LYD_INTOPT_NOTIF | LYD_INTOPT_NO_SIBLINGS;
-        break;
-    case LYD_TYPE_REPLY_YANG:
-        int_opts = LYD_INTOPT_REPLY | LYD_INTOPT_NO_SIBLINGS;
-        break;
-    default:
-        LOGINT(ctx);
-        return LY_EINT;
-    }
-
-    if (subtree_sibling) {
-        *subtree_sibling = 0;
-    }
-    return _lyd_parse_lyb(ctx, ext, parent, first_p, in, parse_opts, val_opts, int_opts, parsed, lydctx_p);
-}
-
 LIBYANG_API_DEF int
 lyd_lyb_data_length(const char *data)
 {
diff --git a/src/parser_xml.c b/src/parser_xml.c
index ff91715..ba707f6 100644
--- a/src/parser_xml.c
+++ b/src/parser_xml.c
@@ -968,6 +968,87 @@
     return rc;
 }
 
+LY_ERR
+lyd_parse_xml(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct lyd_node *parent,
+        struct lyd_node **first_p, struct ly_in *in, uint32_t parse_opts, uint32_t val_opts, uint32_t int_opts,
+        struct ly_set *parsed, ly_bool *subtree_sibling, struct lyd_ctx **lydctx_p)
+{
+    LY_ERR rc = LY_SUCCESS;
+    struct lyd_xml_ctx *lydctx;
+    ly_bool parsed_data_nodes = 0;
+    enum LYXML_PARSER_STATUS status;
+
+    assert(ctx && in && lydctx_p);
+    assert(!(parse_opts & ~LYD_PARSE_OPTS_MASK));
+    assert(!(val_opts & ~LYD_VALIDATE_OPTS_MASK));
+
+    /* init context */
+    lydctx = calloc(1, sizeof *lydctx);
+    LY_CHECK_ERR_RET(!lydctx, LOGMEM(ctx), LY_EMEM);
+    LY_CHECK_GOTO(rc = lyxml_ctx_new(ctx, in, &lydctx->xmlctx), cleanup);
+    lydctx->parse_opts = parse_opts;
+    lydctx->val_opts = val_opts;
+    lydctx->int_opts = int_opts;
+    lydctx->free = lyd_xml_ctx_free;
+    lydctx->ext = ext;
+
+    /* find the operation node if it exists already */
+    LY_CHECK_GOTO(rc = lyd_parser_find_operation(parent, int_opts, &lydctx->op_node), cleanup);
+
+    /* parse XML data */
+    while (lydctx->xmlctx->status == LYXML_ELEMENT) {
+        LY_CHECK_GOTO(rc = lydxml_subtree_r(lydctx, parent, first_p, parsed), cleanup);
+        parsed_data_nodes = 1;
+
+        if (!(int_opts & LYD_INTOPT_WITH_SIBLINGS)) {
+            break;
+        }
+    }
+
+    /* check final state */
+    if ((int_opts & LYD_INTOPT_NO_SIBLINGS) && (lydctx->xmlctx->status == LYXML_ELEMENT)) {
+        LOGVAL(ctx, LYVE_SYNTAX, "Unexpected sibling node.");
+        rc = LY_EVALID;
+        goto cleanup;
+    }
+    if ((int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_NOTIF | LYD_INTOPT_REPLY)) && !lydctx->op_node) {
+        LOGVAL(ctx, LYVE_DATA, "Missing the operation node.");
+        rc = LY_EVALID;
+        goto cleanup;
+    }
+
+    if (!parsed_data_nodes) {
+        /* no data nodes were parsed */
+        lydctx->op_node = NULL;
+    }
+
+    if (parse_opts & LYD_PARSE_SUBTREE) {
+        /* check for a sibling element */
+        assert(subtree_sibling);
+        if (!lyxml_ctx_peek(lydctx->xmlctx, &status) && (status == LYXML_ELEMENT)) {
+            *subtree_sibling = 1;
+        } else {
+            *subtree_sibling = 0;
+        }
+    }
+
+cleanup:
+    /* there should be no unres stored if validation should be skipped */
+    assert(!(parse_opts & LYD_PARSE_ONLY) || (!lydctx->node_types.count && !lydctx->meta_types.count &&
+            !lydctx->node_when.count));
+
+    if (rc) {
+        lyd_xml_ctx_free((struct lyd_ctx *)lydctx);
+    } else {
+        *lydctx_p = (struct lyd_ctx *)lydctx;
+
+        /* the XML context is no more needed, freeing it also stops logging line numbers which would be confusing now */
+        lyxml_ctx_free(lydctx->xmlctx);
+        lydctx->xmlctx = NULL;
+    }
+    return rc;
+}
+
 /**
  * @brief Parse all expected non-data XML elements of a NETCONF rpc message.
  *
@@ -1601,20 +1682,23 @@
 }
 
 LY_ERR
-lyd_parse_xml(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct lyd_node *parent,
+lyd_parse_xml_netconf(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct lyd_node *parent,
         struct lyd_node **first_p, struct ly_in *in, uint32_t parse_opts, uint32_t val_opts, enum lyd_type data_type,
-        struct lyd_node **envp, struct ly_set *parsed, ly_bool *subtree_sibling, struct lyd_ctx **lydctx_p)
+        struct lyd_node **envp, struct ly_set *parsed, struct lyd_ctx **lydctx_p)
 {
     LY_ERR rc = LY_SUCCESS;
     struct lyd_xml_ctx *lydctx;
     uint32_t i, int_opts = 0, close_elem = 0;
     ly_bool parsed_data_nodes = 0;
-    enum LYXML_PARSER_STATUS status;
 
     assert(ctx && in && lydctx_p);
     assert(!(parse_opts & ~LYD_PARSE_OPTS_MASK));
     assert(!(val_opts & ~LYD_VALIDATE_OPTS_MASK));
 
+    assert((data_type == LYD_TYPE_RPC_NETCONF) || (data_type == LYD_TYPE_NOTIF_NETCONF) ||
+            (data_type == LYD_TYPE_REPLY_NETCONF));
+    assert(!(parse_opts & LYD_PARSE_SUBTREE));
+
     /* init context */
     lydctx = calloc(1, sizeof *lydctx);
     LY_CHECK_ERR_RET(!lydctx, LOGMEM(ctx), LY_EMEM);
@@ -1625,20 +1709,6 @@
     lydctx->ext = ext;
 
     switch (data_type) {
-    case LYD_TYPE_DATA_YANG:
-        if (!(parse_opts & LYD_PARSE_SUBTREE)) {
-            int_opts = LYD_INTOPT_WITH_SIBLINGS;
-        }
-        break;
-    case LYD_TYPE_RPC_YANG:
-        int_opts = LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_NO_SIBLINGS;
-        break;
-    case LYD_TYPE_NOTIF_YANG:
-        int_opts = LYD_INTOPT_NOTIF | LYD_INTOPT_NO_SIBLINGS;
-        break;
-    case LYD_TYPE_REPLY_YANG:
-        int_opts = LYD_INTOPT_REPLY | LYD_INTOPT_NO_SIBLINGS;
-        break;
     case LYD_TYPE_RPC_NETCONF:
         assert(!parent);
         rc = lydxml_env_netconf_rpc(lydctx->xmlctx, envp, &int_opts, &close_elem);
@@ -1663,7 +1733,12 @@
         }
         LY_CHECK_GOTO(rc, cleanup);
         break;
+    default:
+        LOGINT(ctx);
+        rc = LY_EINT;
+        goto cleanup;
     }
+
     lydctx->int_opts = int_opts;
 
     /* find the operation node if it exists already */
@@ -1709,16 +1784,6 @@
         lydctx->op_node = NULL;
     }
 
-    if (parse_opts & LYD_PARSE_SUBTREE) {
-        /* check for a sibling element */
-        assert(subtree_sibling);
-        if (!lyxml_ctx_peek(lydctx->xmlctx, &status) && (status == LYXML_ELEMENT)) {
-            *subtree_sibling = 1;
-        } else {
-            *subtree_sibling = 0;
-        }
-    }
-
 cleanup:
     /* there should be no unres stored if validation should be skipped */
     assert(!(parse_opts & LYD_PARSE_ONLY) || (!lydctx->node_types.count && !lydctx->meta_types.count &&
diff --git a/src/printer_json.c b/src/printer_json.c
index 3c7a6fd..6cfd330 100644
--- a/src/printer_json.c
+++ b/src/printer_json.c
@@ -537,6 +537,10 @@
 
     assert(any->schema->nodetype & LYD_NODE_ANY);
 
+    if ((any->schema->nodetype == LYS_ANYDATA) && (any->value_type != LYD_ANYDATA_DATATREE)) {
+        LOGINT_RET(pctx->ctx);
+    }
+
     if (any->value_type == LYD_ANYDATA_LYB) {
         uint32_t parser_options = LYD_PARSE_ONLY | LYD_PARSE_OPAQ | LYD_PARSE_STRICT;
 
@@ -605,7 +609,7 @@
             }
         } else {
             /* print as a string */
-            ly_print_(pctx->out, "\"%s\"", any->value.str);
+            json_print_string(pctx->out, any->value.str);
         }
         break;
     case LYD_ANYDATA_LYB:
diff --git a/src/printer_lyb.c b/src/printer_lyb.c
index 62902de..7928262 100644
--- a/src/printer_lyb.c
+++ b/src/printer_lyb.c
@@ -1054,8 +1054,12 @@
     struct ly_out *out2 = NULL;
     struct lylyb_ctx *lybctx = lyd_lybctx->lybctx;
 
+    if ((anydata->schema->nodetype == LYS_ANYDATA) && (anydata->value_type != LYD_ANYDATA_DATATREE)) {
+        LOGINT_RET(lybctx->ctx);
+    }
+
     if (anydata->value_type == LYD_ANYDATA_DATATREE) {
-        /* will be printed as a nested LYB data tree */
+        /* will be printed as a nested LYB data tree because the used modules need to be written */
         value_type = LYD_ANYDATA_LYB;
     } else {
         value_type = anydata->value_type;
diff --git a/src/printer_xml.c b/src/printer_xml.c
index 058bc44..c7a6c85 100644
--- a/src/printer_xml.c
+++ b/src/printer_xml.c
@@ -388,6 +388,10 @@
     uint32_t prev_opts, prev_lo;
     LY_ERR ret;
 
+    if ((node->schema->nodetype == LYS_ANYDATA) && (node->value_type != LYD_ANYDATA_DATATREE)) {
+        LOGINT_RET(pctx->ctx);
+    }
+
     xml_print_node_open(pctx, &node->node);
 
     if (!any->value.tree) {
diff --git a/src/tree_data.c b/src/tree_data.c
index a082d8a..e3d7ac9 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -1,9 +1,10 @@
 /**
  * @file tree_data.c
  * @author Radek Krejci <rkrejci@cesnet.cz>
+ * @author Michal Vasko <mvasko@cesnet.cz>
  * @brief Data tree functions
  *
- * Copyright (c) 2015 - 2020 CESNET, z.s.p.o.
+ * Copyright (c) 2015 - 2022 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.
@@ -99,7 +100,7 @@
     struct lyd_ctx *lydctx = NULL;
     struct ly_set parsed = {0};
     struct lyd_node *first;
-    uint32_t i;
+    uint32_t i, int_opts = 0;
     ly_bool subtree_sibling = 0;
 
     assert(ctx && (parent || first_p));
@@ -112,18 +113,23 @@
     /* remember input position */
     in->func_start = in->current;
 
+    /* set internal options */
+    if (!(parse_opts & LYD_PARSE_SUBTREE)) {
+        int_opts = LYD_INTOPT_WITH_SIBLINGS;
+    }
+
     /* parse the data */
     switch (format) {
     case LYD_XML:
-        rc = lyd_parse_xml(ctx, ext, parent, first_p, in, parse_opts, val_opts, LYD_TYPE_DATA_YANG, NULL, &parsed,
+        rc = lyd_parse_xml(ctx, ext, parent, first_p, in, parse_opts, val_opts, int_opts, &parsed,
                 &subtree_sibling, &lydctx);
         break;
     case LYD_JSON:
-        rc = lyd_parse_json(ctx, ext, parent, first_p, in, parse_opts, val_opts, LYD_TYPE_DATA_YANG, &parsed,
+        rc = lyd_parse_json(ctx, ext, parent, first_p, in, parse_opts, val_opts, int_opts, &parsed,
                 &subtree_sibling, &lydctx);
         break;
     case LYD_LYB:
-        rc = lyd_parse_lyb(ctx, ext, parent, first_p, in, parse_opts, val_opts, LYD_TYPE_DATA_YANG, &parsed,
+        rc = lyd_parse_lyb(ctx, ext, parent, first_p, in, parse_opts, val_opts, int_opts, &parsed,
                 &subtree_sibling, &lydctx);
         break;
     case LYD_UNKNOWN:
@@ -288,7 +294,7 @@
     struct lyd_ctx *lydctx = NULL;
     struct ly_set parsed = {0};
     struct lyd_node *first = NULL, *envp = NULL;
-    uint32_t i, parse_opts, val_opts;
+    uint32_t i, parse_opts, val_opts, int_opts = 0;
 
     if (!ctx) {
         ctx = LYD_CTX(parent);
@@ -305,20 +311,25 @@
     /* remember input position */
     in->func_start = in->current;
 
-    /* check params based on the data type */
-    if ((data_type == LYD_TYPE_RPC_NETCONF) || (data_type == LYD_TYPE_NOTIF_NETCONF)) {
-        LY_CHECK_ARG_RET(ctx, format == LYD_XML, !parent, tree, op, LY_EINVAL);
-    } else if (data_type == LYD_TYPE_REPLY_NETCONF) {
-        LY_CHECK_ARG_RET(ctx, format == LYD_XML, parent, parent->schema->nodetype & (LYS_RPC | LYS_ACTION), tree, !op,
-                LY_EINVAL);
-    }
+    /* set parse and validation opts */
     parse_opts = LYD_PARSE_ONLY | LYD_PARSE_STRICT;
     val_opts = 0;
 
-    /* parse the data */
-    switch (format) {
-    case LYD_XML:
-        rc = lyd_parse_xml(ctx, ext, parent, &first, in, parse_opts, val_opts, data_type, &envp, &parsed, NULL, &lydctx);
+    switch (data_type) {
+
+    /* special XML NETCONF data types */
+    case LYD_TYPE_RPC_NETCONF:
+    case LYD_TYPE_NOTIF_NETCONF:
+        LY_CHECK_ARG_RET(ctx, format == LYD_XML, !parent, tree, op, LY_EINVAL);
+    /* fallthrough */
+    case LYD_TYPE_REPLY_NETCONF:
+        if (data_type == LYD_TYPE_REPLY_NETCONF) {
+            LY_CHECK_ARG_RET(ctx, format == LYD_XML, parent, parent->schema->nodetype & (LYS_RPC | LYS_ACTION), tree, !op,
+                    LY_EINVAL);
+        }
+
+        /* parse the NETCONF message */
+        rc = lyd_parse_xml_netconf(ctx, ext, parent, &first, in, parse_opts, val_opts, data_type, &envp, &parsed, &lydctx);
         if (rc && envp) {
             /* special situation when the envelopes were parsed successfully */
             if (tree) {
@@ -328,12 +339,47 @@
             }
             goto cleanup;
         }
+
+        /* set out params correctly */
+        if (tree) {
+            if (envp) {
+                /* special out param meaning */
+                *tree = envp;
+            } else {
+                *tree = parent ? NULL : first;
+            }
+        }
+        if (op) {
+            *op = lydctx->op_node;
+        }
+        goto cleanup;
+
+    /* set internal opts */
+    case LYD_TYPE_RPC_YANG:
+        int_opts = LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_NO_SIBLINGS;
+        break;
+    case LYD_TYPE_NOTIF_YANG:
+        int_opts = LYD_INTOPT_NOTIF | LYD_INTOPT_NO_SIBLINGS;
+        break;
+    case LYD_TYPE_REPLY_YANG:
+        int_opts = LYD_INTOPT_REPLY | LYD_INTOPT_NO_SIBLINGS;
+        break;
+    case LYD_TYPE_DATA_YANG:
+        LOGINT(ctx);
+        rc = LY_EINT;
+        goto cleanup;
+    }
+
+    /* parse the data */
+    switch (format) {
+    case LYD_XML:
+        rc = lyd_parse_xml(ctx, ext, parent, &first, in, parse_opts, val_opts, int_opts, &parsed, NULL, &lydctx);
         break;
     case LYD_JSON:
-        rc = lyd_parse_json(ctx, ext, parent, &first, in, parse_opts, val_opts, data_type, &parsed, NULL, &lydctx);
+        rc = lyd_parse_json(ctx, ext, parent, &first, in, parse_opts, val_opts, int_opts, &parsed, NULL, &lydctx);
         break;
     case LYD_LYB:
-        rc = lyd_parse_lyb(ctx, ext, parent, &first, in, parse_opts, val_opts, data_type, &parsed, NULL, &lydctx);
+        rc = lyd_parse_lyb(ctx, ext, parent, &first, in, parse_opts, val_opts, int_opts, &parsed, NULL, &lydctx);
         break;
     case LYD_UNKNOWN:
         LOGARG(ctx, format);
@@ -344,12 +390,7 @@
 
     /* set out params correctly */
     if (tree) {
-        if (envp) {
-            /* special out param meaning */
-            *tree = envp;
-        } else {
-            *tree = parent ? NULL : first;
-        }
+        *tree = parent ? NULL : first;
     }
     if (op) {
         *op = lydctx->op_node;
diff --git a/src/tree_data_new.c b/src/tree_data_new.c
index b4fb4d6..42b9e9b 100644
--- a/src/tree_data_new.c
+++ b/src/tree_data_new.c
@@ -195,11 +195,85 @@
     return ret;
 }
 
+/**
+ * @brief Convert an anydata value into a datatree.
+ *
+ * @param[in] ctx libyang context.
+ * @param[in] value Anydata value.
+ * @param[in] value_type Anydata @p value type.
+ * @param[out] tree Parsed data tree.
+ * @return LY_ERR value.
+ */
+static LY_ERR
+lyd_create_anydata_datatree(const struct ly_ctx *ctx, const void *value, LYD_ANYDATA_VALUETYPE value_type,
+        struct lyd_node **tree)
+{
+    LY_ERR r;
+    struct ly_in *in = NULL;
+    struct lyd_ctx *lydctx = NULL;
+    uint32_t parse_opts, int_opts;
+
+    *tree = NULL;
+
+    if (!value) {
+        /* empty data tree no matter the value type */
+        return LY_SUCCESS;
+    }
+
+    if (value_type == LYD_ANYDATA_STRING) {
+        /* detect format */
+        if (((char *)value)[0] == '<') {
+            value_type = LYD_ANYDATA_XML;
+        } else if (((char *)value)[0] == '{') {
+            value_type = LYD_ANYDATA_JSON;
+        } else if (!strncmp(value, "lyb", 3)) {
+            value_type = LYD_ANYDATA_LYB;
+        } else {
+            LOGERR(ctx, LY_EINVAL, "Invalid string value of an anydata node.");
+            return LY_EINVAL;
+        }
+    }
+
+    /* create input */
+    LY_CHECK_RET(ly_in_new_memory(value, &in));
+
+    /* set options */
+    parse_opts = LYD_PARSE_ONLY | LYD_PARSE_OPAQ;
+    int_opts = LYD_INTOPT_ANY | LYD_INTOPT_WITH_SIBLINGS;
+
+    switch (value_type) {
+    case LYD_ANYDATA_DATATREE:
+    case LYD_ANYDATA_STRING:
+        /* unreachable */
+        LOGINT_RET(ctx);
+    case LYD_ANYDATA_XML:
+        r = lyd_parse_xml(ctx, NULL, NULL, tree, in, parse_opts, 0, int_opts, NULL, NULL, &lydctx);
+        break;
+    case LYD_ANYDATA_JSON:
+        r = lyd_parse_json(ctx, NULL, NULL, tree, in, parse_opts, 0, int_opts, NULL, NULL, &lydctx);
+        break;
+    case LYD_ANYDATA_LYB:
+        r = lyd_parse_lyb(ctx, NULL, NULL, tree, in, parse_opts | LYD_PARSE_STRICT, 0, int_opts, NULL, NULL, &lydctx);
+        break;
+    }
+    if (lydctx) {
+        lydctx->free(lydctx);
+    }
+    ly_in_free(in, 0);
+
+    if (r) {
+        LOGERR(ctx, LY_EINVAL, "Failed to parse anydata content into a data tree.");
+        return LY_EINVAL;
+    }
+    return LY_SUCCESS;
+}
+
 LY_ERR
 lyd_create_any(const struct lysc_node *schema, const void *value, LYD_ANYDATA_VALUETYPE value_type, ly_bool use_value,
         struct lyd_node **node)
 {
     LY_ERR ret;
+    struct lyd_node *tree;
     struct lyd_node_any *any;
     union lyd_any_value any_val;
 
@@ -212,6 +286,17 @@
     any->prev = &any->node;
     any->flags = LYD_NEW;
 
+    if ((schema->nodetype == LYS_ANYDATA) && (value_type != LYD_ANYDATA_DATATREE)) {
+        /* only a data tree can be stored */
+        LY_CHECK_RET(lyd_create_anydata_datatree(schema->module->ctx, value, value_type, &tree));
+        if (use_value) {
+            free((void *)value);
+        }
+        use_value = 1;
+        value = tree;
+        value_type = LYD_ANYDATA_DATATREE;
+    }
+
     if (use_value) {
         switch (value_type) {
         case LYD_ANYDATA_DATATREE:
diff --git a/tests/utests/data/test_new.c b/tests/utests/data/test_new.c
index b55172f..7cb7ebd 100644
--- a/tests/utests/data/test_new.c
+++ b/tests/utests/data/test_new.c
@@ -153,7 +153,7 @@
     CHECK_LOG_CTX("Inner node (container, notif, RPC, or action) \"l2\" not found.", NULL);
 
     /* anydata */
-    assert_int_equal(lyd_new_any(NULL, mod, "any", "some-value", 0, LYD_ANYDATA_STRING, 0, &node), LY_SUCCESS);
+    assert_int_equal(lyd_new_any(NULL, mod, "any", "{\"node\":\"val\"}", 0, LYD_ANYDATA_STRING, 0, &node), LY_SUCCESS);
     lyd_free_tree(node);
 
     /* key-less list */
diff --git a/tests/utests/data/test_parser_json.c b/tests/utests/data/test_parser_json.c
index a33416f..d341e31 100644
--- a/tests/utests/data/test_parser_json.c
+++ b/tests/utests/data/test_parser_json.c
@@ -282,7 +282,7 @@
     CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
     lyd_free_all(tree);
 
-    data = "{\"a:any\":[null]}";
+    data = "{\"a:any\":{\"node\":20}}";
     CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
     assert_non_null(tree);
     tree = tree->next;