OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
xml_pugi.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #include <boost/algorithm/string/replace.hpp>
6 #include "xml/xml_base.h"
7 #include "xml/xml_pugi.h"
8 #include "base/logging.h"
9 
10 // This is internal implementation detail specific to this lib to make
11 // exposed methods efficient.
12 
13 //XmlPugi::tmp_("");
14 pugi::xml_attribute XmlPugi::GAttr;
15 pugi::xml_node XmlPugi::GNode;
16 
17 XmlPugi::XmlPugi() : writer_(this), node_(GNode), attrib_(GAttr) {
18 }
19 
21  doc_.reset();
22 }
23 
24 pugi::xml_node XmlPugi::RootNode() {
25  return(doc_.root());
26 }
27 
28 const char *XmlPugi::ReadNode(const std::string &name) {
29  PugiPredicate p1(name);
30 
31  pugi::xml_node node = doc_.find_node(p1);
32  if (IsNull(node)) {
33  return NULL;
34  }
35 
36  SetContext(node);
37  if (node.type() != pugi::node_pi) {
38  for (node = node.first_child(); node; node = node.next_sibling()) {
39  // traverse to first plain character data or char data,
40  // skipping XML comments
41  if (node.type() == pugi::node_pcdata ||
42  node.type() == pugi::node_cdata)
43  break;
44  }
45  }
46 
47  return node.value();
48 
49 }
50 
51 pugi::xml_node XmlPugi::FindNode(const std::string &name) {
52  PugiPredicate p1(name);
53 
54  pugi::xml_node node = doc_.find_node(p1);
55  return node;
56 }
57 
58 const char *XmlPugi::ReadNodeName(const std::string &name) {
59  PugiPredicate p1(name);
60 
61  pugi::xml_node node = doc_.find_node(p1);
62  SetContext(node);
63 
64  return node.name();
65 }
66 
67 const char *XmlPugi::ReadNodeValue() {
68  pugi::xml_node node = node_;
69 
70  if (node.type() != pugi::node_pi) {
71  for (node = node.first_child(); node; node = node.next_sibling()) {
72  // traverse to first plain character data or char data,
73  // skipping XML comments
74  if (node.type() == pugi::node_pcdata ||
75  node.type() == pugi::node_cdata)
76  break;
77  }
78  }
79  return node.value();
80 }
81 
82 const char *XmlPugi::ReadChildNode() {
83  pugi::xml_node tmp = (node_ == GNode) ? doc_.first_child() :
84  node_.first_child();
85  SetContext(tmp);
86  return tmp.value();
87 }
88 
90  pugi::xml_node tmp = (node_ == GNode) ? doc_.first_child() :
91  node_.first_child();
92  SetContext(tmp);
93  return tmp.name();
94 }
95 
96 const char *XmlPugi::ReadNextNode() {
97  pugi::xml_node tmp = node_.next_sibling();
98 
99  SetContext(tmp);
100  return tmp.value();
101 }
102 
104  pugi::xml_node tmp = node_.next_sibling();
105 
106  SetContext(tmp);
107  return tmp.name();
108 }
109 
111  SetContext(node_);
112 }
113 
114 const char *XmlPugi::ReadAttrib(const std::string &str) {
115  pugi::xml_attribute tmp = node_.attribute(str.c_str());
116  SetContext(node_, tmp);
117  return tmp.value();
118 }
119 
121  pugi::xml_attribute tmp = node_.first_attribute();
122  SetContext(node_, tmp);
123  return tmp.value();
124 }
125 
126 const char *XmlPugi::ReadNextAttrib() {
127  pugi::xml_attribute tmp = attrib_.next_attribute();
128  SetContext(node_, tmp);
129  return tmp.value();
130 }
131 
134 }
135 
136 const char *XmlPugi::ReadParentName() {
137  pugi::xml_node tmp = node_.parent();
138  SetContext(tmp);
139  return tmp.name();
140 }
141 
142 int XmlPugi::WriteDoc(uint8_t *buf) {
143  buf_tmp_ = buf; // this will be used by writer_->write
144  ts_ = 0;
145  doc_.save(writer_, "", pugi::format_default, pugi::encoding_utf8);
146 
147  if (ts_ == 0) return -1;
148  return static_cast<int>(ts_);
149 }
150 
151 int XmlPugi::WriteRawDoc(uint8_t *buf) {
152  buf_tmp_ = buf; // this will be used by writer_->write
153  ts_ = 0;
154  doc_.save(writer_, "", pugi::format_raw | pugi::format_no_declaration);
155 
156  if (ts_ == 0) return -1;
157  return static_cast<int>(ts_);
158 }
159 
160 void XmlPugi::PrintDoc(std::ostream& os) const {
161  doc_.print(os, " ", pugi::format_raw | pugi::format_no_declaration);
162 }
163 
164 void XmlPugi::PrintDocFormatted(std::ostream& os) const {
165  doc_.print(os, " ", pugi::format_indent | pugi::format_no_declaration);
166 }
167 
168 void XmlPugi::SetContext(pugi::xml_node node, pugi::xml_attribute attrib) {
169  node_ = node;
170  attrib_ = attrib;
171 }
172 
173 int XmlPugi::LoadDoc(const std::string &document) {
174  RewindDoc();
175  doc_.reset();
176 
177  pugi::xml_parse_result ret = doc_.load_buffer(document.c_str(), document.size(),
178  pugi::parse_default,
179  pugi::encoding_utf8);
180  if (ret == false) {
181  LOG(DEBUG, "XML doc load failed, code: " << ret << " " << ret.description());
182  LOG(DEBUG, "Error offset: " << ret.offset << " (error at [..." << (document.c_str() + ret.offset) << "]");
183  LOG(DEBUG, "Document: " << document);
184  return -1;
185  }
186  return 0;
187 }
188 
190  SetContext();
191 }
192 
193 void XmlPugi::AppendDoc(const std::string &node_name, XmlBase *a_doc) {
194  std::string str;
195  pugi::xml_node node_s;
196  pugi::xml_node node1;
197  pugi::xml_node node2;
198 
199  PugiPredicate p1(node_name);
200  node1 = doc_.find_node(p1);
201  SetContext(node1);
202 
203  XmlPugi *xp = static_cast<XmlPugi *>(a_doc);
204  node_s = xp->doc_.first_child();
205  if (!IsNull(node1)) {
206  node2 = node1.parent().append_copy(node_s);
207  SetContext(node2);
208  }
209 
210 }
211 
212 int XmlPugi::AddNode(const std::string &key, const std::string &value) {
213  pugi::xml_node node;
214 
215  if (IsNull(node_)) {
216  node = doc_.append_child(key.c_str());
217  } else {
218  node = node_.parent().append_child(key.c_str());
219  }
220  if (value != "") {
221  node.text().set(value.c_str());
222  }
223 
224  SetContext(node);
225  return 0;
226 }
227 
228 int XmlPugi::DeleteNode(const std::string &key) {
229  PugiPredicate p1(key);
230  pugi::xml_node node = doc_.find_node(p1);
231  if (IsNull(node))
232  return -1;
233 
234  node.parent().remove_child(key.c_str());
235  return 0;
236 }
237 
238 int XmlPugi::ModifyNode(const std::string &key, const std::string &value) {
239  PugiPredicate p1(key);
240  pugi::xml_node node = doc_.find_node(p1);
241  if (IsNull(node))
242  return -1;
243 
244  node.text().set(value.c_str());
245 
246  SetContext(node);
247  return 0;
248 }
249 
250 int XmlPugi::AddChildNode(const std::string &key, const std::string &value) {
251  pugi::xml_node node;
252 
253  if (IsNull(node_)) {
254  node = doc_.append_child(key.c_str());
255  } else {
256  node = node_.append_child(key.c_str());
257  }
258  if (value != "") {
259  node.text().set(value.c_str());
260  }
261 
262  SetContext(node);
263  return 0;
264 }
265 
266 int XmlPugi::AddChildNodeAfter(const std::string &node_name,
267  const std::string &key,
268  const std::string &value) {
269 
270  PugiPredicate p1(node_name);
271  pugi::xml_node node1 = doc_.find_node(p1);
272  SetContext(node1);
273 
274  if (!IsNull(node1)) {
275  AddChildNode(key, value);
276  }
277 
278  return 0;
279 }
280 
281 
282 int XmlPugi::AddAttribute(const std::string &key, const std::string &value) {
283  if (IsNull(node_))
284  return -1;
285 
286  pugi::xml_attribute attrib;
287 
288  if (IsNull(attrib_) ) {
289  attrib = node_.append_attribute(key.c_str()) = value.c_str();
290  } else {
291  attrib =
292  node_.insert_attribute_after(key.c_str(), attrib_) = value.c_str();
293  }
294 
295  SetContext(node_, attrib);
296  return 0;
297 }
298 
299 int XmlPugi::DeleteAttribute(const std::string &key) {
300  if (IsNull(node_))
301  return -1;
302  pugi::xml_attribute tmp = node_.attribute(key.c_str());
303  bool res;
304  if (IsNull(tmp)) {
305  return -1;
306  } else {
307  pugi::xml_attribute attrib = tmp.next_attribute();
308  res = node_.remove_attribute(tmp);
309  SetContext(node_, attrib);
310  return (res ? -1 : 0);
311  }
312  return 0;
313 }
314 
315 int XmlPugi::ModifyAttribute(const std::string &key, const std::string &value) {
316  if (node_.type() == pugi::node_null)
317  return -1;
318 
319  //ReadAttrib(key);
320  pugi::xml_attribute tmp = node_.attribute(key.c_str());
321  if (IsNull(tmp)) {
322  return -1;
323  } else {
324  tmp.set_value(value.c_str());
325  SetContext(node_, tmp);
326  }
327 
328  return 0;
329 }
330 
331 void XmlPugi::xmpp_buf_write::write(const void *data, size_t sz) {
332  ref->SetBuf(data, sz);
333 }
334 
335 void XmlPugi::SetBuf(const void *buf, size_t sz) {
336  memcpy(buf_tmp_ + ts_, buf, sz);
337  ts_ += sz;
338  *(buf_tmp_+ts_) = '\0';
339 }
XmlPugi()
Definition: xml_pugi.cc:17
virtual int LoadDoc(const std::string &doc)
Definition: xml_pugi.cc:173
pugi::xml_node FindNode(const std::string &name)
Definition: xml_pugi.cc:51
virtual const char * ReadNextNode()
Definition: xml_pugi.cc:96
virtual const char * ReadParentName()
Definition: xml_pugi.cc:136
virtual int ModifyNode(const std::string &key, const std::string &value)
Definition: xml_pugi.cc:238
virtual void write(const void *data, size_t sz)
Definition: xml_pugi.cc:331
pugi::xml_node node_
Definition: xml_pugi.h:78
virtual const char * ReadNodeValue()
Definition: xml_pugi.cc:67
size_t ts_
Definition: xml_pugi.h:72
virtual void RewindNode()
Definition: xml_pugi.cc:110
virtual const char * ReadChildNode()
Definition: xml_pugi.cc:82
virtual int WriteRawDoc(uint8_t *buf)
Definition: xml_pugi.cc:151
pugi::xml_node RootNode()
Definition: xml_pugi.cc:24
virtual void PrintDocFormatted(std::ostream &os) const
Definition: xml_pugi.cc:164
virtual int DeleteAttribute(const std::string &key)
Definition: xml_pugi.cc:299
static pugi::xml_attribute GAttr
Definition: xml_pugi.h:92
uint8_t * buf_tmp_
Definition: xml_pugi.h:71
virtual void PrintDoc(std::ostream &os) const
Definition: xml_pugi.cc:160
virtual int AddAttribute(const std::string &key, const std::string &value)
Definition: xml_pugi.cc:282
static pugi::xml_node GNode
Definition: xml_pugi.h:93
virtual ~XmlPugi()
Definition: xml_pugi.cc:20
virtual int AddChildNode(const std::string &key, const std::string &value)
Definition: xml_pugi.cc:250
bool IsNull(pugi::xml_node &node)
Definition: xml_pugi.h:63
virtual const char * ReadNodeName(const std::string &name)
Definition: xml_pugi.cc:58
virtual void RewindDoc()
Definition: xml_pugi.cc:189
virtual int ModifyAttribute(const std::string &key, const std::string &value)
Definition: xml_pugi.cc:315
virtual const char * ReadChildNodeName()
Definition: xml_pugi.cc:89
virtual const char * ReadAttrib(const std::string &str)
Definition: xml_pugi.cc:114
virtual const char * ReadNode(const std::string &name)
Definition: xml_pugi.cc:28
virtual int AddNode(const std::string &key, const std::string &value)
Definition: xml_pugi.cc:212
void SetBuf(const void *buf, size_t sz)
Definition: xml_pugi.cc:335
virtual int WriteDoc(uint8_t *buf)
Definition: xml_pugi.cc:142
virtual void AppendDoc(const std::string &str, XmlBase *a_doc)
Definition: xml_pugi.cc:193
virtual int DeleteNode(const std::string &key)
Definition: xml_pugi.cc:228
pugi::xml_attribute attrib_
Definition: xml_pugi.h:79
virtual const char * ReadNextNodeName()
Definition: xml_pugi.cc:103
virtual void RewindAttrib()
Definition: xml_pugi.cc:132
virtual const char * ReadNextAttrib()
Definition: xml_pugi.cc:126
#define LOG(_Level, _Msg)
Definition: logging.h:33
struct xmpp_buf_write writer_
Definition: xml_pugi.h:73
virtual int AddChildNodeAfter(const std::string &node_name, const std::string &key, const std::string &value)
Definition: xml_pugi.cc:266
virtual const char * ReadFirstAttrib()
Definition: xml_pugi.cc:120
pugi::xml_document doc_
Definition: xml_pugi.h:75
void SetContext(pugi::xml_node node=GNode, pugi::xml_attribute atrib=GAttr)
Definition: xml_pugi.cc:168