diff --git a/src/others/xml/parsers/lv_xml_keyboard_parser.c b/src/others/xml/parsers/lv_xml_keyboard_parser.c
new file mode 100644
index 0000000000..f4ed974b5d
--- /dev/null
+++ b/src/others/xml/parsers/lv_xml_keyboard_parser.c
@@ -0,0 +1,85 @@
+/**
+ * @file lv_xml_keyboard_parser.c
+ *
+ */
+
+/*********************
+ * INCLUDES
+ *********************/
+#include "lv_xml_keyboard_parser.h"
+#if LV_USE_XML
+
+#include "../../../lvgl.h"
+#include "../../../lvgl_private.h"
+
+/*********************
+ * DEFINES
+ *********************/
+
+/**********************
+ * TYPEDEFS
+ **********************/
+
+/**********************
+ * STATIC PROTOTYPES
+ **********************/
+static lv_keyboard_mode_t mode_text_to_enum_value(const char * txt);
+
+/**********************
+ * STATIC VARIABLES
+ **********************/
+
+/**********************
+ * MACROS
+ **********************/
+
+/**********************
+ * GLOBAL FUNCTIONS
+ **********************/
+
+void * lv_xml_keyboard_create(lv_xml_parser_state_t * state, const char ** attrs)
+{
+ LV_UNUSED(attrs);
+ void * item = lv_keyboard_create(lv_xml_state_get_parent(state));
+
+ return item;
+}
+
+void lv_xml_keyboard_apply(lv_xml_parser_state_t * state, const char ** attrs)
+{
+ void * item = lv_xml_state_get_item(state);
+
+ lv_xml_obj_apply(state, attrs); /*Apply the common properties, e.g. width, height, styles flags etc*/
+
+ for(int i = 0; attrs[i]; i += 2) {
+ const char * name = attrs[i];
+ const char * value = attrs[i + 1];
+
+ // if(lv_streq("textarea", name)) lv_keyboard_set_mode(item, lv_obj_get_child_by_name());
+ if(lv_streq("mode", name)) lv_keyboard_set_mode(item, mode_text_to_enum_value(value));
+ }
+}
+
+/**********************
+ * STATIC FUNCTIONS
+ **********************/
+
+static lv_keyboard_mode_t mode_text_to_enum_value(const char * txt)
+{
+ if(lv_streq("text_upper", txt)) return LV_KEYBOARD_MODE_TEXT_UPPER;
+ if(lv_streq("text_lower", txt)) return LV_KEYBOARD_MODE_TEXT_LOWER;
+#if LV_USE_ARABIC_PERSIAN_CHARS == 1
+ if(lv_streq("text_arabic", txt)) return LV_KEYBOARD_MODE_TEXT_ARABIC;
+#endif
+ if(lv_streq("number", txt)) return LV_KEYBOARD_MODE_NUMBER;
+ if(lv_streq("special", txt)) return LV_KEYBOARD_MODE_SPECIAL;
+ if(lv_streq("user_1", txt)) return LV_KEYBOARD_MODE_USER_1;
+ if(lv_streq("user_2", txt)) return LV_KEYBOARD_MODE_USER_2;
+ if(lv_streq("user_3", txt)) return LV_KEYBOARD_MODE_USER_3;
+ if(lv_streq("user_4", txt)) return LV_KEYBOARD_MODE_USER_4;
+
+ LV_LOG_WARN("%s is an unknown value for keyboard's mode", txt);
+ return 0; /*Return 0 in lack of a better option. */
+}
+
+#endif /* LV_USE_XML */
diff --git a/src/others/xml/parsers/lv_xml_keyboard_parser.h b/src/others/xml/parsers/lv_xml_keyboard_parser.h
new file mode 100644
index 0000000000..b00e998562
--- /dev/null
+++ b/src/others/xml/parsers/lv_xml_keyboard_parser.h
@@ -0,0 +1,41 @@
+/**
+ * @file lv_xml_keyboard_parser.h
+ *
+ */
+
+#ifndef LV_KEYBOARD_XML_PARSER_H
+#define LV_KEYBOARD_XML_PARSER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*********************
+ * INCLUDES
+ *********************/
+#include "../lv_xml.h"
+#if LV_USE_XML
+
+/**********************
+ * TYPEDEFS
+ **********************/
+
+/**********************
+ * GLOBAL PROTOTYPES
+ **********************/
+
+void * lv_xml_keyboard_create(lv_xml_parser_state_t * state, const char ** attrs);
+
+void lv_xml_keyboard_apply(lv_xml_parser_state_t * state, const char ** attrs);
+
+/**********************
+ * MACROS
+ **********************/
+
+#endif /* LV_USE_XML */
+
+#ifdef __cplusplus
+} /*extern "C"*/
+#endif
+
+#endif /*LV_KEYBOARD_XML_PARSE_H*/
diff --git a/src/others/xml/parsers/lv_xml_textarea_parser.c b/src/others/xml/parsers/lv_xml_textarea_parser.c
new file mode 100644
index 0000000000..cea2c7efc4
--- /dev/null
+++ b/src/others/xml/parsers/lv_xml_textarea_parser.c
@@ -0,0 +1,72 @@
+/**
+ * @file lv_xml_textarea_parser.c
+ *
+ */
+
+/*********************
+ * INCLUDES
+ *********************/
+#include "lv_xml_textarea_parser.h"
+#if LV_USE_XML
+
+#include "../../../lvgl.h"
+#include "../../../lvgl_private.h"
+
+/*********************
+ * DEFINES
+ *********************/
+
+/**********************
+ * TYPEDEFS
+ **********************/
+
+/**********************
+ * STATIC PROTOTYPES
+ **********************/
+
+/**********************
+ * STATIC VARIABLES
+ **********************/
+
+/**********************
+ * MACROS
+ **********************/
+
+/**********************
+ * GLOBAL FUNCTIONS
+ **********************/
+
+void * lv_xml_textarea_create(lv_xml_parser_state_t * state, const char ** attrs)
+{
+ LV_UNUSED(attrs);
+ void * item = lv_textarea_create(lv_xml_state_get_parent(state));
+
+ return item;
+}
+
+void lv_xml_textarea_apply(lv_xml_parser_state_t * state, const char ** attrs)
+{
+ void * item = lv_xml_state_get_item(state);
+
+ lv_xml_obj_apply(state, attrs); /*Apply the common properties, e.g. width, height, styles flags etc*/
+
+ for(int i = 0; attrs[i]; i += 2) {
+ const char * name = attrs[i];
+ const char * value = attrs[i + 1];
+
+
+ if(lv_streq("text", name)) lv_textarea_set_text(item, value);
+ else if(lv_streq("placeholder", name)) lv_textarea_set_placeholder_text(item, value);
+ else if(lv_streq("one_line", name)) lv_textarea_set_one_line(item, lv_xml_to_bool(value));
+ else if(lv_streq("password_mode", name)) lv_textarea_set_password_mode(item, lv_xml_to_bool(value));
+ else if(lv_streq("password_show_time", name)) lv_textarea_set_password_show_time(item, lv_xml_atoi(value));
+ else if(lv_streq("text_selection", name)) lv_textarea_set_text_selection(item, lv_xml_to_bool(value));
+ else if(lv_streq("cursor_pos", name)) lv_textarea_set_cursor_pos(item, lv_xml_atoi(value));
+ }
+}
+
+/**********************
+ * STATIC FUNCTIONS
+ **********************/
+
+#endif /* LV_USE_XML */
diff --git a/src/others/xml/parsers/lv_xml_textarea_parser.h b/src/others/xml/parsers/lv_xml_textarea_parser.h
new file mode 100644
index 0000000000..6269cac03a
--- /dev/null
+++ b/src/others/xml/parsers/lv_xml_textarea_parser.h
@@ -0,0 +1,41 @@
+/**
+ * @file lv_xml_textarea_parser.h
+ *
+ */
+
+#ifndef LV_TEXTAREA_XML_PARSER_H
+#define LV_TEXTAREA_XML_PARSER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*********************
+ * INCLUDES
+ *********************/
+#include "../lv_xml.h"
+#if LV_USE_XML
+
+/**********************
+ * TYPEDEFS
+ **********************/
+
+/**********************
+ * GLOBAL PROTOTYPES
+ **********************/
+
+void * lv_xml_textarea_create(lv_xml_parser_state_t * state, const char ** attrs);
+
+void lv_xml_textarea_apply(lv_xml_parser_state_t * state, const char ** attrs);
+
+/**********************
+ * MACROS
+ **********************/
+
+#endif /* LV_USE_XML */
+
+#ifdef __cplusplus
+} /*extern "C"*/
+#endif
+
+#endif /*LV_TEXTAREA_XML_PARSE_H*/
diff --git a/tests/ref_imgs/xml/lv_keyboard.png b/tests/ref_imgs/xml/lv_keyboard.png
new file mode 100644
index 0000000000..7ef073174a
Binary files /dev/null and b/tests/ref_imgs/xml/lv_keyboard.png differ
diff --git a/tests/ref_imgs/xml/lv_textarea.png b/tests/ref_imgs/xml/lv_textarea.png
new file mode 100644
index 0000000000..25c208922a
Binary files /dev/null and b/tests/ref_imgs/xml/lv_textarea.png differ
diff --git a/tests/ref_imgs_vg_lite/xml/lv_keyboard.png b/tests/ref_imgs_vg_lite/xml/lv_keyboard.png
new file mode 100644
index 0000000000..a10a6fa913
Binary files /dev/null and b/tests/ref_imgs_vg_lite/xml/lv_keyboard.png differ
diff --git a/tests/ref_imgs_vg_lite/xml/lv_textarea.png b/tests/ref_imgs_vg_lite/xml/lv_textarea.png
new file mode 100644
index 0000000000..032154f32f
Binary files /dev/null and b/tests/ref_imgs_vg_lite/xml/lv_textarea.png differ
diff --git a/tests/src/test_cases/xml/test_xml_keyboard.c b/tests/src/test_cases/xml/test_xml_keyboard.c
new file mode 100644
index 0000000000..a9e7b86bc5
--- /dev/null
+++ b/tests/src/test_cases/xml/test_xml_keyboard.c
@@ -0,0 +1,31 @@
+#if LV_BUILD_TEST
+#include "../lvgl.h"
+
+#include "unity/unity.h"
+
+void setUp(void)
+{
+ /* Function run before every test */
+}
+
+void tearDown(void)
+{
+ /* Function run after every test */
+ lv_obj_clean(lv_screen_active());
+}
+
+void test_xml_image_with_attrs(void)
+{
+ lv_obj_t * scr = lv_screen_active();
+
+ const char * keyboard1_attrs[] = {
+ "mode", "text_upper",
+ NULL, NULL,
+ };
+
+ lv_xml_create(scr, "lv_keyboard", keyboard1_attrs);
+
+ TEST_ASSERT_EQUAL_SCREENSHOT("xml/lv_keyboard.png");
+}
+
+#endif
diff --git a/tests/src/test_cases/xml/test_xml_textarea.c b/tests/src/test_cases/xml/test_xml_textarea.c
new file mode 100644
index 0000000000..75570e56aa
--- /dev/null
+++ b/tests/src/test_cases/xml/test_xml_textarea.c
@@ -0,0 +1,36 @@
+#if LV_BUILD_TEST
+#include "../lvgl.h"
+
+#include "unity/unity.h"
+
+void setUp(void)
+{
+ /* Function run before every test */
+}
+
+void tearDown(void)
+{
+ /* Function run after every test */
+ lv_obj_clean(lv_screen_active());
+}
+
+void test_xml_textarea_with_attrs(void)
+{
+ lv_obj_t * scr = lv_screen_active();
+
+ const char * textarea1_attrs[] = {
+ "text", "This is the text",
+ "style_text_align", "center",
+ "one_line", "true",
+ "width", "400",
+ "align", "center",
+ NULL, NULL,
+ };
+
+ lv_xml_create(scr, "lv_textarea", textarea1_attrs);
+
+
+ TEST_ASSERT_EQUAL_SCREENSHOT("xml/lv_textarea.png");
+}
+
+#endif
diff --git a/xmls/lv_keyboard.xml b/xmls/lv_keyboard.xml
new file mode 100644
index 0000000000..5eeb3a8fb9
--- /dev/null
+++ b/xmls/lv_keyboard.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/xmls/lv_textarea.xml b/xmls/lv_textarea.xml
new file mode 100644
index 0000000000..fb66f5d486
--- /dev/null
+++ b/xmls/lv_textarea.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file