diff --git a/sefht.geany b/sefht.geany
index fabc8165b2bdb1bb56f4a1f06689994b03ce7a0c..d0398d5b8b6441edfdb4f4e83a8bff4edd65e0f9 100644
--- a/sefht.geany
+++ b/sefht.geany
@@ -64,7 +64,7 @@ FILE_NAME_31=1303;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fp
 FILE_NAME_32=10846;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator_tag.c;0;8
 FILE_NAME_33=1068;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator_tag.h;0;8
 FILE_NAME_34=1287;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator_tag_data.h;0;8
-FILE_NAME_35=15745;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator_attr.c;0;8
+FILE_NAME_35=23338;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator_attr.c;0;8
 FILE_NAME_36=1051;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator_attr.h;0;8
 FILE_NAME_37=1413;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator_attr_data.h;0;8
 FILE_NAME_38=924;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fstatus.h;0;8
@@ -83,8 +83,8 @@ FILE_NAME_50=4221;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fp
 FILE_NAME_51=994;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_text_mark.c;0;8
 FILE_NAME_52=2447;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_validator.c;0;8
 FILE_NAME_53=9409;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_validator_tag.c;0;8
-FILE_NAME_54=17869;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_validator_attr.c;0;8
-FILE_NAME_55=547;None;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftodo.txt;0;8
+FILE_NAME_54=45433;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_validator_attr.c;0;8
+FILE_NAME_55=556;None;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftodo.txt;0;8
 FILE_NAME_56=201;YAML;0;EUTF-8;0;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2F.gitlab-ci.yml;0;4
 FILE_NAME_57=71;Sh;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fgitlab-ci%2Fupload.sh.in;0;8
 FILE_NAME_58=806;Sh;0;EUTF-8;0;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fgitlab-ci%2Frelease.sh.in;0;4
diff --git a/src/lib/sefht/validator_attr.c b/src/lib/sefht/validator_attr.c
index 46eb4bd78234ef6019d913b832d35d3f95f0db06..81d9754fcd8bdf6112abc97791b56819ef51d461 100644
--- a/src/lib/sefht/validator_attr.c
+++ b/src/lib/sefht/validator_attr.c
@@ -130,7 +130,7 @@ static inline
 bool
 add_attr (struct SH_Validator * validator,
           const char * attr,
-          /*@dependent@*/ const char * tag,
+          /*@null@*/ /*@dependent@*/ const char * tag,
           size_t index,
           /*@null@*/ /*@out@*/ struct SH_Status * status)
 	/*@modifies validator->attrs@*/
@@ -155,7 +155,7 @@ static inline
 bool
 attr_add_tag (struct attr_info * attr,
               const size_t index,
-              /*@dependent@*/ const char * tag,
+              /*@null@*/ /*@dependent@*/ const char * tag,
               /*@null@*/ /*@out@*/ struct SH_Status * status)
 	/*@modifies attr@*/
 	/*@globals fileSystem@*/
@@ -241,6 +241,13 @@ init_attr_from_spec (/*@special@*/ struct SH_Validator * validator,
 		return FALSE;
 	}
 
+	if (0 == spec.tag_n)
+	{
+		attr_data->tags = NULL;
+		attr_data->tag_n = 0;
+		return TRUE;
+	}
+
 	if (spec.tag_n >= (SIZE_MAX / sizeof (struct attr_tag_info)))
 	{
 		set_status (status, E_DOMAIN, 2,
@@ -356,6 +363,13 @@ init_attrs_from_spec (/*@special@*/ struct SH_Validator * validator,
 			attrs[position] = attr_data;
 			attr_n++;
 		}
+		else if ((0 == spec[index].tag_n)
+		&& (0 != attrs[position].tag_n))
+		{
+			free (attrs[position].tags);
+			attrs[position].tags = NULL;
+			attrs[position].tag_n = 0;
+		}
 	}
 	#undef attr_n
 	#undef attrs
@@ -389,12 +403,20 @@ copy_attr (/*@special@*/ struct attr_info * copy,
 		return FALSE;
 	}
 
-	tags = malloc (sizeof (struct attr_tag_info) * attr->tag_n);
-	if (NULL == tags)
+	if (0 == attr->tag_n)
 	{
-		set_status (status, E_ALLOC, 3, "malloc failed");
-		free (name);
-		return FALSE;
+		tags = NULL;
+	}
+	else
+	{
+		tags = malloc (attr->tag_n
+		               * sizeof (struct attr_tag_info));
+		if (NULL == tags)
+		{
+			set_status (status, E_ALLOC, 3, "malloc failed");
+			free (name);
+			return FALSE;
+		}
 	}
 
 	copy->name = name;
@@ -458,7 +480,7 @@ free_attr (struct attr_info attr)
 	/*@releases attr.name@*/
 {
 	free (attr.name);
-	free (attr.tags);
+	if (0 != attr.tag_n) free (attr.tags);
 	return;
 }
 
@@ -561,7 +583,7 @@ static inline
 bool
 add_attr (struct SH_Validator * validator,
           const char * attr,
-          /*@dependent@*/ const char * tag,
+          /*@null@*/ /*@dependent@*/ const char * tag,
           size_t index,
           /*@null@*/ /*@out@*/ struct SH_Status * status)
 	/*@modifies validator->attrs@*/
@@ -592,16 +614,24 @@ add_attr (struct SH_Validator * validator,
 		return FALSE;
 	}
 
-	attr_data.tags = malloc (sizeof (struct attr_tag_info));
-	if (NULL == attr_data.tags)
+	if (NULL == tag)
 	{
-		set_status (status, E_ALLOC, 3, "malloc failed");
-		free (attr_data.name);
-		return FALSE;
+		attr_data.tags = NULL;
+		attr_data.tag_n = 0;
 	}
+	else
+	{
+		attr_data.tags = malloc (sizeof (struct attr_tag_info));
+		if (NULL == attr_data.tags)
+		{
+			set_status (status, E_ALLOC, 3, "malloc failed");
+			free (attr_data.name);
+			return FALSE;
+		}
 
-	attr_data.tags[0].name = tag;
-	attr_data.tag_n = 1;
+		attr_data.tags[0].name = tag;
+		attr_data.tag_n = 1;
+	}
 
 	/* allocate new space */
 	/* The addition and the multiplication is save,
@@ -690,7 +720,7 @@ static inline
 bool
 attr_add_tag (struct attr_info * attr,
               const size_t index,
-              /*@dependent@*/ const char * tag,
+              /*@null@*/ /*@dependent@*/ const char * tag,
               /*@null@*/ /*@out@*/ struct SH_Status * status)
 	/*@modifies attr@*/
 	/*@globals fileSystem@*/
