static void parse_parameter_list(rapidxml::xml_node<>* node, Parameters& parameters)
{
    if (node != NULL)
    {
        std::string name = node->name();

        if (name == "parameteritem")
        {
            parameter p;
            parse_parameter(node->first_node(), p);
            if (! p.name.empty())
            {
                // Copy its description
                std::vector<parameter>::iterator it = std::find_if(parameters.begin(),
                    parameters.end(), par_by_name(p.name));
                if (it != parameters.end())
                {
                    it->brief_description = p.brief_description;
                }
                else
                {
                    parameters.push_back(p);
                }
            }
        }
        else if (name == "param")
        {
            // Element of 'templateparamlist.param (.type,.declname,.defname)'
            parameter p;
            parse_parameter(node->first_node(), p);

            // Doxygen handles templateparamlist param's differently:
            //
            // Case 1:
            // <param><type>typename T</type></param>
            // -> no name, assign type to name, replace typename
            //
            // Case 2:
            // <type>typename</type><declname>T</declname><defname>T</defname>
            // -> set full type
            if (p.name.empty())
            {
                // Case 1
                p.name = p.type;
                boost::replace_all(p.name, "typename", "");
                boost::trim(p.name);
            }
            else
            {
                // Case 2
                p.fulltype = p.type + " " + p.name;
            }

            add_or_set(parameters, p);
        }

        parse_parameter_list(node->first_node(), parameters);
        parse_parameter_list(node->next_sibling(), parameters);
    }
}
void test_parameter_list() {
	char tmp;
	FILE *inn = fopen("tests/test_parameter_list.txt", "r");
	while (!feof(inn)) {
		in = fopen("test.txt", "w+");
		while ((tmp = fgetc(inn)) != '}' && tmp != -1)
			fprintf(in, "%c", tmp);
		if (tmp == EOF) break;
		if (tmp <= 31) continue;
		fseek(in, 0, SEEK_SET);
		idx = 0;
		printf("******************\n");
		get_token_with_history();
		parse_parameter_list();
		fclose(in);
		remove("test.txt");
	}
}
static void parse_element(rapidxml::xml_node<>* node, configuration const& config, std::string const& parent, Element& el)
{
    if (node != NULL)
    {
        std::string name = node->name();
        std::string full = parent + "." + name;

        if (full == ".briefdescription.para")
        {
            parse_para(node, el.brief_description, el.skip);
        }
        else if (full == ".detaileddescription.para")
        {
            std::string para;
            parse_para(node, para, el.skip);
            if (!para.empty() && !el.detailed_description.empty())
            {
                el.detailed_description += "\n\n";
            }
            el.detailed_description += para;
        }
        else if (full == ".location")
        {
            std::string loc = get_attribute(node, "file");
            // Location of (header)file. It is a FULL path, so find the start
            // and strip the rest
            std::size_t pos = loc.rfind(config.start_include);
            if (pos != std::string::npos)
            {
                loc = loc.substr(pos);
            }
            el.location = loc;
            el.line = atol(get_attribute(node, "line").c_str());
        }
        else if (full == ".detaileddescription.para.qbk")
        {
            el.qbk_markup.push_back(markup(node->value()));
        }
        else if (full == ".detaileddescription.para.qbk.after.synopsis")
        {
            el.qbk_markup.push_back(markup(markup_after, markup_synopsis, node->value()));
        }
        else if (full == ".detaileddescription.para.qbk.before.synopsis")
        {
            el.qbk_markup.push_back(markup(markup_before, markup_synopsis, node->value()));
        }
        else if (full == ".detaileddescription.para.qbk.distinguish")
        {
            el.additional_description = node->value();
            boost::trim(el.additional_description);
        }
        else if (full == ".templateparamlist")
        {
            parse_parameter_list(node->first_node(), el.template_parameters);
        }
        else if (full == ".detaileddescription.para.parameterlist")
        {
            std::string kind = get_attribute(node, "kind");
            if (kind == "param")
            {
                parse_parameter_list(node->first_node(), el.parameters);
            }
            else if (kind == "templateparam")
            {
                parse_parameter_list(node->first_node(), el.template_parameters);
            }
        }

        parse_element(node->first_node(), config, full, el);
        parse_element(node->next_sibling(), config, parent, el);
    }
}