TinyXML的
我有一个XML文件,它保存了一堆加载到对象中的数据。现在,我有一个巨大的方法来解析XML文件并根据XML文件的内容创建适当的对象。这个函数非常大,并导入了许多类定义。
每个类类型从XML进行自己的加载会更好吗?这样,XML代码分散在我的文件中,而不是一个位置。问题是我需要将XML函数应该读取的XML文件中的确切节点传递给它。这可行吗?我正在使用tinyxml,所以如果想象每个类都可以传递XML流(实际上是一个包含XML数据的数组)然后我也会传递该对象的根元素\ images \ fractal \ traversal \所以它知道它是什么应该是读书。
然后保存将以相同的方式工作。
哪种方法最好,使用更广泛?
答案 0 :(得分:0)
我对TinyXML一无所知,但我已经使用libxml2这种类设计已经好几年了,而且它对我来说一直很好。
答案 1 :(得分:0)
序列化函数应该是它们序列化的类的朋友。如果要序列化和反序列化为XML,则应编写执行此功能的friend函数。您甚至可以编写执行此操作的自定义ostream & operator <<()
函数,但如果要聚合对象,则会出现问题。更好的策略是定义一种机制,将单个对象转换为DOM文档中的Node。
答案 2 :(得分:0)
我可以想到一种方法,基于工厂提供基于标签的对象。
这里的困难并不是如何解耦每个对象内容的反序列化,而是解耦标记和对象的关联。
例如,假设您有以下XML
<my_xml>
<bird> ... </bird>
</my_xml>
您如何知道应使用Bird
标记的内容构建<bird>
对象?
有两种方法:
<my_xml>
表示单个对象,因此知道如何反序列化自身。<my_xml>
只不过是一个松散的对象集合第一个很明显,你知道会发生什么,并且可以使用常规构造函数。
C ++中的问题是你有静态类型,这使得第二种情况更加困难,因为你需要虚拟构造。
虽然可以使用原型来实现虚拟构建。
// Base class
class Serializable:
{
public:
virtual std::auto_ptr<XmlNode*> serialize() const = 0;
virtual std::auto_ptr<Serializable> deserialize(const XmlNode&) const = 0;
};
// Collection of prototypes
class Deserializer:
{
public:
static void Register(Tag tag, const Serializable* item)
{
GetMap()[tag] = item;
}
std::auto_ptr<Serializable> Create(const XmlNode& node)
{
return GetConstMap()[node.tag()]->deserialize(node);
// I wish I could write that ;)
}
private:
typedef std::map<Tag, const Serializable*> prototypes_t;
prototypes_t& GetMap()
{
static prototypes_t _Map;
return _Map;
}
prototypes_t const& GetConstMap() { return GetMap(); }
};
// Example
class Bird: public Serializable
{
virtual std::auto_ptr<Bird> deserialize(const XmlNode& node);
};
// In some cpp (bird.cpp is indicated)
const Bird myBirdPrototype;
Deserializer::Register('bird', myBirdPrototype);
反序列化在C ++中总是有点混乱,动态类型确实有助于:)
注意:它也适用于流媒体,但安全地安装起来有点复杂。流式传输的问题是你应该确保不要读取过去的数据并读取所有数据,以便流对于下一个对象处于“良好”状态:)