2010-10-16 30 views
9

Tôi đang cố viết một thư viện mô hình đối tượng tài liệu rất đơn giản để cung cấp một cấu trúc dữ liệu chung để sử dụng trong các dự án tiếp theo của tôi. Chỉ cần giữ cho mọi thứ đơn giản, tôi đã xác định chỉ có ba lớp chính: node, elementattribute. Một nút được xác định bởi tên của nó (ví dụ: tất cả các thẻ html) và về cơ bản là một vùng chứa cho một phần tử có thể vừa là văn bản vừa là các nút con (được lưu trữ trong một std::vector<node>).Làm cách nào để triển khai cấu trúc dữ liệu DOM chung trong C++?

Tôi không thể tìm ra cách xác định toàn bộ cấu trúc cây.

Tôi cần giao diện templatized cho phân loại mà tôi đã giới thiệu.

Ví dụ về sử dụng:

element<string> txt1("Some text"); 

element< element<string> > div1("div", txt1); 

Tôi không muốn tạo ra một mức độ trừu tượng DOM hoàn thành với sự hỗ trợ đầy đủ các XML. Tôi chỉ cần những ý tưởng để tổ chức thông tin theo phong cách giống DOM. Không cần phân tích cú pháp.

Cảm ơn trước!

+0

+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 :) –

Trả lời

1

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).

+0

@Merlyn: danh sách có hiệu suất thời gian chạy khủng khiếp, bạn có chắc chắn bạn không muốn một véc tơ ở đây không? –

+1

@Matthieu: Danh sách tốt hơn thể hiện các hoạt động bạn thực hiện trên cấu trúc như thế này. Bạn không biết kích thước để bắt đầu với, và bạn sẽ không bao giờ làm chỉ mục dựa trên truy cập vào trẻ em. Trong trường hợp này, một danh sách có thể hoạt động tốt hơn cho việc xây dựng và nhanh hơn để truyền tải. Nhưng trong cuộc sống thực, loại perf này hiếm khi trở thành nút cổ chai, và nếu có, bạn sẽ tìm ra giải pháp lưu trữ tùy chỉnh cho phần đó của ứng dụng, thay vì cấu trúc dữ liệu chung. –

+1

@Merlyn: thực hiện giải pháp lưu trữ tùy chỉnh là giải pháp cuối cùng dành riêng cho các chuyên gia. Đối với sự lựa chọn danh sách, tôi mạnh mẽ không đồng ý. Lựa chọn đầu tiên của một container phải là 'vector' hoặc' deque', bởi vì chúng đơn giản hơn. Chỉ khi bạn có yêu cầu cụ thể, bạn nên thay đổi: 'unordered_set' cho unicity,' set' để đặt hàng, 'stack' /' queue' để truy cập cụ thể, vv ... lợi thế duy nhất của việc sử dụng 'list', nói chung, là bảo đảm hủy bỏ vòng lặp. –

0

Nếu bạn nhìn vào các câu trả lời trong quá khứ, bạn sẽ thấy rằng tôi là người đề xuất các mẫu, nhưng nếu bạn không có yêu cầu nào khác, chúng sẽ chỉ cản trở. Trình phân tích cú pháp không thích nhiều loại khác nhau để xử lý. (Mặc dù bạn nói rằng bạn không cần một trình phân tích cú pháp - huh?)

Điểm của XML và DOM là giúp dễ dàng dịch sang và từ bất kỳ cấu trúc nội bộ nào. Bạn không chỉ không cần phải xác định mẫu nút XML, bạn không nên cần bất kỳ cấu trúc dữ liệu tùy chỉnh nào. Bất kỳ cấu trúc nào đã có trong kiểu giống DOM. DAG là phiền hà, bởi vì chúng là các loại cây và đồ thị, nhưng bạn không gợi ý rằng bạn đang đánh vào loại rào cản đó.

Bạn nói (trong nhận xét cho câu trả lời đã xóa) mà bạn không muốn sử dụng thư viện hiện có. Tại sao? Bạn đang thực sự cố gắng làm gì?

+0

"Mặc dù bạn nói rằng bạn không cần một trình phân tích cú pháp - huh?" Vâng! Đúng vậy, tôi không cần một trình phân tích cú pháp! Mathod phân tích cú pháp của tôi là một thủ tục rất tiềm ẩn. Tôi có thể cho bạn thấy một số ví dụ khi thực hiện xong. Điều tôi đang làm là một công cụ tạo mẫu cho html - vì vậy tôi muốn có một biểu diễn dữ liệu html trừu tượng để sử dụng trong thao tác trên cây DOM. – Rizo

+0

@Rizo: Trong trường hợp đó, bạn đang viết một trình phân tích cú pháp và bạn đang tạo thư viện HTML (không phải XML) của riêng mình. Và như tôi đã nói, trừ khi có lý do để sử dụng các mẫu, họ sẽ chỉ cản đường. – Potatoswatter

+0

Tôi chỉ nghĩ rằng xml là cú pháp và tương đương về mặt logic với html (phải không?). – Rizo

Các vấn đề liên quan