GENIEGenerator
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
XmlParserUtils.cxx
Go to the documentation of this file.
1 //____________________________________________________________________________
2 /*
3  Copyright (c) 2003-2024, The GENIE Collaboration
4  For the full text of the license visit http://copyright.genie-mc.org
5 
6  Costas Andreopoulos <c.andreopoulos \at cern.ch>
7  University of Liverpool
8 */
9 //____________________________________________________________________________
10 
11 #include <sstream>
12 
13 #include <TFile.h>
14 #include <TH1F.h>
15 #include <TH1D.h>
16 #include <TH2D.h>
17 #include <TVectorD.h>
18 
21 
23 #include "Framework/Utils/RunOpt.h"
24 
25 
26 using std::ostringstream;
27 
28 string genie::utils::xml::TrimSpaces(xmlChar * xmls) {
29 
30  // trim the leading/trailing spaces from an parsed xml string like in:
31  //
32  // " I am a string with lots of spaces " ---->
33  // "I am a string with lots of spaces"
34  //
35  // In this method, "\n" is treated as 'empty space' so as to trim not only
36  // empty spaces in the line that contains the string but also all leading
37  // and trailing empty lines
38 
39  string str = string( (const char *) xmls );
40  return utils::str::TrimSpaces(str);
41 }
42 
43 //_________________________________________________________________________
44 string genie::utils::xml::GetAttribute(xmlNodePtr xml_cur, string attr_name) {
45  xmlChar * xmls = xmlGetProp(xml_cur, (const xmlChar *) attr_name.c_str());
46  string str = TrimSpaces(xmls);
47  xmlFree(xmls);
48  return str;
49 }
50 
51 
52 //_________________________________________________________________________
53 string genie::utils::xml::GetXMLPathList( bool add_tune ) {
54 
55  // Get a colon separated list of potential locations for xml files
56  // e.g. ".:$MYSITEXML:/path/to/exp/version:$GALGCONF:$GENIE/config"
57  // user additions should be in $GXMLPATH
58  // All of the environment variaables have lower priority than the --xml-path command line argument
59 
60  string pathlist;
61  std::string p0 = RunOpt::Instance()->XMLPath();
62  if ( p0.size() ) { pathlist += std::string(p0) + ":" ; }
63  const char* p1 = std::getenv( "GXMLPATH" );
64  if ( p1 ) { pathlist += std::string(p1) + ":" ; }
65  const char* p2 = std::getenv( "GXMLPATHS" ); // handle extra 's'
66  if ( p2 ) { pathlist += std::string(p2) + ":" ; }
67 
68  // add originally supported alternative path
69  const char* p3 = std::getenv( "GALGCONF" );
70  if ( p3 ) { pathlist += std::string(p3) + ":" ; }
71 
72  if ( add_tune && RunOpt::Instance() -> Tune() ) {
73 
74  if ( RunOpt::Instance() -> Tune() -> IsConfigured() ) {
75 
76  if ( ! RunOpt::Instance() -> Tune() -> IsValidated() ) {
77  LOG( "XmlParser", pFATAL) << "Tune not validated" ;
78  exit(0) ;
79  }
80 
81  if ( ! RunOpt::Instance() -> Tune() -> OnlyConfiguration() )
82  pathlist += RunOpt::Instance() -> Tune() -> TuneDirectory() + ":" ;
83 
84  pathlist += RunOpt::Instance() -> Tune() -> CMCDirectory() + ':' ;
85 
86  } //tune not set in run option
87  } // requested tune and there is a tune
88 
89  pathlist += GetXMLDefaultPath() ; // standard path in case no env
90  auto GENIE_REWEIGHT = std::getenv("GENIE_REWEIGHT");
91  if (GENIE_REWEIGHT)
92  pathlist += ":" + (std::string(GENIE_REWEIGHT) + "/config");
93  pathlist += ":$GENIE/src/Tools/Flux/GNuMINtuple"; // special case
94  return pathlist;
95 }
96 
97 //_________________________________________________________________________
98 string genie::utils::xml::GetXMLFilePath(string basename) {
99  // return a full path to a real XML file
100  // e.g. passing in "GNuMIFlux.xml"
101  // will return "/blah/GENIE/HEAD/config/GNuMIFlux.xml"
102  // allow ::colon:: ::semicolon:: and ::comma:: as path item separators
103 
104  // empty basename should just be returned
105  // otherwise one will end up with a directory rather than a file
106  // as AccessPathName() isn't checking file vs. directory
107  if ( basename == "" ) return basename;
108 
109  std::string pathlist = genie::utils::xml::GetXMLPathList();
110  std::vector<std::string> paths = genie::utils::str::Split(pathlist,":;,");
111  // expand any wildcards, etc.
112  size_t np = paths.size();
113  for ( size_t i=0; i< np; ++i ) {
114  const char* tmppath = paths[i].c_str();
115  std::string onepath = gSystem->ExpandPathName(tmppath);
116  onepath += "/";
117  onepath += basename;
118  bool noAccess = gSystem->AccessPathName(onepath.c_str());
119  if ( ! noAccess ) {
120  // LOG("XmlParserUtils", pDEBUG ) << onepath ;
121  return onepath; // found one
122  }
123  }
124  // didn't find any, return basename in case it is in "." and that
125  // wasn't listed in the XML path list. If you want "." to take
126  // precedence then it needs to be explicitly listed in $GXMLPATH.
127  return basename;
128 }
129 //____________________________________________________________________________
130 xmlNodePtr genie::utils::xml::FindNode(xmlDocPtr xml_doc, string node_path)
131 {
132  xmlNodePtr root_node = xmlDocGetRootElement(xml_doc);
133  if(root_node==NULL) {
134  LOG("XML", pERROR) << "Null root XML node";
135  return NULL;
136  }
137 
138  vector<string> node_path_vec = genie::utils::str::Split(node_path,"/");
139 
140  unsigned int ndepth = node_path_vec.size();
141  unsigned int idepth = 0;
142 
143  xmlNodePtr curr_node = root_node;
144 
145  while (curr_node != NULL) {
146  if( (!xmlStrcmp(
147  curr_node->name, (const xmlChar *) node_path_vec[idepth].c_str())) )
148  {
149  idepth++;
150  if(idepth == ndepth) {
151  return curr_node;
152  } else {
153  curr_node = curr_node->xmlChildrenNode;
154  }
155  }
156  curr_node = curr_node->next;
157  }
158 
159  xmlFree(curr_node);
160  return NULL;
161 }
162 //____________________________________________________________________________
163 bool genie::utils::xml::GetBool(xmlDocPtr xml_doc, string node_path)
164 {
165  xmlNodePtr node = genie::utils::xml::FindNode(xml_doc, node_path);
166  if(node==NULL) {
167  return false;
168  }
169  string content = genie::utils::xml::TrimSpaces(
170  xmlNodeListGetString(xml_doc, node->xmlChildrenNode, 1) );
171 
172  if(content == "true" ||
173  content == "TRUE" ||
174  content == "True" ||
175  content == "on" ||
176  content == "ON" ||
177  content == "On" ||
178  content == "1" ||
179  content == "I") return true;
180 
181  if(content == "false" ||
182  content == "FALSE" ||
183  content == "False" ||
184  content == "off" ||
185  content == "OFF" ||
186  content == "Off" ||
187  content == "0" ||
188  content == "O") return false;
189 
190  LOG("XML", pERROR)
191  << "Could not interpret content (" << content
192  << ") found at node_path: " << node_path << " as a boolean!";
193  return false;
194 }
195 //____________________________________________________________________________
196 int genie::utils::xml::GetInt(xmlDocPtr xml_doc, string node_path)
197 {
198  xmlNodePtr node = genie::utils::xml::FindNode(xml_doc, node_path);
199  if(node==NULL) {
200  return -999999;
201  }
202  string content = genie::utils::xml::TrimSpaces(
203  xmlNodeListGetString(xml_doc, node->xmlChildrenNode, 1) );
204  int value = atoi(content.c_str());
205  return value;
206 }
207 //____________________________________________________________________________
208 vector<int> genie::utils::xml::GetIntArray(xmlDocPtr xml_doc, string node_path)
209 {
210  vector<int> array;
211 
212  xmlNodePtr node = genie::utils::xml::FindNode(xml_doc, node_path);
213  if(node==NULL) {
214  return array;
215  }
216 
217  string content = genie::utils::xml::TrimSpaces(
218  xmlNodeListGetString(xml_doc, node->xmlChildrenNode, 1) );
219 
220  vector<string> str_tokens = genie::utils::str::Split(content, ",");
221  vector<string>::const_iterator str_tokens_iter = str_tokens.begin();
222  for( ; str_tokens_iter != str_tokens.end(); ++str_tokens_iter) {
223  string token = genie::utils::str::TrimSpaces(*str_tokens_iter);
224  if (not token.size() ) continue;
225  array.push_back( atoi(token.c_str()) );
226  }
227  return array;
228 }
229 //____________________________________________________________________________
230 double genie::utils::xml::GetDouble(xmlDocPtr xml_doc, string node_path)
231 {
232  xmlNodePtr node = genie::utils::xml::FindNode(xml_doc, node_path);
233  if(node==NULL) {
234  return -999999;
235  }
236  string content = genie::utils::xml::TrimSpaces(
237  xmlNodeListGetString(xml_doc, node->xmlChildrenNode, 1) );
238  double value = atof(content.c_str());
239  return value;
240 }
241 //____________________________________________________________________________
242 vector<double>
243  genie::utils::xml::GetDoubleArray(xmlDocPtr xml_doc, string node_path)
244 {
245  vector<double> array;
246 
247  xmlNodePtr node = genie::utils::xml::FindNode(xml_doc, node_path);
248  if(node==NULL) {
249  return array;
250  }
251 
252  string content = genie::utils::xml::TrimSpaces(
253  xmlNodeListGetString(xml_doc, node->xmlChildrenNode, 1) );
254 
255  vector<string> str_tokens = genie::utils::str::Split(content, ",");
256  vector<string>::const_iterator str_tokens_iter = str_tokens.begin();
257  for( ; str_tokens_iter != str_tokens.end(); ++str_tokens_iter) {
258  string token = genie::utils::str::TrimSpaces(*str_tokens_iter);
259  if (not token.size() ) continue;
260  array.push_back( atof(token.c_str()) );
261  }
262  return array;
263 }
264 //____________________________________________________________________________
265 string genie::utils::xml::GetString(xmlDocPtr xml_doc, string node_path)
266 {
267  xmlNodePtr node = genie::utils::xml::FindNode(xml_doc, node_path);
268  if(node==NULL) {
269  return "";
270  }
271  string content = genie::utils::xml::TrimSpaces(
272  xmlNodeListGetString(xml_doc, node->xmlChildrenNode, 1) );
273  return content;
274 }
275 //____________________________________________________________________________
276 string genie::utils::xml::GetROOTFileName(xmlDocPtr xml_doc, string node_path)
277 {
278  return genie::utils::xml::GetString(xml_doc, node_path+"/filename");
279 }
280 //____________________________________________________________________________
281 string genie::utils::xml::GetROOTObjName (xmlDocPtr xml_doc, string node_path)
282 {
283  return genie::utils::xml::GetString(xml_doc, node_path+"/objname");
284 }
285 //____________________________________________________________________________
286 string genie::utils::xml::GetROOTObjType (xmlDocPtr xml_doc, string node_path)
287 {
288  return genie::utils::xml::GetString(xml_doc, node_path+"/objtype");
289 }
290 //____________________________________________________________________________
292  xmlDocPtr xml_doc, string node_path, string base_dir)
293 {
294  LOG("XML", pINFO) << "Reading info at XML node node_path: " << node_path;
295 
296  string filename = genie::utils::xml::GetROOTFileName(xml_doc,node_path);
297 
298  string used_base_dir = base_dir;
299  if(base_dir.find("<env>") != string::npos) {
300  used_base_dir = gSystem->Getenv("GENIE");
301  }
302 
303  const char * full_filename =
304  Form("%s/%s", used_base_dir.c_str(), filename.c_str());
305  TFile * file = new TFile(full_filename,"read");
306  if(!file) {
307  LOG("XML",pERROR) << "No file: " << full_filename << " found";
308  return 0;
309  }
310  if(file->IsZombie()) {
311  LOG("XML",pERROR) << "File is a zombie: " << full_filename;
312  return 0;
313  }
314 
315  return file;
316 }
317 //____________________________________________________________________________
319  xmlDocPtr xml_doc, string node_path, string base_dir)
320 {
321  TFile * file = genie::utils::xml::GetTFile(xml_doc,node_path,base_dir);
322  if(!file) return 0;
323 
324  string objname = genie::utils::xml::GetROOTObjName(xml_doc,node_path);
325  TH1F * h = (TH1F*)file->Get(objname.c_str());
326  if(!h) {
327  LOG("XML",pERROR) << "No " << objname;
328  file->Close();
329  delete file;
330  return 0;
331  }
332 
333  TH1F * hcopy = new TH1F(*h);
334  hcopy->SetDirectory(0);
335  file->Close();
336  delete file;
337 
338  return hcopy;
339 }
340 //____________________________________________________________________________
342  xmlDocPtr xml_doc, string node_path, string base_dir)
343 {
344  TFile * file = genie::utils::xml::GetTFile(xml_doc,node_path,base_dir);
345  if(!file) return 0;
346 
347  string objname = genie::utils::xml::GetROOTObjName(xml_doc,node_path);
348  TH1D * h = (TH1D*)file->Get(objname.c_str());
349  if(!h) {
350  LOG("XML",pERROR) << "No " << objname;
351  file->Close();
352  delete file;
353  return 0;
354  }
355 
356  TH1D * hcopy = new TH1D(*h);
357  hcopy->SetDirectory(0);
358  file->Close();
359  delete file;
360 
361  return hcopy;
362 }
363 //____________________________________________________________________________
365  xmlDocPtr xml_doc, string node_path, string base_dir)
366 {
367  TFile * file = genie::utils::xml::GetTFile(xml_doc,node_path,base_dir);
368  if(!file) return 0;
369 
370  string objname = genie::utils::xml::GetROOTObjName(xml_doc,node_path);
371  TH2D * h = (TH2D*)file->Get(objname.c_str());
372  if(!h) {
373  LOG("XML",pERROR) << "No " << objname;
374  file->Close();
375  delete file;
376  return 0;
377  }
378 
379  TH2D * hcopy = new TH2D(*h);
380  hcopy->SetDirectory(0);
381  file->Close();
382  delete file;
383 
384  return hcopy;
385 }
386 //____________________________________________________________________________
388  xmlDocPtr xml_doc, string node_path, string base_dir)
389 {
390  TFile * file = genie::utils::xml::GetTFile(xml_doc,node_path,base_dir);
391  if(!file) return 0;
392 
393  string objname = genie::utils::xml::GetROOTObjName(xml_doc,node_path);
394  TVectorD * vec = (TVectorD*)file->Get(objname.c_str());
395  if(!vec) {
396  LOG("XML",pERROR) << "No " << objname;
397  file->Close();
398  delete file;
399  return 0;
400  }
401 
402  TVectorD * veccopy = new TVectorD(*vec);
403  file->Close();
404  delete file;
405 
406  return veccopy;
407 }
408 //____________________________________________________________________________
409 /*
410 TMatrixDSym * genie::utils::xml::GetTMatrixDSym(
411  xmlDocPtr xml_doc, string node_path, string base_dir)
412 {
413  return 0;
414 }
415 //____________________________________________________________________________
416 TMatrixD * genie::utils::xml::GetTMatrixD(
417  xmlDocPtr xml_doc, string node_path, string base_dir)
418 {
419  return 0;
420 }
421 //____________________________________________________________________________
422 TSpline3 * genie::utils::xml::GetTSpline3(
423  xmlDocPtr xml_doc, string node_path, string base_dir)
424 {
425  return 0;
426 }
427 //____________________________________________________________________________
428 */
string GetXMLPathList(bool add_tune=true)
string GetROOTObjName(xmlDocPtr xml_doc, string node_path)
#define pERROR
Definition: Messenger.h:59
string TrimSpaces(xmlChar *xmls)
#define pFATAL
Definition: Messenger.h:56
xmlNodePtr FindNode(xmlDocPtr xml_doc, string node_path)
TH1D * GetTH1D(xmlDocPtr xml_doc, string node_path, string base_dir="<env>")
string GetROOTFileName(xmlDocPtr xml_doc, string node_path)
#define LOG(stream, priority)
A macro that returns the requested log4cpp::Category appending a string (using the FILE...
Definition: Messenger.h:96
TH1F * GetTH1F(xmlDocPtr xml_doc, string node_path, string base_dir="<env>")
string GetXMLFilePath(string basename)
#define pINFO
Definition: Messenger.h:62
string GetROOTObjType(xmlDocPtr xml_doc, string node_path)
TFile * GetTFile(xmlDocPtr xml_doc, string node_path, string base_dir="<env>")
vector< double > GetDoubleArray(xmlDocPtr xml_doc, string node_path)
string TrimSpaces(string input)
Definition: StringUtils.cxx:18
vector< string > Split(string input, string delim)
Definition: StringUtils.cxx:36
string GetString(xmlDocPtr xml_doc, string node_path)
int GetInt(xmlDocPtr xml_doc, string node_path)
vector< int > GetIntArray(xmlDocPtr xml_doc, string node_path)
string GetXMLDefaultPath()
bool GetBool(xmlDocPtr xml_doc, string node_path)
string GetAttribute(xmlNodePtr xml_cur, string attr_name)
double GetDouble(xmlDocPtr xml_doc, string node_path)
TH2D * GetTH2D(xmlDocPtr xml_doc, string node_path, string base_dir="<env>")
TVectorD * GetTVectorD(xmlDocPtr xml_doc, string node_path, string base_dir="<env>")