【问题标题】:Using xml to load objects. Which is the best approach?使用 xml 加载对象。哪个是最好的方法?
【发布时间】:2009-11-05 01:30:47
【问题描述】:

TinyXML

我有一个 XML 文件,其中保存了一堆加载到对象中的数据。现在,我有一个巨大的方法来解析 XML 文件并根据 XML 文件的内容创建适当的对象。这个函数非常大,并且导入了大量的类定义。

每个类类型都从 XML 进行自己的加载会更好吗?这样,XML 代码分散在我的文件中,而不是在一个位置。问题是我需要将 XML 文件中该函数应该从中读取的确切节点传递给它。这可行吗?我正在使用 tinyxml,所以如果想象每个类都可以传递 XML 流(实际上是一个包含 XML 数据的数组),然后我还会传递该对象的根元素 \images\fractal\traversal\ 所以它知道它是什么应该在读书。

然后,保存将以相同的方式进行。

哪种方法最好且使用更广泛?

【问题讨论】:

    标签: c++ xml design-patterns xml-serialization


    【解决方案1】:

    我对 TinyXML 一无所知,但几年来我一直在使用 libxml2 的这种类设计,它对我来说运行良好。

    【讨论】:

      【解决方案2】:

      序列化函数应该是它们序列化的类的朋友。如果您想序列化和反序列化为 XML,您应该编写执行此功能的友元函数。您甚至可以编写自定义的ostream & operator <<() 函数来执行此操作,但是如果您想聚合对象,这会成为问题。更好的策略是定义一种机制,将单个对象转换为 DOM 文档中的节点。

      【讨论】:

        【解决方案3】:

        我可以想到一种方法,基于工厂根据标签提供对象。

        这里的难点实际上并不是如何解耦每个对象内容的反序列化,而是如何解耦标签和对象的关联。

        例如,假设您有以下 XML

        <my_xml>
          <bird> ... </bird>
        </my_xml>
        

        你怎么知道你应该用&lt;bird&gt;标签的内容构建一个Bird对象?

        有两种方法:

        1. 1 对 1 映射,例如:&lt;my_xml&gt; 表示单个对象,因此知道如何反序列化自身。
        2. 集合:&lt;my_xml&gt; 只不过是一个松散的对象集合

        第一个很明显,你知道会发生什么并且可以使用常规构造函数。

        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++ 中总是有点混乱,动态类型确实有帮助:)

        注意:它也适用于流式传输,但要安全地安装起来有点复杂。流式传输的问题是您应该确保不要读取过去的数据并读取所有数据,以便流处于下一个对象的“良好”状态:)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2022-12-14
          • 1970-01-01
          • 2011-07-10
          • 2023-02-02
          • 2010-09-11
          • 1970-01-01
          • 2020-11-19
          相关资源
          最近更新 更多