Loading a XML file of a customized class

Hi ROOTers
I am trying to write my own classes into XML files. I was successful at this using the following script and using TObjects:

{
  TFile *file = TFile::Open("demo.xml","recreate");
  
  TH1F *h = new TH1F("hwoow","test",1000,-2,2);
  h->FillRandom("gaus");
  //h->Write();
  file->WriteObject(h,"h9585");
  file->Close();



  file=TFile::Open("demo.xml");  
  if(!file->IsZombie()){
    TH1F *h2=(TH1F*)  file->Get("h9585");

    cout << "Test session started ******************************" << endl;
    cout << "Name   : " << h2->GetName() << endl;
    cout << "Npars  : " << h2->GetNdivisions() << endl;
    file->Close();
}

I got the following output running this last script:

Now I want to do this same operation using my own class. So far, I have been able to generate the XML file (see attachment:calib.xml). However I am having problems reading the XML file. I do not know yet where is my mistake, what I am missing. So far, my classes do not derive from the TObject class. This could change if needed.

My class structure looks like this

CMName.h CMBackGroundObj.h CMSingletObj.h TPeakFitter.h CMMasterCalibObj.h

The relation between them is the following

CMBackGroundObj.h inherits from CMName.h
CMSingletObj.h inherits from CMName.h
TPeakFitter.h inherits from CMName.h
and it contains a vector<CMBackGroundObj*> and a vector<CMSingletObj*>

CMMasterCalibObj.h contains a vector<TPeakFitter*>

Now each include header file has the ClassDef(class_name,1) macro and
each source file has the ClassImp(class_name) macro.

My linkDef.h looks like this

My question is, reading from ROOT docs, do I need to generate my own streamers or is it enough to generate the root dictionary code?

Another question is that my vector<> member objects are private. Would that be a problem for the ROOT streamers? I like to think it is not a problem since I was able to generate an XML file from my CMMasterCalibObj class.

When I try to read my XML file of my custom class using the following partial code:


//Previously define in  header file

 vector<CMMasterCalibObj*> UsrCalibVector;
//...
//...
//...

//NOW the code


    //SECOND STEP: Get Pointer to calibObj
  int intPReqID=-1;
  CMMasterCalibObj *selectedCal;
    vector<CMMasterCalibObj*>::iterator it = UsrCalibVector.begin();
    bool bFound=false;
    while(it!=UsrCalibVector.end() && !bFound){
      if((*it)->GetCalibID()==intPReqID){
	selectedCal = (*it);
	bFound=true;
      }
    }

    //THIRD STEP: Save as a XML file
    TFile *fOut = TFile::Open("calib.xml","recreate");
    fOut->WriteObjectAny(selectedCal,"CMMasterCalibObj","mySelCalib");
    fOut->Close();



 

    //FOURTH STEP: Test by opening XML file
  TFile *fileRead = TFile::Open("calib.xml");
  if(!fileRead->IsZombie()){
    selectedCal=(CMMasterCalibObj*)fileRead->Get("mySelCalib");

    cout << "Name of calibration: " << selectedCal->GetName() << endl;
    cout << "Number of calibration points: " << selectedCal->CountCalPeaks() << endl;
    cout << selectedCal->PrintResults();
    fileRead->Close();
  }
  else
    cout << "Error opening XML" << endl;

I get the following output:

Hmmm… any suggestions?

I was able to go around my problem using .root files instead of .xml

Now I am confident that the streamers are available for my classes despite they do not derive from the TObject.
It would be neat to make it work saving files under xml format. Using gdb, my problem resides in the line

selectedCal=(CMMasterCalibObj*)fileRead->Get("mySelCalib");

where the operation fails to assign memory to the pointer. Hence I get a seg fault when I try to call myClass::GetName(). Again, this is not a problem if I work with “.root” files.

Anything I could do to trace the problem? Maybe I hit the limitations of the XML class in ROOT?

[quote]My question is, reading from ROOT docs, do I need to generate my own streamers or is it enough to generate the root dictionary code? [/quote]Yes it is enough, you would only need to write your own streamer in rare cases (and you would have to be very careful in writing it to stay compatible with XML).

[quote]Another question is that my vector<> member objects are private. Would that be a problem for the ROOT streamers? I like to think it is not a problem since I was able to generate an XML file from my CMMasterCalibObj class[/quote]. That’s correct, ROOT has no problem with the data members being private.

Philippe.

Hi,

Can you send me a complete running example showing this problem?

Thanks,
Philippe.

Thxs for answering my questions. I have not been able to put together the idea of streamers yet since I have not read the relevant chapters all together but I just keep reading pieces here and there…

So far for my XML code, I will try to solve the problem if I have a chance on the weekend. I am afraid it will not be straight forward to generate a small simple example with the current problem. On the other hand, I am writing .root files instead and it is working as a charm…

Cheers,

[quote]I am writing .root files instead and it is working as a charm… [/quote]And of course we strongly recommend .root file as they are much more efficient in time (to read and write) and space (on disk).

Cheers,
Philippe.