Added binding methods to HTMLParser.

This commit is contained in:
Relintai 2022-07-19 19:07:50 +02:00
parent f69cd86e5c
commit 2b631968d5
2 changed files with 280 additions and 142 deletions

View File

@ -3,29 +3,50 @@
#include "core/error_macros.h" #include "core/error_macros.h"
#include "core/log/logger.h" #include "core/log/logger.h"
String HTMLParserAttribute::get_attribute() {
return _attribute;
}
void HTMLParserAttribute::set_attribute(const String &val) {
_attribute = val;
}
String HTMLParserAttribute::get_data() {
return _data;
}
void HTMLParserAttribute::set_data(const String &val) {
_data = val;
}
bool HTMLParserAttribute::get_single() {
return _single;
}
void HTMLParserAttribute::set_single(const bool &val) {
_single = val;
}
bool HTMLParserAttribute::match_attrib(const String &attrib) { bool HTMLParserAttribute::match_attrib(const String &attrib) {
return attribute == attrib; return _attribute == attrib;
} }
bool HTMLParserAttribute::match_data(const String &d) { bool HTMLParserAttribute::match_data(const String &d) {
return data == d; return _data == d;
} }
bool HTMLParserAttribute::match_data(const Vector<String> &d) { bool HTMLParserAttribute::match_data(const Vector<String> &d) {
// todo // todo
return false; return false;
} }
bool HTMLParserAttribute::contains_data(const String &d) { bool HTMLParserAttribute::contains_data(const String &d) {
return data.find(d) != -1; return _data.find(d) != -1;
} }
String HTMLParserAttribute::convert_to_string() const { String HTMLParserAttribute::convert_to_string() const {
if (single) { if (_single) {
return attribute; return _attribute;
} }
if (data.find("\"") == -1) { if (_data.find("\"") == -1) {
return attribute + "=\"" + data + "\""; return _attribute + "=\"" + _data + "\"";
} else { } else {
return attribute + "=\'" + data + "\'"; return _attribute + "=\'" + _data + "\'";
} }
} }
@ -34,19 +55,91 @@ void HTMLParserAttribute::print() const {
} }
HTMLParserAttribute::HTMLParserAttribute() { HTMLParserAttribute::HTMLParserAttribute() {
single = false; _single = false;
} }
HTMLParserAttribute::~HTMLParserAttribute() { HTMLParserAttribute::~HTMLParserAttribute() {
} }
void HTMLParserTag::add_child_tag(const Ref<HTMLParserTag> &tag) {
_tags.push_back(tag);
}
void HTMLParserTag::remote_child_tag(const int index) {
ERR_FAIL_INDEX(index, _tags.size());
_tags.remove(index);
}
Ref<HTMLParserTag> HTMLParserTag::get_child_tag(const int index) {
ERR_FAIL_INDEX_V(index, _tags.size(), Ref<HTMLParserTag>());
return _tags[index];
}
int HTMLParserTag::get_child_tag_count() const {
return _tags.size();
}
void HTMLParserTag::clear_child_tags() {
_tags.clear();
}
Vector<Variant> HTMLParserTag::get_child_tags() {
Vector<Variant> r;
for (int i = 0; i < _tags.size(); i++) {
r.push_back(_tags[i].get_ref_ptr());
}
return r;
}
void HTMLParserTag::set_child_tags(const Vector<Variant> &val) {
_tags.clear();
for (int i = 0; i < val.size(); i++) {
Ref<HTMLParserAttribute> e = Ref<HTMLParserAttribute>(val[i]);
_tags.push_back(e);
}
}
void HTMLParserTag::add_child_attribute(const Ref<HTMLParserAttribute> &tag) {
_attributes.push_back(tag);
}
void HTMLParserTag::remote_child_attribute(const int index) {
ERR_FAIL_INDEX(index, _tags.size());
_attributes.remove(index);
}
Ref<HTMLParserAttribute> HTMLParserTag::get_child_attribute(const int index) {
ERR_FAIL_INDEX_V(index, _tags.size(), Ref<HTMLParserAttribute>());
return _attributes[index];
}
int HTMLParserTag::get_child_attribute_count() const {
return _attributes.size();
}
void HTMLParserTag::clear_child_attributes() {
_attributes.clear();
}
Vector<Variant> HTMLParserTag::get_attributes() {
Vector<Variant> r;
for (int i = 0; i < _attributes.size(); i++) {
r.push_back(_attributes[i].get_ref_ptr());
}
return r;
}
void HTMLParserTag::set_attributes(const Vector<Variant> &val) {
_attributes.clear();
for (int i = 0; i < val.size(); i++) {
Ref<HTMLParserAttribute> e = Ref<HTMLParserAttribute>(val[i]);
_attributes.push_back(e);
}
}
Ref<HTMLParserTag> HTMLParserTag::get_first(const String &t) { Ref<HTMLParserTag> HTMLParserTag::get_first(const String &t) {
if (tag == t) { if (_tag == t) {
return Ref<HTMLParserTag>(this); return Ref<HTMLParserTag>(this);
} }
for (int i = 0; i < tags.size(); ++i) { for (int i = 0; i < _tags.size(); ++i) {
Ref<HTMLParserTag> ht = tags.write[i]->get_first(t); Ref<HTMLParserTag> ht = _tags.write[i]->get_first(t);
if (ht.is_valid()) { if (ht.is_valid()) {
return ht; return ht;
@ -57,14 +150,14 @@ Ref<HTMLParserTag> HTMLParserTag::get_first(const String &t) {
} }
Ref<HTMLParserTag> HTMLParserTag::get_first(const String &t, const String &attrib, const String &val) { Ref<HTMLParserTag> HTMLParserTag::get_first(const String &t, const String &attrib, const String &val) {
if (tag == t) { if (_tag == t) {
if (has_attribute(attrib, val)) { if (has_attribute(attrib, val)) {
return Ref<HTMLParserTag>(this); return Ref<HTMLParserTag>(this);
} }
} }
for (int i = 0; i < tags.size(); ++i) { for (int i = 0; i < _tags.size(); ++i) {
Ref<HTMLParserTag> ht = tags.write[i]->get_first(t, attrib, val); Ref<HTMLParserTag> ht = _tags.write[i]->get_first(t, attrib, val);
if (ht.is_valid()) { if (ht.is_valid()) {
return ht; return ht;
@ -78,15 +171,15 @@ String HTMLParserTag::get_attribute_value(const String &attrib) {
Ref<HTMLParserAttribute> a = get_attribute(attrib); Ref<HTMLParserAttribute> a = get_attribute(attrib);
if (a.is_valid()) { if (a.is_valid()) {
return a->data; return a->get_data();
} }
return ""; return "";
} }
Ref<HTMLParserAttribute> HTMLParserTag::get_attribute(const String &attrib) { Ref<HTMLParserAttribute> HTMLParserTag::get_attribute(const String &attrib) {
for (int i = 0; i < attributes.size(); ++i) { for (int i = 0; i < _attributes.size(); ++i) {
Ref<HTMLParserAttribute> a = attributes[i]; Ref<HTMLParserAttribute> a = _attributes[i];
if (a->match_attrib(attrib)) { if (a->match_attrib(attrib)) {
return a; return a;
@ -97,8 +190,8 @@ Ref<HTMLParserAttribute> HTMLParserTag::get_attribute(const String &attrib) {
} }
bool HTMLParserTag::has_attribute(const String &attrib) { bool HTMLParserTag::has_attribute(const String &attrib) {
for (int i = 0; i < attributes.size(); ++i) { for (int i = 0; i < _attributes.size(); ++i) {
Ref<HTMLParserAttribute> a = attributes[i]; Ref<HTMLParserAttribute> a = _attributes[i];
if (a->match_attrib(attrib)) { if (a->match_attrib(attrib)) {
return true; return true;
@ -109,8 +202,8 @@ bool HTMLParserTag::has_attribute(const String &attrib) {
} }
Ref<HTMLParserAttribute> HTMLParserTag::get_attribute(const String &attrib, const String &contains_val) { Ref<HTMLParserAttribute> HTMLParserTag::get_attribute(const String &attrib, const String &contains_val) {
for (int i = 0; i < attributes.size(); ++i) { for (int i = 0; i < _attributes.size(); ++i) {
Ref<HTMLParserAttribute> a = attributes[i]; Ref<HTMLParserAttribute> a = _attributes[i];
if (a->match_attrib(attrib) && a->contains_data(contains_val)) { if (a->match_attrib(attrib) && a->contains_data(contains_val)) {
return a; return a;
@ -121,8 +214,8 @@ Ref<HTMLParserAttribute> HTMLParserTag::get_attribute(const String &attrib, cons
} }
bool HTMLParserTag::has_attribute(const String &attrib, const String &contains_val) { bool HTMLParserTag::has_attribute(const String &attrib, const String &contains_val) {
for (int i = 0; i < attributes.size(); ++i) { for (int i = 0; i < _attributes.size(); ++i) {
Ref<HTMLParserAttribute> a = attributes[i]; Ref<HTMLParserAttribute> a = _attributes[i];
if (a->match_attrib(attrib) && a->contains_data(contains_val)) { if (a->match_attrib(attrib) && a->contains_data(contains_val)) {
return true; return true;
@ -133,81 +226,81 @@ bool HTMLParserTag::has_attribute(const String &attrib, const String &contains_v
} }
void HTMLParserTag::process() { void HTMLParserTag::process() {
if (type != HTMLParserTag::HTML_PARSER_TAG_TYPE_NONE) { if (_type != HTMLParserTag::HTML_PARSER_TAG_TYPE_NONE) {
return; return;
} }
if (data.size() < 2) { if (_data.size() < 2) {
return; return;
} }
ERR_FAIL_COND(data[0] != '<'); ERR_FAIL_COND(_data[0] != '<');
ERR_FAIL_COND(data[data.size() - 1] != '>'); ERR_FAIL_COND(_data[_data.size() - 1] != '>');
int start_index = 1; int start_index = 1;
if (data[1] == '/') { if (_data[1] == '/') {
++start_index; ++start_index;
type = HTMLParserTag::HTML_PARSER_TAG_TYPE_CLOSING_TAG; _type = HTMLParserTag::HTML_PARSER_TAG_TYPE_CLOSING_TAG;
} else if (data[1] == '!') { } else if (_data[1] == '!') {
if (data.size() < 8) { if (_data.size() < 8) {
return; return;
} }
// test for comment. <!-- --> // test for comment. <!-- -->
++start_index; ++start_index;
if (data[2] == '-' && data[3] == '-') { if (_data[2] == '-' && _data[3] == '-') {
type = HTMLParserTag::HTML_PARSER_TAG_TYPE_COMMENT; _type = HTMLParserTag::HTML_PARSER_TAG_TYPE_COMMENT;
int comment_start_index = data.find_char(' ', 3); int comment_start_index = _data.find_char(' ', 3);
if (comment_start_index == -1) { if (comment_start_index == -1) {
comment_start_index = 4; comment_start_index = 4;
} }
tag = data.substr(comment_start_index, data.size() - comment_start_index - 3); _tag = _data.substr(comment_start_index, _data.size() - comment_start_index - 3);
} }
if (data.size() < 11) { if (_data.size() < 11) {
return; return;
} }
// test for doctype. <!doctype > // test for doctype. <!doctype >
int doctype_start_index = data.find("doctype ", 2); int doctype_start_index = _data.find("doctype ", 2);
if (doctype_start_index == -1) { if (doctype_start_index == -1) {
return; return;
} }
type = HTMLParserTag::HTML_PARSER_TAG_TYPE_DOCTYPE; _type = HTMLParserTag::HTML_PARSER_TAG_TYPE_DOCTYPE;
tag = data.substr(doctype_start_index + 8, data.size() - doctype_start_index - 8 - 1); _tag = _data.substr(doctype_start_index + 8, _data.size() - doctype_start_index - 8 - 1);
} else { } else {
String tag_text; String tag_text;
if (data[data.size() - 2] == '/') { if (_data[_data.size() - 2] == '/') {
// will catch all that looks like <br/> // will catch all that looks like <br/>
// tags that look like <br> will be caught later in a post process, in a way // tags that look like <br> will be caught later in a post process, in a way
// which also tries to catch erroneously not closed tags that supposed to be closed // which also tries to catch erroneously not closed tags that supposed to be closed
type = HTMLParserTag::HTML_PARSER_TAG_TYPE_SELF_CLOSING_TAG; _type = HTMLParserTag::HTML_PARSER_TAG_TYPE_SELF_CLOSING_TAG;
tag_text = data.substr(1, data.size() - 3); tag_text = _data.substr(1, _data.size() - 3);
} else { } else {
type = HTMLParserTag::HTML_PARSER_TAG_TYPE_OPENING_TAG; _type = HTMLParserTag::HTML_PARSER_TAG_TYPE_OPENING_TAG;
tag_text = data.substr(1, data.size() - 2); tag_text = _data.substr(1, _data.size() - 2);
} }
int fspc_index = tag_text.find_char(' '); int fspc_index = tag_text.find_char(' ');
if (fspc_index == -1) { if (fspc_index == -1) {
// no args // no args
tag = tag_text; _tag = tag_text;
return; return;
} }
// grab the tag itself // grab the tag itself
tag = tag_text.substr(0, fspc_index); _tag = tag_text.substr(0, fspc_index);
if (fspc_index + 1 == tag_text.size()) { if (fspc_index + 1 == tag_text.size()) {
// no args, but had a space like <br /> // no args, but had a space like <br />
@ -218,17 +311,17 @@ void HTMLParserTag::process() {
parse_args(args); parse_args(args);
} }
int tag_end_index = data.find_char(' ', start_index); int tag_end_index = _data.find_char(' ', start_index);
if (tag_end_index == -1) { if (tag_end_index == -1) {
// simple tag // simple tag
tag = data.substr(start_index, data.size() - start_index - 1); _tag = _data.substr(start_index, _data.size() - start_index - 1);
return; return;
} }
} }
void HTMLParserTag::parse_args(const String &args) { void HTMLParserTag::parse_args(const String &args) {
attributes.clear(); _attributes.clear();
int i = 0; int i = 0;
while (i < args.size()) { while (i < args.size()) {
@ -244,14 +337,14 @@ void HTMLParserTag::parse_args(const String &args) {
a.instance(); a.instance();
if (equals_index == -1) { if (equals_index == -1) {
a->attribute = args.substr(i, args.size() - i); a->set_attribute(args.substr(i, args.size() - i));
a->single = true; a->set_single(true);
attributes.push_back(a); _attributes.push_back(a);
return; return;
} }
a->attribute = args.substr(i, equals_index - i); a->set_attribute(args.substr(i, equals_index - i));
// todo // todo
// a.trim(); // a.trim();
@ -260,7 +353,7 @@ void HTMLParserTag::parse_args(const String &args) {
if (next_char_index >= args.size()) { if (next_char_index >= args.size()) {
// an attribute looks like this "... attrib=" // an attribute looks like this "... attrib="
attributes.push_back(a); _attributes.push_back(a);
return; return;
} }
@ -270,7 +363,7 @@ void HTMLParserTag::parse_args(const String &args) {
if (next_char_index >= args.size()) { if (next_char_index >= args.size()) {
// an attribute looks like this "... attrib= " // an attribute looks like this "... attrib= "
attributes.push_back(a); _attributes.push_back(a);
return; return;
} }
} }
@ -289,13 +382,13 @@ void HTMLParserTag::parse_args(const String &args) {
// missing closing ' or " if c is ' or " // missing closing ' or " if c is ' or "
// else missing parameter // else missing parameter
a->data = args.substr(next_char_index, args.size() - next_char_index - 1); a->set_data(args.substr(next_char_index, args.size() - next_char_index - 1));
attributes.push_back(a); _attributes.push_back(a);
return; return;
} }
a->data = args.substr(next_char_index, end_index - next_char_index); a->set_data(args.substr(next_char_index, end_index - next_char_index));
attributes.push_back(a); _attributes.push_back(a);
i = end_index + 1; i = end_index + 1;
} }
@ -306,90 +399,90 @@ String HTMLParserTag::convert_to_string(const int level) const {
s += String(" ").repeat(level); s += String(" ").repeat(level);
if (type == HTML_PARSER_TAG_TYPE_CONTENT) { if (_type == HTML_PARSER_TAG_TYPE_CONTENT) {
s += data + "\n"; s += _data + "\n";
if (tags.size() != 0) { if (_tags.size() != 0) {
s += String(" ").repeat(level); s += String(" ").repeat(level);
s += "(!CONTENT TAG HAS TAGS!)\n"; s += "(!CONTENT TAG HAS TAGS!)\n";
for (int i = 0; i < tags.size(); ++i) { for (int i = 0; i < _tags.size(); ++i) {
s += tags[i]->convert_to_string(level + 1) + "\n"; s += _tags[i]->convert_to_string(level + 1) + "\n";
} }
} }
} else if (type == HTML_PARSER_TAG_TYPE_OPENING_TAG) { } else if (_type == HTML_PARSER_TAG_TYPE_OPENING_TAG) {
int ln = level + 1; int ln = level + 1;
s += "<" + tag; s += "<" + _tag;
for (int i = 0; i < attributes.size(); ++i) { for (int i = 0; i < _attributes.size(); ++i) {
s += " " + attributes[i]->convert_to_string(); s += " " + _attributes[i]->convert_to_string();
} }
s += ">\n"; s += ">\n";
for (int i = 0; i < tags.size(); ++i) { for (int i = 0; i < _tags.size(); ++i) {
s += tags[i]->convert_to_string(ln); s += _tags[i]->convert_to_string(ln);
} }
s += String(" ").repeat(level); s += String(" ").repeat(level);
s += "</" + tag + ">\n"; s += "</" + _tag + ">\n";
} else if (type == HTML_PARSER_TAG_TYPE_CLOSING_TAG) { } else if (_type == HTML_PARSER_TAG_TYPE_CLOSING_TAG) {
// HTMLParserTag should handle this automatically // HTMLParserTag should handle this automatically
// it's here for debugging purposes though // it's here for debugging purposes though
s += "</" + tag + "(!)>"; s += "</" + _tag + "(!)>";
if (tags.size() != 0) { if (_tags.size() != 0) {
s += String(" ").repeat(level); s += String(" ").repeat(level);
s += "(!CLOSING TAG HAS TAGS!)\n"; s += "(!CLOSING TAG HAS TAGS!)\n";
for (int i = 0; i < tags.size(); ++i) { for (int i = 0; i < _tags.size(); ++i) {
s += tags[i]->convert_to_string(level + 1) + "\n"; s += _tags[i]->convert_to_string(level + 1) + "\n";
} }
} }
} else if (type == HTML_PARSER_TAG_TYPE_SELF_CLOSING_TAG) { } else if (_type == HTML_PARSER_TAG_TYPE_SELF_CLOSING_TAG) {
s += "<" + tag; s += "<" + _tag;
for (int i = 0; i < attributes.size(); ++i) { for (int i = 0; i < _attributes.size(); ++i) {
s += " " + attributes[i]->convert_to_string(); s += " " + _attributes[i]->convert_to_string();
} }
s += "/>\n"; s += "/>\n";
if (tags.size() != 0) { if (_tags.size() != 0) {
s += String(" ").repeat(level); s += String(" ").repeat(level);
s += "(!SELF CLOSING TAG HAS TAGS!)\n"; s += "(!SELF CLOSING TAG HAS TAGS!)\n";
for (int i = 0; i < tags.size(); ++i) { for (int i = 0; i < _tags.size(); ++i) {
s += tags[i]->convert_to_string(level + 1) + "\n"; s += _tags[i]->convert_to_string(level + 1) + "\n";
} }
} }
} else if (type == HTML_PARSER_TAG_TYPE_COMMENT) { } else if (_type == HTML_PARSER_TAG_TYPE_COMMENT) {
s += "<!-- " + data + " -->\n"; s += "<!-- " + _data + " -->\n";
if (tags.size() != 0) { if (_tags.size() != 0) {
s += String(" ").repeat(level); s += String(" ").repeat(level);
s += "(!COMMENT TAG HAS TAGS!)\n"; s += "(!COMMENT TAG HAS TAGS!)\n";
for (int i = 0; i < tags.size(); ++i) { for (int i = 0; i < _tags.size(); ++i) {
s += tags[i]->convert_to_string(level + 1) + "\n"; s += _tags[i]->convert_to_string(level + 1) + "\n";
} }
} }
} else if (type == HTML_PARSER_TAG_TYPE_DOCTYPE) { } else if (_type == HTML_PARSER_TAG_TYPE_DOCTYPE) {
s += data + "\n"; s += _data + "\n";
if (tags.size() != 0) { if (_tags.size() != 0) {
s += String(" ").repeat(level); s += String(" ").repeat(level);
s += "(!DOCTYPE TAG HAS TAGS!)\n"; s += "(!DOCTYPE TAG HAS TAGS!)\n";
for (int i = 0; i < tags.size(); ++i) { for (int i = 0; i < _tags.size(); ++i) {
s += tags[i]->convert_to_string(level + 1) + "\n"; s += _tags[i]->convert_to_string(level + 1) + "\n";
} }
} }
} else if (type == HTML_PARSER_TAG_TYPE_NONE) { } else if (_type == HTML_PARSER_TAG_TYPE_NONE) {
for (int i = 0; i < tags.size(); ++i) { for (int i = 0; i < _tags.size(); ++i) {
s += tags[i]->convert_to_string(level) + "\n"; s += _tags[i]->convert_to_string(level) + "\n";
s += String(" ").repeat(level); s += String(" ").repeat(level);
} }
} }
@ -401,12 +494,16 @@ void HTMLParserTag::print() const {
} }
HTMLParserTag::HTMLParserTag() { HTMLParserTag::HTMLParserTag() {
type = HTMLParserTag::HTML_PARSER_TAG_TYPE_NONE; _type = HTMLParserTag::HTML_PARSER_TAG_TYPE_NONE;
} }
HTMLParserTag::~HTMLParserTag() { HTMLParserTag::~HTMLParserTag() {
tags.clear(); _tags.clear();
attributes.clear(); _attributes.clear();
}
Ref<HTMLParserTag> HTMLParser::get_root() {
return _root;
} }
void HTMLParser::parse(const String &data) { void HTMLParser::parse(const String &data) {
@ -436,7 +533,7 @@ void HTMLParser::parse(const String &data) {
if (data[j] == '>') { if (data[j] == '>') {
Ref<HTMLParserTag> t = memnew(HTMLParserTag); Ref<HTMLParserTag> t = memnew(HTMLParserTag);
t->data = data.substr(i, j - i + 1); t->set_data(data.substr(i, j - i + 1));
t->process(); t->process();
tags.push_back(t); tags.push_back(t);
@ -452,8 +549,8 @@ void HTMLParser::parse(const String &data) {
if (data[j] == '<') { if (data[j] == '<') {
Ref<HTMLParserTag> t = memnew(HTMLParserTag); Ref<HTMLParserTag> t = memnew(HTMLParserTag);
t->data = data.substr(i, j - i); t->set_data(data.substr(i, j - i));
t->type = HTMLParserTag::HTML_PARSER_TAG_TYPE_CONTENT; t->set_type(HTMLParserTag::HTML_PARSER_TAG_TYPE_CONTENT);
tags.push_back(t); tags.push_back(t);
@ -508,8 +605,8 @@ void HTMLParser::parse(const String &data) {
state = STATE_NONE; state = STATE_NONE;
Ref<HTMLParserTag> t = memnew(HTMLParserTag); Ref<HTMLParserTag> t = memnew(HTMLParserTag);
t->data = data.substr(i, j - i); t->set_data(data.substr(i, j - i));
t->type = HTMLParserTag::HTML_PARSER_TAG_TYPE_CONTENT; t->set_type(HTMLParserTag::HTML_PARSER_TAG_TYPE_CONTENT);
tags.push_back(t); tags.push_back(t);
@ -520,7 +617,7 @@ void HTMLParser::parse(const String &data) {
} }
} }
root.instance(); _root.instance();
// process tags into hierarchical order // process tags into hierarchical order
Vector<Ref<HTMLParserTag>> tag_stack; Vector<Ref<HTMLParserTag>> tag_stack;
@ -529,53 +626,53 @@ void HTMLParser::parse(const String &data) {
ERR_CONTINUE(!t.is_valid()); ERR_CONTINUE(!t.is_valid());
if (t->type == HTMLParserTag::HTML_PARSER_TAG_TYPE_NONE) { if (t->get_type() == HTMLParserTag::HTML_PARSER_TAG_TYPE_NONE) {
ERR_PRINT("HTMLParser::parse: t->type == HTMLParserTag::HTML_PARSER_TAG_TYPE_NONE!"); ERR_PRINT("HTMLParser::parse: t->type == HTMLParserTag::HTML_PARSER_TAG_TYPE_NONE!");
//memdelete(t); //memdelete(t);
tags.write[i].unref(); tags.write[i].unref();
continue; continue;
} else if (t->type == HTMLParserTag::HTML_PARSER_TAG_TYPE_OPENING_TAG) { } else if (t->get_type() == HTMLParserTag::HTML_PARSER_TAG_TYPE_OPENING_TAG) {
tag_stack.push_back(t); tag_stack.push_back(t);
tags.write[i].unref(); tags.write[i].unref();
continue; continue;
} else if (t->type == HTMLParserTag::HTML_PARSER_TAG_TYPE_SELF_CLOSING_TAG) { } else if (t->get_type() == HTMLParserTag::HTML_PARSER_TAG_TYPE_SELF_CLOSING_TAG) {
if (tag_stack.size() == 0) { if (tag_stack.size() == 0) {
root->tags.push_back(t); _root->add_child_tag(t);
} else { } else {
tag_stack.write[tag_stack.size() - 1]->tags.push_back(t); tag_stack.write[tag_stack.size() - 1]->add_child_tag(t);
} }
tags.write[i].unref(); tags.write[i].unref();
continue; continue;
} else if (t->type == HTMLParserTag::HTML_PARSER_TAG_TYPE_CONTENT) { } else if (t->get_type() == HTMLParserTag::HTML_PARSER_TAG_TYPE_CONTENT) {
if (tag_stack.size() == 0) { if (tag_stack.size() == 0) {
root->tags.push_back(t); _root->add_child_tag(t);
} else { } else {
tag_stack.write[tag_stack.size() - 1]->tags.push_back(t); tag_stack.write[tag_stack.size() - 1]->add_child_tag(t);
} }
tags.write[i].unref(); tags.write[i].unref();
continue; continue;
} else if (t->type == HTMLParserTag::HTML_PARSER_TAG_TYPE_COMMENT) { } else if (t->get_type() == HTMLParserTag::HTML_PARSER_TAG_TYPE_COMMENT) {
if (tag_stack.size() == 0) { if (tag_stack.size() == 0) {
root->tags.push_back(t); _root->add_child_tag(t);
} else { } else {
tag_stack.write[tag_stack.size() - 1]->tags.push_back(t); tag_stack.write[tag_stack.size() - 1]->add_child_tag(t);
} }
tags.write[i].unref(); tags.write[i].unref();
continue; continue;
} else if (t->type == HTMLParserTag::HTML_PARSER_TAG_TYPE_DOCTYPE) { } else if (t->get_type() == HTMLParserTag::HTML_PARSER_TAG_TYPE_DOCTYPE) {
if (tag_stack.size() == 0) { if (tag_stack.size() == 0) {
root->tags.push_back(t); _root->add_child_tag(t);
} else { } else {
tag_stack.write[tag_stack.size() - 1]->tags.push_back(t); tag_stack.write[tag_stack.size() - 1]->add_child_tag(t);
} }
tags.write[i].unref(); tags.write[i].unref();
continue; continue;
} else if (t->type == HTMLParserTag::HTML_PARSER_TAG_TYPE_CLOSING_TAG) { } else if (t->get_type() == HTMLParserTag::HTML_PARSER_TAG_TYPE_CLOSING_TAG) {
if (tag_stack.size() == 0) { if (tag_stack.size() == 0) {
tags.write[i].unref(); tags.write[i].unref();
@ -589,7 +686,7 @@ void HTMLParser::parse(const String &data) {
Ref<HTMLParserTag> ts = tag_stack[j]; Ref<HTMLParserTag> ts = tag_stack[j];
// we sould only have opening tags on the stack // we sould only have opening tags on the stack
if (ts->tag == t->tag) { if (ts->get_tag() == t->get_tag()) {
// found // found
tag_index = j; tag_index = j;
break; break;
@ -603,16 +700,16 @@ void HTMLParser::parse(const String &data) {
for (int j = tag_index + 1; j < tag_stack.size(); ++j) { for (int j = tag_index + 1; j < tag_stack.size(); ++j) {
Ref<HTMLParserTag> ts = tag_stack[j]; Ref<HTMLParserTag> ts = tag_stack[j];
ts->type = HTMLParserTag::HTML_PARSER_TAG_TYPE_SELF_CLOSING_TAG; ts->set_type(HTMLParserTag::HTML_PARSER_TAG_TYPE_SELF_CLOSING_TAG);
opening_tag->tags.push_back(ts); opening_tag->add_child_tag(ts);
} }
tag_stack.resize(tag_index); tag_stack.resize(tag_index);
if (tag_stack.size() == 0) { if (tag_stack.size() == 0) {
root->tags.push_back(opening_tag); _root->add_child_tag(opening_tag);
} else { } else {
tag_stack.write[tag_stack.size() - 1]->tags.push_back(opening_tag); tag_stack.write[tag_stack.size() - 1]->add_child_tag(opening_tag);
} }
tags.write[i].unref(); tags.write[i].unref();
@ -621,9 +718,9 @@ void HTMLParser::parse(const String &data) {
} }
} }
// add everything remaining on the stack to root // add everything remaining on the stack to _root
for (int i = 0; i < tag_stack.size(); ++i) { for (int i = 0; i < tag_stack.size(); ++i) {
root->tags.push_back(tag_stack[i]); _root->add_child_tag(tag_stack[i]);
} }
for (int i = 0; i < tags.size(); ++i) { for (int i = 0; i < tags.size(); ++i) {
@ -637,15 +734,15 @@ void HTMLParser::parse(const String &data) {
} }
String HTMLParser::convert_to_string() const { String HTMLParser::convert_to_string() const {
if (!root.is_valid()) { if (!_root.is_valid()) {
return ""; return "";
} }
return root->convert_to_string(); return _root->convert_to_string();
} }
void HTMLParser::print() const { void HTMLParser::print() const {
if (root.is_valid()) { if (_root.is_valid()) {
root->print(); _root->print();
} }
} }
@ -653,5 +750,5 @@ HTMLParser::HTMLParser() {
} }
HTMLParser::~HTMLParser() { HTMLParser::~HTMLParser() {
root.unref(); _root.unref();
} }

View File

@ -10,9 +10,14 @@ class HTMLParserAttribute : public Reference {
GDCLASS(HTMLParserAttribute, Reference); GDCLASS(HTMLParserAttribute, Reference);
public: public:
String attribute; String get_attribute();
String data; void set_attribute(const String &val);
bool single;
String get_data();
void set_data(const String &val);
bool get_single();
void set_single(const bool &val);
bool match_attrib(const String &attrib); bool match_attrib(const String &attrib);
bool match_data(const String &d); bool match_data(const String &d);
@ -24,6 +29,11 @@ public:
HTMLParserAttribute(); HTMLParserAttribute();
virtual ~HTMLParserAttribute(); virtual ~HTMLParserAttribute();
protected:
String _attribute;
String _data;
bool _single;
}; };
class HTMLParserTag : public Reference { class HTMLParserTag : public Reference {
@ -40,13 +50,32 @@ public:
HTML_PARSER_TAG_TYPE_CONTENT HTML_PARSER_TAG_TYPE_CONTENT
}; };
int type; int get_type();
void set_type(const int &val);
String tag; String get_tag();
String data; void set_tag(const String &val);
Vector<Ref<HTMLParserTag>> tags; String get_data();
Vector<Ref<HTMLParserAttribute>> attributes; void set_data(const String &val);
void add_child_tag(const Ref<HTMLParserTag> &tag);
void remote_child_tag(const int index);
Ref<HTMLParserTag> get_child_tag(const int index);
int get_child_tag_count() const;
void clear_child_tags();
Vector<Variant> get_child_tags();
void set_child_tags(const Vector<Variant> &val);
void add_child_attribute(const Ref<HTMLParserAttribute> &tag);
void remote_child_attribute(const int index);
Ref<HTMLParserAttribute> get_child_attribute(const int index);
int get_child_attribute_count() const;
void clear_child_attributes();
Vector<Variant> get_attributes();
void set_attributes(const Vector<Variant> &val);
Ref<HTMLParserTag> get_first(const String &t); Ref<HTMLParserTag> get_first(const String &t);
Ref<HTMLParserTag> get_first(const String &t, const String &attrib, const String &val); Ref<HTMLParserTag> get_first(const String &t, const String &attrib, const String &val);
@ -67,13 +96,22 @@ public:
HTMLParserTag(); HTMLParserTag();
virtual ~HTMLParserTag(); virtual ~HTMLParserTag();
protected:
int _type;
String _tag;
String _data;
Vector<Ref<HTMLParserTag>> _tags;
Vector<Ref<HTMLParserAttribute>> _attributes;
}; };
class HTMLParser : public Reference { class HTMLParser : public Reference {
GDCLASS(HTMLParser, Reference); GDCLASS(HTMLParser, Reference);
public: public:
Ref<HTMLParserTag> root; Ref<HTMLParserTag> get_root();
void parse(const String &data); void parse(const String &data);
//void parse_tag(const String &data, const int index); //void parse_tag(const String &data, const int index);
@ -83,6 +121,9 @@ public:
HTMLParser(); HTMLParser();
virtual ~HTMLParser(); virtual ~HTMLParser();
protected:
Ref<HTMLParserTag> _root;
}; };
#endif #endif