1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4 Date started: 09/28/2004
5 Purpose: XML element class
8 ------------- Copyright (C) 2001 Jon S. Berndt (jon@jsbsim.org) -------------
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
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
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.
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.
27 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
29 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
36 #include "FGXMLElement.h"
37 #include "string_utilities.h"
41 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
43 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
47 IDENT(IdSrc,"$Id: FGXMLElement.cpp,v 1.45 2014/01/13 10:46:02 ehofman Exp $");
48 IDENT(IdHdr,ID_XMLELEMENT);
50 bool Element::converterIsInitialized = false;
51 map <string, map <string, double> > Element::convert;
53 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
55 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
57 Element::Element(const string& nm)
64 if (!converterIsInitialized) {
65 converterIsInitialized = true;
66 // convert ["from"]["to"] = factor, so: from * factor = to
68 convert["M"]["FT"] = 3.2808399;
69 convert["FT"]["M"] = 1.0/convert["M"]["FT"];
70 convert["CM"]["FT"] = 0.032808399;
71 convert["FT"]["CM"] = 1.0/convert["CM"]["FT"];
72 convert["KM"]["FT"] = 3280.8399;
73 convert["FT"]["KM"] = 1.0/convert["KM"]["FT"];
74 convert["FT"]["IN"] = 12.0;
75 convert["IN"]["FT"] = 1.0/convert["FT"]["IN"];
76 convert["IN"]["M"] = convert["IN"]["FT"] * convert["FT"]["M"];
77 convert["M"]["IN"] = convert["M"]["FT"] * convert["FT"]["IN"];
79 convert["M2"]["FT2"] = convert["M"]["FT"]*convert["M"]["FT"];
80 convert["FT2"]["M2"] = 1.0/convert["M2"]["FT2"];
81 convert["CM2"]["FT2"] = convert["CM"]["FT"]*convert["CM"]["FT"];
82 convert["FT2"]["CM2"] = 1.0/convert["CM2"]["FT2"];
83 convert["M2"]["IN2"] = convert["M"]["IN"]*convert["M"]["IN"];
84 convert["IN2"]["M2"] = 1.0/convert["M2"]["IN2"];
85 convert["FT2"]["IN2"] = 144.0;
86 convert["IN2"]["FT2"] = 1.0/convert["FT2"]["IN2"];
88 convert["IN3"]["CC"] = 16.387064;
89 convert["CC"]["IN3"] = 1.0/convert["IN3"]["CC"];
90 convert["FT3"]["IN3"] = 1728.0;
91 convert["IN3"]["FT3"] = 1.0/convert["FT3"]["IN3"];
92 convert["M3"]["FT3"] = 35.3146667;
93 convert["FT3"]["M3"] = 1.0/convert["M3"]["FT3"];
94 convert["LTR"]["IN3"] = 61.0237441;
95 convert["IN3"]["LTR"] = 1.0/convert["LTR"]["IN3"];
97 convert["LBS"]["KG"] = 0.45359237;
98 convert["KG"]["LBS"] = 1.0/convert["LBS"]["KG"];
99 convert["SLUG"]["KG"] = 14.59390;
100 convert["KG"]["SLUG"] = 1.0/convert["SLUG"]["KG"];
101 // Moments of Inertia
102 convert["SLUG*FT2"]["KG*M2"] = 1.35594;
103 convert["KG*M2"]["SLUG*FT2"] = 1.0/convert["SLUG*FT2"]["KG*M2"];
105 convert["RAD"]["DEG"] = 180.0/M_PI;
106 convert["DEG"]["RAD"] = 1.0/convert["RAD"]["DEG"];
108 convert["RAD/SEC"]["DEG/SEC"] = convert["RAD"]["DEG"];
109 convert["DEG/SEC"]["RAD/SEC"] = 1.0/convert["RAD/SEC"]["DEG/SEC"];
111 convert["LBS/FT"]["N/M"] = 14.5939;
112 convert["N/M"]["LBS/FT"] = 1.0/convert["LBS/FT"]["N/M"];
114 convert["LBS/FT/SEC"]["N/M/SEC"] = 14.5939;
115 convert["N/M/SEC"]["LBS/FT/SEC"] = 1.0/convert["LBS/FT/SEC"]["N/M/SEC"];
116 // Damping force (Square Law)
117 convert["LBS/FT2/SEC2"]["N/M2/SEC2"] = 47.880259;
118 convert["N/M2/SEC2"]["LBS/FT2/SEC2"] = 1.0/convert["LBS/FT2/SEC2"]["N/M2/SEC2"];
120 convert["WATTS"]["HP"] = 0.001341022;
121 convert["HP"]["WATTS"] = 1.0/convert["WATTS"]["HP"];
123 convert["N"]["LBS"] = 0.22482;
124 convert["LBS"]["N"] = 1.0/convert["N"]["LBS"];
126 convert["KTS"]["FT/SEC"] = 1.68781;
127 convert["FT/SEC"]["KTS"] = 1.0/convert["KTS"]["FT/SEC"];
128 convert["M/S"]["FT/S"] = 3.2808399;
129 convert["M/SEC"]["FT/SEC"] = 3.2808399;
130 convert["FT/S"]["M/S"] = 1.0/convert["M/S"]["FT/S"];
131 convert["M/SEC"]["FT/SEC"] = 3.2808399;
132 convert["FT/SEC"]["M/SEC"] = 1.0/convert["M/SEC"]["FT/SEC"];
133 convert["KM/SEC"]["FT/SEC"] = 3280.8399;
134 convert["FT/SEC"]["KM/SEC"] = 1.0/convert["KM/SEC"]["FT/SEC"];
136 convert["FT*LBS"]["N*M"] = 1.35581795;
137 convert["N*M"]["FT*LBS"] = 1/convert["FT*LBS"]["N*M"];
139 convert["M4*SEC/KG"]["FT4*SEC/SLUG"] = convert["M"]["FT"]*convert["M"]["FT"]*
140 convert["M"]["FT"]*convert["M"]["FT"]/convert["KG"]["SLUG"];
141 convert["FT4*SEC/SLUG"]["M4*SEC/KG"] =
142 1.0/convert["M4*SEC/KG"]["FT4*SEC/SLUG"];
144 convert["INHG"]["PSF"] = 70.7180803;
145 convert["PSF"]["INHG"] = 1.0/convert["INHG"]["PSF"];
146 convert["ATM"]["INHG"] = 29.9246899;
147 convert["INHG"]["ATM"] = 1.0/convert["ATM"]["INHG"];
148 convert["PSI"]["INHG"] = 2.03625437;
149 convert["INHG"]["PSI"] = 1.0/convert["PSI"]["INHG"];
150 convert["INHG"]["PA"] = 3386.0; // inches Mercury to pascals
151 convert["PA"]["INHG"] = 1.0/convert["INHG"]["PA"];
152 convert["LBS/FT2"]["N/M2"] = 14.5939/convert["FT"]["M"];
153 convert["N/M2"]["LBS/FT2"] = 1.0/convert["LBS/FT2"]["N/M2"];
154 convert["LBS/FT2"]["PA"] = convert["LBS/FT2"]["N/M2"];
155 convert["PA"]["LBS/FT2"] = 1.0/convert["LBS/FT2"]["PA"];
157 convert["KG/MIN"]["LBS/MIN"] = convert["KG"]["LBS"];
159 convert["LBS/HP*HR"]["KG/KW*HR"] = 0.6083;
160 convert["KG/KW*HR"]["LBS/HP*HR"] = 1.0/convert["LBS/HP*HR"]["KG/KW*HR"];
162 convert["KG/L"]["LBS/GAL"] = 8.3454045;
163 convert["LBS/GAL"]["KG/L"] = 1.0/convert["KG/L"]["LBS/GAL"];
166 convert["M"]["M"] = 1.00;
167 convert["KM"]["KM"] = 1.00;
168 convert["FT"]["FT"] = 1.00;
169 convert["IN"]["IN"] = 1.00;
171 convert["M2"]["M2"] = 1.00;
172 convert["FT2"]["FT2"] = 1.00;
174 convert["IN3"]["IN3"] = 1.00;
175 convert["CC"]["CC"] = 1.0;
176 convert["M3"]["M3"] = 1.0;
177 convert["FT3"]["FT3"] = 1.0;
178 convert["LTR"]["LTR"] = 1.0;
180 convert["KG"]["KG"] = 1.00;
181 convert["LBS"]["LBS"] = 1.00;
182 // Moments of Inertia
183 convert["KG*M2"]["KG*M2"] = 1.00;
184 convert["SLUG*FT2"]["SLUG*FT2"] = 1.00;
186 convert["DEG"]["DEG"] = 1.00;
187 convert["RAD"]["RAD"] = 1.00;
189 convert["DEG/SEC"]["DEG/SEC"] = 1.00;
190 convert["RAD/SEC"]["RAD/SEC"] = 1.00;
192 convert["LBS/FT"]["LBS/FT"] = 1.00;
193 convert["N/M"]["N/M"] = 1.00;
195 convert["LBS/FT/SEC"]["LBS/FT/SEC"] = 1.00;
196 convert["N/M/SEC"]["N/M/SEC"] = 1.00;
197 // Damping force (Square law)
198 convert["LBS/FT2/SEC2"]["LBS/FT2/SEC2"] = 1.00;
199 convert["N/M2/SEC2"]["N/M2/SEC2"] = 1.00;
201 convert["HP"]["HP"] = 1.00;
202 convert["WATTS"]["WATTS"] = 1.00;
204 convert["N"]["N"] = 1.00;
206 convert["FT/SEC"]["FT/SEC"] = 1.00;
207 convert["KTS"]["KTS"] = 1.00;
208 convert["M/S"]["M/S"] = 1.0;
209 convert["M/SEC"]["M/SEC"] = 1.0;
210 convert["KM/SEC"]["KM/SEC"] = 1.0;
212 convert["FT*LBS"]["FT*LBS"] = 1.00;
213 convert["N*M"]["N*M"] = 1.00;
215 convert["M4*SEC/KG"]["M4*SEC/KG"] = 1.0;
216 convert["FT4*SEC/SLUG"]["FT4*SEC/SLUG"] = 1.0;
218 convert["PSI"]["PSI"] = 1.00;
219 convert["PSF"]["PSF"] = 1.00;
220 convert["INHG"]["INHG"] = 1.00;
221 convert["ATM"]["ATM"] = 1.0;
222 convert["PA"]["PA"] = 1.0;
223 convert["N/M2"]["N/M2"] = 1.00;
224 convert["LBS/FT2"]["LBS/FT2"] = 1.00;
226 convert["LBS/SEC"]["LBS/SEC"] = 1.00;
227 convert["KG/MIN"]["KG/MIN"] = 1.0;
228 convert["LBS/MIN"]["LBS/MIN"] = 1.0;
230 convert["LBS/HP*HR"]["LBS/HP*HR"] = 1.0;
231 convert["KG/KW*HR"]["KG/KW*HR"] = 1.0;
233 convert["KG/L"]["KG/L"] = 1.0;
234 convert["LBS/GAL"]["LBS/GAL"] = 1.0;
238 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
240 Element::~Element(void)
242 for (unsigned int i=0; i<children.size(); i++) delete children[i];
247 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
249 string Element::GetAttributeValue(const string& attr)
251 if (HasAttribute(attr)) return attributes[attr];
255 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
257 bool Element::HasAttribute(const string& attr)
259 map<string, string>::iterator found = attributes.find(attr);
261 return found != attributes.end();
264 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
266 double Element::GetAttributeValueAsNumber(const string& attr)
268 string attribute = GetAttributeValue(attr);
270 if (attribute.empty()) {
271 cerr << ReadFrom() << "Expecting numeric attribute value, but got no data"
277 if (is_number(trim(attribute)))
278 number = atof(attribute.c_str());
280 cerr << ReadFrom() << "Expecting numeric attribute value, but got: "
281 << attribute << endl;
289 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
291 Element* Element::GetElement(unsigned int el)
293 if (children.size() > el) {
303 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
305 Element* Element::GetNextElement(void)
307 if (children.size() > element_index+1) {
309 return children[element_index];
316 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
318 string Element::GetDataLine(unsigned int i)
320 if (data_lines.size() > 0) return data_lines[i];
321 else return string("");
324 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
326 double Element::GetDataAsNumber(void)
328 if (data_lines.size() == 1) {
330 if (is_number(trim(data_lines[0])))
331 number = atof(data_lines[0].c_str());
333 cerr << ReadFrom() << "Expected numeric value, but got: " << data_lines[0]
339 } else if (data_lines.size() == 0) {
340 cerr << ReadFrom() << "Expected numeric value, but got no data" << endl;
343 cerr << ReadFrom() << "Attempting to get single data value in element "
344 << "<" << name << ">" << endl
345 << " from multiple lines:" << endl;
346 for(unsigned int i=0; i<data_lines.size(); ++i)
347 cerr << data_lines[i] << endl;
352 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
354 unsigned int Element::GetNumElements(const string& element_name)
356 unsigned int number_of_elements=0;
357 Element* el=FindElement(element_name);
359 number_of_elements++;
360 el=FindNextElement(element_name);
362 return number_of_elements;
365 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
367 Element* Element::FindElement(const string& el)
369 if (el.empty() && children.size() >= 1) {
373 for (unsigned int i=0; i<children.size(); i++) {
374 if (el == children[i]->GetName()) {
383 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
385 Element* Element::FindNextElement(const string& el)
388 if (element_index < children.size()) {
389 return children[element_index++];
395 for (unsigned int i=element_index; i<children.size(); i++) {
396 if (el == children[i]->GetName()) {
405 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
407 double Element::FindElementValueAsNumber(const string& el)
409 Element* element = FindElement(el);
411 double value = element->GetDataAsNumber();
412 value = DisperseValue(element, value);
415 cerr << ReadFrom() << "Attempting to get non-existent element " << el
421 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
423 string Element::FindElementValue(const string& el)
425 Element* element = FindElement(el);
427 return element->GetDataLine();
433 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
435 double Element::FindElementValueAsNumberConvertTo(const string& el, const string& target_units)
437 Element* element = FindElement(el);
440 cerr << ReadFrom() << "Attempting to get non-existent element " << el
445 string supplied_units = element->GetAttributeValue("unit");
447 if (!supplied_units.empty()) {
448 if (convert.find(supplied_units) == convert.end()) {
449 cerr << element->ReadFrom() << "Supplied unit: \""
450 << supplied_units << "\" does not exist (typo?)." << endl;
453 if (convert[supplied_units].find(target_units) == convert[supplied_units].end()) {
454 cerr << element->ReadFrom() << "Supplied unit: \""
455 << supplied_units << "\" cannot be converted to " << target_units
461 double value = element->GetDataAsNumber();
462 if (!supplied_units.empty()) {
463 value *= convert[supplied_units][target_units];
466 value = DisperseValue(element, value, supplied_units, target_units);
471 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
473 double Element::FindElementValueAsNumberConvertFromTo( const string& el,
474 const string& supplied_units,
475 const string& target_units)
477 Element* element = FindElement(el);
480 cerr << "Attempting to get non-existent element " << el << endl;
484 if (!supplied_units.empty()) {
485 if (convert.find(supplied_units) == convert.end()) {
486 cerr << element->ReadFrom() << "Supplied unit: \""
487 << supplied_units << "\" does not exist (typo?)." << endl;
490 if (convert[supplied_units].find(target_units) == convert[supplied_units].end()) {
491 cerr << element->ReadFrom() << "Supplied unit: \""
492 << supplied_units << "\" cannot be converted to " << target_units
498 double value = element->GetDataAsNumber();
499 if (!supplied_units.empty()) {
500 value *= convert[supplied_units][target_units];
503 value = DisperseValue(element, value, supplied_units, target_units);
508 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
510 FGColumnVector3 Element::FindElementTripletConvertTo( const string& target_units)
512 FGColumnVector3 triplet;
515 string supplied_units = GetAttributeValue("unit");
517 if (!supplied_units.empty()) {
518 if (convert.find(supplied_units) == convert.end()) {
519 cerr << ReadFrom() << "Supplied unit: \""
520 << supplied_units << "\" does not exist (typo?)." << endl;
523 if (convert[supplied_units].find(target_units) == convert[supplied_units].end()) {
524 cerr << ReadFrom() << "Supplied unit: \""
525 << supplied_units << "\" cannot be converted to " << target_units
531 item = FindElement("x");
532 if (!item) item = FindElement("roll");
534 value = item->GetDataAsNumber();
535 if (!supplied_units.empty()) value *= convert[supplied_units][target_units];
536 triplet(1) = DisperseValue(item, value, supplied_units, target_units);
542 item = FindElement("y");
543 if (!item) item = FindElement("pitch");
545 value = item->GetDataAsNumber();
546 if (!supplied_units.empty()) value *= convert[supplied_units][target_units];
547 triplet(2) = DisperseValue(item, value, supplied_units, target_units);
552 item = FindElement("z");
553 if (!item) item = FindElement("yaw");
555 value = item->GetDataAsNumber();
556 if (!supplied_units.empty()) value *= convert[supplied_units][target_units];
557 triplet(3) = DisperseValue(item, value, supplied_units, target_units);
565 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
567 double Element::DisperseValue(Element *e, double val, const std::string supplied_units, const std::string target_units)
571 if (e->HasAttribute("dispersion")) {
572 disp = e->GetAttributeValueAsNumber("dispersion");
573 if (!supplied_units.empty()) disp *= convert[supplied_units][target_units];
574 string attType = e->GetAttributeValue("type");
575 if (attType == "gaussian") {
576 double grn = GaussianRandomNumber();
577 value = val + disp*grn;
578 /* std::cout << "DISPERSION GAUSSIAN: Initial: " << val
579 << " Dispersion: " << disp
580 << " Gaussian Rand Num: " << grn
581 << " Total Dispersed Value: " << value << endl; */
582 } else if (attType == "uniform") {
583 double urn = ((((double)rand()/RAND_MAX)-0.5)*2.0);
584 value = val + disp * urn;
585 /* std::cout << "DISPERSION UNIFORM: Initial: " << val
586 << " Dispersion: " << disp
587 << " Uniform Rand Num: " << urn
588 << " Total Dispersed Value: " << value << endl; */
590 cerr << ReadFrom() << "Unknown dispersion type" << attType << endl;
598 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
600 double Element::GaussianRandomNumber(void)
602 static double V1, V2, S;
603 static int phase = 0;
607 V1 = V2 = S = X = 0.0;
610 double U1 = (double)rand() / RAND_MAX;
611 double U2 = (double)rand() / RAND_MAX;
615 S = V1 * V1 + V2 * V2;
616 } while(S >= 1 || S == 0);
618 X = V1 * sqrt(-2 * log(S) / S);
620 X = V2 * sqrt(-2 * log(S) / S);
627 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
629 void Element::Print(unsigned int level)
631 unsigned int i, spaces;
634 for (spaces=0; spaces<=level; spaces++) cout << " "; // format output
635 cout << "Element Name: " << name;
637 map<string, string>::iterator it;
638 for (it = attributes.begin(); it != attributes.end(); ++it)
639 cout << " " << it->first << " = " << it->second;
642 for (i=0; i<data_lines.size(); i++) {
643 for (spaces=0; spaces<=level; spaces++) cout << " "; // format output
644 cout << data_lines[i] << endl;
646 for (i=0; i<children.size(); i++) {
647 children[i]->Print(level);
651 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
653 void Element::AddAttribute(const string& name, const string& value)
655 attributes[name] = value;
658 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
660 void Element::AddData(string d)
662 string::size_type string_start = d.find_first_not_of(" \t");
663 if (string_start != string::npos && string_start > 0) {
664 d.erase(0,string_start);
666 data_lines.push_back(d);
669 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
671 string Element::ReadFrom(void) const
673 ostringstream message;
676 << "In file " << GetFileName() << ": line " << GetLineNumber()
679 return message.str();
682 } // end namespace JSBSim