schema CHANGE unify actions, inouts and notification with lys*_node
diff --git a/doc/transition.dox b/doc/transition.dox
index 33deff3..b1fc424 100644
--- a/doc/transition.dox
+++ b/doc/transition.dox
@@ -184,7 +184,6 @@
  * -                            | ::lysc_is_userordered()         | Added functionality to simplify the examination of generic compiled schema nodes.
  * -                            | ::lysc_is_np_cont()             | ^
  * -                            | ::lysc_node_children()          | ^
- * -                            | ::lysc_node_children_full()     | ^
  * -                            | ::lysc_node_actions()           | ^
  * -                            | ::lysc_node_notifs()            | ^
  * -                            | ::lysc_node_parent_full()       | ^
diff --git a/src/parser_yang.c b/src/parser_yang.c
index 591aaa5..24c999d 100644
--- a/src/parser_yang.c
+++ b/src/parser_yang.c
@@ -83,7 +83,7 @@
 LY_ERR parse_choice(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_node **siblings);
 LY_ERR parse_case(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_node **siblings);
 LY_ERR parse_list(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_node **siblings);
-LY_ERR parse_grouping(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_grp **groupings);
+LY_ERR parse_grouping(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_node_grp **groupings);
 
 /**
  * @brief Add another character to dynamic buffer, a low-level function.
@@ -2617,12 +2617,13 @@
  */
 static LY_ERR
 parse_inout(struct lys_yang_parser_ctx *ctx, enum ly_stmt inout_kw, struct lysp_node *parent,
-        struct lysp_action_inout *inout_p)
+        struct lysp_node_action_inout *inout_p)
 {
     LY_ERR ret = LY_SUCCESS;
     char *word;
     size_t word_len;
     enum ly_stmt kw;
+    ly_bool input = &((struct lysp_node_action *)parent)->input == inout_p ? 1 : 0;
 
     if (inout_p->nodetype) {
         LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(inout_kw));
@@ -2630,7 +2631,8 @@
     }
 
     /* initiate structure */
-    inout_p->nodetype = &((struct lysp_action *)parent)->input == inout_p ? LYS_INPUT : LYS_OUTPUT;
+    LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), input ? "input" : "output", 0, &inout_p->name));
+    inout_p->nodetype = input ? LYS_INPUT : LYS_OUTPUT;
     inout_p->parent = parent;
 
     /* parse substatements */
@@ -2681,9 +2683,6 @@
     LY_CHECK_RET(ret);
 
 checks:
-    /* finalize parent pointers to the reallocated items */
-    LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, inout_p->groupings, NULL, NULL, NULL));
-
     if (!inout_p->data) {
         LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "data-def-stmt", ly_stmt2str(inout_kw));
         return LY_EVALID;
@@ -2701,15 +2700,15 @@
  * @return LY_ERR values.
  */
 LY_ERR
-parse_action(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_action **actions)
+parse_action(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_node_action **actions)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word;
     size_t word_len;
     enum ly_stmt kw;
-    struct lysp_action *act;
+    struct lysp_node_action *act;
 
-    LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *actions, act, LY_EMEM);
+    LY_LIST_NEW_RET(PARSER_CTX(ctx), actions, act, next, LY_EMEM);
 
     /* get value */
     LY_CHECK_RET(get_argument(ctx, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
@@ -2755,20 +2754,19 @@
     }
     LY_CHECK_RET(ret);
 
+checks:
     /* always initialize inout, they are technically present (needed for later deviations/refines) */
     if (!act->input.nodetype) {
         act->input.nodetype = LYS_INPUT;
         act->input.parent = (struct lysp_node *)act;
+        LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "input", 0, &act->input.name));
     }
     if (!act->output.nodetype) {
         act->output.nodetype = LYS_OUTPUT;
         act->output.parent = (struct lysp_node *)act;
+        LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "output", 0, &act->output.name));
     }
 
-checks:
-    /* finalize parent pointers to the reallocated items */
-    LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, act->groupings, NULL, NULL, NULL));
-
     return ret;
 }
 
@@ -2781,15 +2779,15 @@
  * @return LY_ERR values.
  */
 LY_ERR
-parse_notif(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_notif **notifs)
+parse_notif(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_node_notif **notifs)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word;
     size_t word_len;
     enum ly_stmt kw;
-    struct lysp_notif *notif;
+    struct lysp_node_notif *notif;
 
-    LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *notifs, notif, LY_EMEM);
+    LY_LIST_NEW_RET(PARSER_CTX(ctx), notifs, notif, next, LY_EMEM);
 
     /* get value */
     LY_CHECK_RET(get_argument(ctx, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
@@ -2797,7 +2795,7 @@
     notif->nodetype = LYS_NOTIF;
     notif->parent = parent;
 
-    YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, goto checks) {
+    YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, ) {
         switch (kw) {
         case LY_STMT_DESCRIPTION:
             LY_CHECK_RET(parse_text_field(ctx, LYEXT_SUBSTMT_DESCRIPTION, 0, &notif->dsc, Y_STR_ARG, &notif->exts));
@@ -2855,10 +2853,6 @@
             return LY_EVALID;
         }
     }
-    LY_CHECK_RET(ret);
-checks:
-    /* finalize parent pointers to the reallocated items */
-    LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, notif->groupings, NULL, NULL, NULL));
 
     return ret;
 }
@@ -2872,15 +2866,15 @@
  * @return LY_ERR values.
  */
 LY_ERR
-parse_grouping(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_grp **groupings)
+parse_grouping(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_node_grp **groupings)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word;
     size_t word_len;
     enum ly_stmt kw;
-    struct lysp_grp *grp;
+    struct lysp_node_grp *grp;
 
-    LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *groupings, grp, LY_EMEM);
+    LY_LIST_NEW_RET(PARSER_CTX(ctx), groupings, grp, next, LY_EMEM);
 
     /* get value */
     LY_CHECK_RET(get_argument(ctx, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
@@ -2888,7 +2882,7 @@
     grp->nodetype = LYS_GROUPING;
     grp->parent = parent;
 
-    YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, goto checks) {
+    YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, ) {
         switch (kw) {
         case LY_STMT_DESCRIPTION:
             LY_CHECK_RET(parse_text_field(ctx, LYEXT_SUBSTMT_DESCRIPTION, 0, &grp->dsc, Y_STR_ARG, &grp->exts));
@@ -2904,40 +2898,40 @@
             PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "grouping");
         /* fall through */
         case LY_STMT_ANYXML:
-            LY_CHECK_RET(parse_any(ctx, kw, (struct lysp_node *)grp, &grp->data));
+            LY_CHECK_RET(parse_any(ctx, kw, &grp->node, &grp->data));
             break;
         case LY_STMT_CHOICE:
-            LY_CHECK_RET(parse_choice(ctx, (struct lysp_node *)grp, &grp->data));
+            LY_CHECK_RET(parse_choice(ctx, &grp->node, &grp->data));
             break;
         case LY_STMT_CONTAINER:
-            LY_CHECK_RET(parse_container(ctx, (struct lysp_node *)grp, &grp->data));
+            LY_CHECK_RET(parse_container(ctx, &grp->node, &grp->data));
             break;
         case LY_STMT_LEAF:
-            LY_CHECK_RET(parse_leaf(ctx, (struct lysp_node *)grp, &grp->data));
+            LY_CHECK_RET(parse_leaf(ctx, &grp->node, &grp->data));
             break;
         case LY_STMT_LEAF_LIST:
-            LY_CHECK_RET(parse_leaflist(ctx, (struct lysp_node *)grp, &grp->data));
+            LY_CHECK_RET(parse_leaflist(ctx, &grp->node, &grp->data));
             break;
         case LY_STMT_LIST:
-            LY_CHECK_RET(parse_list(ctx, (struct lysp_node *)grp, &grp->data));
+            LY_CHECK_RET(parse_list(ctx, &grp->node, &grp->data));
             break;
         case LY_STMT_USES:
-            LY_CHECK_RET(parse_uses(ctx, (struct lysp_node *)grp, &grp->data));
+            LY_CHECK_RET(parse_uses(ctx, &grp->node, &grp->data));
             break;
 
         case LY_STMT_TYPEDEF:
-            LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node *)grp, &grp->typedefs));
+            LY_CHECK_RET(parse_typedef(ctx, &grp->node, &grp->typedefs));
             break;
         case LY_STMT_ACTION:
             PARSER_CHECK_STMTVER2_RET(ctx, "action", "grouping");
-            LY_CHECK_RET(parse_action(ctx, (struct lysp_node *)grp, &grp->actions));
+            LY_CHECK_RET(parse_action(ctx, &grp->node, &grp->actions));
             break;
         case LY_STMT_GROUPING:
-            LY_CHECK_RET(parse_grouping(ctx, (struct lysp_node *)grp, &grp->groupings));
+            LY_CHECK_RET(parse_grouping(ctx, &grp->node, &grp->groupings));
             break;
         case LY_STMT_NOTIFICATION:
             PARSER_CHECK_STMTVER2_RET(ctx, "notification", "grouping");
-            LY_CHECK_RET(parse_notif(ctx, (struct lysp_node *)grp, &grp->notifs));
+            LY_CHECK_RET(parse_notif(ctx, &grp->node, &grp->notifs));
             break;
         case LY_STMT_EXTENSION_INSTANCE:
             LY_CHECK_RET(parse_ext(ctx, word, word_len, LYEXT_SUBSTMT_SELF, 0, &grp->exts));
@@ -2947,10 +2941,6 @@
             return LY_EVALID;
         }
     }
-    LY_CHECK_RET(ret);
-checks:
-    /* finalize parent pointers to the reallocated items */
-    LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, grp->groupings, NULL, grp->actions, grp->notifs));
 
     return ret;
 }
@@ -2964,15 +2954,15 @@
  * @return LY_ERR values.
  */
 LY_ERR
-parse_augment(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_augment **augments)
+parse_augment(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_node_augment **augments)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word;
     size_t word_len;
     enum ly_stmt kw;
-    struct lysp_augment *aug;
+    struct lysp_node_augment *aug;
 
-    LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *augments, aug, LY_EMEM);
+    LY_LIST_NEW_RET(PARSER_CTX(ctx), augments, aug, next, LY_EMEM);
 
     /* get value */
     LY_CHECK_RET(get_argument(ctx, Y_STR_ARG, NULL, &word, &buf, &word_len));
@@ -2981,7 +2971,7 @@
     aug->nodetype = LYS_AUGMENT;
     aug->parent = parent;
 
-    YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, goto checks) {
+    YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, ) {
         switch (kw) {
         case LY_STMT_DESCRIPTION:
             LY_CHECK_RET(parse_text_field(ctx, LYEXT_SUBSTMT_DESCRIPTION, 0, &aug->dsc, Y_STR_ARG, &aug->exts));
@@ -3043,10 +3033,6 @@
             return LY_EVALID;
         }
     }
-    LY_CHECK_RET(ret);
-checks:
-    /* finalize parent pointers to the reallocated items */
-    LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, NULL, aug->actions, aug->notifs));
 
     return ret;
 }
@@ -3078,7 +3064,7 @@
     INSERT_WORD_RET(ctx, buf, uses->name, word, word_len);
 
     /* parse substatements */
-    YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, goto checks) {
+    YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, ) {
         switch (kw) {
         case LY_STMT_DESCRIPTION:
             LY_CHECK_RET(parse_text_field(ctx, LYEXT_SUBSTMT_DESCRIPTION, 0, &uses->dsc, Y_STR_ARG, &uses->exts));
@@ -3110,9 +3096,6 @@
             return LY_EVALID;
         }
     }
-checks:
-    /* finalize parent pointers to the reallocated items */
-    LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, uses->augments, NULL, NULL));
 
     return ret;
 }
@@ -3316,7 +3299,7 @@
     INSERT_WORD_RET(ctx, buf, cont->name, word, word_len);
 
     /* parse substatements */
-    YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, goto checks) {
+    YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, ) {
         switch (kw) {
         case LY_STMT_CONFIG:
             LY_CHECK_RET(parse_config(ctx, &cont->flags, &cont->exts));
@@ -3390,9 +3373,7 @@
             return LY_EVALID;
         }
     }
-checks:
-    /* finalize parent pointers to the reallocated items */
-    LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, cont->groupings, NULL, cont->actions, cont->notifs));
+
     return ret;
 }
 
@@ -3423,7 +3404,7 @@
     INSERT_WORD_RET(ctx, buf, list->name, word, word_len);
 
     /* parse substatements */
-    YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, goto checks) {
+    YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, ) {
         switch (kw) {
         case LY_STMT_CONFIG:
             LY_CHECK_RET(parse_config(ctx, &list->flags, &list->exts));
@@ -3509,10 +3490,6 @@
             return LY_EVALID;
         }
     }
-    LY_CHECK_RET(ret);
-checks:
-    /* finalize parent pointers to the reallocated items */
-    LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, list->groupings, NULL, list->actions, list->notifs));
 
     return ret;
 }
@@ -4212,9 +4189,6 @@
     LY_CHECK_RET(ret);
 
 checks:
-    /* finalize parent pointers to the reallocated items */
-    LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, mod->groupings, mod->augments, mod->rpcs, mod->notifs));
-
     /* mandatory substatements */
     if (!mod->mod->ns) {
         LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "namespace", "module");
@@ -4422,10 +4396,6 @@
     LY_CHECK_RET(ret);
 
 checks:
-    /* finalize parent pointers to the reallocated items */
-    LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, submod->groupings, submod->augments,
-            submod->rpcs, submod->notifs));
-
     /* mandatory substatements */
     if (!submod->prefix) {
         LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "belongs-to", "submodule");
diff --git a/src/parser_yin.c b/src/parser_yin.c
index bc20d0e..6eb8c9b 100644
--- a/src/parser_yin.c
+++ b/src/parser_yin.c
@@ -137,7 +137,7 @@
  */
 struct inout_meta {
     struct lysp_node *parent;          /**< Parent node. */
-    struct lysp_action_inout *inout_p; /**< inout_p Input/output pointer to write to. */
+    struct lysp_node_action_inout *inout_p; /**< inout_p Input/output pointer to write to. */
 };
 
 /**
@@ -372,7 +372,7 @@
             inout_meta = calloc(1, sizeof *inout_meta);
             LY_CHECK_GOTO(!inout_meta, mem_err);
             inout_meta->parent = parent;
-            inout_meta->inout_p = va_arg(ap, struct lysp_action_inout *);
+            inout_meta->inout_p = va_arg(ap, struct lysp_node_action_inout *);
             (*result)[i].dest = inout_meta;
         } else {
             (*result)[i].dest = va_arg(ap, void *);
@@ -1681,7 +1681,6 @@
     };
 
     LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_USES, NULL, &uses->exts));
-    LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, uses->augments, NULL, NULL));
 
     return LY_SUCCESS;
 }
@@ -2200,9 +2199,6 @@
     subelems_deallocator(subelems_size, subelems);
     LY_CHECK_RET(ret);
 
-    /* finalize parent pointers to the reallocated items */
-    LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, list->groupings, NULL, list->actions, list->notifs));
-
     if (list->max && (list->min > list->max)) {
         LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, list->min, list->max);
         return LY_EVALID;
@@ -2222,14 +2218,14 @@
 static LY_ERR
 yin_parse_notification(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *notif_meta)
 {
-    struct lysp_notif *notif;
-    struct lysp_notif **notifs = (struct lysp_notif **)notif_meta->nodes;
+    struct lysp_node_notif *notif;
+    struct lysp_node_notif **notifs = (struct lysp_node_notif **)notif_meta->nodes;
     LY_ERR ret = LY_SUCCESS;
     struct yin_subelement *subelems = NULL;
     size_t subelems_size;
 
     /* allocate new notification */
-    LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *notifs, notif, LY_EMEM);
+    LY_LIST_NEW_RET(ctx->xmlctx->ctx, notifs, notif, next, LY_EMEM);
     notif->nodetype = LYS_NOTIF;
     notif->parent = notif_meta->parent;
 
@@ -2260,9 +2256,6 @@
     subelems_deallocator(subelems_size, subelems);
     LY_CHECK_RET(ret);
 
-    /* finalize parent pointers to the reallocated items */
-    LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, notif->groupings, NULL, NULL, NULL));
-
     return LY_SUCCESS;
 }
 
@@ -2277,14 +2270,14 @@
 static LY_ERR
 yin_parse_grouping(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *gr_meta)
 {
-    struct lysp_grp *grp;
-    struct lysp_grp **grps = (struct lysp_grp **)gr_meta->nodes;
+    struct lysp_node_grp *grp;
+    struct lysp_node_grp **grps = (struct lysp_node_grp **)gr_meta->nodes;
     LY_ERR ret = LY_SUCCESS;
     struct yin_subelement *subelems = NULL;
     size_t subelems_size;
 
     /* create new grouping */
-    LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *grps, grp, LY_EMEM);
+    LY_LIST_NEW_RET(ctx->xmlctx->ctx, grps, grp, next, LY_EMEM);
     grp->nodetype = LYS_GROUPING;
     grp->parent = gr_meta->parent;
 
@@ -2293,7 +2286,7 @@
     LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &grp->name, Y_IDENTIF_ARG, LY_STMT_GROUPING));
 
     /* parse grouping content */
-    LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 16, (struct lysp_node *)grp, &subelems,
+    LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 16, &grp->node, &subelems,
             LY_STMT_ACTION, &grp->actions, 0,
             LY_STMT_ANYDATA, &grp->data, 0,
             LY_STMT_ANYXML, &grp->data, 0,
@@ -2312,12 +2305,8 @@
             LY_STMT_EXTENSION_INSTANCE, NULL, 0));
     ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_GROUPING, NULL, &grp->exts);
     subelems_deallocator(subelems_size, subelems);
-    LY_CHECK_RET(ret);
 
-    /* finalize parent pointers to the reallocated items */
-    LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, grp->groupings, NULL, grp->actions, grp->notifs));
-
-    return LY_SUCCESS;
+    return ret;
 }
 
 /**
@@ -2370,11 +2359,8 @@
             LY_STMT_EXTENSION_INSTANCE, NULL, 0));
     ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_CONTAINER, NULL, &cont->exts);
     subelems_deallocator(subelems_size, subelems);
-    LY_CHECK_RET(ret);
 
-    LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, cont->groupings, NULL, cont->actions, cont->notifs));
-
-    return LY_SUCCESS;
+    return ret;
 }
 
 /**
@@ -2491,6 +2477,7 @@
     size_t subelems_size;
 
     /* initiate structure */
+    LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), (inout_kw == LY_STMT_INPUT) ? "input" : "output", 0, &inout_meta->inout_p->name));
     inout_meta->inout_p->nodetype = (inout_kw == LY_STMT_INPUT) ? LYS_INPUT : LYS_OUTPUT;
     inout_meta->inout_p->parent = inout_meta->parent;
 
@@ -2521,9 +2508,6 @@
         return LY_EVALID;
     }
 
-    /* finalize parent pointers to the reallocated items */
-    LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, inout_meta->inout_p->groupings, NULL, NULL, NULL));
-
     return LY_SUCCESS;
 }
 
@@ -2538,13 +2522,13 @@
 static LY_ERR
 yin_parse_action(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *act_meta)
 {
-    struct lysp_action *act, **acts = (struct lysp_action **)act_meta->nodes;
+    struct lysp_node_action *act, **acts = (struct lysp_node_action **)act_meta->nodes;
     LY_ERR ret = LY_SUCCESS;
     struct yin_subelement *subelems = NULL;
     size_t subelems_size;
 
     /* create new action */
-    LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *acts, act, LY_EMEM);
+    LY_LIST_NEW_RET(ctx->xmlctx->ctx, acts, act, next, LY_EMEM);
     act->nodetype = act_meta->parent ? LYS_ACTION : LYS_RPC;
     act->parent = act_meta->parent;
 
@@ -2571,14 +2555,14 @@
     if (!act->input.nodetype) {
         act->input.nodetype = LYS_INPUT;
         act->input.parent = (struct lysp_node *)act;
+        LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "input", 0, &act->input.name));
     }
     if (!act->output.nodetype) {
         act->output.nodetype = LYS_OUTPUT;
         act->output.parent = (struct lysp_node *)act;
+        LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "output", 0, &act->output.name));
     }
 
-    LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, act->groupings, NULL, NULL, NULL));
-
     return LY_SUCCESS;
 }
 
@@ -2593,14 +2577,14 @@
 static LY_ERR
 yin_parse_augment(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *aug_meta)
 {
-    struct lysp_augment *aug;
-    struct lysp_augment **augs = (struct lysp_augment **)aug_meta->nodes;
+    struct lysp_node_augment *aug;
+    struct lysp_node_augment **augs = (struct lysp_node_augment **)aug_meta->nodes;
     LY_ERR ret = LY_SUCCESS;
     struct yin_subelement *subelems = NULL;
     size_t subelems_size;
 
     /* create new augment */
-    LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *augs, aug, LY_EMEM);
+    LY_LIST_NEW_RET(ctx->xmlctx->ctx, augs, aug, next, LY_EMEM);
     aug->nodetype = LYS_AUGMENT;
     aug->parent = aug_meta->parent;
 
@@ -2630,11 +2614,8 @@
             LY_STMT_EXTENSION_INSTANCE, NULL, 0));
     ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_AUGMENT, NULL, &aug->exts);
     subelems_deallocator(subelems_size, subelems);
-    LY_CHECK_RET(ret);
 
-    LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, NULL, aug->actions, aug->notifs));
-
-    return LY_SUCCESS;
+    return ret;
 }
 
 /**
@@ -3697,9 +3678,6 @@
     subelems_deallocator(subelems_size, subelems);
     LY_CHECK_RET(ret);
 
-    /* finalize parent pointers to the reallocated items */
-    LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, mod->groupings, mod->augments, mod->rpcs, mod->notifs));
-
     /* submodules share the namespace with the module names, so there must not be
      * a submodule of the same name in the context, no need for revision matching */
     dup = ly_ctx_get_submodule(ctx->xmlctx->ctx, NULL, mod->mod->name, NULL);
@@ -3765,9 +3743,6 @@
     subelems_deallocator(subelems_size, subelems);
     LY_CHECK_RET(ret);
 
-    /* finalize parent pointers to the reallocated items */
-    LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, submod->groupings, submod->augments, submod->rpcs, submod->notifs));
-
     /* submodules share the namespace with the module names, so there must not be
      * a submodule of the same name in the context, no need for revision matching */
     dup = ly_ctx_get_submodule(ctx->xmlctx->ctx, NULL, submod->name, NULL);
diff --git a/src/printer_yang.c b/src/printer_yang.c
index 7dc0109..2cd9604 100644
--- a/src/printer_yang.c
+++ b/src/printer_yang.c
@@ -991,14 +991,18 @@
 
 static void yprp_node(struct ypr_ctx *ctx, const struct lysp_node *node);
 static void yprc_node(struct ypr_ctx *ctx, const struct lysc_node *node);
-static void yprp_action(struct ypr_ctx *ctx, const struct lysp_action *action);
+static void yprp_action(struct ypr_ctx *ctx, const struct lysp_node_action *action);
+static void yprp_notification(struct ypr_ctx *ctx, const struct lysp_node_notif *notif);
 
 static void
-yprp_grouping(struct ypr_ctx *ctx, const struct lysp_grp *grp)
+yprp_grouping(struct ypr_ctx *ctx, const struct lysp_node_grp *grp)
 {
     LY_ARRAY_COUNT_TYPE u;
     ly_bool flag = 0;
     struct lysp_node *data;
+    struct lysp_node_action *action;
+    struct lysp_node_notif *notif;
+    struct lysp_node_grp *subgrp;
 
     ly_print_(ctx->out, "\n%*sgrouping %s", INDENT, grp->name);
     LEVEL++;
@@ -1013,9 +1017,9 @@
         yprp_typedef(ctx, &grp->typedefs[u]);
     }
 
