PDA

Visualizza la versione completa : [c++]caricamento dati


giuseppe500
26-11-2009, 15:49
Ciao.
devo leggere un formato di dati con una stessa logica di lettura da un xml e da un file di testo.
Ad es:
riga file di testo:


#21=IFCARBITRARYCLOSEDPROFILEDEF(.AREA.,$,#23);


xml


<IfcArbitraryClosedProfileDef id="21">
<ProfileType>area</ProfileType>
<OuterCurve>
<IfcPolyline xsi:nil="true" ref="23"/>
</OuterCurve>
</IfcArbitraryClosedProfileDef>


il ref 23:


#23=IFCPOLYLINE((#41,#42,#43,#44,#45,#46,#47,#48,# 49,#50,#51,#52,#41));
[code]
e xml:
[code]
<IfcPolyline id="23">
<Points ex:cType="list">
<IfcCartesianPoint pos="0" xsi:nil="true" ref="41"/>
<IfcCartesianPoint pos="1" xsi:nil="true" ref="42"/>
<IfcCartesianPoint pos="2" xsi:nil="true" ref="43"/>
<IfcCartesianPoint pos="3" xsi:nil="true" ref="44"/>
<IfcCartesianPoint pos="4" xsi:nil="true" ref="45"/>
<IfcCartesianPoint pos="5" xsi:nil="true" ref="46"/>
<IfcCartesianPoint pos="6" xsi:nil="true" ref="47"/>
<IfcCartesianPoint pos="7" xsi:nil="true" ref="48"/>
<IfcCartesianPoint pos="8" xsi:nil="true" ref="49"/>
<IfcCartesianPoint pos="9" xsi:nil="true" ref="50"/>
<IfcCartesianPoint pos="10" xsi:nil="true" ref="51"/>
<IfcCartesianPoint pos="11" xsi:nil="true" ref="52"/>
<IfcCartesianPoint pos="12" xsi:nil="true" ref="41"/>
</Points>
</IfcPolyline>


alla fine voglio trovare una serie di dati con i valori dei IfcCartesianPoint che sono circa cosi:
x 2 coordinate
txt


#41=IFCCARTESIANPOINT((-152.4,-63.5));

xml


<IfcCartesianPoint id="i87">
<Coordinates ex:cType="list">
<IfcLengthMeasure pos="0">0.</IfcLengthMeasure>
<IfcLengthMeasure pos="1">0.</IfcLengthMeasure>
</Coordinates>
</IfcCartesianPoint>


mentre leggo l'xml tag per tag o il file di testo riga per riga instanzio delle classi corrispondenti al tipo di nodo o di testo(#41=IFCCARTESIANPOINT ((-152.4,-63.5))o <ifccartesianpoint></ ec.... ;e popolo questa classe, alla fine le metto in una mappa di riferimenti popolati e eseguo la logica dell applicativo che è uguale per tutti e due i formati e che ho gia fatto ma non voglio pubblicare qui perchè è relativamente importante ai fini del post.
Ecco vorrei utilizzare il polimorfismo o i function object (come shodan mi ha insegnato e che forse qui possono tornare utili)per popolare le classi in modo differente se sono in un file di testo o in un xml , mantenendo la logica dell applicazione in una classe comune CLogica uguale.
quello che ho pensato è di considerare la posizione nella riga di testo per i valori , ad es :
1)leggere nome IFCARBITRARYCLOSEDPROFILEDEF e instanziare classe corrispondente
2)dopo alla posizione 2 leggere tipo profilo(area nel caso)
3)alla posizione 4 risolvere riferimento 23(nel caso):



#21=IFCARBITRARYCLOSEDPROFILEDEF(.AREA.,$,#23);


queste "posizioni" mi sembrano uguali a quelle dei tag xml:


1)<IfcArbitraryClosedProfileDef id="21">
2) <ProfileType>area</ProfileType>
<OuterCurve>
4) <IfcPolyline xsi:nil="true" ref="23"/>
</OuterCurve>
</IfcArbitraryClosedProfileDef>


ma mi sembra un metodo poco sicuro , dato che questa corrispondenza non è specificata.
consigli ?
grazie in anticipo.

giuseppe500
26-11-2009, 16:27
io pensavo una cosa del genere:


static enum StringValue { evNotDefined,
evIfcArbitraryClosedProfileDef,
evProfileType,
evIfcPolyline,
};


static std::map<std::string, StringValue> s_mapStringValuesXml;
static std::map<int, StringValue> s_mapStringValuesTxt;


e un inizializzazione :


//Se sono in xml
s_mapStringValuesXml["IfcArbitraryClosedProfileDef"] = evIfcArbitraryClosedProfileDef;
s_mapStringValuesXml["ProfileType"] = evProfileType;
s_mapStringValuesXml["IfcPolyline"] = evIfcPolyline;

//se sono in txt:
s_mapStringValuesTxt[1] = evIfcArbitraryClosedProfileDef;
s_mapStringValuesTxt[2] = evProfileType;
s_mapStringValuesTxt[3] = evIfcPolyline;


per poi poter fare:


string strInput....
switch(s_mapStringValues[strInput])
{
case evStringValue1:
cout << 1;
break;
case evStringValue2:
cout << 2;
break;
case evStringValue3:
cout << 3;
break;


o in txt:


int pos....
switch(s_mapStringValues[pos])
{
case evStringValue1:
cout << 1;
break;
case evStringValue2:
cout << 2;
break;
case evStringValue3:
cout << 3;
break;



ma vorrei renderla generica per vari supporti (per es aggiungere gestione campi di un db)
ad es utilizzando un template e quello che non riuesco a capire , penso si chiami specializzazione , ecco forse creando un function object tramite template che si differenzia a secondo del tipo posso risolvere.
E' forse troppo cervellotico?

Loading