Thay vì cố gắng gõ mạnh mỗi nút dựa trên bao nhiêu cha mẹ nó đã, tổ chức mã của bạn như một cấu trúc cây:
class Element
{
public:
std::string Name;
std::map<std::string, std::string, std::less<std::string> > Attributes;
std::list<Element> Children;
};
public interface của bạn có thể sẽ trông khác nhiều so với này. Tôi chỉ đang cố gắng hiển thị bố cục kiểu chung.
Bạn không thực sự cần các tính năng Nút hoặc Thuộc tính, trừ khi bạn cần lặp lại chúng trong bộ sưu tập cùng với Phần tử. Nó là một tính năng hữu ích cho các thư viện XML DOM, nhưng nếu bạn chỉ đang cố tạo một cấu trúc dữ liệu, bạn không cần phải tuân theo thiết kế DOM cho chữ cái đó.
Trong thực tế, nếu bạn chỉ đi cho một cấu trúc dữ liệu chung, bạn có thể chỉ muốn property bag:
#include<map>
#include<string>
#include<iostream>
class PropertyBag;
typedef std::map<std::string, PropertyBag> PropertyMap;
class PropertyBag : public PropertyMap
{
public:
PropertyBag(const std::string& value)
: value(value)
{
}
PropertyBag& operator=(const std::string& value)
{
this->value = value;
return *this;
}
operator std::string&() { return value; }
private:
std::string value;
friend PropertyMap::mapped_type& PropertyMap::operator[](const PropertyMap::key_type&);
PropertyBag() { }
};
void SomeFunction(const std::string& value)
{
std::cout << value << "\n";
}
int main(int argc, char* argv[])
{
PropertyBag config("configuration root");
config["child1"] = "value1";
config["child1"]["subchild1"] = "value2";
SomeFunction(config["child1"]);
SomeFunction(config["child1"]["subchild1"]);
return 0;
}
Chỉ cần nói về cú pháp, bạn cũng có thể thử để có được khôn lanh với quá tải operator()
, và/hoặc các phương pháp chuỗi:
PropertyBag& SomeMethod(const std::string& someParam)
{
// do something here...
return *this;
}
PropertyBag& operator()(const std::string& p1, const std::string& p2)
{
// ...
return *this;
}
// ...
Configuration config1("root")
.SomeMethod("p1")
.SomeMethod("p2");
Configuration config2("root")
("Something", "blah")
("sizzle", "V2");
Tôi tưởng tượng bản sao văn bản/mã ít hơn, thì càng tốt. Bạn càng có thể lấy mã của mình để có cú pháp như JSON hoặc YAML thì càng tốt.
Khi C++ 0x xuất hiện, bạn có thể có nhiều tùy chọn đơn giản hơn cho bạn.Bạn cũng có thể xem xét boost::assign library để có cú pháp khởi tạo dễ dàng để sử dụng trên cấu trúc dữ liệu của bạn.
Bạn cũng có thể xem boost::any library cho kiểu dữ liệu mà bạn có thể sử dụng làm giá trị, thay vì chuỗi (hỗ trợ phương pháp chèn an toàn kiểu bất kỳ, miễn là bạn trích xuất cùng loại).
+1, bây giờ tôi hiểu câu hỏi tốt hơn. Tôi nghĩ rằng bạn đang cố gắng để thực hiện một thư viện XML :) –