我使用libxml的HTML解析器来创建html文档的dom树。 libxml将每个节点的文本内容作为单个字符串(节点)给出,但我的要求是进一步将每个文本节点拆分为空格并创建尽可能多的单词节点。到目前为止,我还没有从libxml找到任何选项,所以我创建了一个昂贵的CPU逻辑来分割文本节点。下面是递归方法的一部分。
void parse(xmlNodePtr cur, El*& parent) {
if (!cur) {
return;
}
string tagName = (const char*) cur->name;
string content = node_text(cur); // function defined below
Element* el = new Element(tagName, content);
parent->childs.push_back(el);
size_t pos;
string text;
cur = cur->children;
while (cur != NULL) {
if (xmlNodeIsText(cur) && (pos = node_text_find(cur, text, " ")) != string::npos) {
string first = text.substr(0, pos);
string second = text.substr(pos + 1);
El *el1 = new Element("text", first);
el->childs.push_back(el1);
El *el2 = new Element("text", " ");
el->childs.push_back(el2);
xmlNodeSetContent(cur, BAD_CAST second.c_str());
continue;
}
parse(cur, el);
cur = cur->next;
}
}
string node_text(xmlNodePtr cur) {
string content;
if (xmlNodeIsText(cur)) {
xmlChar *buf = xmlNodeGetContent(cur);
content = (const char*) buf;
}
return content;
}
size_t node_text_find(xmlNodePtr cur, string& text, string what){
text = node_text(cur);
return text.find_first_of(what);
}
上面代码的问题是它对于某些UTF字符串(如中文)没有用,而且这段代码在整个解析过程中增加了时间。
任何人都可以建议更好的方法,提前谢谢你!
答案 0 :(得分:1)
我没有完整的答案,但我确实看到你做了xmlChar
到char
的明确演员。这是一个不好的迹象,也可能是因为它不能用于Unicode。
如果你正在使用Unicode,xmlChar可能是,你需要使用Unicode文本处理库。不是std :: string。
你实际上有两个选择。查找以UTF-8进行处理或将UTF-8转换为wchar
(宽字符)的库。如果转换为wchar
,则可以使用wstring
及其函数来处理Unicode。
libxml2 xmlChar * to std::wstring看起来很有用。
至于速度,我的眼睛是否欺骗了我,或者你是否在一个空间上分裂并创造了一个新的元素然后再分裂?这不是表现的方式。我认为如果删除文本节点,将所有单词拆分出去并添加新节点,情况会更好。
减速很可能是在重复创建,复制和销毁对象时。努力减少这种情况。例如,如果Element有一个接受开始/结束迭代器对的构造函数形式,或者一个开始,长度对,那么比创建一个子串(copy!)和创建一个Element(copy!)然后销毁它更有效。子串。
重复调用xmlNodeSetContent和文本字符串的后半部分(可能很大),可以获得O 2 性能。不好。