Salome HOME
Update copyright: 2016
[modules/geom.git] / src / XAO / XAO_XaoExporter.cxx
1 // Copyright (C) 2013-2016  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Frederic Pons (OpenCascade)
20
21 #include <libxml/parser.h>
22
23 #include "XAO_XaoExporter.hxx"
24 #include "XAO_Xao.hxx"
25 #include "XAO_Geometry.hxx"
26 #include "XAO_Group.hxx"
27 #include "XAO_Field.hxx"
28 #include "XAO_Step.hxx"
29 #include "XAO_XaoUtils.hxx"
30
31 namespace XAO
32 {
33     const xmlChar* C_TAG_XAO = (xmlChar*)"XAO";
34     const xmlChar* C_ATTR_XAO_AUTHOR = (xmlChar*)"author";
35     const xmlChar* C_ATTR_XAO_VERSION = (xmlChar*)"version";
36
37     const xmlChar* C_TAG_GEOMETRY = (xmlChar*)"geometry";
38     const xmlChar* C_ATTR_GEOMETRY_NAME = (xmlChar*)"name";
39
40     const xmlChar* C_TAG_SHAPE = (xmlChar*)"shape";
41     const xmlChar* C_ATTR_SHAPE_FORMAT = (xmlChar*)"format";
42
43     const xmlChar* C_TAG_TOPOLOGY = (xmlChar*)"topology";
44     const xmlChar* C_TAG_VERTICES = (xmlChar*)"vertices";
45     const xmlChar* C_TAG_VERTEX = (xmlChar*)"vertex";
46     const xmlChar* C_TAG_EDGES = (xmlChar*)"edges";
47     const xmlChar* C_TAG_EDGE = (xmlChar*)"edge";
48     const xmlChar* C_TAG_FACES = (xmlChar*)"faces";
49     const xmlChar* C_TAG_FACE = (xmlChar*)"face";
50     const xmlChar* C_TAG_SOLIDS = (xmlChar*)"solids";
51     const xmlChar* C_TAG_SOLID = (xmlChar*)"solid";
52     const xmlChar* C_ATTR_COUNT = (xmlChar*)"count";
53     const xmlChar* C_ATTR_ELT_INDEX = (xmlChar*)"index";
54     const xmlChar* C_ATTR_ELT_NAME = (xmlChar*)"name";
55     const xmlChar* C_ATTR_ELT_REFERENCE = (xmlChar*)"reference";
56
57     const xmlChar* C_TAG_GROUPS = (xmlChar*)"groups";
58     const xmlChar* C_TAG_GROUP = (xmlChar*)"group";
59     const xmlChar* C_ATTR_GROUP_NAME = (xmlChar*)"name";
60     const xmlChar* C_ATTR_GROUP_DIM = (xmlChar*)"dimension";
61
62     const xmlChar* C_TAG_ELEMENT = (xmlChar*)"element";
63     const xmlChar* C_ATTR_ELEMENT_INDEX = (xmlChar*)"index";
64     const xmlChar* C_TAG_VALUE = (xmlChar*)"value";
65     const xmlChar* C_ATTR_VALUE_COMPONENT = (xmlChar*)"component";
66
67     const xmlChar* C_TAG_FIELDS = (xmlChar*)"fields";
68     const xmlChar* C_TAG_FIELD = (xmlChar*)"field";
69     const xmlChar* C_ATTR_FIELD_NAME = (xmlChar*)"name";
70     const xmlChar* C_ATTR_FIELD_TYPE = (xmlChar*)"type";
71     const xmlChar* C_ATTR_FIELD_DIMENSION = (xmlChar*)"dimension";
72     const xmlChar* C_TAG_COMPONENTS = (xmlChar*)"components";
73     const xmlChar* C_TAG_COMPONENT = (xmlChar*)"component";
74     const xmlChar* C_ATTR_COMPONENT_COLUMN = (xmlChar*)"column";
75     const xmlChar* C_ATTR_COMPONENT_NAME = (xmlChar*)"name";
76
77     const xmlChar* C_TAG_STEPS = (xmlChar*)"steps";
78     const xmlChar* C_TAG_STEP = (xmlChar*)"step";
79     const xmlChar* C_ATTR_STEP_NUMBER = (xmlChar*)"number";
80     const xmlChar* C_ATTR_STEP_STAMP = (xmlChar*)"stamp";
81 }
82
83 using namespace XAO;
84
85 namespace {
86     xmlDocPtr exportXMLDoc(Xao* xaoObject);
87     void exportGeometry(Geometry* xaoGeometry, xmlDocPtr doc, xmlNodePtr xao);
88     void exportGeometricElements(Geometry* xaoGeometry, xmlNodePtr topology,
89                                  XAO::Dimension dim, const xmlChar* colTag, const xmlChar* eltTag);
90     void exportGroups(Xao* xaoObject, xmlNodePtr xao);
91     void exportFields(Xao* xaoObject, xmlNodePtr xao);
92     void exportStep(Step* step, Field* field, xmlNodePtr nodeSteps);
93
94     void parseXMLDoc(xmlDocPtr doc, Xao* xaoObject);
95     void parseXaoNode(xmlDocPtr doc, xmlNodePtr xaoNode, Xao* xaoObject);
96     void parseGeometryNode(xmlDocPtr doc, xmlNodePtr geometryNode, Xao* xaoObject);
97     void parseShapeNode(xmlDocPtr doc, xmlNodePtr shapeNode, Geometry* geometry);
98     void parseTopologyNode(xmlNodePtr topologyNode, Geometry* geometry);
99     void parseVerticesNode(xmlNodePtr verticesNode, Geometry* geometry);
100     void parseEdgesNode(xmlNodePtr edgesNode, Geometry* geometry);
101     void parseFacesNode(xmlNodePtr facesNode, Geometry* geometry);
102     void parseSolidsNode(xmlNodePtr solidsNode, Geometry* geometry);
103     void parseGroupsNode(xmlNodePtr groupsNode, Xao* xaoObject);
104     void parseGroupNode(xmlNodePtr groupNode, Xao* xaoObject);
105
106     void parseFieldsNode(xmlNodePtr fieldsNode, Xao* xaoObject);
107     void parseFieldNode(xmlNodePtr fieldNode, Xao* xaoObject);
108     void parseStepNode(xmlNodePtr stepNode, Field* field);
109     void parseStepElementNode(xmlNodePtr eltNode, Step* step);
110
111     std::string readStringProp(xmlNodePtr node, const xmlChar* attribute,
112                                const bool& required, const std::string& defaultValue, const std::string& exception = std::string(""));
113     int readIntegerProp(xmlNodePtr node, const xmlChar* attribute,
114                         const bool& required, const int& defaultValue, const std::string& exception = std::string(""));
115
116   std::string readStringProp(xmlNodePtr node, const xmlChar* attribute,
117                              const bool& required, const std::string& defaultValue,
118                              const std::string& exception /*= std::string() */)
119   {
120     xmlChar* strAttr = xmlGetProp(node, attribute);
121     if (strAttr == NULL)
122     {
123         if (required)
124         {
125             if (exception.size() > 0)
126                 throw XAO_Exception(exception.c_str());
127
128             throw XAO_Exception(MsgBuilder() << "Line " << node->line << ": "
129                                              << "Property " << (char*)attribute << " is required.");
130         }
131
132         return defaultValue;
133     }
134
135     std::string res = (char*)strAttr;
136     xmlFree(strAttr);
137     return res;
138   }
139
140   int readIntegerProp(xmlNodePtr node, const xmlChar* attribute,
141                       const bool& required, const int& defaultValue,
142                       const std::string& exception /*= std::string() */)
143   {
144     xmlChar* strAttr = xmlGetProp(node, attribute);
145     if (strAttr == NULL)
146     {
147         if (required)
148         {
149             if (exception.size() > 0)
150                 throw XAO_Exception(exception.c_str());
151
152             throw XAO_Exception(MsgBuilder() << "Line " << node->line << ": "
153                                              << "Property " << (char*)attribute << " is required.");
154         }
155
156         return defaultValue;
157     }
158
159     int res = XaoUtils::stringToInt((char*)strAttr);
160     xmlFree(strAttr);
161     return res;
162   }
163
164   xmlDocPtr exportXMLDoc(Xao* xaoObject)
165   {
166     // Creating the Xml document
167     xmlDocPtr masterDocument = xmlNewDoc(BAD_CAST "1.0");
168     xmlNodePtr xao = xmlNewNode(0, C_TAG_XAO);
169     xmlDocSetRootElement(masterDocument, xao);
170
171     xmlNewProp(xao, C_ATTR_XAO_VERSION, BAD_CAST xaoObject->getVersion().c_str());
172     xmlNewProp(xao, C_ATTR_XAO_AUTHOR, BAD_CAST xaoObject->getAuthor().c_str());
173
174     if (xaoObject->getGeometry() != NULL)
175     {
176         exportGeometry(xaoObject->getGeometry(), masterDocument, xao);
177     }
178
179     exportGroups(xaoObject, xao);
180     exportFields(xaoObject, xao);
181
182     return masterDocument;
183   }
184
185   void exportGeometricElements(Geometry* xaoGeometry,
186                                xmlNodePtr topology, XAO::Dimension dim, const xmlChar* colTag, const xmlChar* eltTag)
187   {
188     xmlNodePtr vertices = xmlNewChild(topology, 0, colTag, 0);
189     xmlNewProp(vertices, C_ATTR_COUNT, BAD_CAST XaoUtils::intToString(xaoGeometry->countElements(dim)).c_str());
190     GeometricElementList::iterator it = xaoGeometry->begin(dim);
191     for (; it != xaoGeometry->end(dim); it++)
192     {
193         int index = it->first;
194         GeometricElement elt = it->second;
195         xmlNodePtr vertex = xmlNewChild(vertices, 0, eltTag, 0);
196         xmlNewProp(vertex, C_ATTR_ELT_INDEX, BAD_CAST XaoUtils::intToString(index).c_str());
197         xmlNewProp(vertex, C_ATTR_ELT_NAME, BAD_CAST elt.getName().c_str());
198         xmlNewProp(vertex, C_ATTR_ELT_REFERENCE, BAD_CAST elt.getReference().c_str());
199     }
200   }
201
202   void exportGeometry(Geometry* xaoGeometry, xmlDocPtr doc, xmlNodePtr xao)
203   {
204     // Geometric part
205     xmlNodePtr geometry = xmlNewChild(xao, 0, C_TAG_GEOMETRY, 0);
206     xmlNewProp(geometry, C_ATTR_GEOMETRY_NAME, BAD_CAST xaoGeometry->getName().c_str());
207
208     xmlNodePtr shape = xmlNewChild(geometry, 0, C_TAG_SHAPE, 0);
209     xmlNewProp(shape, C_ATTR_SHAPE_FORMAT, BAD_CAST XaoUtils::shapeFormatToString(xaoGeometry->getFormat()).c_str());
210     std::string txtShape = xaoGeometry->getShapeString();
211     xmlNodePtr cdata = xmlNewCDataBlock(doc, BAD_CAST txtShape.c_str(), txtShape.size());
212     xmlAddChild(shape, cdata);
213
214     xmlNodePtr topology = xmlNewChild(geometry, 0, C_TAG_TOPOLOGY, 0);
215
216     exportGeometricElements(xaoGeometry, topology, XAO::VERTEX, C_TAG_VERTICES, C_TAG_VERTEX);
217     exportGeometricElements(xaoGeometry, topology, XAO::EDGE, C_TAG_EDGES, C_TAG_EDGE);
218     exportGeometricElements(xaoGeometry, topology, XAO::FACE, C_TAG_FACES, C_TAG_FACE);
219     exportGeometricElements(xaoGeometry, topology, XAO::SOLID, C_TAG_SOLIDS, C_TAG_SOLID);
220   }
221
222   void exportGroups(Xao* xaoObject, xmlNodePtr xao)
223   {
224     xmlNodePtr groups = xmlNewChild(xao, 0, C_TAG_GROUPS, 0);
225     xmlNewProp(groups, C_ATTR_COUNT, BAD_CAST XaoUtils::intToString(xaoObject->countGroups()).c_str());
226
227     for (int i = 0; i < xaoObject->countGroups(); i++)
228     {
229         //Group* grp = (*it);
230         Group* grp = xaoObject->getGroup(i);
231         xmlNodePtr group = xmlNewChild(groups, 0, C_TAG_GROUP, 0);
232         xmlNewProp(group, C_ATTR_GROUP_NAME, BAD_CAST grp->getName().c_str());
233         xmlNewProp(group, C_ATTR_GROUP_DIM, BAD_CAST XaoUtils::dimensionToString(grp->getDimension()).c_str());
234         xmlNewProp(group, C_ATTR_COUNT, BAD_CAST XaoUtils::intToString(grp->count()).c_str());
235
236         for (std::set<int>::iterator it = grp->begin(); it != grp->end(); ++it)
237         {
238             int grpElt = (*it);
239             xmlNodePtr elt = xmlNewChild(group, 0, C_TAG_ELEMENT, 0);
240             xmlNewProp(elt, C_ATTR_ELEMENT_INDEX, BAD_CAST XaoUtils::intToString(grpElt).c_str());
241         }
242     }
243   }
244
245   void exportFields(Xao* xaoObject, xmlNodePtr xao)
246   {
247     xmlNodePtr fields = xmlNewChild(xao, 0, C_TAG_FIELDS, 0);
248     xmlNewProp(fields, C_ATTR_COUNT, BAD_CAST XaoUtils::intToString(xaoObject->countFields()).c_str());
249
250     for (int i = 0; i < xaoObject->countFields(); i++)
251     {
252         Field* field = xaoObject->getField(i);
253         xmlNodePtr nodeField = xmlNewChild(fields, 0, C_TAG_FIELD, 0);
254         xmlNewProp(nodeField, C_ATTR_FIELD_NAME, BAD_CAST field->getName().c_str());
255         xmlNewProp(nodeField, C_ATTR_FIELD_TYPE, BAD_CAST XaoUtils::fieldTypeToString(field->getType()).c_str());
256         xmlNewProp(nodeField, C_ATTR_FIELD_DIMENSION, BAD_CAST XaoUtils::dimensionToString(field->getDimension()).c_str());
257
258         int nbComponents = field->countComponents();
259         xmlNodePtr components = xmlNewChild(nodeField, 0, C_TAG_COMPONENTS, 0);
260         xmlNewProp(components, C_ATTR_COUNT, BAD_CAST XaoUtils::intToString(nbComponents).c_str());
261
262         for (int j = 0; j < nbComponents; j++)
263         {
264             xmlNodePtr nodeComponent = xmlNewChild(components, 0, C_TAG_COMPONENT, 0);
265             xmlNewProp(nodeComponent, C_ATTR_COMPONENT_COLUMN, BAD_CAST XaoUtils::intToString(j).c_str());
266             xmlNewProp(nodeComponent, C_ATTR_COMPONENT_NAME, BAD_CAST field->getComponentName(j).c_str());
267         }
268
269         int nbSteps = field->countSteps();
270         xmlNodePtr nodeSteps = xmlNewChild(nodeField, 0, C_TAG_STEPS, 0);
271         xmlNewProp(nodeSteps, C_ATTR_COUNT, BAD_CAST XaoUtils::intToString(nbSteps).c_str());
272         for (stepIterator itStep = field->begin(); itStep != field->end(); itStep++)
273         {
274             Step* step = *itStep;
275             exportStep(step, field, nodeSteps);
276         }
277     }
278   }
279
280   void exportStep(Step* step, Field* field, xmlNodePtr nodeSteps)
281   {
282     xmlNodePtr nodeStep = xmlNewChild(nodeSteps, 0, C_TAG_STEP, 0);
283     xmlNewProp(nodeStep, C_ATTR_STEP_NUMBER, BAD_CAST XaoUtils::intToString(step->getStep()).c_str());
284     if (step->getStamp() >= 0)
285     {
286         xmlNewProp(nodeStep, C_ATTR_STEP_STAMP, BAD_CAST XaoUtils::intToString(step->getStamp()).c_str());
287     }
288
289     for(int i = 0; i < step->countElements(); ++i)
290     {
291         xmlNodePtr nodeElt = xmlNewChild(nodeStep, 0, C_TAG_ELEMENT, 0);
292         xmlNewProp(nodeElt, C_ATTR_ELEMENT_INDEX, BAD_CAST XaoUtils::intToString(i).c_str());
293
294         for (int j = 0; j < step->countComponents(); ++j)
295         {
296             std::string content = step->getStringValue(i, j);
297             xmlNodePtr nodeValue = xmlNewChild(nodeElt, NULL, C_TAG_VALUE, BAD_CAST content.c_str());
298             xmlNewProp(nodeValue, C_ATTR_VALUE_COMPONENT, BAD_CAST XaoUtils::intToString(j).c_str());
299         }
300     }
301   }
302
303   void parseXMLDoc(xmlDocPtr doc, Xao* xaoObject)
304   {
305     // Get the root element node
306     xmlNodePtr root = xmlDocGetRootElement(doc);
307     if (xmlStrcmp(root->name , C_TAG_XAO) != 0)
308         throw XAO_Exception("Cannot read XAO file: invalid format XAO node not found");
309
310     parseXaoNode(doc, root, xaoObject);
311
312     xmlFreeDoc(doc);       // free document
313     //xmlCleanupParser();    // free globals //vsr: xmlCleanupParser should not be called from the application
314   }
315
316   void parseXaoNode(xmlDocPtr doc, xmlNodePtr xaoNode, Xao* xaoObject)
317   {
318     std::string version = readStringProp(xaoNode, C_ATTR_XAO_VERSION, false, "");
319     if (version != "")
320         xaoObject->setVersion(version);
321
322     std::string author = readStringProp(xaoNode, C_ATTR_XAO_AUTHOR, false, "");
323     xaoObject->setAuthor(author);
324
325     for (xmlNodePtr node = xaoNode->children; node; node = node->next)
326     {
327         if (xmlStrcmp(node->name, C_TAG_GEOMETRY) == 0)
328             parseGeometryNode(doc, node, xaoObject);
329         else if (xmlStrcmp(node->name, C_TAG_GROUPS) == 0)
330             parseGroupsNode(node, xaoObject);
331         else if (xmlStrcmp(node->name, C_TAG_FIELDS) == 0)
332             parseFieldsNode(node, xaoObject);
333     }
334   }
335
336   void parseGeometryNode(xmlDocPtr doc, xmlNodePtr geometryNode, Xao* xaoObject)
337   {
338     // get the shape and topo nodes
339     xmlNodePtr shapeNode = NULL;
340     xmlNodePtr topoNode = NULL;
341     for (xmlNodePtr node = geometryNode->children; node; node = node->next)
342     {
343         if (xmlStrcmp(node->name, C_TAG_SHAPE) == 0)
344             shapeNode = node;
345         else if (xmlStrcmp(node->name, C_TAG_TOPOLOGY) == 0)
346             topoNode = node;
347     }
348
349     std::string name = readStringProp(geometryNode, C_ATTR_GEOMETRY_NAME, false, "");
350     std::string strFormat = readStringProp(shapeNode, C_ATTR_SHAPE_FORMAT, true, "");
351     XAO::Format shapeFormat = XaoUtils::stringToShapeFormat(strFormat);
352     Geometry* geometry = Geometry::createGeometry(shapeFormat, name);
353
354     parseShapeNode(doc, shapeNode, geometry);
355     parseTopologyNode(topoNode, geometry);
356
357     xaoObject->setGeometry(geometry);
358   }
359
360   void parseShapeNode(xmlDocPtr doc, xmlNodePtr shapeNode, Geometry* geometry)
361   {
362     if (geometry->getFormat() == XAO::BREP)
363     {
364         xmlChar* data = xmlNodeGetContent(shapeNode->children);
365         if (data == NULL)
366             throw XAO_Exception("Missing BREP");
367         geometry->setShapeString((char*)data);
368         xmlFree(data);
369     }
370     else
371     {
372         throw XAO_Exception(MsgBuilder() << "Shape format not supported: "
373                                          << XaoUtils::shapeFormatToString(geometry->getFormat()));
374     }
375   }
376
377   void parseTopologyNode(xmlNodePtr topologyNode, Geometry* geometry)
378   {
379     for (xmlNodePtr node = topologyNode->children; node; node = node->next)
380     {
381         if (xmlStrcmp(node->name, C_TAG_VERTICES) == 0)
382             parseVerticesNode(node, geometry);
383         else if (xmlStrcmp(node->name, C_TAG_EDGES) == 0)
384             parseEdgesNode(node, geometry);
385         else if (xmlStrcmp(node->name, C_TAG_FACES) == 0)
386             parseFacesNode(node, geometry);
387         else if (xmlStrcmp(node->name, C_TAG_SOLIDS) == 0)
388             parseSolidsNode(node, geometry);
389     }
390   }
391
392   void parseVerticesNode(xmlNodePtr verticesNode, Geometry* geometry)
393   {
394     int count = readIntegerProp(verticesNode, C_ATTR_COUNT, true, -1);
395     geometry->setCountVertices(count);
396
397     for (xmlNodePtr node = verticesNode->children; node; node = node->next)
398     {
399         if (xmlStrcmp(node->name, C_TAG_VERTEX) == 0)
400         {
401             int index = readIntegerProp(node, C_ATTR_ELT_INDEX, true, -1);
402             std::string name = readStringProp(node, C_ATTR_ELT_NAME, false, "");
403             std::string reference = readStringProp(node, C_ATTR_ELT_REFERENCE, true, "");
404
405             geometry->setVertex(index, name, reference);
406         }
407     }
408   }
409
410   void parseEdgesNode(xmlNodePtr edgesNode, Geometry* geometry)
411   {
412     int count = readIntegerProp(edgesNode, C_ATTR_COUNT, true, -1);
413     geometry->setCountEdges(count);
414
415     for (xmlNodePtr node = edgesNode->children; node; node = node->next)
416     {
417         if (xmlStrcmp(node->name, C_TAG_EDGE) == 0)
418         {
419             int index = readIntegerProp(node, C_ATTR_ELT_INDEX, true, -1);
420             std::string name = readStringProp(node, C_ATTR_ELT_NAME, false, "");
421             std::string reference = readStringProp(node, C_ATTR_ELT_REFERENCE, true, "");
422
423             geometry->setEdge(index, name, reference);
424         }
425     }
426   }
427
428   void parseFacesNode(xmlNodePtr facesNode, Geometry* geometry)
429   {
430     int count = readIntegerProp(facesNode, C_ATTR_COUNT, true, -1);
431     geometry->setCountFaces(count);
432
433     for (xmlNodePtr node = facesNode->children; node; node = node->next)
434     {
435         if (xmlStrcmp(node->name, C_TAG_FACE) == 0)
436         {
437             int index = readIntegerProp(node, C_ATTR_ELT_INDEX, true, -1);
438             std::string name = readStringProp(node, C_ATTR_ELT_NAME, false, "");
439             std::string reference = readStringProp(node, C_ATTR_ELT_REFERENCE, true, "");
440
441             geometry->setFace(index, name, reference);
442         }
443     }
444   }
445
446   void parseSolidsNode(xmlNodePtr solidsNode, Geometry* geometry)
447   {
448     int count = readIntegerProp(solidsNode, C_ATTR_COUNT, true, -1);
449     geometry->setCountSolids(count);
450
451     for (xmlNodePtr node = solidsNode->children; node; node = node->next)
452     {
453         if (xmlStrcmp(node->name, C_TAG_SOLID) == 0)
454         {
455             int index = readIntegerProp(node, C_ATTR_ELT_INDEX, true, -1);
456             std::string name = readStringProp(node, C_ATTR_ELT_NAME, false, "");
457             std::string reference = readStringProp(node, C_ATTR_ELT_REFERENCE, true, "");
458
459             geometry->setSolid(index, name, reference);
460         }
461     }
462   }
463
464   void parseGroupsNode(xmlNodePtr groupsNode, Xao* xaoObject)
465   {
466     for (xmlNodePtr node = groupsNode->children; node; node = node->next)
467     {
468         if (xmlStrcmp(node->name, C_TAG_GROUP) == 0)
469         {
470             parseGroupNode(node, xaoObject);
471         }
472     }
473   }
474
475   void parseGroupNode(xmlNodePtr groupNode, Xao* xaoObject)
476   {
477     std::string strDimension = readStringProp(groupNode, C_ATTR_GROUP_DIM, true, "");
478     XAO::Dimension dim = XaoUtils::stringToDimension(strDimension);
479     Group* group = xaoObject->addGroup(dim);
480
481     std::string name = readStringProp(groupNode, C_ATTR_GROUP_NAME, false, "");
482     group->setName(name);
483
484     for (xmlNodePtr node = groupNode->children; node; node = node->next)
485     {
486         if (xmlStrcmp(node->name, C_TAG_ELEMENT) == 0)
487         {
488             int index = readIntegerProp(node, C_ATTR_ELEMENT_INDEX, true, -1);
489             group->add(index);
490         }
491     }
492   }
493
494   void parseFieldsNode(xmlNodePtr fieldsNode, Xao* xaoObject)
495   {
496     for (xmlNodePtr node = fieldsNode->children; node; node = node->next)
497     {
498         if (xmlStrcmp(node->name, C_TAG_FIELD) == 0)
499         {
500             parseFieldNode(node, xaoObject);
501         }
502     }
503   }
504
505   void parseFieldNode(xmlNodePtr fieldNode, Xao* xaoObject)
506   {
507     std::string strDimension = readStringProp(fieldNode, C_ATTR_FIELD_DIMENSION, true, "");
508     XAO::Dimension dim = XaoUtils::stringToDimension(strDimension);
509
510     std::string strType = readStringProp(fieldNode, C_ATTR_FIELD_TYPE, true, "");
511     XAO::Type type = XaoUtils::stringToFieldType(strType);
512
513     // we need to get the number of components first to create the field
514     xmlNodePtr componentsNode = NULL;
515     xmlNodePtr stepsNode = NULL;
516
517     for (xmlNodePtr node = fieldNode->children; node; node = node->next)
518     {
519         if (xmlStrcmp(node->name, C_TAG_COMPONENTS) == 0)
520             componentsNode = node;
521         else if (xmlStrcmp(node->name, C_TAG_STEPS) == 0)
522             stepsNode = node;
523     }
524
525     // ensure that the components node is defined
526     if (componentsNode == NULL)
527     {
528         throw XAO_Exception(MsgBuilder() << "Line " << fieldNode->line << ": "
529                                          << "No components defined for field.");
530     }
531
532     // create the field
533     int nbComponents = readIntegerProp(componentsNode, C_ATTR_COUNT, true, -1);
534     Field* field = xaoObject->addField(type, dim, nbComponents);
535
536     // parse the components
537     for (xmlNodePtr compNode = componentsNode->children; compNode; compNode = compNode->next)
538     {
539         std::string compName= readStringProp(compNode, C_ATTR_COMPONENT_NAME, false, "");
540         if (compName.size() > 0)
541         {
542             int col = readIntegerProp(compNode, C_ATTR_COMPONENT_COLUMN, true, -1);
543             field->setComponentName(col, compName);
544         }
545     }
546
547     // set the name
548     std::string name = readStringProp(fieldNode, C_ATTR_FIELD_NAME, false, "");
549     if (name.size() > 0) field->setName(name);
550
551     // read the steps
552     if (stepsNode != 0)
553     {
554         for (xmlNodePtr stepNode = stepsNode->children; stepNode; stepNode = stepNode->next)
555         {
556             if (xmlStrcmp(stepNode->name, C_TAG_STEP) == 0)
557             {
558                 parseStepNode(stepNode, field);
559             }
560         }
561     }
562   }
563
564   void parseStepNode(xmlNodePtr stepNode, Field* field)
565   {
566     int stepNumber = readIntegerProp(stepNode, C_ATTR_STEP_NUMBER, true, -1);
567     Step* step = field->addNewStep(stepNumber);
568
569     int stepStamp = readIntegerProp(stepNode, C_ATTR_STEP_STAMP, false, -1);
570     if (stepStamp != -1)
571     {
572         step->setStamp(stepStamp);
573     }
574
575     for (xmlNodePtr eltNode = stepNode->children; eltNode; eltNode = eltNode->next)
576     {
577         if (xmlStrcmp(eltNode->name, C_TAG_ELEMENT) == 0)
578         {
579             parseStepElementNode(eltNode, step);
580         }
581     }
582   }
583
584   void parseStepElementNode(xmlNodePtr eltNode, Step* step)
585   {
586     int index = readIntegerProp(eltNode, C_ATTR_ELT_INDEX, true, -1);
587
588     for (xmlNodePtr valNode = eltNode->children; valNode; valNode = valNode->next)
589     {
590         if (xmlStrcmp(valNode->name, C_TAG_VALUE) == 0)
591         {
592             int component = readIntegerProp(valNode, C_ATTR_VALUE_COMPONENT, true, -1);
593             xmlChar* data = xmlNodeGetContent(valNode->children);
594
595             std::string value;
596             if (data != NULL)
597             {
598                 value = (char*)data;
599             }
600             else if (step->getType() != XAO::STRING)
601             {
602                 throw XAO_Exception(MsgBuilder() << "Line " << valNode->line << ": no content for value.");
603             }
604
605             step->setStringValue(index, component, value);
606         }
607     }
608   }
609 }
610
611 const bool XaoExporter::saveToFile(Xao* xaoObject, const std::string& fileName)
612 throw (XAO_Exception)
613 {
614     xmlDocPtr doc = exportXMLDoc(xaoObject);
615     xmlSaveFormatFileEnc(fileName.c_str(), doc, "UTF-8", 1); // format = 1 for node indentation
616     xmlFreeDoc(doc);
617
618     return true;
619 }
620
621 const std::string XaoExporter::saveToXml(Xao* xaoObject)
622 throw (XAO_Exception)
623 {
624     xmlDocPtr doc = exportXMLDoc(xaoObject);
625
626     xmlChar *xmlbuff;
627     int buffersize;
628     xmlDocDumpFormatMemory(doc, &xmlbuff, &buffersize, 1); // format = 1 for node indentation
629     xmlFreeDoc(doc);
630     xmlCleanupGlobals();
631
632     return (char*)xmlbuff;
633 }
634
635 const bool XaoExporter::readFromFile(const std::string& fileName, Xao* xaoObject)
636 throw (XAO_Exception)
637 {
638     // parse the file and get the DOM
639     int options = XML_PARSE_HUGE | XML_PARSE_NOCDATA;
640     xmlDocPtr doc = xmlReadFile(fileName.c_str(), NULL, options);
641     if (doc == NULL)
642     {
643         throw XAO_Exception("Cannot read XAO file");
644     }
645
646     parseXMLDoc(doc, xaoObject);
647     return true;
648 }
649
650 const bool XaoExporter::setXML(const std::string& xml, Xao* xaoObject)
651 throw (XAO_Exception)
652 {
653     int options = XML_PARSE_HUGE | XML_PARSE_NOCDATA;
654     xmlDocPtr doc = xmlReadDoc(BAD_CAST xml.c_str(), "", NULL, options);
655     if (doc == NULL)
656     {
657         throw XAO_Exception("Cannot read XAO stream");
658     }
659
660     parseXMLDoc(doc, xaoObject);
661     return true;
662 }