data tree FEATURE creating XML opaque nodes and attributes
diff --git a/doc/transition.dox b/doc/transition.dox
index 310ca46..e82aa00 100644
--- a/doc/transition.dox
+++ b/doc/transition.dox
@@ -351,9 +351,11 @@
  * lyd_new(), lyd_new_output()  | ::lyd_new_inner(), ::lyd_new_list(), ::lyd_new_list2() | Redesigned functionality to better fit new lyd_node structures, creating RPC's output data is now done via a flag parameter of the functions.
  * lyd_new_leaf(), lyd_new_output_leaf() | ::lyd_new_term()       | ^
  * lyd_new_anydata(), lyd_new_output_anydata() | ::lyd_new_any()  | ^
- * lyd_insert_attr()            | ::lyd_new_attr()                | Unify naming used in other functions with the similar functionality.
- * -                            | ::lyd_new_meta()                | Added functionality to store the data (temporarily) not connected with schema definitions.
+ * lyd_insert_attr()            | ::lyd_new_meta()                | Unify naming used in other functions with the similar functionality.
+ * -                            | ::lyd_new_attr()                | Added functionality to store the data (temporarily) not connected with schema definitions.
+ * -                            | ::lyd_new_attr2()               | ^
  * -                            | ::lyd_new_opaq()                | ^
+ * -                            | ::lyd_new_opaq2()               | ^
  * -                            | ::lyd_new_path2()               | Supplement functionality to ::lyd_new_path().
  * lyd_insert()                 | ::lyd_insert_child()            | Renamed to better distinguish from ::lyd_insert_sibling().
  * lyd_new_yangdata()           | TBD                             | Not yet implemented feature.
diff --git a/src/tree_data.c b/src/tree_data.c
index f492f35..a2f0506 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -1115,7 +1115,34 @@
 }
 
 API LY_ERR
