diff --git a/vlib/net/html/tag.v b/vlib/net/html/tag.v index 920b72a6d6..61dcb530e6 100644 --- a/vlib/net/html/tag.v +++ b/vlib/net/html/tag.v @@ -69,6 +69,19 @@ pub fn (tag &Tag) str() string { return html_str.str() } +// get_tag retrieves the first found child tag in the tag that has the given tag name. +pub fn (tag &Tag) get_tag(name string) ?&Tag { + for child in tag.children { + if child.name == name { + return child + } + if c := child.get_tag(name) { + return c + } + } + return none +} + // get_tags retrieves all the child tags recursively in the tag that has the given tag name. pub fn (tag &Tag) get_tags(name string) []&Tag { mut res := []&Tag{} @@ -81,6 +94,20 @@ pub fn (tag &Tag) get_tags(name string) []&Tag { return res } +// get_tag_by_attribute retrieves the first found child tag in the tag that has the given attribute name. +pub fn (tag &Tag) get_tag_by_attribute(name string) ?&Tag { + // mut res := &Tag{} + for child in tag.children { + if child.attributes[name] != '' { + return child + } + if c := child.get_tag_by_attribute(name) { + return c + } + } + return none +} + // get_tags_by_attribute retrieves all the child tags recursively in the tag that has the given attribute name. pub fn (tag &Tag) get_tags_by_attribute(name string) []&Tag { mut res := []&Tag{} @@ -93,6 +120,19 @@ pub fn (tag &Tag) get_tags_by_attribute(name string) []&Tag { return res } +// get_tag_by_attribute_value retrieves the first found child tag in the tag that has the given attribute name and value. +pub fn (tag &Tag) get_tag_by_attribute_value(name string, value string) ?&Tag { + for child in tag.children { + if child.attributes[name] == value { + return child + } + if c := child.get_tag_by_attribute_value(name, value) { + return c + } + } + return none +} + // get_tags_by_attribute_value retrieves all the child tags recursively in the tag that has the given attribute name and value. pub fn (tag &Tag) get_tags_by_attribute_value(name string, value string) []&Tag { mut res := []&Tag{} @@ -105,6 +145,26 @@ pub fn (tag &Tag) get_tags_by_attribute_value(name string, value string) []&Tag return res } +// get_tag_by_class_name retrieves the first found child tag in the tag that has the given class name(s). +pub fn (tag &Tag) get_tag_by_class_name(names ...string) ?&Tag { + for child in tag.children { + mut matched := true + for name in names { + matched = child.class_set.exists(name) + if !matched { + break + } + } + if matched { + return child + } + if c := child.get_tag_by_class_name(...names) { + return c + } + } + return none +} + // get_tags_by_class_name retrieves all the child tags recursively in the tag that has the given class name(s). pub fn (tag &Tag) get_tags_by_class_name(names ...string) []&Tag { mut res := []&Tag{} diff --git a/vlib/net/html/tag_test.v b/vlib/net/html/tag_test.v index 6e18b76914..8fe131fc18 100644 --- a/vlib/net/html/tag_test.v +++ b/vlib/net/html/tag_test.v @@ -8,7 +8,7 @@ const (
-
+
@@ -30,7 +30,17 @@ const ( ' ) -fn test_search_by_tag_type() { +fn test_search_tag_by_type() { + mut dom := parse(html.html) + tag := dom.get_tag('body')[0] + assert tag.get_tag('div') or { assert false }.attributes['id'] == '1st' + assert tag.get_tag_by_attribute('href') or { assert false }.content == 'V' + // TODO: update after improved parsing to not add trailing white space to attribute values + assert tag.get_tag_by_attribute_value('id', '3rd') or { assert false }.str() == '
' + assert tag.get_tag_by_class_name('foo') or { assert false }.attributes['class'] == 'foo bar' +} + +fn test_search_tags_by_type() { mut dom := parse(html.html) tag := dom.get_tag_by_attribute_value('id', '2nd')[0] assert tag.get_tags('div').len == 5