Merge branch 'master' into devel
diff --git a/src/common.c b/src/common.c
index 49e8b2b..395c41a 100644
--- a/src/common.c
+++ b/src/common.c
@@ -254,6 +254,8 @@
         return "rpc";
     case LYS_USES:
         return "uses";
+    case LYS_ACTION:
+        return "action";
     }
 
     return NULL;
diff --git a/src/common.h b/src/common.h
index 51cb24e..1a53b19 100644
--- a/src/common.h
+++ b/src/common.h
@@ -91,7 +91,7 @@
 /*
  * logger
  */
-extern volatile uint8_t ly_log_level;
+extern volatile int8_t ly_log_level;
 
 void ly_log(LY_LOG_LEVEL level, const char *format, ...);
 
@@ -137,6 +137,7 @@
     LYE_EOF,
     LYE_INSTMT,
     LYE_INCHILDSTMT,
+    LYE_INPAR,
     LYE_INID,
     LYE_INDATE,
     LYE_INARG,
@@ -166,6 +167,7 @@
     LYE_CIRC_LEAFREFS,
     LYE_CIRC_IMPORTS,
     LYE_CIRC_INCLUDES,
+    LYE_INVER,
 
     LYE_OBSDATA,
     LYE_OBSTYPE,
@@ -190,6 +192,7 @@
     LYE_NOREQINS,
     LYE_NOLEAFREF,
     LYE_NOMANDCHOICE,
+    LYE_INACT,
 
     LYE_XPATH_INTOK,
     LYE_XPATH_EOF,
diff --git a/src/libyang.h b/src/libyang.h
index e0c7ace..e96fc06 100644
--- a/src/libyang.h
+++ b/src/libyang.h
@@ -1082,11 +1082,11 @@
  * @brief Verbosity levels of the libyang logger.
  */
 typedef enum {
-    LY_LLSILENT,   /**< Print no messages. */
-    LY_LLERR,      /**< Print only error messages, default value. */
-    LY_LLWRN,      /**< Print error and warning messages. */
-    LY_LLVRB,      /**< Besides errors and warnings, print some other verbose messages. */
-    LY_LLDBG       /**< Print all messages including some development debug messages. */
+    LY_LLSILENT = -1, /**< Print no messages. */
+    LY_LLERR = 0,     /**< Print only error messages, default value. */
+    LY_LLWRN,         /**< Print error and warning messages. */
+    LY_LLVRB,         /**< Besides errors and warnings, print some other verbose messages. */
+    LY_LLDBG          /**< Print all messages including some development debug messages. */
 } LY_LOG_LEVEL;
 
 /**
@@ -1147,6 +1147,7 @@
     LYVE_EOF,          /**< unexpected end of input data */
     LYVE_INSTMT,       /**< invalid statement (schema) */
     /* */
+    LYVE_INPAR,        /**< invalid (in)direct parent (schema) */
     LYVE_INID,         /**< invalid identifier (schema) */
     LYVE_INDATE,       /**< invalid date format */
     LYVE_INARG,        /**< invalid value of a statement argument (schema) */
@@ -1176,6 +1177,7 @@
     LYVE_CIRC_LEAFREFS,/**< circular chain of leafrefs detected (schema) */
     LYVE_CIRC_IMPORTS, /**< circular chain of imports detected (schema) */
     LYVE_CIRC_INCLUDES,/**< circular chain of includes detected (schema) */
+    LYVE_INVER,        /**< non-matching YANG versions of module and its submodules (schema) */
 
     LYVE_OBSDATA,      /**< obsolete data instantiation (data) */
     /* */
@@ -1200,6 +1202,7 @@
     LYVE_NOREQINS,     /**< required instance does not exits (data) */
     LYVE_NOLEAFREF,    /**< leaf pointed to by leafref does not exist (data) */
     LYVE_NOMANDCHOICE, /**< no mandatory choice case branch exists (data) */
+    LYVE_INACT,        /**< action contains some other node than container or list with keys (data) */
 
     LYVE_XPATH_INTOK,  /**< unexpected XPath token */
     LYVE_XPATH_EOF,    /**< unexpected end of an XPath expression */
diff --git a/src/log.c b/src/log.c
index 272ca39..a13d099 100644
--- a/src/log.c
+++ b/src/log.c
@@ -24,7 +24,7 @@
 #include "tree_internal.h"
 
 extern LY_ERR ly_errno_int;
-volatile uint8_t ly_log_level = LY_LLERR;
+volatile int8_t ly_log_level = LY_LLERR;
 static void (*ly_log_clb)(LY_LOG_LEVEL level, const char *msg, const char *path);
 static volatile int path_flag = 1;
 
@@ -134,6 +134,7 @@
 /* LYE_EOF */          "Unexpected end of input data.",
 /* LYE_INSTMT */       "Invalid keyword \"%s\".",
 /* LYE_INCHILDSTMT */  "Invalid keyword \"%s\" as a child to \"%s\".",
+/* LYE_INPAR */        "Invalid ancestor \"%s\" of \"%s\".",
 /* LYE_INID */         "Invalid identifier \"%s\" (%s).",
 /* LYE_INDATE */       "Invalid date format of \"%s\", \"YYYY-MM-DD\" expected.",
 /* LYE_INARG */        "Invalid value \"%s\" of \"%s\".",
@@ -163,6 +164,7 @@
 /* LYE_CIRC_LEAFREFS */"A circular chain of leafrefs detected.",
 /* LYE_CIRC_IMPORTS */ "A circular dependency (import) for module \"%s\".",
 /* LYE_CIRC_INCLUDES */"A circular dependency (include) for submodule \"%s\".",
+/* LYE_INVER */        "Different YANG versions of a submodule and its main module.",
 
 /* LYE_OBSDATA */      "Obsolete data \"%s\" instantiated.",
 /* LYE_OBSTYPE */      "Data node \"%s\" with obsolete type \"%s\" instantiated.",
@@ -187,6 +189,7 @@
 /* LYE_NOREQINS */     "Required instance of \"%s\" does not exists.",
 /* LYE_NOLEAFREF */    "Leafref \"%s\" of value \"%s\" points to a non-existing leaf.",
 /* LYE_NOMANDCHOICE */ "Mandatory choice \"%s\" missing a case branch.",
+/* LYE_INACT */        "Action contains a redundant %s \"%s\".",
 
 /* LYE_XPATH_INTOK */  "Unexpected XPath token %s (%.15s).",
 /* LYE_XPATH_EOF */    "Unexpected XPath expression end.",
@@ -216,6 +219,7 @@
     LYVE_EOF,          /* LYE_EOF */
     LYVE_INSTMT,       /* LYE_INSTMT */
     LYVE_INSTMT,       /* LYE_INCHILDSTMT */
+    LYVE_INPAR,        /* LYE_INPAR */
     LYVE_INID,         /* LYE_INID */
     LYVE_INDATE,       /* LYE_INDATE */
     LYVE_INARG,        /* LYE_INARG */
@@ -245,6 +249,7 @@
     LYVE_CIRC_LEAFREFS,/* LYE_CIRC_LEAFREFS */
     LYVE_CIRC_IMPORTS, /* LYE_CIRC_IMPORTS */
     LYVE_CIRC_INCLUDES,/* LYE_CIRC_INCLUDES */
+    LYVE_INVER,        /* LYE_INVER */
 
     LYVE_OBSDATA,      /* LYE_OBSDATA */
     LYVE_OBSDATA,      /* LYE_OBSTYPE */
@@ -269,6 +274,7 @@
     LYVE_NOREQINS,     /* LYE_NOREQINS */
     LYVE_NOLEAFREF,    /* LYE_NOLEAFREF */
     LYVE_NOMANDCHOICE, /* LYE_NOMANDCHOICE */
+    LYVE_INACT,        /* LYE_INACT */
 
     LYVE_XPATH_INTOK,  /* LYE_XPATH_INTOK */
     LYVE_XPATH_EOF,    /* LYE_XPATH_EOF */
diff --git a/src/parser.c b/src/parser.c
index 1daef7b..d1e333e 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -125,15 +125,18 @@
 };
 
 int
-lyp_is_rpc(struct lys_node *node)
+lyp_is_rpc_action(struct lys_node *node)
 {
     assert(node);
 
     while (lys_parent(node)) {
         node = lys_parent(node);
+        if (node->nodetype == LYS_ACTION) {
+            break;
+        }
     }
 
-    if (node->nodetype == LYS_RPC) {
+    if (node->nodetype & (LYS_RPC | LYS_ACTION)) {
         return 1;
     } else {
         return 0;
diff --git a/src/parser.h b/src/parser.h
index a499a33..a35bcfb 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -79,12 +79,12 @@
 int dup_identities_check(const char *id, struct lys_module *module);
 
 /**
- * @brief Get know if the node is part of the RPC's input/output
+ * @brief Get know if the node is part of the RPC/action's input/output
  *
  * @param node Schema node to be examined.
  * @return 1 for true, 0 for false
  */
-int lyp_is_rpc(struct lys_node *node);
+int lyp_is_rpc_action(struct lys_node *node);
 
 /**
  * @brief Check validity of parser options.
diff --git a/src/parser_xml.c b/src/parser_xml.c
index e3fb116..9cc48a8 100644
--- a/src/parser_xml.c
+++ b/src/parser_xml.c
@@ -116,8 +116,8 @@
 
 /* logs directly */
 static int
-xml_parse_data(struct ly_ctx *ctx, struct lyxml_elem *xml, const struct lys_node *schema_parent, struct lyd_node *parent,
-               struct lyd_node *prev, int options, struct unres_data *unres, struct lyd_node **result)
+xml_parse_data(struct ly_ctx *ctx, struct lyxml_elem *xml, struct lyd_node *parent, struct lyd_node *prev, int options,
+               struct unres_data *unres, struct lyd_node **result, struct lyd_node **action)
 {
     struct lyd_node *diter, *dlast, *first_sibling;
     struct lys_node *schema = NULL;
@@ -142,9 +142,7 @@
     }
 
     /* find schema node */
-    if (schema_parent) {
-        schema = xml_data_search_schemanode(xml, schema_parent->child, options);
-    } else if (!parent) {
+    if (!parent) {
         /* starting in root */
         for (i = 0; i < ctx->models.used; i++) {
             /* match data model based on namespace */
@@ -156,6 +154,10 @@
                         if (schema->nodetype != LYS_RPC) {
                             continue;
                         }
+                    } else if (options & LYD_OPT_ACTION) {
+                        if (!(schema->nodetype & (LYS_CONTAINER | LYS_LIST))) {
+                            continue;
+                        }
                     } else if (options & LYD_OPT_NOTIF) {
                         if (schema->nodetype != LYS_NOTIF) {
                             continue;
@@ -192,6 +194,7 @@
     case LYS_LIST:
     case LYS_NOTIF:
     case LYS_RPC:
+    case LYS_ACTION:
         *result = calloc(1, sizeof **result);
         havechildren = 1;
         break;
@@ -357,6 +360,9 @@
             ((struct lyd_node_anyxml *)*result)->xml_struct = 0;
             ((struct lyd_node_anyxml *)*result)->value.str = lydict_insert(ctx, xml->content, 0);
         }
+    } else if (schema->nodetype == LYS_ACTION) {
+        options &= ~LYS_ACTION;
+        options |= LYS_RPC;
     }
 
     /* first part of validation checks */
@@ -433,14 +439,22 @@
         }
     }
 
+    if ((*result)->schema->nodetype == LYS_ACTION) {
+        if (!(options & LYD_OPT_ACTION) || *action) {
+            LOGVAL(LYE_SPEC, LY_VLOG_LYD, (*result), "Unexpected action node \"%s\".", (*result)->schema->name);
+            goto error;
+        }
+        *action = *result;
+    }
+
     /* process children */
     if (havechildren && xml->child) {
         diter = dlast = NULL;
         LY_TREE_FOR_SAFE(xml->child, next, child) {
             if (schema->nodetype & (LYS_RPC | LYS_NOTIF)) {
-                r = xml_parse_data(ctx, child, NULL, *result, dlast, 0, unres, &diter);
+                r = xml_parse_data(ctx, child, *result, dlast, 0, unres, &diter, action);
             } else {
-                r = xml_parse_data(ctx, child, NULL, *result, dlast, options, unres, &diter);
+                r = xml_parse_data(ctx, child, *result, dlast, options, unres, &diter, action);
             }
             if (r) {
                 goto error;
@@ -499,8 +513,8 @@
     va_list ap;
     int r;
     struct unres_data *unres = NULL;
-    struct lys_node *rpc = NULL;
-    struct lyd_node *result = NULL, *iter, *last;
+    struct lys_node *rpc_act = NULL;
+    struct lyd_node *result = NULL, *iter, *last, *reply_parent = NULL, *action = NULL;
     struct lyxml_elem *xmlstart, *xmlelem, *xmlaux;
 
     ly_errno = LY_SUCCESS;
@@ -529,11 +543,13 @@
 
     va_start(ap, options);
     if (options & LYD_OPT_RPCREPLY) {
-        rpc = va_arg(ap,  struct lys_node*);
-        if (!rpc || (rpc->nodetype != LYS_RPC)) {
+        rpc_act = va_arg(ap,  struct lys_node *);
+        if (!rpc_act || !(rpc_act->nodetype & (LYS_RPC | LYS_ACTION))) {
             LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
             goto error;
         }
+        reply_parent = _lyd_new(NULL, rpc_act);
+        result = reply_parent;
     }
 
     if (!(options & LYD_OPT_NOSIBLINGS)) {
@@ -549,10 +565,18 @@
     } else {
         xmlstart = *root;
     }
-    iter = result = last = NULL;
 
+    if ((options & LYD_OPT_RPC)
+            && !strcmp(xmlstart->name, "action") && !strcmp(xmlstart->ns->value, "urn:ietf:params:xml:ns:yang:1")) {
+        /* it's an action, not a simple RPC */
+        xmlstart = xmlstart->child;
+        options &= ~LYD_OPT_RPC;
+        options |= LYD_OPT_ACTION;
+    }
+
+    iter = last = NULL;
     LY_TREE_FOR_SAFE(xmlstart, xmlaux, xmlelem) {
-        r = xml_parse_data(ctx, xmlelem, rpc, NULL, last, options, unres, &iter);
+        r = xml_parse_data(ctx, xmlelem, reply_parent, last, options, unres, &iter, &action);
         if (r) {
             goto error;
         } else if (options & LYD_OPT_DESTRUCT) {
@@ -572,28 +596,17 @@
         }
     }
 
-    if (options & LYD_OPT_RPCREPLY) {
-        last = result;
-        result = lyd_new_output(NULL, lys_node_module(rpc), rpc->name);
-        /* insert all the output parameters into RPC */
-        do {
-            iter = last;
-            last = iter->next;
-            if (lyd_insert(result, iter)) {
-                LOGINT;
-                lyd_free_withsiblings(last);
-                goto error;
-            }
-        } while (last);
-    }
-
     /* check for missing top level mandatory nodes */
     if (lyd_check_topmandatory(result, ctx, options)) {
         goto error;
     }
 
     /* add/validate default values, unres */
-    if (lyd_defaults_add_unres(&result, options, ctx, unres)) {
+    if (action) {
+        if (lyd_defaults_add_unres(&action, options, ctx, unres)) {
+            goto error;
+        }
+    } else if (lyd_defaults_add_unres(&result, options, ctx, unres)) {
         goto error;
     }
 
diff --git a/src/parser_yang.c b/src/parser_yang.c
index 096cbf4..5411a66 100644
--- a/src/parser_yang.c
+++ b/src/parser_yang.c
@@ -38,7 +38,6 @@
     int size;
     struct lys_tpdf *tpdf;
 
-
     if (root) {
         node = root;
     }
@@ -60,13 +59,13 @@
                     size = ((struct lys_node_grp *)child)->tpdf_size;
                     break;
                 case LYS_RPC:
-                    tpdf = ((struct lys_node_rpc *)child)->tpdf;
-                    size = ((struct lys_node_rpc *)child)->tpdf_size;
+                    tpdf = ((struct lys_node_rpc_action *)child)->tpdf;
+                    size = ((struct lys_node_rpc_action *)child)->tpdf_size;
                     break;
                 case LYS_INPUT:
                 case LYS_OUTPUT:
-                    tpdf = ((struct lys_node_rpc_inout *)child)->tpdf;
-                    size = ((struct lys_node_rpc_inout *)child)->tpdf_size;
+                    tpdf = ((struct lys_node_inout *)child)->tpdf;
+                    size = ((struct lys_node_inout *)child)->tpdf_size;
                     break;
                 case LYS_NOTIF:
                     tpdf = ((struct lys_node_notif *)child)->tpdf;
@@ -266,22 +265,18 @@
     }
     free(value);
 
-    /* hack - store pointer to the parent node for later status check */
     if (type == FEATURE_KEYWORD) {
         f = (struct lys_feature *) ptr;
-        f->features[f->features_size] = f;
-        ret = unres_schema_add_str(module, unres, &f->features[f->features_size], UNRES_IFFEAT, exp);
-        f->features_size++;
+        ret = resolve_iffeature_compile(&f->iffeature[f->iffeature_size], exp, (struct lys_node *)f, unres);
+        f->iffeature_size++;
     } else {
         n = (struct lys_node *) ptr;
-        n->features[n->features_size] = (struct lys_feature *) n;
-        ret = unres_schema_add_str(module, unres, &n->features[n->features_size], UNRES_IFFEAT, exp);
-        n->features_size++;
+        ret = resolve_iffeature_compile(&n->iffeature[n->iffeature_size], exp, n, unres);
+        n->iffeature_size++;
     }
-
     lydict_remove(module->ctx, exp);
-    if (ret == -1) {
 
+    if (ret) {
         return EXIT_FAILURE;
     }
     return EXIT_SUCCESS;
@@ -1307,13 +1302,14 @@
             ((struct lys_node_list *)parent)->tpdf_size++;
             break;
         case LYS_RPC:
-            ret = &((struct lys_node_rpc *)parent)->tpdf[((struct lys_node_rpc *)parent)->tpdf_size];
-            ((struct lys_node_rpc *)parent)->tpdf_size++;
+        case LYS_ACTION:
+            ret = &((struct lys_node_rpc_action *)parent)->tpdf[((struct lys_node_rpc_action *)parent)->tpdf_size];
+            ((struct lys_node_rpc_action *)parent)->tpdf_size++;
             break;
         case LYS_INPUT:
         case LYS_OUTPUT:
-            ret = &((struct lys_node_rpc_inout *)parent)->tpdf[((struct lys_node_rpc_inout *)parent)->tpdf_size];
-            ((struct lys_node_rpc_inout *)parent)->tpdf_size++;
+            ret = &((struct lys_node_inout *)parent)->tpdf[((struct lys_node_inout *)parent)->tpdf_size];
+            ((struct lys_node_inout *)parent)->tpdf_size++;
             break;
         case LYS_NOTIF:
             ret = &((struct lys_node_notif *)parent)->tpdf[((struct lys_node_notif *)parent)->tpdf_size];
diff --git a/src/parser_yang.h b/src/parser_yang.h
index e2a4c3d..9e5a518 100644
--- a/src/parser_yang.h
+++ b/src/parser_yang.h
@@ -82,8 +82,8 @@
         struct lys_node_leaf *ptr_leaf;
         struct lys_tpdf *ptr_tpdf;
         struct lys_node_augment *ptr_augment;
-        struct lys_node_rpc *ptr_rpc;
-        struct lys_node_rpc_inout *ptr_inout;
+        struct lys_node_rpc_action *ptr_rpc;
+        struct lys_node_inout *ptr_inout;
     };
     uint8_t flag;
 };
diff --git a/src/parser_yang_bis.c b/src/parser_yang_bis.c
index 5f6254d..5d2d83e 100644
--- a/src/parser_yang_bis.c
+++ b/src/parser_yang_bis.c
@@ -3086,7 +3086,7 @@
 
   case 24:
 
-    { if (strlen(yyget_text(scanner))!=1 || yyget_text(scanner)[0]!='1') {
+    { if (strcmp(yyget_text(scanner), "1") && strcmp(yyget_text(scanner), "1.1")) {
                                                YYABORT;
                                              }
                                            }
@@ -3096,7 +3096,7 @@
   case 26:
 
     { if (read_all) {
-                 if (strlen(s)!=1 || s[0]!='1') {
+                 if (strcmp(s, "1") && strcmp(s, "1.1")) {
                    free(s);
                    YYABORT;
                  }
@@ -3614,9 +3614,9 @@
 
     { if (read_all) {
                              if (size_arrays->node[size_arrays->next].if_features) {
-                               ((struct lys_feature*)actual)->features = calloc(size_arrays->node[size_arrays->next].if_features,
-                                                                                sizeof *((struct lys_feature*)actual)->features);
-                               if (!((struct lys_feature*)actual)->features) {
+                               ((struct lys_feature*)actual)->iffeature = calloc(size_arrays->node[size_arrays->next].if_features,
+                                                                                sizeof *((struct lys_feature*)actual)->iffeature);
+                               if (!((struct lys_feature*)actual)->iffeature) {
                                  LOGMEM;
                                  YYABORT;
                                }
@@ -4558,8 +4558,8 @@
                                (yyval.nodes).container = actual;
                                actual_type = CONTAINER_KEYWORD;
                                if (size_arrays->node[size_arrays->next].if_features) {
-                                 (yyval.nodes).container->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).container->features);
-                                 if (!(yyval.nodes).container->features) {
+                                 (yyval.nodes).container->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).container->iffeature);
+                                 if (!(yyval.nodes).container->iffeature) {
                                    LOGMEM;
                                    YYABORT;
                                  }
@@ -4740,8 +4740,8 @@
                             (yyval.nodes).node.flag = 0;
                             actual_type = LEAF_KEYWORD;
                             if (size_arrays->node[size_arrays->next].if_features) {
-                              (yyval.nodes).node.ptr_leaf->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).node.ptr_leaf->features);
-                              if (!(yyval.nodes).node.ptr_leaf->features) {
+                              (yyval.nodes).node.ptr_leaf->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).node.ptr_leaf->iffeature);
+                              if (!(yyval.nodes).node.ptr_leaf->iffeature) {
                                 LOGMEM;
                                 YYABORT;
                               }
@@ -4933,8 +4933,8 @@
                                (yyval.nodes).node.flag = 0;
                                actual_type = LEAF_LIST_KEYWORD;
                                if (size_arrays->node[size_arrays->next].if_features) {
-                                 (yyval.nodes).node.ptr_leaflist->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).node.ptr_leaflist->features);
-                                 if (!(yyval.nodes).node.ptr_leaflist->features) {
+                                 (yyval.nodes).node.ptr_leaflist->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).node.ptr_leaflist->iffeature);
+                                 if (!(yyval.nodes).node.ptr_leaflist->iffeature) {
                                    LOGMEM;
                                    YYABORT;
                                  }
@@ -5168,8 +5168,8 @@
                           (yyval.nodes).node.flag = 0;
                           actual_type = LIST_KEYWORD;
                           if (size_arrays->node[size_arrays->next].if_features) {
-                            (yyval.nodes).node.ptr_list->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).node.ptr_list->features);
-                            if (!(yyval.nodes).node.ptr_list->features) {
+                            (yyval.nodes).node.ptr_list->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).node.ptr_list->iffeature);
+                            if (!(yyval.nodes).node.ptr_list->iffeature) {
                               LOGMEM;
                               YYABORT;
                             }
@@ -5441,8 +5441,8 @@
                             (yyval.nodes).choice.s = NULL;
                             actual_type = CHOICE_KEYWORD;
                             if (size_arrays->node[size_arrays->next].if_features) {
-                              (yyval.nodes).choice.ptr_choice->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).choice.ptr_choice->features);
-                              if (!(yyval.nodes).choice.ptr_choice->features) {
+                              (yyval.nodes).choice.ptr_choice->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).choice.ptr_choice->iffeature);
+                              if (!(yyval.nodes).choice.ptr_choice->iffeature) {
                                 LOGMEM;
                                 YYABORT;
                               }
@@ -5609,8 +5609,8 @@
                           (yyval.nodes).cs = actual;
                           actual_type = CASE_KEYWORD;
                           if (size_arrays->node[size_arrays->next].if_features) {
-                            (yyval.nodes).cs->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).cs->features);
-                            if (!(yyval.nodes).cs->features) {
+                            (yyval.nodes).cs->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).cs->iffeature);
+                            if (!(yyval.nodes).cs->iffeature) {
                               LOGMEM;
                               YYABORT;
                             }
@@ -5706,15 +5706,15 @@
                             (yyval.nodes).anyxml = actual;
                             actual_type = ANYXML_KEYWORD;
                             if (size_arrays->node[size_arrays->next].if_features) {
-                              (yyval.nodes).anyxml->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).anyxml->features);
-                              if (!(yyval.nodes).anyxml->features) {
+                              (yyval.nodes).anyxml->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).anyxml->iffeature);
+                              if (!(yyval.nodes).anyxml->iffeature) {
                                 LOGMEM;
                                 YYABORT;
                               }
                             }
                             if (size_arrays->node[size_arrays->next].must) {
                               (yyval.nodes).anyxml->must = calloc(size_arrays->node[size_arrays->next].must, sizeof *(yyval.nodes).anyxml->must);
-                              if (!(yyval.nodes).anyxml->features || !(yyval.nodes).anyxml->must) {
+                              if (!(yyval.nodes).anyxml->iffeature || !(yyval.nodes).anyxml->must) {
                                 LOGMEM;
                                 YYABORT;
                               }
@@ -5847,8 +5847,8 @@
                           (yyval.nodes).uses.config_inherit = config_inherit;
                           actual_type = USES_KEYWORD;
                           if (size_arrays->node[size_arrays->next].if_features) {
-                            (yyval.nodes).uses.ptr_uses->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).uses.ptr_uses->features);
-                            if (!(yyval.nodes).uses.ptr_uses->features) {
+                            (yyval.nodes).uses.ptr_uses->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).uses.ptr_uses->iffeature);
+                            if (!(yyval.nodes).uses.ptr_uses->iffeature) {
                               LOGMEM;
                               YYABORT;
                             }
