Skip to content

Parsing

自顶向下parsing

1、void parse(tinyxml2::XMLElement * elem, xml::collection<Item> & collection)

2、void parse(tinyxml2::XMLElement * elem, xml::node<xml::attributes<Attrs...>, Children...> & node)

3、void parse(tinyxml2::XMLElement * elem, xml::leaf<T, xml::attributes<Attrs...>> & leaf)

attributes

attributes对应是struct dict,attributes的值使用的是std::tuple,解析attributes是非常简单的:

同时遍历struct dictnamesvalues,它对应的就是一个for循环,只不过,它是在compile time实现的,显然这是compile-time computation,下面是实现代码,它使用了std::index_sequence技巧来实现的:

template < typename ... Attrs, std::size_t ... I >
void read_attrs(tinyxml2::XMLElement * elem, xml::dict<Attrs...> & attributes, std::index_sequence<I...>) {
    (load(elem, attributes.names[I], std::get<I>(attributes.values)), ...);
}

std::tuple VS std::vector

std::tuple的元素类型、长度在compile time就已经知道了;

std::vector的元素类型在compile time已经知道了,但是它的长度在compile time未知;

trait/consistent interface

template < typename T >
void read(tinyxml2::XMLElement *, T *);

template < >
void read<double>(tinyxml2::XMLElement * elem, double * d) { elem->QueryDoubleText(d); }

template < >
void read<int>(tinyxml2::XMLElement * elem, int * i) { elem->QueryIntText(i); }

template < >
void read<std::string>(tinyxml2::XMLElement * elem, std::string * str) { *str = elem->GetText(); }

/* --------------------------------------------------------------------------------------- */
template < typename T >
void load(tinyxml2::XMLElement * , std::string_view , T & );

template <>
void load<int>(tinyxml2::XMLElement * elem, std::string_view attribute_name, int & attribute) {
    elem->QueryAttribute(attribute_name.data(), &attribute);
}

template <>
void load<std::string>(tinyxml2::XMLElement * elem, std::string_view attribute_name, std::string & attribute) {
    attribute = elem->Attribute(attribute_name.data());
}