Bonjour à tous,
J'utilise Xeumeuleu pour manipuler le XML (lib basée sur Xercès C++ ). Je n'ai jamais eu de problème avec (je trouve quand même le XML très lourd à gérer, je ne sais pas si je referai ce choix dans le futur). A cause des difficultés rencontrées avec ce XML, j'ai introduit une petite généralisation via une classe de base pour pouvoir plus tard manipuler autre chose si besoin (CSV, etc. ). Et là c'est le drame, je n'arrive plus à gérer correctement les listes à l'intérieur d'un même noeud.
J'avoue être démuni, je cherche depuis une semaine le problème sans aucuns résultats, donc j'espère que vous aurez des meilleures idées que moi !
Voici mon main : j'écris dans un fichier XML une structure simple (deux points ici), et j'essaye ensuite de les loader à nouveau. La première solution ne marche pas, je "rentre" pas correctement dans les noeuds, alors que la deuxième marche très bien.
Voici les deux classes pour lire le XML. Elles utilisent une factory qui marche très bien. Les deux classes sont quasi identiques : une manipule mon abstraction CIXMLHandler, l'autre directement le xml:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 int main() { { // Write a XML file for example, works nicely CIoPoint point1 (1,2); CIoPoint point2 (3.2,4.6); xml::xofstream file_out("test.xml"); COXMLHandler h_out (file_out); h_out.Start("Document"); point1.Save(h_out); point2.Save(h_out); h_out.End(); } // Try to read the same XML file xml::xifstream file_in("test.xml"); #ifdef MY_HANDLER // Doesnt'work CIXMLHandler h_in(file_in); h_in.Start("Document"); CIXMLHandler::node_vector_ptr vect = h_in.GetNodes(); #else // Works CXmlListLoader2<> h_in(file_in); file_in >> xml::start("Document"); h_in.Load(); CXmlListLoader2<>::vector_ptr vect = h_in.GetCollection(); #endif return 0; }istream (le flux de Xeumeuleu).
Enfin, voici mon abstraction:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73 template <class T = IIoObject> class CXmlListLoader { public: typedef std::vector<boost::shared_ptr<T> > vector_ptr; CXmlListLoader(CIXMLHandler& handler) : m_handler(handler) {} void Load() { xml::xistream& xis = m_handler.GetXMLStream(); xis >> xml::list(*this, &CXmlListLoader<T>::Load ); } const vector_ptr& GetCollection() {return m_collection;} private: void Load(const std::string& , xml::xistream& xis) { try { const std::string name = xml::attribute<std::string>(xis, "name" ); // Exception if attribute does not have a name boost::shared_ptr<IIoObject> node = CObjectFactory<IIoObject>::Instance().Create(name); node->Load(m_handler); m_collection.push_back(boost::static_pointer_cast<T>(node) ); } catch (const std::exception& e) { std::cout << e.what() << std::endl; } } CIXMLHandler& m_handler; vector_ptr m_collection; }; template <class T = IIoObject> class CXmlListLoader2 { public: typedef std::vector<boost::shared_ptr<T> > vector_ptr; CXmlListLoader2(xml::xistream& stream) : m_stream(stream) {} void Load() { m_stream >> xml::list(*this, &CXmlListLoader2<T>::Load ); } const vector_ptr& GetCollection() {return m_collection;} private: void Load(const std::string& , xml::xistream& xis) { try { const std::string name = xml::attribute<std::string>(xis, "name" ); // Exception if attribute does not have a name boost::shared_ptr<IIoObject> node = CObjectFactory<IIoObject>::Instance().Create(name); node->Load(xis); m_collection.push_back(boost::static_pointer_cast<T>(node) ); } catch (const std::exception& e) { std::cout << e.what() << std::endl; } } xml::xistream& m_stream; vector_ptr m_collection; };
et sa classe fille pour gérer le XML, qui implémente simplement les fonctions membres virtuelles, en stockant un flux xml par référence :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 class IIHandler { public: typedef std::vector<boost::shared_ptr<IIoObject> > node_vector_ptr; IIHandler() {} virtual ~IIHandler() {} // Read a Node with name virtual void Start(const std::string& str) = 0; // Get Out of a node virtual void End() = 0; // Extract nodes virtual node_vector_ptr GetNodes() = 0; // Read Attribute virtual void Attribute(const std::string& tag, std::string& value) = 0; virtual void Attribute(const std::string& tag, bool& value) = 0; virtual void Attribute(const std::string& tag, int& value) = 0; virtual void Attribute(const std::string& tag, long& value) = 0; virtual void Attribute(const std::string& tag, float& value) = 0; virtual void Attribute(const std::string& tag, double& value) = 0; virtual void Attribute(const std::string& tag, unsigned int& value) = 0; virtual void Attribute(const std::string& tag, unsigned long& value) = 0; // Read content inside Node virtual void Content(const std::string& tag, std::string& value) = 0; virtual void Content(const std::string& tag, bool& value) = 0; virtual void Content(const std::string& tag, int& value) = 0; virtual void Content(const std::string& tag, long& value) = 0; virtual void Content(const std::string& tag, float& value) = 0; virtual void Content(const std::string& tag, double& value) = 0; virtual void Content(const std::string& tag, unsigned int& value) = 0; virtual void Content(const std::string& tag, unsigned long& value) = 0; };
Pour info, ma classe CIoPoint est tout ce qu'il y a de plus simple, je ne montre ici que les deux fonctions Load :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42 class CIXMLHandler : public IIHandler { public: CIXMLHandler(xml::xistream& stream); virtual ~CIXMLHandler() {} // Go into Node with name virtual void Start(const std::string& str); // Get Out of a node virtual void End(); // Extract nodes virtual node_vector_ptr GetNodes(); // Read Attribute to a Node virtual void Attribute(const std::string& tag, std::string& value); virtual void Attribute(const std::string& tag, bool& value); virtual void Attribute(const std::string& tag, int& value); virtual void Attribute(const std::string& tag, long& value); virtual void Attribute(const std::string& tag, float& value); virtual void Attribute(const std::string& tag, double& value); virtual void Attribute(const std::string& tag, unsigned int& value); virtual void Attribute(const std::string& tag, unsigned long& value); // Read content inside Node virtual void Content(const std::string& tag, std::string& value); virtual void Content(const std::string& tag, bool& value); virtual void Content(const std::string& tag, int& value); virtual void Content(const std::string& tag, long& value); virtual void Content(const std::string& tag, float& value); virtual void Content(const std::string& tag, double& value); virtual void Content(const std::string& tag, unsigned int& value); virtual void Content(const std::string& tag, unsigned long& value); xml::xistream& GetXMLStream() {return m_stream;} private: // Manipulate input XML File xml::xistream& m_stream; };
Au final, mon encapsulation ne marche pas. Mais je ne sais vraiment pas où. Je ne fais que transférer les appels au flux XML comme via un proxy, mais ça ne semble pas marcher. Je voulais juste éviter les appels direct à la bibliothèque Xeumeuleu en passant par une abstraction et tout encapsuler, mais il semble que quelque chose manque. J'ai pourtant tout bien passé par référence...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 void CIoPoint::Load(IIHandler& h) { double x = 0, y = 0; h.Attribute("x", x); h.Attribute("y", y); m_point = CPoint<double>(x, y); } void CIoPoint::Load(xml::xistream& str) { double x = 0, y = 0; str >> xml::attribute("x", x); str >> xml::attribute("y", y); m_point = CPoint<double>(x, y); }
Je peux fournir l'exemple ci dessus en projet Visual Studio, mais il nécessite boost.TR1 , Xeumeuleu et Xercès pour fonctionner, alors je pense pas que ce soit très intéressant.
Merci pour votre aide !![]()
Partager