28 #include <Base/Common/W32Compat.hh>
41 #include <libxml/tree.h>
42 #include <libxml/encoding.h>
43 #include <libxml/parser.h>
45 #include <Base/Common/FileHandling.hh>
55 isInitialized_ =
false;
81 isInitialized_ =
false;
90 if (xmlValidateName(BAD_CAST RootNodeName.c_str(), 0)!=0) {
91 BIASERR(
"'" << RootNodeName <<
92 "'is no valid node name, maybe contains blanks??\n");
102 isInitialized_ =
false;
106 xmlDoc_ = xmlNewDoc(BAD_CAST XML_DEFAULT_VERSION);
107 if (xmlDoc_ == NULL) {
108 BIASERR(
"Error creating the xml document tree\n");
113 CurrNode_ = RootNode_ =
114 xmlNewDocNode(xmlDoc_, NULL, BAD_CAST RootNodeName.c_str(), NULL);
115 if (RootNode_ == NULL) {
117 BIASERR(
"Error creating the root node\n");
122 xmlDocSetRootElement(xmlDoc_, RootNode_);
124 isInitialized_ =
true;
132 const std::string& NewNodeName) {
134 if (xmlValidateName(BAD_CAST NewNodeName.c_str(), 0)!=0) {
135 BIASERR(
"'" << NewNodeName <<
136 "'is no valid node name, maybe contains blanks??\n");
140 if (!isInitialized_) {
141 BIASERR(
"Not initialized: Please call createXML/loadXML first\n");
145 CurrNode_ = xmlNewChild(ParentNode, NULL,
146 BAD_CAST NewNodeName.c_str(), NULL);
147 if (CurrNode_ == NULL) {
148 BIASERR(
"Error creating the child node\n");
157 const std::string& AttributeName,
158 const bool AttributeValue) {
160 if (AttributeValue) {
165 addAttribute(Node,AttributeName,stst.str());
170 const std::string& AttributeName,
171 const int AttributeValue) {
173 stst << AttributeValue;
174 addAttribute(Node,AttributeName,stst.str());
179 const std::string& AttributeName,
180 const double AttributeValue) {
183 stst << setprecision(10);
184 stst << AttributeValue;
186 addAttribute(Node,AttributeName,stst.str());
191 const std::string& AttributeName,
192 const std::vector<double> &AttributeValue) {
195 stst << setprecision(10);
196 for (
int i=0; i<(int)AttributeValue.size()-1; i++){
197 stst << AttributeValue[i] <<
" ";
199 if (AttributeValue.size()>0)
200 stst << AttributeValue[AttributeValue.size()-1];
201 addAttribute(Node,AttributeName,stst.str());
207 const std::string& AttributeName,
208 const std::vector<int> &AttributeValue) {
210 for (
int i=0; i<(int)AttributeValue.size()-1; i++){
211 stst << AttributeValue[i] <<
" ";
213 if (AttributeValue.size()>0)
214 stst << AttributeValue[AttributeValue.size()-1];
216 addAttribute(Node,AttributeName,stst.str());
221 const std::string& AttributeName,
222 const std::string& AttributeValue) {
224 if (xmlValidateName(BAD_CAST AttributeName.c_str(), 0)!=0) {
225 BIASERR(
"'" << AttributeName <<
226 "'is no valid attribute name, maybe contains blanks??\n");
230 if (!isInitialized_) {
231 BIASERR(
"Not initialized: Please call createXML/loadXML first\n");
236 attPtr = xmlSetProp(Node, BAD_CAST AttributeName.c_str(),
237 BAD_CAST AttributeValue.c_str());
238 if (attPtr == NULL) {
239 BIASERR(
"Error creating the child node\n");
246 const std::string& AttributeName,
247 const char* AttributeValue)
249 std::string toStr(AttributeValue);
250 addAttribute(Node, AttributeName, toStr);
256 if (!isInitialized_) {
257 BIASERR(
"Not initialized: Please call createXML/loadXML first\n");
261 xmlNodeAddContent(Node, BAD_CAST Content.c_str());
267 if (!isInitialized_) {
268 BIASERR(
"Not initialized: Please call createXML/loadXML first\n");
274 ss << setprecision(10);
277 xmlNodeAddContent(Node, BAD_CAST ss.str().c_str());
283 if (!isInitialized_) {
284 BIASERR(
"Not initialized: Please call createXML/loadXML first\n");
290 xmlNodeAddContent(Node, BAD_CAST ss.str().c_str());
296 if (!isInitialized_) {
297 BIASERR(
"Not initialized: Please call createXML/loadXML first\n");
302 for (
unsigned int i=0; i<Content.size(); i++) {
303 ss << Content[i] <<
" ";
305 xmlNodeAddContent(Node, BAD_CAST ss.str().c_str());
311 if (!isInitialized_) {
312 BIASERR(
"Not initialized: Please call createXML/loadXML first\n");
316 myNode = xmlNewComment(BAD_CAST Comment.c_str());
317 xmlAddChild(Node, myNode);
323 if (!isInitialized_) {
324 BIASERR(
"Not initialized: Please call createXML/loadXML first\n");
328 xmlNodeSetContent(Node, BAD_CAST Content.c_str());
335 if (!isInitialized_) {
336 BIASERR(
"Not initialized: Please call createXML/loadXML first\n");
342 ss << setprecision(10);
345 xmlNodeSetContent(Node, BAD_CAST ss.str().c_str());
352 if (!isInitialized_) {
353 BIASERR(
"Not initialized: Please call createXML/loadXML first\n");
359 xmlNodeSetContent(Node, BAD_CAST ss.str().c_str());
366 if (!isInitialized_) {
367 BIASERR(
"Not initialized: Please call createXML/loadXML first\n");
372 for (
unsigned int i=0; i<Content.size(); i++) {
373 ss << Content[i] <<
" ";
375 xmlNodeSetContent(Node, BAD_CAST ss.str().c_str());
380 bool AutoAddCompressionSuffix)
const {
381 if (!isInitialized_) {
382 BIASERR(
"Not initialized: Please call createXML/loadXML first\n");
386 string FileName( FilenameConst );
392 if ((xmlGetDocCompressMode(xmlDoc_)>0) && AutoAddCompressionSuffix)
399 BIASASSERT(this->xmlDoc_!=NULL);
402 int nBytes = xmlSaveFormatFileEnc(FileName.c_str(), this->xmlDoc_,
403 Encoding_.c_str(), 2 );
407 BIASERR(
"Error saving XML file " << FileName <<
" ("
408 << FilenameConst <<
"), wrote " << nBytes <<
" bytes");
419 std::string Filename(FilenameConst);
425 if (isInitialized_) {
430 isInitialized_ =
false;
434 xmlDoc_ = xmlParseFile(Filename.c_str());
437 if (xmlDoc_ == NULL) {
438 BIASERR(
"Error parsing the xml document: '"<<Filename
439 <<
"' XML syntax error/not well formed? Or file not found? \n");
444 RootNode_ = CurrNode_ = xmlDocGetRootElement(xmlDoc_);
454 CurrNode_ = ParentNode->children;
455 while (CurrNode_!=NULL) {
456 if (CurrNode_->type == XML_ELEMENT_NODE) {
459 CurrNode_ = CurrNode_->next;
467 return getNextChild(NULL);
473 if (SiblingNode!=NULL) {
474 CurrNode_ = SiblingNode;
477 while (CurrNode_->next!=NULL) {
478 CurrNode_ = CurrNode_->next;
479 if (CurrNode_->type == XML_ELEMENT_NODE) {
490 const std::string& ChildName) {
493 myNode = getFirstChild(ParentNode);
494 while(myNode!=NULL) {
495 if (ChildName==getNodeName(myNode)) {
498 myNode = getNextChild();
507 const std::string& ChildName,
508 std::vector<xmlNodePtr>& childrenWithSameName)
510 childrenWithSameName.clear();
511 xmlNodePtr currentChildNode;
512 currentChildNode = getFirstChild(ParentNode);
513 while(currentChildNode!=NULL) {
514 if (ChildName==getNodeName(currentChildNode)) {
515 childrenWithSameName.push_back(currentChildNode);
517 currentChildNode = getNextChild();
522 const std::string& ChildName,
523 const std::string& AttributeName,
524 const std::string& AttributeValue) {
527 myNode = getFirstChild(ParentNode);
528 while(myNode!=NULL) {
529 if (ChildName==getNodeName(myNode)) {
530 if(getAttributeValueString(myNode, AttributeName) == AttributeValue) {
534 myNode = getNextChild();
547 if ((Node!=NULL) && (Node->name!=NULL)) {
548 ret = (
char*) Node->name;
558 if (Node->children!=NULL){
559 if(Node->children->content!=NULL){
560 temp = (
char*) Node->children->content;
562 int rear=(
int)temp.size()-1;
563 while(temp[front]==
' ' || (
int)temp[front]==32 || (
int)temp[front]==10)
565 if (front >=(
int)temp.size())
return "";
566 while(temp[rear]==
' ' || (
int)temp[rear]==32 || (int)temp[rear]==10)
568 if (rear < 0)
return "";
569 if (front>rear)
return "";
570 ret.resize(rear-front+1);
571 for(
int k=front; k<=rear; k++)
572 ret[k-front]=temp[k];
582 s = getNodeContentString(Node);
583 return atoi(s.c_str());
589 stringstream s(getNodeContentString(Node));
590 std::vector<int> ret;
601 stringstream s(getNodeContentString(Node));
602 std::vector<double> ret;
616 s = getNodeContentString(Node);
618 double d = atof(s.c_str());
626 CurrAttr_ = Node->properties;
627 while (CurrAttr_!=NULL) {
628 if (CurrAttr_->type == XML_ATTRIBUTE_NODE) {
631 CurrAttr_ = CurrAttr_->next;
640 while (CurrAttr_->next!=NULL) {
641 CurrAttr_ = CurrAttr_->next;
642 if (CurrAttr_->type == XML_ATTRIBUTE_NODE) {
651 const std::string& attribute_name)
655 xmlAttrPtr result = getFirstAttribute(Node);
657 while (result != NULL){
658 if (getAttributeName(result) == attribute_name)
return result;
660 result = getNextAttribute();
668 std::vector<xmlNodePtr>& children)
671 xmlNodePtr child = getFirstChild(ParentNode);
672 while (child != NULL){
673 children.push_back(child);
674 child = getNextChild();
680 std::vector<xmlAttrPtr>& attributes)
683 xmlAttrPtr attr = getFirstAttribute(ParentNode);
684 while (attr != NULL){
685 attributes.push_back(attr);
686 attr = getNextAttribute();
693 if (Attribute->name!=NULL) {
694 ret = (
char*) Attribute->name;
703 s = getAttributeValueString(Attribute);
708 }
else if (s ==
"false" || s.empty()) {
711 BIASERR(
"Undefined boolean value \"" << s <<
"\" found! Using \"false\" instead!");
719 if (Attribute->children!=NULL) {
720 if (Attribute->children->content!=NULL) {
721 ret = (
char*) Attribute->children->content;
731 s = getAttributeValueString(Attribute);
732 return atoi(s.c_str());
739 s = getAttributeValueString(Attribute);
741 double d = atof(s.c_str());
749 stringstream s(getAttributeValueString(Attribute));
750 std::vector<double> tempVec;
754 tempVec.push_back(temp);
763 stringstream s(getAttributeValueString(Attribute));
764 std::vector<int> tempVec;
767 tempVec.push_back(temp);
773 const std::string& AttributeName)
const{
776 pc = (
char*) xmlGetProp(Node, BAD_CAST AttributeName.c_str());
786 const std::string& AttributeName)
const {
789 pc = (
char*) xmlGetProp(Node, BAD_CAST AttributeName.c_str());
796 if (temp ==
"true") {
798 }
else if (temp ==
"false" || temp.empty()) {
808 const std::string& AttributeName)
const {
811 pc = (
char*) xmlGetProp(Node, BAD_CAST AttributeName.c_str());
816 return atoi(ret.c_str());
821 const std::string& AttributeName)
const {
824 pc = (
char*) xmlGetProp(Node, BAD_CAST AttributeName.c_str());
830 double retValue = atof(ret.c_str());
837 const std::string& AttributeName)
const {
840 std::vector<double> tempVec;
842 pc = (
char*) xmlGetProp(Node, BAD_CAST AttributeName.c_str());
848 tempVec.push_back(temp);
855 const std::string& AttributeName)
const {
858 std::vector<int> tempVec;
860 pc = (
char*) xmlGetProp(Node, BAD_CAST AttributeName.c_str());
866 tempVec.push_back(temp);
873 if (isInitialized_) {
875 ret = xmlGetDocCompressMode(xmlDoc_);
876 if (level>9) level = 9;
877 if (level<0) level = 0;
878 xmlSetDocCompressMode(xmlDoc_, level);
880 BIASERR(
"No document yet! Ignored compression level");
889 if (!isInitialized_) {
890 BIASERR(
"Not initialized: Please call createXML/loadXML first\n");
897 xmlDocDumpFormatMemory(xmlDoc_, &xmlbuff, &buffersize, 1);
899 str.replace(0, buffersize, (
char *) xmlbuff);
908 if (isInitialized_) {
914 isInitialized_ =
false;
917 xmlDoc_ = xmlReadMemory(str.c_str(), (int)str.length(),
"noname.xml", NULL, 0);
919 if (xmlDoc_ == NULL) {
920 BIASERR(
"Error parsing the xml document, was not well formed (ReadFromString)");
924 RootNode_ = CurrNode_ = xmlDocGetRootElement(xmlDoc_);
936 int inlen = (int)isoLatin1.length();
937 int outlen = 2*inlen;
938 unsigned char *outbuf =
new unsigned char[outlen+1];
939 res = isolat1ToUTF8(outbuf, &outlen, BAD_CAST isoLatin1.c_str(), &inlen);
941 for (
int i = 0; i < outlen; i++) { utf8 += outbuf[i]; }
955 int inlen = (int)utf8.length();
956 int outlen = 2*inlen;
957 unsigned char *outbuf =
new unsigned char[outlen+1];
958 res = UTF8Toisolat1(outbuf, &outlen, BAD_CAST utf8.c_str(), &inlen);
960 for (
int i = 0; i < outlen; i++) { isoLatin1 += outbuf[i]; }
void addAttribute(const xmlNodePtr Node, const std::string &AttributeName, bool AttributeValue)
Add an attribute to a node.
std::string getAttributeName(const xmlAttrPtr Attribute) const
Get the name of a given Attribute.
xmlNodePtr getNextChild()
Get the next child of the parent specified in the last getFirstChild() call, the class remembers the ...
int write(const std::string &Filename, bool AutoAddCompressionSuffix=true) const
Write the whole tree that was constructed in memory to disk.
xmlNodePtr read(const std::string &Filename)
Read and parse an XML file from disk, DtD validation is not yet implemented.
void addComment(const xmlNodePtr Node, const std::string &Comment)
Add comment to a node.
xmlNodePtr getChild(const xmlNodePtr ParentNode, const std::string &ChildName)
Get a child of a Parent node by specifying the childs name, NULL is returned if the ParentNode has no...
xmlNodePtr create(const std::string &RootNodeName)
Create the base of a new XML-Tree in memory, already with a one and only root node.
static int IsoLatin1ToUtf8(const std::string &isoLatin1, std::string &utf8)
Convert character string from UTF-8 format to ISO 8895-1.
bool getAttributeValueBool(const xmlAttrPtr Attribute) const
Get the value of a given Attribute, with type-cast overloads for different attribute types...
xmlAttrPtr getFirstAttribute(const xmlNodePtr Node)
Get the first attribute of a given parent, or NULL for no attributes.
std::vector< double > getAttributeValueVecDbl(const xmlAttrPtr Attribute) const
std::string getAttributeValueString(const xmlAttrPtr Attribute) const
int getAttributeValueInt(const xmlAttrPtr Attribute) const
std::vector< double > getNodeContentVectorDouble(const xmlNodePtr Node) const
void addContent(const xmlNodePtr Node, const std::string &Content)
Add content to a node.
double getNodeContentDouble(const xmlNodePtr Node) const
xmlNodePtr addChildNode(const xmlNodePtr ParentNode, const std::string &NewNodeName)
Add a child node to an incoming node with the given name.
int WriteToString(std::string &str)
serialize tree to string
void GetChildren(const xmlNodePtr ParentNode, const std::string &ChildName, std::vector< xmlNodePtr > &childrenWithSameName)
Convenience wrapper: returns a vector of pointors to every (direct) child with the specified name...
void GetAttributes(const xmlNodePtr Node, std::vector< xmlAttrPtr > &attributes)
accesor functions for recursive usage
xmlNodePtr ReadFromString(const std::string &str)
construct tree from string
void setContent(const xmlNodePtr Node, const std::string &Content)
Set content of a node.
xmlNodePtr getFirstChild(const xmlNodePtr ParentNode)
Get the first child of a given parent, or NULL for no childs.
static int FilenameExpansion(const std::string &in, std::string &out)
Expand filename, e.g.
xmlAttrPtr getAttributeByName(const xmlNodePtr Node, const std::string &attribute_name)
search for a specific attribute
xmlAttrPtr getNextAttribute()
Get the next attribute of the parent specified in the last getFirstAttribute() call, the class remembers the last returned attribute.
xmlNodePtr GetChildWithAttributeValueString(const xmlNodePtr ParentNode, const std::string &ChildName, const std::string &AttributeName, const std::string &AttributeValue)
Finds the 'first' child with name ChildName and an attribute named AttributeName that has the string ...
double getAttributeValueDouble(const xmlAttrPtr Attribute) const
std::vector< int > getNodeContentVectorInt(const xmlNodePtr Node) const
std::string getNodeName(const xmlNodePtr Node) const
Get the name of a given Node.
int SetCompression(int level=9)
set level of compression, needs zlib
int getNodeContentInt(const xmlNodePtr Node) const
std::vector< int > getAttributeValueVecInt(const xmlAttrPtr Attribute) const
static std::string LowerCase(const std::string &input)
Return lower case string of input.
std::string getNodeContentString(const xmlNodePtr Node) const
Get the content of a given Node.
static int Utf8ToIsoLatin1(const std::string &utf8, std::string &isoLatin1)
Convert character string from ISO 8895-1 format to UTF-8.