diff options
Diffstat (limited to 'src/treebuilder/treebuilder.c')
-rw-r--r-- | src/treebuilder/treebuilder.c | 71 |
1 files changed, 70 insertions, 1 deletions
diff --git a/src/treebuilder/treebuilder.c b/src/treebuilder/treebuilder.c index 2ca2132..28621bd 100644 --- a/src/treebuilder/treebuilder.c +++ b/src/treebuilder/treebuilder.c @@ -12,7 +12,7 @@ #include "treebuilder/internal.h" #include "treebuilder/treebuilder.h" #include "utils/utils.h" - +#include "utils/string.h" static const struct { const char *name; @@ -1242,6 +1242,75 @@ bool formatting_list_replace(hubbub_treebuilder *treebuilder, return true; } +/** + * Adjust foreign attributes. + * + * \param treebuilder Treebuilder instance + * \param tag Tag to adjust the attributes of + */ +void adjust_foreign_attributes(hubbub_treebuilder *treebuilder, + hubbub_tag *tag) +{ + for (size_t i = 0; i < tag->n_attributes; i++) { + hubbub_attribute *attr = &tag->attributes[i]; + const uint8_t *name = treebuilder->input_buffer + + attr->name.data.off; + +#define S(s) (uint8_t *) s, SLEN(s) + + /* 10 == strlen("xlink:href") */ + if (attr->name.len >= 10 && + strncmp((char *) name, "xlink:", + SLEN("xlink:")) == 0) { + size_t len = attr->name.len - 6; + name += 6; + + if (hubbub_string_match(name, len, S("actutate")) || + hubbub_string_match(name, len, + S("arcrole")) || + hubbub_string_match(name, len, + S("href")) || + hubbub_string_match(name, len, + S("role")) || + hubbub_string_match(name, len, + S("show")) || + hubbub_string_match(name, len, + S("title")) || + hubbub_string_match(name, len, + S("type"))) { + attr->ns = HUBBUB_NS_XLINK; + attr->name.data.off += 6; + attr->name.len -= 6; + } + /* 8 == strlen("xml:base") */ + } else if (attr->name.len >= 8 && + strncmp((char *) name, "xml:", SLEN("xml:")) == 0) { + size_t len = attr->name.len - 4; + name += 4; + + if (hubbub_string_match(name, len, S("base")) || + hubbub_string_match(name, len, + S("lang")) || + hubbub_string_match(name, len, + S("space"))) { + attr->ns = HUBBUB_NS_XML; + attr->name.data.off += 4; + attr->name.len -= 4; + } + } else if (hubbub_string_match(name, attr->name.len, + S("xmlns")) || + hubbub_string_match(name, attr->name.len, + S("xmlns:xlink"))) { + attr->ns = HUBBUB_NS_XMLNS; + attr->name.data.off += 6; + attr->name.len -= 6; + } + +#undef S + } +} + + #ifndef NDEBUG static const char *element_type_to_name(element_type type); |