@@ -6247,8 +6247,8 @@
                              (yyval.nodes).node.flag = 0;
                              actual_type = AUGMENT_KEYWORD;
                              if (size_arrays->node[size_arrays->next].if_features) {
-                               (yyval.nodes).node.ptr_augment->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).node.ptr_augment->features);
-                               if (!(yyval.nodes).node.ptr_augment->features) {
+                               (yyval.nodes).node.ptr_augment->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).node.ptr_augment->iffeature);
+                               if (!(yyval.nodes).node.ptr_augment->iffeature) {
                                  LOGMEM;
                                  YYABORT;
                                }
@@ -6357,7 +6357,7 @@
   case 421:
 
     { if (read_all) {
-                                                 if (!(actual = yang_read_node(trg, NULL, s, LYS_RPC, sizeof(struct lys_node_rpc)))) {
+                                                 if (!(actual = yang_read_node(trg, NULL, s, LYS_RPC, sizeof(struct lys_node_rpc_action)))) {
                                                    YYABORT;
                                                  }
                                                  data_node = actual;
@@ -6381,8 +6381,8 @@
                          (yyval.nodes).node.flag = 0;
                          actual_type = RPC_KEYWORD;
                          if (size_arrays->node[size_arrays->next].if_features) {
-                           (yyval.nodes).node.ptr_rpc->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).node.ptr_rpc->features);
-                           if (!(yyval.nodes).node.ptr_rpc->features) {
+                           (yyval.nodes).node.ptr_rpc->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).node.ptr_rpc->iffeature);
+                           if (!(yyval.nodes).node.ptr_rpc->iffeature) {
                              LOGMEM;
                              YYABORT;
                            }
@@ -6523,7 +6523,7 @@
                                        LOGMEM;
                                        YYABORT;
                                      }
-                                     if (!(actual = yang_read_node(trg, actual, s, LYS_INPUT, sizeof(struct lys_node_rpc_inout)))) {
+                                     if (!(actual = yang_read_node(trg, actual, s, LYS_INPUT, sizeof(struct lys_node_inout)))) {
                                       YYABORT;
                                      }
                                      data_node = actual;
@@ -6615,7 +6615,7 @@
                                          LOGMEM;
                                          YYABORT;
                                        }
-                                       if (!(actual = yang_read_node(trg, actual, s, LYS_OUTPUT, sizeof(struct lys_node_rpc_inout)))) {
+                                       if (!(actual = yang_read_node(trg, actual, s, LYS_OUTPUT, sizeof(struct lys_node_inout)))) {
                                         YYABORT;
                                        }
                                        data_node = actual;
@@ -6669,8 +6669,8 @@
                                   (yyval.nodes).notif = actual;
                                   actual_type = NOTIFICATION_KEYWORD;
                                   if (size_arrays->node[size_arrays->next].if_features) {
-                                    (yyval.nodes).notif->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).notif->features);
-                                    if (!(yyval.nodes).notif->features) {
+                                    (yyval.nodes).notif->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).notif->iffeature);
+                                    if (!(yyval.nodes).notif->iffeature) {
                                       LOGMEM;
                                       YYABORT;
                                     }
diff --git a/src/parser_yin.c b/src/parser_yin.c
index 73e5600..348cb2e 100644
--- a/src/parser_yin.c
+++ b/src/parser_yin.c
@@ -67,6 +67,8 @@
                                       struct unres_schema *unres);
 static struct lys_node *read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
                                           int resolve, struct unres_schema *unres);
+static struct lys_node *read_yin_rpc_action(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
+                                            int resolve, struct unres_schema *unres);
 static struct lys_when *read_yin_when(struct lys_module *module, struct lyxml_elem *yin);
 
 /* logs directly */
@@ -90,26 +92,24 @@
 
 /* logs directly */
 static int
-fill_yin_iffeature(struct lys_node *parent, struct lyxml_elem *yin, struct lys_feature **iffeat, struct unres_schema *unres)
+fill_yin_iffeature(struct lys_node *parent, struct lyxml_elem *yin, struct lys_iffeature *iffeat, struct unres_schema *unres)
 {
     int r;
     const char *value;
 
     GETVAL(value, yin, "name");
     if (!(value = transform_schema2json(parent->module, value))) {
+error:
         return EXIT_FAILURE;
     }
 
-    /* HACK - store pointer to the parent node for later status check */
-    *iffeat = (struct lys_feature *)parent;
-    r = unres_schema_add_str(parent->module, unres, iffeat, UNRES_IFFEAT, value);
+    r = resolve_iffeature_compile(iffeat, value, parent, unres);
     lydict_remove(parent->module->ctx, value);
-    if (!r) {
-        return EXIT_SUCCESS;
+    if (r) {
+        return EXIT_FAILURE;
     }
 
-error:
-    return EXIT_FAILURE;
+    return EXIT_SUCCESS;
 }
 
 /* logs directly */
@@ -1051,15 +1051,15 @@
     }
 
     if (c) {
-        f->features = calloc(c, sizeof *f->features);
-        if (!f->features) {
+        f->iffeature = calloc(c, sizeof *f->iffeature);
+        if (!f->iffeature) {
             LOGMEM;
             goto error;
         }
     }
     LY_TREE_FOR(yin->child, child) {
-        ret = fill_yin_iffeature((struct lys_node *)f, child, &f->features[f->features_size], unres);
-        f->features_size++;
+        ret = fill_yin_iffeature((struct lys_node *)f, child, &f->iffeature[f->iffeature_size], unres);
+        f->iffeature_size++;
         if (ret) {
             goto error;
         }
@@ -2015,6 +2015,8 @@
             node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
         } else if (!strcmp(child->name, "anyxml")) {
             node = read_yin_anyxml(module, (struct lys_node *)aug, child, 0, unres);
+        } else if (!strcmp(child->name, "action")) {
+            node = read_yin_rpc_action(module, (struct lys_node *)aug, child, 0, unres);
         } else {
             LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
             goto error;
@@ -2029,8 +2031,8 @@
     }
 
     if (c) {
-        aug->features = calloc(c, sizeof *aug->features);
-        if (!aug->features) {
+        aug->iffeature = calloc(c, sizeof *aug->iffeature);
+        if (!aug->iffeature) {
             LOGMEM;
             goto error;
         }
@@ -2038,8 +2040,8 @@
 
     LY_TREE_FOR_SAFE(yin->child, next, child) {
         if (!strcmp(child->name, "if-feature")) {
-            ret = fill_yin_iffeature((struct lys_node *)aug, child, &aug->features[aug->features_size], unres);
-            aug->features_size++;
+            ret = fill_yin_iffeature((struct lys_node *)aug, child, &aug->iffeature[aug->iffeature_size], unres);
+            aug->iffeature_size++;
             if (ret) {
                 goto error;
             }
@@ -2654,15 +2656,15 @@
     }
 
     if (c_ftrs) {
-        cs->features = calloc(c_ftrs, sizeof *cs->features);
-        if (!cs->features) {
+        cs->iffeature = calloc(c_ftrs, sizeof *cs->iffeature);
+        if (!cs->iffeature) {
             LOGMEM;
             goto error;
         }
     }
     LY_TREE_FOR(yin->child, sub) {
-        ret = fill_yin_iffeature(retval, sub, &cs->features[cs->features_size], unres);
-        cs->features_size++;
+        ret = fill_yin_iffeature(retval, sub, &cs->iffeature[cs->iffeature_size], unres);
+        cs->iffeature_size++;
         if (ret) {
             goto error;
         }
@@ -2823,16 +2825,16 @@
     }
 
     if (c_ftrs) {
-        choice->features = calloc(c_ftrs, sizeof *choice->features);
-        if (!choice->features) {
+        choice->iffeature = calloc(c_ftrs, sizeof *choice->iffeature);
+        if (!choice->iffeature) {
             LOGMEM;
             goto error;
         }
     }
 
     LY_TREE_FOR(yin->child, sub) {
-        ret = fill_yin_iffeature(retval, sub, &choice->features[choice->features_size], unres);
-        choice->features_size++;
+        ret = fill_yin_iffeature(retval, sub, &choice->iffeature[choice->iffeature_size], unres);
+        choice->iffeature_size++;
         if (ret) {
             goto error;
         }
@@ -2958,8 +2960,8 @@
         }
     }
     if (c_ftrs) {
-        anyxml->features = calloc(c_ftrs, sizeof *anyxml->features);
-        if (!anyxml->features) {
+        anyxml->iffeature = calloc(c_ftrs, sizeof *anyxml->iffeature);
+        if (!anyxml->iffeature) {
             LOGMEM;
             goto error;
         }
@@ -2973,8 +2975,8 @@
                 goto error;
             }
         } else if (!strcmp(sub->name, "if-feature")) {
-            r = fill_yin_iffeature(retval, sub, &anyxml->features[anyxml->features_size], unres);
-            anyxml->features_size++;
+            r = fill_yin_iffeature(retval, sub, &anyxml->iffeature[anyxml->iffeature_size], unres);
+            anyxml->iffeature_size++;
             if (r) {
                 goto error;
             }
@@ -3128,8 +3130,8 @@
         }
     }
     if (c_ftrs) {
-        leaf->features = calloc(c_ftrs, sizeof *leaf->features);
-        if (!leaf->features) {
+        leaf->iffeature = calloc(c_ftrs, sizeof *leaf->iffeature);
+        if (!leaf->iffeature) {
             LOGMEM;
             goto error;
         }
@@ -3143,8 +3145,8 @@
                 goto error;
             }
         } else if (!strcmp(sub->name, "if-feature")) {
-            r = fill_yin_iffeature(retval, sub, &leaf->features[leaf->features_size], unres);
-            leaf->features_size++;
+            r = fill_yin_iffeature(retval, sub, &leaf->iffeature[leaf->iffeature_size], unres);
+            leaf->iffeature_size++;
             if (r) {
                 goto error;
             }
@@ -3345,8 +3347,8 @@
         }
     }
     if (c_ftrs) {
-        llist->features = calloc(c_ftrs, sizeof *llist->features);
-        if (!llist->features) {
+        llist->iffeature = calloc(c_ftrs, sizeof *llist->iffeature);
+        if (!llist->iffeature) {
             LOGMEM;
             goto error;
         }
@@ -3360,8 +3362,8 @@
                 goto error;
             }
         } else if (!strcmp(sub->name, "if-feature")) {
-            r = fill_yin_iffeature(retval, sub, &llist->features[llist->features_size], unres);
-            llist->features_size++;
+            r = fill_yin_iffeature(retval, sub, &llist->iffeature[llist->iffeature_size], unres);
+            llist->iffeature_size++;
             if (r) {
                 goto error;
             }
@@ -3433,7 +3435,8 @@
                 !strcmp(sub->name, "choice") ||
                 !strcmp(sub->name, "uses") ||
                 !strcmp(sub->name, "grouping") ||
-                !strcmp(sub->name, "anyxml")) {
+                !strcmp(sub->name, "anyxml") ||
+                !strcmp(sub->name, "action")) {
             lyxml_unlink_elem(module->ctx, sub, 2);
             lyxml_add_child(module->ctx, &root, sub);
 
@@ -3598,8 +3601,8 @@
         }
     }
     if (c_ftrs) {
-        list->features = calloc(c_ftrs, sizeof *list->features);
-        if (!list->features) {
+        list->iffeature = calloc(c_ftrs, sizeof *list->iffeature);
+        if (!list->iffeature) {
             LOGMEM;
             goto error;
         }
@@ -3612,8 +3615,8 @@
                 goto error;
             }
         } else if (!strcmp(sub->name, "if-feature")) {
-            r = fill_yin_iffeature(retval, sub, &list->features[list->features_size], unres);
-            list->features_size++;
+            r = fill_yin_iffeature(retval, sub, &list->iffeature[list->iffeature_size], unres);
+            list->iffeature_size++;
             if (r) {
                 goto error;
             }
@@ -3644,6 +3647,8 @@
             node = read_yin_grouping(module, retval, sub, resolve, unres);
         } else if (!strcmp(sub->name, "anyxml")) {
             node = read_yin_anyxml(module, retval, sub, resolve, unres);
+        } else if (!strcmp(sub->name, "action")) {
+            node = read_yin_rpc_action(module, retval, sub, resolve, unres);
         } else {
             LOGINT;
             goto error;
@@ -3770,7 +3775,8 @@
                 !strcmp(sub->name, "choice") ||
                 !strcmp(sub->name, "uses") ||
                 !strcmp(sub->name, "grouping") ||
-                !strcmp(sub->name, "anyxml")) {
+                !strcmp(sub->name, "anyxml") ||
+                !strcmp(sub->name, "action")) {
             lyxml_unlink_elem(module->ctx, sub, 2);
             lyxml_add_child(module->ctx, &root, sub);
 
@@ -3803,8 +3809,8 @@
         }
     }
     if (c_ftrs) {
-        cont->features = calloc(c_ftrs, sizeof *cont->features);
-        if (!cont->features) {
+        cont->iffeature = calloc(c_ftrs, sizeof *cont->iffeature);
+        if (!cont->iffeature) {
             LOGMEM;
             goto error;
         }
@@ -3824,8 +3830,8 @@
                 goto error;
             }
         } else if (!strcmp(sub->name, "if-feature")) {
-            r = fill_yin_iffeature(retval, sub, &cont->features[cont->features_size], unres);
-            cont->features_size++;
+            r = fill_yin_iffeature(retval, sub, &cont->iffeature[cont->iffeature_size], unres);
+            cont->iffeature_size++;
             if (r) {
                 goto error;
             }
@@ -3850,6 +3856,8 @@
             node = read_yin_grouping(module, retval, sub, resolve, unres);
         } else if (!strcmp(sub->name, "anyxml")) {
             node = read_yin_anyxml(module, retval, sub, resolve, unres);
+        } else if (!strcmp(sub->name, "action")) {
+            node = read_yin_rpc_action(module, retval, sub, resolve, unres);
         }
         if (!node) {
             goto error;
@@ -3920,7 +3928,8 @@
                 !strcmp(sub->name, "choice") ||
                 !strcmp(sub->name, "uses") ||
                 !strcmp(sub->name, "grouping") ||
-                !strcmp(sub->name, "anyxml")) {
+                !strcmp(sub->name, "anyxml") ||
+                !strcmp(sub->name, "action")) {
             lyxml_unlink_elem(module->ctx, sub, 2);
             lyxml_add_child(module->ctx, &root, sub);
 
@@ -3970,6 +3979,8 @@
             node = read_yin_grouping(module, retval, sub, resolve, unres);
         } else if (!strcmp(sub->name, "anyxml")) {
             node = read_yin_anyxml(module, retval, sub, resolve, unres);
+        } else if (!strcmp(sub->name, "action")) {
+            node = read_yin_rpc_action(module, retval, sub, resolve, unres);
         }
         if (!node) {
             goto error;
@@ -3998,7 +4009,7 @@
     struct lyxml_elem *sub, *next, root;
     struct lys_node *node = NULL;
     struct lys_node *retval = NULL;
-    struct lys_node_rpc_inout *inout;
+    struct lys_node_inout *inout;
     int r;
     int c_tpdf = 0;
 
@@ -4195,8 +4206,8 @@
         }
     }
     if (c_ftrs) {
-        notif->features = calloc(c_ftrs, sizeof *notif->features);
-        if (!notif->features) {
+        notif->iffeature = calloc(c_ftrs, sizeof *notif->iffeature);
+        if (!notif->iffeature) {
             LOGMEM;
             goto error;
         }
@@ -4210,8 +4221,8 @@
                 goto error;
             }
         } else if (!strcmp(sub->name, "if-feature")) {
-            r = fill_yin_iffeature(retval, sub, &notif->features[notif->features_size], unres);
-            notif->features_size++;
+            r = fill_yin_iffeature(retval, sub, &notif->iffeature[notif->iffeature_size], unres);
+            notif->iffeature_size++;
             if (r) {
                 goto error;
             }
@@ -4258,16 +4269,26 @@
 
 /* logs directly */
 static struct lys_node *
-read_yin_rpc(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
-             struct unres_schema *unres)
+read_yin_rpc_action(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
+                    struct unres_schema *unres)
 {
     struct lyxml_elem *sub, *next, root;
     struct lys_node *node = NULL;
     struct lys_node *retval;
-    struct lys_node_rpc *rpc;
+    struct lys_node_rpc_action *rpc;
     int r;
     int c_tpdf = 0, c_ftrs = 0;
 
+    if (!strcmp(yin->name, "action")) {
+        for (node = parent; node; node = lys_parent(node)) {
+            if (node->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)
+                    || ((node->nodetype == LYS_LIST) && !((struct lys_node_list *)node)->keys_size)) {
+                LOGVAL(LYE_INPAR, LY_VLOG_NONE, NULL, strnodetype(node->nodetype), "action");
+                return NULL;
+            }
+        }
+    }
+
     /* init */
     memset(&root, 0, sizeof root);
 
@@ -4276,7 +4297,7 @@
         LOGMEM;
         return NULL;
     }
