Как реализовать общую структуру данных DOM в C ++? - PullRequest
10 голосов
/ 17 октября 2010

Я пытаюсь написать очень простую реализацию библиотеки объектной модели документа, чтобы обеспечить общую структуру данных для использования в моих дальнейших проектах. Для простоты я определил только три основных класса: node, element и attribute. Узел определяется его именем (например, всеми HTML-тегами) и в основном является контейнером для элемента, который может быть как текстовым, так и подузлами (хранится в std::vector<node>).

Я просто не могу понять, как определить целую древовидную структуру.

Мне нужны шаблонные интерфейсы для того класса, о котором я говорил.

Пример использования:

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

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

Я не хочу создавать полный уровень абстракции DOM с полной поддержкой XML. Мне просто нужны идеи для организации информации в стиле DOM. Разбор не требуется.

Заранее спасибо!

Ответы [ 2 ]

2 голосов
/ 17 октября 2010

Вместо того, чтобы пытаться строго набирать каждый узел в зависимости от количества его родителей, организуйте свой код в виде древовидной структуры:

class Element
{
public:
  std::string Name;
  std::map<std::string, std::string, std::less<std::string> > Attributes;
  std::list<Element> Children;
};

Ваш публичный интерфейс, вероятно, будет сильно отличаться от этого. Я просто пытаюсь показать общий вид шрифта.

Вам на самом деле не нужны функции Node или Attribute, если вам не нужно перебирать их в коллекции вместе с Elements. Это полезная функция для библиотек XML DOM, но если вы просто пытаетесь создать структуру данных, вам не обязательно следовать букве DOM.

На самом деле, если вы просто собираетесь использовать общую структуру данных, вам может понадобиться пакет свойств:

#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;
}

Просто говоря о синтаксисе, вы также можете попытаться запутаться с перегрузкой operator() и / или с цепочечными методами:

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");

Я представляю, чем меньше дублирования текста / кода, тем лучше. Чем ближе ваш код будет иметь синтаксис, такой как JSON или YAML, тем лучше.

Когда выйдет c ++ 0x, у вас могут появиться гораздо более простые варианты. Вы также можете заглянуть в библиотеку boost :: assign для простого синтаксиса инициализации, используемого в вашей структуре данных.

Вы также можете найти в boost :: any library тип данных, который можно использовать в качестве значения вместо строк (поддерживает безопасный для ввода метод вставки любого значения, если распакуйте его как тот же тип).

0 голосов
/ 17 октября 2010

Если вы посмотрите на мои прошлые ответы, вы увидите, что я сторонник шаблонов, но если у вас нет других требований, они будут только мешать.Парсеры не любят много разных типов, чтобы иметь дело с.(Хотя вы говорите, что вам не нужен синтаксический анализатор - да?)

Смысл XML и DOM состоит в том, чтобы упростить перевод в любую внутреннюю структуру и из нее.Мало того, что вам не нужно определять шаблон узла XML, вам не нужно любой вид настраиваемой структуры данных.Любая структура уже в стиле DOM.DAG проблематичны, потому что они являются своего рода деревьями и своего рода графами, но вы не намекаете, что сталкиваетесь с таким препятствием.

Вы говорите (в комментарии к удаленному ответу), что вы нене хочу использовать существующую библиотеку.Зачем?Что ты на самом деле пытаешься сделать?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...