-lyd_new_attr(struct lyd_node *parent, const char *module_name, const char *name, const char *val_str,
+lyd_new_opaq2(struct lyd_node *parent, const struct ly_ctx *ctx, const char *name, const char *value,
+        const char *module_ns, struct lyd_node **node)
+{
+    struct lyd_node *ret = NULL;
+
+    LY_CHECK_ARG_RET(ctx, parent || ctx, parent || node, name, module_ns, LY_EINVAL);
+
+    if (!ctx) {
+        ctx = LYD_CTX(parent);
+    }
+    if (!value) {
+        value = "";
+    }
+
+    LY_CHECK_RET(lyd_create_opaq(ctx, name, strlen(name), NULL, 0, module_ns, strlen(module_ns), value,
+            strlen(value), NULL, LY_PREF_XML, NULL, 0, &ret));
+    if (parent) {
+        lyd_insert_node(parent, NULL, ret);
+    }
+
+    if (node) {
+        *node = ret;
+    }
+    return LY_SUCCESS;
+}
+
+API LY_ERR
+lyd_new_attr(struct lyd_node *parent, const char *module_name, const char *name, const char *value,
         struct lyd_attr **attr)
 {
     struct lyd_attr *ret = NULL;
@@ -1143,12 +1170,46 @@
     }
 
     /* set value if none */
-    if (!val_str) {
-        val_str = "";
+    if (!value) {
+        value = "";
     }
 
-    LY_CHECK_RET(lyd_create_attr(parent, &ret, ctx, name, name_len, prefix, pref_len, module_name, mod_len, val_str,
-            strlen(val_str), NULL, LY_PREF_JSON, NULL, LYD_HINT_DATA));
+    LY_CHECK_RET(lyd_create_attr(parent, &ret, ctx, name, name_len, prefix, pref_len, module_name, mod_len, value,
+            strlen(value), NULL, LY_PREF_JSON, NULL, LYD_HINT_DATA));
+
+    if (attr) {
+        *attr = ret;
+    }
+    return LY_SUCCESS;
+}
+
+API LY_ERR
+lyd_new_attr2(struct lyd_node *parent, const char *module_ns, const char *name, const char *value,
+        struct lyd_attr **attr)
+{
+    struct lyd_attr *ret = NULL;
+    const struct ly_ctx *ctx;
+    const char *prefix, *tmp;
+    size_t pref_len, name_len;
+
+    LY_CHECK_ARG_RET(NULL, parent, !parent->schema, name, LY_EINVAL);
+
+    ctx = LYD_CTX(parent);
+
+    /* parse the name */
+    tmp = name;
+    if (ly_parse_nodeid(&tmp, &prefix, &pref_len, &name, &name_len) || tmp[0]) {
+        LOGERR(ctx, LY_EINVAL, "Attribute name \"%s\" is not valid.", name);
+        return LY_EVALID;
+    }
+
+    /* set value if none */
+    if (!value) {
+        value = "";
+    }
+
+    LY_CHECK_RET(lyd_create_attr(parent, &ret, ctx, name, name_len, prefix, pref_len, module_ns,
+            module_ns ? strlen(module_ns) : 0, value, strlen(value), NULL, LY_PREF_XML, NULL, LYD_HINT_DATA));
 
     if (attr) {
         *attr = ret;
diff --git a/src/tree_data.h b/src/tree_data.h
index a928dd8..cf236ec 100644
--- a/src/tree_data.h
+++ b/src/tree_data.h
@@ -163,7 +163,9 @@
  * - ::lyd_new_list2()
  * - ::lyd_new_any()
  * - ::lyd_new_opaq()
+ * - ::lyd_new_opaq2()
  * - ::lyd_new_attr()
+ * - ::lyd_new_attr2()
  * - ::lyd_new_meta()
  * - ::lyd_new_path()
  * - ::lyd_new_path2()
@@ -1003,7 +1005,7 @@
         struct lyd_meta **meta);
 
 /**
- * @brief Create a new opaque node in the data tree.
+ * @brief Create a new JSON opaque node in the data tree. To create an XML opaque node, use ::lyd_new_opaq2().
  *
  * @param[in] parent Parent node for the node beaing created. NULL in case of creating a top level element.
  * @param[in] ctx libyang context. If NULL, @p parent context will be used.
@@ -1017,16 +1019,43 @@
         const char *module_name, struct lyd_node **node);
 
 /**
- * @brief Create new attribute for an opaque data node.
+ * @brief Create a new XML opaque node in the data tree. To create a JSON opaque node, use ::lyd_new_opaq().
+ *
+ * @param[in] parent Parent node for the node beaing created. NULL in case of creating a top level element.
+ * @param[in] ctx libyang context. If NULL, @p parent context will be used.
+ * @param[in] name Node name.
+ * @param[in] value Node value, may be NULL.
+ * @param[in] module_ns Node module namespace.
+ * @param[out] node Optional created node.
+ * @return LY_ERR value.
+ */
+LY_ERR lyd_new_opaq2(struct lyd_node *parent, const struct ly_ctx *ctx, const char *name, const char *value,
+        const char *module_ns, struct lyd_node **node);
+
+/**
+ * @brief Create new JSON attribute for an opaque data node. To create an XML attribute, use ::lyd_new_attr2().
  *
  * @param[in] parent Parent opaque node for the attribute being created.
  * @param[in] module_name Name of the module of the attribute being created. There may be none.
  * @param[in] name Attribute name. It can include the module name as the prefix.
- * @param[in] val_str String value of the attribute. Is stored directly.
+ * @param[in] value Attribute value, may be NULL.
  * @param[out] attr Optional created attribute.
  * @return LY_ERR value.
  */
-LY_ERR lyd_new_attr(struct lyd_node *parent, const char *module_name, const char *name, const char *val_str,
+LY_ERR lyd_new_attr(struct lyd_node *parent, const char *module_name, const char *name, const char *value,
+        struct lyd_attr **attr);
+
+/**
+ * @brief Create new XML attribute for an opaque data node. To create a JSON attribute, use ::lyd_new_attr().
+ *
+ * @param[in] parent Parent opaque node for the attribute being created.
+ * @param[in] module_ns Namespace of the module of the attribute being created. There may be none.
+ * @param[in] name Attribute name. It can include an XML prefix.
+ * @param[in] value Attribute value, may be NULL.
+ * @param[out] attr Optional created attribute.
+ * @return LY_ERR value.
+ */
+LY_ERR lyd_new_attr2(struct lyd_node *parent, const char *module_ns, const char *name, const char *value,
         struct lyd_attr **attr);
 
 /**