-    LY_ARRAY_FOR(grp->groupings, u) {
+    LY_LIST_FOR(grp->groupings, subgrp) {
         ypr_open(ctx->out, &flag);
-        yprp_grouping(ctx, &grp->groupings[u]);
+        yprp_grouping(ctx, subgrp);
     }
 
     LY_LIST_FOR(grp->data, data) {
@@ -1023,8 +1027,14 @@
         yprp_node(ctx, data);
     }
 
-    LY_ARRAY_FOR(grp->actions, u) {
-        yprp_action(ctx, &grp->actions[u]);
+    LY_LIST_FOR(grp->actions, action) {
+        ypr_open(ctx->out, &flag);
+        yprp_action(ctx, action);
+    }
+
+    LY_LIST_FOR(grp->notifs, notif) {
+        ypr_open(ctx->out, &flag);
+        yprp_notification(ctx, notif);
     }
 
     LEVEL--;
@@ -1032,10 +1042,11 @@
 }
 
 static void
-yprp_inout(struct ypr_ctx *ctx, const struct lysp_action_inout *inout, ly_bool *flag)
+yprp_inout(struct ypr_ctx *ctx, const struct lysp_node_action_inout *inout, ly_bool *flag)
 {
     LY_ARRAY_COUNT_TYPE u;
     struct lysp_node *data;
+    struct lysp_node_grp *grp;
 
     if (!inout->data) {
         /* no children */
@@ -1053,8 +1064,8 @@
     LY_ARRAY_FOR(inout->typedefs, u) {
         yprp_typedef(ctx, &inout->typedefs[u]);
     }
-    LY_ARRAY_FOR(inout->groupings, u) {
-        yprp_grouping(ctx, &inout->groupings[u]);
+    LY_LIST_FOR(inout->groupings, grp) {
+        yprp_grouping(ctx, grp);
     }
 
     LY_LIST_FOR(inout->data, data) {
@@ -1066,7 +1077,7 @@
 }
 
 static void
-yprc_inout(struct ypr_ctx *ctx, const struct lysc_action *action, const struct lysc_action_inout *inout, ly_bool *flag)
+yprc_inout(struct ypr_ctx *ctx, const struct lysc_node_action *action, const struct lysc_node_action_inout *inout, ly_bool *flag)
 {
     LY_ARRAY_COUNT_TYPE u;
     struct lysc_node *data;
@@ -1080,7 +1091,7 @@
     ly_print_(ctx->out, "\n%*s%s {\n", INDENT, (&action->input == inout) ? "input" : "output");
     LEVEL++;
 
-    yprc_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, (&action->input == inout) ? action->input_exts : action->output_exts, NULL, 0);
+    yprc_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, (&action->input == inout) ? action->input.exts : action->output.exts, NULL, 0);
     LY_ARRAY_FOR(inout->musts, u) {
         yprc_must(ctx, &inout->musts[u], NULL);
     }
@@ -1096,11 +1107,12 @@
 }
 
 static void
-yprp_notification(struct ypr_ctx *ctx, const struct lysp_notif *notif)
+yprp_notification(struct ypr_ctx *ctx, const struct lysp_node_notif *notif)
 {
     LY_ARRAY_COUNT_TYPE u;
     ly_bool flag = 0;
     struct lysp_node *data;
+    struct lysp_node_grp *grp;
 
     ly_print_(ctx->out, "%*snotification %s", INDENT, notif->name);
 
@@ -1120,9 +1132,9 @@
         yprp_typedef(ctx, &notif->typedefs[u]);
     }
 
-    LY_ARRAY_FOR(notif->groupings, u) {
+    LY_LIST_FOR(notif->groupings, grp) {
         ypr_open(ctx->out, &flag);
-        yprp_grouping(ctx, &notif->groupings[u]);
+        yprp_grouping(ctx, grp);
     }
 
     LY_LIST_FOR(notif->data, data) {
@@ -1135,7 +1147,7 @@
 }
 
 static void
-yprc_notification(struct ypr_ctx *ctx, const struct lysc_notif *notif)
+yprc_notification(struct ypr_ctx *ctx, const struct lysc_node_notif *notif)
 {
     LY_ARRAY_COUNT_TYPE u;
     ly_bool flag = 0;
@@ -1165,10 +1177,11 @@
 }
 
 static void
-yprp_action(struct ypr_ctx *ctx, const struct lysp_action *action)
+yprp_action(struct ypr_ctx *ctx, const struct lysp_node_action *action)
 {
     LY_ARRAY_COUNT_TYPE u;
     ly_bool flag = 0;
+    struct lysp_node_grp *grp;
 
     ly_print_(ctx->out, "%*s%s %s", INDENT, action->parent ? "action" : "rpc", action->name);
 
@@ -1184,9 +1197,9 @@
         yprp_typedef(ctx, &action->typedefs[u]);
     }
 
-    LY_ARRAY_FOR(action->groupings, u) {
+    LY_LIST_FOR(action->groupings, grp) {
         ypr_open(ctx->out, &flag);
-        yprp_grouping(ctx, &action->groupings[u]);
+        yprp_grouping(ctx, grp);
     }
 
     yprp_inout(ctx, &action->input, &flag);
@@ -1197,7 +1210,7 @@
 }
 
 static void
-yprc_action(struct ypr_ctx *ctx, const struct lysc_action *action)
+yprc_action(struct ypr_ctx *ctx, const struct lysc_node_action *action)
 {
     ly_bool flag = 0;
 
@@ -1271,6 +1284,9 @@
     LY_ARRAY_COUNT_TYPE u;
     ly_bool flag = 0;
     struct lysp_node *child;
+    struct lysp_node_action *action;
+    struct lysp_node_notif *notif;
+    struct lysp_node_grp *grp;
     struct lysp_node_container *cont = (struct lysp_node_container *)node;
 
     yprp_node_common1(ctx, node, &flag);
@@ -1290,9 +1306,9 @@
         yprp_typedef(ctx, &cont->typedefs[u]);
     }
 
-    LY_ARRAY_FOR(cont->groupings, u) {
+    LY_LIST_FOR(cont->groupings, grp) {
         ypr_open(ctx->out, &flag);
-        yprp_grouping(ctx, &cont->groupings[u]);
+        yprp_grouping(ctx, grp);
     }
 
     LY_LIST_FOR(cont->child, child) {
@@ -1300,14 +1316,14 @@
         yprp_node(ctx, child);
     }
 
-    LY_ARRAY_FOR(cont->actions, u) {
+    LY_LIST_FOR(cont->actions, action) {
         ypr_open(ctx->out, &flag);
-        yprp_action(ctx, &cont->actions[u]);
+        yprp_action(ctx, action);
     }
 
-    LY_ARRAY_FOR(cont->notifs, u) {
+    LY_LIST_FOR(cont->notifs, notif) {
         ypr_open(ctx->out, &flag);
-        yprp_notification(ctx, &cont->notifs[u]);
+        yprp_notification(ctx, notif);
     }
 
     LEVEL--;
@@ -1320,6 +1336,8 @@
     LY_ARRAY_COUNT_TYPE u;
     ly_bool flag = 0;
     struct lysc_node *child;
+    struct lysc_node_action *action;
+    struct lysc_node_notif *notif;
     struct lysc_node_container *cont = (struct lysc_node_container *)node;
 
     yprc_node_common1(ctx, node, &flag);
@@ -1340,14 +1358,14 @@
             yprc_node(ctx, child);
         }
 
-        LY_ARRAY_FOR(cont->actions, u) {
+        LY_LIST_FOR(cont->actions, action) {
             ypr_open(ctx->out, &flag);
-            yprc_action(ctx, &cont->actions[u]);
+            yprc_action(ctx, action);
         }
 
-        LY_ARRAY_FOR(cont->notifs, u) {
+        LY_LIST_FOR(cont->notifs, notif) {
             ypr_open(ctx->out, &flag);
-            yprc_notification(ctx, &cont->notifs[u]);
+            yprc_notification(ctx, notif);
         }
     }
 
@@ -1573,6 +1591,9 @@
     LY_ARRAY_COUNT_TYPE u;
     ly_bool flag = 0;
     struct lysp_node *child;
+    struct lysp_node_action *action;
+    struct lysp_node_notif *notif;
+    struct lysp_node_grp *grp;
     struct lysp_node_list *list = (struct lysp_node_list *)node;
 
     yprp_node_common1(ctx, node, &flag);
@@ -1617,9 +1638,9 @@
         yprp_typedef(ctx, &list->typedefs[u]);
     }
 
-    LY_ARRAY_FOR(list->groupings, u) {
+    LY_LIST_FOR(list->groupings, grp) {
         ypr_open(ctx->out, &flag);
-        yprp_grouping(ctx, &list->groupings[u]);
+        yprp_grouping(ctx, grp);
     }
 
     LY_LIST_FOR(list->child, child) {
@@ -1627,14 +1648,14 @@
         yprp_node(ctx, child);
     }
 
-    LY_ARRAY_FOR(list->actions, u) {
+    LY_LIST_FOR(list->actions, action) {
         ypr_open(ctx->out, &flag);
-        yprp_action(ctx, &list->actions[u]);
+        yprp_action(ctx, action);
     }
 
-    LY_ARRAY_FOR(list->notifs, u) {
+    LY_LIST_FOR(list->notifs, notif) {
         ypr_open(ctx->out, &flag);
-        yprp_notification(ctx, &list->notifs[u]);
+        yprp_notification(ctx, notif);
     }
 
     LEVEL--;
@@ -1645,7 +1666,6 @@
 yprc_list(struct ypr_ctx *ctx, const struct lysc_node *node)
 {
     LY_ARRAY_COUNT_TYPE u, v;
-    struct lysc_node *child;
     struct lysc_node_list *list = (struct lysc_node_list *)node;
 
     yprc_node_common1(ctx, node, NULL);
@@ -1684,16 +1704,20 @@
     ypr_reference(ctx, node->ref, node->exts, NULL);
 
     if (!(ctx->options & LYS_PRINT_NO_SUBSTMT)) {
+        struct lysc_node *child;
+        struct lysc_node_action *action;
+        struct lysc_node_notif *notif;
+
         LY_LIST_FOR(list->child, child) {
             yprc_node(ctx, child);
         }
 
-        LY_ARRAY_FOR(list->actions, u) {
-            yprc_action(ctx, &list->actions[u]);
+        LY_LIST_FOR(list->actions, action) {
+            yprc_action(ctx, action);
         }
 
-        LY_ARRAY_FOR(list->notifs, u) {
-            yprc_notification(ctx, &list->notifs[u]);
+        LY_LIST_FOR(list->notifs, notif) {
+            yprc_notification(ctx, notif);
         }
     }
 
@@ -1752,10 +1776,11 @@
 }
 
 static void
-yprp_augment(struct ypr_ctx *ctx, const struct lysp_augment *aug)
+yprp_augment(struct ypr_ctx *ctx, const struct lysp_node_augment *aug)
 {
-    LY_ARRAY_COUNT_TYPE u;
     struct lysp_node *child;
+    struct lysp_node_action *action;
+    struct lysp_node_notif *notif;
 
     ly_print_(ctx->out, "%*saugment \"%s\" {\n", INDENT, aug->nodeid);
     LEVEL++;
@@ -1771,12 +1796,12 @@
         yprp_node(ctx, child);
     }
 
-    LY_ARRAY_FOR(aug->actions, u) {
-        yprp_action(ctx, &aug->actions[u]);
+    LY_LIST_FOR(aug->actions, action) {
+        yprp_action(ctx, action);
     }
 
-    LY_ARRAY_FOR(aug->notifs, u) {
-        yprp_notification(ctx, &aug->notifs[u]);
+    LY_LIST_FOR(aug->notifs, notif) {
+        yprp_notification(ctx, notif);
     }
 
     LEVEL--;
@@ -1789,6 +1814,7 @@
     LY_ARRAY_COUNT_TYPE u;
     ly_bool flag = 0;
     struct lysp_node_uses *uses = (struct lysp_node_uses *)node;
+    struct lysp_node_augment *aug;
 
     yprp_node_common1(ctx, node, &flag);
     yprp_node_common2(ctx, node, &flag);
@@ -1798,9 +1824,9 @@
         yprp_refine(ctx, &uses->refines[u]);
     }
 
-    LY_ARRAY_FOR(uses->augments, u) {
+    LY_LIST_FOR(uses->augments, aug) {
         ypr_open(ctx->out, &flag);
-        yprp_augment(ctx, &uses->augments[u]);
+        yprp_augment(ctx, aug);
     }
 
     LEVEL--;
@@ -2063,6 +2089,10 @@
 {
     LY_ARRAY_COUNT_TYPE u;
     struct lysp_node *data;
+    struct lysp_node_action *action;
+    struct lysp_node_notif *notif;
+    struct lysp_node_grp *grp;
+    struct lysp_node_augment *aug;
 
     LY_ARRAY_FOR(modp->extensions, u) {
         ly_print_(ctx->out, "\n");
@@ -2085,24 +2115,24 @@
         yprp_typedef(ctx, &modp->typedefs[u]);
     }
 
-    LY_ARRAY_FOR(modp->groupings, u) {
-        yprp_grouping(ctx, &modp->groupings[u]);
+    LY_LIST_FOR(modp->groupings, grp) {
+        yprp_grouping(ctx, grp);
     }
 
     LY_LIST_FOR(modp->data, data) {
         yprp_node(ctx, data);
     }
 
-    LY_ARRAY_FOR(modp->augments, u) {
-        yprp_augment(ctx, &modp->augments[u]);
+    LY_LIST_FOR(modp->augments, aug) {
+        yprp_augment(ctx, aug);
     }
 
-    LY_ARRAY_FOR(modp->rpcs, u) {
-        yprp_action(ctx, &modp->rpcs[u]);
+    LY_LIST_FOR(modp->rpcs, action) {
+        yprp_action(ctx, action);
     }
 
-    LY_ARRAY_FOR(modp->notifs, u) {
-        yprp_notification(ctx, &modp->notifs[u]);
+    LY_LIST_FOR(modp->notifs, notif) {
+        yprp_notification(ctx, notif);
     }
 
     LY_ARRAY_FOR(modp->deviations, u) {
@@ -2227,7 +2257,6 @@
 yang_print_compiled(struct ly_out *out, const struct lys_module *module, uint32_t options)
 {
     LY_ARRAY_COUNT_TYPE u;
-    struct lysc_node *data;
     struct lysc_module *modc = module->compiled;
     struct ypr_ctx ctx_ = {.out = out, .level = 0, .module = module, .options = options}, *ctx = &ctx_;
 
@@ -2265,16 +2294,20 @@
     }
 
     if (!(ctx->options & LYS_PRINT_NO_SUBSTMT)) {
+        struct lysc_node *data;
+        struct lysc_node_action *rpc;
+        struct lysc_node_notif *notif;
+
         LY_LIST_FOR(modc->data, data) {
             yprc_node(ctx, data);
         }
 
-        LY_ARRAY_FOR(modc->rpcs, u) {
-            yprc_action(ctx, &modc->rpcs[u]);
+        LY_LIST_FOR(modc->rpcs, rpc) {
+            yprc_action(ctx, rpc);
         }
 
-        LY_ARRAY_FOR(modc->notifs, u) {
-            yprc_notification(ctx, &modc->notifs[u]);
+        LY_LIST_FOR(modc->notifs, notif) {
+            yprc_notification(ctx, notif);
         }
     }
 
diff --git a/src/printer_yin.c b/src/printer_yin.c
index 8926394..d1e56b4 100644
--- a/src/printer_yin.c
+++ b/src/printer_yin.c
@@ -504,14 +504,18 @@
 }
 
 static void yprp_node(struct ypr_ctx *ctx, const struct lysp_node *node);
-static void yprp_action(struct ypr_ctx *ctx, const struct lysp_action *action);
+static void yprp_action(struct ypr_ctx *ctx, const struct lysp_node_action *action);
+static void yprp_notification(struct ypr_ctx *ctx, const struct lysp_node_notif *notif);
 
 static void
-yprp_grouping(struct ypr_ctx *ctx, const struct lysp_grp *grp)
+yprp_grouping(struct ypr_ctx *ctx, const struct lysp_node_grp *grp)
 {
     LY_ARRAY_COUNT_TYPE u;
     int8_t flag = 0;
     struct lysp_node *data;
+    struct lysp_node_action *action;
+    struct lysp_node_notif *notif;
+    struct lysp_node_grp *subgrp;
 
     ypr_open(ctx, "grouping", "name", grp->name, flag);
     LEVEL++;
@@ -526,9 +530,9 @@
         yprp_typedef(ctx, &grp->typedefs[u]);
     }
 
-    LY_ARRAY_FOR(grp->groupings, u) {
+    LY_LIST_FOR(grp->groupings, subgrp) {
         ypr_close_parent(ctx, &flag);
-        yprp_grouping(ctx, &grp->groupings[u]);
+        yprp_grouping(ctx, subgrp);
     }
 
     LY_LIST_FOR(grp->data, data) {
@@ -536,9 +540,14 @@
         yprp_node(ctx, data);
     }
 
-    LY_ARRAY_FOR(grp->actions, u) {
+    LY_LIST_FOR(grp->actions, action) {
         ypr_close_parent(ctx, &flag);
-        yprp_action(ctx, &grp->actions[u]);
+        yprp_action(ctx, action);
+    }
+
+    LY_LIST_FOR(grp->notifs, notif) {
+        ypr_close_parent(ctx, &flag);
+        yprp_notification(ctx, notif);
     }
 
     LEVEL--;
@@ -546,10 +555,11 @@
 }
 
 static void
-yprp_inout(struct ypr_ctx *ctx, const struct lysp_action_inout *inout, int8_t *flag)
+yprp_inout(struct ypr_ctx *ctx, const struct lysp_node_action_inout *inout, int8_t *flag)
 {
     LY_ARRAY_COUNT_TYPE u;
     struct lysp_node *data;
+    struct lysp_node_grp *grp;
 
     if (!inout->data) {
         /* input/output is empty */
@@ -567,8 +577,8 @@
     LY_ARRAY_FOR(inout->typedefs, u) {
         yprp_typedef(ctx, &inout->typedefs[u]);
     }
-    LY_ARRAY_FOR(inout->groupings, u) {
-        yprp_grouping(ctx, &inout->groupings[u]);
+    LY_LIST_FOR(inout->groupings, grp) {
+        yprp_grouping(ctx, grp);
     }
 
     LY_LIST_FOR(inout->data, data) {
@@ -580,11 +590,12 @@
 }
 
 static void
-yprp_notification(struct ypr_ctx *ctx, const struct lysp_notif *notif)
+yprp_notification(struct ypr_ctx *ctx, const struct lysp_node_notif *notif)
 {
     LY_ARRAY_COUNT_TYPE u;
     int8_t flag = 0;
     struct lysp_node *data;
+    struct lysp_node_grp *grp;
 
     ypr_open(ctx, "notification", "name", notif->name, flag);
 
@@ -605,9 +616,9 @@
         yprp_typedef(ctx, &notif->typedefs[u]);
     }
 
-    LY_ARRAY_FOR(notif->groupings, u) {
+    LY_LIST_FOR(notif->groupings, grp) {
         ypr_close_parent(ctx, &flag);
-        yprp_grouping(ctx, &notif->groupings[u]);
+        yprp_grouping(ctx, grp);
     }
 
     LY_LIST_FOR(notif->data, data) {
@@ -620,10 +631,11 @@
 }
 
 static void
-yprp_action(struct ypr_ctx *ctx, const struct lysp_action *action)
+yprp_action(struct ypr_ctx *ctx, const struct lysp_node_action *action)
 {
     LY_ARRAY_COUNT_TYPE u;
     int8_t flag = 0;
+    struct lysp_node_grp *grp;
 
     ypr_open(ctx, action->parent ? "action" : "rpc", "name", action->name, flag);
 
@@ -639,9 +651,9 @@
         yprp_typedef(ctx, &action->typedefs[u]);
     }
 
-    LY_ARRAY_FOR(action->groupings, u) {
+    LY_LIST_FOR(action->groupings, grp) {
         ypr_close_parent(ctx, &flag);
-        yprp_grouping(ctx, &action->groupings[u]);
+        yprp_grouping(ctx, grp);
     }
 
     yprp_inout(ctx, &action->input, &flag);
@@ -680,6 +692,9 @@
     LY_ARRAY_COUNT_TYPE u;
     int8_t flag = 0;
     struct lysp_node *child;
+    struct lysp_node_action *action;
+    struct lysp_node_notif *notif;
+    struct lysp_node_grp *grp;
     struct lysp_node_container *cont = (struct lysp_node_container *)node;
 
     yprp_node_common1(ctx, node, &flag);
@@ -700,9 +715,9 @@
         yprp_typedef(ctx, &cont->typedefs[u]);
     }
 
-    LY_ARRAY_FOR(cont->groupings, u) {
+    LY_LIST_FOR(cont->groupings, grp) {
         ypr_close_parent(ctx, &flag);
-        yprp_grouping(ctx, &cont->groupings[u]);
+        yprp_grouping(ctx, grp);
     }
 
     LY_LIST_FOR(cont->child, child) {
@@ -710,14 +725,14 @@
         yprp_node(ctx, child);
     }
 
-    LY_ARRAY_FOR(cont->actions, u) {
+    LY_LIST_FOR(cont->actions, action) {
         ypr_close_parent(ctx, &flag);
-        yprp_action(ctx, &cont->actions[u]);
+        yprp_action(ctx, action);
     }
 
-    LY_ARRAY_FOR(cont->notifs, u) {
+    LY_LIST_FOR(cont->notifs, notif) {
         ypr_close_parent(ctx, &flag);
-        yprp_notification(ctx, &cont->notifs[u]);
+        yprp_notification(ctx, notif);
     }
 
     LEVEL--;
@@ -840,6 +855,9 @@
     LY_ARRAY_COUNT_TYPE u;
     int8_t flag = 0;
     struct lysp_node *child;
+    struct lysp_node_action *action;
+    struct lysp_node_notif *notif;
+    struct lysp_node_grp *grp;
     struct lysp_node_list *list = (struct lysp_node_list *)node;
 
     yprp_node_common1(ctx, node, &flag);
@@ -884,9 +902,9 @@
         yprp_typedef(ctx, &list->typedefs[u]);
     }
 
-    LY_ARRAY_FOR(list->groupings, u) {
+    LY_LIST_FOR(list->groupings, grp) {
         ypr_close_parent(ctx, &flag);
-        yprp_grouping(ctx, &list->groupings[u]);
+        yprp_grouping(ctx, grp);
     }
 
     LY_LIST_FOR(list->child, child) {
@@ -894,14 +912,14 @@
         yprp_node(ctx, child);
     }
 
-    LY_ARRAY_FOR(list->actions, u) {
+    LY_LIST_FOR(list->actions, action) {
         ypr_close_parent(ctx, &flag);
-        yprp_action(ctx, &list->actions[u]);
+        yprp_action(ctx, action);
     }
 
-    LY_ARRAY_FOR(list->notifs, u) {
+    LY_LIST_FOR(list->notifs, notif) {
         ypr_close_parent(ctx, &flag);
-        yprp_notification(ctx, &list->notifs[u]);
+        yprp_notification(ctx, notif);
     }
 
     LEVEL--;
@@ -959,10 +977,11 @@
 }
 
 static void
-yprp_augment(struct ypr_ctx *ctx, const struct lysp_augment *aug)
+yprp_augment(struct ypr_ctx *ctx, const struct lysp_node_augment *aug)
 {
-    LY_ARRAY_COUNT_TYPE u;
     struct lysp_node *child;
+    struct lysp_node_action *action;
+    struct lysp_node_notif *notif;
 
     ypr_open(ctx, "augment", "target-node", aug->nodeid, 1);
     LEVEL++;
@@ -978,12 +997,12 @@
         yprp_node(ctx, child);
     }
 
-    LY_ARRAY_FOR(aug->actions, u) {
-        yprp_action(ctx, &aug->actions[u]);
+    LY_LIST_FOR(aug->actions, action) {
+        yprp_action(ctx, action);
     }
 
-    LY_ARRAY_FOR(aug->notifs, u) {
-        yprp_notification(ctx, &aug->notifs[u]);
+    LY_LIST_FOR(aug->notifs, notif) {
+        yprp_notification(ctx, notif);
     }
 
     LEVEL--;
@@ -996,6 +1015,7 @@
     LY_ARRAY_COUNT_TYPE u;
     int8_t flag = 0;
     struct lysp_node_uses *uses = (struct lysp_node_uses *)node;
+    struct lysp_node_augment *aug;
 
     yprp_node_common1(ctx, node, &flag);
     yprp_node_common2(ctx, node, &flag);
@@ -1005,9 +1025,9 @@
         yprp_refine(ctx, &uses->refines[u]);
     }
 
-    LY_ARRAY_FOR(uses->augments, u) {
+    LY_LIST_FOR(uses->augments, aug) {
         ypr_close_parent(ctx, &flag);
-        yprp_augment(ctx, &uses->augments[u]);
+        yprp_augment(ctx, aug);
     }
 
     LEVEL--;
@@ -1416,6 +1436,10 @@
 {
     LY_ARRAY_COUNT_TYPE u;
     struct lysp_node *data;
+    struct lysp_node_action *action;
+    struct lysp_node_notif *notif;
+    struct lysp_node_grp *grp;
+    struct lysp_node_augment *aug;
 
     LY_ARRAY_FOR(modp->extensions, u) {
         ly_print_(ctx->out, "\n");
@@ -1438,24 +1462,24 @@
         yprp_typedef(ctx, &modp->typedefs[u]);
     }
 
-    LY_ARRAY_FOR(modp->groupings, u) {
-        yprp_grouping(ctx, &modp->groupings[u]);
+    LY_LIST_FOR(modp->groupings, grp) {
+        yprp_grouping(ctx, grp);
     }
 
     LY_LIST_FOR(modp->data, data) {
         yprp_node(ctx, data);
     }
 
-    LY_ARRAY_FOR(modp->augments, u) {
-        yprp_augment(ctx, &modp->augments[u]);
+    LY_LIST_FOR(modp->augments, aug) {
+        yprp_augment(ctx, aug);
     }
 
-    LY_ARRAY_FOR(modp->rpcs, u) {
-        yprp_action(ctx, &modp->rpcs[u]);
+    LY_LIST_FOR(modp->rpcs, action) {
+        yprp_action(ctx, action);
     }
 
-    LY_ARRAY_FOR(modp->notifs, u) {
-        yprp_notification(ctx, &modp->notifs[u]);
+    LY_LIST_FOR(modp->notifs, notif) {
+        yprp_notification(ctx, notif);
     }
 
     LY_ARRAY_FOR(modp->deviations, u) {
diff --git a/src/schema_compile.c b/src/schema_compile.c
index 44821bc..a692b7b 100644
--- a/src/schema_compile.c
+++ b/src/schema_compile.c
@@ -969,14 +969,14 @@
         when = ((struct lysc_node_case *)node)->when;
         break;
     case LYS_NOTIF:
-        when = ((struct lysc_notif *)node)->when;
-        musts = ((struct lysc_notif *)node)->musts;
+        when = ((struct lysc_node_notif *)node)->when;
+        musts = ((struct lysc_node_notif *)node)->musts;
         break;
     case LYS_RPC:
     case LYS_ACTION:
         /* first process when and input musts */
-        when = ((struct lysc_action *)node)->when;
-        musts = ((struct lysc_action *)node)->input.musts;
+        when = ((struct lysc_node_action *)node)->when;
+        musts = ((struct lysc_node_action *)node)->input.musts;
         break;
     default:
         /* nothing to check */
@@ -1073,7 +1073,7 @@
         /* now check output musts */
         input_done = 1;
         when = NULL;
-        musts = ((struct lysc_action *)node)->output.musts;
+        musts = ((struct lysc_node_action *)node)->output.musts;
         opts = LYXP_SCNODE_OUTPUT;
         goto check_musts;
     }
@@ -1475,31 +1475,10 @@
 lys_compile_unres_mod(struct lysc_ctx *ctx)
 {
     struct lysc_node *node;
-    struct lysc_action **actions;
-    struct lysc_notif **notifs;
     struct lysc_augment *aug;
     struct lysc_deviation *dev;
-    struct ly_set disabled_op = {0};
     uint32_t i;
 
-#define ARRAY_DEL_ITEM(array, item) \
-    { \
-        LY_ARRAY_COUNT_TYPE u__; \
-        LY_ARRAY_FOR(array, u__) { \
-            if ((array) + u__ == item) { \
-                LY_ARRAY_DECREMENT(array); \
-                if (u__ < LY_ARRAY_COUNT(array)) { \
-                    memmove((array) + u__, (array) + u__ + 1, (LY_ARRAY_COUNT(array) - u__) * sizeof *(array)); \
-                } \
-                if (!LY_ARRAY_COUNT(array)) { \
-                    LY_ARRAY_FREE(array); \
-                    (array) = NULL; \
-                } \
-                break; \
-            } \
-        } \
-    }
-
     /* remove all disabled nodes */
     for (i = 0; i < ctx->disabled.count; ++i) {
         node = ctx->disabled.snodes[i];
@@ -1510,47 +1489,9 @@
             return LY_EVALID;
         }
 
-        if (node->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) {
-            /* just remember all RPCs/actions/notifs for now */
-            ly_set_add(&disabled_op, node, 1, NULL);
-        } else {
-            lysc_node_free(ctx->ctx, node, 1);
-        }
+        lysc_node_free(ctx->ctx, node, 1);
     }
 
-    /* remove ops also from their arrays, from end so as not to move other items and change these pointer targets */
-    i = disabled_op.count;
-    while (i) {
-        --i;
-        node = disabled_op.snodes[i];
-        if (node->nodetype == LYS_RPC) {
-            actions = &node->module->compiled->rpcs;
-            assert(actions);
-            notifs = NULL;
-        } else if (node->nodetype == LYS_ACTION) {
-            actions = lysc_node_actions_p(node->parent);
-            assert(actions);
-            notifs = NULL;
-        } else if (node->parent) {
-            actions = NULL;
-            notifs = lysc_node_notifs_p(node->parent);
-            assert(notifs);
-        } else {
-            actions = NULL;
-            notifs = &node->module->compiled->notifs;
-            assert(notifs);
-        }
-
-        if (actions) {
-            lysc_action_free(ctx->ctx, (struct lysc_action *)node);
-            ARRAY_DEL_ITEM(*actions, (struct lysc_action *)node);
-        } else {
-            lysc_notif_free(ctx->ctx, (struct lysc_notif *)node);
-            ARRAY_DEL_ITEM(*notifs, (struct lysc_notif *)node);
-        }
-    }
-    ly_set_erase(&disabled_op, NULL);
-
     /* check that all augments were applied */
     for (i = 0; i < ctx->augs.count; ++i) {
         aug = ctx->augs.objs[i];
@@ -1580,7 +1521,6 @@
     }
 
     return LY_SUCCESS;
-#undef ARRAY_DEL_ITEM
 }
 
 /**
@@ -1730,8 +1670,8 @@
     struct lysp_module *sp;
     struct lysp_submodule *submod;
     struct lysp_node *pnode;
-    struct lysp_grp *grps;
-    LY_ARRAY_COUNT_TYPE u, v;
+    struct lysp_node_grp *grp;
+    LY_ARRAY_COUNT_TYPE u;
     LY_ERR ret = LY_SUCCESS;
 
     LY_CHECK_ARG_RET(NULL, mod, mod->parsed, !mod->compiled, mod->ctx, LY_EINVAL);
@@ -1778,9 +1718,15 @@
         LY_CHECK_GOTO(ret = lys_compile_node(&ctx, pnode, NULL, 0, NULL), error);
     }
 
-    /* top-level RPCs and notifications */
-    COMPILE_OP_ARRAY_GOTO(&ctx, sp->rpcs, mod_c->rpcs, NULL, lys_compile_action, 0, ret, error);
-    COMPILE_OP_ARRAY_GOTO(&ctx, sp->notifs, mod_c->notifs, NULL, lys_compile_notif, 0, ret, error);
+    /* top-level RPCs */
+    LY_LIST_FOR((struct lysp_node *)sp->rpcs, pnode) {
+        LY_CHECK_GOTO(ret = lys_compile_node(&ctx, pnode, NULL, 0, NULL), error);
+    }
+
+    /* top-level notifications */
+    LY_LIST_FOR((struct lysp_node *)sp->notifs, pnode) {
+        LY_CHECK_GOTO(ret = lys_compile_node(&ctx, pnode, NULL, 0, NULL), error);
+    }
 
     /* extension instances */
     COMPILE_EXTS_GOTO(&ctx, sp->exts, mod_c->exts, mod_c, LYEXT_PAR_MODULE, ret, error);
@@ -1795,8 +1741,15 @@
             LY_CHECK_GOTO(ret, error);
         }
 
-        COMPILE_OP_ARRAY_GOTO(&ctx, submod->rpcs, mod_c->rpcs, NULL, lys_compile_action, 0, ret, error);
-        COMPILE_OP_ARRAY_GOTO(&ctx, submod->notifs, mod_c->notifs, NULL, lys_compile_notif, 0, ret, error);
+        LY_LIST_FOR((struct lysp_node *)submod->rpcs, pnode) {
+            ret = lys_compile_node(&ctx, pnode, NULL, 0, NULL);
+            LY_CHECK_GOTO(ret, error);
+        }
+
+        LY_LIST_FOR((struct lysp_node *)submod->notifs, pnode) {
+            ret = lys_compile_node(&ctx, pnode, NULL, 0, NULL);
+            LY_CHECK_GOTO(ret, error);
+        }
 
         COMPILE_EXTS_GOTO(&ctx, submod->exts, mod_c->exts, mod_c, LYEXT_PAR_MODULE, ret, error);
     }
@@ -1805,16 +1758,15 @@
     /* validate non-instantiated groupings from the parsed schema,
      * without it we would accept even the schemas with invalid grouping specification */
     ctx.options |= LYS_COMPILE_GROUPING;
-    LY_ARRAY_FOR(sp->groupings, u) {
-        if (!(sp->groupings[u].flags & LYS_USED_GRP)) {
-            LY_CHECK_GOTO(ret = lys_compile_grouping(&ctx, NULL, &sp->groupings[u]), error);
+    LY_LIST_FOR(sp->groupings, grp) {
+        if (!(grp->flags & LYS_USED_GRP)) {
+            LY_CHECK_GOTO(ret = lys_compile_grouping(&ctx, NULL, grp), error);
         }
     }
     LY_LIST_FOR(sp->data, pnode) {
-        grps = (struct lysp_grp *)lysp_node_groupings(pnode);
-        LY_ARRAY_FOR(grps, u) {
-            if (!(grps[u].flags & LYS_USED_GRP)) {
-                LY_CHECK_GOTO(ret = lys_compile_grouping(&ctx, pnode, &grps[u]), error);
+        LY_LIST_FOR((struct lysp_node_grp *)lysp_node_groupings(pnode), grp) {
+            if (!(grp->flags & LYS_USED_GRP)) {
+                LY_CHECK_GOTO(ret = lys_compile_grouping(&ctx, pnode, grp), error);
             }
         }
     }
@@ -1822,16 +1774,15 @@
         submod = sp->includes[u].submodule;
         ctx.pmod = (struct lysp_module *)submod;
 
-        LY_ARRAY_FOR(submod->groupings, v) {
-            if (!(submod->groupings[v].flags & LYS_USED_GRP)) {
-                LY_CHECK_GOTO(ret = lys_compile_grouping(&ctx, NULL, &submod->groupings[v]), error);
+        LY_LIST_FOR(submod->groupings, grp) {
+            if (!(grp->flags & LYS_USED_GRP)) {
+                LY_CHECK_GOTO(ret = lys_compile_grouping(&ctx, NULL, grp), error);
             }
         }
         LY_LIST_FOR(submod->data, pnode) {
-            grps = (struct lysp_grp *)lysp_node_groupings(pnode);
-            LY_ARRAY_FOR(grps, v) {
-                if (!(grps[v].flags & LYS_USED_GRP)) {
-                    LY_CHECK_GOTO(ret = lys_compile_grouping(&ctx, pnode, &grps[v]), error);
+            LY_LIST_FOR((struct lysp_node_grp *)lysp_node_groupings(pnode), grp) {
+                if (!(grp->flags & LYS_USED_GRP)) {
+                    LY_CHECK_GOTO(ret = lys_compile_grouping(&ctx, pnode, grp), error);
                 }
             }
         }
diff --git a/src/schema_compile_amend.c b/src/schema_compile_amend.c
index faf2c84..7a24c76 100644
--- a/src/schema_compile_amend.c
+++ b/src/schema_compile_amend.c
@@ -174,19 +174,20 @@
 lys_precompile_uses_augments_refines(struct lysc_ctx *ctx, struct lysp_node_uses *uses_p, const struct lysc_node *ctx_node)
 {
     LY_ERR ret = LY_SUCCESS;
-    LY_ARRAY_COUNT_TYPE u;
     struct lyxp_expr *exp = NULL;
     struct lysc_augment *aug;
+    struct lysp_node_augment *aug_p;
     struct lysc_refine *rfn;
     struct lysp_refine **new_rfn;
+    LY_ARRAY_COUNT_TYPE u;
     uint32_t i;
 
-    LY_ARRAY_FOR(uses_p->augments, u) {
+    LY_LIST_FOR(uses_p->augments, aug_p) {
         lysc_update_path(ctx, NULL, "{augment}");
-        lysc_update_path(ctx, NULL, uses_p->augments[u].nodeid);
+        lysc_update_path(ctx, NULL, aug_p->nodeid);
 
         /* parse the nodeid */
-        LY_CHECK_GOTO(ret = lys_nodeid_check(ctx, uses_p->augments[u].nodeid, 0, NULL, &exp), cleanup);
+        LY_CHECK_GOTO(ret = lys_nodeid_check(ctx, aug_p->nodeid, 0, NULL, &exp), cleanup);
 
         /* allocate new compiled augment and store it in the set */
         aug = calloc(1, sizeof *aug);
@@ -197,7 +198,7 @@
         exp = NULL;
         aug->nodeid_pmod = ctx->pmod;
         aug->nodeid_ctx_node = ctx_node;
-        aug->aug_p = &uses_p->augments[u];
+        aug->aug_p = aug_p;
 
         lysc_update_path(ctx, NULL, NULL);
         lysc_update_path(ctx, NULL, NULL);
@@ -416,8 +417,15 @@
     const struct lysp_node_case *orig_cas;
     struct lysp_node_anydata *any;
     const struct lysp_node_anydata *orig_any;
+    struct lysp_node_action *action;
+    const struct lysp_node_action *orig_action;
+    struct lysp_node_action_inout *action_inout;
+    const struct lysp_node_action_inout *orig_action_inout;
+    struct lysp_node_notif *notif;
+    const struct lysp_node_notif *orig_notif;
 
-    assert(orig->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CHOICE | LYS_CASE | LYS_ANYDATA));
+    assert(orig->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CHOICE | LYS_CASE | LYS_ANYDATA |
+            LYS_RPC | LYS_ACTION | LYS_NOTIF));
 
     /* common part */
     LY_CHECK_RET(lysp_node_common_dup(ctx, node, orig));
@@ -485,6 +493,30 @@
 
         DUP_ARRAY(ctx, orig_any->musts, any->musts, lysp_restr_dup);
         break;
+    case LYS_RPC:
+    case LYS_ACTION:
+        action = (struct lysp_node_action *)node;
+        orig_action = (const struct lysp_node_action *)orig;
+
+        action->input.nodetype = orig_action->input.nodetype;
+        action->output.nodetype = orig_action->output.nodetype;
+        /* we do not need the rest */
+        break;
+    case LYS_INPUT:
+    case LYS_OUTPUT:
+        action_inout = (struct lysp_node_action_inout *)node;
+        orig_action_inout = (const struct lysp_node_action_inout *)orig;
+
+        DUP_ARRAY(ctx, orig_action_inout->musts, action_inout->musts, lysp_restr_dup);
+        /* we do not need the rest */
+        break;
+    case LYS_NOTIF:
+        notif = (struct lysp_node_notif *)node;
+        orig_notif = (const struct lysp_node_notif *)orig;
+
+        DUP_ARRAY(ctx, orig_notif->musts, notif->musts, lysp_restr_dup);
+        /* we do not need the rest */
+        break;
     default:
         LOGINT_RET(ctx);
     }
@@ -492,58 +524,6 @@
     return ret;
 }
 
-static LY_ERR
-lysp_action_inout_dup(const struct ly_ctx *ctx, struct lysp_action_inout *inout, const struct lysp_action_inout *orig)
-{
-    inout->parent = NULL;
-    inout->nodetype = orig->nodetype;
-    DUP_ARRAY(ctx, orig->musts, inout->musts, lysp_restr_dup);
-    /* we dot need these arrays */
-    DUP_ARRAY(ctx, orig->exts, inout->exts, lysp_ext_dup);
-
-    return LY_SUCCESS;
-}
-
-static LY_ERR
-lysp_action_dup(const struct ly_ctx *ctx, struct lysp_action *act, const struct lysp_action *orig)
-{
-    LY_ERR ret = LY_SUCCESS;
-
-    act->parent = NULL;
-    act->nodetype = orig->nodetype;
-    act->flags = orig->flags;
-    DUP_STRING(ctx, orig->name, act->name, ret);
-    DUP_STRING(ctx, orig->dsc, act->dsc, ret);
-    DUP_STRING(ctx, orig->ref, act->ref, ret);
-    DUP_ARRAY(ctx, orig->iffeatures, act->iffeatures, lysp_qname_dup);
-
-    act->input.nodetype = orig->input.nodetype;
-    act->output.nodetype = orig->output.nodetype;
-    /* we do not need choldren of in/out */
-    DUP_ARRAY(ctx, orig->exts, act->exts, lysp_ext_dup);
-
-    return ret;
-}
-
-static LY_ERR
-lysp_notif_dup(const struct ly_ctx *ctx, struct lysp_notif *notif, const struct lysp_notif *orig)
-{
-    LY_ERR ret = LY_SUCCESS;
-
-    notif->parent = NULL;
-    notif->nodetype = orig->nodetype;
-    notif->flags = orig->flags;
-    DUP_STRING(ctx, orig->name, notif->name, ret);
-    DUP_STRING(ctx, orig->dsc, notif->dsc, ret);
-    DUP_STRING(ctx, orig->ref, notif->ref, ret);
-    DUP_ARRAY(ctx, orig->iffeatures, notif->iffeatures, lysp_qname_dup);
-    DUP_ARRAY(ctx, orig->musts, notif->musts, lysp_restr_dup);
-    /* we do not need these arrays */
-    DUP_ARRAY(ctx, orig->exts, notif->exts, lysp_ext_dup);
-
-    return ret;
-}
-
 /**
  * @brief Duplicate a single parsed node. Only attributes that are used in compilation are copied.
  *
@@ -567,60 +547,42 @@
     switch (pnode->nodetype) {
     case LYS_CONTAINER:
         mem = calloc(1, sizeof(struct lysp_node_container));
-        LY_CHECK_ERR_GOTO(!mem, LOGMEM(ctx); ret = LY_EMEM, cleanup);
-        LY_CHECK_GOTO(ret = lysp_node_dup(ctx, mem, pnode), cleanup);
         break;
     case LYS_LEAF:
         mem = calloc(1, sizeof(struct lysp_node_leaf));
-        LY_CHECK_ERR_GOTO(!mem, LOGMEM(ctx); ret = LY_EMEM, cleanup);
-        LY_CHECK_GOTO(ret = lysp_node_dup(ctx, mem, pnode), cleanup);
         break;
     case LYS_LEAFLIST:
         mem = calloc(1, sizeof(struct lysp_node_leaflist));
-        LY_CHECK_ERR_GOTO(!mem, LOGMEM(ctx); ret = LY_EMEM, cleanup);
-        LY_CHECK_GOTO(ret = lysp_node_dup(ctx, mem, pnode), cleanup);
         break;
     case LYS_LIST:
         mem = calloc(1, sizeof(struct lysp_node_list));
-        LY_CHECK_ERR_GOTO(!mem, LOGMEM(ctx); ret = LY_EMEM, cleanup);
-        LY_CHECK_GOTO(ret = lysp_node_dup(ctx, mem, pnode), cleanup);
         break;
     case LYS_CHOICE:
         mem = calloc(1, sizeof(struct lysp_node_choice));
-        LY_CHECK_ERR_GOTO(!mem, LOGMEM(ctx); ret = LY_EMEM, cleanup);
-        LY_CHECK_GOTO(ret = lysp_node_dup(ctx, mem, pnode), cleanup);
         break;
     case LYS_CASE:
         mem = calloc(1, sizeof(struct lysp_node_case));
-        LY_CHECK_ERR_GOTO(!mem, LOGMEM(ctx); ret = LY_EMEM, cleanup);
-        LY_CHECK_GOTO(ret = lysp_node_dup(ctx, mem, pnode), cleanup);
         break;
     case LYS_ANYDATA:
     case LYS_ANYXML:
         mem = calloc(1, sizeof(struct lysp_node_anydata));
-        LY_CHECK_ERR_GOTO(!mem, LOGMEM(ctx); ret = LY_EMEM, cleanup);
-        LY_CHECK_GOTO(ret = lysp_node_dup(ctx, mem, pnode), cleanup);
         break;
     case LYS_INPUT:
     case LYS_OUTPUT:
-        mem = calloc(1, sizeof(struct lysp_action_inout));
-        LY_CHECK_ERR_GOTO(!mem, LOGMEM(ctx); ret = LY_EMEM, cleanup);
-        LY_CHECK_GOTO(ret = lysp_action_inout_dup(ctx, mem, (struct lysp_action_inout *)pnode), cleanup);
+        mem = calloc(1, sizeof(struct lysp_node_action_inout));
         break;
     case LYS_ACTION:
     case LYS_RPC:
-        mem = calloc(1, sizeof(struct lysp_action));
-        LY_CHECK_ERR_GOTO(!mem, LOGMEM(ctx); ret = LY_EMEM, cleanup);
-        LY_CHECK_GOTO(ret = lysp_action_dup(ctx, mem, (struct lysp_action *)pnode), cleanup);
+        mem = calloc(1, sizeof(struct lysp_node_action));
         break;
     case LYS_NOTIF:
-        mem = calloc(1, sizeof(struct lysp_notif));
-        LY_CHECK_ERR_GOTO(!mem, LOGMEM(ctx); ret = LY_EMEM, cleanup);
-        LY_CHECK_GOTO(ret = lysp_notif_dup(ctx, mem, (struct lysp_notif *)pnode), cleanup);
+        mem = calloc(1, sizeof(struct lysp_node_notif));
         break;
     default:
         LOGINT_RET(ctx);
     }
+    LY_CHECK_ERR_GOTO(!mem, LOGMEM(ctx); ret = LY_EMEM, cleanup);
+    LY_CHECK_GOTO(ret = lysp_node_dup(ctx, mem, pnode), cleanup);
 
     if (with_links) {
         /* copy also parent and child pointers */
@@ -903,11 +865,11 @@
             musts = &((struct lysp_node_container *)target)->musts;
             break;
         case LYS_NOTIF:
-            musts = &((struct lysp_notif *)target)->musts;
+            musts = &((struct lysp_node_notif *)target)->musts;
             break;
         case LYS_INPUT:
         case LYS_OUTPUT:
-            musts = &((struct lysp_action_inout *)target)->musts;
+            musts = &((struct lysp_node_action_inout *)target)->musts;
             break;
         default:
             AMEND_WRONG_NODETYPE("deviation", "add", "must");
@@ -1146,11 +1108,11 @@
             musts = &((struct lysp_node_container *)target)->musts;
             break;
         case LYS_NOTIF:
-            musts = &((struct lysp_notif *)target)->musts;
+            musts = &((struct lysp_node_notif *)target)->musts;
             break;
         case LYS_INPUT:
         case LYS_OUTPUT:
-            musts = &((struct lysp_action_inout *)target)->musts;
+            musts = &((struct lysp_node_action_inout *)target)->musts;
             break;
         default:
             AMEND_WRONG_NODETYPE("deviation", "delete", "must");
@@ -1435,7 +1397,7 @@
 
     /* compare names */
     if (pnode->nodetype & (LYS_ACTION | LYS_RPC)) {
-        pname = ((struct lysp_action *)pnode)->name;
+        pname = ((struct lysp_node_action *)pnode)->name;
     } else if (pnode->nodetype & (LYS_INPUT | LYS_OUTPUT)) {
         pname = (pnode->nodetype & LYS_INPUT) ? "input" : "output";
     } else {
@@ -1623,21 +1585,17 @@
         /* no children */
         break;
     case LYS_NOTIF:
-        ((struct lysp_notif *)dev_pnode)->data = NULL;
-        lysp_notif_free((struct ly_ctx *)ctx, (struct lysp_notif *)dev_pnode);
-        free(dev_pnode);
-        return;
+        ((struct lysp_node_notif *)dev_pnode)->data = NULL;
+        break;
     case LYS_RPC:
     case LYS_ACTION:
-        ((struct lysp_action *)dev_pnode)->input.data = NULL;
-        ((struct lysp_action *)dev_pnode)->output.data = NULL;
-        lysp_action_free((struct ly_ctx *)ctx, (struct lysp_action *)dev_pnode);
-        free(dev_pnode);
-        return;
+        ((struct lysp_node_action *)dev_pnode)->input.data = NULL;
+        ((struct lysp_node_action *)dev_pnode)->output.data = NULL;
+        break;
     case LYS_INPUT:
     case LYS_OUTPUT:
-        ((struct lysp_action_inout *)dev_pnode)->data = NULL;
-        lysp_action_inout_free((struct ly_ctx *)ctx, (struct lysp_action_inout *)dev_pnode);
+        ((struct lysp_node_action_inout *)dev_pnode)->data = NULL;
+        lysp_node_free((struct ly_ctx *)ctx, dev_pnode);
         free(dev_pnode);
         return;
     default:
@@ -1794,16 +1752,15 @@
  * @return LY_EVALID on failure.
  */
 static LY_ERR
-lys_compile_augment(struct lysc_ctx *ctx, struct lysp_augment *aug_p, struct lysc_node *target)
+lys_compile_augment(struct lysc_ctx *ctx, struct lysp_node_augment *aug_p, struct lysc_node *target)
 {
     LY_ERR ret = LY_SUCCESS;
     struct lysp_node *pnode;
     struct lysc_node *node;
     struct lysc_when *when_shared = NULL;
-    struct lysc_action **actions;
-    struct lysc_notif **notifs;
+    struct lysc_node_action **actions;
+    struct lysc_node_notif **notifs;
     ly_bool allow_mandatory = 0, enabled;
-    LY_ARRAY_COUNT_TYPE u;
     struct ly_set child_set = {0};
     uint32_t i, opt_prev = ctx->options;
 
@@ -1844,8 +1801,7 @@
             } else {
                 ctx->options |= LYS_COMPILE_RPC_OUTPUT;
             }
-            ret = lys_compile_node(ctx, pnode, (struct lysc_node *)lysc_node_parent_full(target), 0, &child_set);
-            LY_CHECK_GOTO(ret, cleanup);
+            LY_CHECK_GOTO(ret = lys_compile_node(ctx, pnode, target, 0, &child_set), cleanup);
         } else {
             LY_CHECK_GOTO(ret = lys_compile_node(ctx, pnode, target, 0, &child_set), cleanup);
         }
@@ -1907,19 +1863,22 @@
         if (!actions) {
             LOGVAL(ctx->ctx, LYVE_REFERENCE,
                     "Invalid augment of %s node which is not allowed to contain RPC/action node \"%s\".",
-                    lys_nodetype2str(target->nodetype), aug_p->actions[0].name);
+                    lys_nodetype2str(target->nodetype), aug_p->actions->name);
             ret = LY_EVALID;
             goto cleanup;
         }
 
         /* compile actions into the target */
-        COMPILE_OP_ARRAY_GOTO(ctx, aug_p->actions, *actions, target, lys_compile_action, 0, ret, cleanup);
+        LY_LIST_FOR((struct lysp_node *)aug_p->actions, pnode) {
+            LY_CHECK_GOTO(ret = lys_compile_node(ctx, pnode, target, 0, NULL), cleanup);
+        }
 
         if (aug_p->when) {
             /* inherit when */
-            LY_ARRAY_FOR(*actions, u) {
-                ret = lys_compile_when(ctx, aug_p->when, aug_p->flags, lysc_data_node(target),
-                        (struct lysc_node *)&(*actions)[u], &when_shared);
+            struct lysc_node *iter;
+
+            LY_LIST_FOR((struct lysc_node *)*actions, iter) {
+                ret = lys_compile_when(ctx, aug_p->when, aug_p->flags, lysc_data_node(target), iter, &when_shared);
                 LY_CHECK_GOTO(ret, cleanup);
             }
         }
@@ -1928,19 +1887,22 @@
         if (!notifs) {
             LOGVAL(ctx->ctx, LYVE_REFERENCE,
                     "Invalid augment of %s node which is not allowed to contain notification node \"%s\".",
-                    lys_nodetype2str(target->nodetype), aug_p->notifs[0].name);
+                    lys_nodetype2str(target->nodetype), aug_p->notifs->name);
             ret = LY_EVALID;
             goto cleanup;
         }
 
         /* compile notifications into the target */
-        COMPILE_OP_ARRAY_GOTO(ctx, aug_p->notifs, *notifs, target, lys_compile_notif, 0, ret, cleanup);
+        LY_LIST_FOR((struct lysp_node *)aug_p->notifs, pnode) {
+            LY_CHECK_GOTO(ret = lys_compile_node(ctx, pnode, target, 0, NULL), cleanup);
+        }
 
         if (aug_p->when) {
             /* inherit when */
-            LY_ARRAY_FOR(*notifs, u) {
-                ret = lys_compile_when(ctx, aug_p->when, aug_p->flags, lysc_data_node(target),
-                        (struct lysc_node *)&(*notifs)[u], &when_shared);
+            struct lysc_node *iter;
+
+            LY_LIST_FOR((struct lysc_node *)*notifs, iter) {
+                ret = lys_compile_when(ctx, aug_p->when, aug_p->flags, lysc_data_node(target), iter, &when_shared);
                 LY_CHECK_GOTO(ret, cleanup);
             }
         }
@@ -2033,7 +1995,7 @@
  * @return LY_ERR value.
  */
 static LY_ERR
-lys_precompile_own_augment(struct lysc_ctx *ctx, struct lysp_augment *aug_p, const struct lysp_module *pmod)
+lys_precompile_own_augment(struct lysc_ctx *ctx, struct lysp_node_augment *aug_p, const struct lysp_module *pmod)
 {
     LY_ERR ret = LY_SUCCESS;
     struct lyxp_expr *exp = NULL;
@@ -2069,22 +2031,21 @@
 LY_ERR
 lys_precompile_own_augments(struct lysc_ctx *ctx)
 {
-    LY_ARRAY_COUNT_TYPE u, v, w;
-    const struct lys_module *aug_mod;
+    LY_ARRAY_COUNT_TYPE u, v;
 
     LY_ARRAY_FOR(ctx->cur_mod->augmented_by, u) {
-        aug_mod = ctx->cur_mod->augmented_by[u];
+        const struct lys_module *aug_mod = ctx->cur_mod->augmented_by[u];
+        struct lysp_node_augment *aug;
 
         /* collect all module augments */
-        LY_ARRAY_FOR(aug_mod->parsed->augments, v) {
-            LY_CHECK_RET(lys_precompile_own_augment(ctx, &aug_mod->parsed->augments[v], aug_mod->parsed));
+        LY_LIST_FOR(aug_mod->parsed->augments, aug) {
+            LY_CHECK_RET(lys_precompile_own_augment(ctx, aug, aug_mod->parsed));
         }
 
         /* collect all submodules augments */
         LY_ARRAY_FOR(aug_mod->parsed->includes, v) {
-            LY_ARRAY_FOR(aug_mod->parsed->includes[v].submodule->augments, w) {
-                LY_CHECK_RET(lys_precompile_own_augment(ctx, &aug_mod->parsed->includes[v].submodule->augments[w],
-                        (struct lysp_module *)aug_mod->parsed->includes[v].submodule));
+            LY_LIST_FOR(aug_mod->parsed->includes[v].submodule->augments, aug) {
+                LY_CHECK_RET(lys_precompile_own_augment(ctx, aug, (struct lysp_module *)aug_mod->parsed->includes[v].submodule));
             }
         }
     }
@@ -2244,6 +2205,7 @@
     const struct lysc_node *target;
     struct lys_module *mod;
     struct lysp_submodule *submod;
+    struct lysp_node_augment *aug;
     ly_bool has_dev = 0;
     uint16_t flags;
     uint32_t idx, opt_prev = ctx->options;
@@ -2260,12 +2222,12 @@
 
     mod_p = ctx->cur_mod->parsed;
 
-    LY_ARRAY_FOR(mod_p->augments, u) {
+    LY_LIST_FOR(mod_p->augments, aug) {
         lysc_update_path(ctx, NULL, "{augment}");
-        lysc_update_path(ctx, NULL, mod_p->augments[u].nodeid);
+        lysc_update_path(ctx, NULL, aug->nodeid);
 
         /* get target module */
-        ret = lys_nodeid_check(ctx, mod_p->augments[u].nodeid, 1, &mod, NULL);
+        ret = lys_nodeid_check(ctx, aug->nodeid, 1, &mod, NULL);
         LY_CHECK_RET(ret);
 
         /* add this module into the target module augmented_by, if not there already from previous augments */
@@ -2275,13 +2237,13 @@
         if (mod != ctx->cur_mod) {
             /* apply the augment, find the target node first */
             flags = 0;
-            ret = lysc_resolve_schema_nodeid(ctx, mod_p->augments[u].nodeid, 0, NULL, ctx->cur_mod, LY_PREF_SCHEMA,
+            ret = lysc_resolve_schema_nodeid(ctx, aug->nodeid, 0, NULL, ctx->cur_mod, LY_PREF_SCHEMA,
                     (void *)mod_p, 0, &target, &flags);
             LY_CHECK_RET(ret);
 
             /* apply the augment */
             ctx->options |= flags;
-            ret = lys_compile_augment(ctx, &mod_p->augments[u], (struct lysc_node *)target);
+            ret = lys_compile_augment(ctx, aug, (struct lysc_node *)target);
             ctx->options = opt_prev;
             LY_CHECK_RET(ret);
         }
@@ -2309,22 +2271,22 @@
     /* the same for augments and deviations in submodules */
     LY_ARRAY_FOR(mod_p->includes, v) {
         submod = mod_p->includes[v].submodule;
-        LY_ARRAY_FOR(submod->augments, u) {
+        LY_LIST_FOR(submod->augments, aug) {
             lysc_update_path(ctx, NULL, "{augment}");
-            lysc_update_path(ctx, NULL, submod->augments[u].nodeid);
+            lysc_update_path(ctx, NULL, aug->nodeid);
 
-            ret = lys_nodeid_check(ctx, submod->augments[u].nodeid, 1, &mod, NULL);
+            ret = lys_nodeid_check(ctx, aug->nodeid, 1, &mod, NULL);
             LY_CHECK_RET(ret);
 
             lys_array_add_mod_ref(ctx, ctx->cur_mod, &mod->augmented_by);
             if (mod != ctx->cur_mod) {
                 flags = 0;
-                ret = lysc_resolve_schema_nodeid(ctx, mod_p->augments[u].nodeid, 0, NULL, ctx->cur_mod, LY_PREF_SCHEMA,
+                ret = lysc_resolve_schema_nodeid(ctx, aug->nodeid, 0, NULL, ctx->cur_mod, LY_PREF_SCHEMA,
                         submod, 0, &target, &flags);
                 LY_CHECK_RET(ret);
 
                 ctx->options |= flags;
-                ret = lys_compile_augment(ctx, &submod->augments[u], (struct lysc_node *)target);
+                ret = lys_compile_augment(ctx, aug, (struct lysc_node *)target);
                 ctx->options = opt_prev;
                 LY_CHECK_RET(ret);
             }
diff --git a/src/schema_compile_amend.h b/src/schema_compile_amend.h
index e9ec1ed..808e64f 100644
--- a/src/schema_compile_amend.h
+++ b/src/schema_compile_amend.h
@@ -33,7 +33,7 @@
     const struct lysp_module *nodeid_pmod;       /**< module where the nodeid is defined, used to resolve prefixes */
     const struct lysc_node *nodeid_ctx_node;     /**< nodeid context node for relative targets */
 
-    struct lysp_augment *aug_p;                  /**< pointer to the parsed augment to apply */
+    struct lysp_node_augment *aug_p;                  /**< pointer to the parsed augment to apply */
 };
 
 /**
diff --git a/src/schema_compile_node.c b/src/schema_compile_node.c
index fb2c96f..7ea1ac5 100644
--- a/src/schema_compile_node.c
+++ b/src/schema_compile_node.c
@@ -258,9 +258,9 @@
 
     /* get the when array */
     if (node->nodetype & LYS_ACTION) {
-        node_when = &((struct lysc_action *)node)->when;
+        node_when = &((struct lysc_node_action *)node)->when;
     } else if (node->nodetype == LYS_NOTIF) {
-        node_when = &((struct lysc_notif *)node)->when;
+        node_when = &((struct lysc_node_notif *)node)->when;
     } else {
         node_when = &node->when;
     }
@@ -2007,10 +2007,9 @@
         const struct lysc_node *exclude)
 {
     const struct lysc_node *iter, *iter2;
-    const struct lysc_action *actions;
-    const struct lysc_notif *notifs;
+    const struct lysc_node_action *actions;
+    const struct lysc_node_notif *notifs;
     uint32_t getnext_flags;
-    LY_ARRAY_COUNT_TYPE u;
 
 #define CHECK_NODE(iter, exclude, name) (iter != (void *)exclude && (iter)->module == exclude->module && !strcmp(name, (iter)->name))
 
@@ -2058,15 +2057,15 @@
     }
 
     actions = parent ? lysc_node_actions(parent) : ctx->cur_mod->compiled->rpcs;
-    LY_ARRAY_FOR(actions, u) {
-        if (CHECK_NODE(&actions[u], exclude, name)) {
+    LY_LIST_FOR((struct lysc_node *)actions, iter) {
+        if (CHECK_NODE(iter, exclude, name)) {
             goto error;
         }
     }
 
     notifs = parent ? lysc_node_notifs(parent) : ctx->cur_mod->compiled->notifs;
-    LY_ARRAY_FOR(notifs, u) {
-        if (CHECK_NODE(&notifs[u], exclude, name)) {
+    LY_LIST_FOR((struct lysc_node *)notifs, iter) {
+        if (CHECK_NODE(iter, exclude, name)) {
             goto error;
         }
     }
@@ -2079,222 +2078,407 @@
 #undef CHECK_NODE
 }
 
-LY_ERR
-lys_compile_action(struct lysc_ctx *ctx, struct lysp_action *action_p, struct lysc_node *parent,
-        struct lysc_action *action, uint16_t uses_status)
+/**
+ * @brief Connect the node into the siblings list and check its name uniqueness. Also,
+ * keep specific order of augments targetting the same node.
+ *
+ * @param[in] ctx Compile context
+ * @param[in] parent Parent node holding the children list, in case of node from a choice's case,
+ * the choice itself is expected instead of a specific case node.
+ * @param[in] node Schema node to connect into the list.
+ * @return LY_ERR value - LY_SUCCESS or LY_EEXIST.
+ * In case of LY_EEXIST, the node is actually kept in the tree, so do not free it directly.
+ */
+static LY_ERR
+lys_compile_node_connect(struct lysc_ctx *ctx, struct lysc_node *parent, struct lysc_node *node)
 {
-    LY_ERR ret = LY_SUCCESS;
-    struct lysp_node *child_p, *dev_pnode = NULL, *dev_input_p = NULL, *dev_output_p = NULL;
-    struct lysp_action_inout *inout_p;
-    ly_bool not_supported, enabled;
-    uint32_t opt_prev = ctx->options;
+    struct lysc_node **children, *anchor = NULL;
+    int insert_after = 0;
 
-    lysc_update_path(ctx, parent, action_p->name);
+    node->parent = parent;
 
-    /* apply deviation on the action/RPC */
-    LY_CHECK_RET(lys_compile_node_deviations_refines(ctx, (struct lysp_node *)action_p, parent, &dev_pnode, &not_supported));
-    if (not_supported) {
-        lysc_update_path(ctx, NULL, NULL);
-        ret = LY_EDENIED;
-        goto cleanup;
-    } else if (dev_pnode) {
-        action_p = (struct lysp_action *)dev_pnode;
+    if (parent) {
+        if (parent->nodetype == LYS_CHOICE) {
+            assert(node->nodetype == LYS_CASE);
+            children = (struct lysc_node **)&((struct lysc_node_choice *)parent)->cases;
+        } else if (parent->nodetype & (LYS_ACTION | LYS_RPC)) {
+            assert(node->nodetype & (LYS_INPUT | LYS_OUTPUT));
+            /* inout nodes are part of the action and nothing more than setting the parent pointer is necessary */
+            return LY_SUCCESS;
+        } else if (node->nodetype == LYS_ACTION) {
+            children = (struct lysc_node **)lysc_node_actions_p(parent);
+        } else if (node->nodetype == LYS_NOTIF) {
+            children = (struct lysc_node **)lysc_node_notifs_p(parent);
+        } else {
+            children = lysc_node_children_p(parent, ctx->options);
+        }
+        assert(children);
+
+        if (!(*children)) {
+            /* first child */
+            *children = node;
+        } else if (node->flags & LYS_KEY) {
+            /* special handling of adding keys */
+            assert(node->module == parent->module);
+            anchor = *children;
+            if (anchor->flags & LYS_KEY) {
+                while ((anchor->flags & LYS_KEY) && anchor->next) {
+                    anchor = anchor->next;
+                }
+                /* insert after the last key */
+                insert_after = 1;
+            } /* else insert before anchor (at the beginning) */
+        } else if ((*children)->prev->module == node->module) {
+            /* last child is from the same module, keep the order and insert at the end */
+            anchor = (*children)->prev;
+            insert_after = 1;
+        } else if (parent->module == node->module) {
+            /* adding module child after some augments were connected */
+            for (anchor = *children; anchor->module == node->module; anchor = anchor->next) {}
+        } else {
+            /* some augments are already connected and we are connecting new ones,
+             * keep module name order and insert the node into the children list */
+            anchor = *children;
+            do {
+                anchor = anchor->prev;
+
+                /* check that we have not found the last augment node from our module or
+                 * the first augment node from a "smaller" module or
+                 * the first node from a local module */
+                if ((anchor->module == node->module) || (strcmp(anchor->module->name, node->module->name) < 0) ||
+                        (anchor->module == parent->module)) {
+                    /* insert after */
+                    insert_after = 1;
+                    break;
+                }
+
+                /* we have traversed all the nodes, insert before anchor (as the first node) */
+            } while (anchor->prev->next);
+        }
+
+        /* insert */
+        if (anchor) {
+            if (insert_after) {
+                node->next = anchor->next;
+                node->prev = anchor;
+                anchor->next = node;
+                if (node->next) {
+                    /* middle node */
+                    node->next->prev = node;
+                } else {
+                    /* last node */
+                    (*children)->prev = node;
+                }
+            } else {
+                node->next = anchor;
+                node->prev = anchor->prev;
+                anchor->prev = node;
+                if (anchor == *children) {
+                    /* first node */
+                    *children = node;
+                } else {
+                    /* middle node */
+                    node->prev->next = node;
+                }
+            }
+        }
+
+        /* check the name uniqueness (even for an only child, it may be in case) */
+        if (lys_compile_node_uniqness(ctx, parent, node->name, node)) {
+            return LY_EEXIST;
+        }
+    } else {
+        /* top-level element */
+        struct lysc_node **list;
+
+        if (node->nodetype == LYS_RPC) {
+            list = (struct lysc_node **)&ctx->cur_mod->compiled->rpcs;
+        } else if (node->nodetype == LYS_NOTIF) {
+            list = (struct lysc_node **)&ctx->cur_mod->compiled->notifs;
+        } else {
+            list = &ctx->cur_mod->compiled->data;
+        }
+        if (!(*list)) {
+            *list = node;
+        } else {
+            /* insert at the end of the module's top-level nodes list */
+            (*list)->prev->next = node;
+            node->prev = (*list)->prev;
+            (*list)->prev = node;
+        }
+
+        /* check the name uniqueness on top-level */
+        if (lys_compile_node_uniqness(ctx, NULL, node->name, node)) {
+            return LY_EEXIST;
+        }
     }
 
-    /* member needed for uniqueness check lys_getnext() */
-    action->nodetype = parent ? LYS_ACTION : LYS_RPC;
-    action->module = ctx->cur_mod;
-    action->parent = parent;
+    return LY_SUCCESS;
+}
 
-    LY_CHECK_GOTO(ret = lys_compile_node_uniqness(ctx, parent, action_p->name, (struct lysc_node *)action), cleanup);
+/**
+ * @brief Set config flags for a node.
+ *
+ * @param[in] ctx Compile context.
+ * @param[in] node Compiled node config to set.
+ * @param[in] parent Parent of @p node.
+ * @return LY_ERR value.
+ */
+static LY_ERR
+lys_compile_config(struct lysc_ctx *ctx, struct lysc_node *node, struct lysc_node *parent)
+{
+    /* case never has any explicit config */
+    assert((node->nodetype != LYS_CASE) || !(node->flags & LYS_CONFIG_MASK));
 
-    if (ctx->options & (LYS_COMPILE_RPC_MASK | LYS_COMPILE_NOTIFICATION)) {
+    if (node->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF | LYS_INPUT | LYS_OUTPUT)) {
+        /* no config inheritance, config flag is set by copying flags from parsed node */
+        return LY_SUCCESS;
+    } else if (ctx->options & (LYS_COMPILE_RPC_INPUT | LYS_COMPILE_RPC_OUTPUT)) {
+        /* ignore config statements inside RPC/action data */
+        node->flags &= ~LYS_CONFIG_MASK;
+        node->flags |= (ctx->options & LYS_COMPILE_RPC_INPUT) ? LYS_CONFIG_W : LYS_CONFIG_R;
+    } else if (ctx->options & LYS_COMPILE_NOTIFICATION) {
+        /* ignore config statements inside Notification data */
+        node->flags &= ~LYS_CONFIG_MASK;
+        node->flags |= LYS_CONFIG_R;
+    } else if (!(node->flags & LYS_CONFIG_MASK)) {
+        /* config not explicitly set, inherit it from parent */
+        if (parent) {
+            node->flags |= parent->flags & LYS_CONFIG_MASK;
+        } else {
+            /* default is config true */
+            node->flags |= LYS_CONFIG_W;
+        }
+    } else {
+        /* config set explicitly */
+        node->flags |= LYS_SET_CONFIG;
+    }
+
+    if (parent && (parent->flags & LYS_CONFIG_R) && (node->flags & LYS_CONFIG_W)) {
         LOGVAL(ctx->ctx, LYVE_SEMANTICS,
-                "Action \"%s\" is placed inside %s.", action_p->name,
-                ctx->options & LYS_COMPILE_RPC_MASK ? "another RPC/action" : "notification");
-        ret = LY_EVALID;
-        goto cleanup;
+                "Configuration node cannot be child of any state data node.");
+        return LY_EVALID;
     }
 
-    action->flags = action_p->flags & LYS_FLAGS_COMPILED_MASK;
-
-    /* if-features */
-    LY_CHECK_RET(lys_eval_iffeatures(ctx->ctx, action_p->iffeatures, &enabled));
-    if (!enabled && !(ctx->options & (LYS_COMPILE_DISABLED | LYS_COMPILE_GROUPING))) {
-        ly_set_add(&ctx->disabled, action, 1, NULL);
-        ctx->options |= LYS_COMPILE_DISABLED;
-    }
-
-    /* status - it is not inherited by specification, but it does not make sense to have
-     * current in deprecated or deprecated in obsolete, so we do print warning and inherit status */
-    ret = lys_compile_status(ctx, &action->flags, uses_status ? uses_status : (parent ? parent->flags : 0));
-    LY_CHECK_GOTO(ret, cleanup);
-
-    DUP_STRING_GOTO(ctx->ctx, action_p->name, action->name, ret, cleanup);
-    DUP_STRING_GOTO(ctx->ctx, action_p->dsc, action->dsc, ret, cleanup);
-    DUP_STRING_GOTO(ctx->ctx, action_p->ref, action->ref, ret, cleanup);
-
-    /* connect any action augments */
-    LY_CHECK_GOTO(ret = lys_compile_node_augments(ctx, (struct lysc_node *)action), cleanup);
-
-    /* input */
-    lysc_update_path(ctx, (struct lysc_node *)action, "input");
-
-    /* apply deviations on input */
-    LY_CHECK_GOTO(ret = lys_compile_node_deviations_refines(ctx, (struct lysp_node *)&action_p->input,
-            (struct lysc_node *)action, &dev_input_p, &not_supported), cleanup);
-    if (not_supported) {
-        inout_p = NULL;
-    } else if (dev_input_p) {
-        inout_p = (struct lysp_action_inout *)dev_input_p;
-    } else {
-        inout_p = &action_p->input;
-    }
-
-    if (inout_p) {
-        action->input.nodetype = LYS_INPUT;
-        COMPILE_ARRAY_GOTO(ctx, inout_p->musts, action->input.musts, lys_compile_must, ret, cleanup);
-        COMPILE_EXTS_GOTO(ctx, inout_p->exts, action->input_exts, &action->input, LYEXT_PAR_INPUT, ret, cleanup);
-        ctx->options |= LYS_COMPILE_RPC_INPUT;
-
-        /* connect any input augments */
-        LY_CHECK_GOTO(ret = lys_compile_node_augments(ctx, (struct lysc_node *)&action->input), cleanup);
-
-        LY_LIST_FOR(inout_p->data, child_p) {
-            LY_CHECK_GOTO(ret = lys_compile_node(ctx, child_p, (struct lysc_node *)action, uses_status, NULL), cleanup);
-        }
-        ctx->options = opt_prev;
-    }
-
-    lysc_update_path(ctx, NULL, NULL);
-
-    /* output */
-    lysc_update_path(ctx, (struct lysc_node *)action, "output");
-
-    /* apply deviations on output */
-    LY_CHECK_GOTO(ret = lys_compile_node_deviations_refines(ctx, (struct lysp_node *)&action_p->output,
-            (struct lysc_node *)action, &dev_output_p, &not_supported), cleanup);
-    if (not_supported) {
-        inout_p = NULL;
-    } else if (dev_output_p) {
-        inout_p = (struct lysp_action_inout *)dev_output_p;
-    } else {
-        inout_p = &action_p->output;
-    }
-
-    if (inout_p) {
-        action->output.nodetype = LYS_OUTPUT;
-        COMPILE_ARRAY_GOTO(ctx, inout_p->musts, action->output.musts, lys_compile_must, ret, cleanup);
-        COMPILE_EXTS_GOTO(ctx, inout_p->exts, action->output_exts, &action->output, LYEXT_PAR_OUTPUT, ret, cleanup);
-        ctx->options |= LYS_COMPILE_RPC_OUTPUT;
-
-        /* connect any output augments */
-        LY_CHECK_GOTO(ret = lys_compile_node_augments(ctx, (struct lysc_node *)&action->output), cleanup);
-
-        LY_LIST_FOR(inout_p->data, child_p) {
-            LY_CHECK_GOTO(ret = lys_compile_node(ctx, child_p, (struct lysc_node *)action, uses_status, NULL), cleanup);
-        }
-        ctx->options = opt_prev;
-    }
-
-    lysc_update_path(ctx, NULL, NULL);
-
-    /* wait with extensions compilation until all the children are compiled */
-    COMPILE_EXTS_GOTO(ctx, action_p->exts, action->exts, action, LYEXT_PAR_NODE, ret, cleanup);
-
-    if ((action->input.musts || action->output.musts) && !(ctx->options & (LYS_COMPILE_DISABLED | LYS_COMPILE_GROUPING))) {
-        /* do not check "must" semantics in a grouping */
-        ret = ly_set_add(&ctx->unres->xpath, action, 0, NULL);
-        LY_CHECK_GOTO(ret, cleanup);
-    }
-
-    lysc_update_path(ctx, NULL, NULL);
-
-cleanup:
-    lysp_dev_node_free(ctx->ctx, dev_pnode);
-    lysp_dev_node_free(ctx->ctx, dev_input_p);
-    lysp_dev_node_free(ctx->ctx, dev_output_p);
-    ctx->options = opt_prev;
-    return ret;
+    return LY_SUCCESS;
 }
 
 LY_ERR
-lys_compile_notif(struct lysc_ctx *ctx, struct lysp_notif *notif_p, struct lysc_node *parent, struct lysc_notif *notif,
-        uint16_t uses_status)
+lys_compile_node_(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysc_node *parent, uint16_t uses_status,
+        LY_ERR (*node_compile_spec)(struct lysc_ctx *, struct lysp_node *, struct lysc_node *),
+        struct lysc_node *node, struct ly_set *child_set)
 {
     LY_ERR ret = LY_SUCCESS;
-    struct lysp_node *child_p, *dev_pnode = NULL;
     ly_bool not_supported, enabled;
-    uint32_t opt_prev = ctx->options;
+    struct lysp_node *dev_pnode = NULL;
 
-    lysc_update_path(ctx, parent, notif_p->name);
+    node->nodetype = pnode->nodetype;
+    node->module = ctx->cur_mod;
+    node->prev = node;
 
-    LY_CHECK_RET(lys_compile_node_deviations_refines(ctx, (struct lysp_node *)notif_p, parent, &dev_pnode, &not_supported));
+    /* compile any deviations for this node */
+    LY_CHECK_GOTO(ret = lys_compile_node_deviations_refines(ctx, pnode, parent, &dev_pnode, &not_supported), error);
     if (not_supported) {
-        lysc_update_path(ctx, NULL, NULL);
-        ret = LY_EDENIED;
-        goto cleanup;
+        goto error;
     } else if (dev_pnode) {
-        notif_p = (struct lysp_notif *)dev_pnode;
+        pnode = dev_pnode;
     }
 
-    /* member needed for uniqueness check lys_getnext() */
-    notif->nodetype = LYS_NOTIF;
-    notif->module = ctx->cur_mod;
-    notif->parent = parent;
-
-    LY_CHECK_GOTO(ret = lys_compile_node_uniqness(ctx, parent, notif_p->name, (struct lysc_node *)notif), cleanup);
-
-    if (ctx->options & (LYS_COMPILE_RPC_MASK | LYS_COMPILE_NOTIFICATION)) {
-        LOGVAL(ctx->ctx, LYVE_SEMANTICS,
-                "Notification \"%s\" is placed inside %s.", notif_p->name,
-                ctx->options & LYS_COMPILE_RPC_MASK ? "RPC/action" : "another notification");
-        ret = LY_EVALID;
-        goto cleanup;
-    }
-
-    notif->flags = notif_p->flags & LYS_FLAGS_COMPILED_MASK;
+    node->flags = pnode->flags & LYS_FLAGS_COMPILED_MASK;
 
     /* if-features */
-    LY_CHECK_RET(lys_eval_iffeatures(ctx->ctx, notif_p->iffeatures, &enabled));
+    LY_CHECK_GOTO(ret = lys_eval_iffeatures(ctx->ctx, pnode->iffeatures, &enabled), error);
     if (!enabled && !(ctx->options & (LYS_COMPILE_DISABLED | LYS_COMPILE_GROUPING))) {
-        ly_set_add(&ctx->disabled, notif, 1, NULL);
+        ly_set_add(&ctx->disabled, node, 1, NULL);
         ctx->options |= LYS_COMPILE_DISABLED;
     }
 
+    /* config */
+    ret = lys_compile_config(ctx, node, parent);
+    LY_CHECK_GOTO(ret, error);
+
+    /* list ordering */
+    if (node->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
+        if ((node->flags & LYS_CONFIG_R) && (node->flags & LYS_ORDBY_MASK)) {
+            LOGWRN(ctx->ctx, "The ordered-by statement is ignored in lists representing %s (%s).",
+                    (ctx->options & LYS_COMPILE_RPC_OUTPUT) ? "RPC/action output parameters" :
+                    (ctx->options & LYS_COMPILE_NOTIFICATION) ? "notification content" : "state data", ctx->path);
+            node->flags &= ~LYS_ORDBY_MASK;
+            node->flags |= LYS_ORDBY_SYSTEM;
+        } else if (!(node->flags & LYS_ORDBY_MASK)) {
+            /* default ordering is system */
+            node->flags |= LYS_ORDBY_SYSTEM;
+        }
+    }
+
     /* status - it is not inherited by specification, but it does not make sense to have
      * current in deprecated or deprecated in obsolete, so we do print warning and inherit status */
-    ret = lys_compile_status(ctx, &notif->flags, uses_status ? uses_status : (parent ? parent->flags : 0));
-    LY_CHECK_GOTO(ret, cleanup);
+    LY_CHECK_GOTO(ret = lys_compile_status(ctx, &node->flags, uses_status ? uses_status : (parent ? parent->flags : 0)), error);
 
-    DUP_STRING_GOTO(ctx->ctx, notif_p->name, notif->name, ret, cleanup);
-    DUP_STRING_GOTO(ctx->ctx, notif_p->dsc, notif->dsc, ret, cleanup);
-    DUP_STRING_GOTO(ctx->ctx, notif_p->ref, notif->ref, ret, cleanup);
-    COMPILE_ARRAY_GOTO(ctx, notif_p->musts, notif->musts, lys_compile_must, ret, cleanup);
+    DUP_STRING_GOTO(ctx->ctx, pnode->name, node->name, ret, error);
+    DUP_STRING_GOTO(ctx->ctx, pnode->dsc, node->dsc, ret, error);
+    DUP_STRING_GOTO(ctx->ctx, pnode->ref, node->ref, ret, error);
+
+    /* insert into parent's children/compiled module (we can no longer free the node separately on error) */
+    LY_CHECK_GOTO(ret = lys_compile_node_connect(ctx, parent, node), cleanup);
+
+    if (pnode->when) {
+        /* compile when */
+        ret = lys_compile_when(ctx, pnode->when, pnode->flags, lysc_data_node(node), node, NULL);
+        LY_CHECK_GOTO(ret, cleanup);
+    }
+
+    /* connect any augments */
+    LY_CHECK_GOTO(ret = lys_compile_node_augments(ctx, node), cleanup);
+
+    /* nodetype-specific part */
+    LY_CHECK_GOTO(ret = node_compile_spec(ctx, pnode, node), cleanup);
+
+    /* final compilation tasks that require the node to be connected */
+    COMPILE_EXTS_GOTO(ctx, pnode->exts, node->exts, node, LYEXT_PAR_NODE, ret, cleanup);
+    if (node->flags & LYS_MAND_TRUE) {
+        /* inherit LYS_MAND_TRUE in parent containers */
+        lys_compile_mandatory_parents(parent, 1);
+    }
+
+    if (child_set) {
+        /* add the new node into set */
+        LY_CHECK_GOTO(ret = ly_set_add(child_set, node, 1, NULL), cleanup);
+    }
+
+    goto cleanup;
+
+error:
+    lysc_node_free(ctx->ctx, node, 0);
+cleanup:
+    if (ret && dev_pnode) {
+        LOGVAL(ctx->ctx, LYVE_OTHER, "Compilation of a deviated and/or refined node failed.");
+    }
+    lysp_dev_node_free(ctx->ctx, dev_pnode);
+    return ret;
+}
+
+/**
+ * @brief Compile parsed action's input/output node information.
+ * @param[in] ctx Compile context
+ * @param[in] pnode Parsed inout node.
+ * @param[in,out] node Pre-prepared structure from lys_compile_node_() with filled generic node information
+ * is enriched with the inout-specific information.
+ * @return LY_ERR value - LY_SUCCESS or LY_EVALID.
+ */
+LY_ERR
+lys_compile_node_action_inout(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysc_node *node)
+{
+    LY_ERR ret = LY_SUCCESS;
+    struct lysp_node *child_p;
+    uint32_t prev_options = ctx->options;
+
+    struct lysp_node_action_inout *inout_p = (struct lysp_node_action_inout *)pnode;
+    struct lysc_node_action_inout *inout = (struct lysc_node_action_inout *)node;
+
+    COMPILE_ARRAY_GOTO(ctx, inout_p->musts, inout->musts, lys_compile_must, ret, done);
+    COMPILE_EXTS_GOTO(ctx, inout_p->exts, inout->exts, inout, inout_p->nodetype == LYS_INPUT ? LYEXT_PAR_INPUT : LYEXT_PAR_OUTPUT,
+            ret, done);
+    ctx->options |= inout_p->nodetype == LYS_INPUT ? LYS_COMPILE_RPC_INPUT : LYS_COMPILE_RPC_OUTPUT;
+
+    LY_LIST_FOR(inout_p->data, child_p) {
+        LY_CHECK_GOTO(ret = lys_compile_node(ctx, child_p, node, 0, NULL), done);
+    }
+
+    ctx->options = prev_options;
+
+done:
+    return ret;
+}
+
+/**
+ * @brief Compile parsed action node information.
+ * @param[in] ctx Compile context
+ * @param[in] pnode Parsed action node.
+ * @param[in,out] node Pre-prepared structure from lys_compile_node() with filled generic node information
+ * is enriched with the action-specific information.
+ * @return LY_ERR value - LY_SUCCESS or LY_EVALID.
+ */
+LY_ERR
+lys_compile_node_action(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysc_node *node)
+{
+    LY_ERR ret;
+    struct lysp_node_action *action_p = (struct lysp_node_action *)pnode;
+    struct lysc_node_action *action = (struct lysc_node_action *)node;
+    struct lysp_node_action_inout *input, implicit_input = {
+        .nodetype = LYS_INPUT,
+        .name = "input",
+        .parent = pnode,
+    };
+    struct lysp_node_action_inout *output, implicit_output = {
+        .nodetype = LYS_OUTPUT,
+        .name = "output",
+        .parent = pnode,
+    };
+
+    /* output */
+    lysc_update_path(ctx, (struct lysc_node *)action, "input");
+    if (action_p->input.nodetype == LYS_UNKNOWN) {
+        input = &implicit_input;
+    } else {
+        input = &action_p->input;
+    }
+    ret = lys_compile_node_(ctx, (struct lysp_node *)input, (struct lysc_node *)action, 0,
+            lys_compile_node_action_inout, (struct lysc_node *)&action->input, NULL);
+    lysc_update_path(ctx, NULL, NULL);
+    LY_CHECK_GOTO(ret, done);
+
+    /* output */
+    lysc_update_path(ctx, (struct lysc_node *)action, "output");
+    if (action_p->input.nodetype == LYS_UNKNOWN) {
+        output = &implicit_output;
+    } else {
+        output = &action_p->output;
+    }
+    ret = lys_compile_node_(ctx, (struct lysp_node *)output, (struct lysc_node *)action, 0,
+            lys_compile_node_action_inout, (struct lysc_node *)&action->output, NULL);
+    lysc_update_path(ctx, NULL, NULL);
+    LY_CHECK_GOTO(ret, done);
+
+    /* do not check "must" semantics in a grouping */
+    if ((action->input.musts || action->output.musts) && !(ctx->options & (LYS_COMPILE_DISABLED | LYS_COMPILE_GROUPING))) {
+        ret = ly_set_add(&ctx->unres->xpath, action, 0, NULL);
+        LY_CHECK_GOTO(ret, done);
+    }
+
+done:
+    return ret;
+}
+
+/**
+ * @brief Compile parsed action node information.
+ * @param[in] ctx Compile context
+ * @param[in] pnode Parsed action node.
+ * @param[in,out] node Pre-prepared structure from lys_compile_node() with filled generic node information
+ * is enriched with the action-specific information.
+ * @return LY_ERR value - LY_SUCCESS or LY_EVALID.
+ */
+LY_ERR
+lys_compile_node_notif(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysc_node *node)
+{
+    LY_ERR ret = LY_SUCCESS;
+    struct lysp_node_notif *notif_p = (struct lysp_node_notif *)pnode;
+    struct lysc_node_notif *notif = (struct lysc_node_notif *)node;
+    struct lysp_node *child_p;
+
+    COMPILE_ARRAY_GOTO(ctx, notif_p->musts, notif->musts, lys_compile_must, ret, done);
     if (notif_p->musts && !(ctx->options & (LYS_COMPILE_GROUPING | LYS_COMPILE_DISABLED))) {
         /* do not check "must" semantics in a grouping */
         ret = ly_set_add(&ctx->unres->xpath, notif, 0, NULL);
-        LY_CHECK_GOTO(ret, cleanup);
+        LY_CHECK_GOTO(ret, done);
     }
 
-    ctx->options |= LYS_COMPILE_NOTIFICATION;
-
-    /* connect any notification augments */
-    LY_CHECK_GOTO(ret = lys_compile_node_augments(ctx, (struct lysc_node *)notif), cleanup);
-
     LY_LIST_FOR(notif_p->data, child_p) {
-        ret = lys_compile_node(ctx, child_p, (struct lysc_node *)notif, uses_status, NULL);
-        LY_CHECK_GOTO(ret, cleanup);
+        ret = lys_compile_node(ctx, child_p, (struct lysc_node *)notif, 0, NULL);
+        LY_CHECK_GOTO(ret, done);
     }
 
-    /* wait with extension compilation until all the children are compiled */
-    COMPILE_EXTS_GOTO(ctx, notif_p->exts, notif->exts, notif, LYEXT_PAR_NODE, ret, cleanup);
-
-    lysc_update_path(ctx, NULL, NULL);
-
-cleanup:
-    lysp_dev_node_free(ctx->ctx, dev_pnode);
-    ctx->options = opt_prev;
+done:
     return ret;
 }
 
@@ -2358,8 +2542,15 @@
         ret = ly_set_add(&ctx->unres->xpath, cont, 0, NULL);
         LY_CHECK_GOTO(ret, done);
     }
-    COMPILE_OP_ARRAY_GOTO(ctx, cont_p->actions, cont->actions, node, lys_compile_action, 0, ret, done);
-    COMPILE_OP_ARRAY_GOTO(ctx, cont_p->notifs, cont->notifs, node, lys_compile_notif, 0, ret, done);
+
+    LY_LIST_FOR((struct lysp_node *)cont_p->actions, child_p) {
+        ret = lys_compile_node(ctx, child_p, node, 0, NULL);
+        LY_CHECK_GOTO(ret, done);
+    }
+    LY_LIST_FOR((struct lysp_node *)cont_p->notifs, child_p) {
+        ret = lys_compile_node(ctx, child_p, node, 0, NULL);
+        LY_CHECK_GOTO(ret, done);
+    }
 
 done:
     return ret;
@@ -2603,9 +2794,9 @@
                 return LY_ENOTFOUND;
             }
             if (!ly_strncmp("input", name, name_len)) {
-                ctx_node = (struct lysc_node *)&((struct lysc_action *)ctx_node)->input;
+                ctx_node = (struct lysc_node *)&((struct lysc_node_action *)ctx_node)->input;
             } else if (!ly_strncmp("output", name, name_len)) {
-                ctx_node = (struct lysc_node *)&((struct lysc_action *)ctx_node)->output;
+                ctx_node = (struct lysc_node *)&((struct lysc_node_action *)ctx_node)->output;
                 getnext_extra_flag = LYS_GETNEXT_OUTPUT;
             } else {
                 /* only input or output is valid */
@@ -2902,8 +3093,14 @@
         LY_CHECK_RET(lys_compile_node_list_unique(ctx, list_p->uniques, list));
     }
 
-    COMPILE_OP_ARRAY_GOTO(ctx, list_p->actions, list->actions, node, lys_compile_action, 0, ret, done);
-    COMPILE_OP_ARRAY_GOTO(ctx, list_p->notifs, list->notifs, node, lys_compile_notif, 0, ret, done);
+    LY_LIST_FOR((struct lysp_node *)list_p->actions, child_p) {
+        ret = lys_compile_node(ctx, child_p, node, 0, NULL);
+        LY_CHECK_GOTO(ret, done);
+    }
+    LY_LIST_FOR((struct lysp_node *)list_p->notifs, child_p) {
+        ret = lys_compile_node(ctx, child_p, node, 0, NULL);
+        LY_CHECK_GOTO(ret, done);
+    }
 
     /* checks */
     if (list->min > list->max) {
@@ -3078,127 +3275,6 @@
 }
 
 /**
- * @brief Connect the node into the siblings list and check its name uniqueness. Also,
- * keep specific order of augments targetting the same node.
- *
- * @param[in] ctx Compile context
- * @param[in] parent Parent node holding the children list, in case of node from a choice's case,
- * the choice itself is expected instead of a specific case node.
- * @param[in] node Schema node to connect into the list.
- * @return LY_ERR value - LY_SUCCESS or LY_EEXIST.
- * In case of LY_EEXIST, the node is actually kept in the tree, so do not free it directly.
- */
-static LY_ERR
-lys_compile_node_connect(struct lysc_ctx *ctx, struct lysc_node *parent, struct lysc_node *node)
-{
-    struct lysc_node **children, *anchor = NULL;
-    int insert_after = 0;
-
-    node->parent = parent;
-
-    if (parent) {
-        if (parent->nodetype == LYS_CHOICE) {
-            assert(node->nodetype == LYS_CASE);
-            children = (struct lysc_node **)&((struct lysc_node_choice *)parent)->cases;
-        } else {
-            children = lysc_node_children_p(parent, ctx->options);
-        }
-        assert(children);
-
-        if (!(*children)) {
-            /* first child */
-            *children = node;
-        } else if (node->flags & LYS_KEY) {
-            /* special handling of adding keys */
-            assert(node->module == parent->module);
-            anchor = *children;
-            if (anchor->flags & LYS_KEY) {
-                while ((anchor->flags & LYS_KEY) && anchor->next) {
-                    anchor = anchor->next;
-                }
-                /* insert after the last key */
-                insert_after = 1;
-            } /* else insert before anchor (at the beginning) */
-        } else if ((*children)->prev->module == node->module) {
-            /* last child is from the same module, keep the order and insert at the end */
-            anchor = (*children)->prev;
-            insert_after = 1;
-        } else if (parent->module == node->module) {
-            /* adding module child after some augments were connected */
-            for (anchor = *children; anchor->module == node->module; anchor = anchor->next) {}
-        } else {
-            /* some augments are already connected and we are connecting new ones,
-             * keep module name order and insert the node into the children list */
-            anchor = *children;
-            do {
-                anchor = anchor->prev;
-
-                /* check that we have not found the last augment node from our module or
-                 * the first augment node from a "smaller" module or
-                 * the first node from a local module */
-                if ((anchor->module == node->module) || (strcmp(anchor->module->name, node->module->name) < 0) ||
-                        (anchor->module == parent->module)) {
-                    /* insert after */
-                    insert_after = 1;
-                    break;
-                }
-
-                /* we have traversed all the nodes, insert before anchor (as the first node) */
-            } while (anchor->prev->next);
-        }
-
-        /* insert */
-        if (anchor) {
-            if (insert_after) {
-                node->next = anchor->next;
-                node->prev = anchor;
-                anchor->next = node;
-                if (node->next) {
-                    /* middle node */
-                    node->next->prev = node;
-                } else {
-                    /* last node */
-                    (*children)->prev = node;
-                }
-            } else {
-                node->next = anchor;
-                node->prev = anchor->prev;
-                anchor->prev = node;
-                if (anchor == *children) {
-                    /* first node */
-                    *children = node;
-                } else {
-                    /* middle node */
-                    node->prev->next = node;
-                }
-            }
-        }
-
-        /* check the name uniqueness (even for an only child, it may be in case) */
-        if (lys_compile_node_uniqness(ctx, parent, node->name, node)) {
-            return LY_EEXIST;
-        }
-    } else {
-        /* top-level element */
-        if (!ctx->cur_mod->compiled->data) {
-            ctx->cur_mod->compiled->data = node;
-        } else {
-            /* insert at the end of the module's top-level nodes list */
-            ctx->cur_mod->compiled->data->prev->next = node;
-            node->prev = ctx->cur_mod->compiled->data->prev;
-            ctx->cur_mod->compiled->data->prev = node;
-        }
-
-        /* check the name uniqueness on top-level */
-        if (lys_compile_node_uniqness(ctx, NULL, node->name, node)) {
-            return LY_EEXIST;
-        }
-    }
-
-    return LY_SUCCESS;
-}
-
-/**
  * @brief Prepare the case structure in choice node for the new data node.
  *
  * It is able to handle implicit as well as explicit cases and the situation when the case has multiple data nodes and the case was already
@@ -3258,19 +3334,19 @@
 
 /**
  * @brief Get the grouping with the specified name from given groupings sized array.
- * @param[in] grp Sized array of groupings.
+ * @param[in] grps Linked list of groupings.
  * @param[in] name Name of the grouping to find,
  * @return NULL when there is no grouping with the specified name
  * @return Pointer to the grouping of the specified @p name.
  */
-static struct lysp_grp *
-match_grouping(struct lysp_grp *grp, const char *name)
+static struct lysp_node_grp *
+match_grouping(struct lysp_node_grp *grps, const char *name)
 {
-    LY_ARRAY_COUNT_TYPE u;
+    struct lysp_node_grp *grp;
 
-    LY_ARRAY_FOR(grp, u) {
-        if (!strcmp(grp[u].name, name)) {
-            return &grp[u];
+    LY_LIST_FOR(grps, grp) {
+        if (!strcmp(grp->name, name)) {
+            return grp;
         }
     }
 
@@ -3287,11 +3363,11 @@
  * @return LY_ERR value.
  */
 static LY_ERR
-lys_compile_uses_find_grouping(struct lysc_ctx *ctx, struct lysp_node_uses *uses_p, struct lysp_grp **grp_p,
+lys_compile_uses_find_grouping(struct lysc_ctx *ctx, struct lysp_node_uses *uses_p, struct lysp_node_grp **grp_p,
         struct lysp_module **grp_pmod)
 {
     struct lysp_node *pnode;
-    struct lysp_grp *grp;
+    struct lysp_node_grp *grp;
     LY_ARRAY_COUNT_TYPE u;
     const char *id, *name, *prefix, *local_pref;
     size_t prefix_len, name_len;
@@ -3309,13 +3385,9 @@
         /* current module, search local groupings first */
         pmod = ctx->pmod->mod->parsed; /* make sure that we will start in main_module, not submodule */
         for (pnode = uses_p->parent; !found && pnode; pnode = pnode->parent) {
-            grp = (struct lysp_grp *)lysp_node_groupings(pnode);
-            LY_ARRAY_FOR(grp, u) {
-                if (!strcmp(grp[u].name, name)) {
-                    grp = &grp[u];
-                    found = ctx->pmod;
-                    break;
-                }
+            if ((grp = match_grouping((struct lysp_node_grp *)lysp_node_groupings(pnode), name))) {
+                found = ctx->pmod;
+                break;
             }
         }
     } else {
@@ -3375,14 +3447,11 @@
 {
     struct lysp_node *pnode;
     struct lysc_node *child;
-    struct lysp_grp *grp = NULL;
+    struct lysp_node_grp *grp = NULL;
     uint32_t i, grp_stack_count;
     struct lysp_module *grp_mod, *mod_old = ctx->pmod;
     LY_ERR ret = LY_SUCCESS;
     struct lysc_when *when_shared = NULL;
-    LY_ARRAY_COUNT_TYPE u;
-    struct lysc_notif **notifs = NULL;
-    struct lysc_action **actions = NULL;
     struct ly_set uses_child_set = {0};
 
     /* find the referenced grouping */
@@ -3433,21 +3502,25 @@
 
     /* compile actions */
     if (grp->actions) {
+        struct lysc_node_action **actions;
         actions = parent ? lysc_node_actions_p(parent) : &ctx->cur_mod->compiled->rpcs;
         if (!actions) {
             LOGVAL(ctx->ctx, LYVE_REFERENCE, "Invalid child %s \"%s\" of uses parent %s \"%s\" node.",
-                    grp->actions[0].name, lys_nodetype2str(grp->actions[0].nodetype), parent->name,
-                    lys_nodetype2str(parent->nodetype));
+                    grp->actions->name, lys_nodetype2str(grp->actions->nodetype),
+                    parent->name, lys_nodetype2str(parent->nodetype));
             ret = LY_EVALID;
             goto cleanup;
         }
-        COMPILE_OP_ARRAY_GOTO(ctx, grp->actions, *actions, parent, lys_compile_action, 0, ret, cleanup);
+        LY_LIST_FOR((struct lysp_node *)grp->actions, pnode) {
+            /* LYS_STATUS_USES in uses_status is a special bits combination to be able to detect status flags from uses */
+            ret = lys_compile_node(ctx, pnode, parent, (uses_p->flags & LYS_STATUS_MASK) | LYS_STATUS_USES, &uses_child_set);
+            LY_CHECK_GOTO(ret, cleanup);
+        }
 
         if (uses_p->when) {
             /* inherit when */
-            LY_ARRAY_FOR(*actions, u) {
-                ret = lys_compile_when(ctx, uses_p->when, uses_p->flags, lysc_data_node(parent),
-                        (struct lysc_node *)&(*actions)[u], &when_shared);
+            LY_LIST_FOR((struct lysc_node *)*actions, child) {
+                ret = lys_compile_when(ctx, uses_p->when, uses_p->flags, lysc_data_node(parent), child, &when_shared);
                 LY_CHECK_GOTO(ret, cleanup);
             }
         }
@@ -3455,21 +3528,26 @@
 
     /* compile notifications */
     if (grp->notifs) {
+        struct lysc_node_notif **notifs;
         notifs = parent ? lysc_node_notifs_p(parent) : &ctx->cur_mod->compiled->notifs;
         if (!notifs) {
             LOGVAL(ctx->ctx, LYVE_REFERENCE, "Invalid child %s \"%s\" of uses parent %s \"%s\" node.",
-                    grp->notifs[0].name, lys_nodetype2str(grp->notifs[0].nodetype), parent->name,
-                    lys_nodetype2str(parent->nodetype));
+                    grp->notifs->name, lys_nodetype2str(grp->notifs->nodetype),
+                    parent->name, lys_nodetype2str(parent->nodetype));
             ret = LY_EVALID;
             goto cleanup;
         }
-        COMPILE_OP_ARRAY_GOTO(ctx, grp->notifs, *notifs, parent, lys_compile_notif, 0, ret, cleanup);
+
+        LY_LIST_FOR((struct lysp_node *)grp->notifs, pnode) {
+            /* LYS_STATUS_USES in uses_status is a special bits combination to be able to detect status flags from uses */
+            ret = lys_compile_node(ctx, pnode, parent, (uses_p->flags & LYS_STATUS_MASK) | LYS_STATUS_USES, &uses_child_set);
+            LY_CHECK_GOTO(ret, cleanup);
+        }
 
         if (uses_p->when) {
             /* inherit when */
-            LY_ARRAY_FOR(*notifs, u) {
-                ret = lys_compile_when(ctx, uses_p->when, uses_p->flags, lysc_data_node(parent),
-                        (struct lysc_node *)&(*notifs)[u], &when_shared);
+            LY_LIST_FOR((struct lysc_node *)*notifs, child) {
+                ret = lys_compile_when(ctx, uses_p->when, uses_p->flags, lysc_data_node(parent), child, &when_shared);
                 LY_CHECK_GOTO(ret, cleanup);
             }
         }
@@ -3561,7 +3639,7 @@
 }
 
 LY_ERR
-lys_compile_grouping(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysp_grp *grp)
+lys_compile_grouping(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysp_node_grp *grp)
 {
     LY_ERR ret;
     char *path;
@@ -3614,58 +3692,12 @@
     return ret;
 }
 
-/**
- * @brief Set config flags for a node.
- *
- * @param[in] ctx Compile context.
- * @param[in] node Compiled node config to set.
- * @param[in] parent Parent of @p node.
- * @return LY_ERR value.
- */
-static LY_ERR
-lys_compile_config(struct lysc_ctx *ctx, struct lysc_node *node, struct lysc_node *parent)
-{
-    /* case never has any explicit config */
-    assert((node->nodetype != LYS_CASE) || !(node->flags & LYS_CONFIG_MASK));
-
-    if (ctx->options & (LYS_COMPILE_RPC_INPUT | LYS_COMPILE_RPC_OUTPUT)) {
-        /* ignore config statements inside RPC/action data */
-        node->flags &= ~LYS_CONFIG_MASK;
-        node->flags |= (ctx->options & LYS_COMPILE_RPC_INPUT) ? LYS_CONFIG_W : LYS_CONFIG_R;
-    } else if (ctx->options & LYS_COMPILE_NOTIFICATION) {
-        /* ignore config statements inside Notification data */
-        node->flags &= ~LYS_CONFIG_MASK;
-        node->flags |= LYS_CONFIG_R;
-    } else if (!(node->flags & LYS_CONFIG_MASK)) {
-        /* config not explicitly set, inherit it from parent */
-        if (parent) {
-            node->flags |= parent->flags & LYS_CONFIG_MASK;
-        } else {
-            /* default is config true */
-            node->flags |= LYS_CONFIG_W;
-        }
-    } else {
-        /* config set explicitly */
-        node->flags |= LYS_SET_CONFIG;
-    }
-
-    if (parent && (parent->flags & LYS_CONFIG_R) && (node->flags & LYS_CONFIG_W)) {
-        LOGVAL(ctx->ctx, LYVE_SEMANTICS,
-                "Configuration node cannot be child of any state data node.");
-        return LY_EVALID;
-    }
-
-    return LY_SUCCESS;
-}
-
 LY_ERR
 lys_compile_node(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysc_node *parent, uint16_t uses_status,
         struct ly_set *child_set)
 {
     LY_ERR ret = LY_SUCCESS;
     struct lysc_node *node = NULL;
-    struct lysp_node *dev_pnode = NULL;
-    ly_bool not_supported, enabled;
     uint32_t prev_opts = ctx->options;
 
     LY_ERR (*node_compile_spec)(struct lysc_ctx *, struct lysp_node *, struct lysc_node *);
@@ -3707,6 +3739,28 @@
         node = (struct lysc_node *)calloc(1, sizeof(struct lysc_node_anydata));
         node_compile_spec = lys_compile_node_any;
         break;
+    case LYS_RPC:
+    case LYS_ACTION:
+        if (ctx->options & (LYS_COMPILE_RPC_MASK | LYS_COMPILE_NOTIFICATION)) {
+            LOGVAL(ctx->ctx, LYVE_SEMANTICS,
+                    "Action \"%s\" is placed inside %s.", pnode->name,
+                    ctx->options & LYS_COMPILE_RPC_MASK ? "another RPC/action" : "notification");
+            return LY_EVALID;
+        }
+        node = (struct lysc_node *)calloc(1, sizeof(struct lysc_node_action));
+        node_compile_spec = lys_compile_node_action;
+        break;
+    case LYS_NOTIF:
+        if (ctx->options & (LYS_COMPILE_RPC_MASK | LYS_COMPILE_NOTIFICATION)) {
+            LOGVAL(ctx->ctx, LYVE_SEMANTICS,
+                    "Notification \"%s\" is placed inside %s.", pnode->name,
+                    ctx->options & LYS_COMPILE_RPC_MASK ? "RPC/action" : "another notification");
+            return LY_EVALID;
+        }
+        node = (struct lysc_node *)calloc(1, sizeof(struct lysc_node_notif));
+        node_compile_spec = lys_compile_node_notif;
+        ctx->options |= LYS_COMPILE_NOTIFICATION;
+        break;
     case LYS_USES:
         ret = lys_compile_uses(ctx, (struct lysp_node_uses *)pnode, parent, child_set);
         lysc_update_path(ctx, NULL, NULL);
@@ -3718,91 +3772,9 @@
     }
     LY_CHECK_ERR_RET(!node, LOGMEM(ctx->ctx), LY_EMEM);
 
-    /* compile any deviations for this node */
-    LY_CHECK_ERR_GOTO(ret = lys_compile_node_deviations_refines(ctx, pnode, parent, &dev_pnode, &not_supported),
-            free(node), cleanup);
-    if (not_supported) {
-        free(node);
-        goto cleanup;
-    } else if (dev_pnode) {
-        pnode = dev_pnode;
-    }
+    ret = lys_compile_node_(ctx, pnode, parent, uses_status, node_compile_spec, node, child_set);
 
-    node->nodetype = pnode->nodetype;
-    node->module = ctx->cur_mod;
-    node->prev = node;
-    node->flags = pnode->flags & LYS_FLAGS_COMPILED_MASK;
-
-    /* if-features */
-    LY_CHECK_ERR_RET(ret = lys_eval_iffeatures(ctx->ctx, pnode->iffeatures, &enabled), free(node), ret);
-    if (!enabled && !(ctx->options & (LYS_COMPILE_DISABLED | LYS_COMPILE_GROUPING))) {
-        ly_set_add(&ctx->disabled, node, 1, NULL);
-        ctx->options |= LYS_COMPILE_DISABLED;
-    }
-
-    /* config */
-    ret = lys_compile_config(ctx, node, parent);
-    LY_CHECK_GOTO(ret, error);
-
-    /* list ordering */
-    if (node->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
-        if ((node->flags & LYS_CONFIG_R) && (node->flags & LYS_ORDBY_MASK)) {
-            LOGWRN(ctx->ctx, "The ordered-by statement is ignored in lists representing %s (%s).",
-                    (ctx->options & LYS_COMPILE_RPC_OUTPUT) ? "RPC/action output parameters" :
-                    (ctx->options & LYS_COMPILE_NOTIFICATION) ? "notification content" : "state data", ctx->path);
-            node->flags &= ~LYS_ORDBY_MASK;
-            node->flags |= LYS_ORDBY_SYSTEM;
-        } else if (!(node->flags & LYS_ORDBY_MASK)) {
-            /* default ordering is system */
-            node->flags |= LYS_ORDBY_SYSTEM;
-        }
-    }
-
-    /* status - it is not inherited by specification, but it does not make sense to have
-     * current in deprecated or deprecated in obsolete, so we do print warning and inherit status */
-    LY_CHECK_GOTO(ret = lys_compile_status(ctx, &node->flags, uses_status ? uses_status : (parent ? parent->flags : 0)), error);
-
-    DUP_STRING_GOTO(ctx->ctx, pnode->name, node->name, ret, error);
-    DUP_STRING_GOTO(ctx->ctx, pnode->dsc, node->dsc, ret, error);
-    DUP_STRING_GOTO(ctx->ctx, pnode->ref, node->ref, ret, error);
-
-    /* insert into parent's children/compiled module (we can no longer free the node separately on error) */
-    LY_CHECK_GOTO(ret = lys_compile_node_connect(ctx, parent, node), cleanup);
-
-    if (pnode->when) {
-        /* compile when */
-        ret = lys_compile_when(ctx, pnode->when, pnode->flags, lysc_data_node(node), node, NULL);
-        LY_CHECK_GOTO(ret, cleanup);
-    }
-
-    /* connect any augments */
-    LY_CHECK_GOTO(ret = lys_compile_node_augments(ctx, node), cleanup);
-
-    /* nodetype-specific part */
-    LY_CHECK_GOTO(ret = node_compile_spec(ctx, pnode, node), cleanup);
-
-    /* final compilation tasks that require the node to be connected */
-    COMPILE_EXTS_GOTO(ctx, pnode->exts, node->exts, node, LYEXT_PAR_NODE, ret, cleanup);
-    if (node->flags & LYS_MAND_TRUE) {
-        /* inherit LYS_MAND_TRUE in parent containers */
-        lys_compile_mandatory_parents(parent, 1);
-    }
-
-    if (child_set) {
-        /* add the new node into set */
-        LY_CHECK_GOTO(ret = ly_set_add(child_set, node, 1, NULL), cleanup);
-    }
-
-    goto cleanup;
-
-error:
-    lysc_node_free(ctx->ctx, node, 0);
-cleanup:
     ctx->options = prev_opts;
-    if (ret && dev_pnode) {
-        LOGVAL(ctx->ctx, LYVE_OTHER, "Compilation of a deviated and/or refined node failed.");
-    }
-    lysp_dev_node_free(ctx->ctx, dev_pnode);
     lysc_update_path(ctx, NULL, NULL);
     return ret;
 }
diff --git a/src/schema_compile_node.h b/src/schema_compile_node.h
index 44fb5a9..869b250 100644
--- a/src/schema_compile_node.h
+++ b/src/schema_compile_node.h
@@ -71,38 +71,6 @@
         struct lysc_type **type, const char **units, struct lysp_qname **dflt);
 
 /**
- * @brief Compile parsed RPC/action schema node information.
- *
- * @param[in] ctx Compile context
- * @param[in] action_p Parsed RPC/action schema node.
- * @param[in] parent Parent node of the action, NULL in case of RPC (top-level action)
- * @param[in,out] action Prepared (empty) compiled action structure to fill.
- * @param[in] uses_status If the RPC/action is being placed instead of uses, here we have the uses's status value (as node's flags).
- * Zero means no uses, non-zero value with no status bit set mean the default status.
- * @return LY_SUCCESS on success,
- * @return LY_EVALID on validation error,
- * @return LY_EDENIED on not-supported deviation.
- */
-LY_ERR lys_compile_action(struct lysc_ctx *ctx, struct lysp_action *action_p, struct lysc_node *parent,
-        struct lysc_action *action, uint16_t uses_status);
-
-/**
- * @brief Compile parsed Notification schema node information.
- *
- * @param[in] ctx Compile context
- * @param[in] notif_p Parsed Notification schema node.
- * @param[in] parent Parent node of the Notification, NULL in case of top-level Notification
- * @param[in,out] notif Prepared (empty) compiled notification structure to fill.
- * @param[in] uses_status If the Notification is being placed instead of uses, here we have the uses's status value (as node's flags).
- * Zero means no uses, non-zero value with no status bit set mean the default status.
- * @return LY_SUCCESS on success,
- * @return LY_EVALID on validation error,
- * @return LY_EDENIED on not-supported deviation.
- */
-LY_ERR lys_compile_notif(struct lysc_ctx *ctx, struct lysp_notif *notif_p, struct lysc_node *parent,
-        struct lysc_notif *notif, uint16_t uses_status);
-
-/**
  * @brief Find the node according to the given descendant/absolute schema nodeid.
  * Used in unique, refine and augment statements.
  *
@@ -159,7 +127,7 @@
  * @param[in] grp Parsed grouping node to check.
  * @return LY_ERR value.
  */
-LY_ERR lys_compile_grouping(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysp_grp *grp);
+LY_ERR lys_compile_grouping(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysp_node_grp *grp);
 
 /**
  * @brief Compile parsed schema node information.
diff --git a/src/tree_data.h b/src/tree_data.h
index f42d90b..a5804c9 100644
--- a/src/tree_data.h
+++ b/src/tree_data.h
@@ -543,8 +543,7 @@
                                           used to get know that nodes are not equal, it cannot be used to decide that the
                                           nodes are equal due to possible collisions. */
     uint32_t flags;                  /**< [data node flags](@ref dnodeflags) */
-    const struct lysc_node *schema;  /**< pointer to the schema definition of this node, note that the target can be not just
-                                          ::lysc_node but ::lysc_action or ::lysc_notif as well */
+    const struct lysc_node *schema;  /**< pointer to the schema definition of this node */
     struct lyd_node_inner *parent;   /**< pointer to the parent node, NULL in case of root node */
     struct lyd_node *next;           /**< pointer to the next sibling node (NULL if there is no one) */
     struct lyd_node *prev;           /**< pointer to the previous sibling node \note Note that this pointer is
diff --git a/src/tree_schema.c b/src/tree_schema.c
index 4a55eb6..db98315 100644
--- a/src/tree_schema.c
+++ b/src/tree_schema.c
@@ -51,9 +51,8 @@
 lysc_tree_dfs_full(const struct lysc_node *root, lysc_dfs_clb dfs_clb, void *data)
 {
     struct lysc_node *elem, *elem2;
-    const struct lysc_action *acts;
-    const struct lysc_notif *notifs;
-    LY_ARRAY_COUNT_TYPE u;
+    const struct lysc_node_action *action;
+    const struct lysc_node_notif *notif;
 
     LY_CHECK_ARG_RET(NULL, root, dfs_clb, LY_EINVAL);
 
@@ -61,23 +60,21 @@
         /* schema node */
         LY_CHECK_RET(dfs_clb(elem, data, &LYSC_TREE_DFS_continue));
 
-        acts = lysc_node_actions(elem);
-        LY_ARRAY_FOR(acts, u) {
-            LYSC_TREE_DFS_BEGIN(&acts[u], elem2) {
+        LY_LIST_FOR(lysc_node_actions(elem), action) {
+            LYSC_TREE_DFS_BEGIN(action, elem2) {
                 /* action subtree */
                 LY_CHECK_RET(dfs_clb(elem2, data, &LYSC_TREE_DFS_continue));
 
-                LYSC_TREE_DFS_END(&acts[u], elem2);
+                LYSC_TREE_DFS_END(action, elem2);
             }
         }
 
-        notifs = lysc_node_notifs(elem);
-        LY_ARRAY_FOR(notifs, u) {
-            LYSC_TREE_DFS_BEGIN(&notifs[u], elem2) {
+        LY_LIST_FOR(lysc_node_notifs(elem), notif) {
+            LYSC_TREE_DFS_BEGIN(notif, elem2) {
                 /* notification subtree */
                 LY_CHECK_RET(dfs_clb(elem2, data, &LYSC_TREE_DFS_continue));
 
-                LYSC_TREE_DFS_END(&notifs[u], elem2);
+                LYSC_TREE_DFS_END(notif, elem2);
             }
         }
 
@@ -90,7 +87,6 @@
 API LY_ERR
 lysc_module_dfs_full(const struct lys_module *mod, lysc_dfs_clb dfs_clb, void *data)
 {
-    LY_ARRAY_COUNT_TYPE u;
     const struct lysc_node *root;
 
     LY_CHECK_ARG_RET(NULL, mod, mod->compiled, dfs_clb, LY_EINVAL);
@@ -101,13 +97,13 @@
     }
 
     /* RPCs */
-    LY_ARRAY_FOR(mod->compiled->rpcs, u) {
-        LY_CHECK_RET(lysc_tree_dfs_full((struct lysc_node *)&mod->compiled->rpcs[u], dfs_clb, data));
+    LY_LIST_FOR((const struct lysc_node *)mod->compiled->rpcs, root) {
+        LY_CHECK_RET(lysc_tree_dfs_full(root, dfs_clb, data));
     }
 
     /* notifications */
-    LY_ARRAY_FOR(mod->compiled->notifs, u) {
-        LY_CHECK_RET(lysc_tree_dfs_full((struct lysc_node *)&mod->compiled->notifs[u], dfs_clb, data));
+    LY_LIST_FOR((const struct lysc_node *)mod->compiled->notifs, root) {
+        LY_CHECK_RET(lysc_tree_dfs_full(root, dfs_clb, data));
     }
 
     return LY_SUCCESS;
@@ -135,9 +131,6 @@
     const struct lysc_node *next = NULL;
     struct lysc_node **snode;
     ly_bool action_flag = 0, notif_flag = 0;
-    const struct lysc_action *actions;
-    const struct lysc_notif *notifs;
-    LY_ARRAY_COUNT_TYPE u;
 
     LY_CHECK_ARG_RET(NULL, parent || module, NULL);
 
@@ -172,36 +165,10 @@
 
     } else if (last->nodetype & (LYS_RPC | LYS_ACTION)) {
         action_flag = 1;
-        if (last->parent) {
-            actions = lysc_node_actions(last->parent);
-        } else {
-            actions = module->rpcs;
-        }
-        LY_ARRAY_FOR(actions, u) {
-            if (&actions[u] == (struct lysc_action *)last) {
-                break;
-            }
-        }
-        if (u + 1 < LY_ARRAY_COUNT(actions)) {
-            next = (struct lysc_node *)(&actions[u + 1]);
-        }
-        goto repeat;
+        next = last->next;
     } else if (last->nodetype == LYS_NOTIF) {
         action_flag = notif_flag = 1;
-        if (last->parent) {
-            notifs = lysc_node_notifs(last->parent);
-        } else {
-            notifs = module->notifs;
-        }
-        LY_ARRAY_FOR(notifs, u) {
-            if (&notifs[u] == (struct lysc_notif *)last) {
-                break;
-            }
-        }
-        if (u + 1 < LY_ARRAY_COUNT(notifs)) {
-            next = (struct lysc_node *)(&notifs[u + 1]);
-        }
-        goto repeat;
+        next = last->next;
     } else {
         next = last->next;
     }
@@ -637,8 +604,8 @@
 API LY_ERR
 lysc_set_private(const struct lysc_node *node, void *priv, void **prev_priv_p)
 {
-    struct lysc_action *act;
-    struct lysc_notif *notif;
+    struct lysc_node_action *act;
+    struct lysc_node_notif *notif;
 
     LY_CHECK_ARG_RET(NULL, node, LY_EINVAL);
 
@@ -658,14 +625,14 @@
         break;
     case LYS_RPC:
     case LYS_ACTION:
-        act = (struct lysc_action *)node;
+        act = (struct lysc_node_action *)node;
         if (prev_priv_p) {
             *prev_priv_p = act->priv;
         }
         act->priv = priv;
         break;
     case LYS_NOTIF:
-        notif = (struct lysc_notif *)node;
+        notif = (struct lysc_node_notif *)node;
         if (prev_priv_p) {
             *prev_priv_p = notif->priv;
         }
diff --git a/src/tree_schema.h b/src/tree_schema.h
index 36afd4e..eb0f609 100644
--- a/src/tree_schema.h
+++ b/src/tree_schema.h
@@ -108,7 +108,6 @@
  * - ::lysc_has_when()
  *
  * - ::lysc_node_children()
- * - ::lysc_node_children_full()
  * - ::lysc_node_parent_full()
  * - ::lysc_node_actions()
  * - ::lysc_node_notifs()
@@ -171,7 +170,7 @@
  * </pre>
  *
  * Use the same parameters for #LYSC_TREE_DFS_BEGIN and #LYSC_TREE_DFS_END. While
- * START can be any of the lysc_node* types (including lysc_action and lysc_notif),
+ * START can be any of the lysc_node* types (including lysc_node_action and lysc_node_notif),
  * ELEM variable must be of the struct lysc_node* type.
  *
  * To skip a particular subtree, instead of the continue statement, set LYSC_TREE_DFS_continue
@@ -193,7 +192,7 @@
  * to the #LYSC_TREE_DFS_BEGIN - they always have to be used together.
  *
  * Use the same parameters for #LYSC_TREE_DFS_BEGIN and #LYSC_TREE_DFS_END. While
- * START can be a pointer to any of the lysc_node* types (including lysc_action and lysc_notif),
+ * START can be a pointer to any of the lysc_node* types (including lysc_node_action and lysc_node_notif),
  * ELEM variable must be pointer to the lysc_node type.
  *
  * Use with closing curly bracket '}' after the macro.
@@ -206,7 +205,7 @@
     if (LYSC_TREE_DFS_continue) { \
         (LYSC_TREE_DFS_next) = NULL; \
     } else { \
-        (LYSC_TREE_DFS_next) = (struct lysc_node *)lysc_node_children_full(ELEM, 0); \
+        (LYSC_TREE_DFS_next) = (struct lysc_node *)lysc_node_children(ELEM, 0); \
     } \
     if (!(LYSC_TREE_DFS_next)) { \
         /* no children, try siblings */ \
@@ -228,7 +227,7 @@
     } \
     if ((ELEM)->nodetype == LYS_INPUT) { \
         /* after input, get output */ \
-        (NEXT) = (struct lysc_node *)lysc_node_children_full(lysc_node_parent_full(ELEM), LYS_CONFIG_R); \
+        (NEXT) = (struct lysc_node *)lysc_node_children(lysc_node_parent_full(ELEM), LYS_CONFIG_R); \
     } else if ((ELEM)->nodetype == LYS_OUTPUT) { \
         /* no sibling of output */ \
         (NEXT) = NULL; \
@@ -354,9 +353,9 @@
  */
 typedef enum {
     LYEXT_PAR_MODULE,    /**< ::lysc_module */
-    LYEXT_PAR_NODE,      /**< ::lysc_node (and the derived structures including ::lysc_action and ::lysc_notif) */
-    LYEXT_PAR_INPUT,     /**< ::lysc_action_inout */
-    LYEXT_PAR_OUTPUT,    /**< ::lysc_action_inout */
+    LYEXT_PAR_NODE,      /**< ::lysc_node (and the derived structures including ::lysc_node_action and ::lysc_node_notif) */
+    LYEXT_PAR_INPUT,     /**< ::lysc_node_action_inout */
+    LYEXT_PAR_OUTPUT,    /**< ::lysc_node_action_inout */
     LYEXT_PAR_TYPE,      /**< ::lysc_type */
     LYEXT_PAR_TYPE_BIT,  /**< ::lysc_type_bitenum_item */
     LYEXT_PAR_TYPE_ENUM, /**< ::lysc_type_bitenum_item */
@@ -640,24 +639,6 @@
 };
 
 /**
- * @brief YANG grouping-stmt
- */
-struct lysp_grp {
-    struct lysp_node *parent;        /**< parent node (NULL if this is a top-level grouping) */
-    uint16_t nodetype;               /**< LYS_GROUPING */
-    uint16_t flags;                  /**< [schema node flags](@ref snodeflags) - only LYS_STATUS_* values are allowed */
-    const char *name;                /**< grouping name (mandatory) */
-    const char *dsc;                 /**< description statement */
-    const char *ref;                 /**< reference statement */
-    struct lysp_tpdf *typedefs;      /**< list of typedefs ([sized array](@ref sizedarrays)) */
-    struct lysp_grp *groupings;      /**< list of groupings ([sized array](@ref sizedarrays)) */
-    struct lysp_node *data;          /**< list of data nodes (linked list) */
-    struct lysp_action *actions;     /**< list of actions ([sized array](@ref sizedarrays)) */
-    struct lysp_notif *notifs;       /**< list of notifications ([sized array](@ref sizedarrays)) */
-    struct lysp_ext_instance *exts;  /**< list of the extension instances ([sized array](@ref sizedarrays)) */
-};
-
-/**
  * @brief YANG when-stmt
  */
 struct lysp_when {
@@ -685,24 +666,6 @@
 };
 
 /**
- * @brief YANG uses-augment-stmt and augment-stmt (compatible with struct lysp_node )
- */
-struct lysp_augment {
-    struct lysp_node *parent;        /**< parent node (NULL if this is a top-level augment) */
-    uint16_t nodetype;               /**< LYS_AUGMENT */
-    uint16_t flags;                  /**< [schema node flags](@ref snodeflags) - only LYS_STATUS_* values are allowed */
-    struct lysp_node *child;         /**< list of data nodes (linked list) */
-    const char *nodeid;              /**< target schema nodeid (mandatory) - absolute for global augments, descendant for uses's augments */
-    const char *dsc;                 /**< description statement */
-    const char *ref;                 /**< reference statement */
-    struct lysp_when *when;          /**< when statement */
-    struct lysp_qname *iffeatures;   /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
-    struct lysp_ext_instance *exts;  /**< list of the extension instances ([sized array](@ref sizedarrays)) */
-    struct lysp_action *actions;     /**< list of actions ([sized array](@ref sizedarrays)) */
-    struct lysp_notif *notifs;       /**< list of notifications ([sized array](@ref sizedarrays)) */
-};
-
-/**
  * @ingroup schematree
  * @defgroup deviatetypes Deviate types
  *
@@ -973,38 +936,48 @@
  * @brief Extension structure of the lysp_node for YANG container
  */
 struct lysp_node_container {
-    struct lysp_node *parent;        /**< parent node (NULL if this is a top-level node) */
-    uint16_t nodetype;               /**< LYS_CONTAINER */
-    uint16_t flags;                  /**< [schema node flags](@ref snodeflags) */
-    struct lysp_node *next;          /**< pointer to the next sibling node (NULL if there is no one) */
-    const char *name;                /**< node name (mandatory) */
-    const char *dsc;                 /**< description statement */
-    const char *ref;                 /**< reference statement */
-    struct lysp_when *when;          /**< when statement */
-    struct lysp_qname *iffeatures;   /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
-    struct lysp_ext_instance *exts;  /**< list of the extension instances ([sized array](@ref sizedarrays)) */
+    union {
+        struct lysp_node node;        /**< implicit cast for the members compatible with ::lysp_node */
+        struct {
+            struct lysp_node *parent; /**< parent node (NULL if this is a top-level node) */
+            uint16_t nodetype;       /**< LYS_CONTAINER */
+            uint16_t flags;          /**< [schema node flags](@ref snodeflags) */
+            struct lysp_node *next;  /**< pointer to the next sibling node (NULL if there is no one) */
+            const char *name;        /**< node name (mandatory) */
+            const char *dsc;         /**< description statement */
+            const char *ref;         /**< reference statement */
+            struct lysp_when *when;  /**< when statement */
+            struct lysp_qname *iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
+            struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
+        };
+    };                            /**< common part corresponding to ::lysp_node */
 
     /* container */
     struct lysp_restr *musts;        /**< list of must restrictions ([sized array](@ref sizedarrays)) */
     const char *presence;            /**< presence description */
     struct lysp_tpdf *typedefs;      /**< list of typedefs ([sized array](@ref sizedarrays)) */
-    struct lysp_grp *groupings;      /**< list of groupings ([sized array](@ref sizedarrays)) */
+    struct lysp_node_grp *groupings; /**< list of groupings (linked list) */
     struct lysp_node *child;         /**< list of data nodes (linked list) */
-    struct lysp_action *actions;     /**< list of actions ([sized array](@ref sizedarrays)) */
-    struct lysp_notif *notifs;       /**< list of notifications ([sized array](@ref sizedarrays)) */
+    struct lysp_node_action *actions;/**< list of actions (linked list) */
+    struct lysp_node_notif *notifs;  /**< list of notifications (linked list) */
 };
 
 struct lysp_node_leaf {
-    struct lysp_node *parent;        /**< parent node (NULL if this is a top-level node) */
-    uint16_t nodetype;               /**< LYS_LEAF */
-    uint16_t flags;                  /**< [schema node flags](@ref snodeflags) */
-    struct lysp_node *next;          /**< pointer to the next sibling node (NULL if there is no one) */
-    const char *name;                /**< node name (mandatory) */
-    const char *dsc;                 /**< description statement */
-    const char *ref;                 /**< reference statement */
-    struct lysp_when *when;          /**< when statement */
-    struct lysp_qname *iffeatures;   /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
-    struct lysp_ext_instance *exts;  /**< list of the extension instances ([sized array](@ref sizedarrays)) */
+    union {
+        struct lysp_node node;       /**< implicit cast for the members compatible with ::lysp_node */
+        struct {
+            struct lysp_node *parent; /**< parent node (NULL if this is a top-level node) */
+            uint16_t nodetype;       /**< LYS_LEAF */
+            uint16_t flags;          /**< [schema node flags](@ref snodeflags) */
+            struct lysp_node *next;  /**< pointer to the next sibling node (NULL if there is no one) */
+            const char *name;        /**< node name (mandatory) */
+            const char *dsc;         /**< description statement */
+            const char *ref;         /**< reference statement */
+            struct lysp_when *when;  /**< when statement */
+            struct lysp_qname *iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
+            struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
+        };
+    };                            /**< common part corresponding to ::lysp_node */
 
     /* leaf */
     struct lysp_restr *musts;        /**< list of must restrictions ([sized array](@ref sizedarrays)) */
@@ -1014,16 +987,21 @@
 };
 
 struct lysp_node_leaflist {
-    struct lysp_node *parent;        /**< parent node (NULL if this is a top-level node) */
-    uint16_t nodetype;               /**< LYS_LEAFLIST */
-    uint16_t flags;                  /**< [schema node flags](@ref snodeflags) */
-    struct lysp_node *next;          /**< pointer to the next sibling node (NULL if there is no one) */
-    const char *name;                /**< node name (mandatory) */
-    const char *dsc;                 /**< description statement */
-    const char *ref;                 /**< reference statement */
-    struct lysp_when *when;          /**< when statement */
-    struct lysp_qname *iffeatures;   /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
-    struct lysp_ext_instance *exts;  /**< list of the extension instances ([sized array](@ref sizedarrays)) */
+    union {
+        struct lysp_node node;       /**< implicit cast for the members compatible with ::lysp_node */
+        struct {
+            struct lysp_node *parent; /**< parent node (NULL if this is a top-level node) */
+            uint16_t nodetype;       /**< LYS_LEAFLIST */
+            uint16_t flags;          /**< [schema node flags](@ref snodeflags) */
+            struct lysp_node *next;  /**< pointer to the next sibling node (NULL if there is no one) */
+            const char *name;        /**< node name (mandatory) */
+            const char *dsc;         /**< description statement */
+            const char *ref;         /**< reference statement */
+            struct lysp_when *when;  /**< when statement */
+            struct lysp_qname *iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
+            struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
+        };
+    };                            /**< common part corresponding to ::lysp_node */
 
     /* leaf-list */
     struct lysp_restr *musts;        /**< list of must restrictions ([sized array](@ref sizedarrays)) */
@@ -1036,41 +1014,51 @@
 };
 
 struct lysp_node_list {
-    struct lysp_node *parent;        /**< parent node (NULL if this is a top-level node) */
-    uint16_t nodetype;               /**< LYS_LIST */
-    uint16_t flags;                  /**< [schema node flags](@ref snodeflags) */
-    struct lysp_node *next;          /**< pointer to the next sibling node (NULL if there is no one) */
-    const char *name;                /**< node name (mandatory) */
-    const char *dsc;                 /**< description statement */
-    const char *ref;                 /**< reference statement */
-    struct lysp_when *when;          /**< when statement */
-    struct lysp_qname *iffeatures;   /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
-    struct lysp_ext_instance *exts;  /**< list of the extension instances ([sized array](@ref sizedarrays)) */
+    union {
+        struct lysp_node node;       /**< implicit cast for the members compatible with ::lysp_node */
+        struct {
+            struct lysp_node *parent; /**< parent node (NULL if this is a top-level node) */
+            uint16_t nodetype;       /**< LYS_LIST */
+            uint16_t flags;          /**< [schema node flags](@ref snodeflags) */
+            struct lysp_node *next;  /**< pointer to the next sibling node (NULL if there is no one) */
+            const char *name;        /**< node name (mandatory) */
+            const char *dsc;         /**< description statement */
+            const char *ref;         /**< reference statement */
+            struct lysp_when *when;  /**< when statement */
+            struct lysp_qname *iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
+            struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
+        };
+    };                            /**< common part corresponding to ::lysp_node */
 
     /* list */
     struct lysp_restr *musts;        /**< list of must restrictions ([sized array](@ref sizedarrays)) */
     const char *key;                 /**< keys specification */
     struct lysp_tpdf *typedefs;      /**< list of typedefs ([sized array](@ref sizedarrays)) */
-    struct lysp_grp *groupings;      /**< list of groupings ([sized array](@ref sizedarrays)) */
+    struct lysp_node_grp *groupings; /**< list of groupings (linked list) */
     struct lysp_node *child;         /**< list of data nodes (linked list) */
-    struct lysp_action *actions;     /**< list of actions ([sized array](@ref sizedarrays)) */
-    struct lysp_notif *notifs;       /**< list of notifications ([sized array](@ref sizedarrays)) */
+    struct lysp_node_action *actions;/**< list of actions (linked list) */
+    struct lysp_node_notif *notifs;  /**< list of notifications (linked list) */
     struct lysp_qname *uniques;      /**< list of unique specifications ([sized array](@ref sizedarrays)) */
     uint32_t min;                    /**< min-elements constraint */
     uint32_t max;                    /**< max-elements constraint, 0 means unbounded */
 };
 
 struct lysp_node_choice {
-    struct lysp_node *parent;        /**< parent node (NULL if this is a top-level node) */
-    uint16_t nodetype;               /**< LYS_CHOICE */
-    uint16_t flags;                  /**< [schema node flags](@ref snodeflags) */
-    struct lysp_node *next;          /**< pointer to the next sibling node (NULL if there is no one) */
-    const char *name;                /**< node name (mandatory) */
-    const char *dsc;                 /**< description statement */
-    const char *ref;                 /**< reference statement */
-    struct lysp_when *when;          /**< when statement */
-    struct lysp_qname *iffeatures;   /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
-    struct lysp_ext_instance *exts;  /**< list of the extension instances ([sized array](@ref sizedarrays)) */
+    union {
+        struct lysp_node node;       /**< implicit cast for the members compatible with ::lysp_node */
+        struct {
+            struct lysp_node *parent; /**< parent node (NULL if this is a top-level node) */
+            uint16_t nodetype;       /**< LYS_CHOICE */
+            uint16_t flags;          /**< [schema node flags](@ref snodeflags) */
+            struct lysp_node *next;  /**< pointer to the next sibling node (NULL if there is no one) */
+            const char *name;        /**< node name (mandatory) */
+            const char *dsc;         /**< description statement */
+            const char *ref;         /**< reference statement */
+            struct lysp_when *when;  /**< when statement */
+            struct lysp_qname *iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
+            struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
+        };
+    };                            /**< common part corresponding to ::lysp_node */
 
     /* choice */
     struct lysp_node *child;         /**< list of data nodes (linked list) */
@@ -1078,108 +1066,205 @@
 };
 
 struct lysp_node_case {
-    struct lysp_node *parent;        /**< parent node (NULL if this is a top-level node) */
-    uint16_t nodetype;               /**< LYS_CASE */
-    uint16_t flags;                  /**< [schema node flags](@ref snodeflags) */
-    struct lysp_node *next;          /**< pointer to the next sibling node (NULL if there is no one) */
-    const char *name;                /**< node name (mandatory) */
-    const char *dsc;                 /**< description statement */
-    const char *ref;                 /**< reference statement */
-    struct lysp_when *when;          /**< when statement */
-    struct lysp_qname *iffeatures;   /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
-    struct lysp_ext_instance *exts;  /**< list of the extension instances ([sized array](@ref sizedarrays)) */
+    union {
+        struct lysp_node node;       /**< implicit cast for the members compatible with ::lysp_node */
+        struct {
+            struct lysp_node *parent; /**< parent node (NULL if this is a top-level node) */
+            uint16_t nodetype;       /**< LYS_CASE */
+            uint16_t flags;          /**< [schema node flags](@ref snodeflags) */
+            struct lysp_node *next;  /**< pointer to the next sibling node (NULL if there is no one) */
+            const char *name;        /**< node name (mandatory) */
+            const char *dsc;         /**< description statement */
+            const char *ref;         /**< reference statement */
+            struct lysp_when *when;  /**< when statement */
+            struct lysp_qname *iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
+            struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
+        };
+    };                            /**< common part corresponding to ::lysp_node */
 
     /* case */
     struct lysp_node *child;         /**< list of data nodes (linked list) */
 };
 
 struct lysp_node_anydata {
-    struct lysp_node *parent;        /**< parent node (NULL if this is a top-level node) */
-    uint16_t nodetype;               /**< LYS_ANYXML or LYS_ANYDATA */
-    uint16_t flags;                  /**< [schema node flags](@ref snodeflags) */
-    struct lysp_node *next;          /**< pointer to the next sibling node (NULL if there is no one) */
-    const char *name;                /**< node name (mandatory) */
-    const char *dsc;                 /**< description statement */
-    const char *ref;                 /**< reference statement */
-    struct lysp_when *when;          /**< when statement */
-    struct lysp_qname *iffeatures;   /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
-    struct lysp_ext_instance *exts;  /**< list of the extension instances ([sized array](@ref sizedarrays)) */
+    union {
+        struct lysp_node node;       /**< implicit cast for the members compatible with ::lysp_node */
+        struct {
+            struct lysp_node *parent; /**< parent node (NULL if this is a top-level node) */
+            uint16_t nodetype;       /**< LYS_ANYXML or LYS_ANYDATA */
+            uint16_t flags;          /**< [schema node flags](@ref snodeflags) */
+            struct lysp_node *next;  /**< pointer to the next sibling node (NULL if there is no one) */
+            const char *name;        /**< node name (mandatory) */
+            const char *dsc;         /**< description statement */
+            const char *ref;         /**< reference statement */
+            struct lysp_when *when;  /**< when statement */
+            struct lysp_qname *iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
+            struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
+        };
+    };                            /**< common part corresponding to ::lysp_node */
 
     /* anyxml/anydata */
     struct lysp_restr *musts;        /**< list of must restrictions ([sized array](@ref sizedarrays)) */
 };
 
 struct lysp_node_uses {
-    struct lysp_node *parent;        /**< parent node (NULL if this is a top-level node) */
-    uint16_t nodetype;               /**< LYS_USES */
-    uint16_t flags;                  /**< [schema node flags](@ref snodeflags) */
-    struct lysp_node *next;          /**< pointer to the next sibling node (NULL if there is no one) */
-    const char *name;                /**< grouping name reference (mandatory) */
-    const char *dsc;                 /**< description statement */
-    const char *ref;                 /**< reference statement */
-    struct lysp_when *when;          /**< when statement */
-    struct lysp_qname *iffeatures;   /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
-    struct lysp_ext_instance *exts;  /**< list of the extension instances ([sized array](@ref sizedarrays)) */
+    union {
+        struct lysp_node node;       /**< implicit cast for the members compatible with ::lysp_node */
+        struct {
+            struct lysp_node *parent; /**< parent node (NULL if this is a top-level node) */
+            uint16_t nodetype;       /**< LYS_USES */
+            uint16_t flags;          /**< [schema node flags](@ref snodeflags) */
+            struct lysp_node *next;  /**< pointer to the next sibling node (NULL if there is no one) */
+            const char *name;        /**< grouping name reference (mandatory) */
+            const char *dsc;         /**< description statement */
+            const char *ref;         /**< reference statement */
+            struct lysp_when *when;  /**< when statement */
+            struct lysp_qname *iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
+            struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
+        };
+    };                            /**< common part corresponding to ::lysp_node */
 
     /* uses */
     struct lysp_refine *refines;     /**< list of uses's refines ([sized array](@ref sizedarrays)) */
-    struct lysp_augment *augments;   /**< list of uses's augment ([sized array](@ref sizedarrays)) */
+    struct lysp_node_augment *augments; /**< list of augments (linked list) */
 };
 
 /**
  * @brief YANG input-stmt and output-stmt
  */
-struct lysp_action_inout {
-    struct lysp_node *parent;        /**< parent node (NULL if this is a top-level node) */
-    uint16_t nodetype;               /**< LYS_INPUT or LYS_OUTPUT */
+struct lysp_node_action_inout {
+    union {
+        struct lysp_node node;       /**< implicit cast for the members compatible with ::lysp_node */
+        struct {
+            struct lysp_node *parent; /**< parent node (NULL if this is a top-level node) */
+            uint16_t nodetype;       /**< LYS_INPUT or LYS_OUTPUT */
+            uint16_t flags;          /**< [schema node flags](@ref snodeflags) */
+            struct lysp_node *next;  /**< NULL */
+            const char *name;        /**< empty string */
+            const char *dsc;         /**< ALWAYS NULL, compatibility member with ::lysp_node */
+            const char *ref;         /**< ALWAYS NULL, compatibility member with ::lysp_node */
+            struct lysp_when *when;  /**< ALWAYS NULL, compatibility member with ::lysp_node */
+            struct lysp_qname *iffeatures; /**< ALWAYS NULL, compatibility member with ::lysp_node */
+            struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
+        };
+    };                            /**< common part corresponding to ::lysp_node */
+
+    /* inout */
     struct lysp_restr *musts;        /**< list of must restrictions ([sized array](@ref sizedarrays)) */
     struct lysp_tpdf *typedefs;      /**< list of typedefs ([sized array](@ref sizedarrays)) */
-    struct lysp_grp *groupings;      /**< list of groupings ([sized array](@ref sizedarrays)) */
+    struct lysp_node_grp *groupings; /**< list of groupings (linked list) */
     struct lysp_node *data;          /**< list of data nodes (linked list) */
-    struct lysp_ext_instance *exts;  /**< list of the extension instances ([sized array](@ref sizedarrays)) */
 };
 
 /**
  * @brief YANG rpc-stmt and action-stmt
  */
-struct lysp_action {
-    struct lysp_node *parent;        /**< parent node (NULL if this is a top-level node) */
-    uint16_t nodetype;               /**< LYS_RPC or LYS_ACTION */
-    uint16_t flags;                  /**< [schema node flags](@ref snodeflags) */
-    struct lysp_tpdf *typedefs;      /**< list of typedefs ([sized array](@ref sizedarrays)) */
-    const char *name;                /**< grouping name reference (mandatory) */
-    const char *dsc;                 /**< description statement */
-    const char *ref;                 /**< reference statement */
-    struct lysp_grp *groupings;      /**< list of groupings ([sized array](@ref sizedarrays)) */
-    struct lysp_qname *iffeatures;   /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
-    struct lysp_ext_instance *exts;  /**< list of the extension instances ([sized array](@ref sizedarrays)) */
+struct lysp_node_action {
+    union {
+        struct lysp_node node;       /**< implicit cast for the members compatible with ::lysp_node */
+        struct {
+            struct lysp_node *parent; /**< parent node (NULL if this is a top-level node) */
+            uint16_t nodetype;       /**< LYS_RPC or LYS_ACTION */
+            uint16_t flags;          /**< [schema node flags](@ref snodeflags) */
+            struct lysp_node_action *next; /**< pointer to the next action (NULL if there is no one) */
+            const char *name;        /**< grouping name reference (mandatory) */
+            const char *dsc;         /**< description statement */
+            const char *ref;         /**< reference statement */
+            struct lysp_when *when;  /**< ALWAYS NULL, compatibility member with ::lysp_node */
+            struct lysp_qname *iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
+            struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
+        };
+    };                            /**< common part corresponding to ::lysp_node */
 
     /* action */
-    struct lysp_action_inout input;  /**< RPC's/Action's input */
-    struct lysp_action_inout output; /**< RPC's/Action's output */
+    struct lysp_tpdf *typedefs;      /**< list of typedefs ([sized array](@ref sizedarrays)) */
+    struct lysp_node_grp *groupings; /**< list of groupings (linked list) */
+
+    struct lysp_node_action_inout input;  /**< RPC's/Action's input */
+    struct lysp_node_action_inout output; /**< RPC's/Action's output */
 };
 
 /**
  * @brief YANG notification-stmt
  */
-struct lysp_notif {
-    struct lysp_node *parent;        /**< parent node (NULL if this is a top-level node) */
-    uint16_t nodetype;               /**< LYS_NOTIF */
-    uint16_t flags;                  /**< [schema node flags](@ref snodeflags) - only LYS_STATUS_* values are allowed */
-    struct lysp_tpdf *typedefs;      /**< list of typedefs ([sized array](@ref sizedarrays)) */
-    const char *name;                /**< grouping name reference (mandatory) */
-    const char *dsc;                 /**< description statement */
-    const char *ref;                 /**< reference statement */
-    struct lysp_grp *groupings;      /**< list of groupings ([sized array](@ref sizedarrays)) */
-    struct lysp_qname *iffeatures;   /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
-    struct lysp_ext_instance *exts;  /**< list of the extension instances ([sized array](@ref sizedarrays)) */
+struct lysp_node_notif {
+    union {
+        struct lysp_node node;       /**< implicit cast for the members compatible with ::lysp_node */
+        struct {
+            struct lysp_node *parent; /**< parent node (NULL if this is a top-level node) */
+            uint16_t nodetype;       /**< LYS_NOTIF */
+            uint16_t flags;          /**< [schema node flags](@ref snodeflags) - only LYS_STATUS_* values are allowed */
+            struct lysp_node_notif *next; /**< pointer to the next notification (NULL if there is no one) */
+            const char *name;        /**< grouping name reference (mandatory) */
+            const char *dsc;         /**< description statement */
+            const char *ref;         /**< reference statement */
+            struct lysp_when *when;  /**< ALWAYS NULL, compatibility member with ::lysp_node */
+            struct lysp_qname *iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
+            struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
+        };
+    };                            /**< common part corresponding to ::lysp_node */
 
     /* notif */
     struct lysp_restr *musts;        /**< list of must restrictions ([sized array](@ref sizedarrays)) */
+    struct lysp_tpdf *typedefs;      /**< list of typedefs ([sized array](@ref sizedarrays)) */
+    struct lysp_node_grp *groupings; /**< list of groupings (linked list) */
     struct lysp_node *data;          /**< list of data nodes (linked list) */
 };
 
 /**
+ * @brief YANG grouping-stmt
+ */
+struct lysp_node_grp {
+    union {
+        struct lysp_node node;       /**< implicit cast for the members compatible with ::lysp_node */
+        struct {
+            struct lysp_node *parent;/**< parent node (NULL if this is a top-level grouping) */
+            uint16_t nodetype;       /**< LYS_GROUPING */
+            uint16_t flags;          /**< [schema node flags](@ref snodeflags) - only LYS_STATUS_* values are allowed */
+            struct lysp_node_grp *next; /**< pointer to the next grouping (NULL if there is no one) */
+            const char *name;        /**< grouping name (mandatory) */
+            const char *dsc;         /**< description statement */
+            const char *ref;         /**< reference statement */
+            struct lysp_when *when;  /**< ALWAYS NULL, compatibility member with ::lysp_node */
+            struct lysp_qname *iffeatures; /**< ALWAYS NULL, compatibility member with ::lysp_node */
+            struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
+        };
+    };                                /**< common part corresponding to ::lysp_node */
+
+    /* grp */
+    struct lysp_tpdf *typedefs;       /**< list of typedefs ([sized array](@ref sizedarrays)) */
+    struct lysp_node_grp *groupings;  /**< list of groupings (linked list) */
+    struct lysp_node *data;           /**< list of data nodes (linked list) */
+    struct lysp_node_action *actions; /**< list of actions (linked list) */
+    struct lysp_node_notif *notifs;   /**< list of notifications (linked list) */
+};
+
+/**
+ * @brief YANG uses-augment-stmt and augment-stmt (compatible with struct lysp_node )
+ */
+struct lysp_node_augment {
+    union {
+        struct lysp_node node;       /**< implicit cast for the members compatible with ::lysp_node */
+        struct {
+            struct lysp_node *parent;/**< parent node (NULL if this is a top-level augment) */
+            uint16_t nodetype;       /**< LYS_AUGMENT */
+            uint16_t flags;          /**< [schema node flags](@ref snodeflags) - only LYS_STATUS_* values are allowed */
+            struct lysp_node_augment *next; /**< pointer to the next augment (NULL if there is no one) */
+            const char *nodeid;      /**< target schema nodeid (mandatory) - absolute for global augments, descendant for uses's augments */
+            const char *dsc;         /**< description statement */
+            const char *ref;         /**< reference statement */
+            struct lysp_when *when;  /**< when statement */
+            struct lysp_qname *iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
+            struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
+        };
+    };                                /**< common part corresponding to ::lysp_node */
+
+    struct lysp_node *child;         /**< list of data nodes (linked list) */
+    struct lysp_node_action *actions;/**< list of actions (linked list) */
+    struct lysp_node_notif *notifs;  /**< list of notifications (linked list) */
+};
+
+/**
  * @brief supported YANG schema version values
  */
 typedef enum LYS_VERSION {
@@ -1204,11 +1289,11 @@
     struct lysp_feature *features;   /**< list of feature definitions ([sized array](@ref sizedarrays)) */
     struct lysp_ident *identities;   /**< list of identities ([sized array](@ref sizedarrays)) */
     struct lysp_tpdf *typedefs;      /**< list of typedefs ([sized array](@ref sizedarrays)) */
-    struct lysp_grp *groupings;      /**< list of groupings ([sized array](@ref sizedarrays)) */
+    struct lysp_node_grp *groupings; /**< list of groupings (linked list) */
     struct lysp_node *data;          /**< list of module's top-level data nodes (linked list) */
-    struct lysp_augment *augments;   /**< list of augments ([sized array](@ref sizedarrays)) */
-    struct lysp_action *rpcs;        /**< list of RPCs ([sized array](@ref sizedarrays)) */
-    struct lysp_notif *notifs;       /**< list of notifications ([sized array](@ref sizedarrays)) */
+    struct lysp_node_augment *augments; /**< list of augments (linked list) */
+    struct lysp_node_action *rpcs;   /**< list of RPCs (linked list) */
+    struct lysp_node_notif *notifs;  /**< list of notifications (linked list) */
     struct lysp_deviation *deviations; /**< list of deviations ([sized array](@ref sizedarrays)) */
     struct lysp_ext_instance *exts;  /**< list of the extension instances ([sized array](@ref sizedarrays)) */
 
@@ -1228,11 +1313,11 @@
     struct lysp_feature *features;   /**< list of feature definitions ([sized array](@ref sizedarrays)) */
     struct lysp_ident *identities;   /**< list of identities ([sized array](@ref sizedarrays)) */
     struct lysp_tpdf *typedefs;      /**< list of typedefs ([sized array](@ref sizedarrays)) */
-    struct lysp_grp *groupings;      /**< list of groupings ([sized array](@ref sizedarrays)) */
+    struct lysp_node_grp *groupings; /**< list of groupings (linked list) */
     struct lysp_node *data;          /**< list of module's top-level data nodes (linked list) */
-    struct lysp_augment *augments;   /**< list of augments ([sized array](@ref sizedarrays)) */
-    struct lysp_action *rpcs;        /**< list of RPCs ([sized array](@ref sizedarrays)) */
-    struct lysp_notif *notifs;       /**< list of notifications ([sized array](@ref sizedarrays)) */
+    struct lysp_node_augment *augments; /**< list of augments (linked list) */
+    struct lysp_node_action *rpcs;   /**< list of RPCs (linked list) */
+    struct lysp_node_notif *notifs;  /**< list of notifications (linked list) */
     struct lysp_deviation *deviations; /**< list of deviations ([sized array](@ref sizedarrays)) */
     struct lysp_ext_instance *exts;  /**< list of the extension instances ([sized array](@ref sizedarrays)) */
 
@@ -1495,55 +1580,76 @@
     struct lysc_range *length;       /**< Optional length limitation */
 };
 
-struct lysc_action_inout {
-    uint16_t nodetype;               /**< LYS_INPUT or LYS_OUTPUT */
-    struct lysc_node *data;          /**< first child node (linked list) */
-    struct lysc_must *musts;         /**< list of must restrictions ([sized array](@ref sizedarrays)) */
-};
-
 /**
  * @brief Maximum number of hashes stored in a schema node.
  */
 #define LYS_NODE_HASH_COUNT 4
 
-struct lysc_action {
-    uint16_t nodetype;               /**< LYS_RPC or LYS_ACTION */
-    uint16_t flags;                  /**< [schema node flags](@ref snodeflags) */
-    uint8_t hash[LYS_NODE_HASH_COUNT]; /**< schema hash required for LYB printer/parser */
-    struct lys_module *module;       /**< module structure */
-    struct lysc_node *parent;        /**< parent node (NULL in case of top level node - RPC) */
-
-    struct lysc_ext_instance *input_exts;  /**< list of the extension instances of input ([sized array](@ref sizedarrays)) */
-    struct lysc_ext_instance *output_exts; /**< list of the extension instances of outpu ([sized array](@ref sizedarrays)) */
-
-    const char *name;                /**< action/RPC name (mandatory) */
-    const char *dsc;                 /**< description */
-    const char *ref;                 /**< reference */
-    struct lysc_ext_instance *exts;  /**< list of the extension instances ([sized array](@ref sizedarrays)) */
-
-    struct lysc_action_inout input;  /**< RPC's/action's input */
-    struct lysc_action_inout output; /**< RPC's/action's output */
-    struct lysc_when **when;         /**< list of pointers to when statements ([sized array](@ref sizedarrays)) */
-    void *priv;                      /** private arbitrary user data, not used by libyang */
-
-};
-
-struct lysc_notif {
-    uint16_t nodetype;               /**< LYS_NOTIF */
+struct lysc_node_action_inout {
+    uint16_t nodetype;               /**< LYS_INPUT or LYS_OUTPUT */
     uint16_t flags;                  /**< [schema node flags](@ref snodeflags) */
     uint8_t hash[LYS_NODE_HASH_COUNT]; /**< schema hash required for LYB printer/parser */
     struct lys_module *module;       /**< module structure */
     struct lysc_node *parent;        /**< parent node (NULL in case of top level node) */
-
-    struct lysc_node *data;          /**< first child node (linked list) */
-    struct lysc_must *musts;         /**< list of must restrictions ([sized array](@ref sizedarrays)) */
-
+    struct lysc_node *next;          /**< next sibling node (NULL if there is no one) */
+    struct lysc_node *prev;          /**< pointer to the previous sibling node \note Note that this pointer is
+                                          never NULL. If there is no sibling node, pointer points to the node
+                                          itself. In case of the first node, this pointer points to the last
+                                          node in the list. */
     const char *name;                /**< Notification name (mandatory) */
     const char *dsc;                 /**< description */
     const char *ref;                 /**< reference */
     struct lysc_ext_instance *exts;  /**< list of the extension instances ([sized array](@ref sizedarrays)) */
     struct lysc_when **when;         /**< list of pointers to when statements ([sized array](@ref sizedarrays)) */
     void *priv;                      /** private arbitrary user data, not used by libyang */
+
+    struct lysc_node *data;          /**< first child node (linked list) */
+    struct lysc_must *musts;         /**< list of must restrictions ([sized array](@ref sizedarrays)) */
+};
+
+struct lysc_node_action {
+    uint16_t nodetype;               /**< LYS_RPC or LYS_ACTION */
+    uint16_t flags;                  /**< [schema node flags](@ref snodeflags) */
+    uint8_t hash[LYS_NODE_HASH_COUNT]; /**< schema hash required for LYB printer/parser */
+    struct lys_module *module;       /**< module structure */
+    struct lysc_node *parent;        /**< parent node (NULL in case of top level node - RPC) */
+    struct lysc_node_action *next;   /**< next sibling node (NULL if there is no one) */
+    struct lysc_node_action *prev;   /**< pointer to the previous sibling node \note Note that this pointer is
+                                          never NULL. If there is no sibling node, pointer points to the node
+                                          itself. In case of the first node, this pointer points to the last
+                                          node in the list. */
+    const char *name;                /**< action/RPC name (mandatory) */
+    const char *dsc;                 /**< description */
+    const char *ref;                 /**< reference */
+    struct lysc_ext_instance *exts;  /**< list of the extension instances ([sized array](@ref sizedarrays)) */
+    struct lysc_when **when;         /**< ALWAYS NULL, compatibility member with ::lysc_node */
+    void *priv;                      /** private arbitrary user data, not used by libyang */
+
+    struct lysc_node_action_inout input;  /**< RPC's/action's input */
+    struct lysc_node_action_inout output; /**< RPC's/action's output */
+
+};
+
+struct lysc_node_notif {
+    uint16_t nodetype;               /**< LYS_NOTIF */
+    uint16_t flags;                  /**< [schema node flags](@ref snodeflags) */
+    uint8_t hash[LYS_NODE_HASH_COUNT]; /**< schema hash required for LYB printer/parser */
+    struct lys_module *module;       /**< module structure */
+    struct lysc_node *parent;        /**< parent node (NULL in case of top level node) */
+    struct lysc_node_notif *next;    /**< next sibling node (NULL if there is no one) */
+    struct lysc_node_notif *prev;    /**< pointer to the previous sibling node \note Note that this pointer is
+                                          never NULL. If there is no sibling node, pointer points to the node
+                                          itself. In case of the first node, this pointer points to the last
+                                          node in the list. */
+    const char *name;                /**< Notification name (mandatory) */
+    const char *dsc;                 /**< description */
+    const char *ref;                 /**< reference */
+    struct lysc_ext_instance *exts;  /**< list of the extension instances ([sized array](@ref sizedarrays)) */
+    struct lysc_when **when;         /**< list of pointers to when statements ([sized array](@ref sizedarrays)) */
+    void *priv;                      /** private arbitrary user data, not used by libyang */
+
+    struct lysc_node *data;          /**< first child node (linked list) */
+    struct lysc_must *musts;         /**< list of must restrictions ([sized array](@ref sizedarrays)) */
 };
 
 /**
@@ -1588,8 +1694,8 @@
 
     struct lysc_node *child;         /**< first child node (linked list) */
     struct lysc_must *musts;         /**< list of must restrictions ([sized array](@ref sizedarrays)) */
-    struct lysc_action *actions;     /**< list of actions ([sized array](@ref sizedarrays)) */
-    struct lysc_notif *notifs;       /**< list of notifications ([sized array](@ref sizedarrays)) */
+    struct lysc_node_action *actions;/**< first of actions nodes (linked list) */
+    struct lysc_node_notif *notifs;  /**< first of notifications nodes (linked list) */
 };
 
 struct lysc_node_case {
@@ -1712,10 +1818,10 @@
 
     struct lysc_node *child;         /**< first child node (linked list) */
     struct lysc_must *musts;         /**< list of must restrictions ([sized array](@ref sizedarrays)) */
-    struct lysc_action *actions;     /**< list of actions ([sized array](@ref sizedarrays)) */
-    struct lysc_notif *notifs;       /**< list of notifications ([sized array](@ref sizedarrays)) */
+    struct lysc_node_action *actions;/**< first of actions nodes (linked list) */
+    struct lysc_node_notif *notifs;  /**< first of notifications nodes (linked list) */
 
-    struct lysc_node_leaf ***uniques; /**< list of sized arrays of pointers to the unique nodes ([sized array](@ref sizedarrays)) */
+    struct lysc_node_leaf ***uniques;/**< list of sized arrays of pointers to the unique nodes ([sized array](@ref sizedarrays)) */
     uint32_t min;                    /**< min-elements constraint */
     uint32_t max;                    /**< max-elements constraint */
 };
@@ -1751,8 +1857,8 @@
     struct lys_module *mod;          /**< covering module structure */
 
     struct lysc_node *data;          /**< list of module's top-level data nodes (linked list) */
-    struct lysc_action *rpcs;        /**< list of RPCs ([sized array](@ref sizedarrays)) */
-    struct lysc_notif *notifs;       /**< list of notifications ([sized array](@ref sizedarrays)) */
+    struct lysc_node_action *rpcs;   /**< first of actions nodes (linked list) */
+    struct lysc_node_notif *notifs;  /**< first of notifications nodes (linked list) */
     struct lysc_ext_instance *exts;  /**< list of the extension instances ([sized array](@ref sizedarrays)) */
 };
 
@@ -1796,12 +1902,12 @@
 const struct lysc_when *lysc_has_when(const struct lysc_node *node);
 
 /**
- * @brief Get the groupings sized array of the given (parsed) schema node.
+ * @brief Get the groupings linked list of the given (parsed) schema node.
  * Decides the node's type and in case it has a groupings array, returns it.
  * @param[in] node Node to examine.
- * @return The node's groupings sized array if any, NULL otherwise.
+ * @return The node's groupings linked list if any, NULL otherwise.
  */
-const struct lysp_grp *lysp_node_groupings(const struct lysp_node *node);
+const struct lysp_node_grp *lysp_node_groupings(const struct lysp_node *node);
 
 /**
  * @brief Get the typedefs sized array of the given (parsed) schema node.
@@ -1812,20 +1918,20 @@
 const struct lysp_tpdf *lysp_node_typedefs(const struct lysp_node *node);
 
 /**
- * @brief Get the actions/RPCs sized array of the given (parsed) schema node.
+ * @brief Get the actions/RPCs linked list of the given (parsed) schema node.
  * Decides the node's type and in case it has a actions/RPCs array, returns it.
  * @param[in] node Node to examine.
- * @return The node's actions/RPCs sized array if any, NULL otherwise.
+ * @return The node's actions/RPCs linked list if any, NULL otherwise.
  */
-const struct lysp_action *lysp_node_actions(const struct lysp_node *node);
+const struct lysp_node_action *lysp_node_actions(const struct lysp_node *node);
 
 /**
- * @brief Get the Notifications sized array of the given (parsed) schema node.
+ * @brief Get the Notifications linked list of the given (parsed) schema node.
  * Decides the node's type and in case it has a Notifications array, returns it.
  * @param[in] node Node to examine.
- * @return The node's Notifications sized array if any, NULL otherwise.
+ * @return The node's Notifications linked list if any, NULL otherwise.
  */
-const struct lysp_notif *lysp_node_notifs(const struct lysp_node *node);
+const struct lysp_node_notif *lysp_node_notifs(const struct lysp_node *node);
 
 /**
  * @brief Get the children linked list of the given (parsed) schema node.
@@ -1836,41 +1942,30 @@
 const struct lysp_node *lysp_node_children(const struct lysp_node *node);
 
 /**
- * @brief Get the actions/RPCs sized array of the given (compiled) schema node.
+ * @brief Get the actions/RPCs linked list of the given (compiled) schema node.
  * Decides the node's type and in case it has a actions/RPCs array, returns it.
  * @param[in] node Node to examine.
- * @return The node's actions/RPCs sized array if any, NULL otherwise.
+ * @return The node's actions/RPCs linked list if any, NULL otherwise.
  */
-const struct lysc_action *lysc_node_actions(const struct lysc_node *node);
+const struct lysc_node_action *lysc_node_actions(const struct lysc_node *node);
 
 /**
- * @brief Get the Notifications sized array of the given (compiled) schema node.
+ * @brief Get the Notifications linked list of the given (compiled) schema node.
  * Decides the node's type and in case it has a Notifications array, returns it.
  * @param[in] node Node to examine.
- * @return The node's Notifications sized array if any, NULL otherwise.
+ * @return The node's Notifications linked list if any, NULL otherwise.
  */
-const struct lysc_notif *lysc_node_notifs(const struct lysc_node *node);
+const struct lysc_node_notif *lysc_node_notifs(const struct lysc_node *node);
 
 /**
  * @brief Get the children linked list of the given (compiled) schema node.
- * Skips over input and output nodes. To return them, use ::lysc_node_children_full().
- *
- * @param[in] node Node to examine.
- * @param[in] flags Config flag to distinguish input (LYS_CONFIG_W) and output (LYS_CONFIG_R) data in case of RPC/action node.
- * @return The node's children linked list if any, NULL otherwise.
- */
-const struct lysc_node *lysc_node_children(const struct lysc_node *node, uint16_t flags);
-
-/**
- * @brief Get the children linked list of the given (compiled) schema node.
- * Returns all children node types including input and output. To skip them, use ::lysc_node_children().
  *
  * @param[in] node Node to examine.
  * @param[in] flags Config flag to distinguish input (LYS_CONFIG_W) and output (LYS_CONFIG_R) child in case of RPC/action node.
  * @return Children linked list if any,
  * @return NULL otherwise.
  */
-const struct lysc_node *lysc_node_children_full(const struct lysc_node *node, uint16_t flags);
+const struct lysc_node *lysc_node_children(const struct lysc_node *node, uint16_t flags);
 
 /**
  * @brief Get the parent pointer from any type of (compiled) schema node.
diff --git a/src/tree_schema_free.c b/src/tree_schema_free.c
index 0098040..d19db15 100644
--- a/src/tree_schema_free.c
+++ b/src/tree_schema_free.c
@@ -26,7 +26,7 @@
 #include "xml.h"
 #include "xpath.h"
 
-void lysp_grp_free(struct ly_ctx *ctx, struct lysp_grp *grp);
+void lysp_grp_free(struct ly_ctx *ctx, struct lysp_node_grp *grp);
 void lysc_extension_free(struct ly_ctx *ctx, struct lysc_ext **ext);
 static void lysc_node_free_(struct ly_ctx *ctx, struct lysc_node *node);
 
@@ -205,68 +205,23 @@
 }
 
 void
-lysp_action_inout_free(struct ly_ctx *ctx, struct lysp_action_inout *inout)
+lysp_grp_free(struct ly_ctx *ctx, struct lysp_node_grp *grp)
 {
     struct lysp_node *node, *next;
 
-    FREE_ARRAY(ctx, inout->musts, lysp_restr_free);
-    FREE_ARRAY(ctx, inout->typedefs, lysp_tpdf_free);
-    FREE_ARRAY(ctx, inout->groupings, lysp_grp_free);
-    LY_LIST_FOR_SAFE(inout->data, next, node) {
-        lysp_node_free(ctx, node);
-    }
-    FREE_ARRAY(ctx, inout->exts, lysp_ext_instance_free);
-
-}
-
-void
-lysp_action_free(struct ly_ctx *ctx, struct lysp_action *action)
-{
-    FREE_STRING(ctx, action->name);
-    FREE_STRING(ctx, action->dsc);
-    FREE_STRING(ctx, action->ref);
-    FREE_ARRAY(ctx, action->iffeatures, lysp_qname_free);
-    FREE_ARRAY(ctx, action->typedefs, lysp_tpdf_free);
-    FREE_ARRAY(ctx, action->groupings, lysp_grp_free);
-    lysp_action_inout_free(ctx, &action->input);
-    lysp_action_inout_free(ctx, &action->output);
-    FREE_ARRAY(ctx, action->exts, lysp_ext_instance_free);
-}
-
-void
-lysp_notif_free(struct ly_ctx *ctx, struct lysp_notif *notif)
-{
-    struct lysp_node *node, *next;
-
-    FREE_STRING(ctx, notif->name);
-    FREE_STRING(ctx, notif->dsc);
-    FREE_STRING(ctx, notif->ref);
-    FREE_ARRAY(ctx, notif->iffeatures, lysp_qname_free);
-    FREE_ARRAY(ctx, notif->musts, lysp_restr_free);
-    FREE_ARRAY(ctx, notif->typedefs, lysp_tpdf_free);
-    FREE_ARRAY(ctx, notif->groupings, lysp_grp_free);
-    LY_LIST_FOR_SAFE(notif->data, next, node) {
-        lysp_node_free(ctx, node);
-    }
-    FREE_ARRAY(ctx, notif->exts, lysp_ext_instance_free);
-}
-
-void
-lysp_grp_free(struct ly_ctx *ctx, struct lysp_grp *grp)
-{
-    struct lysp_node *node, *next;
-
-    FREE_STRING(ctx, grp->name);
-    FREE_STRING(ctx, grp->dsc);
-    FREE_STRING(ctx, grp->ref);
     FREE_ARRAY(ctx, grp->typedefs, lysp_tpdf_free);
-    FREE_ARRAY(ctx, grp->groupings, lysp_grp_free);
+    LY_LIST_FOR_SAFE((struct lysp_node *)grp->groupings, next, node) {
+        lysp_node_free(ctx, node);
+    }
     LY_LIST_FOR_SAFE(grp->data, next, node) {
         lysp_node_free(ctx, node);
     }
-    FREE_ARRAY(ctx, grp->actions, lysp_action_free);
-    FREE_ARRAY(ctx, grp->notifs, lysp_notif_free);
-    FREE_ARRAY(ctx, grp->exts, lysp_ext_instance_free);
+    LY_LIST_FOR_SAFE((struct lysp_node *)grp->actions, next, node) {
+        lysp_node_free(ctx, node);
+    }
+    LY_LIST_FOR_SAFE((struct lysp_node *)grp->notifs, next, node) {
+        lysp_node_free(ctx, node);
+    }
 }
 
 void
@@ -279,21 +234,19 @@
 }
 
 void
-lysp_augment_free(struct ly_ctx *ctx, struct lysp_augment *augment)
+lysp_augment_free(struct ly_ctx *ctx, struct lysp_node_augment *augment)
 {
     struct lysp_node *node, *next;
 
-    FREE_STRING(ctx, augment->nodeid);
-    FREE_STRING(ctx, augment->dsc);
-    FREE_STRING(ctx, augment->ref);
-    FREE_MEMBER(ctx, augment->when, lysp_when_free);
-    FREE_ARRAY(ctx, augment->iffeatures, lysp_qname_free);
     LY_LIST_FOR_SAFE(augment->child, next, node) {
         lysp_node_free(ctx, node);
     }
-    FREE_ARRAY(ctx, augment->actions, lysp_action_free);
-    FREE_ARRAY(ctx, augment->notifs, lysp_notif_free);
-    FREE_ARRAY(ctx, augment->exts, lysp_ext_instance_free);
+    LY_LIST_FOR_SAFE((struct lysp_node *)augment->actions, next, node) {
+        lysp_node_free(ctx, node);
+    }
+    LY_LIST_FOR_SAFE((struct lysp_node *)augment->notifs, next, node) {
+        lysp_node_free(ctx, node);
+    }
 }
 
 void
@@ -378,12 +331,18 @@
         FREE_ARRAY(ctx, ((struct lysp_node_container *)node)->musts, lysp_restr_free);
         FREE_STRING(ctx, ((struct lysp_node_container *)node)->presence);
         FREE_ARRAY(ctx, ((struct lysp_node_container *)node)->typedefs, lysp_tpdf_free);
-        FREE_ARRAY(ctx, ((struct lysp_node_container *)node)->groupings, lysp_grp_free);
+        LY_LIST_FOR_SAFE((struct lysp_node *)((struct lysp_node_container *)node)->groupings, next, child) {
+            lysp_node_free(ctx, child);
+        }
         LY_LIST_FOR_SAFE(((struct lysp_node_container *)node)->child, next, child) {
             lysp_node_free(ctx, child);
         }
-        FREE_ARRAY(ctx, ((struct lysp_node_container *)node)->actions, lysp_action_free);
-        FREE_ARRAY(ctx, ((struct lysp_node_container *)node)->notifs, lysp_notif_free);
+        LY_LIST_FOR_SAFE((struct lysp_node *)((struct lysp_node_container *)node)->actions, next, child) {
+            lysp_node_free(ctx, child);
+        }
+        LY_LIST_FOR_SAFE((struct lysp_node *)((struct lysp_node_container *)node)->notifs, next, child) {
+            lysp_node_free(ctx, child);
+        }
         break;
     case LYS_LEAF:
         FREE_ARRAY(ctx, ((struct lysp_node_leaf *)node)->musts, lysp_restr_free);
@@ -401,12 +360,18 @@
         FREE_ARRAY(ctx, ((struct lysp_node_list *)node)->musts, lysp_restr_free);
         FREE_STRING(ctx, ((struct lysp_node_list *)node)->key);
         FREE_ARRAY(ctx, ((struct lysp_node_list *)node)->typedefs, lysp_tpdf_free);
-        FREE_ARRAY(ctx, ((struct lysp_node_list *)node)->groupings,  lysp_grp_free);
+        LY_LIST_FOR_SAFE((struct lysp_node *)((struct lysp_node_list *)node)->groupings, next, child) {
+            lysp_node_free(ctx, child);
+        }
         LY_LIST_FOR_SAFE(((struct lysp_node_list *)node)->child, next, child) {
             lysp_node_free(ctx, child);
         }
-        FREE_ARRAY(ctx, ((struct lysp_node_list *)node)->actions, lysp_action_free);
-        FREE_ARRAY(ctx, ((struct lysp_node_list *)node)->notifs, lysp_notif_free);
+        LY_LIST_FOR_SAFE((struct lysp_node *)((struct lysp_node_list *)node)->actions, next, child) {
+            lysp_node_free(ctx, child);
+        }
+        LY_LIST_FOR_SAFE((struct lysp_node *)((struct lysp_node_list *)node)->notifs, next, child) {
+            lysp_node_free(ctx, child);
+        }
         FREE_ARRAY(ctx, ((struct lysp_node_list *)node)->uniques, lysp_qname_free);
         break;
     case LYS_CHOICE:
@@ -426,7 +391,50 @@
         break;
     case LYS_USES:
         FREE_ARRAY(ctx, ((struct lysp_node_uses *)node)->refines, lysp_refine_free);
-        FREE_ARRAY(ctx, ((struct lysp_node_uses *)node)->augments, lysp_augment_free);
+        LY_LIST_FOR_SAFE((struct lysp_node *)((struct lysp_node_uses *)node)->augments, next, child) {
+            lysp_node_free(ctx, child);
+        }
+        break;
+    case LYS_RPC:
+    case LYS_ACTION:
+        FREE_ARRAY(ctx, ((struct lysp_node_action *)node)->typedefs, lysp_tpdf_free);
+        LY_LIST_FOR_SAFE((struct lysp_node *)((struct lysp_node_action *)node)->groupings, next, child) {
+            lysp_node_free(ctx, child);
+        }
+        if (((struct lysp_node_action *)node)->input.nodetype) {
+            lysp_node_free(ctx, (struct lysp_node *)&((struct lysp_node_action *)node)->input);
+        }
+        if (((struct lysp_node_action *)node)->output.nodetype) {
+            lysp_node_free(ctx, (struct lysp_node *)&((struct lysp_node_action *)node)->output);
+        }
+        break;
+    case LYS_INPUT:
+    case LYS_OUTPUT:
+        FREE_ARRAY(ctx, ((struct lysp_node_action_inout *)node)->musts, lysp_restr_free);
+        FREE_ARRAY(ctx, ((struct lysp_node_action_inout *)node)->typedefs, lysp_tpdf_free);
+        LY_LIST_FOR_SAFE((struct lysp_node *)((struct lysp_node_action_inout *)node)->groupings, next, child) {
+            lysp_node_free(ctx, child);
+        }
+        LY_LIST_FOR_SAFE(((struct lysp_node_action_inout *)node)->data, next, child) {
+            lysp_node_free(ctx, child);
+        }
+        /* do not free the node, it is never standalone but part of the action node */
+        return;
+    case LYS_NOTIF:
+        FREE_ARRAY(ctx, ((struct lysp_node_notif *)node)->musts, lysp_restr_free);
+        FREE_ARRAY(ctx, ((struct lysp_node_notif *)node)->typedefs, lysp_tpdf_free);
+        LY_LIST_FOR_SAFE((struct lysp_node *)((struct lysp_node_notif *)node)->groupings, next, child) {
+            lysp_node_free(ctx, child);
+        }
+        LY_LIST_FOR_SAFE(((struct lysp_node_notif *)node)->data, next, child) {
+            lysp_node_free(ctx, child);
+        }
+        break;
+    case LYS_GROUPING:
+        lysp_grp_free(ctx, (struct lysp_node_grp *)node);
+        break;
+    case LYS_AUGMENT:
+        lysp_augment_free(ctx, (struct lysp_node_augment *)node);
         break;
     default:
         LOGINT(ctx);
@@ -454,13 +462,21 @@
     FREE_ARRAY(ctx, module->features, lysp_feature_free);
     FREE_ARRAY(ctx, module->identities, lysp_ident_free);
     FREE_ARRAY(ctx, module->typedefs, lysp_tpdf_free);
-    FREE_ARRAY(ctx, module->groupings, lysp_grp_free);
+    LY_LIST_FOR_SAFE((struct lysp_node *)module->groupings, next, node) {
+        lysp_node_free(ctx, node);
+    }
     LY_LIST_FOR_SAFE(module->data, next, node) {
         lysp_node_free(ctx, node);
     }
-    FREE_ARRAY(ctx, module->augments, lysp_augment_free);
-    FREE_ARRAY(ctx, module->rpcs, lysp_action_free);
-    FREE_ARRAY(ctx, module->notifs, lysp_notif_free);
+    LY_LIST_FOR_SAFE((struct lysp_node *)module->augments, next, node) {
+        lysp_node_free(ctx, node);
+    }
+    LY_LIST_FOR_SAFE((struct lysp_node *)module->rpcs, next, node) {
+        lysp_node_free(ctx, node);
+    }
+    LY_LIST_FOR_SAFE((struct lysp_node *)module->notifs, next, node) {
+        lysp_node_free(ctx, node);
+    }
     FREE_ARRAY(ctx, module->deviations, lysp_deviation_free);
     FREE_ARRAY(ctx, module->exts, lysp_ext_instance_free);
 
@@ -646,7 +662,7 @@
 }
 
 void
-lysc_action_inout_free(struct ly_ctx *ctx, struct lysc_action_inout *inout)
+lysc_node_action_inout_free(struct ly_ctx *ctx, struct lysc_node_action_inout *inout)
 {
     struct lysc_node *child, *child_next;
 
@@ -657,29 +673,21 @@
 }
 
 void
-lysc_action_free(struct ly_ctx *ctx, struct lysc_action *action)
+lysc_node_action_free(struct ly_ctx *ctx, struct lysc_node_action *action)
 {
-    FREE_STRING(ctx, action->name);
-    FREE_STRING(ctx, action->dsc);
-    FREE_STRING(ctx, action->ref);
-    FREE_ARRAY(ctx, action->exts, lysc_ext_instance_free);
-    FREE_ARRAY(ctx, action->when, lysc_when_free);
-    FREE_ARRAY(ctx, action->input_exts, lysc_ext_instance_free);
-    lysc_action_inout_free(ctx, &action->input);
-    FREE_ARRAY(ctx, action->output_exts, lysc_ext_instance_free);
-    lysc_action_inout_free(ctx, &action->output);
+    if (action->input.nodetype) {
+        lysc_node_free_(ctx, (struct lysc_node *)&action->input);
+    }
+    if (action->output.nodetype) {
+        lysc_node_free_(ctx, (struct lysc_node *)&action->output);
+    }
 }
 
 void
-lysc_notif_free(struct ly_ctx *ctx, struct lysc_notif *notif)
+lysc_node_notif_free(struct ly_ctx *ctx, struct lysc_node_notif *notif)
 {
     struct lysc_node *child, *child_next;
 
-    FREE_STRING(ctx, notif->name);
-    FREE_STRING(ctx, notif->dsc);
-    FREE_STRING(ctx, notif->ref);
-    FREE_ARRAY(ctx, notif->exts, lysc_ext_instance_free);
-    FREE_ARRAY(ctx, notif->when, lysc_when_free);
     FREE_ARRAY(ctx, notif->musts, lysc_must_free);
     LY_LIST_FOR_SAFE(notif->data, child_next, child) {
         lysc_node_free_(ctx, child);
@@ -694,9 +702,13 @@
     LY_LIST_FOR_SAFE(node->child, child_next, child) {
         lysc_node_free_(ctx, child);
     }
+    LY_LIST_FOR_SAFE((struct lysc_node *)node->actions, child_next, child) {
+        lysc_node_free_(ctx, child);
+    }
+    LY_LIST_FOR_SAFE((struct lysc_node *)node->notifs, child_next, child) {
+        lysc_node_free_(ctx, child);
+    }
     FREE_ARRAY(ctx, node->musts, lysc_must_free);
-    FREE_ARRAY(ctx, node->actions, lysc_action_free);
-    FREE_ARRAY(ctx, node->notifs, lysc_notif_free);
 }
 
 static void
@@ -748,8 +760,12 @@
     }
     LY_ARRAY_FREE(node->uniques);
 
-    FREE_ARRAY(ctx, node->actions, lysc_action_free);
-    FREE_ARRAY(ctx, node->notifs, lysc_notif_free);
+    LY_LIST_FOR_SAFE((struct lysc_node *)node->actions, child_next, child) {
+        lysc_node_free_(ctx, child);
+    }
+    LY_LIST_FOR_SAFE((struct lysc_node *)node->notifs, child_next, child) {
+        lysc_node_free_(ctx, child);
+    }
 }
 
 static void
@@ -781,6 +797,8 @@
 static void
 lysc_node_free_(struct ly_ctx *ctx, struct lysc_node *node)
 {
+    ly_bool inout = 0;
+
     /* common part */
     FREE_STRING(ctx, node->name);
     FREE_STRING(ctx, node->dsc);
@@ -810,13 +828,28 @@
     case LYS_ANYXML:
         lysc_node_anydata_free(ctx, (struct lysc_node_anydata *)node);
         break;
+    case LYS_RPC:
+    case LYS_ACTION:
+        lysc_node_action_free(ctx, (struct lysc_node_action *)node);
+        break;
+    case LYS_INPUT:
+    case LYS_OUTPUT:
+        lysc_node_action_inout_free(ctx, (struct lysc_node_action_inout *)node);
+        inout = 1;
+        break;
+    case LYS_NOTIF:
+        lysc_node_notif_free(ctx, (struct lysc_node_notif *)node);
+        break;
     default:
         LOGINT(ctx);
     }
 
     FREE_ARRAY(ctx, node->when, lysc_when_free);
     FREE_ARRAY(ctx, node->exts, lysc_ext_instance_free);
-    free(node);
+
+    if (!inout) {
+        free(node);
+    }
 }
 
 void
@@ -824,6 +857,11 @@
 {
     struct lysc_node *iter, **child_p;
 
+    if (node->nodetype & (LYS_INPUT | LYS_OUTPUT)) {
+        /* nothing to do - inouts are part of actions and cannot be unlinked/freed separately */
+        return;
+    }
+
     if (unlink) {
         /* unlink from siblings */
         if (node->prev->next) {
@@ -834,8 +872,18 @@
         } else {
             /* unlinking the last node */
             if (node->parent) {
-                iter = (struct lysc_node *)lysc_node_children(node->parent, node->flags & LYS_CONFIG_MASK);
+                if (node->nodetype == LYS_ACTION) {
+                    iter = (struct lysc_node *)lysc_node_actions(node->parent);
+                } else if (node->nodetype == LYS_NOTIF) {
+                    iter = (struct lysc_node *)lysc_node_notifs(node->parent);
+                } else {
+                    iter = (struct lysc_node *)lysc_node_children(node->parent, node->flags & LYS_CONFIG_MASK);
+                }
                 LY_CHECK_ERR_RET(!iter, LOGINT(ctx), );
+            } else if (node->nodetype == LYS_RPC) {
+                iter = (struct lysc_node *)node->module->compiled->rpcs;
+            } else if (node->nodetype == LYS_NOTIF) {
+                iter = (struct lysc_node *)node->module->compiled->notifs;
             } else {
                 iter = node->module->compiled->data;
             }
@@ -845,7 +893,17 @@
 
         /* unlink from parent */
         if (node->parent) {
-            child_p = lysc_node_children_p(node->parent, node->flags & LYS_CONFIG_MASK);
+            if (node->nodetype == LYS_ACTION) {
+                child_p = (struct lysc_node **)lysc_node_actions_p(node->parent);
+            } else if (node->nodetype == LYS_NOTIF) {
+                child_p = (struct lysc_node **)lysc_node_notifs_p(node->parent);
+            } else {
+                child_p = lysc_node_children_p(node->parent, node->flags & LYS_CONFIG_MASK);
+            }
+        } else if (node->nodetype == LYS_RPC) {
+            child_p = (struct lysc_node **)&node->module->compiled->rpcs;
+        } else if (node->nodetype == LYS_NOTIF) {
+            child_p = (struct lysc_node **)&node->module->compiled->notifs;
         } else {
             child_p = &node->module->compiled->data;
         }
@@ -870,8 +928,12 @@
     LY_LIST_FOR_SAFE(module->data, node_next, node) {
         lysc_node_free_(ctx, node);
     }
-    FREE_ARRAY(ctx, module->rpcs, lysc_action_free);
-    FREE_ARRAY(ctx, module->notifs, lysc_notif_free);
+    LY_LIST_FOR_SAFE((struct lysc_node *)module->rpcs, node_next, node) {
+        lysc_node_free_(ctx, node);
+    }
+    LY_LIST_FOR_SAFE((struct lysc_node *)module->notifs, node_next, node) {
+        lysc_node_free_(ctx, node);
+    }
     FREE_ARRAY(ctx, module->exts, lysc_ext_instance_free);
 
     free(module);
diff --git a/src/tree_schema_helpers.c b/src/tree_schema_helpers.c
index 7ecf7d7..592bccb 100644
--- a/src/tree_schema_helpers.c
+++ b/src/tree_schema_helpers.c
@@ -394,97 +394,6 @@
 }
 
 LY_ERR
-lysp_parse_finalize_reallocated(struct lys_parser_ctx *ctx, struct lysp_grp *groupings, struct lysp_augment *augments,
-        struct lysp_action *actions, struct lysp_notif *notifs)
-{
-    LY_ARRAY_COUNT_TYPE u, v;
-    struct lysp_node *child;
-
-    /* finalize parent pointers to the reallocated items */
-
-    /* gropings */
-    LY_ARRAY_FOR(groupings, u) {
-        LY_LIST_FOR(groupings[u].data, child) {
-            child->parent = (struct lysp_node *)&groupings[u];
-        }
-        LY_ARRAY_FOR(groupings[u].actions, v) {
-            groupings[u].actions[v].parent = (struct lysp_node *)&groupings[u];
-        }
-        LY_ARRAY_FOR(groupings[u].notifs, v) {
-            groupings[u].notifs[v].parent = (struct lysp_node *)&groupings[u];
-        }
-        LY_ARRAY_FOR(groupings[u].groupings, v) {
-            groupings[u].groupings[v].parent = (struct lysp_node *)&groupings[u];
-        }
-        if (groupings[u].typedefs) {
-            LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, &groupings[u], 0, NULL));
-        }
-    }
-
-    /* augments */
-    LY_ARRAY_FOR(augments, u) {
-        LY_LIST_FOR(augments[u].child, child) {
-            child->parent = (struct lysp_node *)&augments[u];
-        }
-        LY_ARRAY_FOR(augments[u].actions, v) {
-            augments[u].actions[v].parent = (struct lysp_node *)&augments[u];
-        }
-        LY_ARRAY_FOR(augments[u].notifs, v) {
-            augments[u].notifs[v].parent = (struct lysp_node *)&augments[u];
-        }
-    }
-
-    /* actions */
-    LY_ARRAY_FOR(actions, u) {
-        if (actions[u].input.parent) {
-            actions[u].input.parent = (struct lysp_node *)&actions[u];
-            LY_LIST_FOR(actions[u].input.data, child) {
-                child->parent = (struct lysp_node *)&actions[u].input;
-            }
-            LY_ARRAY_FOR(actions[u].input.groupings, v) {
-                actions[u].input.groupings[v].parent = (struct lysp_node *)&actions[u].input;
-            }
-            if (actions[u].input.typedefs) {
-                LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, &actions[u].input, 0, NULL));
-            }
-        }
-        if (actions[u].output.parent) {
-            actions[u].output.parent = (struct lysp_node *)&actions[u];
-            LY_LIST_FOR(actions[u].output.data, child) {
-                child->parent = (struct lysp_node *)&actions[u].output;
-            }
-            LY_ARRAY_FOR(actions[u].output.groupings, v) {
-                actions[u].output.groupings[v].parent = (struct lysp_node *)&actions[u].output;
-            }
-            if (actions[u].output.typedefs) {
-                LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, &actions[u].output, 0, NULL));
-            }
-        }
-        LY_ARRAY_FOR(actions[u].groupings, v) {
-            actions[u].groupings[v].parent = (struct lysp_node *)&actions[u];
-        }
-        if (actions[u].typedefs) {
-            LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, &actions[u], 0, NULL));
-        }
-    }
-
-    /* notifications */
-    LY_ARRAY_FOR(notifs, u) {
-        LY_LIST_FOR(notifs[u].data, child) {
-            child->parent = (struct lysp_node *)&notifs[u];
-        }
-        LY_ARRAY_FOR(notifs[u].groupings, v) {
-            notifs[u].groupings[v].parent = (struct lysp_node *)&notifs[u];
-        }
-        if (notifs[u].typedefs) {
-            LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, &notifs[u], 0, NULL));
-        }
-    }
-
-    return LY_SUCCESS;
-}
-
-LY_ERR
 lysp_check_dup_typedefs(struct lys_parser_ctx *ctx, struct lysp_module *mod)
 {
     struct hash_table *ids_global;
@@ -1122,13 +1031,13 @@
         switch (node->nodetype) {
         case LYS_RPC:
         case LYS_ACTION:
-            if (((struct lysc_action *)node)->when) {
-                return *((struct lysc_action *)node)->when;
+            if (((struct lysc_node_action *)node)->when) {
+                return *((struct lysc_node_action *)node)->when;
             }
             break;
         case LYS_NOTIF:
-            if (((struct lysc_notif *)node)->when) {
-                return *((struct lysc_notif *)node)->when;
+            if (((struct lysc_node_notif *)node)->when) {
+                return *((struct lysc_node_notif *)node)->when;
             }
             break;
         default:
@@ -1233,21 +1142,21 @@
     case LYS_LIST:
         return ((struct lysp_node_list *)node)->typedefs;
     case LYS_GROUPING:
-        return ((struct lysp_grp *)node)->typedefs;
+        return ((struct lysp_node_grp *)node)->typedefs;
     case LYS_RPC:
     case LYS_ACTION:
-        return ((struct lysp_action *)node)->typedefs;
+        return ((struct lysp_node_action *)node)->typedefs;
     case LYS_INPUT:
     case LYS_OUTPUT:
-        return ((struct lysp_action_inout *)node)->typedefs;
+        return ((struct lysp_node_action_inout *)node)->typedefs;
     case LYS_NOTIF:
-        return ((struct lysp_notif *)node)->typedefs;
+        return ((struct lysp_node_notif *)node)->typedefs;
     default:
         return NULL;
     }
 }
 
-API const struct lysp_grp *
+API const struct lysp_node_grp *
 lysp_node_groupings(const struct lysp_node *node)
 {
     switch (node->nodetype) {
@@ -1256,21 +1165,21 @@
     case LYS_LIST:
         return ((struct lysp_node_list *)node)->groupings;
     case LYS_GROUPING:
-        return ((struct lysp_grp *)node)->groupings;
+        return ((struct lysp_node_grp *)node)->groupings;
     case LYS_RPC:
     case LYS_ACTION:
-        return ((struct lysp_action *)node)->groupings;
+        return ((struct lysp_node_action *)node)->groupings;
     case LYS_INPUT:
     case LYS_OUTPUT:
-        return ((struct lysp_action_inout *)node)->groupings;
+        return ((struct lysp_node_action_inout *)node)->groupings;
     case LYS_NOTIF:
-        return ((struct lysp_notif *)node)->groupings;
+        return ((struct lysp_node_notif *)node)->groupings;
     default:
         return NULL;
     }
 }
 
-struct lysp_action **
+struct lysp_node_action **
 lysp_node_actions_p(struct lysp_node *node)
 {
     assert(node);
@@ -1281,18 +1190,18 @@
     case LYS_LIST:
         return &((struct lysp_node_list *)node)->actions;
     case LYS_GROUPING:
-        return &((struct lysp_grp *)node)->actions;
+        return &((struct lysp_node_grp *)node)->actions;
     case LYS_AUGMENT:
-        return &((struct lysp_augment *)node)->actions;
+        return &((struct lysp_node_augment *)node)->actions;
     default:
         return NULL;
     }
 }
 
-API const struct lysp_action *
+API const struct lysp_node_action *
 lysp_node_actions(const struct lysp_node *node)
 {
-    struct lysp_action **actions;
+    struct lysp_node_action **actions;
 
     actions = lysp_node_actions_p((struct lysp_node *)node);
     if (actions) {
@@ -1302,7 +1211,7 @@
     }
 }
 
-struct lysp_notif **
+struct lysp_node_notif **
 lysp_node_notifs_p(struct lysp_node *node)
 {
     assert(node);
@@ -1312,18 +1221,18 @@
     case LYS_LIST:
         return &((struct lysp_node_list *)node)->notifs;
     case LYS_GROUPING:
-        return &((struct lysp_grp *)node)->notifs;
+        return &((struct lysp_node_grp *)node)->notifs;
     case LYS_AUGMENT:
-        return &((struct lysp_augment *)node)->notifs;
+        return &((struct lysp_node_augment *)node)->notifs;
     default:
         return NULL;
     }
 }
 
-API const struct lysp_notif *
+API const struct lysp_node_notif *
 lysp_node_notifs(const struct lysp_node *node)
 {
-    struct lysp_notif **notifs;
+    struct lysp_node_notif **notifs;
 
     notifs = lysp_node_notifs_p((struct lysp_node *)node);
     if (notifs) {
@@ -1347,14 +1256,14 @@
     case LYS_CASE:
         return &((struct lysp_node_case *)node)->child;
     case LYS_GROUPING:
-        return &((struct lysp_grp *)node)->data;
+        return &((struct lysp_node_grp *)node)->data;
     case LYS_AUGMENT:
-        return &((struct lysp_augment *)node)->child;
+        return &((struct lysp_node_augment *)node)->child;
     case LYS_INPUT:
     case LYS_OUTPUT:
-        return &((struct lysp_action_inout *)node)->data;
+        return &((struct lysp_node_action_inout *)node)->data;
     case LYS_NOTIF:
-        return &((struct lysp_notif *)node)->data;
+        return &((struct lysp_node_notif *)node)->data;
     default:
         return NULL;
     }
@@ -1377,7 +1286,7 @@
     }
 }
 
-struct lysc_action **
+struct lysc_node_action **
 lysc_node_actions_p(struct lysc_node *node)
 {
     assert(node);
@@ -1391,10 +1300,10 @@
     }
 }
 
-API const struct lysc_action *
+API const struct lysc_node_action *
 lysc_node_actions(const struct lysc_node *node)
 {
-    struct lysc_action **actions;
+    struct lysc_node_action **actions;
 
     actions = lysc_node_actions_p((struct lysc_node *)node);
     if (actions) {
@@ -1404,7 +1313,7 @@
     }
 }
 
-struct lysc_notif **
+struct lysc_node_notif **
 lysc_node_notifs_p(struct lysc_node *node)
 {
     assert(node);
@@ -1418,10 +1327,10 @@
     }
 }
 
-API const struct lysc_notif *
+API const struct lysc_node_notif *
 lysc_node_notifs(const struct lysc_node *node)
 {
-    struct lysc_notif **notifs;
+    struct lysc_node_notif **notifs;
 
     notifs = lysc_node_notifs_p((struct lysc_node *)node);
     if (notifs) {
@@ -1447,16 +1356,16 @@
     case LYS_RPC:
     case LYS_ACTION:
         if (flags & LYS_CONFIG_R) {
-            return &((struct lysc_action *)node)->output.data;
+            return &((struct lysc_node_action *)node)->output.data;
         } else {
             /* LYS_CONFIG_W, but also the default case */
-            return &((struct lysc_action *)node)->input.data;
+            return &((struct lysc_node_action *)node)->input.data;
         }
     case LYS_INPUT:
     case LYS_OUTPUT:
-        return &((struct lysc_action_inout *)node)->data;
+        return &((struct lysc_node_action_inout *)node)->data;
     case LYS_NOTIF:
-        return &((struct lysc_notif *)node)->data;
+        return &((struct lysc_node_notif *)node)->data;
     default:
         return NULL;
     }
@@ -1471,30 +1380,20 @@
         return NULL;
     }
 
-    children = lysc_node_children_p(node, flags);
-    if (children) {
-        return *children;
-    } else {
-        return NULL;
-    }
-}
-
-API const struct lysc_node *
-lysc_node_children_full(const struct lysc_node *node, uint16_t flags)
-{
-    if (!node) {
-        return NULL;
-    }
-
-    if (node->nodetype == LYS_RPC || node->nodetype == LYS_ACTION) {
+    if ((node->nodetype == LYS_RPC) || (node->nodetype == LYS_ACTION)) {
         if (flags & LYS_CONFIG_R) {
-            return (struct lysc_node *)&((struct lysc_action *)node)->output;
+            return (struct lysc_node *)&((struct lysc_node_action *)node)->output;
         } else {
             /* LYS_CONFIG_W, but also the default case */
-            return (struct lysc_node *)&((struct lysc_action *)node)->input;
+            return (struct lysc_node *)&((struct lysc_node_action *)node)->input;
         }
     } else {
-        return lysc_node_children(node, flags);
+        children = lysc_node_children_p(node, flags);
+        if (children) {
+            return *children;
+        } else {
+            return NULL;
+        }
     }
 }
 
@@ -1504,14 +1403,14 @@
     if (!node) {
         return NULL;
     } else if (node->nodetype == LYS_INPUT) {
-        return (struct lysc_node *)(((char *)node) - offsetof(struct lysc_action, input));
+        return (struct lysc_node *)(((char *)node) - offsetof(struct lysc_node_action, input));
     } else if (node->nodetype == LYS_OUTPUT) {
-        return (struct lysc_node *)(((char *)node) - offsetof(struct lysc_action, output));
+        return (struct lysc_node *)(((char *)node) - offsetof(struct lysc_node_action, output));
     } else if (node->parent && (node->parent->nodetype & (LYS_RPC | LYS_ACTION))) {
         if (node->flags & LYS_CONFIG_W) {
-            return (struct lysc_node *)&((struct lysc_action *)node->parent)->input;
+            return (struct lysc_node *)&((struct lysc_node_action *)node->parent)->input;
         } else {
-            return (struct lysc_node *)&((struct lysc_action *)node->parent)->output;
+            return (struct lysc_node *)&((struct lysc_node_action *)node->parent)->output;
         }
     } else {
         return node->parent;
diff --git a/src/tree_schema_internal.h b/src/tree_schema_internal.h
index 7fccb76..558c010 100644
--- a/src/tree_schema_internal.h
+++ b/src/tree_schema_internal.h
@@ -236,18 +236,6 @@
 LY_ERR lysp_check_dup_identities(struct lys_parser_ctx *ctx, struct lysp_module *mod);
 
 /**
- * @brief Finalize some of the structures in case they are stored in sized array,
- * which can be possibly reallocated and some other data may point to them.
- *
- * Update parent pointers in the nodes inside grouping/augment/RPC/Notification, which could be reallocated.
- *
- * @param[in] mod Parsed module to be updated.
- * @return LY_ERR value (currently only LY_SUCCESS, but it can change in future).
- */
-LY_ERR lysp_parse_finalize_reallocated(struct lys_parser_ctx *ctx, struct lysp_grp *groupings, struct lysp_augment *augments,
-        struct lysp_action *actions, struct lysp_notif *notifs);
-
-/**
  * @brief Just move the newest revision into the first position, does not sort the rest
  * @param[in] revs Sized-array of the revisions in a printable schema tree.
  */
@@ -332,37 +320,13 @@
 void lysp_node_free(struct ly_ctx *ctx, struct lysp_node *node);
 
 /**
- * @brief Free a parsed input/output node.
- *
- * @param[in] ctx libyang context.
- * @param[in] inout Input/output to free.
- */
-void lysp_action_inout_free(struct ly_ctx *ctx, struct lysp_action_inout *inout);
-
-/**
- * @brief Free a parsed action node.
- *
- * @param[in] ctx libyang context.
- * @param[in] action Action to free.
- */
-void lysp_action_free(struct ly_ctx *ctx, struct lysp_action *action);
-
-/**
- * @brief Free a parsed notification node.
- *
- * @param[in] ctx libyang context.
- * @param[in] notif Notification to free.
- */
-void lysp_notif_free(struct ly_ctx *ctx, struct lysp_notif *notif);
-
-/**
  * @brief Get address of a node's actions list if any.
  *
  * Decides the node's type and in case it has an actions list, returns its address.
  * @param[in] node Node to check.
  * @return Address of the node's actions member if any, NULL otherwise.
  */
-struct lysp_action **lysp_node_actions_p(struct lysp_node *node);
+struct lysp_node_action **lysp_node_actions_p(struct lysp_node *node);
 
 /**
  * @brief Get address of a node's notifications list if any.
@@ -371,7 +335,7 @@
  * @param[in] node Node to check.
  * @return Address of the node's notifs member if any, NULL otherwise.
  */
-struct lysp_notif **lysp_node_notifs_p(struct lysp_node *node);
+struct lysp_node_notif **lysp_node_notifs_p(struct lysp_node *node);
 
 /**
  * @brief Get address of a node's child pointer if any.
@@ -399,7 +363,7 @@
  * @param[in] node Node to check.
  * @return Address of the node's notifs member if any, NULL otherwise.
  */
-struct lysc_notif **lysc_node_notifs_p(struct lysc_node *node);
+struct lysc_node_notif **lysc_node_notifs_p(struct lysc_node *node);
 
 /**
  * @brief Get address of a node's actions pointer if any.
@@ -408,7 +372,7 @@
  * @param[in] node Node to check.
  * @return Address of the node's actions member if any, NULL otherwise.
  */
-struct lysc_action **lysc_node_actions_p(struct lysc_node *node);
+struct lysc_node_action **lysc_node_actions_p(struct lysc_node *node);
 
 /**
  * @brief Iterate over the specified type of the extension instances
@@ -618,7 +582,7 @@
  * @param[in,out] inout Compiled inout structure to be cleaned.
  * Since the structure is part of the RPC/action structure, it is not freed itself.
  */
-void lysc_action_inout_free(struct ly_ctx *ctx, struct lysc_action_inout *inout);
+void lysc_node_action_inout_free(struct ly_ctx *ctx, struct lysc_node_action_inout *inout);
 
 /**
  * @brief Free the data inside compiled RPC/action structure.
@@ -626,7 +590,7 @@
  * @param[in,out] action Compiled action structure to be cleaned.
  * Since the structure is typically part of the sized array, the structure itself is not freed.
  */
-void lysc_action_free(struct ly_ctx *ctx, struct lysc_action *action);
+void lysc_node_action_free(struct ly_ctx *ctx, struct lysc_node_action *action);
 
 /**
  * @brief Free the items inside the compiled Notification structure.
@@ -634,7 +598,7 @@
  * @param[in,out] action Compiled Notification structure to be cleaned.
  * Since the structure is typically part of the sized array, the structure itself is not freed.
  */
-void lysc_notif_free(struct ly_ctx *ctx, struct lysc_notif *notif);
+void lysc_node_notif_free(struct ly_ctx *ctx, struct lysc_node_notif *notif);
 
 /**
  * @brief Free the compiled extension instance structure.
diff --git a/src/validation.c b/src/validation.c
index e4c51dd..5c8ebf9 100644
--- a/src/validation.c
+++ b/src/validation.c
@@ -1178,14 +1178,14 @@
         musts = ((struct lysc_node_anydata *)node->schema)->musts;
         break;
     case LYS_NOTIF:
-        musts = ((struct lysc_notif *)node->schema)->musts;
+        musts = ((struct lysc_node_notif *)node->schema)->musts;
         break;
     case LYS_RPC:
     case LYS_ACTION:
         if (op == LYD_VALIDATE_OP_RPC) {
-            musts = ((struct lysc_action *)node->schema)->input.musts;
+            musts = ((struct lysc_node_action *)node->schema)->input.musts;
         } else if (op == LYD_VALIDATE_OP_REPLY) {
-            musts = ((struct lysc_action *)node->schema)->output.musts;
+            musts = ((struct lysc_node_action *)node->schema)->output.musts;
         } else {
             LOGINT(LYD_CTX(node));
             return LY_EINT;
diff --git a/tests/utests/data/test_parser_json.c b/tests/utests/data/test_parser_json.c
index aa11927..b71e9b8 100644
--- a/tests/utests/data/test_parser_json.c
+++ b/tests/utests/data/test_parser_json.c
@@ -441,12 +441,12 @@
 
     assert_non_null(op);
 
-    CHECK_LYSC_ACTION((struct lysc_action *)op->schema, dsc, 0, LYS_STATUS_CURR,
+    CHECK_LYSC_ACTION((struct lysc_node_action *)op->schema, dsc, 0, LYS_STATUS_CURR,
             1, 0, 0, 1, "edit-config", LYS_RPC,
             0, 0, 0, 0, 0, ref, 0);
 
     node = tree;
-    CHECK_LYSC_ACTION((struct lysc_action *)node->schema, dsc, 0, LYS_STATUS_CURR,
+    CHECK_LYSC_ACTION((struct lysc_node_action *)node->schema, dsc, 0, LYS_STATUS_CURR,
             1, 0, 0, 1, "edit-config", LYS_RPC,
             0, 0, 0, 0, 0, ref, 0);
     node = lyd_child(node)->next;
@@ -483,7 +483,7 @@
     ly_in_free(in, 0);
 
     assert_non_null(op);
-    CHECK_LYSC_ACTION((struct lysc_action *)op->schema, NULL, 0, LYS_STATUS_CURR,
+    CHECK_LYSC_ACTION((struct lysc_node_action *)op->schema, NULL, 0, LYS_STATUS_CURR,
             1, 0, 0, 1, "act", LYS_ACTION,
             1, 0, 0, 1, 0, NULL, 0);
 
@@ -507,7 +507,7 @@
     ly_in_free(in, 0);
 
     assert_non_null(ntf);
-    CHECK_LYSC_NOTIF((struct lysc_notif *)ntf->schema, 1, NULL, 0, 0x4, 1, 0, "n1", 1, 0, NULL, 0);
+    CHECK_LYSC_NOTIF((struct lysc_node_notif *)ntf->schema, 1, NULL, 0, 0x4, 1, 0, "n1", 1, 0, NULL, 0);
 
     CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR, 1, "c", 1, LYS_CONTAINER, 0, 0, NULL, 0);
 
@@ -520,7 +520,7 @@
     ly_in_free(in, 0);
 
     assert_non_null(ntf);
-    CHECK_LYSC_NOTIF((struct lysc_notif *)ntf->schema, 0, NULL, 0, 0x4, 1, 0, "n2", 0, 0, NULL, 0);
+    CHECK_LYSC_NOTIF((struct lysc_node_notif *)ntf->schema, 0, NULL, 0, 0x4, 1, 0, "n2", 0, 0, NULL, 0);
 
     assert_non_null(tree);
     assert_ptr_equal(ntf, tree);
@@ -546,7 +546,7 @@
     ly_in_free(in, 0);
 
     assert_non_null(op);
-    CHECK_LYSC_ACTION((struct lysc_action *)op->schema, NULL, 0, LYS_STATUS_CURR,
+    CHECK_LYSC_ACTION((struct lysc_node_action *)op->schema, NULL, 0, LYS_STATUS_CURR,
             1, 0, 0, 1, "act", LYS_ACTION,
             1, 0, 0, 1, 0, NULL, 0);
     node = lyd_child(op);
diff --git a/tests/utests/data/test_parser_xml.c b/tests/utests/data/test_parser_xml.c
index a74bc7a..d2cbca4 100644
--- a/tests/utests/data/test_parser_xml.c
+++ b/tests/utests/data/test_parser_xml.c
@@ -326,14 +326,14 @@
 
     assert_non_null(op);
 
-    CHECK_LYSC_ACTION((struct lysc_action *)op->schema, dsc, 0, LYS_STATUS_CURR,
+    CHECK_LYSC_ACTION((struct lysc_node_action *)op->schema, dsc, 0, LYS_STATUS_CURR,
             1, 0, 0, 1, "edit-config", LYS_RPC,
             0, 0, 0, 0, 0, ref, 0);
 
     assert_non_null(tree);
 
     node = tree;
-    CHECK_LYSC_ACTION((struct lysc_action *)node->schema, dsc, 0, LYS_STATUS_CURR,
+    CHECK_LYSC_ACTION((struct lysc_node_action *)node->schema, dsc, 0, LYS_STATUS_CURR,
             1, 0, 0, 1, "edit-config", LYS_RPC,
             0, 0, 0, 0, 0, ref, 0);
     node = lyd_child(node)->next;
@@ -391,7 +391,7 @@
     ly_in_free(in, 0);
 
     assert_non_null(op);
-    CHECK_LYSC_ACTION((struct lysc_action *)op->schema, NULL, 0, LYS_STATUS_CURR,
+    CHECK_LYSC_ACTION((struct lysc_node_action *)op->schema, NULL, 0, LYS_STATUS_CURR,
             1, 0, 0, 1, "act", LYS_ACTION,
             1, 0, 0, 1, 0, NULL, 0);
 
@@ -425,7 +425,7 @@
     ly_in_free(in, 0);
 
     assert_non_null(ntf);
-    CHECK_LYSC_NOTIF((struct lysc_notif *)ntf->schema, 1, NULL, 0, 0x4, 1, 0, "n1", 1, 0, NULL, 0);
+    CHECK_LYSC_NOTIF((struct lysc_node_notif *)ntf->schema, 1, NULL, 0, 0x4, 1, 0, "n1", 1, 0, NULL, 0);
 
     CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR, 1, "c", 1, LYS_CONTAINER, 0, 0, NULL, 0);
 
@@ -439,7 +439,7 @@
     ly_in_free(in, 0);
 
     assert_non_null(ntf);
-    CHECK_LYSC_NOTIF((struct lysc_notif *)ntf->schema, 0, NULL, 0, 0x4, 1, 0, "n2", 0, 0, NULL, 0);
+    CHECK_LYSC_NOTIF((struct lysc_node_notif *)ntf->schema, 0, NULL, 0, 0x4, 1, 0, "n2", 0, 0, NULL, 0);
 
     assert_non_null(tree);
     assert_ptr_equal(ntf, tree);
@@ -470,7 +470,7 @@
 
     assert_non_null(op);
 
-    CHECK_LYSC_ACTION((struct lysc_action *)op->schema, NULL, 0, LYS_STATUS_CURR,
+    CHECK_LYSC_ACTION((struct lysc_node_action *)op->schema, NULL, 0, LYS_STATUS_CURR,
             1, 0, 0, 1, "act", LYS_ACTION,
             1, 0, 0, 1, 0, NULL, 0);
     node = lyd_child(op);
diff --git a/tests/utests/data/test_validation.c b/tests/utests/data/test_validation.c
index df6404c..c06c474 100644
--- a/tests/utests/data/test_validation.c
+++ b/tests/utests/data/test_validation.c
@@ -1087,7 +1087,7 @@
     /* missing leafref */
     assert_int_equal(LY_EVALID, lyd_validate_op(op_tree, NULL, LYD_VALIDATE_OP_RPC, NULL));
     CHECK_LOG_CTX("Invalid leafref value \"target\" - no existing target instance \"/lf3\".",
-            "Schema location /j:cont/l1/act/lf2, data location /j:cont/l1[k='val1']/act/lf2.");
+            "Schema location /j:cont/l1/act/input/lf2, data location /j:cont/l1[k='val1']/act/lf2.");
     ly_in_free(in, 0);
 
     CHECK_PARSE_LYD_PARAM("<cont xmlns=\"urn:tests:j\">\n"
@@ -1139,7 +1139,7 @@
     /* missing leafref */
     assert_int_equal(LY_EVALID, lyd_validate_op(op_tree, NULL, LYD_VALIDATE_OP_REPLY, NULL));
     CHECK_LOG_CTX("Invalid leafref value \"target\" - no existing target instance \"/lf4\".",
-            "Schema location /j:cont/l1/act/lf2, data location /j:cont/l1[k='val1']/act/lf2.");
+            "Schema location /j:cont/l1/act/output/lf2, data location /j:cont/l1[k='val1']/act/lf2.");
 
     CHECK_PARSE_LYD_PARAM("<cont xmlns=\"urn:tests:j\">\n"
             "  <lf1>not true</lf1>\n"
diff --git a/tests/utests/schema/test_parser_yang.c b/tests/utests/schema/test_parser_yang.c
index 66dba0d..1aa43e3 100644
--- a/tests/utests/schema/test_parser_yang.c
+++ b/tests/utests/schema/test_parser_yang.c
@@ -27,10 +27,8 @@
 /* originally static functions from tree_schema_free.c and parser_yang.c */
 void lysp_ext_instance_free(struct ly_ctx *ctx, struct lysp_ext_instance *ext);
 void lysp_deviation_free(struct ly_ctx *ctx, struct lysp_deviation *dev);
-void lysp_grp_free(struct ly_ctx *ctx, struct lysp_grp *grp);
-void lysp_action_free(struct ly_ctx *ctx, struct lysp_action *action);
-void lysp_notif_free(struct ly_ctx *ctx, struct lysp_notif *notif);
-void lysp_augment_free(struct ly_ctx *ctx, struct lysp_augment *augment);
+void lysp_grp_free(struct ly_ctx *ctx, struct lysp_node_grp *grp);
+void lysp_augment_free(struct ly_ctx *ctx, struct lysp_node_augment *augment);
 void lysp_deviate_free(struct ly_ctx *ctx, struct lysp_deviate *d);
 void lysp_node_free(struct ly_ctx *ctx, struct lysp_node *node);
 void lysp_when_free(struct ly_ctx *ctx, struct lysp_when *when);
@@ -43,14 +41,14 @@
         uint16_t *flags, char **word_p, char **word_b, size_t *word_len);
 LY_ERR skip_comment(struct lys_yang_parser_ctx *ctx, uint8_t comment);
 
-LY_ERR parse_action(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_action **actions);
+LY_ERR parse_action(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_node_action **actions);
 LY_ERR parse_any(struct lys_yang_parser_ctx *ctx, enum ly_stmt kw, struct lysp_node *parent, struct lysp_node **siblings);
-LY_ERR parse_augment(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_augment **augments);
+LY_ERR parse_augment(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_node_augment **augments);
 LY_ERR parse_case(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_node **siblings);
 LY_ERR parse_container(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_node **siblings);
 LY_ERR parse_deviate(struct lys_yang_parser_ctx *ctx, struct lysp_deviate **deviates);
 LY_ERR parse_deviation(struct lys_yang_parser_ctx *ctx, struct lysp_deviation **deviations);
-LY_ERR parse_grouping(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_grp **groupings);
+LY_ERR parse_grouping(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_node_grp **groupings);
 LY_ERR parse_choice(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_node **siblings);
 LY_ERR parse_leaf(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_node **siblings);
 LY_ERR parse_leaflist(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_node **siblings);
@@ -58,7 +56,7 @@
 LY_ERR parse_maxelements(struct lys_yang_parser_ctx *ctx, uint32_t *max, uint16_t *flags, struct lysp_ext_instance **exts);
 LY_ERR parse_minelements(struct lys_yang_parser_ctx *ctx, uint32_t *min, uint16_t *flags, struct lysp_ext_instance **exts);
 LY_ERR parse_module(struct lys_yang_parser_ctx *ctx, struct lysp_module *mod);
-LY_ERR parse_notif(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_notif **notifs);
+LY_ERR parse_notif(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_node_notif **notifs);
 LY_ERR parse_submodule(struct lys_yang_parser_ctx *ctx, struct lysp_submodule *submod);
 LY_ERR parse_uses(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_node **siblings);
 LY_ERR parse_when(struct lys_yang_parser_ctx *ctx, struct lysp_when **when_p);
@@ -1291,7 +1289,7 @@
 static void
 test_grouping(void **state)
 {
-    struct lysp_grp *grp = NULL;
+    struct lysp_node_grp *grp = NULL;
 
     YCTX->parsed_mod->version = 2; /* simulate YANG 1.1 */
 
@@ -1300,7 +1298,7 @@
     in.current = "l {" MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \
     assert_int_equal(LY_EVALID, parse_grouping(YCTX, NULL, &grp)); \
     CHECK_LOG_CTX("Duplicate keyword \""MEMBER"\".", "Line number 1."); \
-    FREE_ARRAY(YCTX->parsed_mod->mod->ctx, grp, lysp_grp_free); grp = NULL;
+    lysp_node_free(YCTX->parsed_mod->mod->ctx, &grp->node); grp = NULL;
 
     TEST_DUP("description", "text1", "text2");
     TEST_DUP("reference", "1", "2");
@@ -1320,24 +1318,27 @@
     assert_null(grp->parent);
     assert_int_equal(LYS_STATUS_CURR, grp->flags);
     ly_set_erase(&YCTX->tpdfs_nodes, NULL);
-    FREE_ARRAY(YCTX->parsed_mod->mod->ctx, grp, lysp_grp_free); grp = NULL;
+    lysp_node_free(YCTX->parsed_mod->mod->ctx, &grp->node);
+    grp = NULL;
 
     /* invalid content */
     in.current = "grp {config true} ...";
     assert_int_equal(LY_EVALID, parse_grouping(YCTX, NULL, &grp));
     CHECK_LOG_CTX("Invalid keyword \"config\" as a child of \"grouping\".", "Line number 1.");
-    FREE_ARRAY(YCTX->parsed_mod->mod->ctx, grp, lysp_grp_free); grp = NULL;
+    lysp_node_free(YCTX->parsed_mod->mod->ctx, &grp->node);
+    grp = NULL;
 
     in.current = "grp {must 'expr'} ...";
     assert_int_equal(LY_EVALID, parse_grouping(YCTX, NULL, &grp));
     CHECK_LOG_CTX("Invalid keyword \"must\" as a child of \"grouping\".", "Line number 1.");
-    FREE_ARRAY(YCTX->parsed_mod->mod->ctx, grp, lysp_grp_free); grp = NULL;
+    lysp_node_free(YCTX->parsed_mod->mod->ctx, &grp->node);
+    grp = NULL;
 }
 
 static void
 test_action(void **state)
 {
-    struct lysp_action *rpcs = NULL;
+    struct lysp_node_action *rpcs = NULL;
     struct lysp_node_container *c = NULL;
 
     YCTX->parsed_mod->version = 2; /* simulate YANG 1.1 */
@@ -1347,7 +1348,7 @@
     in.current = "func {" MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \
     assert_int_equal(LY_EVALID, parse_action(YCTX, NULL, &rpcs)); \
     CHECK_LOG_CTX("Duplicate keyword \""MEMBER"\".", "Line number 1."); \
-    FREE_ARRAY(YCTX->parsed_mod->mod->ctx, rpcs, lysp_action_free); rpcs = NULL;
+    lysp_node_free(YCTX->parsed_mod->mod->ctx, (struct lysp_node*)rpcs); rpcs = NULL;
 
     TEST_DUP("description", "text1", "text2");
     TEST_DUP("input", "{leaf l1 {type empty;}} description a", "{leaf l2 {type empty;}} description a");
@@ -1391,13 +1392,13 @@
     assert_non_null(rpcs->output.data);
 
     ly_set_erase(&YCTX->tpdfs_nodes, NULL);
-    FREE_ARRAY(YCTX->parsed_mod->mod->ctx, rpcs, lysp_action_free); rpcs = NULL;
+    lysp_node_free(YCTX->parsed_mod->mod->ctx, (struct lysp_node *)rpcs); rpcs = NULL;
 
     /* invalid content */
     in.current = "func {config true} ...";
     assert_int_equal(LY_EVALID, parse_action(YCTX, NULL, &rpcs));
     CHECK_LOG_CTX("Invalid keyword \"config\" as a child of \"rpc\".", "Line number 1.");
-    FREE_ARRAY(YCTX->parsed_mod->mod->ctx, rpcs, lysp_action_free); rpcs = NULL;
+    lysp_node_free(YCTX->parsed_mod->mod->ctx, (struct lysp_node *)rpcs); rpcs = NULL;
 
     lysp_node_free(YCTX->parsed_mod->mod->ctx, (struct lysp_node *)c);
 }
@@ -1405,7 +1406,7 @@
 static void
 test_notification(void **state)
 {
-    struct lysp_notif *notifs = NULL;
+    struct lysp_node_notif *notifs = NULL;
     struct lysp_node_container *c = NULL;
 
     YCTX->parsed_mod->version = 2; /* simulate YANG 1.1 */
@@ -1415,7 +1416,7 @@
     in.current = "func {" MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \
     assert_int_equal(LY_EVALID, parse_notif(YCTX, NULL, &notifs)); \
     CHECK_LOG_CTX("Duplicate keyword \""MEMBER"\".", "Line number 1."); \
-    FREE_ARRAY(YCTX->parsed_mod->mod->ctx, notifs, lysp_notif_free); notifs = NULL;
+    lysp_node_free(YCTX->parsed_mod->mod->ctx, (struct lysp_node*)notifs); notifs = NULL;
 
     TEST_DUP("description", "text1", "text2");
     TEST_DUP("reference", "1", "2");
@@ -1442,13 +1443,13 @@
     assert_int_equal(LYS_STATUS_CURR, notifs->flags);
 
     ly_set_erase(&YCTX->tpdfs_nodes, NULL);
-    FREE_ARRAY(YCTX->parsed_mod->mod->ctx, notifs, lysp_notif_free); notifs = NULL;
+    lysp_node_free(YCTX->parsed_mod->mod->ctx, (struct lysp_node *)notifs); notifs = NULL;
 
     /* invalid content */
     in.current = "ntf {config true} ...";
     assert_int_equal(LY_EVALID, parse_notif(YCTX, NULL, &notifs));
     CHECK_LOG_CTX("Invalid keyword \"config\" as a child of \"notification\".", "Line number 1.");
-    FREE_ARRAY(YCTX->parsed_mod->mod->ctx, notifs, lysp_notif_free); notifs = NULL;
+    lysp_node_free(YCTX->parsed_mod->mod->ctx, (struct lysp_node *)notifs); notifs = NULL;
 
     lysp_node_free(YCTX->parsed_mod->mod->ctx, (struct lysp_node *)c);
 }
@@ -1485,7 +1486,7 @@
 static void
 test_augment(void **state)
 {
-    struct lysp_augment *a = NULL;
+    struct lysp_node_augment *a = NULL;
 
     YCTX->parsed_mod->version = 2; /* simulate YANG 1.1 */
 
@@ -1494,7 +1495,7 @@
     in.current = "l {" MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \
     assert_int_equal(LY_EVALID, parse_augment(YCTX, NULL, &a)); \
     CHECK_LOG_CTX("Duplicate keyword \""MEMBER"\".", "Line number 1."); \
-    FREE_ARRAY(YCTX->parsed_mod->mod->ctx, a, lysp_augment_free); a = NULL;
+    lysp_node_free(YCTX->parsed_mod->mod->ctx, (struct lysp_node *)a); a = NULL;
 
     TEST_DUP("description", "text1", "text2");
     TEST_DUP("reference", "1", "2");
@@ -1516,7 +1517,7 @@
     assert_non_null(a->when);
     assert_null(a->parent);
     assert_int_equal(LYS_STATUS_CURR, a->flags);
-    FREE_ARRAY(YCTX->parsed_mod->mod->ctx, a, lysp_augment_free); a = NULL;
+    lysp_node_free(YCTX->parsed_mod->mod->ctx, (struct lysp_node *)a); a = NULL;
 }
 
 static void
diff --git a/tests/utests/schema/test_parser_yin.c b/tests/utests/schema/test_parser_yin.c
index 5adcf3a..8fa9914 100644
--- a/tests/utests/schema/test_parser_yin.c
+++ b/tests/utests/schema/test_parser_yin.c
@@ -70,7 +70,7 @@
 
 struct inout_meta {
     struct lysp_node *parent;          /**< Parent node. */
-    struct lysp_action_inout *inout_p; /**< inout_p Input/output pointer to write to. */
+    struct lysp_node_action_inout *inout_p; /**< inout_p Input/output pointer to write to. */
 };
 
 struct minmax_dev_meta {
@@ -110,11 +110,8 @@
 void lysp_include_free(struct ly_ctx *ctx, struct lysp_include *include);
 void lysp_feature_free(struct ly_ctx *ctx, struct lysp_feature *feat);
 void lysp_ident_free(struct ly_ctx *ctx, struct lysp_ident *ident);
-void lysp_notif_free(struct ly_ctx *ctx, struct lysp_notif *notif);
-void lysp_grp_free(struct ly_ctx *ctx, struct lysp_grp *grp);
-void lysp_action_inout_free(struct ly_ctx *ctx, struct lysp_action_inout *inout);
-void lysp_action_free(struct ly_ctx *ctx, struct lysp_action *action);
-void lysp_augment_free(struct ly_ctx *ctx, struct lysp_augment *augment);
+void lysp_grp_free(struct ly_ctx *ctx, struct lysp_node_grp *grp);
+void lysp_augment_free(struct ly_ctx *ctx, struct lysp_node_augment *augment);
 void lysp_deviate_free(struct ly_ctx *ctx, struct lysp_deviate *d);
 void lysp_deviation_free(struct ly_ctx *ctx, struct lysp_deviation *dev);
 void lysp_import_free(struct ly_ctx *ctx, struct lysp_import *import);
@@ -2603,7 +2600,7 @@
 test_notification_elem(void **state)
 {
     const char *data;
-    struct lysp_notif *notifs = NULL;
+    struct lysp_node_notif *notifs = NULL;
     struct tree_node_meta notif_meta = {NULL, (struct lysp_node **)&notifs};
 
     /* max subelems */
@@ -2657,14 +2654,14 @@
     assert_string_equal(notifs->ref, "ref");
     assert_string_equal(notifs->typedefs->name, "tpdf");
     TEST_1_CHECK_LYSP_EXT_INSTANCE(&(notifs->exts[0]),  LYEXT_SUBSTMT_SELF);
-    FREE_ARRAY(UTEST_LYCTX, notifs, lysp_notif_free);
+    lysp_node_free(UTEST_LYCTX, (struct lysp_node *)notifs);
     notifs = NULL;
 
     /* min subelems */
     data = ELEMENT_WRAPPER_START "<notification name=\"notif-name\" />" ELEMENT_WRAPPER_END;
     assert_int_equal(test_element_helper(state, data, &notif_meta, NULL, NULL), LY_SUCCESS);
     assert_string_equal(notifs->name, "notif-name");
-    FREE_ARRAY(UTEST_LYCTX, notifs, lysp_notif_free);
+    lysp_node_free(UTEST_LYCTX, (struct lysp_node *)notifs);
     notifs = NULL;
 }
 
@@ -2672,7 +2669,7 @@
 test_grouping_elem(void **state)
 {
     const char *data;
-    struct lysp_grp *grps = NULL;
+    struct lysp_node_grp *grps = NULL;
     struct tree_node_meta grp_meta = {NULL, (struct lysp_node **)&grps};
 
     /* max subelems */
@@ -2719,14 +2716,14 @@
     assert_string_equal(grps->data->next->next->next->next->next->next->next->name, "choice");
     assert_int_equal(grps->data->next->next->next->next->next->next->next->nodetype, LYS_CHOICE);
     TEST_1_CHECK_LYSP_EXT_INSTANCE(&(grps->exts[0]),  LYEXT_SUBSTMT_SELF);
-    FREE_ARRAY(UTEST_LYCTX, grps, lysp_grp_free);
+    lysp_node_free(UTEST_LYCTX, &grps->node);
     grps = NULL;
 
     /* min subelems */
     data = ELEMENT_WRAPPER_START "<grouping name=\"grp-name\" />" ELEMENT_WRAPPER_END;
     assert_int_equal(test_element_helper(state, data, &grp_meta, NULL, NULL), LY_SUCCESS);
     assert_string_equal(grps->name, "grp-name");
-    FREE_ARRAY(UTEST_LYCTX, grps, lysp_grp_free);
+    lysp_node_free(UTEST_LYCTX, &grps->node);
     grps = NULL;
 }
 
@@ -2954,7 +2951,7 @@
 test_inout_elem(void **state)
 {
     const char *data;
-    struct lysp_action_inout inout = {};
+    struct lysp_node_action_inout inout = {};
     struct inout_meta inout_meta = {NULL, &inout};
 
     /* max subelements */
@@ -2998,7 +2995,7 @@
     assert_int_equal(inout.data->next->next->next->next->next->next->next->nodetype, LYS_USES);
     assert_null(inout.data->next->next->next->next->next->next->next->next);
     TEST_1_CHECK_LYSP_EXT_INSTANCE(&(inout.exts[0]),  LYEXT_SUBSTMT_SELF);
-    lysp_action_inout_free(UTEST_LYCTX, &inout);
+    lysp_node_free(UTEST_LYCTX, (struct lysp_node *)&inout);
     memset(&inout, 0, sizeof inout);
 
     /* max subelements */
@@ -3042,18 +3039,18 @@
     assert_int_equal(inout.data->next->next->next->next->next->next->next->nodetype, LYS_USES);
     assert_null(inout.data->next->next->next->next->next->next->next->next);
     TEST_1_CHECK_LYSP_EXT_INSTANCE(&(inout.exts[0]),  LYEXT_SUBSTMT_SELF);
-    lysp_action_inout_free(UTEST_LYCTX, &inout);
+    lysp_node_free(UTEST_LYCTX, (struct lysp_node *)&inout);
     memset(&inout, 0, sizeof inout);
 
     /* min subelems */
     data = ELEMENT_WRAPPER_START "<input><leaf name=\"l\"><type name=\"empty\"/></leaf></input>" ELEMENT_WRAPPER_END;
     assert_int_equal(test_element_helper(state, data, &inout_meta, NULL, NULL), LY_SUCCESS);
-    lysp_action_inout_free(UTEST_LYCTX, &inout);
+    lysp_node_free(UTEST_LYCTX, (struct lysp_node *)&inout);
     memset(&inout, 0, sizeof inout);
 
     data = ELEMENT_WRAPPER_START "<output><leaf name=\"l\"><type name=\"empty\"/></leaf></output>" ELEMENT_WRAPPER_END;
     assert_int_equal(test_element_helper(state, data, &inout_meta, NULL, NULL), LY_SUCCESS);
-    lysp_action_inout_free(UTEST_LYCTX, &inout);
+    lysp_node_free(UTEST_LYCTX, (struct lysp_node *)&inout);
     memset(&inout, 0, sizeof inout);
 
     /* invalid combinations */
@@ -3067,7 +3064,7 @@
 test_action_elem(void **state)
 {
     const char *data;
-    struct lysp_action *actions = NULL;
+    struct lysp_node_action *actions = NULL;
     struct tree_node_meta act_meta = {NULL, (struct lysp_node **)&actions};
     uint16_t flags;
 
@@ -3105,7 +3102,7 @@
     assert_string_equal(actions->output.musts->arg.str, "cond");
     assert_string_equal(actions->input.data->name, "uses-name");
     TEST_1_CHECK_LYSP_EXT_INSTANCE(&(actions->exts[0]),  LYEXT_SUBSTMT_SELF);
-    FREE_ARRAY(UTEST_LYCTX, actions, lysp_action_free)
+    lysp_node_free(UTEST_LYCTX, (struct lysp_node *)actions);
     actions = NULL;
 
     YCTX->parsed_mod->version = LYS_VERSION_1_1;
@@ -3138,14 +3135,14 @@
     assert_string_equal(actions->input.data->name, "uses-name");
     assert_string_equal(actions->output.musts->arg.str, "cond");
     TEST_1_CHECK_LYSP_EXT_INSTANCE(&(actions->exts[0]),  LYEXT_SUBSTMT_SELF);
-    FREE_ARRAY(UTEST_LYCTX, actions, lysp_action_free)
+    lysp_node_free(UTEST_LYCTX, (struct lysp_node *)actions);
     actions = NULL;
 
     /* min subelems */
     data = ELEMENT_WRAPPER_START "<action name=\"act\" />" ELEMENT_WRAPPER_END;
     assert_int_equal(test_element_helper(state, data, &act_meta, NULL, NULL), LY_SUCCESS);
     assert_string_equal(actions->name, "act");
-    FREE_ARRAY(UTEST_LYCTX, actions, lysp_action_free)
+    lysp_node_free(UTEST_LYCTX, (struct lysp_node *)actions);
     actions = NULL;
 }
 
@@ -3153,7 +3150,7 @@
 test_augment_elem(void **state)
 {
     const char *data;
-    struct lysp_augment *augments = NULL;
+    struct lysp_node_augment *augments = NULL;
     struct tree_node_meta aug_meta = {NULL, (struct lysp_node **)&augments};
 
     YCTX->parsed_mod->version = LYS_VERSION_1_1;
@@ -3209,13 +3206,13 @@
     assert_string_equal(augments->actions->name, "action");
     assert_string_equal(augments->notifs->name, "notif");
     TEST_1_CHECK_LYSP_EXT_INSTANCE(&(augments->exts[0]),  LYEXT_SUBSTMT_SELF);
-    FREE_ARRAY(UTEST_LYCTX, augments, lysp_augment_free)
+    lysp_node_free(YCTX->parsed_mod->mod->ctx, (struct lysp_node *)augments);
     augments = NULL;
 
     data = ELEMENT_WRAPPER_START "<augment target-node=\"target\" />" ELEMENT_WRAPPER_END;
     assert_int_equal(test_element_helper(state, data, &aug_meta, NULL, NULL), LY_SUCCESS);
     assert_string_equal(augments->nodeid, "target");
-    FREE_ARRAY(UTEST_LYCTX, augments, lysp_augment_free)
+    lysp_node_free(YCTX->parsed_mod->mod->ctx, (struct lysp_node *)augments);
     augments = NULL;
 }
 
diff --git a/tests/utests/schema/test_schema_common.c b/tests/utests/schema/test_schema_common.c
index 8d9e42e..6885e0c 100644
--- a/tests/utests/schema/test_schema_common.c
+++ b/tests/utests/schema/test_schema_common.c
@@ -480,7 +480,7 @@
             "    }\n"
             "}";
     assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
-    CHECK_LOG_CTX("Not found node \"l\" in path.", "Schema location /h:rp/l2.");
+    CHECK_LOG_CTX("Not found node \"l\" in path.", "Schema location /h:rp/input/l2.");
 
     /* rpc input -> rpc output must */
     str = "module h {\n"
@@ -501,7 +501,7 @@
             "    }\n"
             "}";
     assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_SUCCESS);
-    CHECK_LOG_CTX("Schema node \"l\" not found (\"../l\") with context node \"/h:rp/l2\".", NULL);
+    CHECK_LOG_CTX("Schema node \"l\" not found (\"../l\") with context node \"/h:rp/input/l2\".", NULL);
 
     /* rpc input -> notif leafref */
     str = "module i {\n"
@@ -523,7 +523,7 @@
             "    }\n"
             "}";
     assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
-    CHECK_LOG_CTX("Not found node \"notif\" in path.", "Schema location /i:rp/l2.");
+    CHECK_LOG_CTX("Not found node \"notif\" in path.", "Schema location /i:rp/input/l2.");
 
     /* rpc input -> notif must */
     str = "module i {\n"
@@ -544,7 +544,7 @@
             "    }\n"
             "}";
     assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_SUCCESS);
-    CHECK_LOG_CTX("Schema node \"l\" not found (\"/notif/l\") with context node \"/i:rp/l2\".", NULL);
+    CHECK_LOG_CTX("Schema node \"l\" not found (\"/notif/l\") with context node \"/i:rp/input/l2\".", NULL);
 
     /* action output -> state */
     str = "module j {\n"
@@ -606,7 +606,7 @@
             "    }\n"
             "}";
     assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
-    CHECK_LOG_CTX("Not found node \"l\" in path.", "Schema location /k:cont/ll/act/l2.");
+    CHECK_LOG_CTX("Not found node \"l\" in path.", "Schema location /k:cont/ll/act/output/l2.");
 
     /* action output -> action input must */
     str = "module k {\n"
@@ -636,7 +636,7 @@
             "    }\n"
             "}";
     assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_SUCCESS);
-    CHECK_LOG_CTX("Schema node \"l\" not found (\"/cont/ll/act/l\") with context node \"/k:cont/ll/act/l2\".", NULL);
+    CHECK_LOG_CTX("Schema node \"l\" not found (\"/cont/ll/act/l\") with context node \"/k:cont/ll/act/output/l2\".", NULL);
 }
 
 struct module_clb_list {
diff --git a/tests/utests/schema/test_tree_schema_compile.c b/tests/utests/schema/test_tree_schema_compile.c
index 58b2526..aa3ebc0 100644
--- a/tests/utests/schema/test_tree_schema_compile.c
+++ b/tests/utests/schema/test_tree_schema_compile.c
@@ -546,13 +546,13 @@
 test_action(void **state)
 {
     const struct lys_module *mod;
-    const struct lysc_action *rpc;
+    const struct lysc_node_action *rpc;
 
     assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module a {namespace urn:a;prefix a;"
             "rpc a {input {leaf x {type int8;} leaf y {type int8;}} output {leaf result {type int16;}}}}", LYS_IN_YANG, &mod));
     rpc = mod->compiled->rpcs;
     assert_non_null(rpc);
-    assert_int_equal(1, LY_ARRAY_COUNT(rpc));
+    assert_null(rpc->next);
     assert_int_equal(LYS_RPC, rpc->nodetype);
     assert_int_equal(LYS_STATUS_CURR, rpc->flags);
     assert_string_equal("a", rpc->name);
@@ -563,7 +563,7 @@
             "augment /top/b/output {leaf result2 {type string;}}}", LYS_IN_YANG, &mod));
     rpc = lysc_node_actions(mod->compiled->data);
     assert_non_null(rpc);
-    assert_int_equal(1, LY_ARRAY_COUNT(rpc));
+    assert_null(rpc->next);
     assert_int_equal(LYS_ACTION, rpc->nodetype);
     assert_int_equal(LYS_STATUS_CURR, rpc->flags);
     assert_string_equal("b", rpc->name);
@@ -603,38 +603,42 @@
 test_notification(void **state)
 {
     const struct lys_module *mod;
-    const struct lysc_notif *notif;
+    const struct lysc_node_notif *notif;
 
     assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module a {namespace urn:a;prefix a;"
             "notification a1 {leaf x {type int8;}} notification a2;}", LYS_IN_YANG, &mod));
     notif = mod->compiled->notifs;
     assert_non_null(notif);
-    assert_int_equal(2, LY_ARRAY_COUNT(notif));
+    assert_non_null(notif->next);
+    assert_null(notif->next->next);
     assert_int_equal(LYS_NOTIF, notif->nodetype);
     assert_int_equal(LYS_STATUS_CURR, notif->flags);
     assert_string_equal("a1", notif->name);
     assert_non_null(notif->data);
     assert_string_equal("x", notif->data->name);
-    assert_int_equal(LYS_NOTIF, notif[1].nodetype);
-    assert_int_equal(LYS_STATUS_CURR, notif[1].flags);
-    assert_string_equal("a2", notif[1].name);
-    assert_null(notif[1].data);
+    notif = notif->next;
+    assert_int_equal(LYS_NOTIF, notif->nodetype);
+    assert_int_equal(LYS_STATUS_CURR, notif->flags);
+    assert_string_equal("a2", notif->name);
+    assert_null(notif->data);
 
     assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module b {yang-version 1.1; namespace urn:b;prefix b; container top {"
             "notification b1 {leaf x {type int8;}} notification b2 {must \"/top\";}}}", LYS_IN_YANG, &mod));
     notif = lysc_node_notifs(mod->compiled->data);
     assert_non_null(notif);
-    assert_int_equal(2, LY_ARRAY_COUNT(notif));
+    assert_non_null(notif->next);
+    assert_null(notif->next->next);
     assert_int_equal(LYS_NOTIF, notif->nodetype);
     assert_int_equal(LYS_STATUS_CURR, notif->flags);
     assert_string_equal("b1", notif->name);
     assert_non_null(notif->data);
     assert_string_equal("x", notif->data->name);
-    assert_int_equal(LYS_NOTIF, notif[1].nodetype);
-    assert_int_equal(LYS_STATUS_CURR, notif[1].flags);
-    assert_string_equal("b2", notif[1].name);
-    assert_null(notif[1].data);
-    assert_int_equal(1, LY_ARRAY_COUNT(notif[1].musts));
+    notif = notif->next;
+    assert_int_equal(LYS_NOTIF, notif->nodetype);
+    assert_int_equal(LYS_STATUS_CURR, notif->flags);
+    assert_string_equal("b2", notif->name);
+    assert_null(notif->data);
+    assert_int_equal(1, LY_ARRAY_COUNT(notif->musts));
 
     /* invalid */
     assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa;container top {notification x;}}",
@@ -2088,20 +2092,22 @@
     assert_non_null(mod->compiled->data);
     cont = (const struct lysc_node_container *)mod->compiled->data;
     assert_non_null(cont->actions);
-    assert_int_equal(2, LY_ARRAY_COUNT(cont->actions));
-    assert_string_equal("e", cont->actions[1].name);
-    assert_string_equal("g", cont->actions[0].name);
-    assert_string_equal("ultra g", cont->actions[0].dsc);
+    assert_non_null(cont->actions->next);
+    assert_null(cont->actions->next->next);
+    assert_string_equal("e", cont->actions->next->name);
+    assert_string_equal("g", cont->actions->name);
+    assert_string_equal("ultra g", cont->actions->dsc);
 
     assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module f {yang-version 1.1;namespace urn:f;prefix f; grouping grp {notification g { description \"super g\";}}"
             "container top {notification f; uses grp {refine g {description \"ultra g\";}}}}", LYS_IN_YANG, &mod));
     assert_non_null(mod->compiled->data);
     cont = (const struct lysc_node_container *)mod->compiled->data;
     assert_non_null(cont->notifs);
-    assert_int_equal(2, LY_ARRAY_COUNT(cont->notifs));
-    assert_string_equal("f", cont->notifs[1].name);
-    assert_string_equal("g", cont->notifs[0].name);
-    assert_string_equal("ultra g", cont->notifs[0].dsc);
+    assert_non_null(cont->notifs->next);
+    assert_null(cont->notifs->next->next);
+    assert_string_equal("f", cont->notifs->next->name);
+    assert_string_equal("g", cont->notifs->name);
+    assert_string_equal("ultra g", cont->notifs->dsc);
 
     /* empty grouping */
     assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module g {namespace urn:g;prefix g; grouping grp; uses grp;}", LYS_IN_YANG, &mod));
@@ -2348,8 +2354,7 @@
     const struct lysc_node_choice *ch;
     const struct lysc_node_case *c;
     const struct lysc_node_container *cont;
-    const struct lysc_action *rpc;
-    const struct lysc_notif *notif;
+    const struct lysc_node_action *rpc;
 
     ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, "module a {namespace urn:a;prefix a; typedef atype {type string;}"
             "container top {leaf a {type string;}}}");
@@ -2444,7 +2449,7 @@
             "augment /hi:func/hi:output {leaf y {type string;}}}", LYS_IN_YANG, NULL));
     assert_non_null(mod = ly_ctx_get_module_implemented(UTEST_LYCTX, "himp"));
     assert_non_null(rpc = mod->compiled->rpcs);
-    assert_int_equal(1, LY_ARRAY_COUNT(rpc));
+    assert_null(rpc->next);
     assert_non_null(rpc->input.data);
     assert_string_equal("x", rpc->input.data->name);
     assert_null(rpc->input.data->next);
@@ -2457,8 +2462,8 @@
             "augment /root {uses grp;}}", LYS_IN_YANG, &mod));
     assert_non_null(cont = (const struct lysc_node_container *)mod->compiled->data);
     assert_null(cont->child);
-    assert_non_null(notif = cont->notifs);
-    assert_int_equal(1, LY_ARRAY_COUNT(notif));
+    assert_non_null(cont->notifs);
+    assert_null(cont->notifs->next);
 
     assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa; container c {leaf a {type string;}}"
             "augment /x/ {leaf a {type int8;}}}", LYS_IN_YANG, &mod));
@@ -2538,9 +2543,10 @@
     assert_non_null(((struct lysc_node_choice *)node)->dflt);
     assert_non_null(((struct lysc_node_choice *)node)->cases);
     assert_null(((struct lysc_node_choice *)node)->cases->next);
-    assert_int_equal(1, LY_ARRAY_COUNT(mod->compiled->rpcs));
-    assert_null(mod->compiled->rpcs[0].input.data);
-    assert_null(mod->compiled->rpcs[0].output.data);
+    assert_non_null(mod->compiled->rpcs);
+    assert_null(mod->compiled->rpcs->next);
+    assert_null(mod->compiled->rpcs->input.data);
+    assert_null(mod->compiled->rpcs->output.data);
 
     assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module c {namespace urn:c;prefix c; typedef mytype {type string; units kilometers;}"
             "leaf c1 {type mytype;} leaf c2 {type mytype; units meters;} leaf c3 {type mytype; units meters;}"
diff --git a/tests/utests/utests.h b/tests/utests/utests.h
index 873e224..b1637b5 100644
--- a/tests/utests/utests.h
+++ b/tests/utests/utests.h
@@ -220,7 +220,7 @@
     assert_non_null(NODE); \
     CHECK_POINTER((NODE)->data, DATA); \
     CHECK_ARRAY((NODE)->exts, EXTS); \
-    CHECK_ARRAY((NODE)->groupings, GROUPINGS); \
+    CHECK_POINTER((NODE)->groupings, GROUPINGS); \
     CHECK_ARRAY((NODE)->musts, MUSTS); \
     assert_int_equal((NODE)->nodetype, NODETYPE); \
     CHECK_POINTER((NODE)->parent, PARENT); \
@@ -253,7 +253,7 @@
     CHECK_STRING((NODE)->dsc, DSC); \
     CHECK_ARRAY((NODE)->exts, EXTS); \
     assert_int_equal((NODE)->flags, FLAGS); \
-    CHECK_ARRAY((NODE)->groupings, GROUPINGS); \
+    CHECK_POINTER((NODE)->groupings, GROUPINGS); \
     CHECK_ARRAY((NODE)->iffeatures, IFFEATURES); \
     CHECK_LYSP_ACTION_INOUT(&((NODE)->input), INPUT_DATA, INPUT_EXTS, INPUT_GROUPINGS, \
                 INPUT_MUSTS, LYS_INPUT, INPUT_PARENT, INPUT_TYPEDEFS); \
@@ -515,12 +515,12 @@
     CHECK_ARRAY((NODE)->exts, EXTS); \
     assert_int_equal((NODE)->flags, FLAGS); \
     CHECK_LYSC_ACTION_INOUT(&(NODE)->input, INPUT_DATA, INPUT_MUST, LYS_INPUT); \
-    CHECK_ARRAY((NODE)->input_exts, INPUT_EXTS); \
+    CHECK_ARRAY((NODE)->input.exts, INPUT_EXTS); \
     CHECK_POINTER((NODE)->module, MODULE); \
     assert_string_equal((NODE)->name, NAME); \
     assert_int_equal((NODE)->nodetype, NODETYPE); \
     CHECK_LYSC_ACTION_INOUT(&(NODE)->output, OUTPUT_DATA, OUTPUT_MUST, LYS_OUTPUT); \
-    CHECK_ARRAY((NODE)->output_exts, OUTPUT_EXTS); \
+    CHECK_ARRAY((NODE)->output.exts, OUTPUT_EXTS); \
     CHECK_POINTER((NODE)->parent, PARENT); \
     CHECK_POINTER((NODE)->priv, PRIV); \
     CHECK_STRING((NODE)->ref, REF); \