-    rpc->nodetype = LYS_RPC;
+    rpc->nodetype = (!strcmp(yin->name, "rpc") ? LYS_RPC : LYS_ACTION);
     rpc->prev = (struct lys_node *)rpc;
     retval = (struct lys_node *)rpc;
 
@@ -4310,8 +4331,8 @@
             lyxml_add_child(module->ctx, &root, sub);
         } else if (!strcmp(sub->name, "output")) {
             if (rpc->child
-                && (rpc->child->nodetype == LYS_INPUT
-                    || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
+                && (rpc->child->nodetype == LYS_OUTPUT
+                    || (rpc->child->next && rpc->child->next->nodetype == LYS_OUTPUT))) {
                 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
                 goto error;
             }
@@ -4343,8 +4364,8 @@
         }
     }
     if (c_ftrs) {
-        rpc->features = calloc(c_ftrs, sizeof *rpc->features);
-        if (!rpc->features) {
+        rpc->iffeature = calloc(c_ftrs, sizeof *rpc->iffeature);
+        if (!rpc->iffeature) {
             LOGMEM;
             goto error;
         }
@@ -4358,8 +4379,8 @@
                 goto error;
             }
         } else if (!strcmp(sub->name, "if-feature")) {
-            r = fill_yin_iffeature(retval, sub, &rpc->features[rpc->features_size], unres);
-            rpc->features_size++;
+            r = fill_yin_iffeature(retval, sub, &rpc->iffeature[rpc->iffeature_size], unres);
+            rpc->iffeature_size++;
             if (r) {
                 goto error;
             }
@@ -4370,9 +4391,7 @@
     LY_TREE_FOR_SAFE(root.child, next, sub) {
         if (!strcmp(sub->name, "grouping")) {
             node = read_yin_grouping(module, retval, sub, resolve, unres);
-        } else if (!strcmp(sub->name, "input")) {
-            node = read_yin_input_output(module, retval, sub, resolve, unres);
-        } else if (!strcmp(sub->name, "output")) {
+        } else if (!strcmp(sub->name, "input") || !strcmp(sub->name, "output")) {
             node = read_yin_input_output(module, retval, sub, resolve, unres);
         }
         if (!node) {
@@ -4482,8 +4501,8 @@
         }
     }
     if (c_ftrs) {
-        uses->features = calloc(c_ftrs, sizeof *uses->features);
-        if (!uses->features) {
+        uses->iffeature = calloc(c_ftrs, sizeof *uses->iffeature);
+        if (!uses->iffeature) {
             LOGMEM;
             goto error;
         }
@@ -4503,8 +4522,8 @@
                 goto error;
             }
         } else if (!strcmp(sub->name, "if-feature")) {
-            r = fill_yin_iffeature(retval, sub, &uses->features[uses->features_size], unres);
-            uses->features_size++;
+            r = fill_yin_iffeature(retval, sub, &uses->iffeature[uses->iffeature_size], unres);
+            uses->iffeature_size++;
             if (r) {
                 goto error;
             }
@@ -4703,20 +4722,36 @@
                 goto error;
             }
         } else if (!strcmp(child->name, "yang-version")) {
-            /* TODO: support YANG 1.1 ? */
             if (version_flag) {
                 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
                 goto error;
             }
             GETVAL(value, child, "value");
-            if (strcmp(value, "1")) {
+            if (strcmp(value, "1") && strcmp(value, "1.1")) {
                 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
                 goto error;
             }
             version_flag = 1;
-            if (!submodule) {
-                module->version = 1;
-            } /* TODO else check for the submodule's same version as in main module, waits for YANG 1.1 support */
+            if (!strcmp(value, "1")) {
+                if (submodule) {
+                    if (module->version > 1) {
+                        LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
+                        goto error;
+                    }
+                } else {
+                    module->version = 1;
+                }
+            } else {
+                if (submodule) {
+                    if (module->version != 2) {
+                        LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
+                        goto error;
+                    }
+                } else {
+                    module->version = 2;
+                }
+            }
+
             lyxml_free(ctx, child);
 
         } else if (!strcmp(child->name, "extension")) {
@@ -4993,7 +5028,7 @@
         } else if (!strcmp(child->name, "anyxml")) {
             node = read_yin_anyxml(trg, NULL, child, 1, unres);
         } else if (!strcmp(child->name, "rpc")) {
-            node = read_yin_rpc(trg, NULL, child, 0, unres);
+            node = read_yin_rpc_action(trg, NULL, child, 0, unres);
         } else if (!strcmp(child->name, "notification")) {
             node = read_yin_notif(trg, NULL, child, 0, unres);
         }
diff --git a/src/printer.c b/src/printer.c
index 91c13e6..d223607 100644
--- a/src/printer.c
+++ b/src/printer.c
@@ -134,6 +134,75 @@
 }
 
 static int
+write_iff(struct lyout *out, const struct lys_module *module, struct lys_iffeature *expr, int *index_e, int *index_f)
+{
+    int count = 0, brackets_flag = *index_e;
+    uint8_t op;
+
+    op = iff_getop(expr->expr, *index_e);
+    (*index_e)++;
+
+    switch (op) {
+    case LYS_IFF_F:
+        if (lys_main_module(expr->features[*index_f]->module) != lys_main_module(module)) {
+            count += ly_print(out, "%s:", transform_module_name2import_prefix(module, lys_main_module(expr->features[*index_f]->module)->name));
+        }
+        count += ly_print(out, expr->features[*index_f]->name);
+        (*index_f)++;
+        break;
+    case LYS_IFF_NOT:
+        op = iff_getop(expr->expr, *index_e);
+        if (op == LYS_IFF_F) {
+            /* negation about sole feature */
+            brackets_flag = 0;
+        } else {
+            /* negation around expression */
+            brackets_flag = 1;
+        }
+
+        count += ly_print(out, "not ");
+        if (brackets_flag) {
+            count += ly_print(out, "(");
+        }
+        count += write_iff(out, module, expr, index_e, index_f);
+        if (brackets_flag) {
+                count += ly_print(out, ")");
+        }
+        break;
+    case LYS_IFF_AND:
+    case LYS_IFF_OR:
+        if (brackets_flag && op == LYS_IFF_AND) {
+            /* AND does not need brackets */
+            brackets_flag = 0;
+        }
+
+        if (brackets_flag) {
+            count += ly_print(out, "(");
+        }
+        count += write_iff(out, module, expr, index_e, index_f);
+        count += ly_print(out, " %s ", op == LYS_IFF_OR ? "or" : "and");
+        count += write_iff(out, module, expr, index_e, index_f);
+        if (brackets_flag) {
+            count += ly_print(out, ")");
+        }
+    }
+
+    return count;
+}
+
+int
+ly_print_iffeature(struct lyout *out, const struct lys_module *module, struct lys_iffeature *expr)
+{
+    int index_e = 0, index_f = 0;
+
+    if (expr->expr) {
+        return write_iff(out, module, expr, &index_e, &index_f);
+    }
+
+    return 0;
+}
+
+static int
 lys_print_(struct lyout *out, const struct lys_module *module, LYS_OUTFORMAT format, const char *target_node)
 {
     int ret;
diff --git a/src/printer.h b/src/printer.h
index 0df3080..cc67195 100644
--- a/src/printer.h
+++ b/src/printer.h
@@ -49,6 +49,7 @@
 int ly_print(struct lyout *out, const char *format, ...);
 void ly_print_flush(struct lyout *out);
 int ly_write(struct lyout *out, const char *buf, size_t count);
+int ly_print_iffeature(struct lyout *out, const struct lys_module *module, struct lys_iffeature *expr);
 
 int yang_print_model(struct lyout *out, const struct lys_module *module);
 int yin_print_model(struct lyout *out, const struct lys_module *module);
diff --git a/src/printer_info.c b/src/printer_info.c
index 3fc027a..58b225e 100644
--- a/src/printer_info.c
+++ b/src/printer_info.c
@@ -151,16 +151,20 @@
 }
 
 static void
-info_print_if_feature(struct lyout *out, struct lys_feature ** const features, uint8_t features_size)
+info_print_if_feature(struct lyout *out, const struct lys_module *module,
+                      struct lys_iffeature *iffeature, uint8_t iffeature_size)
 {
     int i;
 
     ly_print(out, "%-*s", INDENT_LEN, "If-feats: ");
 
-    if (features_size) {
-        ly_print(out, "%s\n", features[0]->name);
-        for (i = 1; i < features_size; ++i) {
-            ly_print(out, "%*s%s\n", INDENT_LEN, "", features[i]->name);
+    if (iffeature_size) {
+        ly_print_iffeature(out, module, &iffeature[0]);
+        ly_print(out, "\n");
+        for (i = 1; i < iffeature_size; ++i) {
+            ly_print(out, "%*s", INDENT_LEN, "");
+            ly_print_iffeature(out, module, &iffeature[i]);
+            ly_print(out, "\n");
         }
     } else {
         ly_print(out, "\n");
@@ -722,7 +726,7 @@
     info_print_text(out, feat->dsc, "Desc: ");
     info_print_text(out, feat->ref, "Reference: ");
     info_print_flags(out, feat->flags, LYS_STATUS_MASK | LYS_FENABLED, 0);
-    info_print_if_feature(out, feat->features, feat->features_size);
+    info_print_if_feature(out, feat->module, feat->iffeature, feat->iffeature_size);
 }
 
 static void
@@ -793,7 +797,7 @@
     info_print_text(out, cont->ref, "Reference: ");
     info_print_flags(out, cont->flags, LYS_CONFIG_MASK | LYS_STATUS_MASK | LYS_MAND_MASK, 0);
     info_print_text(out, cont->presence, "Presence: ");
-    info_print_if_feature(out, cont->features, cont->features_size);
+    info_print_if_feature(out, cont->module, cont->iffeature, cont->iffeature_size);
     info_print_when(out, cont->when);
     info_print_must(out, cont->must, cont->must_size);
     info_print_typedef(out, cont->tpdf, cont->tpdf_size);
@@ -818,7 +822,7 @@
     } else {
         ly_print(out, "\n");
     }
-    info_print_if_feature(out, choice->features, choice->features_size);
+    info_print_if_feature(out, choice->module, choice->iffeature, choice->iffeature_size);
     info_print_when(out, choice->when);
     info_print_nacmext(out, choice->nacm);
 
@@ -838,7 +842,7 @@
     info_print_text(out, leaf->type.der->name, "Type: ");
     info_print_text(out, leaf->units, "Units: ");
     info_print_text(out, leaf->dflt, "Default: ");
-    info_print_if_feature(out, leaf->features, leaf->features_size);
+    info_print_if_feature(out, leaf->module, leaf->iffeature, leaf->iffeature_size);
     info_print_when(out, leaf->when);
     info_print_must(out, leaf->must, leaf->must_size);
     info_print_nacmext(out, leaf->nacm);
@@ -857,7 +861,7 @@
     info_print_text(out, llist->type.der->name, "Type: ");
     info_print_text(out, llist->units, "Units: ");
     info_print_list_constr(out, llist->min, llist->max);
-    info_print_if_feature(out, llist->features, llist->features_size);
+    info_print_if_feature(out, llist->module, llist->iffeature, llist->iffeature_size);
     info_print_when(out, llist->when);
     info_print_must(out, llist->must, llist->must_size);
     info_print_nacmext(out, llist->nacm);
@@ -874,7 +878,7 @@
     info_print_text(out, list->ref, "Reference: ");
     info_print_flags(out, list->flags, LYS_CONFIG_MASK | LYS_STATUS_MASK | LYS_MAND_MASK | LYS_USERORDERED, 1);
     info_print_list_constr(out, list->min, list->max);
-    info_print_if_feature(out, list->features, list->features_size);
+    info_print_if_feature(out, list->module, list->iffeature, list->iffeature_size);
     info_print_when(out, list->when);
     info_print_must(out, list->must, list->must_size);
     info_print_keys(out, list->keys, list->keys_size);
@@ -895,7 +899,7 @@
     info_print_text(out, axml->dsc, "Desc: ");
     info_print_text(out, axml->ref, "Reference: ");
     info_print_flags(out, axml->flags, LYS_CONFIG_MASK | LYS_STATUS_MASK | LYS_MAND_MASK, 0);
-    info_print_if_feature(out, axml->features, axml->features_size);
+    info_print_if_feature(out, axml->module, axml->iffeature, axml->iffeature_size);
     info_print_when(out, axml->when);
     info_print_must(out, axml->must, axml->must_size);
     info_print_nacmext(out, axml->nacm);
@@ -927,7 +931,7 @@
     info_print_text(out, cas->dsc, "Desc: ");
     info_print_text(out, cas->ref, "Reference: ");
     info_print_flags(out, cas->flags, LYS_CONFIG_MASK | LYS_STATUS_MASK | LYS_MAND_MASK, 0);
-    info_print_if_feature(out, cas->features, cas->features_size);
+    info_print_if_feature(out, cas->module, cas->iffeature, cas->iffeature_size);
     info_print_when(out, cas->when);
     info_print_nacmext(out, cas->nacm);
 
@@ -937,7 +941,7 @@
 static void
 info_print_input(struct lyout *out, const struct lys_node *node)
 {
-    struct lys_node_rpc_inout *input = (struct lys_node_rpc_inout *)node;
+    struct lys_node_inout *input = (struct lys_node_inout *)node;
 
     assert(lys_parent(node) && lys_parent(node)->nodetype == LYS_RPC);
 
@@ -950,7 +954,7 @@
 static void
 info_print_output(struct lyout *out, const struct lys_node *node)
 {
-    struct lys_node_rpc_inout *output = (struct lys_node_rpc_inout *)node;
+    struct lys_node_inout *output = (struct lys_node_inout *)node;
 
     assert(lys_parent(node) && lys_parent(node)->nodetype == LYS_RPC);
 
@@ -970,7 +974,7 @@
     info_print_text(out, ntf->dsc, "Desc: ");
     info_print_text(out, ntf->ref, "Reference: ");
     info_print_flags(out, ntf->flags, LYS_STATUS_MASK, 0);
-    info_print_if_feature(out, ntf->features, ntf->features_size);
+    info_print_if_feature(out, ntf->module, ntf->iffeature, ntf->iffeature_size);
     info_print_typedef(out, ntf->tpdf, ntf->tpdf_size);
     info_print_nacmext(out, ntf->nacm);
 
@@ -980,20 +984,37 @@
 static void
 info_print_rpc(struct lyout *out, const struct lys_node *node)
 {
-    struct lys_node_rpc *rpc = (struct lys_node_rpc *)node;
+    struct lys_node_rpc_action *rpc = (struct lys_node_rpc_action *)node;
 
     ly_print(out, "%-*s%s\n", INDENT_LEN, "RPC: ", rpc->name);
     ly_print(out, "%-*s%s\n", INDENT_LEN, "Module: ", rpc->module->name);
     info_print_text(out, rpc->dsc, "Desc: ");
     info_print_text(out, rpc->ref, "Reference: ");
     info_print_flags(out, rpc->flags, LYS_STATUS_MASK, 0);
-    info_print_if_feature(out, rpc->features, rpc->features_size);
+    info_print_if_feature(out, rpc->module, rpc->iffeature, rpc->iffeature_size);
     info_print_typedef(out, rpc->tpdf, rpc->tpdf_size);
     info_print_nacmext(out, rpc->nacm);
 
     info_print_snode(out, (struct lys_node *)rpc, rpc->child, "Data:");
 }
 
+static void
+info_print_action(struct lyout *out, const struct lys_node *node)
+{
+    struct lys_node_rpc_action *act = (struct lys_node_rpc_action *)node;
+
+    ly_print(out, "%-*s%s\n", INDENT_LEN, "Action: ", act->name);
+    ly_print(out, "%-*s%s\n", INDENT_LEN, "Module: ", act->module->name);
+    info_print_text(out, act->dsc, "Desc: ");
+    info_print_text(out, act->ref, "Reference: ");
+    info_print_flags(out, act->flags, LYS_STATUS_MASK, 0);
+    info_print_if_feature(out, act->module, act->iffeature, act->iffeature_size);
+    info_print_typedef(out, act->tpdf, act->tpdf_size);
+    info_print_nacmext(out, act->nacm);
+
+    info_print_snode(out, (struct lys_node *)act, act->child, "Data:");
+}
+
 int
 info_print_model(struct lyout *out, const struct lys_module *module, const char *target_node)
 {
@@ -1129,6 +1150,9 @@
         case LYS_RPC:
             info_print_rpc(out, target);
             break;
+        case LYS_ACTION:
+            info_print_action(out, target);
+            break;
         case LYS_INPUT:
             info_print_input(out, target);
             break;
diff --git a/src/printer_tree.c b/src/printer_tree.c
index 4aaac6a..dbe46e0 100644
--- a/src/printer_tree.c
+++ b/src/printer_tree.c
@@ -39,7 +39,7 @@
 
     /* has a following printed child */
     LY_TREE_FOR((struct lys_node *)(including ? node : node->next), cur) {
-        if (module->type && (cur->module != module)) {
+        if (module != lys_node_module(cur)) {
             continue;
         }
 
@@ -89,7 +89,7 @@
     }
 
     /* next is a node that will actually be printed */
-    has_next = sibling_is_valid_child(node, 0, module);
+    has_next = sibling_is_valid_child(node, 0, lys_main_module(module));
 
     if (has_next && !next_is_case) {
         strcat(new_indent, "|  ");
@@ -145,20 +145,21 @@
 }
 
 static void
-tree_print_features(struct lyout *out, const struct lys_feature **features, uint8_t features_size)
+tree_print_features(struct lyout *out, const struct lys_module *module,
+                    struct lys_iffeature *iffeature, uint8_t iffeature_size)
 {
     int i;
 
-    if (!features_size) {
+    if (!iffeature_size) {
         return;
     }
 
     ly_print(out, " {");
-    for (i = 0; i < features_size; i++) {
+    for (i = 0; i < iffeature_size; i++) {
         if (i > 0) {
             ly_print(out, ",");
         }
-        ly_print(out, "%s", features[i]->name);
+        ly_print_iffeature(out, module, &iffeature[i]);
     }
     ly_print(out, "}?");
 }
@@ -223,7 +224,7 @@
 
     ly_print(out, "%s%s", cont->name, (cont->presence ? "!" : ""));
 
-    tree_print_features(out, (const struct lys_feature **)cont->features, cont->features_size);
+    tree_print_features(out, module, cont->iffeature, cont->iffeature_size);
 
     ly_print(out, "\n");
 
@@ -238,7 +239,7 @@
             continue;
         }
         tree_print_snode(out, module, level, new_indent, max_child_len, sub,
-                         LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYXML | LYS_USES,
+                         LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYXML | LYS_USES | LYS_ACTION,
                          spec_config);
     }
 
@@ -281,7 +282,7 @@
         ly_print(out, " <%s>", choice->dflt->name);
     }
 
-    tree_print_features(out, (const struct lys_feature **)choice->features, choice->features_size);
+    tree_print_features(out, module, choice->iffeature, choice->iffeature_size);
 
     ly_print(out, "\n");
 
@@ -322,7 +323,7 @@
 
     ly_print(out, "%s)", cas->name);
 
-    tree_print_features(out, (const struct lys_feature **)cas->features, cas->features_size);
+    tree_print_features(out, module, cas->iffeature, cas->iffeature_size);
 
     ly_print(out, "\n");
 
@@ -379,7 +380,7 @@
     ly_print(out, "%s%s%*sanyxml", anyxml->name, (anyxml->flags & LYS_MAND_TRUE ? " " : "?"),
             3 + (int)((max_name_len - strlen(anyxml->name)) - prefix_len), "   ");
 
-    tree_print_features(out, (const struct lys_feature **)anyxml->features, anyxml->features_size);
+    tree_print_features(out, module, anyxml->iffeature, anyxml->iffeature_size);
 
     ly_print(out, "\n");
 }
@@ -437,7 +438,7 @@
         ly_print(out, " <%s>", leaf->dflt);
     }
 
-    tree_print_features(out, (const struct lys_feature **)leaf->features, leaf->features_size);
+    tree_print_features(out, module, leaf->iffeature, leaf->iffeature_size);
 
     ly_print(out, "\n");
 }
@@ -471,7 +472,7 @@
 
     tree_print_type(out, &leaflist->type);
 
-    tree_print_features(out, (const struct lys_feature **)leaflist->features, leaflist->features_size);
+    tree_print_features(out, module, leaflist->iffeature, leaflist->iffeature_size);
 
     ly_print(out, "\n");
 }
@@ -512,7 +513,7 @@
         ly_print(out, "%s%s", list->keys[i]->name, i + 1 < list->keys_size ? " " : "]");
     }
 
-    tree_print_features(out, (const struct lys_feature **)list->features, list->features_size);
+    tree_print_features(out, module, list->iffeature, list->iffeature_size);
 
     ly_print(out, "\n");
 
@@ -527,7 +528,7 @@
             continue;
         }
         tree_print_snode(out, module, level, new_indent, max_child_len, sub,
-                         LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ANYXML,
+                         LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ANYXML | LYS_ACTION,
                          spec_config);
     }
 
@@ -548,12 +549,12 @@
 }
 
 static void
