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