2009-11-05 74 views
0

TinyXML使用xml加載對象。哪種方法最好?

我有一個XML文件,它保存了一堆加載到對象中的數據。現在,我有一個巨大的方法來解析XML文件,並根據XML文件的內容創建適當的對象。這個函數非常大,並且導入了大量的類定義。

對於每個類類型來說,從XML中進行自己的加載會更好嗎?這樣XML代碼分散在我的文件中,而不是在一個位置。問題是我需要將該函數應讀取的XML文件中的確切節點傳遞給它。這是可行的嗎?我使用tinyxml,所以如果想象每個類都可以傳遞XML流(實際上包含XML數據的數組),然後我還會傳遞該對象的根元素\ images \ fractal \ traversal \,以便它知道它是什麼應該是閱讀。

然後,保存將以同樣的方式工作。

哪種方法最好,應用更廣泛?

回答

0

我對TinyXML一無所知,但我已經使用libxml2這種類設計好幾年了,它一直在爲我工作。

0

序列化函數應該是它們序列化的類的朋友。如果你想序列化和反序列化爲XML,你應該編寫執行此功能的朋友函數。你甚至可以編寫自定義的ostream & operator <<()函數,但如果你想聚合對象,這會變得有問題。更好的策略是定義一種機制,將單個對象轉換爲DOM文檔中的Node。

0

我可以想到一種方法,基於工廠提供基於標籤的對象。

這裏的困難並不是真的如何去耦每個對象內容的反序列化,而是去耦合一個標籤和一個對象的關聯。

例如,假設您有以下XML

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

你怎麼知道你應該建立一個Bird對象與<bird>標籤的內容?

有2點的方法有:

  1. 1對1映射,IG:<my_xml>表示單個對象,並且因此知道如何反序列本身。
  2. 收藏:<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++中凌亂,動態類型確實有幫助那裏:)

注意:它也可以與流媒體,但更復雜一些到位安全。流式傳輸的問題在於,您應該確保不讀取您的數據並讀取所有數據,以便該數據流處於下一個對象的「良好」狀態:)