-tree_print_rpc(struct lyout *out, const struct lys_module *module, int level, char *indent,
-               const struct lys_node *node)
+tree_print_rpc_action(struct lyout *out, const struct lys_module *module, int level, char *indent,
+                      const struct lys_node *node)
 {
     char *new_indent;
     struct lys_node *sub;
-    struct lys_node_rpc *rpc = (struct lys_node_rpc *)node;
+    struct lys_node_rpc_action *rpc = (struct lys_node_rpc_action *)node;
 
     if (lys_is_disabled(node, 0)) {
         return;
@@ -562,7 +563,7 @@
     ly_print(out, "%s%s---x %s", indent,
             (rpc->flags & LYS_STATUS_DEPRC ? "x" : (rpc->flags & LYS_STATUS_OBSLT ? "o" : "+")), rpc->name);
 
-    tree_print_features(out, (const struct lys_feature **)rpc->features, rpc->features_size);
+    tree_print_features(out, module, rpc->iffeature, rpc->iffeature_size);
 
     ly_print(out, "\n");
 
@@ -601,7 +602,7 @@
             (notif->flags & LYS_STATUS_DEPRC ? "x" : (notif->flags & LYS_STATUS_OBSLT ? "o" : "+")),
             notif->name);
 
-    tree_print_features(out, (const struct lys_feature **)notif->features, notif->features_size);
+    tree_print_features(out, module, notif->iffeature, notif->iffeature_size);
 
     ly_print(out, "\n");
 
@@ -670,6 +671,9 @@
     case LYS_USES:
         tree_print_uses(out, module, level, indent, max_name_len, node, spec_config);
         break;
+    case LYS_ACTION:
+        tree_print_rpc_action(out, module, level, indent, node);
+        break;
     case LYS_CASE:
         /* a very special case of cases in an augment */
         tree_print_case(out, module, level, indent, max_name_len, node, 0, spec_config);
@@ -760,7 +764,7 @@
                 break;
             }
             if (node->nodetype == LYS_RPC) {
-                tree_print_rpc(out, module, level, indent, node);
+                tree_print_rpc_action(out, module, level, indent, node);
                 have_rpcs--;
             }
         }
diff --git a/src/printer_xml.c b/src/printer_xml.c
index 7e4478a..0146a22 100644
--- a/src/printer_xml.c
+++ b/src/printer_xml.c
@@ -378,6 +378,7 @@
     switch (node->schema->nodetype) {
     case LYS_NOTIF:
     case LYS_RPC:
+    case LYS_ACTION:
     case LYS_CONTAINER:
         xml_print_container(out, level, node, toplevel);
         break;
@@ -402,15 +403,42 @@
 int
 xml_print_data(struct lyout *out, const struct lyd_node *root, int options)
 {
-    const struct lyd_node *node;
+    const struct lyd_node *node, *next;
+    int level, action = 0;
+
+    assert(root);
+
+    level = (options & LYP_FORMAT ? 1 : 0);
+
+    /* learn whether we are printing an action first */
+    LY_TREE_DFS_BEGIN(root, next, node) {
+        if (node->schema->nodetype == LYS_ACTION) {
+            action = 1;
+            break;
+        }
+        LY_TREE_DFS_END(root, next, node);
+    }
+
+    if (action) {
+        ly_print(out, "%*s<action xmlns=\"urn:ietf:params:xml:ns:yang:1\">%s", LEVEL, INDENT, level ? "\n" : "");
+        if (level) {
+            ++level;
+        }
+    }
 
     /* content */
     LY_TREE_FOR(root, node) {
-        xml_print_node(out, (options & LYP_FORMAT ? 1 : 0), node, 1);
+        xml_print_node(out, level, node, 1);
         if (!(options & LYP_WITHSIBLINGS)) {
             break;
         }
     }
+
+    if (action) {
+        --level;
+        ly_print(out, "%*s</action>%s", LEVEL, INDENT, level ? "\n" : "");
+    }
+
     ly_print_flush(out);
 
     return EXIT_SUCCESS;
diff --git a/src/printer_yang.c b/src/printer_yang.c
index afd1001..0ebc2d5 100644
--- a/src/printer_yang.c
+++ b/src/printer_yang.c
@@ -234,16 +234,11 @@
 }
 
 static void
-yang_print_iffeature(struct lyout *out, int level, const struct lys_module *module, const struct lys_feature *feat)
+yang_print_iffeature(struct lyout *out, int level, const struct lys_module *module, struct lys_iffeature *iffeature)
 {
-    struct lys_module *mod;
-
-    ly_print(out, "%*sif-feature ", LEVEL, INDENT);
-    mod = lys_main_module(feat->module);
-    if (lys_main_module(module) != mod) {
-        ly_print(out, "%s:", transform_module_name2import_prefix(module, mod->name));
-    }
-    ly_print(out, "%s;\n", feat->name);
+    ly_print(out, "%*sif-feature \"", LEVEL, INDENT);
+    ly_print_iffeature(out, module, iffeature);
+    ly_print(out, "\";\n");
 }
 
 static void
@@ -255,9 +250,9 @@
     level++;
 
     yang_print_snode_common(out, level, (struct lys_node *)feat, &flag);
-    for (i = 0; i < feat->features_size; ++i) {
+    for (i = 0; i < feat->iffeature_size; ++i) {
         yang_print_open(out, &flag);
-        yang_print_iffeature(out, level, feat->module, feat->features[i]);
+        yang_print_iffeature(out, level, feat->module, &feat->iffeature[i]);
     }
 
     level--;
@@ -655,8 +650,8 @@
     yang_print_nacmext(out, level, (struct lys_node *)augment, module, NULL);
     yang_print_snode_common(out, level, (struct lys_node *)augment, NULL);
 
-    for (i = 0; i < augment->features_size; i++) {
-        yang_print_iffeature(out, level, module, augment->features[i]);
+    for (i = 0; i < augment->iffeature_size; i++) {
+        yang_print_iffeature(out, level, module, &augment->iffeature[i]);
     }
 
     if (augment->when) {
@@ -670,7 +665,7 @@
         }
         yang_print_snode(out, level, sub,
                          LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST |
-                         LYS_USES | LYS_ANYXML | LYS_CASE);
+                         LYS_USES | LYS_ANYXML | LYS_CASE | LYS_ACTION);
     }
 
     level--;
@@ -738,9 +733,9 @@
         yang_print_when(out, level, node->module, cont->when);
     }
 
-    for (i = 0; i < cont->features_size; i++) {
+    for (i = 0; i < cont->iffeature_size; i++) {
         yang_print_open(out, &flag);
-        yang_print_iffeature(out, level, node->module, cont->features[i]);
+        yang_print_iffeature(out, level, node->module, &cont->iffeature[i]);
     }
 
     for (i = 0; i < cont->must_size; i++) {
@@ -768,7 +763,7 @@
         yang_print_open(out, &flag);
         yang_print_snode(out, level, sub,
                          LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST |
-                         LYS_USES | LYS_GROUPING | LYS_ANYXML);
+                         LYS_USES | LYS_GROUPING | LYS_ANYXML | LYS_ACTION);
     }
 
     level--;
@@ -787,8 +782,8 @@
     yang_print_nacmext(out, level, node, node->module, NULL);
     yang_print_snode_common2(out, level, node, NULL);
 
