IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Problème incompréhensible avec XML


Sujet :

C++

  1. #1
    Membre chevronné
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Points : 2 107
    Points
    2 107
    Par défaut Problème incompréhensible avec XML
    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.
    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;
    }
    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:istream (le flux de Xeumeuleu).
    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;
    };
    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
     
    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;
    };
    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
    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;
    };
    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
     
    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);
    }
    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...

    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 !

  2. #2
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut,
    A quoi ressemble CIXMLHandler::Start ?

  3. #3
    Membre chevronné
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Points : 2 107
    Points
    2 107
    Par défaut
    Salut 3DArchi,

    Comme toutes les fonctions membres, elle transfère au flux la commande concernée. Donc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    void CIXMLHandler::Start(const std::string &str)
    {
    	m_stream.start(str);
    }

  4. #4
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Je comprend pas trop ton truc. CIXMLHandler ne fait pas du tout la même chose que CXmlListLoader2
    En gros, le scénario de chargement pour CXmlListLoader2 est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    CXmlListLoader2<> h_in(file_in);
    file_in >> xml::start("Document");
    h_in.Load();
    CXmlListLoader2<>::vector_ptr vect = h_in.GetCollection();
    Avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    void CXmlListLoader2<>::Load()
    	{
    		m_stream >> xml::list(*this, &CXmlListLoader2<T>::Load );
    	}
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    void CXmlListLoader2<>::Load(const std::string& , xml::xistream& xis)
    // On construit un noeud 
    // Il s'initialise avec noeud->Load
    // On l'ajoute à la collection.
    Avec CIXMLHandler, le scénario est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    CIXMLHandler h_in(file_in);
    h_in.Start("Document");
    CIXMLHandler::node_vector_ptr vect = h_in.GetNodes();
    Avec donc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void CIXMLHandler::Start(const std::string &str)
    {
    	m_stream.start(str);
    }
    Que fait m_stream.start ? Pourquoi il n'y a pas d'équivalent à m_stream >> xml::list(*this, &CXmlListLoader2<T>::Load ); qui - j'imagine - fourni une callback au flux pour qu'il ajoute les noeuds.

  5. #5
    Membre chevronné
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Points : 2 107
    Points
    2 107
    Par défaut
    Re,
    Je suis désolé, mon problème n'est super facile à expliquer...
    Je comprend pas trop ton truc. CIXMLHandler ne fait pas du tout la même chose que CXmlListLoader2
    Si si.
    file_in >> xml::start("Document"); est complètement équivalent à h_in.Start("Document");

    Et la fonction GetNodes() est l'équivalente des deux autres lignes. Je l'avais pas donné, là voici:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    CIXMLHandler::node_vector_ptr CIXMLHandler::GetNodes()
    {
    	CXmlListLoader<> loader(*this);
    	loader.Load();
    	return loader.GetCollection();
    }
    J'encapsule un peu plus de trucs avec mon handler, mais au final c'est vraiment équivalent. Il y a bien appel à xml::list dans les deux cas.

    Merci beaucoup en tout cas 3DArchi pour tenter de me sortir du pétrin !

  6. #6
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut,
    Bon j'imagine que t'as fait du debug pas et pas y tout y tout pour voir la différence.
    Revenons aux sources :
    je n'arrive plus à gérer correctement les listes à l'intérieur d'un même noeud
    Quelle le problème exactement ? Quelle est la différence de comportement ?

Discussions similaires

  1. Problème incompréhensible avec numericUpDown
    Par jlg_47 dans le forum C++/CLI
    Réponses: 1
    Dernier message: 30/12/2010, 22h22
  2. Problème incompréhensible avec Eclipse et JSpinner
    Par esperal dans le forum Eclipse Java
    Réponses: 2
    Dernier message: 20/11/2009, 12h40
  3. Problème incompréhensible avec le type System.Guid !?
    Par jacquesprogram dans le forum VB.NET
    Réponses: 6
    Dernier message: 14/09/2009, 11h23
  4. Perl + XML : problème de '-' avec XML::Simple
    Par rico29600 dans le forum Modules
    Réponses: 6
    Dernier message: 17/07/2007, 14h50
  5. Réponses: 4
    Dernier message: 25/09/2006, 14h57

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo