XmlParserUtils.cxx
Go to the documentation of this file.
1 //____________________________________________________________________________
2 /*
3  Copyright (c) 2003-2020, The GENIE Collaboration
4  For the full text of the license visit http://copyright.genie-mc.org
5 
6  Costas Andreopoulos <constantinos.andreopoulos \at cern.ch>
7  University of Liverpool & STFC Rutherford Appleton Laboratory
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  pathlist += ":$GENIE/src/Tools/Flux/GNuMINtuple"; // special case
91 
92  return pathlist;
93 }
94 
95 //_________________________________________________________________________
97  // return a full path to a real XML file
98  // e.g. passing in "GNuMIFlux.xml"
99  // will return "/blah/GENIE/HEAD/config/GNuMIFlux.xml"
100  // allow ::colon:: ::semicolon:: and ::comma:: as path item separators
101 
102  // empty basename should just be returned
103  // otherwise one will end up with a directory rather than a file
104  // as AccessPathName() isn't checking file vs. directory
105  if ( basename == "" ) return basename;
106 
108  std::vector<std::string> paths = genie::utils::str::Split(pathlist,":;,");
109  // expand any wildcards, etc.
110  size_t np = paths.size();
111  for ( size_t i=0; i< np; ++i ) {
112  const char* tmppath = paths[i].c_str();
113  std::string onepath = gSystem->ExpandPathName(tmppath);
114  onepath += "/";
115  onepath += basename;
116  bool noAccess = gSystem->AccessPathName(onepath.c_str());
117  if ( ! noAccess ) {
118  // LOG("XmlParserUtils", pDEBUG ) << onepath ;
119  return onepath; // found one
120  }
121  }
122  // didn't find any, return basename in case it is in "." and that
123  // wasn't listed in the XML path list. If you want "." to take
124  // precedence then it needs to be explicitly listed in $GXMLPATH.
125  return basename;
126 }
127 //____________________________________________________________________________
128 xmlNodePtr genie::utils::xml::FindNode(xmlDocPtr xml_doc, string node_path)
129 {
130  xmlNodePtr root_node = xmlDocGetRootElement(xml_doc);
131  if(root_node==NULL) {
132  LOG("XML", pERROR) << "Null root XML node";
133  return NULL;
134  }
135 
136  vector<string> node_path_vec = genie::utils::str::Split(node_path,"/");
137 
138  unsigned int ndepth = node_path_vec.size();
139  unsigned int idepth = 0;
140 
141  xmlNodePtr curr_node = root_node;
142 
143  while (curr_node != NULL) {
144  if( (!xmlStrcmp(
145  curr_node->name, (const xmlChar *) node_path_vec[idepth].c_str())) )
146  {
147  idepth++;
148  if(idepth == ndepth) {
149  return curr_node;
150  } else {
151  curr_node = curr_node->xmlChildrenNode;
152  }
153  }
154  curr_node = curr_node->next;
155  }
156 
157  xmlFree(curr_node);
158  return NULL;
159 }
160 //____________________________________________________________________________
161 bool genie::utils::xml::GetBool(xmlDocPtr xml_doc, string node_path)
162 {
163  xmlNodePtr node = genie::utils::xml::FindNode(xml_doc, node_path);
164  if(node==NULL) {
165  return false;
166  }
167  string content = genie::utils::xml::TrimSpaces(
168  xmlNodeListGetString(xml_doc, node->xmlChildrenNode, 1) );
169 
170  if(content == "true" ||
171  content == "TRUE" ||
172  content == "True" ||
173  content == "on" ||
174  content == "ON" ||
175  content == "On" ||
176  content == "1" ||
177  content == "I") return true;
178 
179  if(content == "false" ||
180  content == "FALSE" ||
181  content == "False" ||
182  content == "off" ||
183  content == "OFF" ||
184  content == "Off" ||
185  content == "0" ||
186  content == "O") return false;
187 
188  LOG("XML", pERROR)
189  << "Could not interpret content (" << content
190  << ") found at node_path: " << node_path << " as a boolean!";
191  return false;
192 }
193 //____________________________________________________________________________
194 int genie::utils::xml::GetInt(xmlDocPtr xml_doc, string node_path)
195 {
196  xmlNodePtr node = genie::utils::xml::FindNode(xml_doc, node_path);
197  if(node==NULL) {
198  return -999999;
199  }
200  string content = genie::utils::xml::TrimSpaces(
201  xmlNodeListGetString(xml_doc, node->xmlChildrenNode, 1) );
202  int value = atoi(content.c_str());
203  return value;
204 }
205 //____________________________________________________________________________
206 vector<int> genie::utils::xml::GetIntArray(xmlDocPtr xml_doc, string node_path)
207 {
209 
210  xmlNodePtr node = genie::utils::xml::FindNode(xml_doc, node_path);
211  if(node==NULL) {
212  return array;
213  }
214 
215  string content = genie::utils::xml::TrimSpaces(
216  xmlNodeListGetString(xml_doc, node->xmlChildrenNode, 1) );
217 
218  vector<string> str_tokens = genie::utils::str::Split(content, ",");
219  vector<string>::const_iterator str_tokens_iter = str_tokens.begin();
220  for( ; str_tokens_iter != str_tokens.end(); ++str_tokens_iter) {
221  string token = genie::utils::str::TrimSpaces(*str_tokens_iter);
222  if (not token.size() ) continue;
223  array.push_back( atoi(token.c_str()) );
224  }
225  return array;
226 }
227 //____________________________________________________________________________
228 double genie::utils::xml::GetDouble(xmlDocPtr xml_doc, string node_path)
229 {
230  xmlNodePtr node = genie::utils::xml::FindNode(xml_doc, node_path);
231  if(node==NULL) {
232  return -999999;
233  }
234  string content = genie::utils::xml::TrimSpaces(
235  xmlNodeListGetString(xml_doc, node->xmlChildrenNode, 1) );
236  double value = atof(content.c_str());
237  return value;
238 }
239 //____________________________________________________________________________
241  genie::utils::xml::GetDoubleArray(xmlDocPtr xml_doc, string node_path)
242 {
244 
245  xmlNodePtr node = genie::utils::xml::FindNode(xml_doc, node_path);
246  if(node==NULL) {
247  return array;
248  }
249 
250  string content = genie::utils::xml::TrimSpaces(
251  xmlNodeListGetString(xml_doc, node->xmlChildrenNode, 1) );
252 
253  vector<string> str_tokens = genie::utils::str::Split(content, ",");
254  vector<string>::const_iterator str_tokens_iter = str_tokens.begin();
255  for( ; str_tokens_iter != str_tokens.end(); ++str_tokens_iter) {
256  string token = genie::utils::str::TrimSpaces(*str_tokens_iter);
257  if (not token.size() ) continue;
258  array.push_back( atof(token.c_str()) );
259  }
260  return array;
261 }
262 //____________________________________________________________________________
263 string genie::utils::xml::GetString(xmlDocPtr xml_doc, string node_path)
264 {
265  xmlNodePtr node = genie::utils::xml::FindNode(xml_doc, node_path);
266  if(node==NULL) {
267  return "";
268  }
269  string content = genie::utils::xml::TrimSpaces(
270  xmlNodeListGetString(xml_doc, node->xmlChildrenNode, 1) );
271  return content;
272 }
273 //____________________________________________________________________________
274 string genie::utils::xml::GetROOTFileName(xmlDocPtr xml_doc, string node_path)
275 {
276  return genie::utils::xml::GetString(xml_doc, node_path+"/filename");
277 }
278 //____________________________________________________________________________
279 string genie::utils::xml::GetROOTObjName (xmlDocPtr xml_doc, string node_path)
280 {
281  return genie::utils::xml::GetString(xml_doc, node_path+"/objname");
282 }
283 //____________________________________________________________________________
284 string genie::utils::xml::GetROOTObjType (xmlDocPtr xml_doc, string node_path)
285 {
286  return genie::utils::xml::GetString(xml_doc, node_path+"/objtype");
287 }
288 //____________________________________________________________________________
290  xmlDocPtr xml_doc, string node_path, string base_dir)
291 {
292  LOG("XML", pINFO) << "Reading info at XML node node_path: " << node_path;
293 
294  string filename = genie::utils::xml::GetROOTFileName(xml_doc,node_path);
295 
296  string used_base_dir = base_dir;
297  if(base_dir.find("<env>") != string::npos) {
298  used_base_dir = gSystem->Getenv("GENIE");
299  }
300 
301  const char * full_filename =
302  Form("%s/%s", used_base_dir.c_str(), filename.c_str());
303  TFile * file = new TFile(full_filename,"read");
304  if(!file) {
305  LOG("XML",pERROR) << "No file: " << full_filename << " found";
306  return 0;
307  }
308  if(file->IsZombie()) {
309  LOG("XML",pERROR) << "File is a zombie: " << full_filename;
310  return 0;
311  }
312 
313  return file;
314 }
315 //____________________________________________________________________________
317  xmlDocPtr xml_doc, string node_path, string base_dir)
318 {
319  TFile * file = genie::utils::xml::GetTFile(xml_doc,node_path,base_dir);
320  if(!file) return 0;
321 
322  string objname = genie::utils::xml::GetROOTObjName(xml_doc,node_path);
323  TH1F * h = (TH1F*)file->Get(objname.c_str());
324  if(!h) {
325  LOG("XML",pERROR) << "No " << objname;
326  file->Close();
327  delete file;
328  return 0;
329  }
330 
331  TH1F * hcopy = new TH1F(*h);
332  hcopy->SetDirectory(0);
333  file->Close();
334  delete file;
335 
336  return hcopy;
337 }
338 //____________________________________________________________________________
340  xmlDocPtr xml_doc, string node_path, string base_dir)
341 {
342  TFile * file = genie::utils::xml::GetTFile(xml_doc,node_path,base_dir);
343  if(!file) return 0;
344 
345  string objname = genie::utils::xml::GetROOTObjName(xml_doc,node_path);
346  TH1D * h = (TH1D*)file->Get(objname.c_str());
347  if(!h) {
348  LOG("XML",pERROR) << "No " << objname;
349  file->Close();
350  delete file;
351  return 0;
352  }
353 
354  TH1D * hcopy = new TH1D(*h);
355  hcopy->SetDirectory(0);
356  file->Close();
357  delete file;
358 
359  return hcopy;
360 }
361 //____________________________________________________________________________
363  xmlDocPtr xml_doc, string node_path, string base_dir)
364 {
365  TFile * file = genie::utils::xml::GetTFile(xml_doc,node_path,base_dir);
366  if(!file) return 0;
367 
368  string objname = genie::utils::xml::GetROOTObjName(xml_doc,node_path);
369  TH2D * h = (TH2D*)file->Get(objname.c_str());
370  if(!h) {
371  LOG("XML",pERROR) << "No " << objname;
372  file->Close();
373  delete file;
374  return 0;
375  }
376 
377  TH2D * hcopy = new TH2D(*h);
378  hcopy->SetDirectory(0);
379  file->Close();
380  delete file;
381 
382  return hcopy;
383 }
384 //____________________________________________________________________________
386  xmlDocPtr xml_doc, string node_path, string base_dir)
387 {
388  TFile * file = genie::utils::xml::GetTFile(xml_doc,node_path,base_dir);
389  if(!file) return 0;
390 
391  string objname = genie::utils::xml::GetROOTObjName(xml_doc,node_path);
392  TVectorD * vec = (TVectorD*)file->Get(objname.c_str());
393  if(!vec) {
394  LOG("XML",pERROR) << "No " << objname;
395  file->Close();
396  delete file;
397  return 0;
398  }
399 
400  TVectorD * veccopy = new TVectorD(*vec);
401  file->Close();
402  delete file;
403 
404  return veccopy;
405 }
406 //____________________________________________________________________________
407 /*
408 TMatrixDSym * genie::utils::xml::GetTMatrixDSym(
409  xmlDocPtr xml_doc, string node_path, string base_dir)
410 {
411  return 0;
412 }
413 //____________________________________________________________________________
414 TMatrixD * genie::utils::xml::GetTMatrixD(
415  xmlDocPtr xml_doc, string node_path, string base_dir)
416 {
417  return 0;
418 }
419 //____________________________________________________________________________
420 TSpline3 * genie::utils::xml::GetTSpline3(
421  xmlDocPtr xml_doc, string node_path, string base_dir)
422 {
423  return 0;
424 }
425 //____________________________________________________________________________
426 */
string GetXMLPathList(bool add_tune=true)
string GetROOTObjName(xmlDocPtr xml_doc, string node_path)
#define pERROR
Definition: Messenger.h:59
std::string string
Definition: nybbler.cc:12
string TrimSpaces(xmlChar *xmls)
#define pFATAL
Definition: Messenger.h:56
xmlNodePtr FindNode(xmlDocPtr xml_doc, string node_path)
intermediate_table::const_iterator const_iterator
string filename
Definition: train.py:213
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
std::string getenv(std::string const &name)
Definition: getenv.cc:15
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
auto array(Array const &a)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:228
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)
static QCString str
TH2D * GetTH2D(xmlDocPtr xml_doc, string node_path, string base_dir="<env>")
TVectorD * GetTVectorD(xmlDocPtr xml_doc, string node_path, string base_dir="<env>")