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><</code>,
823 * <code>></code>,
824 * <code>&</code>,
825 * <code>"</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