libnetconf2 REFACTOR initial libyang2 support
diff --git a/src/io.c b/src/io.c
index 252a8b4..9a18ed1 100644
--- a/src/io.c
+++ b/src/io.c
@@ -344,24 +344,22 @@
     return count;
 }
 
-/* return NC_MSG_ERROR can change session status, acquires IO lock as needed */
-NC_MSG_TYPE
-nc_read_msg_io(struct nc_session *session, int io_timeout, struct lyxml_elem **data, int passing_io_lock)
+int
+nc_read_msg_io(struct nc_session *session, int io_timeout, struct ly_in **msg, int passing_io_lock)
 {
-    int ret, io_locked = passing_io_lock;
-    char *msg = NULL, *chunk;
+    int ret = 1, r, io_locked = passing_io_lock;
+    char *data = NULL, *chunk;
     uint64_t chunk_len, len = 0;
     /* use timeout in milliseconds instead seconds */
     uint32_t inact_timeout = NC_READ_INACT_TIMEOUT * 1000;
     struct timespec ts_act_timeout;
-    struct nc_server_reply *reply;
 
-    assert(session && data);
-    *data = NULL;
+    assert(session && msg);
+    *msg = NULL;
 
     if ((session->status != NC_STATUS_RUNNING) && (session->status != NC_STATUS_STARTING)) {
         ERR("Session %u: invalid session to read from.", session->id);
-        ret = NC_MSG_ERROR;
+        ret = -1;
         goto cleanup;
     }
 
@@ -371,11 +369,7 @@
     if (!io_locked) {
         /* SESSION IO LOCK */
         ret = nc_session_io_lock(session, io_timeout, __func__);
-        if (ret < 0) {
-            ret = NC_MSG_ERROR;
-            goto cleanup;
-        } else if (!ret) {
-            ret = NC_MSG_WOULDBLOCK;
+        if (ret < 1) {
             goto cleanup;
         }
         io_locked = 1;
@@ -384,34 +378,35 @@
     /* read the message */
     switch (session->version) {
     case NC_VERSION_10:
-        ret = nc_read_until(session, NC_VERSION_10_ENDTAG, 0, inact_timeout, &ts_act_timeout, &msg);
-        if (ret == -1) {
-            ret = NC_MSG_ERROR;
+        r = nc_read_until(session, NC_VERSION_10_ENDTAG, 0, inact_timeout, &ts_act_timeout, &data);
+        if (r == -1) {
+            ret = r;
             goto cleanup;
         }
 
         /* cut off the end tag */
-        msg[ret - NC_VERSION_10_ENDTAG_LEN] = '\0';
+        data[r - NC_VERSION_10_ENDTAG_LEN] = '\0';
         break;
     case NC_VERSION_11:
         while (1) {
-            ret = nc_read_until(session, "\n#", 0, inact_timeout, &ts_act_timeout, NULL);
-            if (ret == -1) {
-                ret = NC_MSG_ERROR;
+            r = nc_read_until(session, "\n#", 0, inact_timeout, &ts_act_timeout, NULL);
+            if (r == -1) {
+                ret = r;
                 goto cleanup;
             }
-            ret = nc_read_until(session, "\n", 0, inact_timeout, &ts_act_timeout, &chunk);
-            if (ret == -1) {
-                ret = NC_MSG_ERROR;
+            r = nc_read_until(session, "\n", 0, inact_timeout, &ts_act_timeout, &chunk);
+            if (r == -1) {
+                ret = r;
                 goto cleanup;
             }
 
             if (!strcmp(chunk, "#\n")) {
                 /* end of chunked framing message */
                 free(chunk);
-                if (!msg) {
+                if (!data) {
                     ERR("Session %u: invalid frame chunk delimiters.", session->id);
-                    goto malformed_msg;
+                    ret = -2;
+                    goto cleanup;
                 }
                 break;
             }
@@ -421,26 +416,27 @@
             free(chunk);
             if (!chunk_len) {
                 ERR("Session %u: invalid frame chunk size detected, fatal error.", session->id);
-                goto malformed_msg;
+                ret = -2;
+                goto cleanup;
             }
 
             /* now we have size of next chunk, so read the chunk */
-            ret = nc_read_chunk(session, chunk_len, inact_timeout, &ts_act_timeout, &chunk);
-            if (ret == -1) {
-                ret = NC_MSG_ERROR;
+            r = nc_read_chunk(session, chunk_len, inact_timeout, &ts_act_timeout, &chunk);
+            if (r == -1) {
+                ret = r;
                 goto cleanup;
             }
 
             /* realloc message buffer, remember to count terminating null byte */
-            msg = nc_realloc(msg, len + chunk_len + 1);
-            if (!msg) {
+            data = nc_realloc(data, len + chunk_len + 1);
+            if (!data) {
                 ERRMEM;
-                ret = NC_MSG_ERROR;
+                ret = -1;
                 goto cleanup;
             }
-            memcpy(msg + len, chunk, chunk_len);
+            memcpy(data + len, chunk, chunk_len);
             len += chunk_len;
-            msg[len] = '\0';
+            data[len] = '\0';
             free(chunk);
         }
 
@@ -452,74 +448,21 @@
     nc_session_io_unlock(session, __func__);
     io_locked = 0;
 
-    DBG("Session %u: received message:\n%s\n", session->id, msg);
+    DBG("Session %u: received message:\n%s\n", session->id, data);
 
-    /* build XML tree */
-    *data = lyxml_parse_mem(session->ctx, msg, LYXML_PARSE_NOMIXEDCONTENT);
-    if (!*data) {
-        goto malformed_msg;
-    } else if (!(*data)->ns) {
-        ERR("Session %u: invalid message root element (invalid namespace).", session->id);
-        goto malformed_msg;
+    /* build an input structure, eats data */
+    if (ly_in_new_memory(data, msg)) {
+        ret = -1;
+        goto cleanup;
     }
-    free(msg);
-    msg = NULL;
-
-    /* get and return message type */
-    if (!strcmp((*data)->ns->value, NC_NS_BASE)) {
-        if (!strcmp((*data)->name, "rpc")) {
-            return NC_MSG_RPC;
-        } else if (!strcmp((*data)->name, "rpc-reply")) {
-            return NC_MSG_REPLY;
-        } else if (!strcmp((*data)->name, "hello")) {
-            return NC_MSG_HELLO;
-        } else {
-            ERR("Session %u: invalid message root element (invalid name \"%s\").", session->id, (*data)->name);
-            goto malformed_msg;
-        }
-    } else if (!strcmp((*data)->ns->value, NC_NS_NOTIF)) {
-        if (!strcmp((*data)->name, "notification")) {
-            return NC_MSG_NOTIF;
-        } else {
-            ERR("Session %u: invalid message root element (invalid name \"%s\").", session->id, (*data)->name);
-            goto malformed_msg;
-        }
-    } else {
-        ERR("Session %u: invalid message root element (invalid namespace \"%s\").", session->id, (*data)->ns->value);
-        goto malformed_msg;
-    }
-
-malformed_msg:
-    ERR("Session %u: malformed message received.", session->id);
-    if ((session->side == NC_SERVER) && (session->version == NC_VERSION_11)) {
-        /* NETCONF version 1.1 defines sending error reply from the server (RFC 6241 sec. 3) */
-        reply = nc_server_reply_err(nc_err(NC_ERR_MALFORMED_MSG));
-
-        if (io_locked) {
-            /* nc_write_msg_io locks and unlocks the lock by itself */
-            nc_session_io_unlock(session, __func__);
-            io_locked = 0;
-        }
-
-        if (nc_write_msg_io(session, io_timeout, NC_MSG_REPLY, NULL, reply) != NC_MSG_REPLY) {
-            ERR("Session %u: unable to send a \"Malformed message\" error reply, terminating session.", session->id);
-            if (session->status != NC_STATUS_INVALID) {
-                session->status = NC_STATUS_INVALID;
-                session->term_reason = NC_SESSION_TERM_OTHER;
-            }
-        }
-        nc_server_reply_free(reply);
-    }
-    ret = NC_MSG_ERROR;
+    data = NULL;
 
 cleanup:
     if (io_locked) {
+        /* SESSION IO UNLOCK */
         nc_session_io_unlock(session, __func__);
     }
-    free(msg);
-    lyxml_free(session->ctx, *data);
-    *data = NULL;
-
+    free(data);
     return ret;
 }
 
@@ -624,45 +567,36 @@
     return ret;
 }
 
-/* return NC_MSG_ERROR can change session status, acquires IO lock as needed */
-NC_MSG_TYPE
-nc_read_msg_poll_io(struct nc_session *session, int io_timeout, struct lyxml_elem **data)
+int
+nc_read_msg_poll_io(struct nc_session *session, int io_timeout, struct ly_in **msg)
 {
     int ret;
 
-    assert(data);
-    *data = NULL;
+    assert(msg);
+    *msg = NULL;
 
     if ((session->status != NC_STATUS_RUNNING) && (session->status != NC_STATUS_STARTING)) {
         ERR("Session %u: invalid session to read from.", session->id);
-        return NC_MSG_ERROR;
+        return -1;
     }
 
     /* SESSION IO LOCK */
     ret = nc_session_io_lock(session, io_timeout, __func__);
-    if (ret < 0) {
-        return NC_MSG_ERROR;
-    } else if (!ret) {
-        return NC_MSG_WOULDBLOCK;
+    if (ret < 1) {
+        return ret;
     }
 
     ret = nc_read_poll(session, io_timeout);
-    if (ret == 0) {
-        /* timed out */
+    if (ret < 1) {
+        /* timed out or error */
 
         /* SESSION IO UNLOCK */
         nc_session_io_unlock(session, __func__);
-        return NC_MSG_WOULDBLOCK;
-    } else if (ret < 0) {
-        /* poll error, error written */
-
-        /* SESSION IO UNLOCK */
-        nc_session_io_unlock(session, __func__);
-        return NC_MSG_ERROR;
+        return ret;
     }
 
     /* SESSION IO LOCK passed down */
-    return nc_read_msg_io(session, io_timeout, data, 1);
+    return nc_read_msg_io(session, io_timeout, msg, 1);
 }
 
 /* does not really log, only fatal errors */
@@ -964,192 +898,15 @@
 static ssize_t
 nc_write_xmlclb(void *arg, const void *buf, size_t count)
 {
-    return nc_write_clb(arg, buf, count, 0);
-}
+    ssize_t r;
 
-static void
-nc_write_error_elem(struct wclb_arg *arg, const char *name, uint16_t nam_len, const char *prefix, uint16_t pref_len,
-                    int open, int no_attr)
-{
-    if (open) {
-        nc_write_clb((void *)arg, "<", 1, 0);
-    } else {
-        nc_write_clb((void *)arg, "</", 2, 0);
+    r = nc_write_clb(arg, buf, count, 0);
+    if (r == -1) {
+        return -1;
     }
 
-    if (prefix) {
-        nc_write_clb((void *)arg, prefix, pref_len, 0);
-        nc_write_clb((void *)arg, ":", 1, 0);
-    }
-
-    nc_write_clb((void *)arg, name, nam_len, 0);
-    if (!open || !no_attr) {
-        nc_write_clb((void *)arg, ">", 1, 0);
-    }
-}
-
-static void
-nc_write_error(struct wclb_arg *arg, struct nc_server_error *err, const char *prefix)
-{
-    uint16_t i, pref_len = 0;
-    char str_sid[11];
-
-    if (prefix) {
-        pref_len = strlen(prefix);
-    }
-
-    nc_write_error_elem(arg, "rpc-error", 9, prefix, pref_len, 1, 0);
-
-    nc_write_error_elem(arg, "error-type", 10, prefix, pref_len, 1, 0);
-    switch (err->type) {
-    case NC_ERR_TYPE_TRAN:
-        nc_write_clb((void *)arg, "transport", 9, 0);
-        break;
-    case NC_ERR_TYPE_RPC:
-        nc_write_clb((void *)arg, "rpc", 3, 0);
-        break;
-    case NC_ERR_TYPE_PROT:
-        nc_write_clb((void *)arg, "protocol", 8, 0);
-        break;
-    case NC_ERR_TYPE_APP:
-        nc_write_clb((void *)arg, "application", 11, 0);
-        break;
-    default:
-        ERRINT;
-        return;
-    }
-
-    nc_write_error_elem(arg, "error-type", 10, prefix, pref_len, 0, 0);
-
-    nc_write_error_elem(arg, "error-tag", 9, prefix, pref_len, 1, 0);
-    switch (err->tag) {
-    case NC_ERR_IN_USE:
-        nc_write_clb((void *)arg, "in-use", 6, 0);
-        break;
-    case NC_ERR_INVALID_VALUE:
-        nc_write_clb((void *)arg, "invalid-value", 13, 0);
-        break;
-    case NC_ERR_TOO_BIG:
-        nc_write_clb((void *)arg, "too-big", 7, 0);
-        break;
-    case NC_ERR_MISSING_ATTR:
-        nc_write_clb((void *)arg, "missing-attribute", 17, 0);
-        break;
-    case NC_ERR_BAD_ATTR:
-        nc_write_clb((void *)arg, "bad-attribute", 13, 0);
-        break;
-    case NC_ERR_UNKNOWN_ATTR:
-        nc_write_clb((void *)arg, "unknown-attribute", 17, 0);
-        break;
-    case NC_ERR_MISSING_ELEM:
-        nc_write_clb((void *)arg, "missing-element", 15, 0);
-        break;
-    case NC_ERR_BAD_ELEM:
-        nc_write_clb((void *)arg, "bad-element", 11, 0);
-        break;
-    case NC_ERR_UNKNOWN_ELEM:
-        nc_write_clb((void *)arg, "unknown-element", 15, 0);
-        break;
-    case NC_ERR_UNKNOWN_NS:
-        nc_write_clb((void *)arg, "unknown-namespace", 17, 0);
-        break;
-    case NC_ERR_ACCESS_DENIED:
-        nc_write_clb((void *)arg, "access-denied", 13, 0);
-        break;
-    case NC_ERR_LOCK_DENIED:
-        nc_write_clb((void *)arg, "lock-denied", 11, 0);
-        break;
-    case NC_ERR_RES_DENIED:
-        nc_write_clb((void *)arg, "resource-denied", 15, 0);
-        break;
-    case NC_ERR_ROLLBACK_FAILED:
-        nc_write_clb((void *)arg, "rollback-failed", 15, 0);
-        break;
-    case NC_ERR_DATA_EXISTS:
-        nc_write_clb((void *)arg, "data-exists", 11, 0);
-        break;
-    case NC_ERR_DATA_MISSING:
-        nc_write_clb((void *)arg, "data-missing", 12, 0);
-        break;
-    case NC_ERR_OP_NOT_SUPPORTED:
-        nc_write_clb((void *)arg, "operation-not-supported", 23, 0);
-        break;
-    case NC_ERR_OP_FAILED:
-        nc_write_clb((void *)arg, "operation-failed", 16, 0);
-        break;
-    case NC_ERR_MALFORMED_MSG:
-        nc_write_clb((void *)arg, "malformed-message", 17, 0);
-        break;
-    default:
-        ERRINT;
-        return;
-    }
-    nc_write_error_elem(arg, "error-tag", 9, prefix, pref_len, 0, 0);
-
-    nc_write_error_elem(arg, "error-severity", 14, prefix, pref_len, 1, 0);
-    nc_write_clb((void *)arg, "error", 5, 0);
-    nc_write_error_elem(arg, "error-severity", 14, prefix, pref_len, 0, 0);
-
-    if (err->apptag) {
-        nc_write_error_elem(arg, "error-app-tag", 13, prefix, pref_len, 1, 0);
-        nc_write_clb((void *)arg, err->apptag, strlen(err->apptag), 1);
-        nc_write_error_elem(arg, "error-app-tag", 13, prefix, pref_len, 0, 0);
-    }
-
-    if (err->path) {
-        nc_write_error_elem(arg, "error-path", 10, prefix, pref_len, 1, 0);
-        nc_write_clb((void *)arg, err->path, strlen(err->path), 1);
-        nc_write_error_elem(arg, "error-path", 10, prefix, pref_len, 0, 0);
-    }
-
-    if (err->message) {
-        nc_write_error_elem(arg, "error-message", 13, prefix, pref_len, 1, 1);
-        if (err->message_lang) {
-            nc_write_clb((void *)arg, " xml:lang=\"", 11, 0);
-            nc_write_clb((void *)arg, err->message_lang, strlen(err->message_lang), 1);
-            nc_write_clb((void *)arg, "\"", 1, 0);
-        }
-        nc_write_clb((void *)arg, ">", 1, 0);
-        nc_write_clb((void *)arg, err->message, strlen(err->message), 1);
-        nc_write_error_elem(arg, "error-message", 13, prefix, pref_len, 0, 0);
-    }
-
-    if ((err->sid > -1) || err->attr_count || err->elem_count || err->ns_count || err->other_count) {
-        nc_write_error_elem(arg, "error-info", 10, prefix, pref_len, 1, 0);
-
-        if (err->sid > -1) {
-            nc_write_error_elem(arg, "session-id", 10, prefix, pref_len, 1, 0);
-            sprintf(str_sid, "%u", (uint32_t)err->sid);
-            nc_write_clb((void *)arg, str_sid, strlen(str_sid), 0);
-            nc_write_error_elem(arg, "session-id", 10, prefix, pref_len, 0, 0);
-        }
-
-        for (i = 0; i < err->attr_count; ++i) {
-            nc_write_error_elem(arg, "bad-attribute", 13, prefix, pref_len, 1, 0);
-            nc_write_clb((void *)arg, err->attr[i], strlen(err->attr[i]), 1);
-            nc_write_error_elem(arg, "bad-attribute", 13, prefix, pref_len, 0, 0);
-        }
-
-        for (i = 0; i < err->elem_count; ++i) {
-            nc_write_error_elem(arg, "bad-element", 11, prefix, pref_len, 1, 0);
-            nc_write_clb((void *)arg, err->elem[i], strlen(err->elem[i]), 1);
-            nc_write_error_elem(arg, "bad-element", 11, prefix, pref_len, 0, 0);
-        }
-
-        for (i = 0; i < err->ns_count; ++i) {
-            nc_write_error_elem(arg, "bad-namespace", 13, prefix, pref_len, 1, 0);
-            nc_write_clb((void *)arg, err->ns[i], strlen(err->ns[i]), 1);
-            nc_write_error_elem(arg, "bad-namespace", 13, prefix, pref_len, 0, 0);
-        }
-
-        for (i = 0; i < err->other_count; ++i) {
-            lyxml_print_clb(nc_write_xmlclb, (void *)arg, err->other[i], 0);
-        }
-
-        nc_write_error_elem(arg, "error-info", 10, prefix, pref_len, 0, 0);
-    }
-
-    nc_write_error_elem(arg, "rpc-error", 9, prefix, pref_len, 0, 0);
+    /* always return what libyang expects, simply that all the characters were printed */
+    return count;
 }
 
 /* return NC_MSG_ERROR can change session status, acquires IO lock as needed */
@@ -1158,17 +915,16 @@
 {
     va_list ap;
     int count, ret;
-    const char *attrs, *base_prefix;
-    struct lyd_node *content;
-    struct lyxml_elem *rpc_elem;
+    const char *attrs;
+    struct lyd_node *op, *reply_envp, *node;
+    struct lyd_node_opaq *rpc_envp;
     struct nc_server_notif *notif;
     struct nc_server_reply *reply;
-    struct nc_server_reply_error *error_rpl;
-    char *buf = NULL;
+    char *buf;
     struct wclb_arg arg;
     const char **capabilities;
-    uint32_t *sid = NULL, i;
-    int wd = 0;
+    uint32_t *sid = NULL, i, wd = 0;
+    LY_ERR lyrc;
 
     assert(session);
 
@@ -1192,11 +948,11 @@
 
     switch (type) {
     case NC_MSG_RPC:
-        content = va_arg(ap, struct lyd_node *);
+        op = va_arg(ap, struct lyd_node *);
         attrs = va_arg(ap, const char *);
 
         count = asprintf(&buf, "<rpc xmlns=\"%s\" message-id=\"%"PRIu64"\"%s>",
-                         NC_NS_BASE, session->opts.client.msgid + 1, attrs ? attrs : "");
+                NC_NS_BASE, session->opts.client.msgid + 1, attrs ? attrs : "");
         if (count == -1) {
             ERRMEM;
             ret = NC_MSG_ERROR;
@@ -1205,7 +961,7 @@
         nc_write_clb((void *)&arg, buf, count, 0);
         free(buf);
 
-        if (lyd_print_clb(nc_write_xmlclb, (void *)&arg, content, LYD_XML, LYP_WITHSIBLINGS | LYP_NETCONF)) {
+        if (lyd_print_clb(nc_write_xmlclb, (void *)&arg, op, LYD_XML, LYD_PRINT_SHRINK)) {
             ret = NC_MSG_ERROR;
             goto cleanup;
         }
@@ -1215,64 +971,70 @@
         break;
 
     case NC_MSG_REPLY:
-        rpc_elem = va_arg(ap, struct lyxml_elem *);
+        rpc_envp = va_arg(ap, struct lyd_node_opaq *);
         reply = va_arg(ap, struct nc_server_reply *);
 
-        if (rpc_elem && rpc_elem->ns && rpc_elem->ns->prefix) {
-            nc_write_clb((void *)&arg, "<", 1, 0);
-            nc_write_clb((void *)&arg, rpc_elem->ns->prefix, strlen(rpc_elem->ns->prefix), 0);
-            nc_write_clb((void *)&arg, ":rpc-reply", 10, 0);
-            base_prefix = rpc_elem->ns->prefix;
-        }
-        else {
-            nc_write_clb((void *)&arg, "<rpc-reply", 10, 0);
-            base_prefix = NULL;
+        if (!rpc_envp) {
+            /* can be NULL if replying with a malformed-message error */
+            nc_write_clb((void *)&arg, "<rpc-reply xmlns=\"" NC_NS_BASE "\">", 18 + strlen(NC_NS_BASE) + 2, 0);
+
+            assert(reply->type == NC_RPL_ERROR);
+            if (lyd_print_clb(nc_write_xmlclb, (void *)&arg, ((struct nc_server_reply_error *)reply)->err, LYD_XML,
+                    LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS)) {
+                ret = NC_MSG_ERROR;
+                goto cleanup;
+            }
+
+            nc_write_clb((void *)&arg, "</rpc-reply>", 12, 0);
+            break;
         }
 
-        /* can be NULL if replying with a malformed-message error */
-        if (rpc_elem) {
-            lyxml_print_clb(nc_write_xmlclb, (void *)&arg, rpc_elem, LYXML_PRINT_ATTRS);
-            nc_write_clb((void *)&arg, ">", 1, 0);
-        } else {
-            /* but put there at least the correct namespace */
-            nc_write_clb((void *)&arg, " xmlns=\""NC_NS_BASE"\">", 49, 0);
+        /* build a rpc-reply opaque node that can be simply printed */
+        if (lyd_new_opaq2(NULL, session->ctx, "rpc-reply", NULL, rpc_envp->name.prefix, rpc_envp->name.module_ns, &reply_envp)) {
+            ERRINT;
+            ret = NC_MSG_ERROR;
+            goto cleanup;
         }
+
         switch (reply->type) {
         case NC_RPL_OK:
-            nc_write_clb((void *)&arg, "<", 1, 0);
-            if (base_prefix) {
-                nc_write_clb((void *)&arg, base_prefix, strlen(base_prefix), 0);
-                nc_write_clb((void *)&arg, ":", 1, 0);
+            if (lyd_new_opaq2(reply_envp, NULL, "ok", NULL, rpc_envp->name.prefix, rpc_envp->name.module_ns, NULL)) {
+                lyd_free_tree(reply_envp);
+
+                ERRINT;
+                ret = NC_MSG_ERROR;
+                goto cleanup;
             }
-            nc_write_clb((void *)&arg, "ok/>", 4, 0);
             break;
         case NC_RPL_DATA:
             switch(((struct nc_server_reply_data *)reply)->wd) {
             case NC_WD_UNKNOWN:
             case NC_WD_EXPLICIT:
-                wd = LYP_WD_EXPLICIT;
+                wd = LYD_PRINT_WD_EXPLICIT;
                 break;
             case NC_WD_TRIM:
-                wd = LYP_WD_TRIM;
+                wd = LYD_PRINT_WD_TRIM;
                 break;
             case NC_WD_ALL:
-                wd = LYP_WD_ALL;
+                wd = LYD_PRINT_WD_ALL;
                 break;
             case NC_WD_ALL_TAG:
-                wd = LYP_WD_ALL_TAG;
+                wd = LYD_PRINT_WD_ALL_TAG;
                 break;
             }
-            if (lyd_print_clb(nc_write_xmlclb, (void *)&arg, ((struct nc_reply_data *)reply)->data, LYD_XML,
-                              LYP_WITHSIBLINGS | LYP_NETCONF | wd)) {
-                ret = NC_MSG_ERROR;
-                goto cleanup;
+
+            node = ((struct nc_server_reply_data *)reply)->data;
+            assert(node->schema->nodetype & (LYS_RPC | LYS_ACTION));
+            if (lyd_child(node)) {
+                /* temporary */
+                lyd_child(node)->parent = NULL;
+                lyd_insert_child(reply_envp, lyd_child(node));
+                ((struct lyd_node_inner *)node)->child = NULL;
             }
             break;
         case NC_RPL_ERROR:
-            error_rpl = (struct nc_server_reply_error *)reply;
-            for (i = 0; i < error_rpl->count; ++i) {
-                nc_write_error(&arg, error_rpl->err[i], base_prefix);
-            }
+            /* temporary */
+            lyd_insert_child(reply_envp, ((struct nc_server_reply_error *)reply)->err);
             break;
         default:
             ERRINT;
@@ -1280,13 +1042,41 @@
             ret = NC_MSG_ERROR;
             goto cleanup;
         }
-        if (rpc_elem && rpc_elem->ns && rpc_elem->ns->prefix) {
-            nc_write_clb((void *)&arg, "</", 2, 0);
-            nc_write_clb((void *)&arg, rpc_elem->ns->prefix, strlen(rpc_elem->ns->prefix), 0);
-            nc_write_clb((void *)&arg, ":rpc-reply>", 11, 0);
+
+        /* temporary */
+        ((struct lyd_node_opaq *)reply_envp)->attr = rpc_envp->attr;
+
+        /* print */
+        lyrc = lyd_print_clb(nc_write_xmlclb, (void *)&arg, reply_envp, LYD_XML, LYD_PRINT_SHRINK | wd);
+        ((struct lyd_node_opaq *)reply_envp)->attr = NULL;
+
+        /* cleanup */
+        switch (reply->type) {
+        case NC_RPL_OK:
+            /* just free everything */
+            lyd_free_tree(reply_envp);
+            break;
+        case NC_RPL_DATA:
+            if (lyd_child(reply_envp)) {
+                /* connect back to the reply structure */
+                lyd_child(reply_envp)->parent = NULL;
+                lyd_insert_child(((struct nc_server_reply_data *)reply)->data, lyd_child(reply_envp));
+                ((struct lyd_node_opaq *)reply_envp)->child = NULL;
+            }
+            lyd_free_tree(reply_envp);
+            break;
+        case NC_RPL_ERROR:
+            /* unlink from the data reply */
+            lyd_unlink_tree(lyd_child(reply_envp));
+            lyd_free_tree(reply_envp);
+            break;
+        default:
+            break;
         }
-        else {
-            nc_write_clb((void *)&arg, "</rpc-reply>", 12, 0);
+
+        if (lyrc) {
+            ret = NC_MSG_ERROR;
+            goto cleanup;
         }
         break;
 
@@ -1297,7 +1087,7 @@
         nc_write_clb((void *)&arg, "<eventTime>", 11, 0);
         nc_write_clb((void *)&arg, notif->eventtime, strlen(notif->eventtime), 0);
         nc_write_clb((void *)&arg, "</eventTime>", 12, 0);
-        if (lyd_print_clb(nc_write_xmlclb, (void *)&arg, notif->tree, LYD_XML, 0)) {
+        if (lyd_print_clb(nc_write_xmlclb, (void *)&arg, notif->ntf, LYD_XML, LYD_PRINT_SHRINK)) {
             ret = NC_MSG_ERROR;
             goto cleanup;
         }
@@ -1373,4 +1163,3 @@
 
     return ret;
 }
-