Ejemplo n.º 1
0
	std::vector<DomNode> DomDocument::load(
		IODevice &input,
		bool eat_whitespace,
		DomNode insert_point)
	{
		clear_all();

		XMLTokenizer tokenizer(input);
		tokenizer.set_eat_whitespace(eat_whitespace);

		if (insert_point.is_element() == false)
			insert_point = *this;

		std::vector<DomNode> node_stack;
		node_stack.push_back(insert_point);

		std::vector<DomNode> result;
		try
		{
			XMLToken cur_token;
			tokenizer.next(&cur_token);
			while (cur_token.type != XMLToken::NULL_TOKEN)
			{
				switch (cur_token.type)
				{
				case XMLToken::TEXT_TOKEN:
					node_stack.back().append_child(create_text_node(cur_token.value));
					if (node_stack.back() == insert_point)
						result.push_back(node_stack.back().get_last_child());
					break;

				case XMLToken::CDATA_SECTION_TOKEN:
					node_stack.back().append_child(create_cdata_section(cur_token.value));
					if (node_stack.back() == insert_point)
						result.push_back(node_stack.back().get_last_child());
					break;

				case XMLToken::ELEMENT_TOKEN:
					if (cur_token.variant != XMLToken::END)
					{
						DomString namespace_uri = DomDocument_Impl::find_namespace_uri(cur_token.name, cur_token, node_stack.back());
						DomElement element = create_element_ns(namespace_uri, cur_token.name);
						node_stack.back().append_child(element);
						if (node_stack.back() == insert_point)
							result.push_back(node_stack.back().get_last_child());

						int size = (int)cur_token.attributes.size();
						for (int i = 0; i < size; i++)
						{
							XMLToken::Attribute &attribute = cur_token.attributes[i];
							DomString attribute_namespace_uri = DomDocument_Impl::find_namespace_uri(attribute.first, cur_token, node_stack.back());
							element.set_attribute_ns(
								attribute_namespace_uri,
								attribute.first,
								attribute.second);
						}

						if (cur_token.variant == XMLToken::BEGIN)
							node_stack.push_back(element);
					}
					else
					{
						node_stack.pop_back();
						if (node_stack.empty()) throw Exception("Malformed XML tree!");
					}
					break;

				case XMLToken::NULL_TOKEN:
					break;

				case XMLToken::ENTITY_REFERENCE_TOKEN:
					break;

				case XMLToken::ENTITY_TOKEN:
					break;

				case XMLToken::COMMENT_TOKEN:
					node_stack.back().append_child(create_comment(cur_token.value));
					if (node_stack.back() == insert_point)
						result.push_back(node_stack.back().get_last_child());
					break;

				case XMLToken::DOCUMENT_TYPE_TOKEN:
					break;

				case XMLToken::NOTATION_TOKEN:
					break;

				case XMLToken::PROCESSING_INSTRUCTION_TOKEN:
					node_stack.back().append_child(create_processing_instruction(cur_token.name, cur_token.value));
					if (node_stack.back() == insert_point)
						result.push_back(node_stack.back().get_last_child());
					break;
				}

				tokenizer.next(&cur_token);
			}
		}
		catch (const Exception& e)
		{
			for (auto & elem : result)
			{
				insert_point.remove_child(elem);
			}
			throw;
		}
		return result;
	}