QMCPACK
Libxml2Doc.cpp
Go to the documentation of this file.
1 //////////////////////////////////////////////////////////////////////////////////////
2 // This file is distributed under the University of Illinois/NCSA Open Source License.
3 // See LICENSE file in top directory for details.
4 //
5 // Copyright (c) 2016 Jeongnim Kim and QMCPACK developers.
6 //
7 // File developed by: Jeremy McMinnis, jmcminis@gmail.com, University of Illinois at Urbana-Champaign
8 // Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
9 // Raymond Clay III, j.k.rofling@gmail.com, Lawrence Livermore National Laboratory
10 // Jaron T. Krogel, krogeljt@ornl.gov, Oak Ridge National Laboratory
11 // Mark A. Berrill, berrillma@ornl.gov, Oak Ridge National Laboratory
12 // Mark Dewing, markdewing@gmail.com, University of Illinois at Urbana-Champaign
13 //
14 // File created by: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
15 //////////////////////////////////////////////////////////////////////////////////////
16 
17 
18 #include "Libxml2Doc.h"
19 #include "Utilities/Timer.h"
20 #include <array>
21 #include <fstream>
22 #include <iostream>
23 
24 OhmmsXPathObject::OhmmsXPathObject() : NumObjects(0), result(NULL), m_context(NULL) {}
25 
26 OhmmsXPathObject::OhmmsXPathObject(const char* expression, xmlXPathContextPtr context)
27  : NumObjects(0), result(NULL), m_context(NULL)
28 {
29  put(expression, context);
30 }
31 
32 OhmmsXPathObject::OhmmsXPathObject(const char* expression, xmlNodePtr cur)
33  : NumObjects(0), result(NULL), m_context(NULL)
34 {
35  m_context = xmlXPathNewContext(cur->doc);
36  m_context->node = cur;
37 
38  if (expression[0] == '.')
39  {
40  put(expression, m_context);
41  }
42  else
43  {
44  std::array<char, 128> local;
45  if (std::snprintf(local.data(), local.size(), ".%s", expression) < 0)
46  throw std::runtime_error("Error generating expression");
47  put(local.data(), m_context);
48  }
49 }
50 
52 {
53  if (result != NULL)
54  {
55  xmlXPathFreeObject(result);
56  }
57 
58  if (m_context != NULL)
59  {
60  xmlXPathFreeContext(m_context);
61  }
62 }
63 
64 void OhmmsXPathObject::put(const char* expression, xmlXPathContextPtr context)
65 {
66  //free the object if it has been used before
67  if (result != NULL)
68  xmlXPathFreeObject(result);
69  result = xmlXPathEvalExpression((const xmlChar*)expression, context);
70  if (xmlXPathNodeSetIsEmpty(result->nodesetval))
71  {
72  NumObjects = 0;
73  }
74  else
75  {
76  NumObjects = result->nodesetval->nodeNr;
77  }
78 }
79 
80 
81 Libxml2Document::Libxml2Document() : m_doc(NULL), m_root(NULL), m_context(NULL) {}
82 
83 Libxml2Document::Libxml2Document(const std::string& xmlfile) : m_doc(NULL), m_root(NULL), m_context(NULL) { parse(xmlfile); }
84 
86 {
87  if (m_context != NULL)
88  xmlXPathFreeContext(m_context);
89  if (m_doc != NULL)
90  xmlFreeDoc(m_doc);
91 }
92 
93 void Libxml2Document::newDoc(const std::string& rootName)
94 {
95  m_doc = xmlNewDoc(BAD_CAST "1.0");
96  m_root = xmlNewNode(NULL, BAD_CAST rootName.c_str());
97  xmlDocSetRootElement(m_doc, m_root);
98 }
99 
101 {
102  if (m_context == NULL && m_doc != NULL)
103  {
104  m_context = xmlXPathNewContext(m_doc);
105  }
106  return m_context;
107 }
108 
109 void Libxml2Document::dump(const std::string& newxml) { xmlSaveFormatFile(newxml.c_str(), m_doc, 1); }
110 
111 void Libxml2Document::addChild(xmlNodePtr newnode)
112 {
113  xmlKeepBlanksDefault(1);
114  xmlAddChild(m_root, newnode);
115 }
116 
117 void Libxml2Document::addChild(const std::string& expression, xmlNodePtr newnode)
118 {
119  xmlXPathContextPtr acontext = getXPathContext();
120  OhmmsXPathObject res(expression.c_str(), acontext);
121  if (res.size())
122  {
123  xmlAddChild(res[0], newnode);
124  }
125 }
126 
127 xmlNodePtr Libxml2Document::addChild(xmlNodePtr parent, const std::string& nodeName)
128 {
129  xmlNodePtr node = xmlNewChild(parent, NULL, BAD_CAST nodeName.c_str(), NULL);
130  return node;
131 }
132 
133 
134 #if defined(HAVE_MPI2)
135 /** this parse function uses MPI_Bcast but is not used for the moment */
136 bool Libxml2Document::parse(const std::string& xmlfile)
137 {
138  if (m_doc != NULL)
139  xmlFreeDoc(m_doc);
140  qmcplusplus::Timer aClock;
141  int length = 0;
142  std::string buffer;
143  aClock.restart();
144  if (OHMMS::Controller->master())
145  {
146  std::ifstream is(xmlfile.c_str());
147  // get length of file:
148  is.seekg(0, std::ios::end);
149  length = is.tellg();
150  is.seekg(0, std::ios::beg);
151  // allocate memory:
152  buffer.resize(length);
153  // read data as a block:
154  is.read(buffer.data(), length);
155  is.close();
156  }
157  MPI_Bcast(&length, 1, MPI_INT, 0, OHMMS::Controller->getID());
159  if (!(OHMMS::Controller->master()))
160  {
161  buffer.resize(length);
162  }
163  MPI_Bcast(buffer.data(), length, MPI_CHAR, 0, OHMMS::Controller->getID());
164  m_doc = xmlParseMemory(buffer.data(), length);
165  buffer.clear();
166  qmcplusplus::app_log() << " Parsing " << xmlfile << " : " << aClock.elapsed() << " seconds " << std::endl;
167  if (m_doc == NULL)
168  {
169  return false;
170  }
171  m_root = xmlDocGetRootElement(m_doc);
172  if (m_root == NULL)
173  {
174  return false;
175  }
176  InFileRoot = std::string(xmlfile, 0, xmlfile.size() - 4);
177  return true;
178 }
179 #else
180 bool Libxml2Document::parse(const std::string& xmlfile)
181 {
182  if (m_doc != NULL)
183  xmlFreeDoc(m_doc);
184 
185  // read xml document w/o memory limits
186  // note that XML_PARSE_HUGE is part of an enum in libxml2
187  // it is only available in libxml 2.7+
188  m_doc = xmlReadFile(xmlfile.c_str(), NULL, XML_PARSE_HUGE);
189  //m_doc = xmlParseFile(xmlfile.c_str());
190 
191  if (m_doc == NULL)
192  {
193  return false;
194  }
195  m_root = xmlDocGetRootElement(m_doc);
196  if (m_root == NULL)
197  {
198  return false;
199  }
200  InFileRoot = std::string(xmlfile, 0, xmlfile.size() - 4);
201  return true;
202 }
203 
204 bool Libxml2Document::parseFromString(const std::string_view data)
205 {
206  if (m_doc != NULL)
207  xmlFreeDoc(m_doc);
208 
209  // read xml document w/o memory limits
210  // note that XML_PARSE_HUGE is part of an enum in libxml2
211  // it is only available in libxml 2.7+
212  m_doc = xmlReadMemory(data.data(), data.length(), NULL, NULL, XML_PARSE_HUGE);
213 
214  if (m_doc == NULL)
215  {
216  return false;
217  }
218  m_root = xmlDocGetRootElement(m_doc);
219  if (m_root == NULL)
220  {
221  return false;
222  }
223  InFileRoot = std::string("string");
224  return true;
225 }
226 #endif
227 
228 //#if defined(HAVE_MPI)
229 // xmlChar *xmlbuff;
230 // char *charbuff;
231 // int buffersize;
232 //
233 // // build an XML tree from a the file;
234 // if(OHMMS::Controler()->master()) {
235 // m_doc = xmlParseFile(infile.c_str());
236 // if (m_doc == NULL) {
237 // ERRORMSG("File " << infile << " is invalid")
238 // return false;
239 // }
240 // xmlDocDumpFormatMemory(m_doc,&xmlbuff,&buffersize,1);
241 // }
242 //
243 // OHMMS::Controller()->bcast(buffersize);
244 //
245 // if(OHMMS::Controler()->master()) {
246 // charbuff = (char*)xmlbuff;
247 // } else {
248 // charbuff = new char[buffersize];
249 // }
250 //
251 // OHMMS::Controller()->bcast(charbuff,buffersize);
252 //
253 // if(OHMMS::Controller()->master()) {
254 // xmlFreeDoc(xmlbuff);
255 // } else {
256 // m_doc = xmlReadMemory(charbuff, buffersize,
257 // "noname.xml", NULL, 0);
258 // delete [] charbuff;
259 // }
260 //#else
double elapsed() const
Definition: Timer.h:30
void restart()
Definition: Timer.h:29
void barrier() const
xmlDocPtr m_doc
Definition: Libxml2Doc.h:115
if(!okay) throw std xmlNodePtr node
xmlXPathContextPtr getXPathContext()
Definition: Libxml2Doc.cpp:100
std::ostream & app_log()
Definition: OutputManager.h:65
void newDoc(const std::string &rootName)
Definition: Libxml2Doc.cpp:93
Timer class.
Communicate * Controller
Global Communicator for a process.
Definition: Communicate.cpp:35
class to handle xmlXPathObject
Definition: Libxml2Doc.h:26
void put(const char *expression, xmlXPathContextPtr context)
evaluate the expression and create the object
Definition: Libxml2Doc.cpp:64
xmlXPathContextPtr m_context
Definition: Libxml2Doc.h:71
xmlNodePtr m_root
Definition: Libxml2Doc.h:116
xmlXPathContextPtr m_context
Definition: Libxml2Doc.h:117
std::string InFileRoot
Definition: Libxml2Doc.h:118
bool parseFromString(const std::string_view data)
Definition: Libxml2Doc.cpp:204
void addChild(xmlNodePtr newnode)
Definition: Libxml2Doc.cpp:111
bool parse(const std::string &fname)
Definition: Libxml2Doc.cpp:180
void dump(const std::string &newxml)
Definition: Libxml2Doc.cpp:109
xmlXPathObjectPtr result
Definition: Libxml2Doc.h:70