如何在C ++中实现通用DOM数据结构?

时间:2010-10-16 23:42:11

标签: c++ templates dom

我正在尝试编写一个非常简单的文档对象模型库实现,以便提供在我的其他项目中使用的通用数据结构。 为了简单起见,我只定义了三个主要类:nodeelementattribute。节点由它的名称定义(例如所有html标签),并且基本上是元素的容器,可以是文本节点和子节点(存储在std::vector<node>中)。

我无法弄清楚如何定义整个树结构。

我需要为我所提到的分类提供模板化界面。

使用示例:

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

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

我不想在完全支持XML的情况下创建完整的DOM抽象级别。我只需要想法以类似DOM的方式组织信息。不需要解析。

提前致谢!

2 个答案:

答案 0 :(得分:2)

不是尝试根据每个节点有多少父节点来强类型化,而是将代码组织为树结构:

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

您的公共界面可能与此有很大不同。我只是想展示一般的类型布局。

您实际上并不需要节点或属性功能,除非您需要与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 library,以便在数据结构中使用简单的初始化语法。

您还可以查看boost::any library以获取可用作值的数据类型,而不是字符串(支持插入任何值的类型安全方法,只要您将其提取为相同类型即可)。

答案 1 :(得分:0)

如果你看看我过去的答案,你会发现我是模板的支持者,但如果你没有其他要求,他们只会妨碍你。解析器不喜欢很多不同类型的处理。 (虽然你说你不需要解析器 - 嗯?)

XML和DOM的目的是使其易于转换为任何内部结构。您不仅不需要定义XML节点模板,还不需要任何类型的自定义数据结构。任何结构都已经是类似DOM的样式。 DAG很麻烦,因为它们有点树和有点图,但你并没有暗示你正在遇到那种障碍。

您说(在删除答案的评论中)您不想使用现有的库。为什么?你真的想做什么?