framework2

Форк
0
498 строк · 11.6 Кб
1
#include "ofXml.h"
2
#include "ofUtils.h"
3
#include <clocale>
4

5
using std::string;
6

7
ofXml::ofXml()
8
:doc(new pugi::xml_document){
9
	xml = doc->root();
10
}
11

12
ofXml::ofXml(std::shared_ptr<pugi::xml_document> doc, const pugi::xml_node & xml)
13
:doc(doc)
14
,xml(xml){
15

16
}
17

18
bool ofXml::load(const of::filesystem::path & file){
19
	auto auxDoc = std::make_shared<pugi::xml_document>();
20
	auto p = ofToDataPath(file);
21
	auto res = auxDoc->load_file(ofToDataPath(file).c_str());
22
	if( res ){
23
		doc = auxDoc;
24
		xml = doc->root();
25
		return true;
26
	}else{
27
		ofLogWarning("ofXml") << "Cannot load file " << file << ": " << res.description();
28
		return false;
29
	}
30
}
31

32
bool ofXml::load(const ofBuffer & buffer){
33
	return parse(buffer.getText());
34
}
35

36
bool ofXml::parse(const std::string & xmlStr){
37
	auto auxDoc = std::make_shared<pugi::xml_document>();
38
    #if ( defined(PUGIXML_VERSION) && PUGIXML_VERSION >= 150 )
39
        if(auxDoc->load_string(xmlStr.c_str())){
40
    #else
41
        if(auxDoc->load(xmlStr.c_str())){
42
    #endif
43
		doc = auxDoc;
44
		xml = doc->root();
45
		return true;
46
	}else{
47
		return false;
48
	}
49
}
50

51
bool ofXml::save(const of::filesystem::path & file) const{
52
	if(xml == doc->root()){
53
		auto res = doc->save_file(ofToDataPath(file).c_str());
54
		ofLogVerbose("ofXml")<<"ofXML Save : "<< res;
55
		ofLogVerbose("ofXml")<<this->toString();
56
		return res;
57
	}else{
58
		pugi::xml_document doc;
59
		if(doc.append_copy(xml.root())){
60
			return doc.save_file(ofToDataPath(file).c_str());
61
		}
62
	}
63
	return false;
64
}
65

66
void ofXml::clear(){
67
	doc.reset(new pugi::xml_document);
68
	xml = doc->root();
69
}
70

71
std::string ofXml::toString(const std::string & indent) const{
72
	std::ostringstream stream;
73
	if(xml == doc->root()){
74
		doc->print(stream, indent.c_str());
75
	}else{
76
		pugi::xml_document doc;
77
		doc.append_copy(xml.root());
78
	}
79
	return stream.str();
80
}
81

82
ofXml ofXml::getChild(const std::string & name) const{
83
	return ofXml(doc, xml.child(name.c_str()));
84
}
85

86
ofXml::Range<ofXmlIterator<pugi::xml_node_iterator>> ofXml::getChildren() const{
87
	return ofXml::Range<ofXmlIterator<pugi::xml_node_iterator>>(doc, xml.children());
88
}
89

90
ofXml::Range<ofXmlIterator<pugi::xml_named_node_iterator>> ofXml::getChildren(const std::string & name) const{
91
	return ofXml::Range<ofXmlIterator<pugi::xml_named_node_iterator>>(doc, xml.children(name.c_str()));
92
}
93

94
ofXml ofXml::appendChild(const ofXml & xml){
95
	return ofXml(doc, this->xml.append_copy(xml.xml));
96
}
97

98
ofXml ofXml::prependChild(const ofXml & xml){
99
	return ofXml(doc, this->xml.prepend_copy(xml.xml));
100
}
101

102
#if PUGIXML_VERSION>=170
103
ofXml ofXml::appendChild(ofXml && xml){
104
	return ofXml(doc, this->xml.append_move(xml.xml));
105
}
106

107
ofXml ofXml::prependChild(ofXml && xml){
108
	return ofXml(doc, this->xml.prepend_move(xml.xml));
109
}
110

111
bool ofXml::removeChild(ofXml && node){
112
	return xml.remove_child(node.xml);
113
}
114
#endif
115

116
ofXml ofXml::appendChild(const std::string & name){
117
	return ofXml(doc, this->xml.append_child(name.c_str()));
118
}
119

120
ofXml ofXml::prependChild(const std::string & name){
121
	return ofXml(doc, this->xml.prepend_child(name.c_str()));
122
}
123

124
ofXml ofXml::insertChildAfter(const std::string & name, const ofXml & after){
125
	return ofXml(doc, this->xml.insert_child_after(name.c_str(), after.xml));
126
}
127

128
ofXml ofXml::insertChildBefore(const std::string & name, const ofXml & before){
129
	return ofXml(doc, this->xml.insert_child_before(name.c_str(), before.xml));
130
}
131

132
bool ofXml::removeChild(const std::string & name){
133
	return xml.remove_child(name.c_str());
134
}
135

136
bool ofXml::removeChild(const ofXml & node){
137
	return xml.remove_child(node.xml);
138
}
139

140
ofXml ofXml::getNextSibling() const{
141
	return ofXml(doc, this->xml.next_sibling());
142
}
143

144
ofXml ofXml::getPreviousSibling() const{
145
	return ofXml(doc, this->xml.previous_sibling());
146
}
147

148
ofXml ofXml::getNextSibling(const std::string & name) const{
149
	return ofXml(doc, this->xml.next_sibling(name.c_str()));
150
}
151

152
ofXml ofXml::getPreviousSibling(const std::string & name) const{
153
	return ofXml(doc, this->xml.previous_sibling(name.c_str()));
154
}
155

156
ofXml ofXml::getFirstChild() const{
157
	return ofXml(doc, this->xml.first_child());
158
}
159

160
ofXml ofXml::getLastChild() const{
161
	return ofXml(doc, this->xml.last_child());
162
}
163

164
ofXml ofXml::getParent() const {
165
	return ofXml(doc, this->xml.parent());
166
}
167

168
ofXml::Attribute ofXml::getAttribute(const std::string & name) const{
169
	return this->xml.attribute(name.c_str());
170
}
171

172
ofXml::Range<ofXmlAttributeIterator> ofXml::getAttributes() const{
173
	return ofXml::Range<ofXmlAttributeIterator>(doc, this->xml.attributes());
174
}
175

176
ofXml::Attribute ofXml::getFirstAttribute() const{
177
	return this->xml.first_attribute();
178
}
179

180
ofXml::Attribute ofXml::getLastAttribute() const{
181
	return this->xml.last_attribute();
182
}
183

184
ofXml::Attribute ofXml::appendAttribute(const std::string & name){
185
	return this->xml.append_attribute(name.c_str());
186
}
187

188
ofXml::Attribute ofXml::prependAttribute(const std::string & name){
189
	return this->xml.prepend_attribute(name.c_str());
190
}
191

192
bool ofXml::removeAttribute(const std::string & name){
193
	auto attr = getAttribute(name);
194
	if(attr){
195
		return xml.remove_attribute(attr.attr);
196
	}else{
197
		return false;
198
	}
199
}
200

201
bool ofXml::removeAttribute(const ofXml::Attribute & attr){
202
	return xml.remove_attribute(attr.attr);
203
}
204

205
bool ofXml::removeAttribute(ofXml::Attribute && attr){
206
	return xml.remove_attribute(attr.attr);
207
}
208

209
ofXml ofXml::findFirst(const std::string & path) const{
210
	try{
211
		return ofXml(doc, this->xml.select_node(path.c_str()).node());
212
	}catch(pugi::xpath_exception & e){
213
		return ofXml();
214
	}
215
}
216

217
ofXml::Search ofXml::find(const std::string & path) const{
218
	try{
219
		return ofXml::Search(doc, this->xml.select_nodes(path.c_str()));
220
	}catch(pugi::xpath_exception & e){
221
		ofLogError() << e.what();
222
		return ofXml::Search();
223
	}
224
}
225

226
std::string ofXml::getValue() const{
227
	return this->xml.text().as_string();
228
}
229

230
std::string ofXml::getName() const{
231
	return this->xml.name();
232
}
233

234
void ofXml::setName(const std::string & name){
235
	if(xml==doc->document_element()){
236
		xml = doc->append_child(pugi::node_element);
237
	}
238
	this->xml.set_name(name.c_str());
239
}
240

241
int ofXml::getIntValue() const{
242
	return this->xml.text().as_int();
243
}
244

245
unsigned int ofXml::getUintValue() const{
246
	return this->xml.text().as_uint();
247
}
248

249
float ofXml::getFloatValue() const{
250
	auto loc = std::setlocale( LC_NUMERIC, NULL );
251
	std::setlocale( LC_NUMERIC, "C" );
252
	float f = this->xml.text().as_float();
253
	std::setlocale( LC_NUMERIC, loc );
254
	return f;
255
}
256

257
double ofXml::getDoubleValue() const{
258
	auto loc = std::setlocale( LC_NUMERIC, NULL );
259
	std::setlocale( LC_NUMERIC, "C" );
260
	float d = this->xml.text().as_double();
261
	std::setlocale( LC_NUMERIC, loc );
262
	return d;
263
}
264

265
bool ofXml::getBoolValue() const{
266
	return this->xml.text().as_bool();
267
}
268

269
ofXml::operator bool() const{
270
	return this->xml;
271
}
272

273

274

275
//--------------------------------------------------------
276
// Attribute
277

278
ofXml::Attribute::Attribute(const pugi::xml_attribute & attr)
279
:attr(attr){}
280

281
std::string ofXml::Attribute::getValue() const{
282
	return this->attr.as_string();
283
}
284

285
void ofXml::Attribute::setName(const std::string & name){
286
	this->attr.set_name(name.c_str());
287
}
288

289
std::string ofXml::Attribute::getName() const{
290
	return this->attr.name();
291
}
292

293
int ofXml::Attribute::getIntValue() const{
294
	return this->attr.as_int();
295
}
296

297
unsigned int ofXml::Attribute::getUintValue() const{
298
	return this->attr.as_uint();
299
}
300

301
float ofXml::Attribute::getFloatValue() const{
302
	auto loc = std::setlocale( LC_NUMERIC, NULL );
303
	std::setlocale( LC_NUMERIC, "C" );
304
	float f = this->attr.as_float();
305
	std::setlocale( LC_NUMERIC, loc );
306
	return f;
307
}
308

309
double ofXml::Attribute::getDoubleValue() const{
310
	auto loc = std::setlocale( LC_NUMERIC, NULL );
311
	std::setlocale( LC_NUMERIC, "C" );
312
	float d = this->attr.as_double();
313
	std::setlocale( LC_NUMERIC, loc );
314
	return d;
315
}
316

317
bool ofXml::Attribute::getBoolValue() const{
318
	return this->attr.as_bool();
319
}
320

321
ofXml::Attribute::operator bool() const{
322
	return this->attr;
323
}
324

325
ofXml::Attribute ofXml::Attribute::getNextAttribute() const{
326
	return this->attr.next_attribute();
327
}
328

329
ofXml::Attribute ofXml::Attribute::getPreviousAttribute() const{
330
	return this->attr.previous_attribute();
331
}
332

333

334
//-----------------------------------------------
335
// Search
336

337
// Get collection type
338
pugi::xpath_node_set::type_t ofXml::Search::type() const{
339
	return search.type();
340
}
341

342
// Get collection size
343
size_t ofXml::Search::size() const{
344
	return search.size();
345
}
346

347
// Indexing operator
348
ofXml ofXml::Search::operator[](size_t index) const{
349
	return ofXml(doc, search[index].node());
350
}
351

352
// Collection iterators
353
ofXmlSearchIterator ofXml::Search::begin() const{
354
	return ofXmlSearchIterator(doc, search.begin());
355
}
356

357
ofXmlSearchIterator ofXml::Search::end() const{
358
	return ofXmlSearchIterator(doc, search.end());
359
}
360

361
// Sort the collection in ascending/descending order by document order
362
void ofXml::Search::sort(bool reverse){
363
	search.sort(reverse);
364
}
365

366
// Get first node in the collection by document order
367
ofXml ofXml::Search::getFirst() const{
368
	return ofXml(doc, search.first().node());
369
}
370

371
// Check if collection is empty
372
bool ofXml::Search::empty() const{
373
	return search.empty();
374
}
375

376

377
ofXml::Search::Search(std::shared_ptr<pugi::xml_document> doc, pugi::xpath_node_set set)
378
:doc(doc)
379
,search(set){}
380

381
//----------------------------------------------------
382
// SearchIterator
383
ofXmlSearchIterator::ofXmlSearchIterator(){}
384

385
// Iterator operators
386
bool ofXmlSearchIterator::operator==(const ofXmlSearchIterator& rhs) const{
387
	return this->node == rhs.node;
388
}
389

390
bool ofXmlSearchIterator::operator!=(const ofXmlSearchIterator& rhs) const{
391
	return this->node != rhs.node;
392
}
393

394
ofXml & ofXmlSearchIterator::operator*() const{
395
	return xml;
396
}
397

398
ofXml * ofXmlSearchIterator::operator->() const{
399
	return &xml;
400
}
401

402
const ofXmlSearchIterator& ofXmlSearchIterator::operator++(){
403
	if(node){
404
		node = node + 1;
405
		if(node){
406
			xml.xml = node->node();
407
		}
408
	}
409
	return *this;
410
}
411

412
ofXmlSearchIterator ofXmlSearchIterator::operator++(int){
413
	if(node){
414
		auto now = *this;
415
		++(*this);
416
		return now;
417
	}else{
418
		return *this;
419
	}
420
}
421

422
const ofXmlSearchIterator& ofXmlSearchIterator::operator--(){
423
	if(node){
424
		node = node - 1;
425
		if(node){
426
			xml.xml = node->node();
427
		}
428
	}
429
	return *this;
430
}
431

432
ofXmlSearchIterator ofXmlSearchIterator::operator--(int){
433
	if(node){
434
		auto now = *this;
435
		--(*this);
436
		return now;
437
	}else{
438
		return *this;
439
	}
440
}
441

442
void ofSerialize(ofXml & xml, const ofAbstractParameter & parameter){
443
	if(!parameter.isSerializable()){
444
		return;
445
	}
446
	string name = parameter.getEscapedName();
447
	if(name == ""){
448
		name = "UnknownName";
449
	}
450
	ofXml child	= xml.findFirst(name);
451
	
452
	if(!child){
453
		child = xml.appendChild(name);
454
		ofLogVerbose("ofXml") << "creating group " << name;
455
	}
456
	if(parameter.type() == typeid(ofParameterGroup).name()){
457
		const ofParameterGroup & group = static_cast <const ofParameterGroup &>(parameter);
458
		
459
		ofLogVerbose("ofXml") << "group " << name;
460
		for(auto & p: group){
461
			ofSerialize(child, *p);
462
		}
463
		ofLogVerbose("ofXml") << "end group " << name;
464
	}else{
465
		string value = parameter.toString();
466
		child.set(value);
467
	}
468
}
469

470

471
void ofDeserialize(const ofXml & xml, ofAbstractParameter & parameter){
472
	if(!parameter.isSerializable()){
473
		return;
474
	}
475
	string name = parameter.getEscapedName();
476
	
477
	ofXml child = xml.findFirst(name);
478
	if(child){
479
		if(parameter.type() == typeid(ofParameterGroup).name()){
480
			ofParameterGroup & group = static_cast <ofParameterGroup &>(parameter);
481
			for(auto & p: group){
482
				ofDeserialize(child, *p);
483
			}
484
		}else{
485
			if(parameter.type() == typeid(ofParameter <int> ).name()){
486
				parameter.cast <int>() = child.getIntValue();
487
			}else if(parameter.type() == typeid(ofParameter <float> ).name()){
488
				parameter.cast <float>() = child.getFloatValue();
489
			}else if(parameter.type() == typeid(ofParameter <bool> ).name()){
490
				parameter.cast <bool>() = child.getBoolValue();
491
			}else if(parameter.type() == typeid(ofParameter <string> ).name()){
492
				parameter.cast <string>() = child.getValue();
493
			}else{
494
				parameter.fromString(child.getValue());
495
			}
496
		}
497
	}
498
}
499

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.