-    for (i = 0; i < cas->features_size; i++) {
-        yang_print_iffeature(out, level, node->module, cas->features[i]);
+    for (i = 0; i < cas->iffeature_size; i++) {
+        yang_print_iffeature(out, level, node->module, &cas->iffeature[i]);
     }
 
     if (cas->when) {
@@ -826,8 +821,8 @@
 
     yang_print_snode_common2(out, level, node, NULL);
 
-    for (i = 0; i < choice->features_size; i++) {
-        yang_print_iffeature(out, level, node->module, choice->features[i]);
+    for (i = 0; i < choice->iffeature_size; i++) {
+        yang_print_iffeature(out, level, node->module, &choice->iffeature[i]);
     }
 
     if (choice->when) {
@@ -859,8 +854,8 @@
     if (leaf->when) {
         yang_print_when(out, level, node->module, leaf->when);
     }
-    for (i = 0; i < leaf->features_size; i++) {
-        yang_print_iffeature(out, level, node->module, leaf->features[i]);
+    for (i = 0; i < leaf->iffeature_size; i++) {
+        yang_print_iffeature(out, level, node->module, &leaf->iffeature[i]);
     }
     for (i = 0; i < leaf->must_size; i++) {
         yang_print_must(out, level, node->module, &leaf->must[i]);
@@ -888,9 +883,9 @@
     level++;
     yang_print_nacmext(out, level, node, node->module, &flag);
     yang_print_snode_common2(out, level, node, &flag);
-    for (i = 0; i < anyxml->features_size; i++) {
+    for (i = 0; i < anyxml->iffeature_size; i++) {
         yang_print_open(out, &flag);
-        yang_print_iffeature(out, level, node->module, anyxml->features[i]);
+        yang_print_iffeature(out, level, node->module, &anyxml->iffeature[i]);
     }
     for (i = 0; i < anyxml->must_size; i++) {
         yang_print_open(out, &flag);
@@ -917,8 +912,8 @@
     if (llist->when) {
         yang_print_when(out, level, llist->module, llist->when);
     }
-    for (i = 0; i < llist->features_size; i++) {
-        yang_print_iffeature(out, level, node->module, llist->features[i]);
+    for (i = 0; i < llist->iffeature_size; i++) {
+        yang_print_iffeature(out, level, node->module, &llist->iffeature[i]);
     }
     for (i = 0; i < llist->must_size; i++) {
         yang_print_must(out, level, node->module, &llist->must[i]);
@@ -955,8 +950,8 @@
     if (list->when) {
         yang_print_when(out, level, list->module, list->when);
     }
-    for (i = 0; i < list->features_size; i++) {
-        yang_print_iffeature(out, level, node->module, list->features[i]);
+    for (i = 0; i < list->iffeature_size; i++) {
+        yang_print_iffeature(out, level, node->module, &list->iffeature[i]);
     }
     for (i = 0; i < list->must_size; i++) {
         yang_print_must(out, level, list->module, &list->must[i]);
@@ -992,7 +987,7 @@
         }
         yang_print_snode(out, level, sub,
                          LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST |
-                         LYS_USES | LYS_GROUPING | LYS_ANYXML);
+                         LYS_USES | LYS_GROUPING | LYS_ANYXML | LYS_ACTION);
     }
     level--;
     ly_print(out, "%*s}\n", LEVEL, INDENT);
@@ -1017,7 +1012,7 @@
     LY_TREE_FOR(node->child, sub) {
         yang_print_snode(out, level, sub,
                          LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST |
-                         LYS_USES | LYS_GROUPING | LYS_ANYXML);
+                         LYS_USES | LYS_GROUPING | LYS_ANYXML | LYS_ACTION);
     }
 
     level--;
@@ -1043,9 +1038,9 @@
 
     yang_print_nacmext(out, level, node, node->module, &flag);
     yang_print_snode_common(out, level, node, &flag);
-    for (i = 0; i < uses->features_size; i++) {
+    for (i = 0; i < uses->iffeature_size; i++) {
         yang_print_open(out, &flag);
-        yang_print_iffeature(out, level, node->module, uses->features[i]);
+        yang_print_iffeature(out, level, node->module, &uses->iffeature[i]);
     }
     if (uses->when) {
         yang_print_open(out, &flag);
@@ -1071,7 +1066,7 @@
 {
     int i;
     struct lys_node *sub;
-    struct lys_node_rpc_inout *inout = (struct lys_node_rpc_inout *)node;
+    struct lys_node_inout *inout = (struct lys_node_inout *)node;
 
     ly_print(out, "%*s%s {\n", LEVEL, INDENT, (inout->nodetype == LYS_INPUT ? "input" : "output"));
 
@@ -1095,20 +1090,20 @@
 }
 
 static void
-yang_print_rpc(struct lyout *out, int level, const struct lys_node *node)
+yang_print_rpc_action(struct lyout *out, int level, const struct lys_node *node)
 {
     int i, flag = 0;
     struct lys_node *sub;
-    struct lys_node_rpc *rpc = (struct lys_node_rpc *)node;
+    struct lys_node_rpc_action *rpc = (struct lys_node_rpc_action *)node;
 
-    ly_print(out, "%*srpc %s", LEVEL, INDENT, node->name);
+    ly_print(out, "%*s%s %s", LEVEL, INDENT, (node->nodetype == LYS_RPC ? "rpc" : "action"), node->name);
 
     level++;
     yang_print_snode_common(out, level, node, &flag);
 
-    for (i = 0; i < rpc->features_size; i++) {
+    for (i = 0; i < rpc->iffeature_size; i++) {
         yang_print_open(out, &flag);
-        yang_print_iffeature(out, level, node->module, rpc->features[i]);
+        yang_print_iffeature(out, level, node->module, &rpc->iffeature[i]);
     }
 
     for (i = 0; i < rpc->tpdf_size; i++) {
@@ -1141,9 +1136,9 @@
     level++;
     yang_print_snode_common(out, level, node, &flag);
 
-    for (i = 0; i < notif->features_size; i++) {
+    for (i = 0; i < notif->iffeature_size; i++) {
         yang_print_open(out, &flag);
-        yang_print_iffeature(out, level, node->module, notif->features[i]);
+        yang_print_iffeature(out, level, node->module, &notif->iffeature[i]);
     }
 
     for (i = 0; i < notif->tpdf_size; i++) {
@@ -1197,6 +1192,9 @@
     case LYS_CASE:
         yang_print_case(out, level, node);
         break;
+    case LYS_ACTION:
+        yang_print_rpc_action(out, level, node);
+        break;
     case LYS_INPUT:
     case LYS_OUTPUT:
         yang_print_input_output(out, level, node);
@@ -1337,7 +1335,7 @@
         ly_print(out, "\n");
         switch(node->nodetype) {
         case LYS_RPC:
-            yang_print_rpc(out, level, node);
+            yang_print_rpc_action(out, level, node);
             break;
         case LYS_NOTIF:
             yang_print_notif(out, level, node);
diff --git a/src/printer_yin.c b/src/printer_yin.c
index 2f3e479..a36a2c0 100644
--- a/src/printer_yin.c
+++ b/src/printer_yin.c
@@ -221,16 +221,11 @@
 }
 
 static void
-yin_print_iffeature(struct lyout *out, int level, const struct lys_module *module, const struct lys_feature *feat)
+yin_print_iffeature(struct lyout *out, int level, const struct lys_module *module, struct lys_iffeature *iffeature)
 {
-    struct lys_module *mod;
-
     ly_print(out, "%*s<if-feature name=\"", LEVEL, INDENT);
-    mod = lys_main_module(feat->module);
-    if (lys_main_module(module) != mod) {
-        ly_print(out, "%s:", transform_module_name2import_prefix(module, mod->name));
-    }
-    ly_print(out, "%s\"/>\n", feat->name);
+    ly_print_iffeature(out, module, iffeature);
+    ly_print(out, "\"/>\n");
 }
 
 static void
@@ -238,15 +233,15 @@
 {
     int i, close;
 
-    close = (yin_has_snode_common((struct lys_node *)feat) || feat->features_size ? 0 : 1);
+    close = (yin_has_snode_common((struct lys_node *)feat) || feat->iffeature_size ? 0 : 1);
 
     yin_print_open(out, level, "feature", "name", feat->name, close);
 
     if (!close) {
         level++;
         yin_print_snode_common(out, level, (struct lys_node *)feat);
-        for (i = 0; i < feat->features_size; ++i) {
-            yin_print_iffeature(out, level, feat->module, feat->features[i]);
+        for (i = 0; i < feat->iffeature_size; ++i) {
+            yin_print_iffeature(out, level, feat->module, &feat->iffeature[i]);
         }
         level--;
 
@@ -672,8 +667,8 @@
     yin_print_nacmext(out, level, (struct lys_node *)augment, module);
     yin_print_snode_common(out, level, (struct lys_node *)augment);
 
-    for (i = 0; i < augment->features_size; i++) {
-        yin_print_iffeature(out, level, module, augment->features[i]);
+    for (i = 0; i < augment->iffeature_size; i++) {
+        yin_print_iffeature(out, level, module, &augment->iffeature[i]);
     }
 
     if (augment->when) {
@@ -687,7 +682,7 @@
         }
         yin_print_snode(out, level, sub,
                         LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST |
-                        LYS_USES | LYS_ANYXML | LYS_CASE);
+                        LYS_USES | LYS_ANYXML | LYS_CASE | LYS_ACTION);
     }
     level--;
 
@@ -756,8 +751,8 @@
         yin_print_when(out, level, node->module, cont->when);
     }
 
-    for (i = 0; i < cont->features_size; i++) {
-        yin_print_iffeature(out, level, node->module, cont->features[i]);
+    for (i = 0; i < cont->iffeature_size; i++) {
+        yin_print_iffeature(out, level, node->module, &cont->iffeature[i]);
     }
 
     for (i = 0; i < cont->must_size; i++) {
@@ -781,7 +776,7 @@
         }
         yin_print_snode(out, level, sub,
                         LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST |
-                        LYS_USES | LYS_GROUPING | LYS_ANYXML);
+                        LYS_USES | LYS_GROUPING | LYS_ANYXML | LYS_ACTION);
     }
     level--;
 
@@ -801,8 +796,8 @@
     yin_print_nacmext(out, level, node, node->module);
     yin_print_snode_common2(out, level, node);
 
-    for (i = 0; i < cas->features_size; i++) {
-        yin_print_iffeature(out, level, node->module, cas->features[i]);
+    for (i = 0; i < cas->iffeature_size; i++) {
+        yin_print_iffeature(out, level, node->module, &cas->iffeature[i]);
     }
 
     if (cas->when) {
@@ -840,8 +835,8 @@
 
     yin_print_snode_common2(out, level, node);
 
-    for (i = 0; i < choice->features_size; i++) {
-        yin_print_iffeature(out, level, node->module, choice->features[i]);
+    for (i = 0; i < choice->iffeature_size; i++) {
+        yin_print_iffeature(out, level, node->module, &choice->iffeature[i]);
     }
 
     if (choice->when) {
@@ -874,8 +869,8 @@
     if (leaf->when) {
         yin_print_when(out, level, node->module, leaf->when);
     }
-    for (i = 0; i < leaf->features_size; i++) {
-        yin_print_iffeature(out, level, node->module, leaf->features[i]);
+    for (i = 0; i < leaf->iffeature_size; i++) {
+        yin_print_iffeature(out, level, node->module, &leaf->iffeature[i]);
     }
     for (i = 0; i < leaf->must_size; i++) {
         yin_print_must(out, level, node->module, &leaf->must[i]);
@@ -899,7 +894,7 @@
     int i, close;
     struct lys_node_anyxml *anyxml = (struct lys_node_anyxml *)node;
 
-    close = (yin_has_nacmext(node) || yin_has_snode_common2(node) || anyxml->features_size || anyxml->must_size
+    close = (yin_has_nacmext(node) || yin_has_snode_common2(node) || anyxml->iffeature_size || anyxml->must_size
             || anyxml->when ? 0 : 1);
 
     yin_print_open(out, level, "anyxml", "name", anyxml->name, close);
@@ -908,8 +903,8 @@
         level++;
         yin_print_nacmext(out, level, node, node->module);
         yin_print_snode_common2(out, level, node);
-        for (i = 0; i < anyxml->features_size; i++) {
-            yin_print_iffeature(out, level, node->module, anyxml->features[i]);
+        for (i = 0; i < anyxml->iffeature_size; i++) {
+            yin_print_iffeature(out, level, node->module, &anyxml->iffeature[i]);
         }
         for (i = 0; i < anyxml->must_size; i++) {
             yin_print_must(out, level, node->module, &anyxml->must[i]);
@@ -936,8 +931,8 @@
     if (llist->when) {
         yin_print_when(out, level, llist->module, llist->when);
     }
-    for (i = 0; i < llist->features_size; i++) {
-        yin_print_iffeature(out, level, node->module, llist->features[i]);
+    for (i = 0; i < llist->iffeature_size; i++) {
+        yin_print_iffeature(out, level, node->module, &llist->iffeature[i]);
     }
     for (i = 0; i < llist->must_size; i++) {
         yin_print_must(out, level, node->module, &llist->must[i]);
@@ -975,8 +970,8 @@
     if (list->when) {
         yin_print_when(out, level, list->module, list->when);
     }
-    for (i = 0; i < list->features_size; i++) {
-        yin_print_iffeature(out, level, node->module, list->features[i]);
+    for (i = 0; i < list->iffeature_size; i++) {
+        yin_print_iffeature(out, level, node->module, &list->iffeature[i]);
     }
     for (i = 0; i < list->must_size; i++) {
         yin_print_must(out, level, list->module, &list->must[i]);
@@ -1012,7 +1007,7 @@
         }
         yin_print_snode(out, level, sub,
                         LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST |
-                        LYS_USES | LYS_GROUPING | LYS_ANYXML);
+                        LYS_USES | LYS_GROUPING | LYS_ANYXML | LYS_ACTION);
     }
     level--;
 
@@ -1038,7 +1033,7 @@
     LY_TREE_FOR(node->child, sub) {
         yin_print_snode(out, level, sub,
                         LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST |
-                        LYS_USES | LYS_GROUPING | LYS_ANYXML);
+                        LYS_USES | LYS_GROUPING | LYS_ANYXML | LYS_ACTION);
     }
     level--;
 
@@ -1052,7 +1047,7 @@
     struct lys_node_uses *uses = (struct lys_node_uses *)node;
     struct lys_module *mod;
 
-    close = (yin_has_nacmext(node) || yin_has_snode_common(node) || uses->features_size || uses->when
+    close = (yin_has_nacmext(node) || yin_has_snode_common(node) || uses->iffeature_size || uses->when
             || uses->refine_size || uses->augment_size ? 0 : 1);
 
     ly_print(out, "%*s<uses name=\"", LEVEL, INDENT);
@@ -1068,8 +1063,8 @@
         level++;
         yin_print_nacmext(out, level, node, node->module);
         yin_print_snode_common(out, level, node);
-        for (i = 0; i < uses->features_size; i++) {
-            yin_print_iffeature(out, level, node->module, uses->features[i]);
+        for (i = 0; i < uses->iffeature_size; i++) {
+            yin_print_iffeature(out, level, node->module, &uses->iffeature[i]);
         }
         if (uses->when) {
             yin_print_when(out, level, node->module, uses->when);
@@ -1093,7 +1088,7 @@
 {
     int i;
     struct lys_node *sub;
-    struct lys_node_rpc_inout *inout = (struct lys_node_rpc_inout *)node;
+    struct lys_node_inout *inout = (struct lys_node_inout *)node;
 
     ly_print(out, "%*s<%s>\n", LEVEL, INDENT, (inout->nodetype == LYS_INPUT ? "input" : "output"));
 
@@ -1117,22 +1112,22 @@
 }
 
 static void
-yin_print_rpc(struct lyout *out, int level, const struct lys_node *node)
+yin_print_rpc_action(struct lyout *out, int level, const struct lys_node *node)
 {
     int i, close;
     struct lys_node *sub;
-    struct lys_node_rpc *rpc = (struct lys_node_rpc *)node;
+    struct lys_node_rpc_action *rpc = (struct lys_node_rpc_action *)node;
 
-    close = (yin_has_snode_common(node) || rpc->features_size || rpc->tpdf_size || node->child ? 0 : 1);
+    close = (yin_has_snode_common(node) || rpc->iffeature_size || rpc->tpdf_size || node->child ? 0 : 1);
 
-    yin_print_open(out, level, "rpc", "name", node->name, close);
+    yin_print_open(out, level, (node->nodetype == LYS_RPC ? "rpc" : "action"), "name", node->name, close);
 
     if (!close) {
         level++;
         yin_print_snode_common(out, level, node);
 
-        for (i = 0; i < rpc->features_size; i++) {
-            yin_print_iffeature(out, level, node->module, rpc->features[i]);
+        for (i = 0; i < rpc->iffeature_size; i++) {
+            yin_print_iffeature(out, level, node->module, &rpc->iffeature[i]);
         }
 
         for (i = 0; i < rpc->tpdf_size; i++) {
@@ -1148,7 +1143,7 @@
         }
         level--;
 
-        yin_print_close(out, level, "rpc");
+        yin_print_close(out, level, (node->nodetype == LYS_RPC ? "rpc" : "action"));
     }
 }
 
@@ -1159,7 +1154,7 @@
     struct lys_node *sub;
     struct lys_node_notif *notif = (struct lys_node_notif *)node;
 
-    close = (yin_has_snode_common(node) || notif->features_size || notif->tpdf_size || node->child ? 0 : 1);
+    close = (yin_has_snode_common(node) || notif->iffeature_size || notif->tpdf_size || node->child ? 0 : 1);
 
     yin_print_open(out, level, "notification", "name", node->name, close);
 
@@ -1167,8 +1162,8 @@
         level++;
         yin_print_snode_common(out, level, node);
 
-        for (i = 0; i < notif->features_size; i++) {
-            yin_print_iffeature(out, level, node->module, notif->features[i]);
+        for (i = 0; i < notif->iffeature_size; i++) {
+            yin_print_iffeature(out, level, node->module, &notif->iffeature[i]);
         }
 
         for (i = 0; i < notif->tpdf_size; i++) {
@@ -1221,6 +1216,9 @@
     case LYS_CASE:
         yin_print_case(out, level, node);
         break;
+    case LYS_ACTION:
+        yin_print_rpc_action(out, level, node);
+        break;
     case LYS_INPUT:
     case LYS_OUTPUT:
         yin_print_input_output(out, level, node);
@@ -1390,7 +1388,7 @@
 
         switch (node->nodetype) {
         case LYS_RPC:
-            yin_print_rpc(out, level, node);
+            yin_print_rpc_action(out, level, node);
             break;
         case LYS_NOTIF:
             yin_print_notif(out, level, node);
diff --git a/src/resolve.c b/src/resolve.c
index 2711f52..cf27b89 100644
--- a/src/resolve.c
+++ b/src/resolve.c
@@ -955,6 +955,448 @@
 }
 
 /**
+ * @brief Resolve (find) a feature definition. Logs directly.
+ *
+ * @param[in] feat_name Feature name to resolve.
+ * @param[in] len Length of \p feat_name.
+ * @param[in] node Node with the if-feature expression.
+ * @param[out] feature Pointer to be set to point to the feature definition, if feature not found
+ * (return code 1), the pointer is untouched.
+ *
+ * @return 0 on success, 1 on forward reference, -1 on error.
+ */
+static int
+resolve_feature(const char *feat_name, uint16_t len, const struct lys_node *node, struct lys_feature **feature)
+{
+    char *str;
+    const char *mod_name, *name;
+    int mod_name_len, nam_len, i, j;
+    const struct lys_module *module;
+
+    assert(feature);
+
+    /* check prefix */
+    if ((i = parse_node_identifier(feat_name, &mod_name, &mod_name_len, &name, &nam_len)) < 1) {
+        LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, feat_name[-i], &feat_name[-i]);
+        return -1;
+    }
+
+    module = lys_get_import_module(lys_node_module(node), NULL, 0, mod_name, mod_name_len);
+    if (!module) {
+        /* identity refers unknown data model */
+        LOGVAL(LYE_INMOD_LEN, LY_VLOG_NONE, NULL, mod_name_len, mod_name);
+        return -1;
+    }
+
+    if (module != node->module && module == lys_node_module(node)) {
+        /* first, try to search directly in submodule where the feature was mentioned */
+        for (j = 0; j < node->module->features_size; j++) {
+            if (!strncmp(name, node->module->features[j].name, nam_len) && !node->module->features[j].name[nam_len]) {
+                /* check status */
+                if (lyp_check_status(node->flags, lys_node_module(node), node->name, node->module->features[j].flags,
+                                     node->module->features[j].module, node->module->features[j].name, node)) {
+                    return -1;
+                }
+                *feature = &node->module->features[j];
+                return 0;
+            }
+        }
+    }
+
+    /* search in the identified module ... */
+    for (j = 0; j < module->features_size; j++) {
+        if (!strncmp(name, module->features[j].name, nam_len) && !module->features[j].name[nam_len]) {
+            /* check status */
+            if (lyp_check_status(node->flags, lys_node_module(node), node->name, module->features[j].flags,
+                                 module->features[j].module, module->features[j].name, node)) {
+                return -1;
+            }
+            *feature = &module->features[j];
+            return 0;
+        }
+    }
+    /* ... and all its submodules */
+    for (i = 0; i < module->inc_size; i++) {
+        if (!module->inc[i].submodule) {
+            /* not yet resolved */
+            continue;
+        }
+        for (j = 0; j < module->inc[i].submodule->features_size; j++) {
+            if (!strncmp(name, module->inc[i].submodule->features[j].name, nam_len)
+                    && !module->inc[i].submodule->features[j].name[nam_len]) {
+                /* check status */
+                if (lyp_check_status(node->flags, lys_node_module(node), node->name,
+                                     module->inc[i].submodule->features[j].flags,
+                                     module->inc[i].submodule->features[j].module,
+                                     module->inc[i].submodule->features[j].name, node)) {
+                    return -1;
+                }
+                *feature = &module->inc[i].submodule->features[j];
+                return 0;
+            }
+        }
+    }
+
+    /* not found */
+    str = strndup(feat_name, len);
+    LOGVAL(LYE_INRESOLV, LY_VLOG_NONE, NULL, "feature", str);
+    free(str);
+    return 1;
+}
+
+/*
+ * @return
+ *  -  0 if enabled
+ *  -  1 if disabled
+ *  - -1 if not usable by its if-feature expression
+ */
+static int
+resolve_feature_value(const struct lys_feature *feat)
+{
+    int i;
+
+    for (i = 0; i < feat->iffeature_size; i++) {
+        if (resolve_iffeature(&feat->iffeature[i])) {
+            return -1;
+        }
+    }
+
+    return feat->flags & LYS_FENABLED ? 0 : 1;
+}
+
+static int
+resolve_iffeature_recursive(struct lys_iffeature *expr, int *index_e, int *index_f)
+{
+    uint8_t op;
+    int rc, a, b;
+
+    op = iff_getop(expr->expr, *index_e);
+    (*index_e)++;
+
+    switch (op) {
+    case LYS_IFF_F:
+        /* resolve feature */
+        return resolve_feature_value(expr->features[(*index_f)++]);
+    case LYS_IFF_NOT:
+        rc = resolve_iffeature_recursive(expr, index_e, index_f);
+        if (rc == -1) {
+            /* one of the referenced feature is hidden by its if-feature,
+             * so this if-feature expression is always false */
+            return -1;
+        } else {
+            /* invert result */
+            return rc ? 0 : 1;
+        }
+    case LYS_IFF_AND:
+    case LYS_IFF_OR:
+        a = resolve_iffeature_recursive(expr, index_e, index_f);
+        b = resolve_iffeature_recursive(expr, index_e, index_f);
+        if (a == -1 || b == -1) {
+            /* one of the referenced feature is hidden by its if-feature,
+             * so this if-feature expression is always false */
+            return -1;
+        } else if (op == LYS_IFF_AND) {
+            return a && b;
+        } else { /* LYS_IFF_OR */
+            return a || b;
+        }
+    }
+
+    return -1;
+}
+
+int
+resolve_iffeature(struct lys_iffeature *expr)
+{
+    int rc = -1;
+    int index_e = 0, index_f = 0;
+
+    if (expr->expr) {
+        rc = resolve_iffeature_recursive(expr, &index_e, &index_f);
+    }
+    return (rc == 0) ? 0 : 1;
+}
+
+struct iff_stack {
+    int size;
+    int index;     /* first empty item */
+    uint8_t *stack;
+};
+
+static int
+iff_stack_push(struct iff_stack *stack, uint8_t value)
+{
+    if (stack->index == stack->size) {
+        stack->size += 4;
+        stack->stack = ly_realloc(stack->stack, stack->size * sizeof *stack->stack);
+        if (!stack->stack) {
+            LOGMEM;
+            stack->size = 0;
+            return EXIT_FAILURE;
+        }
+    }
+
+    stack->stack[stack->index++] = value;
+    return EXIT_SUCCESS;
+}
+
+static uint8_t
+iff_stack_pop(struct iff_stack *stack)
+{
+    stack->index--;
+    return stack->stack[stack->index];
+}
+
+static void
+iff_stack_clean(struct iff_stack *stack)
+{
+    stack->size = 0;
+    free(stack->stack);
+}
+
+static void
+iff_setop(uint8_t *list, uint8_t op, int pos)
+{
+    uint8_t *item;
+    uint8_t mask = 3;
+
+    assert(pos >= 0);
+    assert(op <= 3); /* max 2 bits */
+
+    item = &list[pos / 4];
+    mask = mask << 2 * (pos % 4);
+    *item = (*item) & ~mask;
+    *item = (*item) | (op << 2 * (pos % 4));
+}
+
+uint8_t
+iff_getop(uint8_t *list, int pos)
+{
+    uint8_t *item;
+    uint8_t mask = 3, result;
+
+    assert(pos >= 0);
+
+    item = &list[pos / 4];
+    result = (*item) & (mask << 2 * (pos % 4));
+    return result >> 2 * (pos % 4);
+}
+
+#define LYS_IFF_LP 0x04 /* ( */
+#define LYS_IFF_RP 0x08 /* ) */
+
+void
+resolve_iffeature_getsizes(struct lys_iffeature *iffeat, unsigned int *expr_size, unsigned int *feat_size)
+{
+    unsigned int e = 0, f = 0, r = 0;
+    uint8_t op;
+
+    assert(iffeat);
+
+    if (!iffeat->expr) {
+        goto result;
+    }
+
+    do {
+        op = iff_getop(iffeat->expr, e++);
+        switch (op) {
+        case LYS_IFF_NOT:
+            if (!r) {
+                r += 1;
+            }
+            break;
+        case LYS_IFF_AND:
+        case LYS_IFF_OR:
+            if (!r) {
+                r += 2;
+            } else {
+                r += 1;
+            }
+            break;
+        case LYS_IFF_F:
+            f++;
+            if (r) {
+                r--;
+            }
+            break;
+        }
+    } while(r);
+
+result:
+    if (expr_size) {
+        *expr_size = e;
+    }
+    if (feat_size) {
+        *feat_size = f;
+    }
+}
+
+int
+resolve_iffeature_compile(struct lys_iffeature *iffeat_expr, const char *value, struct lys_node *node,
+                          struct unres_schema *unres)
+{
+    const char *c = value;
+    int r, rc = EXIT_FAILURE;
+    int i, j, last_not;
+    unsigned int f_size = 0, expr_size = 0;
+    uint8_t op;
+    struct iff_stack stack = {0, 0, NULL};
+
+    assert(c);
+
+    if (isspace(c[0])) {
+        LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, c[0], c);
+        return EXIT_FAILURE;
+    }
+
+    /* pre-parse the expression to get sizes for arrays, also do some syntax checks of the expression */
+    for (i = j = last_not = 0; c[i]; i++) {
+        if (c[i] == '(') {
+            j++;
+            continue;
+        } else if (c[i] == ')') {
+            j--;
+            continue;
+        } else if (isspace(c[i])) {
+            continue;
+        }
+
+        if (!strncmp(&c[i], "not", r = 3) || !strncmp(&c[i], "and", r = 3) || !strncmp(&c[i], "or", r = 2)) {
+            if (c[i + r] == '\0') {
+                LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, c[i], c);
+                return EXIT_FAILURE;
+            } else if (!isspace(c[i + r])) {
+                /* feature name starting with the not/and/or */
+                last_not = 0;
+                f_size++;
+            } else if (c[i] == 'n') { /* not operation */
+                if (last_not) {
+                    /* double not */
+                    expr_size = expr_size - 2;
+                    last_not = 0;
+                } else {
+                    last_not = 1;
+                }
+            } else {
+                /* not a not operation */
+                last_not = 0;
+            }
+            i += r;
+        } else {
+            f_size++;
+            last_not = 0;
+        }
+        expr_size++;
+
+        while (!isspace(c[i])) {
+            if (!c[i] || c[i] == ')') {
+                i--;
+                break;
+            }
+            i++;
+        }
+    }
+    if (j) {
+        /* not matching count of ( and ) */
+        LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "if-feature");
+        return EXIT_FAILURE;
+    }
+
+    /* allocate the memory */
+    iffeat_expr->expr = calloc((j = (expr_size / 4) + ((expr_size % 4) ? 1 : 0)), sizeof *iffeat_expr->expr);
+    iffeat_expr->features = malloc(f_size * sizeof *iffeat_expr->features);
+    stack.size = expr_size;
+    stack.stack = malloc(expr_size * sizeof *stack.stack);
+    if (!stack.stack || !iffeat_expr->expr || !iffeat_expr->features) {
+        LOGMEM;
+        goto error;
+    }
+    f_size--; expr_size--; /* used as indexes from now */
+
+    for (i--; i >= 0; i--) {
+        if (c[i] == ')') {
+            /* push it on stack */
+            iff_stack_push(&stack, LYS_IFF_RP);
+            continue;
+        } else if (c[i] == '(') {
+            /* pop from the stack into result all operators until ) */
+            while((op = iff_stack_pop(&stack)) != LYS_IFF_RP) {
+                iff_setop(iffeat_expr->expr, op, expr_size--);
+            }
+            continue;
+        } else if (isspace(c[i])) {
+            continue;
+        }
+
+        /* end operator or operand -> find beginning and get what is it */
+        j = i + 1;
+        while (i >= 0 && !isspace(c[i]) && c[i] != '(') {
+            i--;
+        }
+        i++; /* get back by one step */
+
+        if (!strncmp(&c[i], "not ", 4)) {
+            if (stack.index && stack.stack[stack.index - 1] == LYS_IFF_NOT) {
+                /* double not */
+                iff_stack_pop(&stack);
+            } else {
+                /* not has the highest priority, so do not pop from the stack
+                 * as in case of AND and OR */
+                iff_stack_push(&stack, LYS_IFF_NOT);
+            }
+        } else if (!strncmp(&c[i], "and ", 4)) {
+            /* as for OR - pop from the stack all operators with the same or higher
+             * priority and store them to the result, then push the AND to the stack */
+            while (stack.index && stack.stack[stack.index - 1] <= LYS_IFF_AND) {
+                op = iff_stack_pop(&stack);
+                iff_setop(iffeat_expr->expr, op, expr_size--);
+            }
+            iff_stack_push(&stack, LYS_IFF_AND);
+        } else if (!strncmp(&c[i], "or ", 3)) {
+            while (stack.index && stack.stack[stack.index - 1] <= LYS_IFF_OR) {
+                op = iff_stack_pop(&stack);
+                iff_setop(iffeat_expr->expr, op, expr_size--);
+            }
+            iff_stack_push(&stack, LYS_IFF_OR);
+        } else {
+            /* feature name, length is j - i */
+
+            /* add it to the result */
+            iff_setop(iffeat_expr->expr, LYS_IFF_F, expr_size--);
+
+            /* now get the link to the feature definition. Since it can be
+             * forward referenced, we have hack for unres - until resolved,
+             * the feature name is stored instead of link to the lys_feature */
+            iffeat_expr->features[f_size] = (void*)strndup(&c[i], j - i);
+            r = unres_schema_add_node(node->module, unres, &iffeat_expr->features[f_size], UNRES_IFFEAT, node);
+            f_size--;
+
+            if (r == -1) {
+                goto error;
+            }
+        }
+    }
+    while (stack.index) {
+        op = iff_stack_pop(&stack);
+        iff_setop(iffeat_expr->expr, op, expr_size--);
+    }
+
+    if (++expr_size || ++f_size) {
+        /* not all expected operators and operands found */
+        LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "if-feature");
+        rc = EXIT_FAILURE;
+    } else {
+        rc = EXIT_SUCCESS;
+    }
+
+error:
+    /* cleanup */
+    iff_stack_clean(&stack);
+
+    return rc;
+}
+
+/**
  * @brief Resolve (find) a data node based on a schema-nodeid.
  *
  * Used for resolving unique statements - so id is expected to be relative and local (without reference to a different
@@ -2237,8 +2679,9 @@
                 break;
 
             case LYS_RPC:
-                tpdf_size = ((struct lys_node_rpc *)parent)->tpdf_size;
-                tpdf = ((struct lys_node_rpc *)parent)->tpdf;
+            case LYS_ACTION:
+                tpdf_size = ((struct lys_node_rpc_action *)parent)->tpdf_size;
+                tpdf = ((struct lys_node_rpc_action *)parent)->tpdf;
                 break;
 
             case LYS_NOTIF:
@@ -2248,8 +2691,8 @@
 
             case LYS_INPUT:
             case LYS_OUTPUT:
-                tpdf_size = ((struct lys_node_rpc_inout *)parent)->tpdf_size;
-                tpdf = ((struct lys_node_rpc_inout *)parent)->tpdf;
+                tpdf_size = ((struct lys_node_inout *)parent)->tpdf_size;
+                tpdf = ((struct lys_node_inout *)parent)->tpdf;
                 break;
 
             default:
@@ -2501,82 +2944,6 @@
     return rc;
 }
 
-/**
- * @brief Resolve (find) a feature definition. Logs directly.
- *
- * @param[in] name Feature name.
- * @param[in] module Module to search in.
- * @param[out] ret Pointer to the resolved feature. Can be NULL.
- *
- * @return EXIT_SUCCESS on success, EXIT_FAILURE on forward reference, -1 on error.
- */
-static int
-resolve_feature(const char *id, const struct lys_module *module, struct lys_feature **ret)
-{
-    const char *mod_name, *name;
-    int mod_name_len, nam_len, i, j;
-    struct lys_node *node;
-
-    assert(id);
-    assert(module);
-
-    /* check prefix */
-    if ((i = parse_node_identifier(id, &mod_name, &mod_name_len, &name, &nam_len)) < 1) {
-        LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, id[-i], &id[-i]);
-        return -1;
-    }
-
-    module = lys_get_import_module(module, NULL, 0, mod_name, mod_name_len);
-    if (!module) {
-        /* identity refers unknown data model */
-        LOGVAL(LYE_INMOD_LEN, LY_VLOG_NONE, NULL, mod_name_len, mod_name);
-        return -1;
-    }
-
-    /* search in the identified module ... */
-    for (j = 0; j < module->features_size; j++) {
-        if (!strcmp(name, module->features[j].name)) {
-            if (ret) {
-                /* check status */
-                node = (struct lys_node *)*ret;
-                if (lyp_check_status(node->flags, node->module, node->name, module->features[j].flags,
-                                 module->features[j].module, module->features[j].name, node)) {
-                    return -1;
-                }
-                *ret = &module->features[j];
-            }
-            return EXIT_SUCCESS;
-        }
-    }
-    /* ... and all its submodules */
-    for (i = 0; i < module->inc_size; i++) {
-        if (!module->inc[i].submodule) {
-            /* not yet resolved */
-            continue;
-        }
-        for (j = 0; j < module->inc[i].submodule->features_size; j++) {
-            if (!strcmp(name, module->inc[i].submodule->features[j].name)) {
-                if (ret) {
-                    /* check status */
-                    node = (struct lys_node *)*ret;
-                    if (lyp_check_status(node->flags, node->module, node->name,
-                                     module->inc[i].submodule->features[j].flags,
-                                     module->inc[i].submodule->features[j].module,
-                                     module->inc[i].submodule->features[j].name, node)) {
-                        return -1;
-                    }
-                    *ret = &(module->inc[i].submodule->features[j]);
-                }
-                return EXIT_SUCCESS;
-            }
-        }
-    }
-
-    /* not found */
-    LOGVAL(LYE_INRESOLV, LY_VLOG_NONE, NULL, "feature", id);
-    return EXIT_FAILURE;
-}
-
 void
 unres_data_del(struct unres_data *unres, uint32_t i)
 {
@@ -4481,31 +4848,31 @@
 resolve_unres_schema_item(struct lys_module *mod, void *item, enum UNRES_ITEM type, void *str_snode,
                           struct unres_schema *unres)
 {
+    /* has_str - whether the str_snode is a string in a dictionary that needs to be freed */
     int rc = -1, has_str = 0, tpdf_flag = 0;
     struct lys_node *node;
-    const char *base_name;
+    const char *expr;
 
     struct lys_ident *ident;
     struct lys_type *stype;
-    struct lys_feature **feat_ptr;
     struct lys_node_choice *choic;
     struct lyxml_elem *yin;
     struct yang_type *yang;
 
     switch (type) {
     case UNRES_IDENT:
-        base_name = str_snode;
+        expr = str_snode;
         has_str = 1;
         ident = item;
 
-        rc = resolve_base_ident(mod, ident, base_name, "identity", NULL);
+        rc = resolve_base_ident(mod, ident, expr, "identity", NULL);
         break;
     case UNRES_TYPE_IDENTREF:
-        base_name = str_snode;
+        expr = str_snode;
         has_str = 1;
         stype = item;
 
-        rc = resolve_base_ident(mod, NULL, base_name, "type", stype);
+        rc = resolve_base_ident(mod, NULL, expr, "type", stype);
         break;
     case UNRES_TYPE_LEAFREF:
         node = str_snode;
@@ -4571,28 +4938,31 @@
         }
         break;
     case UNRES_IFFEAT:
-        base_name = str_snode;
-        has_str = 1;
-        feat_ptr = item;
+        node = str_snode;
+        expr = *((const char **)item);
 
-        rc = resolve_feature(base_name, mod, feat_ptr);
+        rc = resolve_feature(expr, strlen(expr), node, item);
+        if (!rc) {
+            /* success */
+            free((char *)expr);
+        }
         break;
     case UNRES_USES:
         rc = resolve_unres_schema_uses(item, unres);
         break;
     case UNRES_TYPE_DFLT:
-        base_name = str_snode;
+        expr = str_snode;
         has_str = 1;
         stype = item;
 
-        rc = check_default(stype, base_name, mod);
+        rc = check_default(stype, expr, mod);
         break;
     case UNRES_CHOICE_DFLT:
-        base_name = str_snode;
+        expr = str_snode;
         has_str = 1;
         choic = item;
 
-        choic->dflt = resolve_choice_dflt(choic, base_name);
+        choic->dflt = resolve_choice_dflt(choic, expr);
         if (choic->dflt) {
             rc = EXIT_SUCCESS;
         } else {
@@ -4660,7 +5030,7 @@
         LOGVRB("Resolving %s \"%s\" failed, it will be attempted later.", "derived type", type_name);
         break;
     case UNRES_IFFEAT:
-        LOGVRB("Resolving %s \"%s\" failed, it will be attempted later.", "if-feature", (char *)str_node);
+        LOGVRB("Resolving %s \"%s\" failed, it will be attempted later.", "if-feature", (char *)item);
         break;
     case UNRES_USES:
         LOGVRB("Resolving %s \"%s\" failed, it will be attempted later.", "uses", ((struct lys_node_uses *)item)->name);
@@ -4899,7 +5269,7 @@
  * @param[in] type Type of the old unresolved item.
  * @param[in] new_item New item to use in the duplicate.
  *
- * @return EXIT_SUCCESS on success, -1 on error.
+ * @return EXIT_SUCCESS on success, EXIT_FAILURE if item is not in unres, -1 on error.
  */
 int
 unres_schema_dup(struct lys_module *mod, struct unres_schema *unres, void *item, enum UNRES_ITEM type, void *new_item)
@@ -4911,10 +5281,10 @@
     i = unres_schema_find(unres, item, type);
 
     if (i == -1) {
-        return -1;
+        return EXIT_FAILURE;
     }
 
-    if ((type == UNRES_TYPE_LEAFREF) || (type == UNRES_USES) || (type == UNRES_TYPE_DFLT)) {
+    if ((type == UNRES_TYPE_LEAFREF) || (type == UNRES_USES) || (type == UNRES_TYPE_DFLT) || (type == UNRES_IFFEAT)) {
         if (unres_schema_add_node(mod, unres, new_item, type, unres->str_snode[i]) == -1) {
             LOGINT;
             return -1;
@@ -4965,7 +5335,6 @@
         break;
     case UNRES_IDENT:
     case UNRES_TYPE_IDENTREF:
-    case UNRES_IFFEAT:
     case UNRES_TYPE_DFLT:
     case UNRES_CHOICE_DFLT:
     case UNRES_LIST_KEYS:
diff --git a/src/resolve.h b/src/resolve.h
index 37a0fb6..ea920f3 100644
--- a/src/resolve.h
+++ b/src/resolve.h
@@ -97,6 +97,16 @@
 int parse_schema_json_predicate(const char *id, const char **name, int *nam_len, const char **value, int *val_len,
                                 int *has_predicate);
 
+/**
+ * @param[in] expr compiled if-feature expression
+ * @return 0 if enabled, 1 if disabled
+ */
+int resolve_iffeature(struct lys_iffeature *expr);
+void resolve_iffeature_getsizes(struct lys_iffeature *iffeat, unsigned int *expr_size, unsigned int *feat_size);
+int resolve_iffeature_compile(struct lys_iffeature *iffeat_expr, const char *value, struct lys_node *node,
+                              struct unres_schema *unres);
+uint8_t iff_getop(uint8_t *list, int pos);
+
 struct lyd_node *resolve_data_descendant_schema_nodeid(const char *nodeid, struct lyd_node *start);
 
 int resolve_augment_schema_nodeid(const char *nodeid, const struct lys_node *start, const struct lys_module *module,
diff --git a/src/tree_data.c b/src/tree_data.c
index fe6f7fa..511e8cf 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -52,7 +52,7 @@
 
     assert(ctx);
 
-    if (data && lys_parent(data->schema)) {
+    if (data && lys_parent(data->schema) && (data->schema->nodetype != LYS_ACTION)) {
         LOGERR(LY_EINVAL, "Subtree are not top-level data.");
         return EXIT_FAILURE;
     }
@@ -83,13 +83,18 @@
             return EXIT_FAILURE;
         }
     } else if (options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY)) {
-        if (!data || data->parent || (data->prev != data) || (data->schema->nodetype != LYS_RPC)) {
-            LOGERR(LY_EINVAL, "Subtree is not a single RPC.");
+        if (!data || data->parent || (data->prev != data) || !(data->schema->nodetype & (LYS_RPC | LYS_ACTION))) {
+            LOGERR(LY_EINVAL, "Subtree is not a single RPC/reply.");
             return EXIT_FAILURE;
         }
         if (ly_check_mandatory(data, NULL, 1, (options & LYD_OPT_RPCREPLY) ? 1 : 0)) {
             return EXIT_FAILURE;
         }
+    } else if (options & LYD_OPT_ACTION) {
+        if (!data || data->parent || (data->prev != data) || !(data->schema->nodetype & (LYS_CONTAINER | LYS_LIST))) {
+            LOGERR(LY_EINVAL, "Subtree is not a single action.");
+            return EXIT_FAILURE;
+        }
     } else {
         LOGINT;
         return EXIT_FAILURE;
@@ -142,7 +147,7 @@
 static struct lyd_node *
 lyd_parse_data_(struct ly_ctx *ctx, const char *data, LYD_FORMAT format, int options, va_list ap)
 {
-    const struct lys_node *rpc = NULL;
+    const struct lys_node *rpc_act = NULL;
 
     if (lyp_check_options(options)) {
         LOGERR(LY_EINVAL, "%s: Invalid options (multiple data type flags set).", __func__);
@@ -150,14 +155,14 @@
     }
 
     if (options & LYD_OPT_RPCREPLY) {
-        rpc = va_arg(ap,  struct lys_node*);
-        if (!rpc || (rpc->nodetype != LYS_RPC)) {
+        rpc_act = va_arg(ap,  struct lys_node *);
+        if (!rpc_act || !(rpc_act->nodetype & (LYS_RPC | LYS_ACTION))) {
             LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
             return NULL;
         }
     }
 
-    return lyd_parse_(ctx, rpc, data, format, options);
+    return lyd_parse_(ctx, rpc_act, data, format, options);
 }
 
 API struct lyd_node *
@@ -271,7 +276,7 @@
     return siblings;
 }
 
-static struct lyd_node *
+struct lyd_node *
 _lyd_new(struct lyd_node *parent, const struct lys_node *schema)
 {
     struct lyd_node *ret;
@@ -313,7 +318,7 @@
         return NULL;
     }
 
-    if (lys_get_data_sibling(module, siblings, name, LYS_CONTAINER | LYS_LIST | LYS_NOTIF | LYS_RPC, &snode)
+    if (lys_get_data_sibling(module, siblings, name, LYS_CONTAINER | LYS_LIST | LYS_NOTIF | LYS_RPC | LYS_ACTION, &snode)
             || !snode) {
         ly_errno = LY_EINVAL;
         return NULL;
@@ -582,7 +587,7 @@
         return NULL;
     }
 
-    if (lys_get_data_sibling(module, siblings, name, LYS_CONTAINER | LYS_LIST | LYS_NOTIF | LYS_RPC, &snode)
+    if (lys_get_data_sibling(module, siblings, name, LYS_CONTAINER | LYS_LIST | LYS_NOTIF | LYS_RPC | LYS_ACTION, &snode)
             || !snode) {
         return NULL;
     }
@@ -834,7 +839,7 @@
         /* find the schema node */
         schild = NULL;
         while ((schild = lys_getnext(schild, sparent, module, 0))) {
-            if (schild->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYXML | LYS_NOTIF | LYS_RPC)) {
+            if (schild->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYXML | LYS_NOTIF | LYS_RPC | LYS_ACTION)) {
                 /* module comparison */
                 if (mod_name) {
                     node_mod_name = lys_node_module(schild)->name;
@@ -881,6 +886,7 @@
         case LYS_LIST:
         case LYS_NOTIF:
         case LYS_RPC:
+        case LYS_ACTION:
             node = _lyd_new(is_relative ? parent : NULL, schild);
             break;
         case LYS_LEAF:
@@ -2267,13 +2273,13 @@
 
     /* check placing the node to the appropriate place according to the schema */
     for (sparent = lys_parent(node->schema);
-         sparent && !(sparent->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_RPC | LYS_NOTIF));
+         sparent && !(sparent->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_RPC | LYS_ACTION | LYS_NOTIF));
          sparent = lys_parent(sparent));
     if (sparent != parent->schema) {
         return EXIT_FAILURE;
     }
 
-    if (node->parent != parent || (invalid = lyp_is_rpc(node->schema))) {
+    if (node->parent != parent || (invalid = lyp_is_rpc_action(node->schema))) {
         /* it is not just moving under a parent node or it is in an RPC where
          * nodes order matters, so the validation will be necessary */
         invalid++;
@@ -2322,17 +2328,17 @@
 
     /* check placing the node to the appropriate place according to the schema */
     for (par1 = lys_parent(sibling->schema);
-         par1 && !(par1->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_INPUT | LYS_OUTPUT | LYS_NOTIF));
+         par1 && !(par1->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_INPUT | LYS_OUTPUT | LYS_ACTION | LYS_NOTIF));
          par1 = lys_parent(par1));
     for (par2 = lys_parent(node->schema);
-         par2 && !(par2->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_INPUT | LYS_OUTPUT | LYS_NOTIF));
+         par2 && !(par2->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_INPUT | LYS_OUTPUT | LYS_ACTION | LYS_NOTIF));
          par2 = lys_parent(par2));
     if (par1 != par2) {
         ly_errno = LY_EINVAL;
         return EXIT_FAILURE;
     }
 
-    if (node->parent != sibling->parent || (invalid = lyp_is_rpc(node->schema)) || !node->parent) {
+    if (node->parent != sibling->parent || (invalid = lyp_is_rpc_action(node->schema)) || !node->parent) {
         /* a) it is not just moving under a parent node (invalid = 1) or
          * b) it is in an RPC where nodes order matters (invalid = 2) or
          * c) it is top-level where we don't know if it is the same tree (invalid = 1),
@@ -2597,7 +2603,7 @@
     /* sort all the children recursively */
     if (recursive) {
         LY_TREE_FOR(sibling, node) {
-            if ((node->schema->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_RPC | LYS_NOTIF))
+            if ((node->schema->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_RPC | LYS_ACTION | LYS_NOTIF))
                     && lyd_schema_sort(node->child, recursive)) {
                 return -1;
             }
@@ -2626,7 +2632,7 @@
 API int
 lyd_validate(struct lyd_node **node, int options, ...)
 {
-    struct lyd_node *root, *next1, *next2, *iter, *to_free = NULL;
+    struct lyd_node *root, *next1, *next2, *iter, *action = NULL, *to_free = NULL;
     struct ly_ctx *ctx = NULL;
     int ret = EXIT_FAILURE, ap_flag = 0;
     va_list ap;
@@ -2670,6 +2676,11 @@
         }
     }
 
+    if ((options & LYD_OPT_RPC) && *node && ((*node)->schema->nodetype != LYS_RPC)) {
+        options &= ~LYD_OPT_RPC;
+        options |= LYD_OPT_ACTION;
+    }
+
     if (lyd_check_topmandatory(*node, ctx, options)) {
         goto error;
     }
@@ -2681,6 +2692,12 @@
                 to_free = NULL;
             }
 
+            if ((options & LYD_OPT_ACTION) && (iter->schema->nodetype == LYS_ACTION)) {
+                options &= ~LYD_OPT_ACTION;
+                options |= LYD_OPT_RPC;
+                action = iter;
+            }
+
             if (lyv_data_context(iter, options, unres)) {
                 goto error;
             }
@@ -2756,7 +2773,12 @@
     }
 
     /* add default values if needed */
-    if (lyd_defaults_add_unres(node, options, ctx, unres)) {
+    if (action) {
+        /* it will not get deleted */
+        if (lyd_defaults_add_unres(&action, options, ctx, unres)) {
+            goto error;
+        }
+    } else if (lyd_defaults_add_unres(node, options, ctx, unres)) {
         goto error;
     }
 
@@ -2974,6 +2996,7 @@
         case LYS_LIST:
         case LYS_NOTIF:
         case LYS_RPC:
+        case LYS_ACTION:
             new_node = malloc(sizeof *new_node);
             if (!new_node) {
                 LOGMEM;
@@ -3623,7 +3646,7 @@
     unsigned int i, j;
 
     if (!data || !schema ||
-            !(schema->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_ANYXML | LYS_NOTIF | LYS_RPC))) {
+            !(schema->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_ANYXML | LYS_NOTIF | LYS_RPC | LYS_ACTION))) {
         ly_errno = LY_EINVAL;
         return NULL;
     }
@@ -3650,7 +3673,7 @@
         if (siter->nodetype == LYS_AUGMENT) {
             siter = ((struct lys_node_augment *)siter)->target;
             continue;
-        } else if (siter->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_ANYXML | LYS_NOTIF | LYS_RPC)) {
+        } else if (siter->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_ANYXML | LYS_NOTIF | LYS_RPC | LYS_RPC)) {
             /* standard data node */
             ly_set_add(spath, (void*)siter, LY_SET_OPT_USEASLIST);
 
@@ -4329,12 +4352,12 @@
             break;
         case LYS_INPUT:
         case LYS_OUTPUT:
-            assert(options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY));
+            assert(options & (LYD_OPT_RPC | LYD_OPT_ACTION | LYD_OPT_RPCREPLY));
             if ((siter->nodetype == LYS_INPUT) && (options & LYD_OPT_RPCREPLY)) {
                 /* skip input */
                 break;
             }
-            if ((siter->nodetype == LYS_OUTPUT) && (options & LYD_OPT_RPC)) {
+            if ((siter->nodetype == LYS_OUTPUT) && (options & (LYD_OPT_RPC | LYD_OPT_ACTION))) {
                 /* skip output */
                 break;
             }
@@ -4406,7 +4429,7 @@
             }
         }
 
-        if (iter->schema->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_RPC | LYS_NOTIF)) {
+        if (iter->schema->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_RPC | LYS_ACTION | LYS_NOTIF)) {
             if ((options & LYD_WD_MASK) == LYD_WD_EXPLICIT
                     && ((iter->schema->flags & LYS_CONFIG_W) && !(iter->schema->flags & LYS_INCL_STATUS))) {
                 /* do not process config data in explicit mode */
@@ -4582,18 +4605,14 @@
             LOGERR(LY_EINVAL, "Cannot add default values to RPC, RPC reply, and notification without at least the empty container.");
             return EXIT_FAILURE;
         }
-        if ((options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY)) && ((*root)->schema->nodetype != LYS_RPC)) {
-            LOGERR(LY_EINVAL, "Not valid RPC data.");
+        if ((options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY)) && !((*root)->schema->nodetype & (LYS_RPC | LYS_ACTION))) {
+            LOGERR(LY_EINVAL, "Not valid RPC/action data.");
             return EXIT_FAILURE;
         }
         if ((options & LYD_OPT_NOTIF) && ((*root)->schema->nodetype != LYS_NOTIF)) {
             LOGERR(LY_EINVAL, "Not valid notification data.");
             return EXIT_FAILURE;
         }
-        if (!(options & LYD_OPT_NOSIBLINGS) && ((*root)->prev != (*root))) {
-            LOGERR(LY_EINVAL, "Additional invalid data with an RPC, RPC reply, or notification.");
-            return EXIT_FAILURE;
-        }
     } else if (*root && (*root)->parent) {
         /* we have inner node, so it will be considered as
          * a root of subtree where to add default nodes and
diff --git a/src/tree_data.h b/src/tree_data.h
index 8a405b1..854ead6 100644
--- a/src/tree_data.h
+++ b/src/tree_data.h
@@ -381,7 +381,7 @@
 #define LYD_OPT_RPC        0x10 /**< Data represents RPC's input parameters. */
 #define LYD_OPT_RPCREPLY   0x20 /**< Data represents RPC's output parameters (maps to NETCONF <rpc-reply> data). */
 #define LYD_OPT_NOTIF      0x40 /**< Data represents an event notification data. */
-/* 0x80 reserved, formerly LYD_OPT_FILTER */
+/* 0x80 reserved, formerly LYD_OPT_FILTER, now used internally */
 #define LYD_OPT_TYPEMASK   0xff /**< Mask to filter data type options. Always only a single data type option (only
                                      single bit from the lower 8 bits) can be set. */
 
diff --git a/src/tree_internal.h b/src/tree_internal.h
index 6a5b928..c1f1699 100644
--- a/src/tree_internal.h
+++ b/src/tree_internal.h
@@ -59,6 +59,11 @@
 #define LY_NSNACM "urn:ietf:params:xml:ns:yang:ietf-netconf-acm"
 
 /**
+ * @brief internal parser flag for actions
+ */
+#define LYD_OPT_ACTION 0x80
+
+/**
  * @brief Internal list of built-in types
  */
 struct ly_types {
@@ -286,6 +291,15 @@
 int ly_check_mandatory(const struct lyd_node *data, const struct lys_node *schema, int status, int rpc_output);
 
 /**
+ * @brief Create a data container knowing it's schema node.
+ *
+ * @param[in] parent Data parent of the new node.
+ * @param[in] schema Schema node of the new node.
+ * @return New node, NULL on error.
+ */
+struct lyd_node *_lyd_new(struct lyd_node *parent, const struct lys_node *schema);
+
+/**
  * @brief Find the parent node of an attribute.
  *
  * @param[in] root Root element of the data tree with the attribute.
diff --git a/src/tree_schema.c b/src/tree_schema.c
index 1b96cd0..3fa333d 100644
--- a/src/tree_schema.c
+++ b/src/tree_schema.c
@@ -40,7 +40,7 @@
 lys_type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
              struct unres_schema *unres);
 
-API const struct lys_feature *
+API const struct lys_node *
 lys_is_disabled(const struct lys_node *node, int recursive)
 {
     int i;
@@ -50,9 +50,9 @@
         /* input/output does not have if-feature, so skip them */
 
         /* check local if-features */
-        for (i = 0; i < node->features_size; i++) {
-            if (!(node->features[i]->flags & LYS_FENABLED)) {
-                return node->features[i];
+        for (i = 0; i < node->iffeature_size; i++) {
+            if (resolve_iffeature(&node->iffeature[i])) {
+                return node;
             }
         }
     }
@@ -234,6 +234,7 @@
         goto repeat;
 
     case LYS_RPC:
+    case LYS_ACTION:
     case LYS_NOTIF:
     case LYS_CONTAINER:
     case LYS_LEAF:
@@ -944,6 +945,13 @@
     case LYS_CONTAINER:
     case LYS_LIST:
     case LYS_GROUPING:
+        if (!(child->nodetype &
+                (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
+                 LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ACTION))) {
+            LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
+            return EXIT_FAILURE;
+        }
+        break;
     case LYS_USES:
     case LYS_INPUT:
     case LYS_OUTPUT:
@@ -954,7 +962,6 @@
             LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
             return EXIT_FAILURE;
         }
-
         break;
     case LYS_CHOICE:
         if (!(child->nodetype &
@@ -971,6 +978,7 @@
         }
         break;
     case LYS_RPC:
+    case LYS_ACTION:
         if (!(child->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_GROUPING))) {
             LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "rpc");
             return EXIT_FAILURE;
@@ -986,7 +994,7 @@
     case LYS_AUGMENT:
         if (!(child->nodetype &
                 (LYS_ANYXML | LYS_CASE | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF
-                | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
+                | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ACTION))) {
             LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
             return EXIT_FAILURE;
         }
@@ -1638,6 +1646,18 @@
 }
 
 static void
+lys_iffeature_free(struct lys_iffeature *iffeature, uint8_t iffeature_size)
+{
+    uint8_t i;
+
+    for (i = 0; i < iffeature_size; ++i) {
+        free(iffeature[i].expr);
+        free(iffeature[i].features);
+    }
+    free(iffeature);
+}
+
+static void
 lys_augment_free(struct ly_ctx *ctx, struct lys_node_augment *aug, void (*private_destructor)(const struct lys_node *node, void *priv))
 {
     struct lys_node *next, *sub;
@@ -1653,7 +1673,7 @@
     lydict_remove(ctx, aug->dsc);
     lydict_remove(ctx, aug->ref);
 
-    free(aug->features);
+    lys_iffeature_free(aug->iffeature, aug->iffeature_size);
 
     lys_when_free(ctx, aug->when);
 }
@@ -1788,7 +1808,7 @@
 }
 
 static void
-lys_rpc_inout_free(struct ly_ctx *ctx, struct lys_node_rpc_inout *io)
+lys_inout_free(struct ly_ctx *ctx, struct lys_node_inout *io)
 {
     int i;
 
@@ -1911,7 +1931,7 @@
     lydict_remove(ctx, f->name);
     lydict_remove(ctx, f->dsc);
     lydict_remove(ctx, f->ref);
-    free(f->features);
+    lys_iffeature_free(f->iffeature, f->iffeature_size);
 }
 
 static void
@@ -2018,7 +2038,7 @@
     /* common part */
     lydict_remove(ctx, node->name);
     if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
-        free(node->features);
+        lys_iffeature_free(node->iffeature, node->iffeature_size);
         lydict_remove(ctx, node->dsc);
         lydict_remove(ctx, node->ref);
     }
@@ -2060,13 +2080,14 @@
         break;
     case LYS_GROUPING:
     case LYS_RPC:
+    case LYS_ACTION:
     case LYS_NOTIF:
         lys_grp_free(ctx, (struct lys_node_grp *)node);
         break;
 
     case LYS_INPUT:
     case LYS_OUTPUT:
-        lys_rpc_inout_free(ctx, (struct lys_node_rpc_inout *)node);
+        lys_inout_free(ctx, (struct lys_node_inout *)node);
         break;
     case LYS_UNKNOWN:
         LOGINT;
@@ -2217,6 +2238,7 @@
     struct lys_node *retval = NULL, *child;
     struct ly_ctx *ctx = module->ctx;
     int i, j, rc;
+    unsigned int size, size1, size2;
 
     struct lys_node_container *cont = NULL;
     struct lys_node_container *cont_orig = (struct lys_node_container *)node;
@@ -2234,12 +2256,12 @@
     struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
     struct lys_node_grp *grp = NULL;
     struct lys_node_grp *grp_orig = (struct lys_node_grp *)node;
-    struct lys_node_rpc *rpc = NULL;
-    struct lys_node_rpc *rpc_orig = (struct lys_node_rpc *)node;
-    struct lys_node_rpc_inout *io = NULL;
-    struct lys_node_rpc_inout *io_orig = (struct lys_node_rpc_inout *)node;
-    struct lys_node_rpc *ntf = NULL;
-    struct lys_node_rpc *ntf_orig = (struct lys_node_rpc *)node;
+    struct lys_node_rpc_action *rpc = NULL;
+    struct lys_node_rpc_action *rpc_orig = (struct lys_node_rpc_action *)node;
+    struct lys_node_inout *io = NULL;
+    struct lys_node_inout *io_orig = (struct lys_node_inout *)node;
+    struct lys_node_rpc_action *ntf = NULL;
+    struct lys_node_rpc_action *ntf_orig = (struct lys_node_rpc_action *)node;
     struct lys_node_case *cs = NULL;
     struct lys_node_case *cs_orig = (struct lys_node_case *)node;
 
@@ -2294,6 +2316,7 @@
         break;
 
     case LYS_RPC:
+    case LYS_ACTION:
         rpc = calloc(1, sizeof *rpc);
         retval = (struct lys_node *)rpc;
         break;
@@ -2337,18 +2360,44 @@
 
     retval->prev = retval;
 
-    retval->features_size = node->features_size;
-    retval->features = calloc(retval->features_size, sizeof *retval->features);
-    if (!retval->features) {
+    retval->iffeature_size = node->iffeature_size;
+    retval->iffeature = calloc(retval->iffeature_size, sizeof *retval->iffeature);
+    if (!retval->iffeature) {
         LOGMEM;
         goto error;
     }
 
     if (!shallow) {
-        for (i = 0; i < node->features_size; ++i) {
-            retval->features[i] = (struct lys_feature *)retval;
-            if (unres_schema_dup(module, unres, &node->features[i], UNRES_IFFEAT, &retval->features[i])) {
-                retval->features[i] = node->features[i];
+        for (i = 0; i < node->iffeature_size; ++i) {
+            resolve_iffeature_getsizes(&node->iffeature[i], &size1, &size2);
+            if (size1) {
+                /* there is something to duplicate */
+
+                /* duplicate compiled expression */
+                size = (size1 / 4) + (size1 % 4) ? 1 : 0;
+                retval->iffeature[i].expr = malloc(size * sizeof *retval->iffeature[i].expr);
+                memcpy(retval->iffeature[i].expr, node->iffeature[i].expr, size * sizeof *retval->iffeature[i].expr);
+
+                /* list of feature pointer must be updated to point to the resulting tree */
+                retval->iffeature[i].features = malloc(size2 * sizeof *retval->iffeature[i].features);
+                for (j = 0; (unsigned int)j < size2; j++) {
+                    rc = unres_schema_dup(module, unres, &node->iffeature[i].features[j], UNRES_IFFEAT,
+                                          &retval->iffeature[i].features[j]);
+                    if (rc == EXIT_SUCCESS) {
+                        /* feature is not resolved, duplicate the expression string */
+                        retval->iffeature[i].features[j] = (void *)strdup((char *)node->iffeature[i].features[j]);
+                    } else if (rc == EXIT_FAILURE) {
+                        /* feature is resolved in origin, so copy it
+                         * - duplication is used for instantiating groupings
+                         * and if-feature inside grouping is supposed to be
+                         * resolved inside the original grouping, so we want
+                         * to keep pointers to features from the grouping
+                         * context */
+                        retval->iffeature[i].features[j] = node->iffeature[i].features[j];
+                    } else if (rc == -1) {
+                        goto error;
+                    }
+                }
             }
         }
 
@@ -2366,7 +2415,7 @@
             }
         }
     } else {
-        memcpy(retval->features, node->features, retval->features_size * sizeof *retval->features);
+        memcpy(retval->iffeature, node->iffeature, retval->iffeature_size * sizeof *retval->iffeature);
     }
 
     /*
@@ -2703,12 +2752,16 @@
     for (i = 0; i < module->features_size; i++) {
         if (all || !strcmp(module->features[i].name, name)) {
             if (op) {
-                module->features[i].flags |= LYS_FENABLED;
-                /* enable referenced features (recursion) */
-                for (k = 0; k < module->features[i].features_size; k++) {
-                    lys_features_change(module->features[i].features[k]->module,
-                                       module->features[i].features[k]->name, op);
+                /* check referenced features if they are enabled */
+                for (j = 0; j < module->features[i].iffeature_size; j++) {
+                    if (resolve_iffeature(&module->features[i].iffeature[j])) {
+                        LOGERR(LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
+                               module->features[i].name, j + 1);
+                        return EXIT_FAILURE;
+                    }
                 }
+
+                module->features[i].flags |= LYS_FENABLED;
             } else {
                 module->features[i].flags &= ~LYS_FENABLED;
             }
@@ -2719,13 +2772,22 @@
     }
 
     /* submodules */
-    for (j = 0; j < module->inc_size; j++) {
-        for (i = 0; i < module->inc[j].submodule->features_size; i++) {
-            if (all || !strcmp(module->inc[j].submodule->features[i].name, name)) {
+    for (i = 0; i < module->inc_size; i++) {
+        for (j = 0; j < module->inc[i].submodule->features_size; j++) {
+            if (all || !strcmp(module->inc[i].submodule->features[j].name, name)) {
                 if (op) {
-                    module->inc[j].submodule->features[i].flags |= LYS_FENABLED;
+                    /* check referenced features if they are enabled */
+                    for (k = 0; k < module->inc[i].submodule->features[j].iffeature_size; k++) {
+                        if (resolve_iffeature(&module->inc[i].submodule->features[j].iffeature[k])) {
+                            LOGERR(LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
+                                module->inc[i].submodule->features[j].name, k + 1);
+                            return EXIT_FAILURE;
+                        }
+                    }
+
+                    module->inc[i].submodule->features[j].flags |= LYS_FENABLED;
                 } else {
-                    module->inc[j].submodule->features[i].flags &= ~LYS_FENABLED;
+                    module->inc[i].submodule->features[j].flags &= ~LYS_FENABLED;
                 }
                 if (!all) {
                     return EXIT_SUCCESS;
@@ -2902,7 +2964,7 @@
 {
     struct lys_node_leaf *iter = leafref_target;
 
-    if (leafref_target->nodetype != LYS_LEAF) {
+    if (!(leafref_target->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
         LOGINT;
         return -1;
     }
@@ -2918,7 +2980,7 @@
     }
 
     /* create fake child - the ly_set structure to hold the list of
-     * leafrefs referencing the leaf */
+     * leafrefs referencing the leaf(-list) */
     if (!leafref_target->child) {
         leafref_target->child = (void*)ly_set_new();
         if (!leafref_target->child) {
diff --git a/src/tree_schema.h b/src/tree_schema.h
index a929920..f13d450 100644
--- a/src/tree_schema.h
+++ b/src/tree_schema.h
@@ -204,13 +204,14 @@
     LYS_OUTPUT = 0x0400,         /**< output statement node */
     LYS_GROUPING = 0x0800,       /**< grouping statement node */
     LYS_USES = 0x1000,           /**< uses statement node */
-    LYS_AUGMENT = 0x2000         /**< augment statement node */
+    LYS_AUGMENT = 0x2000,        /**< augment statement node */
+    LYS_ACTION = 0x4000          /**< action statement node */
 } LYS_NODE;
 
 /* all nodes sharing the node namespace except RPCs and notifications */
 #define LYS_NO_RPC_NOTIF_NODE 0x007F
 
-#define LYS_ANY 0x3FFF
+#define LYS_ANY 0x7FFF
 
 /**
  * @brief Main schema node structure representing YANG module.
@@ -234,7 +235,7 @@
     uint8_t version:5;               /**< yang-version:
                                           - 0 = not specified, YANG 1.0 as default,
                                           - 1 = YANG 1.0,
-                                          - 2 = YANG 1.1 not yet supported */
+                                          - 2 = YANG 1.1 */
     uint8_t deviated:1;              /**< deviated flag (true/false) if the module is deviated by some other module */
     uint8_t implemented:1;           /**< flag if the module is implemented, not just imported */
 
@@ -540,6 +541,19 @@
      */
 };
 
+#define LYS_IFF_NOT  0x00
+#define LYS_IFF_AND  0x01
+#define LYS_IFF_OR   0x02
+#define LYS_IFF_F    0x03
+
+/**
+ * @brief Compiled if-feature expression structure
+ */
+struct lys_iffeature {
+    uint8_t *expr;                   /**< 2bits array describing the if-feature expression in prefix format */
+    struct lys_feature **features;   /**< array of pointers to the features used in expression */
+};
+
 /**
  * @defgroup nacmflags NACM flags
  * @ingroup schematree
@@ -657,9 +671,8 @@
                                           itself. In case of the first node, this pointer points to the last
                                           node in the list. */
 
-    uint8_t features_size;           /**< number of elements in the #features array */
-    struct lys_feature **features;   /**< array of pointers to feature definitions, this is not the array of feature
-                                          definitions themselves, but the array of if-feature references */
+    uint8_t iffeature_size;          /**< number of elements in the #iffeature array */
+    struct lys_iffeature *iffeature; /**< array of if-feature expressions */
     void *priv;                      /**< private caller's data, not used by libyang */
 };
 
@@ -689,9 +702,8 @@
                                           itself. In case of the first node, this pointer points to the last
                                           node in the list. */
 
-    uint8_t features_size;           /**< number of elements in the #features array */
-    struct lys_feature **features;   /**< array of pointers to feature definitions, this is not the array of feature
-                                          definitions themselves, but the array of if-feature references */
+    uint8_t iffeature_size;          /**< number of elements in the #iffeature array */
+    struct lys_iffeature *iffeature; /**< array of if-feature expressions */
     void *priv;                      /**< private caller's data, not used by libyang */
 
     /* specific container's data */
@@ -731,9 +743,8 @@
                                           itself. In case of the first node, this pointer points to the last
                                           node in the list. */
 
-    uint8_t features_size;           /**< number of elements in the #features array */
-    struct lys_feature **features;   /**< array of pointers to feature definitions, this is not the array of feature
-                                          definitions themselves, but the array of if-feature references */
+    uint8_t iffeature_size;          /**< number of elements in the #iffeature array */
+    struct lys_iffeature *iffeature; /**< array of if-feature expressions */
     void *priv;                      /**< private caller's data, not used by libyang */
 
     /* specific choice's data */
@@ -773,9 +784,8 @@
                                           itself. In case of the first node, this pointer points to the last
                                           node in the list. */
 
-    uint8_t features_size;           /**< number of elements in the #features array */
-    struct lys_feature **features;   /**< array of pointers to feature definitions, this is not the array of feature
-                                          definitions themselves, but the array of if-feature references */
+    uint8_t iffeature_size;          /**< number of elements in the #iffeature array */
+    struct lys_iffeature *iffeature; /**< array of if-feature expressions */
     void *priv;                      /**< private caller's data, not used by libyang */
 
     /* specific leaf's data */
@@ -821,9 +831,8 @@
                                           itself. In case of the first node, this pointer points to the last
                                           node in the list. */
 
-    uint8_t features_size;           /**< number of elements in the #features array */
-    struct lys_feature **features;   /**< array of pointers to feature definitions, this is not the array of feature
-                                          definitions themselves, but the array of if-feature references */
+    uint8_t iffeature_size;          /**< number of elements in the #iffeature array */
+    struct lys_iffeature *iffeature; /**< array of if-feature expressions */
     void *priv;                      /**< private caller's data, not used by libyang */
 
     /* specific leaf-list's data */
@@ -865,9 +874,8 @@
                                           itself. In case of the first node, this pointer points to the last
                                           node in the list. */
 
-    uint8_t features_size;           /**< number of elements in the #features array */
-    struct lys_feature **features;   /**< array of pointers to feature definitions, this is not the array of feature
-                                          definitions themselves, but the array of if-feature references */
+    uint8_t iffeature_size;          /**< number of elements in the #iffeature array */
+    struct lys_iffeature *iffeature; /**< array of if-feature expressions */
     void *priv;                      /**< private caller's data, not used by libyang */
 
     /* specific list's data */
@@ -915,9 +923,8 @@
                                           itself. In case of the first node, this pointer points to the last
                                           node in the list. */
 
-    uint8_t features_size;           /**< number of elements in the #features array */
-    struct lys_feature **features;   /**< array of pointers to feature definitions, this is not the array of feature
-                                          definitions themselves, but the array of if-feature references */
+    uint8_t iffeature_size;          /**< number of elements in the #iffeature array */
+    struct lys_iffeature *iffeature; /**< array of if-feature expressions */
     void *priv;                      /**< private caller's data, not used by libyang */
 
     /* specific anyxml's data */
@@ -956,9 +963,8 @@
                                           itself. In case of the first node, this pointer points to the last
                                           node in the list. */
 
-    uint8_t features_size;           /**< number of elements in the #features array */
-    struct lys_feature **features;   /**< array of pointers to feature definitions, this is not the array of feature
-                                          definitions themselves, but the array of if-feature references */
+    uint8_t iffeature_size;          /**< number of elements in the #iffeature array */
+    struct lys_iffeature *iffeature; /**< array of if-feature expressions */
     void *priv;                      /**< private caller's data, not used by libyang */
 
     /* specific uses's data */
@@ -1004,9 +1010,8 @@
                                           itself. In case of the first node, this pointer points to the last
                                           node in the list. */
 
-    uint8_t features_size;           /**< number of elements in the #features array */
-    struct lys_feature **features;   /**< array of pointers to feature definitions, this is not the array of feature
-                                          definitions themselves, but the array of if-feature references */
+    uint8_t iffeature_size;          /**< number of elements in the #iffeature array */
+    struct lys_iffeature *iffeature; /**< array of if-feature expressions */
     void *priv;                      /**< private caller's data, not used by libyang */
 
     /* specific grouping's data */
@@ -1039,9 +1044,8 @@
                                           itself. In case of the first node, this pointer points to the last
                                           node in the list. */
 
-    uint8_t features_size;           /**< number of elements in the #features array */
-    struct lys_feature **features;   /**< array of pointers to feature definitions, this is not the array of feature
-                                          definitions themselves, but the array of if-feature references */
+    uint8_t iffeature_size;          /**< number of elements in the #iffeature array */
+    struct lys_iffeature *iffeature; /**< array of if-feature expressions */
     void *priv;                      /**< private caller's data, not used by libyang */
 
     /* specific case's data */
@@ -1059,7 +1063,7 @@
  * member.
  *
  */
-struct lys_node_rpc_inout {
+struct lys_node_inout {
     const char *name;
     void *fill1[2];                  /**< padding for compatibility with ::lys_node - dsc and ref */
     uint16_t fill2[1];               /**< padding for compatibility with ::lys_node - flags and nacm */
@@ -1105,9 +1109,8 @@
                                           itself. In case of the first node, this pointer points to the last
                                           node in the list. */
 
-    uint8_t features_size;           /**< number of elements in the #features array */
-    struct lys_feature **features;   /**< array of pointers to feature definitions, this is not the array of feature
-                                          definitions themselves, but the array of if-feature references */
+    uint8_t iffeature_size;          /**< number of elements in the #iffeature array */
+    struct lys_iffeature *iffeature; /**< array of if-feature expressions */
     void *priv;                      /**< private caller's data, not used by libyang */
 
     /* specific rpc's data */
@@ -1121,7 +1124,7 @@
  * Beginning of the structure is completely compatible with ::lys_node structure extending it by the #tpdf_size and
  * #tpdf members.
  */
-struct lys_node_rpc {
+struct lys_node_rpc_action {
     const char *name;                /**< node name (mandatory) */
     const char *dsc;                 /**< description statement (optional) */
     const char *ref;                 /**< reference statement (optional) */
@@ -1129,7 +1132,7 @@
     uint16_t nacm:2;                 /**< [NACM extension flags](@ref nacmflags) */
     struct lys_module *module;       /**< pointer to the node's module (mandatory) */
 
-    LYS_NODE nodetype;               /**< type of the node (mandatory) - #LYS_RPC */
+    LYS_NODE nodetype;               /**< type of the node (mandatory) - #LYS_RPC or #LYS_ACTION */
     struct lys_node *parent;         /**< pointer to the parent node, NULL in case of a top level node */
     struct lys_node *child;          /**< pointer to the first child node */
     struct lys_node *next;           /**< pointer to the next sibling node (NULL if there is no one) */
@@ -1138,9 +1141,8 @@
                                           itself. In case of the first node, this pointer points to the last
                                           node in the list. */
 
-    uint8_t features_size;           /**< number of elements in the #features array */
-    struct lys_feature **features;   /**< array of pointers to feature definitions, this is not the array of feature
-                                          definitions themselves, but the array of if-feature references */
+    uint8_t iffeature_size;          /**< number of elements in the #iffeature array */
+    struct lys_iffeature *iffeature; /**< array of if-feature expressions */
     void *priv;                      /**< private caller's data, not used by libyang */
 
     /* specific rpc's data */
@@ -1183,9 +1185,8 @@
     struct lys_node *target;         /**< pointer to the target node */
 
     /* again compatible members with ::lys_node */
-    uint8_t features_size;           /**< number of elements in the #features array */
-    struct lys_feature **features;   /**< array of pointers to feature definitions, this is not the array of feature
-                                          definitions themselves, but the array of if-feature references */
+    uint8_t iffeature_size;          /**< number of elements in the #iffeature array */
+    struct lys_iffeature *iffeature; /**< array of if-feature expressions */
     void *priv;                      /**< private caller's data, not used by libyang */
 
 };
@@ -1338,9 +1339,8 @@
     uint16_t padding:2;
     struct lys_module *module;       /**< link to the features's data model (mandatory) */
 
-    uint8_t features_size;           /**< number of elements in the #features array */
-    struct lys_feature **features;   /**< array of pointers to feature definitions, this is not the array of feature
-                                          definitions themselves, but the array of if-feature references */
+    uint8_t iffeature_size;          /**< number of elements in the #iffeature array */
+    struct lys_iffeature *iffeature; /**< array of if-feature expressions */
 };
 
 /**
@@ -1477,9 +1477,9 @@
  * - 1 to check if-feature in all ascendant schema nodes
  * - 2 to check if-feature in all ascendant schema nodes until there a node having an instance in a data tree
  * @return - NULL if enabled,
- * - pointer to the disabling feature if disabled.
+ * - pointer to the node with the unsatisfied (disabling) if-feature expression.
  */
-const struct lys_feature *lys_is_disabled(const struct lys_node *node, int recursive);
+const struct lys_node *lys_is_disabled(const struct lys_node *node, int recursive);
 
 /**
  * @brief Get next schema tree (sibling) node element that can be instantiated in a data tree. Returned node can
diff --git a/src/validation.c b/src/validation.c
index bd227b9..9a3e93f 100644
--- a/src/validation.c
+++ b/src/validation.c
@@ -25,7 +25,7 @@
 #include "tree_internal.h"
 #include "xml_internal.h"
 
-static int
+int
 lyv_keys(const struct lyd_node *list)
 {
     struct lyd_node *child;
@@ -95,7 +95,7 @@
     }
 
     /* check elements order in case of RPC's input and output */
-    if (node->validity && lyp_is_rpc(node->schema)) {
+    if (node->validity && lyp_is_rpc_action(node->schema)) {
         if ((node->prev != node) && node->prev->next) {
             for (siter = lys_getnext(node->schema, lys_parent(node->schema), node->schema->module, 0);
                     siter;
@@ -138,7 +138,7 @@
 
         /* mandatory children */
         if ((schema->nodetype & (LYS_CONTAINER | LYS_LIST))
-                && !(options & (LYD_OPT_EDIT | LYD_OPT_GET | LYD_OPT_GETCONFIG))) {
+                && !(options & (LYD_OPT_EDIT | LYD_OPT_GET | LYD_OPT_GETCONFIG | LYD_OPT_ACTION))) {
             if (ly_check_mandatory(node, NULL, (options & LYD_OPT_TYPEMASK) ? 0 : 1, (options & LYD_OPT_RPCREPLY) ? 1 : 0)) {
                 return EXIT_FAILURE;
             }
diff --git a/src/yang.y.in b/src/yang.y.in
index 2d96a9e..a06a4b9 100644
--- a/src/yang.y.in
+++ b/src/yang.y.in
@@ -385,12 +385,12 @@
 

 yang_version_stmt: YANG_VERSION_KEYWORD sep yang_version_arg_str stmtend;

 

-yang_version_arg_str: NON_NEGATIVE_INTEGER { if (strlen(yyget_text(scanner))!=1 || yyget_text(scanner)[0]!='1') {

+yang_version_arg_str: NON_NEGATIVE_INTEGER { if (strcmp(yyget_text(scanner), "1") && strcmp(yyget_text(scanner), "1.1")) {

                                                YYABORT;

                                              }

                                            } optsep

   | string_1 { if (read_all) {

-                 if (strlen(s)!=1 || s[0]!='1') {

+                 if (strcmp(s, "1") && strcmp(s, "1.1")) {

                    free(s);

                    YYABORT;

                  }

@@ -780,9 +780,9 @@
 

 feature_opt_stmt: @EMPTYDIR@ { if (read_all) {

                              if (size_arrays->node[size_arrays->next].if_features) {

-                               ((struct lys_feature*)actual)->features = calloc(size_arrays->node[size_arrays->next].if_features,

-                                                                                sizeof *((struct lys_feature*)actual)->features);

-                               if (!((struct lys_feature*)actual)->features) {

+                               ((struct lys_feature*)actual)->iffeature = calloc(size_arrays->node[size_arrays->next].if_features,

+                                                                                sizeof *((struct lys_feature*)actual)->iffeature);

+                               if (!((struct lys_feature*)actual)->iffeature) {

                                  LOGMEM;

                                  YYABORT;

                                }

@@ -1493,8 +1493,8 @@
                                $$.container = actual;

                                actual_type = CONTAINER_KEYWORD;

                                if (size_arrays->node[size_arrays->next].if_features) {

-                                 $$.container->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.container->features);

-                                 if (!$$.container->features) {

+                                 $$.container->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.container->iffeature);

+                                 if (!$$.container->iffeature) {

                                    LOGMEM;

                                    YYABORT;

                                  }

@@ -1615,8 +1615,8 @@
                             $$.node.flag = 0;

                             actual_type = LEAF_KEYWORD;

                             if (size_arrays->node[size_arrays->next].if_features) {

-                              $$.node.ptr_leaf->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.node.ptr_leaf->features);

-                              if (!$$.node.ptr_leaf->features) {

+                              $$.node.ptr_leaf->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.node.ptr_leaf->iffeature);

+                              if (!$$.node.ptr_leaf->iffeature) {

                                 LOGMEM;

                                 YYABORT;

                               }

@@ -1734,8 +1734,8 @@
                                $$.node.flag = 0;

                                actual_type = LEAF_LIST_KEYWORD;

                                if (size_arrays->node[size_arrays->next].if_features) {

-                                 $$.node.ptr_leaflist->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.node.ptr_leaflist->features);

-                                 if (!$$.node.ptr_leaflist->features) {

+                                 $$.node.ptr_leaflist->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.node.ptr_leaflist->iffeature);

+                                 if (!$$.node.ptr_leaflist->iffeature) {

                                    LOGMEM;

                                    YYABORT;

                                  }

@@ -1890,8 +1890,8 @@
                           $$.node.flag = 0;

                           actual_type = LIST_KEYWORD;

                           if (size_arrays->node[size_arrays->next].if_features) {

-                            $$.node.ptr_list->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.node.ptr_list->features);

-                            if (!$$.node.ptr_list->features) {

+                            $$.node.ptr_list->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.node.ptr_list->iffeature);

+                            if (!$$.node.ptr_list->iffeature) {

                               LOGMEM;

                               YYABORT;

                             }

@@ -2080,8 +2080,8 @@
                             $$.choice.s = NULL;

                             actual_type = CHOICE_KEYWORD;

                             if (size_arrays->node[size_arrays->next].if_features) {

-                              $$.choice.ptr_choice->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.choice.ptr_choice->features);

-                              if (!$$.choice.ptr_choice->features) {

+                              $$.choice.ptr_choice->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.choice.ptr_choice->iffeature);

+                              if (!$$.choice.ptr_choice->iffeature) {

                                 LOGMEM;

                                 YYABORT;

                               }

@@ -2203,8 +2203,8 @@
                           $$.cs = actual;

                           actual_type = CASE_KEYWORD;

                           if (size_arrays->node[size_arrays->next].if_features) {

-                            $$.cs->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.cs->features);

-                            if (!$$.cs->features) {

+                            $$.cs->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.cs->iffeature);

+                            if (!$$.cs->iffeature) {

                               LOGMEM;

                               YYABORT;

                             }

@@ -2271,15 +2271,15 @@
                             $$.anyxml = actual;

                             actual_type = ANYXML_KEYWORD;

                             if (size_arrays->node[size_arrays->next].if_features) {

-                              $$.anyxml->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.anyxml->features);

-                              if (!$$.anyxml->features) {

+                              $$.anyxml->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.anyxml->iffeature);

+                              if (!$$.anyxml->iffeature) {

                                 LOGMEM;

                                 YYABORT;

                               }

                             }

                             if (size_arrays->node[size_arrays->next].must) {

                               $$.anyxml->must = calloc(size_arrays->node[size_arrays->next].must, sizeof *$$.anyxml->must);

-                              if (!$$.anyxml->features || !$$.anyxml->must) {

+                              if (!$$.anyxml->iffeature || !$$.anyxml->must) {

                                 LOGMEM;

                                 YYABORT;

                               }

@@ -2366,8 +2366,8 @@
                           $$.uses.config_inherit = config_inherit;

                           actual_type = USES_KEYWORD;

                           if (size_arrays->node[size_arrays->next].if_features) {

-                            $$.uses.ptr_uses->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.uses.ptr_uses->features);

-                            if (!$$.uses.ptr_uses->features) {

+                            $$.uses.ptr_uses->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.uses.ptr_uses->iffeature);

+                            if (!$$.uses.ptr_uses->iffeature) {

                               LOGMEM;

                               YYABORT;

                             }

@@ -2679,8 +2679,8 @@
                              $$.node.flag = 0;

                              actual_type = AUGMENT_KEYWORD;

                              if (size_arrays->node[size_arrays->next].if_features) {

-                               $$.node.ptr_augment->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.node.ptr_augment->features);

-                               if (!$$.node.ptr_augment->features) {

+                               $$.node.ptr_augment->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.node.ptr_augment->iffeature);

+                               if (!$$.node.ptr_augment->iffeature) {

                                  LOGMEM;

                                  YYABORT;

                                }

@@ -2746,7 +2746,7 @@
   ;

 

 rpc_stmt: RPC_KEYWORD sep identifier_arg_str { if (read_all) {

-                                                 if (!(actual = yang_read_node(trg, NULL, s, LYS_RPC, sizeof(struct lys_node_rpc)))) {

+                                                 if (!(actual = yang_read_node(trg, NULL, s, LYS_RPC, sizeof(struct lys_node_rpc_action)))) {

                                                    YYABORT;

                                                  }

                                                  data_node = actual;

@@ -2767,8 +2767,8 @@
                          $$.node.flag = 0;

                          actual_type = RPC_KEYWORD;

                          if (size_arrays->node[size_arrays->next].if_features) {

-                           $$.node.ptr_rpc->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.node.ptr_rpc->features);

-                           if (!$$.node.ptr_rpc->features) {

+                           $$.node.ptr_rpc->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.node.ptr_rpc->iffeature);

+                           if (!$$.node.ptr_rpc->iffeature) {

                              LOGMEM;

                              YYABORT;

                            }

@@ -2857,7 +2857,7 @@
                                        LOGMEM;

                                        YYABORT;

                                      }

-                                     if (!(actual = yang_read_node(trg, actual, s, LYS_INPUT, sizeof(struct lys_node_rpc_inout)))) {

+                                     if (!(actual = yang_read_node(trg, actual, s, LYS_INPUT, sizeof(struct lys_node_inout)))) {

                                       YYABORT;

                                      }

                                      data_node = actual;

@@ -2921,7 +2921,7 @@
                                          LOGMEM;

                                          YYABORT;

                                        }

-                                       if (!(actual = yang_read_node(trg, actual, s, LYS_OUTPUT, sizeof(struct lys_node_rpc_inout)))) {

+                                       if (!(actual = yang_read_node(trg, actual, s, LYS_OUTPUT, sizeof(struct lys_node_inout)))) {

                                         YYABORT;

                                        }

                                        data_node = actual;

@@ -2959,8 +2959,8 @@
                                   $$.notif = actual;

                                   actual_type = NOTIFICATION_KEYWORD;

                                   if (size_arrays->node[size_arrays->next].if_features) {

-                                    $$.notif->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.notif->features);

-                                    if (!$$.notif->features) {

+                                    $$.notif->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.notif->iffeature);

+                                    if (!$$.notif->iffeature) {

                                       LOGMEM;

                                       YYABORT;

                                     }

@@ -3765,7 +3765,7 @@
 

 string_opt_part3: @EMPTYDIR@

   |  string_opt_part3 '+' optsep STRING optsep

-  

+

 unknown_statement_end: ';'

   |  '{' optsep unknown_statement2_opt '}'

 

diff --git a/tests/api/test_tree_schema.c b/tests/api/test_tree_schema.c
index a73fff8..9624e97 100644
--- a/tests/api/test_tree_schema.c
+++ b/tests/api/test_tree_schema.c
@@ -97,14 +97,14 @@
     }\
     container x {\
         leaf bar-leaf {\
-            if-feature bar;\
+            if-feature \"bar\";\
             type string;\
         }\
         uses gg {\
-            if-feature bar;\
+            if-feature \"bar\";\
         }\
         leaf baz {\
-            if-feature foo;\
+            if-feature \"foo\";\
             type string;\
         }\
         leaf bubba {\
@@ -112,14 +112,14 @@
         }\
     }\
     augment \"/x\" {\
-        if-feature bar;\
+        if-feature \"bar\";\
         container bar-y;\
     }\
     rpc bar-rpc {\
-        if-feature bar;\
+        if-feature \"bar\";\
     }\
     rpc foo-rpc {\
-        if-feature foo;\
+        if-feature \"foo\";\
     }\
 }";
 
@@ -201,14 +201,14 @@
 \n\
   container x {\n\
     leaf bar-leaf {\n\
-      if-feature bar;\n\
+      if-feature \"bar\";\n\
       type string;\n\
     }\n\
     uses gg {\n\
-      if-feature bar;\n\
+      if-feature \"bar\";\n\
     }\n\
     leaf baz {\n\
-      if-feature foo;\n\
+      if-feature \"foo\";\n\
       type string;\n\
     }\n\
     leaf bubba {\n\
@@ -217,15 +217,15 @@
   }\n\
 \n\
   rpc bar-rpc {\n\
-    if-feature bar;\n\
+    if-feature \"bar\";\n\
   }\n\
 \n\
   rpc foo-rpc {\n\
-    if-feature foo;\n\
+    if-feature \"foo\";\n\
   }\n\
 \n\
   augment \"/x\" {\n\
-    if-feature bar;\n\
+    if-feature \"bar\";\n\
     container bar-y;\n\
   }\n\
 }\n";
@@ -577,7 +577,7 @@
     (void) state; /* unused */
     LYS_INFORMAT yang_format = LYS_IN_YIN;
     const struct lys_module *module;
-    const struct lys_feature *feature = NULL;
+    const struct lys_node *node = NULL;
     int rc;
 
     module = lys_parse_mem(ctx, lys_module_a, yang_format);
@@ -585,20 +585,20 @@
         fail();
     }
 
-    feature = lys_is_disabled(module->data->child, 2);
-    if (!feature) {
+    node = lys_is_disabled(module->data->child, 2);
+    if (!node) {
         fail();
     }
 
-    assert_string_equal("bar", feature->name);
+    assert_string_equal("/a:top", node->name);
 
     rc = lys_features_enable(module, "bar");
     if (rc) {
         fail();
     }
 
-    feature = lys_is_disabled(module->data->child, 2);
-    if (feature) {
+    node = lys_is_disabled(module->data->child, 2);
+    if (node) {
         fail();
     }
 }
diff --git a/tests/data/files/all-act.xml b/tests/data/files/all-act.xml
new file mode 100644
index 0000000..4231c04
--- /dev/null
+++ b/tests/data/files/all-act.xml
@@ -0,0 +1,10 @@
+<action xmlns="urn:ietf:params:xml:ns:yang:1">
+  <cont1 xmlns="urn:all">
+    <list1>
+      <leaf18>key_val</leaf18>
+      <act1>
+        <leaf24>some_input</leaf24>
+      </act1>
+    </list1>
+  </cont1>
+</action>
diff --git a/tests/data/files/all-actreply.xml b/tests/data/files/all-actreply.xml
new file mode 100644
index 0000000..afd0c9b
--- /dev/null
+++ b/tests/data/files/all-actreply.xml
@@ -0,0 +1 @@
+<leaf25 xmlns="urn:all">some_output</leaf25>
diff --git a/tests/data/files/all.yang b/tests/data/files/all.yang
index 69d5e31..c811246 100644
--- a/tests/data/files/all.yang
+++ b/tests/data/files/all.yang
@@ -1,4 +1,5 @@
 module all {
+  yang-version 1.1;
   namespace "urn:all";
   prefix all_mod;
 
@@ -8,7 +9,7 @@
 
   feature feat1 {
     status "obsolete";
-    if-feature feat2;
+    if-feature "feat2";
   }
 
   feature feat2;
@@ -43,12 +44,12 @@
 
   container cont1 {
     leaf leaf2 {
-      if-feature feat1;
+      if-feature "feat1";
       status "obsolete";
       type int16;
     }
     uses group1 {
-      if-feature feat2;
+      if-feature "feat2";
       refine "leaf1" {
         config true;
         mandatory false;
@@ -151,6 +152,18 @@
         type uint32;
       }
       anyxml axml1;
+      action act1 {
+        input {
+          leaf leaf24 {
+            type string;
+          }
+        }
+        output {
+          leaf leaf25 {
+            type string;
+          }
+        }
+      }
     }
     leaf-list llist1 {
       type tdef1;
diff --git a/tests/data/files/all.yin b/tests/data/files/all.yin
index 1b7c733..010188f 100644
--- a/tests/data/files/all.yin
+++ b/tests/data/files/all.yin
@@ -2,7 +2,7 @@
 <module name="all"
         xmlns="urn:ietf:params:xml:ns:yang:yin:1"
         xmlns:all_mod="urn:all">
-  <yang-version value="1"/>
+  <yang-version value="1.1"/>
   <namespace uri="urn:all"/>
   <prefix value="all_mod"/>
   <revision date="2016-05-23"/>
@@ -150,6 +150,18 @@
         <type name="uint32"/>
       </leaf>
       <anyxml name="axml1"/>
+      <action name="act1">
+        <input>
+          <leaf name="leaf24">
+            <type name="string"/>
+          </leaf>
+        </input>
+        <output>
+          <leaf name="leaf25">
+            <type name="string"/>
+          </leaf>
+        </output>
+      </action>
     </list>
     <leaf-list name="llist1">
       <type name="tdef1"/>
diff --git a/tests/data/test_parse_print.c b/tests/data/test_parse_print.c
index 0f9b944..0345c9f 100644
--- a/tests/data/test_parse_print.c
+++ b/tests/data/test_parse_print.c
@@ -60,6 +60,7 @@
         fprintf(stderr, "Failed to load data model \"%s\".\n", schema);
         goto error;
     }
+    lys_features_enable(st->mod, "feat2");
     lys_features_enable(st->mod, "*");
 
     st->mod = lys_parse_path(st->ctx, schemadev, LYS_IN_YIN);
@@ -210,6 +211,8 @@
     const char *data = TESTS_DIR"/data/files/all-data.xml";
     const char *rpc = TESTS_DIR"/data/files/all-rpc.xml";
     const char *rpcreply = TESTS_DIR"/data/files/all-rpcreply.xml";
+    const char *act = TESTS_DIR"/data/files/all-act.xml";
+    const char *actreply = TESTS_DIR"/data/files/all-actreply.xml";
     const char *notif = TESTS_DIR"/data/files/all-notif.xml";
 
     /* data */
@@ -285,6 +288,56 @@
     lyd_free(st->dt);
     st->dt = NULL;
 
+    /* act */
+    fd = open(act, O_RDONLY);
+    fstat(fd, &s);
+    st->str1 = malloc(s.st_size + 1);
+    assert_ptr_not_equal(st->str1, NULL);
+    assert_int_equal(read(fd, st->str1, s.st_size), s.st_size);
+    st->str1[s.st_size] = '\0';
+
+    st->dt = lyd_parse_path(st->ctx, act, LYD_XML, LYD_OPT_RPC);
+    assert_ptr_not_equal(st->dt, NULL);
+    lyd_print_mem(&(st->str2), st->dt, LYD_XML, LYP_FORMAT);
+
+    assert_string_equal(st->str1, st->str2);
+
+    close(fd);
+    fd = -1;
+    free(st->str1);
+    st->str1 = NULL;
+    free(st->str2);
+    st->str2 = NULL;
+    lyd_free(st->dt);
+    st->dt = NULL;
+
+    /* actreply */
+    fd = open(actreply, O_RDONLY);
+    fstat(fd, &s);
+    st->str1 = malloc(s.st_size + 1);
+    assert_ptr_not_equal(st->str1, NULL);
+    assert_int_equal(read(fd, st->str1, s.st_size), s.st_size);
+    st->str1[s.st_size] = '\0';
+
+    rpc_schema = ly_ctx_get_node(st->ctx, NULL, "/all:cont1/list1/act1");
+    assert_ptr_not_equal(rpc_schema, NULL);
+    assert_int_equal(rpc_schema->nodetype, LYS_ACTION);
+
+    st->dt = lyd_parse_path(st->ctx, actreply, LYD_XML, LYD_OPT_RPCREPLY, rpc_schema);
+    assert_ptr_not_equal(st->dt, NULL);
+    lyd_print_mem(&(st->str2), st->dt->child, LYD_XML, LYP_FORMAT);
+
+    assert_string_equal(st->str1, st->str2);
+
+    close(fd);
+    fd = -1;
+    free(st->str1);
+    st->str1 = NULL;
+    free(st->str2);
+    st->str2 = NULL;
+    lyd_free(st->dt);
+    st->dt = NULL;
+
     /* notif */
     fd = open(notif, O_RDONLY);
     fstat(fd, &s);
diff --git a/tests/schema/yin/files/d2_output.yang b/tests/schema/yin/files/d2_output.yang
index 4152139..f428834 100644
--- a/tests/schema/yin/files/d2_output.yang
+++ b/tests/schema/yin/files/d2_output.yang
@@ -7,7 +7,7 @@
   }
 
   feature d2_feat {
-    if-feature d1_pref:d1_feat;
+    if-feature "d1_pref:d1_feat";
   }
 
   identity d2_ident {