]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/input_output/FGXMLElement.cpp
Merge commit 'refs/merge-requests/1551' of git://gitorious.org/fg/flightgear into...
[flightgear.git] / src / FDM / JSBSim / input_output / FGXMLElement.cpp
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
3  Author:       Jon Berndt
4  Date started: 09/28/2004
5  Purpose:      XML element class
6  Called by:    FGXMLParse
7
8  ------------- Copyright (C) 2001  Jon S. Berndt (jon@jsbsim.org) -------------
9
10  This program is free software; you can redistribute it and/or modify it under
11  the terms of the GNU Lesser General Public License as published by the Free Software
12  Foundation; either version 2 of the License, or (at your option) any later
13  version.
14
15  This program is distributed in the hope that it will be useful, but WITHOUT
16  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17  FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
18  details.
19
20  You should have received a copy of the GNU Lesser General Public License along with
21  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
22  Place - Suite 330, Boston, MA  02111-1307, USA.
23
24  Further information about the GNU Lesser General Public License can also be found on
25  the world wide web at http://www.gnu.org.
26
27 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
28 INCLUDES
29 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
30
31 #include "FGXMLElement.h"
32
33 #include <cmath>
34 #include <cstdlib>
35 #include <iostream>
36
37 using namespace std;
38
39 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
40 FORWARD DECLARATIONS
41 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
42
43 namespace JSBSim {
44
45 static const char *IdSrc = "$Id: FGXMLElement.cpp,v 1.29 2010/03/18 13:18:31 jberndt Exp $";
46 static const char *IdHdr = ID_XMLELEMENT;
47
48 bool Element::converterIsInitialized = false;
49 map <string, map <string, double> > Element::convert;
50
51 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
52 CLASS IMPLEMENTATION
53 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
54
55 Element::Element(const string& nm)
56 {
57   name   = nm;
58   parent = 0L;
59   element_index = 0;
60
61   if (!converterIsInitialized) {
62     converterIsInitialized = true;
63     // convert ["from"]["to"] = factor, so: from * factor = to
64     // Length
65     convert["M"]["FT"] = 3.2808399;
66     convert["FT"]["M"] = 1.0/convert["M"]["FT"];
67     convert["FT"]["IN"] = 12.0;
68     convert["IN"]["FT"] = 1.0/convert["FT"]["IN"];
69     convert["IN"]["M"] = convert["IN"]["FT"] * convert["FT"]["M"];
70     convert["M"]["IN"] = convert["M"]["FT"] * convert["FT"]["IN"];
71     // Area
72     convert["M2"]["FT2"] = convert["M"]["FT"]*convert["M"]["FT"];
73     convert["FT2"]["M2"] = 1.0/convert["M2"]["FT2"];
74     convert["M2"]["IN2"] = convert["M"]["IN"]*convert["M"]["IN"];
75     convert["IN2"]["M2"] = 1.0/convert["M2"]["IN2"];
76     convert["FT2"]["IN2"] = 144.0;
77     convert["IN2"]["FT2"] = 1.0/convert["FT2"]["IN2"];
78     // Volume
79     convert["IN3"]["CC"] = 16.387064;
80     convert["CC"]["IN3"] = 1.0/convert["IN3"]["CC"];
81     convert["FT3"]["IN3"] = 1728.0;
82     convert["IN3"]["FT3"] = 1.0/convert["FT3"]["IN3"];
83     convert["M3"]["FT3"] = 35.3146667;
84     convert["FT3"]["M3"] = 1.0/convert["M3"]["FT3"];
85     convert["LTR"]["IN3"] = 61.0237441;
86     convert["IN3"]["LTR"] = 1.0/convert["LTR"]["IN3"];
87     // Mass & Weight
88     convert["LBS"]["KG"] = 0.45359237;
89     convert["KG"]["LBS"] = 1.0/convert["LBS"]["KG"];
90     convert["SLUG"]["KG"] = 14.59390;
91     convert["KG"]["SLUG"] = 1.0/convert["SLUG"]["KG"];
92     // Moments of Inertia
93     convert["SLUG*FT2"]["KG*M2"] = 1.35594;
94     convert["KG*M2"]["SLUG*FT2"] = 1.0/convert["SLUG*FT2"]["KG*M2"];
95     // Angles
96     convert["RAD"]["DEG"] = 360.0/(2.0*3.1415926);
97     convert["DEG"]["RAD"] = 1.0/convert["RAD"]["DEG"];
98     // Spring force
99     convert["LBS/FT"]["N/M"] = 14.5939;
100     convert["N/M"]["LBS/FT"] = 1.0/convert["LBS/FT"]["N/M"];
101     // Damping force
102     convert["LBS/FT/SEC"]["N/M/SEC"] = 14.5939;
103     convert["N/M/SEC"]["LBS/FT/SEC"] = 1.0/convert["LBS/FT/SEC"]["N/M/SEC"];
104     // Damping force (Square Law)
105     convert["LBS/FT2/SEC2"]["N/M2/SEC2"] = 47.880259;
106     convert["N/M2/SEC2"]["LBS/FT2/SEC2"] = 1.0/convert["LBS/FT2/SEC2"]["N/M2/SEC2"];
107     // Power
108     convert["WATTS"]["HP"] = 0.001341022;
109     convert["HP"]["WATTS"] = 1.0/convert["WATTS"]["HP"];
110     // Force
111     convert["N"]["LBS"] = 0.22482;
112     convert["LBS"]["N"] = 1.0/convert["N"]["LBS"];
113     // Velocity
114     convert["KTS"]["FT/SEC"] = 1.68781;
115     convert["FT/SEC"]["KTS"] = 1.0/convert["KTS"]["FT/SEC"];
116     convert["M/S"]["FT/S"] = 3.2808399;
117     convert["M/SEC"]["FT/SEC"] = 3.2808399;
118     convert["FT/S"]["M/S"] = 1.0/convert["M/S"]["FT/S"];
119     convert["M/SEC"]["FT/SEC"] = 3.2808399;
120     convert["FT/SEC"]["M/SEC"] = 1.0/convert["M/SEC"]["FT/SEC"];
121     // Torque
122     convert["FT*LBS"]["N*M"] = 1.35581795;
123     convert["N*M"]["FT*LBS"] = 1/convert["FT*LBS"]["N*M"];
124     // Valve
125     convert["M4*SEC/KG"]["FT4*SEC/SLUG"] = convert["M"]["FT"]*convert["M"]["FT"]*
126       convert["M"]["FT"]*convert["M"]["FT"]/convert["KG"]["SLUG"];
127     convert["FT4*SEC/SLUG"]["M4*SEC/KG"] =
128       1.0/convert["M4*SEC/KG"]["FT4*SEC/SLUG"];
129     // Pressure
130     convert["INHG"]["PSF"] = 70.7180803;
131     convert["PSF"]["INHG"] = 1.0/convert["INHG"]["PSF"];
132     convert["ATM"]["INHG"] = 29.9246899;
133     convert["INHG"]["ATM"] = 1.0/convert["ATM"]["INHG"];
134     convert["PSI"]["INHG"] = 2.03625437;
135     convert["INHG"]["PSI"] = 1.0/convert["PSI"]["INHG"];
136     convert["INHG"]["PA"] = 3386.0; // inches Mercury to pascals
137     convert["PA"]["INHG"] = 1.0/convert["INHG"]["PA"];
138     convert["LBS/FT2"]["N/M2"] = 14.5939/convert["FT"]["M"];
139     convert["N/M2"]["LBS/FT2"] = 1.0/convert["LBS/FT2"]["N/M2"];
140     convert["LBS/FT2"]["PA"] = convert["LBS/FT2"]["N/M2"];
141     convert["PA"]["LBS/FT2"] = 1.0/convert["LBS/FT2"]["PA"];
142     // Mass flow
143     convert["KG/MIN"]["LBS/MIN"] = convert["KG"]["LBS"];
144     // Fuel Consumption
145     convert["LBS/HP*HR"]["KG/KW*HR"] = 0.6083;
146     convert["KG/KW*HR"]["LBS/HP*HR"] = 1.0/convert["LBS/HP*HR"]["KG/KW*HR"];
147     // Density
148     convert["KG/L"]["LBS/GAL"] = 8.3454045;
149     convert["LBS/GAL"]["KG/L"] = 1.0/convert["KG/L"]["LBS/GAL"];
150
151     // Length
152     convert["M"]["M"] = 1.00;
153     convert["FT"]["FT"] = 1.00;
154     convert["IN"]["IN"] = 1.00;
155     // Area
156     convert["M2"]["M2"] = 1.00;
157     convert["FT2"]["FT2"] = 1.00;
158     // Volume
159     convert["IN3"]["IN3"] = 1.00;
160     convert["CC"]["CC"] = 1.0;
161     convert["M3"]["M3"] = 1.0;
162     convert["FT3"]["FT3"] = 1.0;
163     convert["LTR"]["LTR"] = 1.0;
164     // Mass & Weight
165     convert["KG"]["KG"] = 1.00;
166     convert["LBS"]["LBS"] = 1.00;
167     // Moments of Inertia
168     convert["KG*M2"]["KG*M2"] = 1.00;
169     convert["SLUG*FT2"]["SLUG*FT2"] = 1.00;
170     // Angles
171     convert["DEG"]["DEG"] = 1.00;
172     convert["RAD"]["RAD"] = 1.00;
173     // Spring force
174     convert["LBS/FT"]["LBS/FT"] = 1.00;
175     convert["N/M"]["N/M"] = 1.00;
176     // Damping force
177     convert["LBS/FT/SEC"]["LBS/FT/SEC"] = 1.00;
178     convert["N/M/SEC"]["N/M/SEC"] = 1.00;
179     // Damping force (Square law)
180     convert["LBS/FT2/SEC2"]["LBS/FT2/SEC2"] = 1.00;
181     convert["N/M2/SEC2"]["N/M2/SEC2"] = 1.00;
182     // Power
183     convert["HP"]["HP"] = 1.00;
184     convert["WATTS"]["WATTS"] = 1.00;
185     // Force
186     convert["N"]["N"] = 1.00;
187     // Velocity
188     convert["FT/SEC"]["FT/SEC"] = 1.00;
189     convert["KTS"]["KTS"] = 1.00;
190     convert["M/S"]["M/S"] = 1.0;
191     convert["M/SEC"]["M/SEC"] = 1.0;
192     // Torque
193     convert["FT*LBS"]["FT*LBS"] = 1.00;
194     convert["N*M"]["N*M"] = 1.00;
195     // Valve
196     convert["M4*SEC/KG"]["M4*SEC/KG"] = 1.0;
197     convert["FT4*SEC/SLUG"]["FT4*SEC/SLUG"] = 1.0;
198     // Pressure
199     convert["PSI"]["PSI"] = 1.00;
200     convert["PSF"]["PSF"] = 1.00;
201     convert["INHG"]["INHG"] = 1.00;
202     convert["ATM"]["ATM"] = 1.0;
203     convert["PA"]["PA"] = 1.0;
204     convert["N/M2"]["N/M2"] = 1.00;
205     convert["LBS/FT2"]["LBS/FT2"] = 1.00;
206     // Mass flow
207     convert["LBS/SEC"]["LBS/SEC"] = 1.00;
208     convert["KG/MIN"]["KG/MIN"] = 1.0;
209     convert["LBS/MIN"]["LBS/MIN"] = 1.0;
210     // Fuel Consumption
211     convert["LBS/HP*HR"]["LBS/HP*HR"] = 1.0;
212     convert["KG/KW*HR"]["KG/KW*HR"] = 1.0;
213     // Density
214     convert["KG/L"]["KG/L"] = 1.0;
215     convert["LBS/GAL"]["LBS/GAL"] = 1.0;
216   }
217 }
218
219 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
220
221 Element::~Element(void)
222 {
223   for (unsigned int i=0; i<children.size(); i++) delete children[i];
224   data_lines.clear();
225   attributes.clear();
226   attribute_key.clear();
227 }
228
229 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
230
231 string Element::GetAttributeValue(const string& attr)
232 {
233   int select=-1;
234   for (unsigned int i=0; i<attribute_key.size(); i++) {
235     if (attribute_key[i] == attr) select = i;
236   }
237   if (select < 0) return string("");
238   else return attributes[attr];
239 }
240
241 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
242
243 double Element::GetAttributeValueAsNumber(const string& attr)
244 {
245   string attribute = GetAttributeValue(attr);
246
247   if (attribute.empty()) return HUGE_VAL;
248   else return (atof(attribute.c_str()));
249 }
250
251 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
252
253 Element* Element::GetElement(unsigned int el)
254 {
255   if (children.size() > el) {
256     element_index = el;
257     return children[el];
258   }
259   else {
260     element_index = 0;
261     return 0L;
262   }
263 }
264
265 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
266
267 Element* Element::GetNextElement(void)
268 {
269   if (children.size() > element_index+1) {
270     element_index++;
271     return children[element_index];
272   } else {
273     element_index = 0;
274     return 0L;
275   }
276 }
277
278 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
279
280 string Element::GetDataLine(unsigned int i)
281 {
282   if (data_lines.size() > 0) return data_lines[i];
283   else return string("");
284 }
285
286 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
287
288 double Element::GetDataAsNumber(void)
289 {
290   if (data_lines.size() == 1) {
291     return atof(data_lines[0].c_str());
292   } else if (data_lines.size() == 0) {
293     return HUGE_VAL;
294   } else {
295     cerr << "Attempting to get single data value from multiple lines in element " << name << endl;
296     return HUGE_VAL;
297   }
298 }
299
300 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
301
302 unsigned int Element::GetNumElements(const string& element_name)
303 {
304   unsigned int number_of_elements=0;
305   Element* el=FindElement(element_name);
306   while (el) {
307     number_of_elements++;
308     el=FindNextElement(element_name);
309   }
310   return number_of_elements;
311 }
312
313 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
314
315 Element* Element::FindElement(const string& el)
316 {
317   if (el.empty() && children.size() >= 1) {
318     element_index = 1;
319     return children[0];
320   }
321   for (unsigned int i=0; i<children.size(); i++) {
322     if (el == children[i]->GetName()) {
323       element_index = i+1;
324       return children[i];
325     }
326   }
327   element_index = 0;
328   return 0L;
329 }
330
331 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
332
333 Element* Element::FindNextElement(const string& el)
334 {
335   if (el.empty()) {
336     if (element_index < children.size()) {
337       return children[element_index++];
338     } else {
339       element_index = 0;
340       return 0L;
341     }
342   }
343   for (unsigned int i=element_index; i<children.size(); i++) {
344     if (el == children[i]->GetName()) {
345       element_index = i+1;
346       return children[i];
347     }
348   }
349   element_index = 0;
350   return 0L;
351 }
352
353 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
354
355 double Element::FindElementValueAsNumber(const string& el)
356 {
357   Element* element = FindElement(el);
358   if (element) {
359     return element->GetDataAsNumber();
360   } else {
361     cerr << "Attempting to get single data value from multiple lines" << endl;
362     return 0;
363   }
364 }
365
366 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
367
368 string Element::FindElementValue(const string& el)
369 {
370   Element* element = FindElement(el);
371   if (element) {
372     return element->GetDataLine();
373   } else {
374     return "";
375   }
376 }
377
378 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
379
380 double Element::FindElementValueAsNumberConvertTo(const string& el, const string& target_units)
381 {
382   Element* element = FindElement(el);
383
384   if (!element) {
385     cerr << "Attempting to get non-existent element " << el << endl;
386     exit(0);
387   }
388
389   string supplied_units = element->GetAttributeValue("unit");
390
391   if (!supplied_units.empty()) {
392     if (convert.find(supplied_units) == convert.end()) {
393       cerr << endl << "Supplied unit: \"" << supplied_units << "\" does not exist (typo?). Add new unit"
394            << " conversion in FGXMLElement.cpp." << endl;
395       exit(-1);
396     }
397     if (convert[supplied_units].find(target_units) == convert[supplied_units].end()) {
398       cerr << endl << "Supplied unit: \"" << supplied_units << "\" cannot be converted to "
399                    << target_units << ". Add new unit conversion in FGXMLElement.cpp or fix typo" << endl;
400       exit(-1);
401     }
402   }
403
404   double value = element->GetDataAsNumber();
405   if (!supplied_units.empty()) {
406     value *= convert[supplied_units][target_units];
407   }
408
409   return value;
410 }
411
412 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
413
414 double Element::FindElementValueAsNumberConvertFromTo( const string& el,
415                                                        const string& supplied_units,
416                                                        const string& target_units)
417 {
418   Element* element = FindElement(el);
419
420   if (!element) {
421     cerr << "Attempting to get non-existent element " << el << endl;
422     exit(0);
423   }
424
425   if (!supplied_units.empty()) {
426     if (convert.find(supplied_units) == convert.end()) {
427       cerr << endl << "Supplied unit: \"" << supplied_units << "\" does not exist (typo?). Add new unit"
428            << " conversion in FGXMLElement.cpp." << endl;
429       exit(-1);
430     }
431     if (convert[supplied_units].find(target_units) == convert[supplied_units].end()) {
432       cerr << endl << "Supplied unit: \"" << supplied_units << "\" cannot be converted to "
433                    << target_units << ". Add new unit conversion in FGXMLElement.cpp or fix typo" << endl;
434       exit(-1);
435     }
436   }
437
438   double value = element->GetDataAsNumber();
439   if (!supplied_units.empty()) {
440     value *= convert[supplied_units][target_units];
441   }
442
443   return value;
444 }
445
446 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
447
448 FGColumnVector3 Element::FindElementTripletConvertTo( const string& target_units)
449 {
450   FGColumnVector3 triplet;
451   Element* item;
452   double value=0.0;
453   string supplied_units = GetAttributeValue("unit");
454
455   if (!supplied_units.empty()) {
456     if (convert.find(supplied_units) == convert.end()) {
457       cerr << endl << "Supplied unit: \"" << supplied_units << "\" does not exist (typo?). Add new unit"
458            << " conversion in FGXMLElement.cpp." << endl;
459       exit(-1);
460     }
461     if (convert[supplied_units].find(target_units) == convert[supplied_units].end()) {
462       cerr << endl << "Supplied unit: \"" << supplied_units << "\" cannot be converted to "
463                    << target_units << ". Add new unit conversion in FGXMLElement.cpp or fix typo" << endl;
464       exit(-1);
465     }
466   }
467
468   item = FindElement("x");
469   if (!item) item = FindElement("roll");
470   if (item) {
471     value = item->GetDataAsNumber();
472     if (!supplied_units.empty()) value *= convert[supplied_units][target_units];
473   } else {
474     value = 0.0;
475     cerr << "Could not find an X triplet item for this column vector." << endl;
476   }
477   triplet(1) = value;
478
479   item = FindElement("y");
480   if (!item) item = FindElement("pitch");
481   if (item) {
482     value = item->GetDataAsNumber();
483     if (!supplied_units.empty()) value *= convert[supplied_units][target_units];
484   } else {
485     value = 0.0;
486     cerr << "Could not find a Y triplet item for this column vector." << endl;
487   }
488   triplet(2) = value;
489
490   item = FindElement("z");
491   if (!item) item = FindElement("yaw");
492   if (item) {
493     value = item->GetDataAsNumber();
494     if (!supplied_units.empty()) value *= convert[supplied_units][target_units];
495   } else {
496     value = 0.0;
497     cerr << "Could not find a Z triplet item for this column vector." << endl;
498   }
499   triplet(3) = value;
500
501   return triplet;
502 }
503
504 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
505
506 void Element::Print(unsigned int level)
507 {
508   unsigned int i, spaces;
509
510   level+=2;
511   for (spaces=0; spaces<=level; spaces++) cout << " "; // format output
512   cout << "Element Name: " << name;
513   for (i=0; i<attributes.size(); i++) {
514     cout << "  " << attribute_key[i] << " = " << attributes[attribute_key[i]];
515   }
516   cout << endl;
517   for (i=0; i<data_lines.size(); i++) {
518     for (spaces=0; spaces<=level; spaces++) cout << " "; // format output
519     cout << data_lines[i] << endl;
520   }
521   for (i=0; i<children.size(); i++) {
522     children[i]->Print(level);
523   }
524 }
525
526 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
527
528 void Element::AddAttribute(const string& name, const string& value)
529 {
530   attribute_key.push_back(name);
531   attributes[name] = value;
532 }
533
534 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
535
536 void Element::AddData(string d)
537 {
538   string::size_type string_start = d.find_first_not_of(" \t");
539   if (string_start != string::npos && string_start > 0) {
540     d.erase(0,string_start);
541   }
542   data_lines.push_back(d);
543 }
544
545 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
546
547 } // end namespace JSBSim