00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <string>
00026 #include <typeinfo>
00027 #include <stdlib.h>
00028 #include <libxml/tree.h>
00029 #include <sofa/simulation/tree/xml/XML.h>
00030 #include <sofa/helper/system/FileRepository.h>
00031 #include <sofa/helper/system/SetDirectory.h>
00032 #include <string.h>
00033
00034
00035
00036 namespace sofa
00037 {
00038
00039 namespace simulation
00040 {
00041
00042 namespace tree
00043 {
00044
00045 namespace xml
00046 {
00047
00048 using std::cout;
00049 using std::endl;
00050
00051
00052 #define is(n1, n2) (! xmlStrcmp((const xmlChar*)n1,(const xmlChar*)n2))
00053 #define getProp(n) ( xmlGetProp(cur, (const xmlChar*)n) )
00054
00055 void recReplaceAttribute(BaseElement* node, const char* attr, const char* value, const char* nodename=NULL)
00056 {
00057 if (nodename)
00058 {
00059 if (node->getName() == nodename)
00060 {
00061
00062 node->setAttribute(attr, value);
00063 }
00064 }
00065 else
00066 {
00067 if (node->getAttribute( attr ))
00068 {
00069
00070 node->setAttribute(attr, value);
00071 }
00072 }
00073 BaseElement::child_iterator<> it = node->begin();
00074 BaseElement::child_iterator<> end = node->end();
00075 while (it != end)
00076 {
00077 recReplaceAttribute( it, attr, value, nodename );
00078 ++it;
00079 }
00080 }
00081
00082
00083 BaseElement* includeNode (xmlNodePtr root,const char *basefilename);
00084 BaseElement* attributeNode(xmlNodePtr root,const char *basefilename);
00085
00086
00087 int numDefault=0;
00088
00089 BaseElement* createNode(xmlNodePtr root, const char *basefilename, bool isRoot = false)
00090 {
00091
00092 if (root->type != XML_ELEMENT_NODE) return NULL;
00093
00094
00095
00096 if (!xmlStrcmp(root->name,(const xmlChar*)"include"))
00097 {
00098 return includeNode(root, basefilename);
00099 }
00100
00101 std::string name, type;
00102
00103 xmlChar *pname = xmlGetProp(root, (const xmlChar*) "name");
00104 xmlChar *ptype = xmlGetProp(root, (const xmlChar*) "type");
00105
00106 if (pname != NULL)
00107 {
00108 name = (const char*)pname;
00109 xmlFree(pname);
00110 }
00111 else
00112 {
00113 name = "default";
00114
00115 char buf[16];
00116 sprintf(buf, "%d", numDefault);
00117 ++numDefault;
00118 name += buf;
00119 }
00120 if (ptype != NULL)
00121 {
00122 type = (const char*)ptype;
00123 xmlFree(ptype);
00124 }
00125 else
00126 {
00127 type = "default";
00128 }
00129
00130 BaseElement* node = BaseElement::Create((const char*)root->name,name,type);
00131
00132 if (node == NULL)
00133 {
00134 std::cerr << "Node "<<root->name<<" name "<<name<<" type "<<type<<" creation failed.\n";
00135 return NULL;
00136 }
00137
00138 if (isRoot)
00139 node->setBaseFile( basefilename );
00140
00141
00142
00143
00144 for (xmlAttrPtr attr = root->properties; attr!=NULL; attr = attr->next)
00145 {
00146 if (attr->children==NULL) continue;
00147 if (!xmlStrcmp(attr->name,(const xmlChar*)"name")) continue;
00148 if (!xmlStrcmp(attr->name,(const xmlChar*)"type")) continue;
00149
00150 node->setAttribute((const char*)attr->name, (const char*)attr->children->content);
00151 }
00152
00153 for (xmlNodePtr child = root->xmlChildrenNode; child != NULL; child = child->next)
00154 {
00155 BaseElement* childnode = createNode(child, basefilename);
00156 if (childnode != NULL)
00157 {
00158
00159 if (childnode->isGroupType())
00160 {
00161 BaseElement::child_iterator<> it(childnode->begin());
00162 for(;it!=childnode->end();++it) {node->addChild(it); childnode->removeChild(it);}
00163 }
00164 else
00165 {
00166 if (!node->addChild(childnode))
00167 {
00168 std::cerr << "Node "<<childnode->getClass()<<" name "<<childnode->getName()<<" type "<<childnode->getType()
00169 <<" cannot be a child of node "<<node->getClass()<<" name "<<node->getName()<<" type "<<node->getType()<<std::endl;
00170 delete childnode;
00171 }
00172 }
00173 }
00174 }
00175 return node;
00176 }
00177
00178 static void dumpNode(BaseElement* node, std::string prefix0="==", std::string prefix=" ")
00179 {
00180 std::cout << prefix0;
00181 std::cout << node->getClass()<<" name "<<node->getName()<<" type "<<node->getType()<<std::endl;
00182 BaseElement::child_iterator<> it = node->begin();
00183 BaseElement::child_iterator<> end = node->end();
00184 while (it != end)
00185 {
00186 BaseElement::child_iterator<> next = it;
00187 ++next;
00188 if (next==end) dumpNode(it, prefix+"\\-", prefix+" ");
00189 else dumpNode(it, prefix+"+-", prefix+"| ");
00190 it = next;
00191 }
00192 }
00193
00194 BaseElement* processXMLLoading(const char *filename, const xmlDocPtr &doc)
00195 {
00196 xmlNodePtr root;
00197
00198 if (doc == NULL) {
00199 std::cerr << "Failed to open " << filename << std::endl;
00200 return NULL;
00201 }
00202
00203 root = xmlDocGetRootElement(doc);
00204
00205 if (root == NULL) {
00206 std::cerr << "empty document" << std::endl;
00207 xmlFreeDoc(doc);
00208 return NULL;
00209 }
00210
00211
00212 std::string basefilename =
00213 sofa::helper::system::SetDirectory::GetRelativeFromDir(filename,sofa::helper::system::SetDirectory::GetCurrentDir().c_str());
00214 BaseElement* graph = createNode(root, basefilename.c_str(), true);
00215
00216 xmlFreeDoc(doc);
00217 xmlCleanupParser();
00218 xmlMemoryDump();
00219
00220 if (graph == NULL)
00221 {
00222 std::cerr << "XML Graph creation failed."<<std::endl;
00223 return NULL;
00224 }
00225
00226
00227
00228
00229 return graph;
00230 }
00231
00232 BaseElement* loadFromMemory(const char *filename, const char *data, unsigned int size )
00233 {
00234
00235
00236
00237
00238
00239 LIBXML_TEST_VERSION
00240
00241 xmlDocPtr doc;
00242
00243 xmlSubstituteEntitiesDefault(1);
00244
00245 doc = xmlParseMemory(data,size);
00246
00247 return processXMLLoading(filename, doc);
00248 }
00249
00250 BaseElement* loadFromFile(const char *filename)
00251 {
00252
00253
00254
00255
00256
00257 LIBXML_TEST_VERSION
00258
00259 xmlDocPtr doc;
00260
00261 xmlSubstituteEntitiesDefault(1);
00262
00263 doc = xmlParseFile(filename);
00264
00265 return processXMLLoading(filename, doc);
00266
00267 }
00268
00269
00270 BaseElement* includeNode(xmlNodePtr root,const char *basefilename)
00271 {
00272 std::string filename;
00273 xmlChar *pfilename = xmlGetProp(root, (const xmlChar*) "href");
00274 if (pfilename)
00275 {
00276 filename = (const char*)pfilename;
00277 xmlFree(pfilename);
00278 }
00279 if (filename.empty())
00280 {
00281 std::cerr << "ERROR: xml include tag requires non empty filename or href attribute." << std::endl;
00282 return NULL;
00283 }
00284
00285 sofa::helper::system::DataRepository.findFileFromFile(filename, basefilename);
00286 xmlDocPtr doc;
00287 doc = xmlParseFile(filename.c_str());
00288 if (doc == NULL)
00289 {
00290 std::cerr << "ERROR: Failed to parse " << filename << std::endl;
00291 return NULL;
00292 }
00293
00294 xmlNodePtr newroot = xmlDocGetRootElement(doc);
00295 if (newroot == NULL)
00296 {
00297 std::cerr << "ERROR: empty document in " << filename << std::endl;
00298 xmlFreeDoc(doc);
00299 return NULL;
00300 }
00301 BaseElement* result = createNode(newroot, filename.c_str(), true);
00302 if (result)
00303 {
00304
00305 if (result->getName() == "Group") result->setGroupType(true);
00306
00307 for (xmlAttrPtr attr = root->properties; attr!=NULL; attr = attr->next)
00308 {
00309 if (attr->children==NULL) continue;
00310 if (!xmlStrcmp(attr->name,(const xmlChar*)"href")) continue;
00311 if (!xmlStrcmp(attr->name,(const xmlChar*)"name"))
00312 {
00313 if(!xmlStrcmp(attr->children->content,(const xmlChar*)"Group")) result->setGroupType(true);
00314 else result->setGroupType(false);
00315
00316 if (!result->isGroupType()) result->setName((const char*)attr->children->content);
00317 }
00318 else
00319 {
00320 const char* attrname = (const char*)attr->name;
00321
00322 const char* value = (const char*)attr->children->content;
00323 if (const char* sep = strstr(attrname,"__"))
00324 {
00325 std::string nodename(attrname, sep);
00326 recReplaceAttribute(result, sep+2, value, nodename.c_str());
00327 }
00328 else
00329 {
00330 recReplaceAttribute(result, attrname, value);
00331 }
00332 }
00333 }
00334 }
00335 xmlFreeDoc(doc);
00336 return result;
00337 }
00338
00339
00340 }
00341
00342 }
00343
00344 }
00345
00346 }
00347