void HtmlParser::parseExtraAttributes(const char* szAttributesText, HtmlNode* pTargetNode, const char* szNamePrefix) { assert(pTargetNode); const char* p = szAttributesText; const char* ps = NULL; MemBuffer mem; bool inQuote1 = false, inQuote2 = false; unsigned char c; while(c = *p) { if(c == '\'') inQuote1 = !inQuote1; else if(c == '\"') inQuote2 = !inQuote2; bool notInQuote = (!inQuote1 && !inQuote2); if(notInQuote && (c == '\"' || c == '\'') && !isspace(p[1])) { //处理属性值引号后面没有空白分隔符的情况:a="v1"b=v2 (这种错误写法不少见,应兼容之) if(ps) { mem.appendPointer(duplicateStrAndUnquote(ps, p - ps + 1)); ps = NULL; } p++; continue; } if(notInQuote && (c == '=' || isspace(c))) { if(ps) { mem.appendPointer(duplicateStrAndUnquote(ps, p - ps)); ps = NULL; } if(c == '=') mem.appendPointer(NULL); } else { if(ps == NULL) ps = p; } p++; } if(ps) mem.appendPointer(duplicateStrAndUnquote(ps, p - ps)); mem.appendPointer(NULL); mem.appendPointer(NULL); char** pp = (char**) mem.getData(); //下面把解析出来的属性值存入pTargetNode->attributes MemBuffer* attributes = pTargetNode->attributes; if(attributes == NULL) { attributes = new MemBuffer(); pTargetNode->attributes = attributes; } for(int i = 0, n = mem.getDataSize() / sizeof(char*) - 2; i < n; i++) { if(!szNamePrefix) { attributes->appendPointer(pp[i]); //attribute name } else { char* newAttributeName = duplicateStr(pp[i], -1, szNamePrefix); attributes->appendPointer(newAttributeName); //attribute name freeDuplicatedStr(pp[i]); } if(pp[i+1] == NULL) { attributes->appendPointer(pp[i+2]); //attribute value i += 2; } else attributes->appendPointer(NULL); //attribute vlalue //标记需free属性名称和属性值文本 //TODO: 将来优化到尽量少复制文本 attributes->appendInt(FLAG_NEED_FREE_NAME | FLAG_NEED_FREE_VALUE); //attribute flags } attributes->shrink(); pTargetNode->attributeCount = attributes->getDataSize() / sizeof(HtmlAttribute); }