Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 11
  1. #1
    Utente di HTML.it
    Registrato dal
    Jun 2003
    Messaggi
    4,826

    [c++]Xml e SAX progetto completo

    Ciao.
    Spero di non annoiarvi se spiego un po quello che sto cercando di fare , magari(mi piacerebbe) questa discussione potrebbe servire a qualcun altro.
    Ho dei documenti xml che possono essere i diverse centinaia di mega e devo effettuare il parsing per importare solo determinati dati che saranno 1/4 dell' xml , esistono infatti molti tag che non mi interessano per niente , almeno per adesso , e quindi posso tralasciarli .
    Per questo ho scelto SAX come motore di parsing di quest importatore.
    Il documento xml è formato da un insieme di tag che hanno un id=xxx e un insieme di tag che anno un ref = xxx.
    I tag ref rimandano a i tag id che conservano al loro interno un insieme di dati particolari.
    /////////////IMPLEMENTAZIONE
    Io ho creato una classe per tutti i tag che hanno un ID=xxx e per tutti i tag che hanno un REF=xxx e ho fatto derivare queste classi da una classe base CEntityBase.
    per ogni classe id e ref ho un array con il tipo in formato testo della classe (anche nome del tax xml), un array di campi che mi interessano (sempre in formato testo) e gli stessi valori implementati come proprietà della classe.
    La proprietà col tipo mi serve per il parsing SAX , infatti testo per ogni start tag di sax che sia uguale alla mia proprietà tipo e se si attivo faccio la stessa cosa con gli attributi e i sottonodi
    di quella che è definita come classe in xml.
    Quando trovo corrispondenza di valori tra le stringhe nelle classi xml e quelle dell' xml leggo i valori e creo l'oggetto c++ con i dati recuperati .
    infine inserisco in una mappa del tipo:
    map<string,map<string,classe> >

    nel primo campo l'id testuale del tipo , e nella seconda mappa l'id testuale prelevato dall'xml(id=xxx) e infine l'oggetto.


    alla fine vorrei essere in grado di avere una mappa per gli id accessibile cosi:
    CEntityBase elemento = map[TIPO][ID]
    e una mappa per i ref cosi:
    CEntityBase elemento = map[TIPO][REF]

    E' possibile questo con le map dell stl?

    Il problema è che cosi mi sembra molto confusionaria la mia mappa , non ho infatti nessun aiuto per navigare le proprieta.
    Pensavo di fare una cosa del genere :
    passare agli oggetti id e ref il puntatore alle istanze dellle due mappe , in modo da poter gestire meglio e in modo piu' ordinato cosi:
    codice:
    la classe base
    class CBaseEntityIfc
    {
    public:
        CBaseEntityIfc(void);
        virtual ~CBaseEntityIfc(void);
        virtual string CBaseEntityIfc::getID();
        virtual string CBaseEntityIfc::getType(){return "IfcBase";};
        virtual string CBaseEntityIfc::setID(string strId){m_strId = strId;};
        virtual string CBaseEntityIfc::setType(string strType){m_strType = strType;};
    protected:
        //l'id e il tipo sono comuni a tutte le classi IFC per questo le
        //implemento nella classe base
        string m_strId;
        string m_strType;
        
    };
    e le classi derivate:
    class CIfcProject :
        public CBaseEntityIfc
    {
    public:
        CIfcProject(void);
        virtual ~CIfcProject(void);
        map<string, CBaseEntityIfc>* pMap;
        CIfcOwnerHistory* getRefOwnerHistory()
        {
            pMap[this->gettype()][m_strREF];
        }
    };
    col puntatore alle mappe che puo essere della mappa ref o della mappa id ho cercato di creare delle funzioni(la funzione getRefOwnerHistory() nell esempio)che mi ritorna un tipo non base , ma il tipo reale che c'è a quell'indice nella mappa cosi da essere un po piu' ordinato e un po piu' chiaro per uno che lo deve modificare.
    altrimenti se non si conoscono i tipi e non si ha la specifica sotto mano non si capisce niente solo con indici testuali , invece se riuscissi a farlo funzionare potrei avere una cosa del tipo:
    strData1 =IFCProject->getRefOwnerHistory()->getData1() ecc.....

    Vorrei trovare un modo un po piu' ordinato ma nonsono riuscito a pensarlo , mentre per la velocità dovrebbe essere abbastanza veloce (credo) in confronto al DOM.

    Scusate se mi sono espresso male o se è uno dei miei soliti voli pindarici.
    ciao

  2. #2
    Utente di HTML.it
    Registrato dal
    Jun 2003
    Messaggi
    4,826
    In soldoni vorrei sapere come creare una struttura di classi tipizzata a partire da un xml con SAX.

    il centro del mio discorso è qui :

    codice:
    class CIfcProject :
        public CBaseEntityIfc
    {
    public:
        CIfcProject(void);
        virtual ~CIfcProject(void);
        map<string, CBaseEntityIfc>* pMap;
        CIfcOwnerHistory* getRefOwnerHistory()
        {
            pMap[this->gettype()][m_strREF];
        }
    
       string gettype(){return "IfcProject"}
    };
    perchè in pratica non posso avere l'oggetto CIfcOwnerHistory con SAX perchè viene dopo nel documento xml e nel momento in cui instanzio la classe ho solo una stringa ref="codicex" a cio' che verra' dopo con id="codicex".
    PAssando il riferimento alla mappa so che finito il parsing alla locazione di memoria puntata da
    pMap[this->gettype()][m_strREF];ci sara' correttamente il dato cercato.
    E offro anche il tipo.

  3. #3
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Forse ho capito male, ma da come lo descrivi assomiglia molto ad un meccanismo di reflection, argomento troppo vasto per affrontarlo nel forum.

    Se fai una ricerca con google usando reflection c++ come chiave troverai molta documentazione a riguardo e diverse librerie per il supporto alla reflection.
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  4. #4
    Utente di HTML.it
    Registrato dal
    Jun 2003
    Messaggi
    4,826
    grazie shodan.
    So cos è la reflection , e l'ho utilizzata in c# , effettivamente il problema è quello ,affrontato con la reflection dovrebbe diventare semplicissimo.Ti chiedevo se l'hai usata e hai esperienza in qualche libreria per vc++, possibilmente di ridotte dimensioni.
    Inoltre per continuare sul discorso di prima io non sto cercando altro che fare un parsing xml con Sax in c++ e andare a popolare delle classi con i dati dell' xml , cosa che c# fa gia' con gli attributi e la deserializzazione xml.
    Vorrei pero' avere il controllo in c++ di ciò che fa con una libreria ad doc.


    Ti chiedevo inoltre con il precedente post se ha un senso passare un riferimento alla mappa che contiene tutte le entità alle singole classi di "deserializzazione" per fare il lavoro di casting e referenziazione ritornando direttamente un istanza ad una classe dove idclasse nella classe della mappa = refClasse classe che punta l'id con una string ref alla fine del parsing , cioè quando tutte le entità sono state popolate.
    per intenderci questo:
    codice:
    class CIfcProject :
        public CBaseEntityIfc
    {
    public:
        CIfcProject(void);
        virtual ~CIfcProject(void);
        map<string, CBaseEntityIfc>* pMap;
        CIfcOwnerHistory* getRefOwnerHistory()
        {
           (*pMap)[this->gettype()][m_strREF];
        }
    };
    questa:
    CIfcOwnerHistory* getRefOwnerHistory()
    {
    (*pMap)[this->gettype()][m_strREF];
    }
    o ti sembra scorretto.


    ciao .

  5. #5
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Originariamente inviato da giuseppe500
    grazie shodan.
    So cos è la reflection , e l'ho utilizzata in c# , effettivamente il problema è quello ,affrontato con la reflection dovrebbe diventare semplicissimo.Ti chiedevo se l'hai usata e hai esperienza in qualche libreria per vc++, possibilmente di ridotte dimensioni.
    Onestamente no: non l'ho mai usata. Il problema è che il C++ non supporta la reflection in modo nativo (forse il prossimo standard farà qualcosa in merito), quindi tutto passa attraverso RTTI. Se hai fatto la ricerca che ti ho suggerito, avrai certamente notato che molti link forniscono anche delle librerie di supporto alla reflection. Inoltre, di fatto, i compilatori presi in considerazione sono ormai due: Gcc/G++ e VC++; quindi non dovresti aver problemi a usare una di quelle librerie.

    Inoltre per continuare sul discorso di prima io non sto cercando altro che fare un parsing xml con Sax in c++ e andare a popolare delle classi con i dati dell' xml , cosa che c# fa gia' con gli attributi e la deserializzazione xml.
    Vorrei pero' avere il controllo in c++ di ciò che fa con una libreria ad doc.
    Quindi le classi le hai già, devi solo istanziarle e settarne i parametri con quelli dell'XML man mano che il parsing procede. O ho capito male?

    Ti chiedevo inoltre con il precedente post se ha un senso passare un riferimento alla mappa che contiene tutte le entità alle singole classi di "deserializzazione" per fare il lavoro di casting e referenziazione ritornando direttamente un istanza ad una classe dove idclasse nella classe della mappa = refClasse classe che punta l'id con una string ref alla fine del parsing , cioè quando tutte le entità sono state popolate.
    Non mi è chiaro a chi lo dovresti passare. Comunque mi sembra di intuire che vorresti un meccanismo simil COM.
    Potresti postare un pezzetto significativo di quell'XML? Almeno per avere qualche riferimento.
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  6. #6
    Utente di HTML.it
    Registrato dal
    Jun 2003
    Messaggi
    4,826
    Originariamente inviato da shodan
    Non mi è chiaro a chi lo dovresti passare. Comunque mi sembra di intuire che vorresti un meccanismo simil COM.
    Potresti postare un pezzetto significativo di quell'XML? Almeno per avere qualche riferimento.

    ecco per es:
    codice:
    <IfcProject id="i1">
      <GlobalId>2ed7deT153aRxe9mZWpFs7</GlobalId> 
    - <OwnerHistory>
      <IfcOwnerHistory xsi:nil="true" ref="i2" /> 
      </OwnerHistory>
      <Name>Default Project</Name> 
      <Description>Description of Default Project</Description> 
    - <RepresentationContexts ex:cType="set">
      <IfcGeometricRepresentationContext pos="0" xsi:nil="true" ref="i20" /> 
      </RepresentationContexts>
    - <UnitsInContext>
      <IfcUnitAssignment xsi:nil="true" ref="i7" /> 
      </UnitsInContext>
      </IfcProject>
    <IfcOwnerHistory xsi:nil="true" ref="i2" /> ad es è un riferimento , dove il valore dell' attributo ref non fa che puntare ad un elemento della mappa importato con un id.
    In pratica quando trovo una classe ifc nell xml ad es <IfcProject id="i1"> instanzio la classe ,leggo i suoi dati e metto la classe nela mappa cMap[id] con l'id nel caso "i1".
    NElla mappa cMap ci stanno tutte le classi ifc "trovate" nell' xml e nel meccansmo di parsing
    Quando invece trovo un riferimento ad es:
    <IfcOwnerHistory xsi:nil="true" ref="i2" />
    so che ref="i2" fara riferimento ad un oggetto nella mappa cMap con id= "i2" quindi per trovare la classe puntata devo fare solamente cMap["i2"].
    e questo lo vorrei fare direttamente nella classe .
    In pratica aggiungerei un riferimento alla mappa(che finora stava all' esterno , nel meccanismo di parsing) interno alla classe id che sto importando correntemente,e una proprietà alla classe ifc:
    codice:
        map<string, CBaseEntityIfc>* pMap;
        string m_strRefOwnerHistory;
        CIfcOwnerHistory* getRefOwnerHistory()
        {
            (*pMap)[this->gettype()][m_strRefOwnerHistory];
        }
    in modo che dall' esterno della classe il riferimento alla classe id venga trovato semplicemente richiamando oggetto->getRefOwnerHistory() e cosi ' per tutti gli altri riferimenti.
    spero di essermi spiegato bene .
    Ciao.

  7. #7
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Tirando un pò le somme.
    Partiamo da qui:
    codice:
    		map<string, CBaseEntityIfc>* pMap;
        string m_strRefOwnerHistory;
        CIfcOwnerHistory* getRefOwnerHistory()
        {
            (*pMap)[this->gettype()][m_strRefOwnerHistory];
        }
    La map è sbagliata. Infatti presuppone un oggetto fatto e finito di tipo CBaseEntityIfc quando invece dev'essere CBaseEntityIfc*,
    visto che nella funzione getRefOwnerHistory() restituisci un puntatore.
    Tra l'altro quella funzione non può compilare perché:
    1) CIfcOwnerHistory non deriva da CBaseEntityIfc;
    2) CIfcOwnerHistory deriva da CBaseEntityIfc, però il compilatore dice che non può effettuare il downcasting.

    Se è questo il caso hai due possibilita:
    1) Restituisci un puntatore a CBaseEntityIfc;
    codice:
    		map<string, CBaseEntityIfc*>* pMap;
        string m_strRefOwnerHistory;
        CBaseEntityIfc* getRefOwnerHistory()
        {
            (*pMap)[this->gettype()][m_strRefOwnerHistory];
        }
    2) Effettui un dynamic_cast.
    codice:
    		map<string, CBaseEntityIfc*>* pMap;
        string m_strRefOwnerHistory;
        CIfcOwnerHistory* getRefOwnerHistory()
        {
     				CBaseEntityIfc* ptr = (*pMap)[this->gettype()][m_strRefOwnerHistory];
     				return dynamic_cast<CIfcOwnerHistory*>(ptr);
        }
    =================================================
    La map.
    Da come hai scritto, sembra più una multimap, però non cambia per il discorso generale.
    Portarsi dietro un riferimento in quel modo mi sembra molto scomodo. (Chi è il reale possessore della mappa, incaricato della distruzione?)
    Io opterei per rendere la map statica dentro la classe base. In questo modo è visibile a tutte le classi della gerarchia e puoi dimenticare
    il puntatore.
    codice:
    class CBaseEntityIfc
    {
    public:
        // typedef di comodo.
        typedef std::map<std::string, CBaseEntityIfc*> RefOwnerMap;
        CBaseEntityIfc(void);
        virtual ~CBaseEntityIfc(void);
        virtual string CBaseEntityIfc::getID();
        virtual string CBaseEntityIfc::getType(){return "IfcBase";};
        virtual string CBaseEntityIfc::setID(string strId){m_strId = strId;};
        virtual string CBaseEntityIfc::setType(string strType){m_strType = strType;};
    protected:
        //l'id e il tipo sono comuni a tutte le classi IFC per questo le
        //implemento nella classe base
        string m_strId;
        string m_strType;
        // mappa statica
        static RefOwnerMap refMap;
    };
    CBaseEntityIfc::RefOwnerMap CBaseEntityIfc::refMap;
    
    e le classi derivate:
    class CIfcProject :
        public CBaseEntityIfc
    {
    public:
        CIfcProject(void);
        virtual ~CIfcProject(void);
    
        CIfcOwnerHistory* getRefOwnerHistory()
        {
            return dynamic_cast<CIfcOwnerHistory*>(CBaseEntityIfc::refMap[this->gettype()][m_strREF]);
        }
    };
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  8. #8
    Utente di HTML.it
    Registrato dal
    Jun 2003
    Messaggi
    4,826
    grazie.
    Ho trovato quest'articolo
    http://www.ddj.com/cpp/184403786#1

    sul Dr. Dobb's Journal che secondo me tratta dell' abstract factory e di cio' di cui abbiamo parlato nei post precendenti.

    Da quello che ho capito riesce ad instanziare classi da una stringa col nome della classe , o l'identificativo dopo che la classe viene registrata.
    Non ho ben capito a cosa serve la funzione BASE_CREATE_FN
    // a BASE_CREATE_FN is a function that takes no parameters
    // and returns an auto_ptr to a manufactuedObj. Note that
    // we use no parameters, but you could add them
    // easily enough to allow overloaded ctors.
    è la funzione che instanzia le classi del pattern abstract factory?e come viene utilizzata nel caso?
    Perchè fa uso cosi estensivo dei template ?
    Non conoscendoli a fondo non riesco a capire perchè li usa.
    grazie.

  9. #9
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Stendo un velo pietoso su come è stato scritto l'articolo ("Apprentice" ma che è Star Wars? )

    Non c'è alcuna relazione tra chiave e nome della classe. Sei libero di usare qualunque stringa. Se poi usi come stringa il nome della classe è più semplice ricordarla.

    BASE_CREATE_FN non è una funzione, ma un puntatore alla funzione preposta alla creazione di un oggetto. Può essere una normale funzione o una funzione static dell'oggetto stesso.


    Era questo il motivo per cui hai aperto il thread?
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  10. #10
    Utente di HTML.it
    Registrato dal
    Jun 2003
    Messaggi
    4,826
    perchè stendi un velo pietoso? è fatto male? non è corretto?
    Si , in parte è il motivo per cui avevo aperto il post , a me basterebbe alla fine un qualcosa che instanzia una classe derivata da quella base con la stringa , nome della classe .
    E' forse inutilmente complicato il codice nell articolo?
    CIao.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.