@@ -699,6 +729,22 @@ attr_add_tag (struct attr_info * attr,
 {
 	struct attr_tag_info * new_tags;
 
+	if (0 == attr->tag_n)
+	{
+		set_success (status);
+		return TRUE;
+	}
+
+	if (NULL == tag)
+	{
+		free (attr->tags);
+		attr->tags = NULL;
+		attr->tag_n = 0;
+
+		set_success (status);
+		return TRUE;
+	}
+
 	if ((attr->tag_n == SIZE_MAX)
 	|| ((attr->tag_n + 1)
 	            > (SIZE_MAX / sizeof (struct attr_tag_info))))
@@ -840,6 +886,9 @@ SH_Validator_check_attr (struct SH_Validator * validator,
 		if (!find_tag (validator, tag, &index)) return FALSE;
 		tag = validator->tags[index].name;
 
+		/* global attr */
+		if (0 == attr->tag_n) return TRUE;
+
 		if (!find_attr_tag (attr, tag, &index)) return FALSE;
 	}
 
@@ -848,7 +897,7 @@ SH_Validator_check_attr (struct SH_Validator * validator,
 
 bool
 SH_Validator_register_attr (struct SH_Validator * validator,
-                            const char * tag,
+                            /*@null@*/ const char * tag,
                             const char * attr,
                             /*@null@*/ /*@out@*/
                             struct SH_Status * status)
@@ -861,13 +910,16 @@ SH_Validator_register_attr (struct SH_Validator * validator,
 	/* note, that index is used for three different arrays */
 	size_t index;
 
-	if ((!find_tag (validator, tag, &index))
-	&& (!add_tag (validator, tag, index, status)))
+	if (NULL != tag)
 	{
-		return FALSE;
-	}
+		if ((!find_tag (validator, tag, &index))
+		&& (!add_tag (validator, tag, index, status)))
+		{
+			return FALSE;
+		}
 
-	tag = validator->tags[index].name;
+		tag = validator->tags[index].name;
+	}
 
 	/* attr already registered */
 	if (find_attr (validator, attr, &index))
@@ -875,6 +927,11 @@ SH_Validator_register_attr (struct SH_Validator * validator,
 		struct attr_info * attr;
 		attr = &validator->attrs[index];
 
+		if (NULL == tag)
+		{
+			return attr_add_tag (attr, 0, NULL, status);
+		}
+
 		if ((!find_attr_tag (attr, tag, &index))
 		&& (!attr_add_tag (attr, index, tag, status)))
 		{
@@ -962,6 +1019,15 @@ SH_Validator_deregister_attr (struct SH_Validator * validator,
 
 		tag = validator->tags[index].name;
 
+		if (0 == attr->tag_n)
+		{
+			set_status (status, E_STATE, 2,
+			            "can't remove specific tag "
+			            "for global attribute, "
+			            "please localize first");
+			return FALSE;
+		}
+
 		if (!find_attr_tag (attr, tag, &index))
 		{
 			/* TODO: define whether this is an error */
diff --git a/tests/test_validator_attr.c b/tests/test_validator_attr.c
index 65f777542594d3fe46f04aa6a22d7ba09050fd88..1fd121ee216fed644fdcca7a9327193c2344c44b 100644
--- a/tests/test_validator_attr.c
+++ b/tests/test_validator_attr.c
@@ -45,11 +45,15 @@ const struct HTML_TAG_DEFINITION HTML_TAGS[] = {
 	{"html"},
 	{"aside"},
 	{"a"},
+	{"p"},
 };
 
 const struct HTML_ATTR_DEFINITION HTML_ATTRS[] = {
 	{"lang", &HTML_TAGS[0], 2},
 	{"href", &HTML_TAGS[2], 1},
+	{"class", &HTML_TAGS[3], 1},
+	{"id", NULL, 0},
+	{"class", NULL, 0},
 };
 
 #define HTML5_TAGS HTML_TAGS
@@ -99,13 +103,17 @@ START_TEST(test_validator_copy_no_status)
 	validator = SH_Validator_new_html5 (NULL);
 	ck_assert_ptr_ne (NULL, validator);
 
-	result = SH_Validator_register_attr (validator, "body", "id",
+	result = SH_Validator_register_attr (validator, NULL, "id",
 	                                     NULL);
-	ck_assert_int_ne (FALSE, result);
+	ck_assert_int_eq (TRUE, result);
 
 	result = SH_Validator_register_attr (validator, "html", "lang",
 	                                     NULL);
-	ck_assert_int_ne (FALSE, result);
+	ck_assert_int_eq (TRUE, result);
+
+	result = SH_Validator_register_attr (validator, "p", "lang",
+	                                     NULL);
+	ck_assert_int_eq (TRUE, result);
 
 	/* test */
 	copy = SH_Validator_copy (validator, NULL);
@@ -129,6 +137,11 @@ START_TEST(test_validator_copy_no_status)
 		{
 			TEST_PTR(attrs[index].tags[j].name)
 		}
+
+		if (0 == validator->attrs[index].tag_n)
+		{
+			TEST_PTR(attrs[index].tags);
+		}
 	}
 	#undef TEST_INT
 	#undef TEST_PTR
@@ -150,13 +163,17 @@ START_TEST(test_validator_copy_with_status)
 	validator = SH_Validator_new_html5 (NULL);
 	ck_assert_ptr_ne (NULL, validator);
 
-	result = SH_Validator_register_attr (validator, "body", "id",
+	result = SH_Validator_register_attr (validator, NULL, "id",
 	                                     NULL);
-	ck_assert_int_ne (FALSE, result);
+	ck_assert_int_eq (TRUE, result);
 
 	result = SH_Validator_register_attr (validator, "html", "lang",
 	                                     NULL);
-	ck_assert_int_ne (FALSE, result);
+	ck_assert_int_eq (TRUE, result);
+
+	result = SH_Validator_register_attr (validator, "p", "lang",
+	                                     NULL);
+	ck_assert_int_eq (TRUE, result);
 
 	/* test */
 	_status_preinit (status);
@@ -182,6 +199,11 @@ START_TEST(test_validator_copy_with_status)
 		{
 			TEST_PTR(attrs[index].tags[j].name)
 		}
+
+		if (0 == validator->attrs[index].tag_n)
+		{
+			TEST_PTR(attrs[index].tags);
+		}
 	}
 	#undef TEST_INT
 	#undef TEST_PTR
@@ -201,40 +223,60 @@ START_TEST(test_validator_spec_no_status)
 	ck_assert_ptr_ne (NULL, validator);
 
 	ck_assert_ptr_ne (NULL, validator->attrs);
-	ck_assert_int_eq (2, validator->attr_n);
+	ck_assert_int_eq (4, validator->attr_n);
 
 	#define attrs validator->attrs
-	#define TEST_STR(S1, S2) ck_assert_ptr_ne (S1, S2);            \
-	                         ck_assert_str_eq (S1, S2);
-
-	ck_assert_ptr_ne (HTML_ATTRS[1].attr, attrs[0].name);
-	ck_assert_str_eq (HTML_ATTRS[1].attr, attrs[0].name);
-	ck_assert_int_eq (HTML_ATTRS[1].tag_n, attrs[0].tag_n);
-	ck_assert_ptr_ne (NULL, attrs[0].tags);
 
-	TEST_STR (HTML_TAGS[2].tag, attrs[0].tags[0].name);
+	/* lang, 2 tags */
+	ck_assert_str_eq ("lang", HTML_ATTRS[0].attr);
+	ck_assert_ptr_ne (HTML_ATTRS[0].attr, attrs[3].name);
+	ck_assert_str_eq (HTML_ATTRS[0].attr, attrs[3].name);
+	ck_assert_int_eq (HTML_ATTRS[0].tag_n, attrs[3].tag_n);
+	ck_assert_ptr_ne (NULL, attrs[3].tags);
 
-	ck_assert_ptr_ne (HTML_ATTRS[0].attr, attrs[1].name);
-	ck_assert_str_eq (HTML_ATTRS[0].attr, attrs[1].name);
-	ck_assert_int_eq (HTML_ATTRS[0].tag_n, attrs[1].tag_n);
-	ck_assert_ptr_ne (NULL, attrs[1].tags);
 
+	#define TEST_STR(S1, S2) ck_assert_ptr_ne (S1, S2);            \
+	                         ck_assert_str_eq (S1, S2);
 	/* The storage order depends on the relative position of memory,
 	 * allocated by different malloc calls. This can change and
 	 * thus must be determined. */
-	if (attrs[1].tags[0].name[0]
-	  > attrs[1].tags[1].name[0])
+	if (attrs[3].tags[0].name[0]
+	  > attrs[3].tags[1].name[0])
 	{
-		TEST_STR (HTML_TAGS[0].tag, attrs[1].tags[0].name);
-		TEST_STR (HTML_TAGS[1].tag, attrs[1].tags[1].name);
+		TEST_STR (HTML_TAGS[0].tag, attrs[3].tags[0].name);
+		TEST_STR (HTML_TAGS[1].tag, attrs[3].tags[1].name);
 	}
 	else
 	{
-		TEST_STR (HTML_TAGS[1].tag, attrs[1].tags[0].name);
-		TEST_STR (HTML_TAGS[0].tag, attrs[1].tags[1].name);
+		TEST_STR (HTML_TAGS[1].tag, attrs[3].tags[0].name);
+		TEST_STR (HTML_TAGS[0].tag, attrs[3].tags[1].name);
 	}
-
 	#undef TEST_STR
+
+	/* href, 1 tag */
+	ck_assert_str_eq ("href", HTML_ATTRS[1].attr);
+	ck_assert_ptr_ne (HTML_ATTRS[1].attr, attrs[1].name);
+	ck_assert_str_eq (HTML_ATTRS[1].attr, attrs[1].name);
+	ck_assert_int_eq (HTML_ATTRS[1].tag_n, attrs[1].tag_n);
+	ck_assert_ptr_ne (NULL, attrs[1].tags);
+
+	ck_assert_ptr_ne (HTML_TAGS[2].tag, attrs[1].tags[0].name);
+	ck_assert_str_eq (HTML_TAGS[2].tag, attrs[1].tags[0].name);
+
+	/* class, global, overwrite */
+	ck_assert_str_eq ("class", HTML_ATTRS[2].attr);
+	ck_assert_ptr_ne (HTML_ATTRS[2].attr, attrs[0].name);
+	ck_assert_str_eq (HTML_ATTRS[2].attr, attrs[0].name);
+	ck_assert_int_eq (0, attrs[0].tag_n);
+	ck_assert_ptr_eq (NULL, attrs[0].tags);
+
+	/* id, global */
+	ck_assert_str_eq ("id", HTML_ATTRS[3].attr);
+	ck_assert_ptr_ne (HTML_ATTRS[3].attr, attrs[2].name);
+	ck_assert_str_eq (HTML_ATTRS[3].attr, attrs[2].name);
+	ck_assert_int_eq (0, attrs[2].tag_n);
+	ck_assert_ptr_eq (NULL, attrs[2].tags);
+
 	#undef attrs
 
 	/* cleanup */
@@ -254,40 +296,60 @@ START_TEST(test_validator_spec_with_status)
 	ck_assert_int_eq (SUCCESS, status.status);
 
 	ck_assert_ptr_ne (NULL, validator->attrs);
-	ck_assert_int_eq (2, validator->attr_n);
+	ck_assert_int_eq (4, validator->attr_n);
 
 	#define attrs validator->attrs
-	#define TEST_STR(S1, S2) ck_assert_ptr_ne (S1, S2);            \
-	                         ck_assert_str_eq (S1, S2);
-
-	ck_assert_ptr_ne (HTML_ATTRS[1].attr, attrs[0].name);
-	ck_assert_str_eq (HTML_ATTRS[1].attr, attrs[0].name);
-	ck_assert_int_eq (HTML_ATTRS[1].tag_n, attrs[0].tag_n);
-	ck_assert_ptr_ne (NULL, attrs[0].tags);
 
-	TEST_STR (HTML_TAGS[2].tag, attrs[0].tags[0].name);
+	/* lang, 2 tags */
+	ck_assert_str_eq ("lang", HTML_ATTRS[0].attr);
+	ck_assert_ptr_ne (HTML_ATTRS[0].attr, attrs[3].name);
+	ck_assert_str_eq (HTML_ATTRS[0].attr, attrs[3].name);
+	ck_assert_int_eq (HTML_ATTRS[0].tag_n, attrs[3].tag_n);
+	ck_assert_ptr_ne (NULL, attrs[3].tags);
 
-	ck_assert_ptr_ne (HTML_ATTRS[0].attr, attrs[1].name);
-	ck_assert_str_eq (HTML_ATTRS[0].attr, attrs[1].name);
-	ck_assert_int_eq (HTML_ATTRS[0].tag_n, attrs[1].tag_n);
-	ck_assert_ptr_ne (NULL, attrs[1].tags);
 
+	#define TEST_STR(S1, S2) ck_assert_ptr_ne (S1, S2);            \
+	                         ck_assert_str_eq (S1, S2);
 	/* The storage order depends on the relative position of memory,
 	 * allocated by different malloc calls. This can change and
 	 * thus must be determined. */
-	if (attrs[1].tags[0].name[0]
-	  > attrs[1].tags[1].name[0])
+	if (attrs[3].tags[0].name[0]
+	  > attrs[3].tags[1].name[0])
 	{
-		TEST_STR (HTML_TAGS[0].tag, attrs[1].tags[0].name);
-		TEST_STR (HTML_TAGS[1].tag, attrs[1].tags[1].name);
+		TEST_STR (HTML_TAGS[0].tag, attrs[3].tags[0].name);
+		TEST_STR (HTML_TAGS[1].tag, attrs[3].tags[1].name);
 	}
 	else
 	{
-		TEST_STR (HTML_TAGS[1].tag, attrs[1].tags[0].name);
-		TEST_STR (HTML_TAGS[0].tag, attrs[1].tags[1].name);
+		TEST_STR (HTML_TAGS[1].tag, attrs[3].tags[0].name);
+		TEST_STR (HTML_TAGS[0].tag, attrs[3].tags[1].name);
 	}
-
 	#undef TEST_STR
+
+	/* href, 1 tag */
+	ck_assert_str_eq ("href", HTML_ATTRS[1].attr);
+	ck_assert_ptr_ne (HTML_ATTRS[1].attr, attrs[1].name);
+	ck_assert_str_eq (HTML_ATTRS[1].attr, attrs[1].name);
+	ck_assert_int_eq (HTML_ATTRS[1].tag_n, attrs[1].tag_n);
+	ck_assert_ptr_ne (NULL, attrs[1].tags);
+
+	ck_assert_ptr_ne (HTML_TAGS[2].tag, attrs[1].tags[0].name);
+	ck_assert_str_eq (HTML_TAGS[2].tag, attrs[1].tags[0].name);
+
+	/* class, global, overwrite */
+	ck_assert_str_eq ("class", HTML_ATTRS[2].attr);
+	ck_assert_ptr_ne (HTML_ATTRS[2].attr, attrs[0].name);
+	ck_assert_str_eq (HTML_ATTRS[2].attr, attrs[0].name);
+	ck_assert_int_eq (0, attrs[0].tag_n);
+	ck_assert_ptr_eq (NULL, attrs[0].tags);
+
+	/* id, global */
+	ck_assert_str_eq ("id", HTML_ATTRS[3].attr);
+	ck_assert_ptr_ne (HTML_ATTRS[3].attr, attrs[2].name);
+	ck_assert_str_eq (HTML_ATTRS[3].attr, attrs[2].name);
+	ck_assert_int_eq (0, attrs[2].tag_n);
+	ck_assert_ptr_eq (NULL, attrs[2].tags);
+
 	#undef attrs
 
 	/* cleanup */
@@ -308,6 +370,7 @@ START_TEST(test_validator_register_no_status)
 	const char * attr3 = "name";
 	const char * attr4 = "src";
 	const char * attr5 = "content";
+	const char * attr6 = "lang";
 	char * attrN;
 	bool result;
 
@@ -416,6 +479,50 @@ START_TEST(test_validator_register_no_status)
 	}
 	#undef attr
 
+	/* test - change to global attr */
+	result = SH_Validator_register_attr (validator, NULL, attr1,
+	                                     NULL);
+	ck_assert_int_eq (TRUE, result);
+
+	ck_assert_int_eq (4, validator->attr_n);
+	ck_assert_str_eq (attr5, validator->attrs[0].name);
+	ck_assert_str_eq (attr1, validator->attrs[1].name);
+	ck_assert_str_eq (attr3, validator->attrs[2].name);
+	ck_assert_str_eq (attr4, validator->attrs[3].name);
+
+	ck_assert_int_eq (0, validator->attrs[1].tag_n);
+	ck_assert_ptr_eq (NULL, validator->attrs[1].tags);
+
+	/* test - new global attr */
+	result = SH_Validator_register_attr (validator, NULL, attr6,
+	                                     NULL);
+	ck_assert_int_eq (TRUE, result);
+
+	ck_assert_int_eq (5, validator->attr_n);
+	ck_assert_str_eq (attr5, validator->attrs[0].name);
+	ck_assert_str_eq (attr1, validator->attrs[1].name);
+	ck_assert_str_eq (attr6, validator->attrs[2].name);
+	ck_assert_str_eq (attr3, validator->attrs[3].name);
+	ck_assert_str_eq (attr4, validator->attrs[4].name);
+
+	ck_assert_int_eq (0, validator->attrs[2].tag_n);
+	ck_assert_ptr_eq (NULL, validator->attrs[2].tags);
+
+	/* test - existing global attr */
+	result = SH_Validator_register_attr (validator, tag1, attr6,
+	                                     NULL);
+	ck_assert_int_eq (TRUE, result);
+
+	ck_assert_int_eq (5, validator->attr_n);
+	ck_assert_str_eq (attr5, validator->attrs[0].name);
+	ck_assert_str_eq (attr1, validator->attrs[1].name);
+	ck_assert_str_eq (attr6, validator->attrs[2].name);
+	ck_assert_str_eq (attr3, validator->attrs[3].name);
+	ck_assert_str_eq (attr4, validator->attrs[4].name);
+
+	ck_assert_int_eq (0, validator->attrs[2].tag_n);
+	ck_assert_ptr_eq (NULL, validator->attrs[2].tags);
+
 	/* test - overflow detection */
 	/* make method fail by filling with garbage until
 	 * upper boundary is reached */
@@ -464,6 +571,7 @@ START_TEST(test_validator_register_with_status)
 	const char * attr3 = "name";
 	const char * attr4 = "src";
 	const char * attr5 = "content";
+	const char * attr6 = "lang";
 	char * attrN;
 	bool result;
 
@@ -594,6 +702,56 @@ START_TEST(test_validator_register_with_status)
 	}
 	#undef attr
 
+	/* test - change to global attr */
+	_status_preinit (status);
+	result = SH_Validator_register_attr (validator, NULL, attr1,
+	                                     &status);
+	ck_assert_int_eq (TRUE, result);
+	ck_assert_int_eq (SUCCESS, status.status);
+
+	ck_assert_int_eq (4, validator->attr_n);
+	ck_assert_str_eq (attr5, validator->attrs[0].name);
+	ck_assert_str_eq (attr1, validator->attrs[1].name);
+	ck_assert_str_eq (attr3, validator->attrs[2].name);
+	ck_assert_str_eq (attr4, validator->attrs[3].name);
+
+	ck_assert_int_eq (0, validator->attrs[1].tag_n);
+	ck_assert_ptr_eq (NULL, validator->attrs[1].tags);
+
+	/* test - new global attr */
+	_status_preinit (status);
+	result = SH_Validator_register_attr (validator, NULL, attr6,
+	                                     &status);
+	ck_assert_int_eq (TRUE, result);
+	ck_assert_int_eq (SUCCESS, status.status);
+
+	ck_assert_int_eq (5, validator->attr_n);
+	ck_assert_str_eq (attr5, validator->attrs[0].name);
+	ck_assert_str_eq (attr1, validator->attrs[1].name);
+	ck_assert_str_eq (attr6, validator->attrs[2].name);
+	ck_assert_str_eq (attr3, validator->attrs[3].name);
+	ck_assert_str_eq (attr4, validator->attrs[4].name);
+
+	ck_assert_int_eq (0, validator->attrs[2].tag_n);
+	ck_assert_ptr_eq (NULL, validator->attrs[2].tags);
+
+	/* test - existing global attr */
+	_status_preinit (status);
+	result = SH_Validator_register_attr (validator, tag1, attr6,
+	                                     &status);
+	ck_assert_int_eq (TRUE, result);
+	ck_assert_int_eq (SUCCESS, status.status);
+
+	ck_assert_int_eq (5, validator->attr_n);
+	ck_assert_str_eq (attr5, validator->attrs[0].name);
+	ck_assert_str_eq (attr1, validator->attrs[1].name);
+	ck_assert_str_eq (attr6, validator->attrs[2].name);
+	ck_assert_str_eq (attr3, validator->attrs[3].name);
+	ck_assert_str_eq (attr4, validator->attrs[4].name);
+
+	ck_assert_int_eq (0, validator->attrs[2].tag_n);
+	ck_assert_ptr_eq (NULL, validator->attrs[2].tags);
+
 	/* test - overflow detection */
 	/* make method fail by filling with garbage until
 	 * upper boundary is reached */
@@ -641,33 +799,47 @@ START_TEST(test_validator_deregister_no_status)
 
 	#define REGISTER SH_Validator_register_attr
 	result = REGISTER (validator, "html", "attr", NULL);
-	ck_assert_int_ne (FALSE, result);
+	ck_assert_int_eq (TRUE, result);
 	result = REGISTER (validator, "html", "id", NULL);
-	ck_assert_int_ne (FALSE, result);
+	ck_assert_int_eq (TRUE, result);
 	result = REGISTER (validator, "html", "name", NULL);
-	ck_assert_int_ne (FALSE, result);
+	ck_assert_int_eq (TRUE, result);
 	result = REGISTER (validator, "html", "class", NULL);
-	ck_assert_int_ne (FALSE, result);
+	ck_assert_int_eq (TRUE, result);
 	result = REGISTER (validator, "body", "attr", NULL);
-	ck_assert_int_ne (FALSE, result);
+	ck_assert_int_eq (TRUE, result);
 	result = REGISTER (validator, "body", "id", NULL);
-	ck_assert_int_ne (FALSE, result);
+	ck_assert_int_eq (TRUE, result);
 	result = REGISTER (validator, "body", "name", NULL);
-	ck_assert_int_ne (FALSE, result);
+	ck_assert_int_eq (TRUE, result);
 	result = REGISTER (validator, "body", "class", NULL);
-	ck_assert_int_ne (FALSE, result);
+	ck_assert_int_eq (TRUE, result);
+	result = REGISTER (validator, NULL, "x", NULL);
+	ck_assert_int_eq (TRUE, result);
+	result = REGISTER (validator, NULL, "y", NULL);
+	ck_assert_int_eq (TRUE, result);
 	#undef REGISTER
 
 	/* test - consistency */
-	ck_assert_int_eq (4, validator->attr_n);
+	ck_assert_int_eq (6, validator->attr_n);
 	ck_assert_str_eq ("attr", validator->attrs[0].name);
 	ck_assert_str_eq ("class", validator->attrs[1].name);
 	ck_assert_str_eq ("id", validator->attrs[2].name);
 	ck_assert_str_eq ("name", validator->attrs[3].name);
+	ck_assert_str_eq ("x", validator->attrs[4].name);
+	ck_assert_str_eq ("y", validator->attrs[5].name);
 	ck_assert_int_eq (2, validator->attrs[0].tag_n);
 	ck_assert_int_eq (2, validator->attrs[1].tag_n);
 	ck_assert_int_eq (2, validator->attrs[2].tag_n);
 	ck_assert_int_eq (2, validator->attrs[3].tag_n);
+	ck_assert_int_eq (0, validator->attrs[4].tag_n);
+	ck_assert_int_eq (0, validator->attrs[5].tag_n);
+	ck_assert_ptr_ne (NULL, validator->attrs[0].tags);
+	ck_assert_ptr_ne (NULL, validator->attrs[1].tags);
+	ck_assert_ptr_ne (NULL, validator->attrs[2].tags);
+	ck_assert_ptr_ne (NULL, validator->attrs[3].tags);
+	ck_assert_ptr_eq (NULL, validator->attrs[4].tags);
+	ck_assert_ptr_eq (NULL, validator->attrs[5].tags);
 
 	#define STR_EQ ck_assert_str_eq
 	/* The storage order depends on the relative position of memory,
@@ -698,29 +870,39 @@ START_TEST(test_validator_deregister_no_status)
 	}
 	#undef STR_EQ
 
+
 	/* test - existent attr */
-	result = SH_Validator_deregister_attr (validator,
-	                                       "html", "attr", NULL);
+	result = SH_Validator_deregister_attr (validator, "html", "attr",
+	                                       NULL);
 	ck_assert_int_eq (TRUE, result);
 
 	/* test - non existent tag */
-	result = SH_Validator_deregister_attr (validator,
-	                                       "html", "attr", NULL);
+	result = SH_Validator_deregister_attr (validator, "html", "attr",
+	                                       NULL);
 	ck_assert_int_eq (FALSE, result);
 
 	/* test - existent attr, auto remove */
-	result = SH_Validator_deregister_attr (validator,
-	                                       "body", "attr", NULL);
+	result = SH_Validator_deregister_attr (validator, "body", "attr",
+	                                       NULL);
 	ck_assert_int_eq (TRUE, result);
 
 	/* test - consistency */
-	ck_assert_int_eq (3, validator->attr_n);
+	ck_assert_int_eq (5, validator->attr_n);
 	ck_assert_str_eq ("class", validator->attrs[0].name);
 	ck_assert_str_eq ("id", validator->attrs[1].name);
 	ck_assert_str_eq ("name", validator->attrs[2].name);
+	ck_assert_str_eq ("x", validator->attrs[3].name);
+	ck_assert_str_eq ("y", validator->attrs[4].name);
 	ck_assert_int_eq (2, validator->attrs[0].tag_n);
 	ck_assert_int_eq (2, validator->attrs[1].tag_n);
 	ck_assert_int_eq (2, validator->attrs[2].tag_n);
+	ck_assert_int_eq (0, validator->attrs[3].tag_n);
+	ck_assert_int_eq (0, validator->attrs[4].tag_n);
+	ck_assert_ptr_ne (NULL, validator->attrs[0].tags);
+	ck_assert_ptr_ne (NULL, validator->attrs[1].tags);
+	ck_assert_ptr_ne (NULL, validator->attrs[2].tags);
+	ck_assert_ptr_eq (NULL, validator->attrs[3].tags);
+	ck_assert_ptr_eq (NULL, validator->attrs[4].tags);
 
 
 	/* test - non existent attr */
@@ -739,11 +921,19 @@ START_TEST(test_validator_deregister_no_status)
 	ck_assert_int_eq (FALSE, result);
 
 	/* test - consistency */
-	ck_assert_int_eq (2, validator->attr_n);
+	ck_assert_int_eq (4, validator->attr_n);
 	ck_assert_str_eq ("class", validator->attrs[0].name);
 	ck_assert_str_eq ("id", validator->attrs[1].name);
+	ck_assert_str_eq ("x", validator->attrs[2].name);
+	ck_assert_str_eq ("y", validator->attrs[3].name);
 	ck_assert_int_eq (2, validator->attrs[0].tag_n);
 	ck_assert_int_eq (2, validator->attrs[1].tag_n);
+	ck_assert_int_eq (0, validator->attrs[2].tag_n);
+	ck_assert_int_eq (0, validator->attrs[3].tag_n);
+	ck_assert_ptr_ne (NULL, validator->attrs[0].tags);
+	ck_assert_ptr_ne (NULL, validator->attrs[1].tags);
+	ck_assert_ptr_eq (NULL, validator->attrs[2].tags);
+	ck_assert_ptr_eq (NULL, validator->attrs[3].tags);
 
 
 	#define STR_EQ ck_assert_str_eq
@@ -779,11 +969,48 @@ START_TEST(test_validator_deregister_no_status)
 	ck_assert_int_eq (FALSE, result);
 
 	/* test - consistency */
-	ck_assert_int_eq (2, validator->attr_n);
+	ck_assert_int_eq (4, validator->attr_n);
 	ck_assert_str_eq ("class", validator->attrs[0].name);
 	ck_assert_str_eq ("id", validator->attrs[1].name);
+	ck_assert_str_eq ("x", validator->attrs[2].name);
+	ck_assert_str_eq ("y", validator->attrs[3].name);
 	ck_assert_int_eq (1, validator->attrs[0].tag_n);
 	ck_assert_int_eq (1, validator->attrs[1].tag_n);
+	ck_assert_int_eq (0, validator->attrs[2].tag_n);
+	ck_assert_int_eq (0, validator->attrs[3].tag_n);
+	ck_assert_ptr_ne (NULL, validator->attrs[0].tags);
+	ck_assert_ptr_ne (NULL, validator->attrs[1].tags);
+	ck_assert_ptr_eq (NULL, validator->attrs[2].tags);
+	ck_assert_ptr_eq (NULL, validator->attrs[3].tags);
+	ck_assert_str_eq ("body", validator->attrs[0].tags[0].name);
+	ck_assert_str_eq ("body", validator->attrs[1].tags[0].name);
+
+	/* test - global attr */
+	result = SH_Validator_deregister_attr (validator, "html", "x",
+	                                       NULL);
+	ck_assert_int_eq (FALSE, result);
+
+	/* test - global attr, non existent tag */
+	result = SH_Validator_deregister_attr (validator, "nav", "x",
+	                                       NULL);
+	ck_assert_int_eq (FALSE, result);
+
+	/* test - global attr, total remove */
+	result = SH_Validator_deregister_attr (validator, NULL, "x",
+	                                       NULL);
+	ck_assert_int_eq (TRUE, result);
+
+	/* test - consistency */
+	ck_assert_int_eq (3, validator->attr_n);
+	ck_assert_str_eq ("class", validator->attrs[0].name);
+	ck_assert_str_eq ("id", validator->attrs[1].name);
+	ck_assert_str_eq ("y", validator->attrs[2].name);
+	ck_assert_int_eq (1, validator->attrs[0].tag_n);
+	ck_assert_int_eq (1, validator->attrs[1].tag_n);
+	ck_assert_int_eq (0, validator->attrs[2].tag_n);
+	ck_assert_ptr_ne (NULL, validator->attrs[0].tags);
+	ck_assert_ptr_ne (NULL, validator->attrs[1].tags);
+	ck_assert_ptr_eq (NULL, validator->attrs[2].tags);
 	ck_assert_str_eq ("body", validator->attrs[0].tags[0].name);
 	ck_assert_str_eq ("body", validator->attrs[1].tags[0].name);
 
@@ -813,33 +1040,47 @@ START_TEST(test_validator_deregister_with_status)
 
 	#define REGISTER SH_Validator_register_attr
 	result = REGISTER (validator, "html", "attr", NULL);
-	ck_assert_int_ne (FALSE, result);
+	ck_assert_int_eq (TRUE, result);
 	result = REGISTER (validator, "html", "id", NULL);
-	ck_assert_int_ne (FALSE, result);
+	ck_assert_int_eq (TRUE, result);
 	result = REGISTER (validator, "html", "name", NULL);
-	ck_assert_int_ne (FALSE, result);
+	ck_assert_int_eq (TRUE, result);
 	result = REGISTER (validator, "html", "class", NULL);
-	ck_assert_int_ne (FALSE, result);
+	ck_assert_int_eq (TRUE, result);
 	result = REGISTER (validator, "body", "attr", NULL);
-	ck_assert_int_ne (FALSE, result);
+	ck_assert_int_eq (TRUE, result);
 	result = REGISTER (validator, "body", "id", NULL);
-	ck_assert_int_ne (FALSE, result);
+	ck_assert_int_eq (TRUE, result);
 	result = REGISTER (validator, "body", "name", NULL);
-	ck_assert_int_ne (FALSE, result);
+	ck_assert_int_eq (TRUE, result);
 	result = REGISTER (validator, "body", "class", NULL);
-	ck_assert_int_ne (FALSE, result);
+	ck_assert_int_eq (TRUE, result);
+	result = REGISTER (validator, NULL, "x", NULL);
+	ck_assert_int_eq (TRUE, result);
+	result = REGISTER (validator, NULL, "y", NULL);
+	ck_assert_int_eq (TRUE, result);
 	#undef REGISTER
 
 	/* test - consistency */
-	ck_assert_int_eq (4, validator->attr_n);
+	ck_assert_int_eq (6, validator->attr_n);
 	ck_assert_str_eq ("attr", validator->attrs[0].name);
 	ck_assert_str_eq ("class", validator->attrs[1].name);
 	ck_assert_str_eq ("id", validator->attrs[2].name);
 	ck_assert_str_eq ("name", validator->attrs[3].name);
+	ck_assert_str_eq ("x", validator->attrs[4].name);
+	ck_assert_str_eq ("y", validator->attrs[5].name);
 	ck_assert_int_eq (2, validator->attrs[0].tag_n);
 	ck_assert_int_eq (2, validator->attrs[1].tag_n);
 	ck_assert_int_eq (2, validator->attrs[2].tag_n);
 	ck_assert_int_eq (2, validator->attrs[3].tag_n);
+	ck_assert_int_eq (0, validator->attrs[4].tag_n);
+	ck_assert_int_eq (0, validator->attrs[5].tag_n);
+	ck_assert_ptr_ne (NULL, validator->attrs[0].tags);
+	ck_assert_ptr_ne (NULL, validator->attrs[1].tags);
+	ck_assert_ptr_ne (NULL, validator->attrs[2].tags);
+	ck_assert_ptr_ne (NULL, validator->attrs[3].tags);
+	ck_assert_ptr_eq (NULL, validator->attrs[4].tags);
+	ck_assert_ptr_eq (NULL, validator->attrs[5].tags);
 
 	#define STR_EQ ck_assert_str_eq
 	/* The storage order depends on the relative position of memory,
@@ -893,13 +1134,22 @@ START_TEST(test_validator_deregister_with_status)
 	ck_assert_int_eq (SUCCESS, status.status);
 
 	/* test - consistency */
-	ck_assert_int_eq (3, validator->attr_n);
+	ck_assert_int_eq (5, validator->attr_n);
 	ck_assert_str_eq ("class", validator->attrs[0].name);
 	ck_assert_str_eq ("id", validator->attrs[1].name);
 	ck_assert_str_eq ("name", validator->attrs[2].name);
+	ck_assert_str_eq ("x", validator->attrs[3].name);
+	ck_assert_str_eq ("y", validator->attrs[4].name);
 	ck_assert_int_eq (2, validator->attrs[0].tag_n);
 	ck_assert_int_eq (2, validator->attrs[1].tag_n);
 	ck_assert_int_eq (2, validator->attrs[2].tag_n);
+	ck_assert_int_eq (0, validator->attrs[3].tag_n);
+	ck_assert_int_eq (0, validator->attrs[4].tag_n);
+	ck_assert_ptr_ne (NULL, validator->attrs[0].tags);
+	ck_assert_ptr_ne (NULL, validator->attrs[1].tags);
+	ck_assert_ptr_ne (NULL, validator->attrs[2].tags);
+	ck_assert_ptr_eq (NULL, validator->attrs[3].tags);
+	ck_assert_ptr_eq (NULL, validator->attrs[4].tags);
 
 
 	/* test - non existent attr */
@@ -924,11 +1174,19 @@ START_TEST(test_validator_deregister_with_status)
 	ck_assert_int_eq (E_VALUE, status.status);
 
 	/* test - consistency */
-	ck_assert_int_eq (2, validator->attr_n);
+	ck_assert_int_eq (4, validator->attr_n);
 	ck_assert_str_eq ("class", validator->attrs[0].name);
 	ck_assert_str_eq ("id", validator->attrs[1].name);
+	ck_assert_str_eq ("x", validator->attrs[2].name);
+	ck_assert_str_eq ("y", validator->attrs[3].name);
 	ck_assert_int_eq (2, validator->attrs[0].tag_n);
 	ck_assert_int_eq (2, validator->attrs[1].tag_n);
+	ck_assert_int_eq (0, validator->attrs[2].tag_n);
+	ck_assert_int_eq (0, validator->attrs[3].tag_n);
+	ck_assert_ptr_ne (NULL, validator->attrs[0].tags);
+	ck_assert_ptr_ne (NULL, validator->attrs[1].tags);
+	ck_assert_ptr_eq (NULL, validator->attrs[2].tags);
+	ck_assert_ptr_eq (NULL, validator->attrs[3].tags);
 
 
 	#define STR_EQ ck_assert_str_eq
@@ -968,11 +1226,54 @@ START_TEST(test_validator_deregister_with_status)
 	ck_assert_int_eq (E_VALUE, status.status);
 
 	/* test - consistency */
-	ck_assert_int_eq (2, validator->attr_n);
+	ck_assert_int_eq (4, validator->attr_n);
+	ck_assert_str_eq ("class", validator->attrs[0].name);
+	ck_assert_str_eq ("id", validator->attrs[1].name);
+	ck_assert_str_eq ("x", validator->attrs[2].name);
+	ck_assert_str_eq ("y", validator->attrs[3].name);
+	ck_assert_int_eq (1, validator->attrs[0].tag_n);
+	ck_assert_int_eq (1, validator->attrs[1].tag_n);
+	ck_assert_int_eq (0, validator->attrs[2].tag_n);
+	ck_assert_int_eq (0, validator->attrs[3].tag_n);
+	ck_assert_ptr_ne (NULL, validator->attrs[0].tags);
+	ck_assert_ptr_ne (NULL, validator->attrs[1].tags);
+	ck_assert_ptr_eq (NULL, validator->attrs[2].tags);
+	ck_assert_ptr_eq (NULL, validator->attrs[3].tags);
+	ck_assert_str_eq ("body", validator->attrs[0].tags[0].name);
+	ck_assert_str_eq ("body", validator->attrs[1].tags[0].name);
+
+	/* test - global attr */
+	_status_preinit (status);
+	result = SH_Validator_deregister_attr (validator, "html", "x",
+	                                       &status);
+	ck_assert_int_eq (FALSE, result);
+	ck_assert_int_eq (E_STATE, status.status);
+
+	/* test - global attr, non existent tag */
+	_status_preinit (status);
+	result = SH_Validator_deregister_attr (validator, "nav", "x",
+	                                       &status);
+	ck_assert_int_eq (FALSE, result);
+	ck_assert_int_eq (E_VALUE, status.status);
+
+	/* test - global attr, total remove */
+	_status_preinit (status);
+	result = SH_Validator_deregister_attr (validator, NULL, "x",
+	                                       &status);
+	ck_assert_int_eq (TRUE, result);
+	ck_assert_int_eq (SUCCESS, status.status);
+
+	/* test - consistency */
+	ck_assert_int_eq (3, validator->attr_n);
 	ck_assert_str_eq ("class", validator->attrs[0].name);
 	ck_assert_str_eq ("id", validator->attrs[1].name);
+	ck_assert_str_eq ("y", validator->attrs[2].name);
 	ck_assert_int_eq (1, validator->attrs[0].tag_n);
 	ck_assert_int_eq (1, validator->attrs[1].tag_n);
+	ck_assert_int_eq (0, validator->attrs[2].tag_n);
+	ck_assert_ptr_ne (NULL, validator->attrs[0].tags);
+	ck_assert_ptr_ne (NULL, validator->attrs[1].tags);
+	ck_assert_ptr_eq (NULL, validator->attrs[2].tags);
 	ck_assert_str_eq ("body", validator->attrs[0].tags[0].name);
 	ck_assert_str_eq ("body", validator->attrs[1].tags[0].name);
 
@@ -995,14 +1296,13 @@ END_TEST
 START_TEST(test_validator_check)
 {
 	struct SH_Validator * validator;
-	const char * tag1 = "html";
-	const char * tag2 = "html";
-	const char * tag3 = "head";
-	const char * tag4 = "body";
-	const char * attr1  = "id";
-	const char * attr2  = "id";
-	const char * attr3  = "class";
-	const char * attr4  = "name";
+	const char * tag_1 = "html";
+	const char * tag_2 = "head";
+	const char * notag = "body";
+	const char * attr_1  = "type";
+	const char * attr_2  = "class";
+	const char * attr_g  = "id";
+	const char * noattr  = "name";
 	bool result;
 
 	/* setup */
@@ -1011,37 +1311,45 @@ START_TEST(test_validator_check)
 
 
 	#define REGISTER SH_Validator_register_attr
-	result = REGISTER (validator, tag1, attr1, NULL);
-	ck_assert_int_ne (FALSE, result);
-	result = REGISTER (validator, tag3, attr3, NULL);
-	ck_assert_int_ne (FALSE, result);
+	result = REGISTER (validator, tag_1, attr_1, NULL);
+	ck_assert_int_eq (TRUE, result);
+	result = REGISTER (validator, tag_2, attr_2, NULL);
+	ck_assert_int_eq (TRUE, result);
+	result = REGISTER (validator, NULL, attr_g, NULL);
+	ck_assert_int_eq (TRUE, result);
 	#undef REGISTER
 
 	/* test */
-	result = SH_Validator_check_attr (validator, tag1, attr1);
+	result = SH_Validator_check_attr (validator, tag_1, attr_1);
 	ck_assert_int_eq (TRUE, result);
 
-	result = SH_Validator_check_attr (validator, tag2, attr2);
-	ck_assert_int_eq (TRUE, result);
+	result = SH_Validator_check_attr (validator, tag_1, attr_2);
+	ck_assert_int_eq (FALSE, result);
 
-	result = SH_Validator_check_attr (validator, tag1, attr3);
+	result = SH_Validator_check_attr (validator, tag_2, noattr);
 	ck_assert_int_eq (FALSE, result);
 
-	result = SH_Validator_check_attr (validator, tag3, attr4);
+	result = SH_Validator_check_attr (validator, notag, attr_1);
 	ck_assert_int_eq (FALSE, result);
 
-	result = SH_Validator_check_attr (validator, tag4, attr2);
+	result = SH_Validator_check_attr (validator, notag, noattr);
 	ck_assert_int_eq (FALSE, result);
 
-	result = SH_Validator_check_attr (validator, tag4, attr4);
+	result = SH_Validator_check_attr (validator, NULL, attr_1);
+	ck_assert_int_eq (TRUE, result);
+
+	result = SH_Validator_check_attr (validator, NULL, noattr);
 	ck_assert_int_eq (FALSE, result);
 
-	result = SH_Validator_check_attr (validator, NULL, attr2);
+	result = SH_Validator_check_attr (validator, tag_1, attr_g);
 	ck_assert_int_eq (TRUE, result);
 
-	result = SH_Validator_check_attr (validator, NULL, attr4);
+	result = SH_Validator_check_attr (validator, notag, attr_g);
 	ck_assert_int_eq (FALSE, result);
 
+	result = SH_Validator_check_attr (validator, NULL, attr_g);
+	ck_assert_int_eq (TRUE, result);
+
 	/* cleanup */
 	SH_Validator_free (validator);
 }
diff --git a/todo.txt b/todo.txt
index b32289b56df578b77c96d0a85e5e4df417f10971..dfdca0521cbf71a4c7c3b413aab8d33a5e789ee1 100644
--- a/todo.txt
+++ b/todo.txt
@@ -2,13 +2,10 @@ create Logger
 
 create Docs
 
-dynamic Validator initialization
-
 remove -Wno-nonnull from AM_CFLAGS
 fix warnings for tests
 
 rewrite validator test
-restructure validator
 
 Fragment:
 - create html on single Text object
@@ -22,6 +19,8 @@ Fragment:
 - support for mapping special chars -> html entities
 
 Validator:
-- support for global attributes
+- check for global attributes
+- change global to local attribute
 - add tag types
 - fix cursed behaviour, when removing fails
+- initialize from file