#pragma once
#include "ofConstants.h"
#include "ofParameter.h"
#include "ofParameterGroup.h"
#include <numeric>
#include <Poco/DOM/Document.h>
#include <Poco/DOM/DocumentFragment.h>
#include <Poco/DOM/Element.h>
#include <Poco/DOM/DOMParser.h>
#include <Poco/DOM/DOMException.h>
#include <Poco/SAX/SAXException.h>
#include <Poco/XML/XMLString.h>
#include <Poco/XML/XMLWriter.h>
#include <Poco/DOM/DOMParser.h>
#include <Poco/DOM/DOMWriter.h>
#include <Poco/DOM/Document.h>
#include <Poco/DOM/Attr.h>
#include <Poco/DOM/Node.h>
#include <Poco/DOM/Text.h>
#include <Poco/DOM/NodeIterator.h>
#include <Poco/DOM/NodeFilter.h>
#include <Poco/DOM/NamedNodeMap.h>
#include <Poco/DOM/ChildNodesList.h>
class ofxXmlPoco{
public:
ofxXmlPoco();
~ofxXmlPoco();
ofxXmlPoco( const std::string & path );
ofxXmlPoco( const ofxXmlPoco& rhs );
const ofxXmlPoco& operator =( const ofxXmlPoco& rhs );
bool load(const std::filesystem::path & path);
bool save(const std::filesystem::path & path);
bool addChild( const std::string& path );
void addXml( ofxXmlPoco& xml, bool copyAll = false);
std::string getValue() const;
std::string getValue(const std::string & path) const;
int getIntValue() const;
int getIntValue(const std::string & path) const;
int64_t getInt64Value() const;
int64_t getInt64Value(const std::string& path) const;
float getFloatValue() const;
float getFloatValue(const std::string & path) const;
bool getBoolValue() const;
bool getBoolValue(const std::string & path) const;
bool setValue(const std::string& path, const std::string& value);
std::string getAttribute(const std::string& path) const;
bool setAttribute(const std::string& path, const std::string& value);
std::map<std::string, std::string> getAttributes() const;
int getNumChildren() const;
int getNumChildren(const std::string& path) const;
bool removeAttribute(const std::string& path);
bool removeAttributes(const std::string& path);
bool removeAttributes();
bool removeContents(const std::string& path);
bool removeContents();
bool remove(const std::string& path);
void remove();
bool exists(const std::string& path) const;
void clear();
std::string getName() const;
bool reset();
bool setToChild(unsigned long index);
bool setTo(const std::string& path);
bool setToParent();
bool setToParent(int numLevelsUp);
bool setToSibling();
bool setToPrevSibling();
bool loadFromBuffer( const std::string& buffer );
std::string toString() const;
static std::vector<std::string> tokenize(const std::string & str, const std::string & delim){
std::vector<std::string> tokens;
size_t p0 = 0, p1 = std::string::npos;
while(p0 != std::string::npos){
p1 = str.find_first_of(delim, p0);
if(p1 != p0){
std::string token = str.substr(p0, p1 - p0);
tokens.push_back(token);
}
p0 = str.find_first_not_of(delim, p1);
}
return tokens;
}
template <class T> bool addValue(const std::string& path, T data=T(), bool createEntirePath = false){
std::string value = ofToString(data);
std::vector<std::string> tokens;
if(path.find('/') != std::string::npos){
tokens = tokenize(path, "/");
}
if(tokens.size() > 1){
Poco::XML::Element* firstElement=nullptr, *lastElement=nullptr;
if(element){
lastElement = element;
}
if(!firstElement){
firstElement = lastElement;
}
for(std::size_t i = 0; i < tokens.size(); i++){
Poco::XML::Element* newElement = getPocoDocument()->createElement(tokens.at(i));
if(lastElement){
lastElement->appendChild(newElement);
}
lastElement = newElement;
}
if(value != ""){
Poco::XML::Text *text = getPocoDocument()->createTextNode(value);
try {
lastElement->appendChild( text );
} catch ( Poco::XML::DOMException &e ){
ofLogError("ofxXml") << "addValue(): couldn't set node value: " << DOMErrorMessage(e.code());
return false;
}
}
if(!element){
element = firstElement;
document->appendChild(element);
}
return true;
}else{
Poco::XML::Element *newElement = getPocoDocument()->createElement(path);
if(value != ""){
Poco::XML::Text *text = getPocoDocument()->createTextNode(value);
try {
newElement->appendChild(text);
text->release();
} catch ( Poco::XML::DOMException &e ){
ofLogError("ofxXml") << "addValue(): couldn't set node value: " << DOMErrorMessage(e.code());
return false;
}
}
if(element){
element->appendChild(newElement);
}else{
element = newElement;
}
}
return true;
}
template <class T> T getValue(const std::string& path, T returnVal=T()) const{
if(element){
if(path == ""){
if(element->firstChild() && element->firstChild()->nodeType() == Poco::XML::Node::TEXT_NODE) {
return ofFromString<T>(element->innerText());
}else{
ofLogWarning("ofxXmlPoco") << "getValue(): path \"" << path<< "\" not found when getting value";
return returnVal;
}
}else{
Poco::XML::Element *e = (Poco::XML::Element*) element->getNodeByPath(path);
if(e){
return ofFromString<T>(e->innerText());
}
}
}
return T();
}
Poco::XML::Element* getPocoElement();
Poco::XML::Element* getPocoElement(const std::string& path);
const Poco::XML::Element* getPocoElement() const;
const Poco::XML::Element* getPocoElement(const std::string& path) const;
Poco::XML::Document* getPocoDocument();
const Poco::XML::Document* getPocoDocument() const;
protected:
void releaseAll();
std::string DOMErrorMessage(short msg);
Poco::XML::Document *document;
Poco::XML::Element *element;
};
void ofSerialize(ofxXmlPoco & xml, const ofAbstractParameter & parameter);
void ofDeserialize(const ofxXmlPoco & xml, ofAbstractParameter & parameter);
Comments