1 /*
2  * CRRCsim - the Charles River Radio Control Club Flight Simulator Project
3  *
4  * Copyright (C) 2003, 2004, 2005, 2006, 2008 Jens Wilhelm Wulf (original author)
5  * Copyright (C) 2004, 2005, 2008 Jan Reucker
6  * Copyright (C) 2005 Olivier Bordes
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2
10  * as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330,
20  * Boston, MA 02111-1307, USA.
21  *
22  */
23 
24 /**
25  * \file SimpleXMLTransfer.cpp
26  *
27  * -per ifdef ausgeklammerte Funktionen sind noch umzusetzen
28  *
29  * -wahrscheinlich eine schon wesentliche �nderung im Vergleich zur java-Version:
30  *  im Zustand STATE_READNAME gehe ich auch bei ((c0 == '/') && myName.length() > 0)
31  *  in STATE_ATTR_NAME �ber. Damit kann man n�mlich auch so etwas wie '<br/>' behandeln,
32  *  die vorige Version konnte nur '<br />'. Wie ist das aktuell in der Java-Version?
33  */
34 
35 #include "SimpleXMLTransfer.h"
36 #include "lib_conversions.h"
37 #include <ctype.h>
38 #include <iostream>
39 #include <cstdlib>
40 
41 // 1: ?
42 // 2: show compare
43 #define DEBUG 0
44 
45 #if DEBUG != 0
46 # include <stdio.h>
47 #endif
48 
XMLException(std::string message)49 XMLException::XMLException(std::string message)
50 {
51   myMessage = message;
52 }
53 
what()54 const char *XMLException::what()
55 {
56   return (myMessage.c_str());
57 }
58 
59 /**
60  * Element ohne Daten erstellen.
61  */
SimpleXMLTransfer()62 SimpleXMLTransfer::SimpleXMLTransfer()
63 {
64   myName      = "data";
65   content     = (std::string *) 0;
66   sourcedescr = "default constructor";
67 }
68 
SimpleXMLTransfer(std::istream & in,int data)69 SimpleXMLTransfer::SimpleXMLTransfer(std::istream & in, int data)
70 {
71   content     = (std::string *) 0;
72   sourcedescr = "istream";
73   readStream(in, data);
74 }
75 
76 /**
77  * Aus einer Datei lesen. <code>source</code> ist der Pfad zur Datei.
78  * Wenn sie mit <code>file://</code> beginnt, wird eine lokale Datei gelesen, ansonsten
79  * wird ein Netzwerkzugriff versucht.
80  * Wenn der Name mit <code>.gz</code> endet, wird angenommen, dass die Datei mit GnuZip
81  * gepackt ist.
82  */
SimpleXMLTransfer(std::string source)83 SimpleXMLTransfer::SimpleXMLTransfer(std::string source)
84 {
85   std::ifstream in;
86 
87   content = (std::string*) 0;
88 
89   in.open(source.c_str());
90   sourcedescr = "file: " + source;
91 
92   if (!in)
93   {
94     throw XMLException("Error opening " + source);
95   }
96   else
97   {
98     readStream(in, -2);
99     in.close();
100   }
101 }
102 
SimpleXMLTransfer(std::istream & in)103 SimpleXMLTransfer::SimpleXMLTransfer(std::istream& in)
104 {
105   content = (std::string*) 0;
106   sourcedescr = "stream";
107   readStream(in, -2);
108 }
109 
SimpleXMLTransfer(SimpleXMLTransfer * source)110 SimpleXMLTransfer::SimpleXMLTransfer(SimpleXMLTransfer* source)
111 {
112   content     = (std::string *) 0;
113   sourcedescr = "copy constructor";
114 
115   setName(source->getName());
116   setContent(source->getContentString());
117 
118   for (int n=0; n<source->getAttributeCount(); n++)
119     addAttribute(source->attributeName(n), source->attributeVal(n));
120 
121   for (int n=0; n<source->getChildCount(); n++)
122     addChild(new SimpleXMLTransfer(source->getChildAt(n)));
123 }
124 
~SimpleXMLTransfer()125 SimpleXMLTransfer::~SimpleXMLTransfer()
126 {
127   SimpleXMLTransfer *tmp;
128 
129   if (content != (std::string*) 0)
130     delete content;
131 
132   while (children.size() > 0)
133   {
134     tmp = children[children.size() - 1];
135     delete tmp;
136     children.pop_back();
137   }
138 }
139 
140 /**
141  * Nur zur internen Vewendung.
142  */
readStream(std::istream & in,int data)143 void SimpleXMLTransfer::readStream(std::istream & in, int data)
144 {
145   bool fLesen = true;
146   bool fGeschlossen = false;
147 
148   std::string name;
149 //  std::string value;
150   std::string myComment;
151   char c0 = ' ';
152   char c1 = ' ';
153   char c2 = ' ';
154   T_State nState;
155   T_State nStateAfterComment = STATE_IDLE;
156   std::string endTagName;
157 
158   std::string attributename;
159   std::string attributeval;
160 
161   if (data != -2)
162   {
163     nState = STATE_READNAME;
164     myName = "";
165     myName.push_back((char) data);
166   }
167   else
168     nState = STATE_IDLE;
169 
170   while (fLesen)
171   {
172     data = in.get();
173 
174     if (data < 0)
175       fLesen = false;
176     else
177     {
178       c0 = (char) data;
179       switch (nState)
180       {
181           // Auf eine �ffnende Klammer warten.
182         case STATE_IDLE:
183           if (c0 == '<')
184             nState = STATE_START;
185           break;
186 
187           //
188         case STATE_START:
189           if (c0 == '?')
190             nState = STATE_INITTAG;
191           else if (c0 == '!')
192           {
193             nStateAfterComment = STATE_IDLE;
194             nState = STATE_COMMENT;
195             myComment = "<!";
196           }
197           else
198           {
199             nState = STATE_READNAME;
200             myName = "";
201             myName.push_back(c0);
202           }
203           break;
204 
205           // Das Ende vom Inittag abwarten.
206         case STATE_INITTAG:
207           if (c0 == '>')
208             nState = STATE_IDLE;
209           break;
210 
211           // Das Ende vom Kommentar abwarten.
212         case STATE_COMMENT:
213           myComment.push_back(c0);
214           if (c0 == '>' && c1 == '-' && c2 == '-')
215           {
216             comment.push_back(myComment);
217             if (nStateAfterComment == STATE_IDLE)
218               commentPos.push_back(-1);
219             else
220               commentPos.push_back(children.size());
221             nState = nStateAfterComment;
222           }
223           break;
224 
225           // Den Namen einlesen
226         case STATE_READNAME:
227           if (c0 == '=')
228           {
229             throw
230             XMLException
231             ("Found \'=\' without preceding attributename in " +
232              myName);
233           }
234           else
235             if ((c0 == '/' || c0 == ' ' || c0 == '\n' || c0 == '\r'
236                  || c0 == '\t') && myName.length() > 0)
237             {
238               nState = STATE_ATTR_NAME;
239               attributename = "";
240             }
241             else
242             {
243               if (c0 == '>')
244               {
245                 nState = STATE_WAIT_CONT;
246               }
247               else
248                 myName.push_back(c0);
249             }
250           break;
251 
252         case STATE_ATTR_NAME:
253           if (c0 == '=')
254           {
255             if (attributename.length() == 0)
256             {
257               // Es wurde versucht, einen Wert zuzuweisen, obwohl noch kein Attribut
258               // definiert wurde.
259               // Vielleicht wurde versucht, dem Element einen Wert zuzuweisen?
260               throw
261               XMLException
262               ("Found \'=\' without preceding attributename in " +
263                myName);
264             }
265             nState = STATE_ATTR_VAL_START;
266           }
267           else
268           {
269             if (c0 == '>')
270             {
271               if (c1 == '/')
272               {
273                 fGeschlossen = true;
274                 fLesen = false;
275               }
276               else
277                 nState = STATE_WAIT_CONT;
278             }
279             else
280             {
281               if (isspace(c0) == false)
282                 attributename.push_back(c0);
283               else
284               {
285                 if (attributename.length() > 0)
286                 {
287                   // Ich hatte bereits einen Namen eingelesen, jetzt kommt Whitespace.
288                   // Also ist der Name beendet, es muss jetzt das Gleichheitszeichen
289                   // und der Wert kommen.
290                   nState = STATE_ATTR_VAL_WAIT_EQ;
291                 }
292               }
293             }
294           }
295           break;
296 
297         case STATE_ATTR_VAL_WAIT_EQ:
298           if (c0 == '=')
299             nState = STATE_ATTR_VAL_START;
300           else if (isspace(c0) == false)
301           {
302             throw XMLException("Element " + myName +
303                                ": expected \'=\', got \'" + c0 +
304                                "\' after attribute " + attributename);
305           }
306           break;
307 
308         case STATE_ATTR_VAL_START:
309           if (c0 == '"')
310           {
311             attributeval = "";
312             nState = STATE_ATTR_VAL;
313           }
314           break;
315 
316         case STATE_ATTR_VAL:
317           if (c0 == '"')
318           {
319             if (attributename.length() > 0)
320               addAttribute(attributename, convFromXML(attributeval));
321             attributeval = "";
322 
323             nState = STATE_ATTR_NAME;
324             attributename = "";
325           }
326           else
327             attributeval.push_back(c0);
328           break;
329 
330         case STATE_WAIT_CONT:
331           if (c0 == '<')
332             nState = STATE_CONT_START;
333           else
334           {
335             if (content == (std::string *) 0 && isspace(c0) == false)
336               content = new std::string();
337             if (content != (std::string *) 0)
338               content->push_back(c0);
339           }
340           break;
341 
342         case STATE_CONT_START:
343           if (c0 == '/')
344             nState = STATE_ENDTAG;
345           else if (c0 == '!')
346           {
347             nStateAfterComment = STATE_WAIT_CONT;
348             nState = STATE_COMMENT;
349             myComment = "<!";
350           }
351           else
352           {
353             SimpleXMLTransfer *child =
354               new SimpleXMLTransfer(in, (int) c0);
355             addChild(child);
356             nState = STATE_WAIT_CONT;
357           }
358           break;
359 
360           // Ich warte auf das Ende und �berpr�fe, ob auch
361           // mein Name wieder korrekt im End-Tag steht.
362         case STATE_ENDTAG:
363           if (c0 == '>')
364           {
365             if (endTagName.compare(getName()) == 0)
366             {
367               fGeschlossen = true;
368               fLesen = false;
369             }
370             else
371             {
372               throw XMLException("XML-Element " + getName()
373                                  +
374                                  " wurde nicht korrekt abgeschlossen: "
375                                  + endTagName);
376             }
377           }
378           else
379             endTagName.push_back(c0);
380           break;
381 
382         default:
383           break;
384       }
385 
386       c2 = c1;
387       c1 = c0;
388     }
389   }
390 
391 #if DEBUG == 1
392   if (content != (std::string *) 0)
393     printf("Content length=%i: %s", content->length(), content->c_str());
394   else
395     printf("No content\n");
396 #endif
397 
398   // trailing whitespace vom content entfernen
399   if (content != (std::string *) 0)
400     while (content->length() > 0
401            && isspace(content->at(content->length() - 1)) == true)
402       content->replace(content->length() - 1, 1, "");
403 
404   if (fGeschlossen == false)
405   {
406     throw XMLException(sourcedescr + ": XML-Element wurde nicht abgeschlossen: " +
407                        getName());
408   }
409 }
410 
411 /**
412  * Liefert den Namen des Elements zur�ck.
413  */
getName()414 std::string SimpleXMLTransfer::getName()
415 {
416   return (myName);
417 }
418 
419 /**
420  * Liefert den Inhalt als String zur�ck
421  */
getContentString()422 std::string SimpleXMLTransfer::getContentString()
423 {
424   if (content != (std::string *) 0)
425     return (*content);
426   else
427     return ("");
428 }
429 
430 /**
431  * Liefert den Wert des Attributs <code>attr</code> zur�ck oder
432  * <code>defaultVal</code>, wenn es nicht existiert.
433  */
434 double
attributeAsDouble(std::string attr,double defaultVal)435 SimpleXMLTransfer::attributeAsDouble(std::string attr, double defaultVal)
436 {
437   int index = indexOfAttribute(attr);
438 
439   if (index < 0)
440   {
441     return (defaultVal);
442   }
443   else
444   {
445     return (convToDouble(attrVal[index]));
446   }
447 }
448 
449 /**
450  * Liefert den Wert des Attributs <code>attr</code> zur�ck oder
451  * eine XMLException, wenn es nicht existiert.
452  */
attributeAsDouble(unsigned int index)453 double SimpleXMLTransfer::attributeAsDouble(unsigned int index)
454 {
455   if (index > attrName.size())
456   {
457     throw XMLException("No such attribute in " + getName());
458   }
459   else
460   {
461     return (convToDouble(attrVal[index]));
462   }
463 }
464 
465 /**
466  * Liefert den Wert des Attributs <code>attr</code> zur�ck oder
467  * eine XMLException, wenn es nicht existiert.
468  */
attributeAsDouble(std::string attr)469 double SimpleXMLTransfer::attributeAsDouble(std::string attr)
470 {
471   int index = indexOfAttribute(attr);
472 
473   if (index < 0)
474   {
475     throw XMLException("No Attribute named " + attr + " in " + getName());
476   }
477   else
478   {
479     return (convToDouble(attrVal[index]));
480   }
481 }
482 
483 /**
484  * Liefert den Inhalt als Double zur�ck
485  */
getContentDouble()486 double SimpleXMLTransfer::getContentDouble()
487 {
488   return (convToDouble(*content));
489 }
490 
491 /**
492  * Liefert den Inhalt als Int zur�ck
493  */
getContentInt()494 int SimpleXMLTransfer::getContentInt()
495 {
496   return (convToInt(*content));
497 }
498 
499 /**
500  * Schnellfunktion zum Zugriff auf ein Attribut dieses Elements oder von
501  * einem Kindeskind.
502  */
getString(std::string path)503 std::string SimpleXMLTransfer::getString(std::string path)
504 {
505   std::string::size_type pos = path.rfind('.');
506 
507   if (pos != std::string::npos)
508   {
509     SimpleXMLTransfer *item = getChild(path.substr(0, pos));
510     return (item->attribute(path.substr(pos + 1)));
511   }
512   else
513   {
514     return (attribute(path));
515   }
516 }
517 
518 /**
519  * Schnellfunktion zum Zugriff auf ein Attribut dieses Elements oder von
520  * einem Kindeskind.
521  *
522  * M�gliche Notation f�r einen Integer-Wert: dezimal, hexadezimal mit
523  * vorangestelltem '0x' oder bin�r mit vorangestelltem '0b'.
524  */
getInt(std::string path)525 int SimpleXMLTransfer::getInt(std::string path)
526 {
527   std::string::size_type pos = path.rfind('.');
528 
529   if (pos != std::string::npos)
530   {
531     SimpleXMLTransfer *item = getChild(path.substr(0, pos));
532     return (item->attributeAsInt(path.substr(pos + 1)));
533   }
534   else
535   {
536     return (attributeAsInt(path));
537   }
538 }
539 
540 /**
541  * Schnellfunktion zum Zugriff auf ein Attribut dieses Elements oder von
542  * einem Kindeskind.
543  */
getDouble(std::string path)544 double SimpleXMLTransfer::getDouble(std::string path)
545 {
546   std::string::size_type pos = path.rfind('.');
547 
548   if (pos != std::string::npos)
549   {
550     SimpleXMLTransfer *item = getChild(path.substr(0, pos));
551     return (item->attributeAsDouble(path.substr(pos + 1)));
552   }
553   else
554   {
555     return (attributeAsDouble(path));
556   }
557 }
558 
getString(std::string path,std::string stringDefault)559 std::string SimpleXMLTransfer::getString(std::string path, std::string stringDefault)
560 {
561   try
562   {
563     std::string::size_type pos = path.rfind('.');
564 
565     if (pos != std::string::npos)
566     {
567       SimpleXMLTransfer *item = getChild(path.substr(0, pos));
568       return (item->attribute(path.substr(pos + 1)));
569     }
570     else
571     {
572       return (attribute(path));
573     }
574   }
575   catch (XMLException e)
576   {
577     makeSureAttributeExists(path, stringDefault.c_str());
578     return(stringDefault);
579   }
580 }
581 
582 /**
583  * Schnellfunktion zum Zugriff auf ein Attribut dieses Elements oder von
584  * einem Kindeskind.
585  *
586  * M�gliche Notation f�r einen Integer-Wert: dezimal, hexadezimal mit
587  * vorangestelltem '0x' oder bin�r mit vorangestelltem '0b'.
588  */
getInt(std::string path,int nDefault)589 int SimpleXMLTransfer::getInt(std::string path, int nDefault)
590 {
591   try
592   {
593     std::string::size_type pos = path.rfind('.');
594 
595     if (pos != std::string::npos)
596     {
597       SimpleXMLTransfer *item = getChild(path.substr(0, pos));
598       return (item->attributeAsInt(path.substr(pos + 1)));
599     }
600     else
601     {
602       return (attributeAsInt(path));
603     }
604   }
605   catch (XMLException e)
606   {
607     makeSureAttributeExists(path, itoStr(nDefault, ' ', 1).c_str());
608     return(nDefault);
609   }
610 }
611 
612 /**
613  * Schnellfunktion zum Zugriff auf ein Attribut dieses Elements oder von
614  * einem Kindeskind.
615  */
getDouble(std::string path,double dDefault)616 double SimpleXMLTransfer::getDouble(std::string path, double dDefault)
617 {
618   try
619   {
620     std::string::size_type pos = path.rfind('.');
621 
622     if (pos != std::string::npos)
623     {
624       SimpleXMLTransfer *item = getChild(path.substr(0, pos));
625       return (item->attributeAsDouble(path.substr(pos + 1)));
626     }
627     else
628     {
629       return (attributeAsDouble(path));
630     }
631   }
632   catch (XMLException e)
633   {
634     makeSureAttributeExists(path, doubleToString(dDefault).c_str());
635     return(dDefault);
636   }
637 }
638 
639 #if 1 == 2
640 
641 /**
642  * Liefert den Wert des Attributs <code>attr</code> zur�ck oder
643  * <code>defaultVal</code>, wenn es nicht existiert.
644  */
attributeAsFloat(std::string attr,float defaultVal)645 float SimpleXMLTransfer::attributeAsFloat(std::string attr, float defaultVal)
646 {
647   int index = indexOfAttribute(attr);
648 
649   if (index < 0)
650     return (defaultVal);
651   else
652     return (convToFloat((String) attrVal.elementAt(index)));
653 }
654 
655 /**
656  * Schnellfunktion zum Zugriff auf ein Attribut dieses Elements oder von
657  * einem Kindeskind.
658  */
getFloat(std::string path)659 float SimpleXMLTransfer::getFloat(std::string path)
660 {
661   int pos = path.lastIndexOf('.');
662 
663   if (pos > 0)
664   {
665     SimpleXMLTransfer item = getChild(path.substring(0, pos));
666     return (item.attributeAsFloat(path.substring(pos + 1)));
667   }
668   else
669     return (attributeAsFloat(path));
670 }
671 
672 /**
673  * Setzt den Kommentar.
674  */
setComment(std::string comment)675 void SimpleXMLTransfer::setComment(std::string comment)
676 {
677   myComment = "<!-- ";
678   myComment.append(comment);
679   myComment.append(" -->");
680 }
681 
682 
683 #endif
684 
685 
setAttribute(std::string attribute,std::string value)686 void SimpleXMLTransfer::setAttribute(std::string attribute, std::string value)
687 {
688   if (attribute.find('.') != std::string::npos)
689   {
690     int index;
691     std::string childName;
692     SimpleXMLTransfer* item = this;
693     std::string::size_type pos;
694 
695     while ((pos = attribute.find('.')) != std::string::npos)
696     {
697       childName = attribute.substr(0, pos);
698       attribute = attribute.substr(pos + 1);
699 
700       index = item->indexOfChild(childName);
701       if (index < 0)
702       {
703         SimpleXMLTransfer* tmp = new SimpleXMLTransfer();
704         tmp->setName(childName);
705         item->addChild(tmp);
706         item = tmp;
707       }
708       else
709         item = item->getChildAt(index);
710     }
711     item->setAttribute(attribute, value);
712   }
713   else
714   {
715     if (indexOfAttribute(attribute) >= 0)
716       throw XMLException("Attribute named " + attribute +
717                          " already exists in " + getName());
718 
719     addAttribute(attribute, value);
720   }
721 }
722 
setAttribute(std::string attribute,long int nValue)723 void SimpleXMLTransfer::setAttribute(std::string attribute, long int nValue)
724 {
725   setAttribute(attribute, itoStr(nValue, ' ', 1));
726 }
727 
setAttributeOverwrite(std::string attribute,std::string value)728 void SimpleXMLTransfer::setAttributeOverwrite(std::string attribute, std::string value)
729 {
730   if (attribute.find('.') != std::string::npos)
731   {
732     int index;
733     std::string childName;
734     SimpleXMLTransfer* item = this;
735     std::string::size_type pos;
736 
737     while ((pos = attribute.find('.')) != std::string::npos)
738     {
739       childName = attribute.substr(0, pos);
740       attribute = attribute.substr(pos + 1);
741 
742       index = item->indexOfChild(childName);
743       if (index < 0)
744       {
745         SimpleXMLTransfer* tmp = new SimpleXMLTransfer();
746         tmp->setName(childName);
747         item->addChild(tmp);
748         item = tmp;
749       }
750       else
751         item = item->getChildAt(index);
752     }
753 
754     item->setAttributeOverwrite(attribute, value);
755   }
756   else
757   {
758     int index = indexOfAttribute(attribute);
759     if (index >= 0)
760     {
761       attrName.erase(attrName.begin() + index);
762       attrVal.erase(attrVal.begin() + index);
763     }
764 
765     addAttribute(attribute, value);
766   }
767 }
768 
setAttributeOverwrite(std::string attribute,long int nValue)769 void SimpleXMLTransfer::setAttributeOverwrite(std::string attribute, long int nValue)
770 {
771   setAttributeOverwrite(attribute, itoStr(nValue, ' ', 1));
772 }
773 
makeSureAttributeExists(std::string attribute,const char * defaultVal)774 void SimpleXMLTransfer::makeSureAttributeExists(std::string attribute, const char* defaultVal)
775 {
776   if (attribute.find('.') != std::string::npos)
777   {
778     int index;
779     std::string childName;
780     SimpleXMLTransfer* item = this;
781     std::string::size_type pos;
782 
783     while ((pos = attribute.find('.')) != std::string::npos)
784     {
785       childName = attribute.substr(0, pos);
786       attribute = attribute.substr(pos + 1);
787 
788       index = item->indexOfChild(childName);
789       if (index < 0)
790       {
791         SimpleXMLTransfer* tmp = new SimpleXMLTransfer();
792         tmp->setName(childName);
793         item->addChild(tmp);
794         item = tmp;
795       }
796       else
797         item = item->getChildAt(index);
798     }
799 
800     item->makeSureAttributeExists(attribute, defaultVal);
801   }
802   else
803   {
804     int index = indexOfAttribute(attribute);
805     if (index < 0)
806     {
807       addAttribute(attribute, defaultVal);
808     }
809   }
810 }
811 
812 /**
813  * Konvertiert einen String (Wert eines Attributes in einer XML-Datei)
814  * in einen Unicode-<code>String</code>.
815  * <br>
816  * Funktioniert nicht allgemeing�ltig, da bestimmte
817  * Dinge falsch umgewandelt werden oder zu einer XMLException f�hren.
818  * <br>
819  * Die Darstellung in <code>in</code> unterliegt also einigen
820  * Einschr�nkungen.
821  * Korrekt umgewandelt werden nur:
822  * <code>&lt;</code>,
823  * <code>&gt;</code>,
824  * <code>&amp;</code>,
825  * <code>&quot;</code>
826  * sowie Zeichen in der Darstellung<code>&#xHEXWERT;</code>.
827  */
convFromXML(std::string in)828 std::string SimpleXMLTransfer::convFromXML(std::string in)
829 {
830   int length = in.length();
831   std::string out;
832   char ch;
833 
834   for (int i = 0; i < length;)
835   {
836     ch = in.at(i);
837 
838     if (ch != '&')
839     {
840       out.push_back(ch);
841       i++;
842     }
843     else
844     {
845       std::string sc = "";
846 
847       i++;
848       while ((ch = in.at(i++)) != ';')
849         sc.push_back(ch);
850 
851       if (sc.length() < 2)
852       {
853         throw XMLException("Error converting character: " + sc);
854       }
855       else
856       {
857         ch = sc.at(0);
858 
859         if (ch == 'l') // lt
860           out.push_back('<');
861         else if (ch == 'g') // gt
862           out.push_back('>');
863         else if (ch == 'a') // amp
864           out.push_back('&');
865         else if (ch == 'q') // quot
866           out.push_back('\"');
867         else if (ch != '#')
868         {
869           throw XMLException("Error converting character: " + sc);
870         }
871         else
872         {
873           out.push_back((char) hex2int(sc.substr(2)));
874         }
875       }
876     }
877   }
878 
879   return (out);
880 }
881 
882 /**
883  * Konvertiert einen String, so dass er in einer XML-Datei
884  * als Wert eines Attributes gespeichert werden kann.
885  * Die Konvertierung ist nicht entsprechend Unicode, also
886  * letztlich doch abh�ngig vom Zeichensatz des Systems.
887  */
convToXML(std::string in)888 std::string SimpleXMLTransfer::convToXML(std::string in)
889 {
890   int length = in.length();
891   std::string out;
892   char ch;
893 
894   for (int i = 0; i < length; i++)
895   {
896     ch = in.at(i);
897 
898     if ((ch <= '~' && ch >= '?') ||
899         (ch <= ';' && ch >= '(') ||
900         (ch <= '%' && ch >= '#') ||
901         (ch == ' ') ||
902         (ch == '!') ||
903         (ch == '='))
904     {
905       out.push_back(ch);
906     }
907     else
908     {
909       out.append("&#x");
910 
911       // Das f�hrte zu ung�ltigen Codes (signed int, negativ):
912       // out += itoHexStr(  (int)(ch)    );
913 
914       // So ist es korrekt:
915       out += itoHexStr(  (int)((unsigned char)(ch))    );
916 
917       out.push_back(';');
918     }
919   }
920 
921   return (out);
922 }
923 
924 /**
925  * F�gt ein Attribut hinzu.
926  * Es gibt keinerlei �berpr�fung.
927  */
928 void
addAttribute(std::string attributeName,std::string attributeVal)929 SimpleXMLTransfer::addAttribute(std::string attributeName,
930                                 std::string attributeVal)
931 {
932   //       System.out.println("SimpleXMLTransfer.addAttribute(" + attributeName + ", " + attributeVal + ")");
933   //
934   attrName.push_back(attributeName);
935   attrVal.push_back(attributeVal);
936 }
937 
938 /**
939  * F�gt ein Attribut hinzu.
940  * Es gibt keinerlei �berpr�fung.
941  */
942 void
addAttribute(std::string attributeName,long int attributeVal)943 SimpleXMLTransfer::addAttribute(std::string attributeName,
944                                 long int attributeVal)
945 {
946   addAttribute(attributeName, itoStr(attributeVal, ' ', 1));
947 }
948 
949 /**
950  * F�gt ein Kind hinzu.
951  * Es gibt keinerlei �berpr�fung.
952  */
addChild(SimpleXMLTransfer * child)953 void SimpleXMLTransfer::addChild(SimpleXMLTransfer * child)
954 {
955   children.push_back(child);
956 }
957 
print()958 void SimpleXMLTransfer::print()
959 {
960   std::cout << "<?xml version=\"1.0\" ?>\n";
961 
962   print(std::cout, 0);
963 }
964 
print(std::ostream & out)965 void SimpleXMLTransfer::print(std::ostream & out)
966 {
967   out << "<?xml version=\"1.0\" ?>\n";
968 
969   print(out, 0);
970 }
971 
print(std::ostream & out,int nIndent,std::string val)972 void SimpleXMLTransfer::print(std::ostream& out,
973                               int           nIndent,
974                               std::string   val)
975 {
976   for (int n = 0; n < nIndent; n++)
977     out << "  ";
978 
979   out << val;
980 }
981 
print(std::ostream & out,int nIndent)982 void SimpleXMLTransfer::print(std::ostream & out, int nIndent)
983 {
984   int nCMax = -1;
985 
986   if (comment.size() > 0 && commentPos[0] == -1)
987   {
988     print(out, nIndent, comment[0] + "\n");
989     nCMax = 0;
990   }
991 
992   // Es k�nnte sein, dass dieses Element ein reiner Kommentar ist!
993   if (getName().length() > 0)
994   {
995     // mich selbst er�ffnen
996     print(out, nIndent, "<" + getName());
997 
998     // Attribute schreiben
999     if (attrName.size() > 0)
1000     {
1001       int nSpalte = nIndent * 2 + getName().length();
1002       std::string aVal;
1003       std::string aName;
1004 
1005       for (unsigned int i = 0; i < attrName.size(); i++)
1006       {
1007         aVal = convToXML(attrVal[i]);
1008         aName = attrName[i];
1009 
1010         if (nSpalte + aVal.length() + aName.length() > 80)
1011         {
1012           out << "\n";
1013 
1014           for (int n = 0; n < nIndent; n++)
1015             out << "  ";
1016 
1017           out << "  ";
1018           nSpalte = nIndent * 2 + 2;
1019         }
1020         else
1021           nSpalte += aVal.length() + aName.length() + 4;
1022 
1023         out << " " << aName << "=\"" << aVal << "\"";
1024       }
1025     }
1026 
1027     if (content != (std::string *) 0 || children.size() > 0)
1028     {
1029       out << ">";
1030 
1031       // Wenn ich irgendwelchen Inhalt habe, schreibe ich den vor den Kindern
1032       // und den Kommentaren.
1033       if (content != (std::string *) 0)
1034       {
1035         out << getContentString();
1036       }
1037 
1038       if (comment.size() > (unsigned int)(nCMax+1))
1039       {
1040         if (commentPos[nCMax+1] == 0)
1041         {
1042           nCMax++;
1043           out << "\n";
1044           print(out, nIndent, comment[nCMax]);
1045         }
1046       }
1047 
1048       // Die Kinder sollen ihre Daten schreiben, falls es welche gibt.
1049       if (children.size() > 0)
1050       {
1051         out << "\n";
1052 
1053         for (unsigned int i = 0; i < children.size(); i++)
1054         {
1055           children[i]->print(out, nIndent + 1);
1056           for (unsigned int m=0; m<comment.size(); m++)
1057           {
1058             if (commentPos[m] == (int)i+1)
1059               print(out, nIndent, comment[m] + "\n");
1060           }
1061         }
1062 
1063         // ich bin fertig
1064         for (int n = 0; n < nIndent; n++)
1065           out << "  ";
1066       }
1067       out << "</" << getName() << ">\n";
1068     }
1069     else
1070       // es gibt keine Kinder
1071       out << " />\n";
1072   }
1073 }
1074 
1075 /**
1076  * Liefert das Kind mit dem Index <code>childIndex</code> zur�ck.
1077  */
getChildAt(int childIndex)1078 SimpleXMLTransfer *SimpleXMLTransfer::getChildAt(int childIndex)
1079 {
1080   if (children.size() == 0)
1081     return ((SimpleXMLTransfer *) 0);
1082   return (children[childIndex]);
1083 }
1084 
1085 /**
1086  * Liefert die Anzahl der Kinder zur�ck.
1087  */
getChildCount()1088 int SimpleXMLTransfer::getChildCount()
1089 {
1090   return (children.size());
1091 }
1092 
1093 /**
1094  * Liefert den Wert des Attributs <code>attr</code> zur�ck oder
1095  * eine XMLException, wenn es nicht existiert.
1096  */
attributeAsInt(std::string attr)1097 int SimpleXMLTransfer::attributeAsInt(std::string attr)
1098 {
1099   int index = indexOfAttribute(attr);
1100 
1101   if (index < 0)
1102   {
1103     throw XMLException("No Attribute named " + attr + " in " + getName());
1104   }
1105   else
1106   {
1107     return (convToInt(attrVal[index]));
1108   }
1109 }
1110 
1111 /**
1112  * Liefert den Wert des Attributs <code>attr</code> zur�ck oder
1113  * <code>defaultVal</code>, wenn es nicht existiert.
1114  */
attributeAsInt(std::string attr,int defaultVal)1115 int SimpleXMLTransfer::attributeAsInt(std::string attr, int defaultVal)
1116 {
1117   int index = indexOfAttribute(attr);
1118 
1119   if (index < 0)
1120   {
1121     return (defaultVal);
1122   }
1123   else
1124   {
1125     return (convToInt(attrVal[index]));
1126   }
1127 }
1128 
1129 /**
1130  * Liefert den Wert des Attributs <code>attr</code> zur�ck oder
1131  * eine XMLException, wenn es nicht existiert.
1132  */
attributeAsFloat(std::string attr)1133 float SimpleXMLTransfer::attributeAsFloat(std::string attr)
1134 {
1135   int index = indexOfAttribute(attr);
1136 
1137   if (index < 0)
1138   {
1139     throw XMLException("No Attribute named " + attr + " in " + getName());
1140   }
1141   else
1142   {
1143     return (convToFloat(attrVal[index]));
1144   }
1145 }
1146 
1147 /**
1148  * Liefert den Wert des Attributs <code>attr</code> zur�ck oder
1149  * <code>defaultVal</code>, wenn es nicht existiert.
1150  */
attribute(std::string attr,std::string defaultVal)1151 std::string SimpleXMLTransfer::attribute(std::string attr,
1152     std::string defaultVal)
1153 {
1154   int index = indexOfAttribute(attr);
1155 
1156   if (index < 0)
1157     return (defaultVal);
1158   else
1159     return (attrVal[index]);
1160 }
1161 
1162 /**
1163  * Liefert den Wert des Attributs <code>attr</code> zur�ck oder
1164  * eine XMLException, wenn es nicht existiert.
1165  */
attribute(std::string attr)1166 std::string SimpleXMLTransfer::attribute(std::string attr)
1167 {
1168   int index = indexOfAttribute(attr);
1169 
1170   if (index < 0)
1171   {
1172     throw XMLException("No Attribute named " + attr + " in " + getName());
1173   }
1174   else
1175   {
1176     return (attrVal[index]);
1177   }
1178 }
1179 
1180 /**
1181  * Liefert den Index des ersten Attributes mit dem Namen
1182  * <code>attr</code> zur�ck oder -1, wenn es keins gibt.
1183  */
indexOfAttribute(std::string attr) const1184 int SimpleXMLTransfer::indexOfAttribute(std::string attr) const
1185 {
1186 #if DEBUG == 1
1187   printf("int SimpleXMLTransfer::indexOfAttribute(\"%s\")\n", attr.c_str());
1188 #endif
1189   if (attrName.size() == 0)
1190     return (-1);
1191 
1192   int index = -1;
1193 
1194   for (unsigned int i = 0; i < attrName.size() && index == -1; i++)
1195     if (attr.compare(attrName[i]) == 0)
1196       index = i;
1197 
1198 #if DEBUG == 1
1199   printf("int SimpleXMLTransfer::indexOfAttribute(\"%s\") = %i\n",
1200          attr.c_str(), index);
1201 #endif
1202   return (index);
1203 }
1204 
convToDouble(std::string value)1205 double SimpleXMLTransfer::convToDouble(std::string value)
1206 {
1207   char*       ptr;
1208   double      tmp;
1209   const char* inptr = value.c_str();
1210 
1211   tmp = strtod(inptr, &ptr);
1212   if (ptr == inptr || *ptr != '\0')
1213   {
1214     value = "convToDouble: no number or trailing garbage in " + value;
1215     throw XMLException(value.c_str());
1216   }
1217   return(tmp);
1218 }
1219 
convToFloat(std::string value)1220 float SimpleXMLTransfer::convToFloat(std::string value)
1221 {
1222   return(convToDouble(value));
1223 }
1224 
1225 /**
1226  * M�gliche Notation f�r einen Integer-Wert: dezimal, hexadezimal mit
1227  * vorangestelltem '0x' oder bin�r mit vorangestelltem '0b'.
1228  */
convToInt(std::string value)1229 int SimpleXMLTransfer::convToInt(std::string value)
1230 {
1231   long        nVal;
1232   char*       ptr;
1233   const char* inptr;
1234   int         base;
1235 
1236   if (value.find("0b") == 0 && value.length() > 2)
1237   {
1238     // bin�re Darstellung
1239     inptr = value.c_str()+2;
1240     base  = 2;
1241   }
1242   else if (value.length() > 1 && toupper(value[1]) == 'X')
1243   {
1244     // hexadezimale Darstellung
1245     inptr = value.c_str()+2;
1246     base  = 16;
1247   }
1248   else
1249   {
1250     // dezimale Darstellung
1251     inptr = value.c_str();
1252     base  = 10;
1253   }
1254 
1255   nVal = strtol(inptr, &ptr, base);
1256   if (ptr == inptr || *ptr != '\0')
1257   {
1258     value = "convToInt: no number or trailing garbage in " + value;
1259     throw XMLException(value.c_str());
1260   }
1261   return(nVal);
1262 }
1263 
1264 /**
1265  * Liefert das erste Kind mit dem Namen <code>child</code> zur�ck
1266  * oder eine <code>XMLException</code>, wenn es keins gab.
1267  *
1268  * Zugriff auf Kindeskinder ist erlaubt, also
1269  * <code>getChild("essen.morgens.brot")</code>
1270  * anstatt
1271  * <code>getChild("essen").getChild("morgens").getChild("brot")</code>
1272  */
getChild(std::string child,bool fCreate)1273 SimpleXMLTransfer *SimpleXMLTransfer::getChild(std::string child, bool fCreate)
1274 {
1275   int                    index;
1276   SimpleXMLTransfer*     tmp;
1277   std::string::size_type pos;
1278 
1279   pos = child.find('.');
1280 
1281   if (pos != std::string::npos)
1282   {
1283     std::string parentName = "";
1284     std::string childName = "";
1285     SimpleXMLTransfer* item = this;
1286 
1287     do
1288     {
1289       childName = child.substr(0, pos);
1290       child     = child.substr(pos + 1);
1291       pos       = child.find('.');
1292 
1293       index = item->indexOfChild(childName);
1294       if (index < 0)
1295       {
1296         if (fCreate)
1297         {
1298           tmp = new SimpleXMLTransfer();
1299           tmp->setName(childName);
1300           item->addChild(tmp);
1301           index = item->indexOfChild(childName);
1302         }
1303         else
1304           throw XMLException("No item named " + childName + " in " +
1305                              parentName);
1306       }
1307 
1308       if (parentName.length() > 0)
1309         parentName.push_back('.');
1310       parentName.append(childName);
1311 
1312       item = item->getChildAt(index);
1313     }
1314     while (pos != std::string::npos);
1315 
1316     index = item->indexOfChild(child);
1317     if (index < 0)
1318     {
1319       if (fCreate)
1320       {
1321         tmp = new SimpleXMLTransfer();
1322         tmp->setName(child);
1323         item->addChild(tmp);
1324         return(tmp);
1325       }
1326       else
1327         throw XMLException("No item named " + child + " in " + parentName);
1328     }
1329 
1330     return (item->getChildAt(index));
1331   }
1332   else
1333   {
1334     index = indexOfChild(child);
1335 
1336     if (index < 0)
1337     {
1338       if (fCreate)
1339       {
1340         tmp = new SimpleXMLTransfer();
1341         tmp->setName(child);
1342         addChild(tmp);
1343         return(tmp);
1344       }
1345       else
1346         throw XMLException("No child named " + child + " in " + getName());
1347     }
1348     else
1349     {
1350       return (children[index]);
1351     }
1352   }
1353 }
1354 
1355 /**
1356  * Liefert den Index des ersten Kindes mit dem Namen
1357  * <code>child</code> zur�ck oder -1, wenn es keins gibt.
1358  */
indexOfChild(std::string child)1359 int SimpleXMLTransfer::indexOfChild(std::string child)
1360 {
1361   if (children.size() == 0)
1362     return (-1);
1363 
1364   int index = -1;
1365   int size  = children.size();
1366 
1367   for (int i = 0; i < size && index == -1; i++)
1368     if (child.compare(children[i]->getName()) == 0)
1369       index = i;
1370 
1371   return (index);
1372 }
1373 
indexOfChild(std::string child,int nStartIdx)1374 int SimpleXMLTransfer::indexOfChild(std::string child, int nStartIdx)
1375 {
1376   if (children.size() == 0)
1377     return (-1);
1378 
1379   if (nStartIdx < 0 || nStartIdx >= (int)(children.size()))
1380     nStartIdx = 0;
1381 
1382   int index = -1;
1383   int size  = children.size();
1384 
1385   for (int i = nStartIdx; i < size && index == -1; i++)
1386     if (child.compare(children[i]->getName()) == 0)
1387       index = i;
1388 
1389   if (index < 0)
1390   {
1391     for (int i = 0; i < nStartIdx && index == -1; i++)
1392       if (child.compare(children[i]->getName()) == 0)
1393         index = i;
1394   }
1395 
1396   return (index);
1397 }
1398 
removeChildAt(int nIndex)1399 void SimpleXMLTransfer::removeChildAt(int nIndex)
1400 {
1401   if (children.size() <= (unsigned int) nIndex)
1402     throw
1403     XMLException
1404     ("void SimpleXMLTransfer::removeChildAt(int nIndex): Index out of bounds in "
1405      + getName());
1406 
1407   children.erase(children.begin() + nIndex);
1408 }
1409 
removeChild(SimpleXMLTransfer * XMLPtr)1410 void SimpleXMLTransfer::removeChild(SimpleXMLTransfer* XMLPtr)
1411 {
1412   bool fErr   = true;
1413 
1414   if (children.size())
1415   {
1416     for (unsigned int nIndex=0; nIndex<children.size(); nIndex++)
1417     {
1418       if (children[nIndex] == XMLPtr)
1419       {
1420         fErr = false;
1421         children.erase(children.begin() + nIndex);
1422         nIndex = children.size() + 1;
1423       }
1424     }
1425   }
1426 
1427   if (fErr)
1428     throw
1429     XMLException
1430     ("void SimpleXMLTransfer::removeChild(...): no such child");
1431 }
1432 
replaceChild(SimpleXMLTransfer * XMLPtrOld,SimpleXMLTransfer * XMLPtrNew)1433 void SimpleXMLTransfer::replaceChild(SimpleXMLTransfer* XMLPtrOld,
1434                                      SimpleXMLTransfer* XMLPtrNew)
1435 {
1436   bool fErr   = true;
1437 
1438   if (children.size())
1439   {
1440     for (unsigned int nIndex=0; nIndex<children.size(); nIndex++)
1441     {
1442       if (children[nIndex] == XMLPtrOld)
1443       {
1444         fErr = false;
1445         children[nIndex] = XMLPtrNew;
1446         nIndex = children.size() + 1;
1447       }
1448     }
1449   }
1450 
1451   if (fErr)
1452     throw
1453     XMLException
1454     ("void SimpleXMLTransfer::replaceChild(...): no such child");
1455 }
1456 
1457 /**
1458  * Setzt den Namen.
1459  */
setName(std::string name)1460 void SimpleXMLTransfer::setName(std::string name)
1461 {
1462   myName = name;
1463 }
1464 
1465 /**
1466  * Setzt den Inhalt.
1467  */
setContent(std::string newContent)1468 void SimpleXMLTransfer::setContent(std::string newContent)
1469 {
1470   if (content != (std::string *) 0)
1471     delete content;
1472 
1473   content = new std::string(newContent);
1474 }
1475 
sortChildrenString(std::string attributeName)1476 void SimpleXMLTransfer::sortChildrenString(std::string attributeName)
1477 {
1478   bool fChanged = true;
1479   int n;
1480   int size;
1481   std::string attr1;
1482   std::string attr2;
1483   SimpleXMLTransfer *tmp;
1484 
1485   size = children.size();
1486 
1487   while (fChanged)
1488   {
1489     fChanged = false;
1490 
1491     for (n = 0; n < size - 1; n++)
1492     {
1493       attr1 = children[n]->attribute(attributeName, "");
1494       attr2 = children[n + 1]->attribute(attributeName, "");
1495 
1496       if (attr1.compare(attr2) > 0)
1497       {
1498         tmp = children[n];
1499         children[n] = children[n + 1];
1500         children[n + 1] = tmp;
1501         fChanged = true;
1502       }
1503     }
1504 
1505     if (fChanged == true)
1506     {
1507       fChanged = false;
1508 
1509       for (n = size - 2; n >= 0; n--)
1510       {
1511         attr1 = children[n]->attribute(attributeName, "");
1512         attr2 = children[n + 1]->attribute(attributeName, "");
1513 
1514         if (attr1.compare(attr2) > 0)
1515         {
1516           tmp = children[n];
1517           children[n] = children[n + 1];
1518           children[n + 1] = tmp;
1519           fChanged = true;
1520         }
1521       }
1522     }
1523   }
1524 }
1525 
sortChildrenDouble(std::string attributeName)1526 void SimpleXMLTransfer::sortChildrenDouble(std::string attributeName)
1527 {
1528   bool fChanged = true;
1529   int n;
1530   int size;
1531   double attr1;
1532   double attr2;
1533   SimpleXMLTransfer *tmp;
1534 
1535   size = children.size();
1536 
1537   while (fChanged)
1538   {
1539     fChanged = false;
1540 
1541     for (n = 0; n < size - 1; n++)
1542     {
1543       attr1 = children[n]->attributeAsDouble(attributeName, 0);
1544       attr2 = children[n + 1]->attributeAsDouble(attributeName, 0);
1545 
1546       if (attr1 > attr2)
1547       {
1548         tmp = children[n];
1549         children[n] = children[n + 1];
1550         children[n + 1] = tmp;
1551         fChanged = true;
1552       }
1553     }
1554 
1555     if (fChanged == true)
1556     {
1557       fChanged = false;
1558 
1559       for (n = size - 2; n >= 0; n--)
1560       {
1561         attr1 = children[n]->attributeAsDouble(attributeName, 0);
1562         attr2 = children[n + 1]->attributeAsDouble(attributeName, 0);
1563 
1564         if (attr1 > attr2)
1565         {
1566           tmp = children[n];
1567           children[n] = children[n + 1];
1568           children[n + 1] = tmp;
1569           fChanged = true;
1570         }
1571       }
1572     }
1573   }
1574 }
1575 
delAttribute(std::string attribute)1576 void SimpleXMLTransfer::delAttribute(std::string attribute)
1577 {
1578   int n = indexOfAttribute(attribute);
1579   if (n < 0)
1580     throw XMLException("Attribute named " + attribute +
1581                        " does not exist in " + getName());
1582 
1583   attrName.erase(attrName.begin() + n);
1584   attrVal.erase(attrVal.begin() + n);
1585 }
1586 
equals(SimpleXMLTransfer * item)1587 bool SimpleXMLTransfer::equals(SimpleXMLTransfer* item)
1588 {
1589   int                nSize;
1590   int                nSizeB;
1591   SimpleXMLTransfer* itA;
1592   SimpleXMLTransfer* itB;
1593   bool               fFound;
1594 
1595   // --- Compare name -------------------------------------
1596   if (getName().compare(item->getName()))
1597   {
1598 #if DEBUG == 2
1599     printf("Name differs: %s != %s\n", getName().c_str(), item->getName().c_str());
1600 #endif
1601     return(false);
1602   }
1603 
1604   // --- Compare attributes -------------------------------
1605   // Number of attributes
1606   nSize = getAttributeCount();
1607   if (nSize != item->getAttributeCount())
1608   {
1609 #if DEBUG == 2
1610     printf("different number of attributes\n");
1611 #endif
1612     return(false);
1613   }
1614   // If we have the same number of attributes, it is OK
1615   // if my attributes can be found and are equal to those
1616   // of item.
1617   for (int n=0; n<nSize; n++)
1618   {
1619     if (item->indexOfAttribute(attrName[n]) == -1)
1620     {
1621 #if DEBUG == 2
1622       printf("No attribute %s\n", attrName[n].c_str());
1623 #endif
1624       return(false);
1625     }
1626 
1627     if (item->attribute(attrName[n]).compare(attrVal[n]))
1628     {
1629 #if DEBUG == 2
1630       printf("%s: %s != %s\n", attrName[n].c_str(), attrVal[n].c_str(), item->attribute(attrName[n]).c_str());
1631 #endif
1632       return(false);
1633     }
1634   }
1635 
1636   // --- Compare children ---------------------------------
1637   // Number of children
1638   nSize = getChildCount();
1639   if (nSize != item->getChildCount())
1640   {
1641 #if DEBUG == 2
1642     printf("different number of children\n");
1643 #endif
1644     return(false);
1645   }
1646 
1647   // name and content
1648   nSizeB = item->getChildCount();
1649   for (int n=0; n<nSize; n++)
1650   {
1651     itA = children[n];
1652     // As order does not matter, I have to compare to every child
1653     // of 'item'.
1654     fFound = false;
1655     for (int m=0; m<nSizeB && !fFound; m++)
1656     {
1657       itB = item->getChildAt(m);
1658       if (itA->equals(itB))
1659         fFound = true;
1660     }
1661     if (!fFound)
1662       return(false);
1663   }
1664 
1665   return(true);
1666 }
1667 
1668 
equalsOrdered(SimpleXMLTransfer * item)1669 bool SimpleXMLTransfer::equalsOrdered(SimpleXMLTransfer* item)
1670 {
1671   int                nSize;
1672   SimpleXMLTransfer* itA;
1673   SimpleXMLTransfer* itB;
1674 
1675   // --- Compare name -------------------------------------
1676   if (getName().compare(item->getName()))
1677   {
1678 #if DEBUG == 2
1679     printf("Name differs: %s != %s\n", getName().c_str(), item->getName().c_str());
1680 #endif
1681     return(false);
1682   }
1683 
1684   // --- Compare attributes -------------------------------
1685   // Number of attributes
1686   nSize = getAttributeCount();
1687   if (nSize != item->getAttributeCount())
1688   {
1689 #if DEBUG == 2
1690     printf("different number of attributes\n");
1691 #endif
1692     return(false);
1693   }
1694   // If we have the same number of attributes, it is OK
1695   // if my attributes can be found and are equal to those
1696   // of item.
1697   for (int n=0; n<nSize; n++)
1698   {
1699     if (item->indexOfAttribute(attrName[n]) == -1)
1700     {
1701 #if DEBUG == 2
1702       printf("No attribute %s\n", attrName[n].c_str());
1703 #endif
1704       return(false);
1705     }
1706 
1707     if (item->attribute(attrName[n]).compare(attrVal[n]))
1708     {
1709 #if DEBUG == 2
1710       printf("%s: %s != %s\n", attrName[n].c_str(), attrVal[n].c_str(), item->attribute(attrName[n]).c_str());
1711 #endif
1712       return(false);
1713     }
1714   }
1715 
1716   // --- Compare children ---------------------------------
1717   // Number of children
1718   nSize = getChildCount();
1719   if (nSize != item->getChildCount())
1720   {
1721 #if DEBUG == 2
1722     printf("different number of children\n");
1723 #endif
1724     return(false);
1725   }
1726 
1727   // name and content
1728   for (int n=0; n<nSize; n++)
1729   {
1730     itA = children[n];
1731     itB = item->getChildAt(n);
1732     if (itA->equalsOrdered(itB) == false)
1733       return(false);
1734   }
1735 
1736   return(true);
1737 }
1738 
overwriteAttribute(unsigned int index,std::string val)1739 void SimpleXMLTransfer::overwriteAttribute(unsigned int index, std::string val)
1740 {
1741   if (index > attrName.size())
1742     throw XMLException("No such attribute in " + getName());
1743   else
1744     attrVal[index] = val;
1745 }
1746 
attributeName(unsigned int index)1747 std::string SimpleXMLTransfer::attributeName(unsigned int index)
1748 {
1749   if (index > attrName.size())
1750     throw XMLException("No such attribute in " + getName());
1751   else
1752     return(attrName[index]);
1753 }
1754 
attributeVal(unsigned int index)1755 std::string SimpleXMLTransfer::attributeVal(unsigned int index)
1756 {
1757   if (index > attrVal.size())
1758     throw XMLException("No such attribute in " + getName());
1759   else
1760     return(attrVal[index]);
1761 }
1762 
1763