示例#1
0
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);
}