types FEATURE support empty data type values
diff --git a/src/plugins_types.c b/src/plugins_types.c
index 9b88174..4e29fb0 100644
--- a/src/plugins_types.c
+++ b/src/plugins_types.c
@@ -1021,7 +1021,7 @@
  * Implementation of the ly_type_validate_clb.
  */
 static LY_ERR
-ly_type_validate_boolean(struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, int options,
+ly_type_validate_boolean(struct ly_ctx *ctx, struct lysc_type *UNUSED(type), const char *value, size_t value_len, int options,
                          const char **canonized, struct ly_err_item **err, void **priv)
 {
     int8_t i;
@@ -1084,6 +1084,28 @@
     return LY_SUCCESS;
 }
 
+/**
+ * @brief Validate value of the YANG built-in empty type.
+ *
+ * Implementation of the ly_type_validate_clb.
+ */
+static LY_ERR
+ly_type_validate_empty(struct ly_ctx *ctx, struct lysc_type *UNUSED(type), const char *value, size_t value_len, int options,
+                       const char **canonized, struct ly_err_item **err, void **UNUSED(priv))
+{
+    if (value_len) {
+        char *errmsg;
+        asprintf(&errmsg, "Invalid empty value \"%.*s\".", (int)value_len, value);
+        *err = ly_err_new(LY_LLERR, LY_EVALID, LYVE_RESTRICTION, errmsg, NULL, NULL);
+        return LY_EVALID;
+    }
+
+    if (options & LY_TYPE_OPTS_CANONIZE) {
+        *canonized = lydict_insert(ctx, "", 0);
+    }
+    return LY_SUCCESS;
+}
+
 struct lysc_type_plugin ly_builtin_type_plugins[LY_DATA_TYPE_COUNT] = {
     {0}, /* LY_TYPE_UNKNOWN */
     {.type = LY_TYPE_BINARY, .validate = ly_type_validate_binary, .store = NULL, .free = NULL},
@@ -1095,7 +1117,7 @@
     {.type = LY_TYPE_BITS, .validate = ly_type_validate_bits, .store = ly_type_store_bits, .free = ly_type_free_bits},
     {.type = LY_TYPE_BOOL, .validate = ly_type_validate_boolean, .store = ly_type_store_boolean, .free = NULL},
     {.type = LY_TYPE_DEC64, .validate = ly_type_validate_decimal64, .store = ly_type_store_decimal64, .free = NULL},
-    {0}, /* TODO LY_TYPE_EMPTY */
+    {.type = LY_TYPE_EMPTY, .validate = ly_type_validate_empty, .store = NULL, .free = NULL},
     {.type = LY_TYPE_ENUM, .validate = ly_type_validate_enum, .store = ly_type_store_enum, .free = NULL},
     {0}, /* TODO LY_TYPE_IDENT */
     {0}, /* TODO LY_TYPE_INST */
diff --git a/tests/features/test_types.c b/tests/features/test_types.c
index 536069d..faf6d70 100644
--- a/tests/features/test_types.c
+++ b/tests/features/test_types.c
@@ -73,7 +73,8 @@
             "leaf dec64-norestr {type decimal64 {fraction-digits 18;}}"
             "leaf str {type string {length 8..10; pattern '[a-z ]*';}}"
             "leaf str-norestr {type string;}"
-            "leaf bool {type boolean;}}";
+            "leaf bool {type boolean;}"
+            "leaf empty {type empty;}}";
 
     s = calloc(1, sizeof *s);
     assert_non_null(s);
@@ -549,6 +550,45 @@
     s->func = NULL;
 }
 
+static void
+test_empty(void **state)
+{
+    struct state_s *s = (struct state_s*)(*state);
+    s->func = test_empty;
+
+    struct lyd_node *tree;
+    struct lyd_node_term *leaf;
+
+    const char *data = "<empty xmlns=\"urn:tests:types\"></empty>";
+
+    /* valid data */
+    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, 0));
+    assert_int_equal(LYS_LEAF, tree->schema->nodetype);
+    assert_string_equal("empty", tree->schema->name);
+    leaf = (struct lyd_node_term*)tree;
+    assert_string_equal("", leaf->value.canonized);
+    lyd_free_all(tree);
+
+    data = "<empty xmlns=\"urn:tests:types\"/>";
+    assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, 0));
+    assert_int_equal(LYS_LEAF, tree->schema->nodetype);
+    assert_string_equal("empty", tree->schema->name);
+    leaf = (struct lyd_node_term*)tree;
+    assert_string_equal("", leaf->value.canonized);
+    lyd_free_all(tree);
+
+    /* invalid value */
+    data = "<empty xmlns=\"urn:tests:types\">x</empty>";
+    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, 0));
+    logbuf_assert("Invalid empty value \"x\". /");
+
+    data = "<empty xmlns=\"urn:tests:types\"> </empty>";
+    assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, 0));
+    logbuf_assert("Invalid empty value \" \". /");
+
+    s->func = NULL;
+}
+
 int main(void)
 {
     const struct CMUnitTest tests[] = {
@@ -560,6 +600,7 @@
         cmocka_unit_test_setup_teardown(test_enums, setup, teardown),
         cmocka_unit_test_setup_teardown(test_binary, setup, teardown),
         cmocka_unit_test_setup_teardown(test_boolean, setup, teardown),
+        cmocka_unit_test_setup_teardown(test_empty, setup, teardown),
     };
 
     return cmocka_run_group_tests(tests, NULL, NULL);