00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifdef WIN32
00018 #pragma warning(disable:4786)
00019 #pragma warning(disable:4503)
00020 #pragma warning(disable:4996)
00021 #endif
00022
00023 #include "config.h"
00024 #ifdef HAS_SSTREAM
00025 #include <sstream>
00026 #endif
00027
00028 #include <algorithm>
00029 using namespace std;
00030
00031 #include "xml.h"
00032 #include "global.h"
00033 #include "stringUtils.h"
00034 #include <ctype.h>
00035 #include <cstdlib>
00036
00037 namespace Cantera {
00038
00039
00040
00041
00042
00043 class XML_Error : public CanteraError {
00044 protected:
00045
00046
00047
00048
00049
00050
00051
00052
00053 XML_Error(int line=0) :
00054 m_line(line)
00055 {
00056 m_msg = "Error in XML file";
00057 if (line > 0) {
00058 m_msg += " at line " + int2str(line+1);
00059 }
00060 m_msg += ".\n";
00061 }
00062
00063
00064 virtual ~XML_Error() throw() {
00065 }
00066
00067 protected:
00068
00069 int m_line;
00070
00071
00072 std::string m_msg;
00073 };
00074
00075
00076
00077
00078
00079 class XML_TagMismatch : public XML_Error {
00080 public:
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090 XML_TagMismatch(std::string opentag, std::string closetag,
00091 int line=0) :
00092 XML_Error(line)
00093 {
00094 m_msg += "<" + opentag + "> paired with </" + closetag + ">.\n";
00095 setError("XML_TagMismatch", m_msg);
00096 }
00097
00098
00099 virtual ~XML_TagMismatch() throw() {}
00100 };
00101
00102
00103
00104
00105
00106 class XML_NoChild : public XML_Error {
00107 public:
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118 XML_NoChild(const XML_Node* p, std::string parent,
00119 std::string child, int line=0) :
00120 XML_Error(line)
00121 {
00122 m_msg += " The XML Node \"" + parent +
00123 "\", does not contain a required\n" +
00124 " XML child node named \""
00125 + child + "\".\n";
00126 #ifdef HAS_SSTREAM
00127 ostringstream ss(ostringstream::out);
00128 p->write(ss,1);
00129 m_msg += ss.str() + "\n";
00130 #endif
00131 setError("XML_NoChild", m_msg);
00132 }
00133
00134
00135 virtual ~XML_NoChild() throw() {}
00136 };
00137
00138
00139
00140
00141
00142 class XML_IllegalUnits : public XML_Error {
00143 public:
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153 XML_IllegalUnits(std::string name, std::string units, int line=0) :
00154 XML_Error(line)
00155 {
00156 m_msg += "Illegal units (" + units +
00157 ") specified for node " + name + ".\n";
00158 setError("XML_IllegalUnits", m_msg);
00159 }
00160
00161
00162 virtual ~XML_IllegalUnits() throw() {}
00163 };
00164
00165
00166
00167
00168
00169
00170 XML_Reader::XML_Reader(std::istream& input) :
00171 m_s(input),
00172 m_line(0)
00173 {
00174 }
00175
00176
00177
00178
00179
00180
00181 void XML_Reader::getchr(char& ch) {
00182 m_s.get(ch);
00183 if (ch == '\n') {
00184 m_line++;
00185 }
00186 }
00187
00188
00189
00190
00191
00192 std::string XML_Reader::strip(const std::string& aline) const {
00193 int len = static_cast<int>(aline.size());
00194 int i, j, ll;
00195 for (i = len-1; i >= 0; i--) {
00196 ll = aline[i];
00197 if (! isspace(ll)) break;
00198 }
00199 for (j = 0; j < i; j++) {
00200 ll = aline[j];
00201 if (! isspace(ll)) break;
00202 }
00203
00204 return aline.substr(j, i - j + 1);
00205 }
00206
00207
00208
00209
00210
00211
00212 std::string XML_Reader::inquotes(const std::string& aline) const {
00213 int len = static_cast<int>(aline.size());
00214 int i, j;
00215 for (i = len-1; i >= 0; i--)
00216 if (aline[i] == '"') break;
00217 for (j = 0; j < i; j++)
00218 if (aline[j] == '"') break;
00219 if (j == i) return "";
00220 else return aline.substr(j+1, i - j - 1);
00221 }
00222
00223
00224
00225
00226
00227
00228 static string::size_type findUnbackslashed(std::string s, const char q,
00229 std::string::size_type istart = 0) {
00230 string::size_type iloc, icurrent, len;
00231 icurrent = istart;
00232 len = s.size();
00233 while (1) {
00234 iloc = s.find(q, icurrent);
00235 if (iloc == string::npos || iloc == 0) {
00236 return iloc;
00237 }
00238 char cm1 = s[iloc-1];
00239 if (cm1 == '\\') {
00240 if (iloc >= (len -1)) return string::npos;
00241 icurrent = iloc + 1;
00242 } else {
00243 return iloc;
00244 }
00245 }
00246 }
00247
00248
00249
00250
00251
00252
00253
00254
00255 int XML_Reader::findQuotedString(const std::string& s, std::string &rstring) const {
00256 const char q1 = '\'';
00257 const char q2 = '"';
00258 rstring = "";
00259 char qtype = ' ';
00260 string::size_type iloc1, iloc2, ilocStart = 0;
00261 iloc1 = findUnbackslashed(s, q1);
00262 iloc2 = findUnbackslashed(s, q2);
00263 if (iloc2 != string::npos) {
00264 ilocStart = iloc2;
00265 qtype = q2;
00266 }
00267 if (iloc1 != string::npos) {
00268 if (iloc1 < ilocStart) {
00269 ilocStart = iloc1;
00270 qtype = q1;
00271 }
00272 }
00273 if (qtype == ' ') return 0;
00274
00275 iloc1 = findUnbackslashed(s, qtype, ilocStart+1);
00276
00277 if (iloc1 == string::npos) {
00278 return 0;
00279 }
00280
00281
00282
00283
00284 rstring = s.substr(ilocStart + 1, iloc1 - 1);
00285
00286
00287
00288 return static_cast<int>(iloc1)+1;
00289 }
00290
00291
00292
00293
00294
00295 void XML_Reader::parseTag(std::string tag, std::string& name,
00296 std::map<std::string, std::string>& attribs) const {
00297 string::size_type iloc;
00298 string attr, val;
00299 string s = strip(tag);
00300 iloc = s.find(' ');
00301 if (iloc != string::npos) {
00302 name = s.substr(0, iloc);
00303 s = strip(s.substr(iloc+1,s.size()));
00304 if (s[s.size()-1] == '/') {
00305 name += "/";
00306 }
00307
00308
00309 while (1) {
00310 iloc = s.find('=');
00311 if (iloc == string::npos) break;
00312 attr = strip(s.substr(0,iloc));
00313 if (attr == "") break;
00314 s = strip(s.substr(iloc+1,s.size()));
00315 iloc = findQuotedString(s, val);
00316 attribs[attr] = val;
00317 if (iloc != string::npos) {
00318 if (iloc < s.size())
00319 s = strip(s.substr(iloc,s.size()));
00320 else
00321 break;
00322 }
00323 }
00324 }
00325 else {
00326 name = s;
00327 }
00328 }
00329
00330 std::string XML_Reader::readTag(std::map<std::string, std::string>& attribs) {
00331 string name, tag = "";
00332 bool incomment = false;
00333 char ch = '-';
00334 while (1) {
00335 if (m_s.eof() || (getchr(ch), ch == '<')) break;
00336 }
00337 char ch1 = ' ', ch2 = ' ';
00338 while (1) {
00339 if (m_s.eof()) { tag = "EOF"; break;}
00340 ch2 = ch1;
00341 ch1 = ch;
00342 getchr(ch);
00343 if (ch == '-') {
00344 if (ch1 == '-' && ch2 == '!') {
00345 incomment = true;
00346 tag = "-";
00347 }
00348 }
00349 else if (ch == '>') {
00350 if (incomment) {
00351 if (ch1 == '-' && ch2 == '-') break;
00352 }
00353 else
00354 break;
00355 }
00356 if (isprint(ch)) tag += ch;
00357 }
00358 if (incomment) {
00359 attribs.clear();
00360 return tag;
00361 }
00362 else {
00363 parseTag(tag, name, attribs);
00364 return name;
00365 }
00366 }
00367
00368 std::string XML_Reader::readValue() {
00369 string tag = "";
00370 char ch, lastch;
00371 ch = '\n';
00372 bool front = true;
00373 while (1) {
00374 if (m_s.eof()) break;
00375 lastch = ch;
00376 getchr(ch);
00377 if (ch == '\n')
00378 front = true;
00379 else if (ch != ' ')
00380 front = false;
00381 if (ch == '<') {
00382 m_s.putback(ch);
00383 break;
00384 }
00385 if (front && lastch == ' ' && ch == ' ') ;
00386 else tag += ch;
00387 }
00388 return strip(tag);
00389 }
00390
00391
00392
00393
00394 XML_Node::XML_Node(const char * cnm)
00395 : m_value(""),
00396 m_parent(0),
00397 m_locked(false),
00398 m_nchildren(0),
00399 m_iscomment(false)
00400 {
00401 if (! cnm) {
00402 m_name = "--";
00403 } else {
00404 m_name = cnm;
00405 }
00406 m_root = this;
00407 }
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420 XML_Node::XML_Node(const std::string nm, XML_Node * const p)
00421 : m_name(nm),
00422 m_value(""),
00423 m_parent(p),
00424 m_locked(false),
00425 m_nchildren(0),
00426 m_iscomment(false)
00427 {
00428 if (!p) m_root = this;
00429 else m_root = &p->root();
00430 }
00431
00432
00433
00434
00435
00436 XML_Node::XML_Node(const XML_Node &right) :
00437 m_name(""),
00438 m_value(""),
00439 m_parent(0),
00440 m_locked(false),
00441 m_nchildren(0),
00442 m_iscomment(false)
00443 {
00444 m_root = this;
00445 right.copy(this);
00446 }
00447
00448
00449
00450
00451
00452 XML_Node & XML_Node::operator=(const XML_Node &right)
00453 {
00454 if (&right != this) {
00455 int n = static_cast<int>(m_children.size());
00456 for (int i = 0; i < n; i++) {
00457 if (m_children[i]) {
00458 if (m_children[i]->parent() == this) {
00459 delete m_children[i];
00460 m_children[i] = 0;
00461 }
00462 }
00463 }
00464 m_children.resize(0);
00465 right.copy(this);
00466 }
00467 return *this;
00468 }
00469
00470
00471 XML_Node::~XML_Node() {
00472 if (m_locked)
00473 throw CanteraError("XML_Node::~XML_Node",
00474 "attempt to delete locked XML_Node "+name());
00475 int n = static_cast<int>(m_children.size());
00476 for (int i = 0; i < n; i++) {
00477 if (m_children[i]) {
00478 if (m_children[i]->parent() == this) {
00479 delete m_children[i];
00480 m_children[i] = 0;
00481 }
00482 }
00483 }
00484 }
00485
00486 void XML_Node::clear() {
00487 int n = static_cast<int>(m_children.size());
00488 for (int i = 0; i < n; i++) {
00489 if (m_children[i]) {
00490 if (m_children[i]->parent() == this) {
00491 delete m_children[i];
00492 m_children[i] = 0;
00493 }
00494 }
00495 }
00496 m_value.clear();
00497 m_childindex.clear();
00498 m_attribs.clear();
00499 m_children.clear();
00500
00501 m_nchildren = 0;
00502 m_iscomment = false;
00503 m_linenum = 0;
00504
00505 }
00506
00507
00508
00509
00510
00511
00512
00513 void XML_Node::addComment(const std::string &comment) {
00514 addChild("comment", comment);
00515 }
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527 XML_Node& XML_Node::addChild(XML_Node& node) {
00528 m_children.push_back(&node);
00529 m_nchildren = static_cast<int>(m_children.size());
00530 m_childindex[node.name()] = m_children.back();
00531 node.setRoot(root());
00532 node.setParent(this);
00533 return *m_children.back();
00534 }
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545 XML_Node& XML_Node::addChild(const std::string &sname) {
00546 XML_Node *xxx = new XML_Node(sname, this);
00547 m_children.push_back(xxx);
00548 m_nchildren = static_cast<int>(m_children.size());
00549 m_childindex[sname] = m_children.back();
00550 xxx->setRoot(root());
00551 xxx->setParent(this);
00552 return *m_children.back();
00553 }
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565 XML_Node& XML_Node::addChild(const std::string &name, const std::string &value) {
00566 XML_Node& c = addChild(name);
00567 c.addValue(value);
00568 return c;
00569 }
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586 XML_Node& XML_Node::addChild(const std::string &name, const doublereal value,
00587 const std::string fmt) {
00588 XML_Node& c = addChild(name);
00589 c.addValue(value, fmt);
00590 return c;
00591 }
00592
00593
00594
00595
00596
00597
00598
00599
00600 void XML_Node::removeChild(const XML_Node * const node) {
00601 vector<XML_Node*>::iterator i;
00602 i = find(m_children.begin(), m_children.end(), node);
00603 m_children.erase(i);
00604 m_nchildren = static_cast<int>(m_children.size());
00605 m_childindex.erase(node->name());
00606 }
00607
00608 std::string XML_Node::id() const {
00609 if (hasAttrib("id")) return attrib("id");
00610 return std::string("");
00611 }
00612
00613
00614
00615
00616
00617
00618
00619 void XML_Node::addValue(const std::string &val) {
00620 m_value = val;
00621 if (m_name == "comment") m_iscomment = true;
00622 }
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633 void XML_Node::addValue(const doublereal val, const std::string fmt) {
00634 m_value = stripws(fp2str(val, fmt));
00635 }
00636
00637
00638
00639
00640
00641 std::string XML_Node::value() const {
00642 return m_value;
00643 }
00644
00645
00646
00647
00648
00649 std::string XML_Node::operator()() const {
00650 return m_value;
00651 }
00652
00653
00654
00655
00656
00657
00658 doublereal XML_Node::fp_value() const {
00659 return atofCheck(m_value.c_str());
00660 }
00661
00662
00663
00664
00665
00666
00667 integer XML_Node::int_value() const {
00668 return std::atoi(m_value.c_str());
00669 }
00670
00671
00672
00673
00674
00675
00676 std::string XML_Node::value(const std::string &cname) const {
00677 return child(cname).value();
00678 }
00679
00680
00681
00682
00683
00684
00685
00686 std::string XML_Node::operator()(std::string loc) const {
00687 return value(loc);
00688 }
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698 void XML_Node::addAttribute(const std::string & attrib, const std::string & value) {
00699 m_attribs[attrib] = value;
00700 }
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712 void XML_Node::addAttribute(const std::string & attrib,
00713 const doublereal value, const std::string fmt) {
00714 m_attribs[attrib] = fp2str(value, fmt);
00715 }
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732 std::string XML_Node::operator[](const std::string & attr) const {
00733 return attrib(attr);
00734 }
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749 std::string XML_Node::attrib(const std::string & attr) const {
00750 std::map<std::string,std::string>::const_iterator i = m_attribs.find(attr);
00751 if (i != m_attribs.end()) return i->second;
00752 return "";
00753 }
00754
00755
00756
00757
00758
00759
00760 std::map<std::string,std::string>& XML_Node::attribs() {
00761 return m_attribs;
00762 }
00763
00764
00765
00766
00767
00768 void XML_Node::setLineNumber(const int n) {
00769 m_linenum = n;
00770 }
00771
00772
00773
00774
00775
00776 int XML_Node::lineNumber() const {
00777 return m_linenum;
00778 }
00779
00780
00781 XML_Node* XML_Node::parent() const {
00782 return m_parent;
00783 }
00784
00785
00786
00787
00788
00789
00790
00791 XML_Node* XML_Node::setParent(XML_Node * const p) {
00792 m_parent = p;
00793 return p;
00794 }
00795
00796
00797
00798
00799
00800
00801
00802 bool XML_Node::hasChild(const std::string ch) const {
00803 return (m_childindex.find(ch) != m_childindex.end());
00804 }
00805
00806
00807
00808
00809
00810
00811
00812 bool XML_Node::hasAttrib(std::string a) const {
00813 return (m_attribs.find(a) != m_attribs.end());
00814 }
00815
00816
00817
00818
00819
00820 XML_Node& XML_Node::child(const int n) const {
00821 return *m_children[n];
00822 }
00823
00824
00825
00826
00827
00828
00829
00830
00831 const std::vector<XML_Node*>& XML_Node::children() const {
00832 return m_children;
00833 }
00834
00835
00836
00837
00838
00839 int XML_Node::nChildren() const {
00840 return m_nchildren;
00841 }
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852 void XML_Node::_require(const std::string &a, const std::string &v) const {
00853 if (hasAttrib(a)) {
00854 if (attrib(a) == v) return;
00855 }
00856 string msg="XML_Node "+name()+" is required to have an attribute named " + a +
00857 " with the value \"" + v +"\", but instead the value is \"" + attrib(a);
00858 throw CanteraError("XML_Node::require", msg);
00859 }
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882 XML_Node* XML_Node::
00883 findNameID(const std::string & nameTarget,
00884 const std::string & idTarget) const {
00885 XML_Node *scResult = 0;
00886 XML_Node *sc;
00887 std::string idattrib = id();
00888 int n;
00889 if (name() == nameTarget) {
00890 if (idTarget == "" || idTarget == idattrib) {
00891 return const_cast<XML_Node*>(this);
00892 }
00893 }
00894 for (n = 0; n < m_nchildren; n++) {
00895 sc = m_children[n];
00896 if (sc->name() == nameTarget) {
00897 if (idTarget == "") return sc;
00898 idattrib = sc->id();
00899 if (idTarget == idattrib) return sc;
00900 }
00901 }
00902 for (n = 0; n < m_nchildren; n++) {
00903 sc = m_children[n];
00904 scResult = sc->findNameID(nameTarget, idTarget);
00905 if (scResult) return scResult;
00906 }
00907 return scResult;
00908 }
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930 XML_Node* XML_Node::findID(const std::string & id, const int depth) const {
00931 if (hasAttrib("id")) {
00932 if (attrib("id") == id) {
00933 return const_cast<XML_Node*>(this);
00934 }
00935 }
00936 if (depth > 0) {
00937 XML_Node* r = 0;
00938 int n = nChildren();
00939 for (int i = 0; i < n; i++) {
00940 r = m_children[i]->findID(id, depth-1);
00941 if (r != 0) return r;
00942 }
00943 }
00944 return 0;
00945 }
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962 XML_Node* XML_Node::findByAttr(const std::string& attr,
00963 const std::string& val) const {
00964 if (hasAttrib(attr)) {
00965 if (attrib(attr) == val) {
00966 return const_cast<XML_Node*>(this);
00967 }
00968 }
00969 XML_Node* r = 0;
00970 int n = nChildren();
00971 for (int i = 0; i < n; i++) {
00972 r = m_children[i]->findByAttr(attr, val);
00973 if (r != 0) return r;
00974 }
00975 return 0;
00976 }
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989 XML_Node* XML_Node::findByName(const std::string& nm) {
00990 if (name() == nm) {
00991 return this;
00992 }
00993 XML_Node* r = 0;
00994 int n = nChildren();
00995 for (int i = 0; i < n; i++) {
00996 r = m_children[i]->findByName(nm);
00997 if (r != 0) return r;
00998 }
00999 return 0;
01000 }
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013 const XML_Node* XML_Node::findByName(const std::string& nm) const {
01014 if (name() == nm) {
01015 return const_cast<XML_Node*>(this);
01016 }
01017 const XML_Node* r = 0;
01018 int n = nChildren();
01019 for (int i = 0; i < n; i++) {
01020 r = m_children[i]->findByName(nm);
01021 if (r != 0) return r;
01022 }
01023 return 0;
01024 }
01025
01026
01027
01028
01029
01030 void XML_Node::writeHeader(std::ostream& s) {
01031 s << "<?xml version=\"1.0\"?>" << endl;
01032 }
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042 void XML_Node::build(std::istream& f) {
01043 XML_Reader r(f);
01044 string nm, nm2, val;
01045 XML_Node* node = this;
01046 map<string, string> attribs;
01047 while (!f.eof()) {
01048 attribs.clear();
01049 nm = r.readTag(attribs);
01050
01051 if (nm == "EOF") break;
01052 if (nm == "--" && m_name == "--" && m_root == this) {
01053 continue;
01054 }
01055 int lnum = r.m_line;
01056 if (nm[nm.size() - 1] == '/') {
01057 nm2 = nm.substr(0,nm.size()-1);
01058 node = &node->addChild(nm2);
01059 node->addValue("");
01060 node->attribs() = attribs;
01061 node->setLineNumber(lnum);
01062 node = node->parent();
01063 }
01064 else if (nm[0] != '/') {
01065 if (nm[0] != '!' && nm[0] != '-' && nm[0] != '?') {
01066 node = &node->addChild(nm);
01067 val = r.readValue();
01068 node->addValue(val);
01069 node->attribs() = attribs;
01070 node->setLineNumber(lnum);
01071 }
01072 else if (nm.substr(0,2) == "--") {
01073 if (nm.substr(nm.size()-2,2) == "--") {
01074 node->addComment(nm.substr(2,nm.size()-4));
01075 }
01076 }
01077 }
01078 else {
01079 if (node->name() != nm.substr(1,nm.size()-1))
01080 throw XML_TagMismatch(node->name(),
01081 nm.substr(1,nm.size()-1), lnum);
01082 node = node->parent();
01083 }
01084 }
01085 }
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097 void XML_Node::copyUnion(XML_Node * const node_dest) const {
01098 XML_Node *sc, *dc;
01099 int ndc, idc;
01100 node_dest->addValue(m_value);
01101 if (m_name == "") return;
01102 map<string,string>::const_iterator b = m_attribs.begin();
01103 for (; b != m_attribs.end(); ++b) {
01104 if (! node_dest->hasAttrib(b->first)) {
01105 node_dest->addAttribute(b->first, b->second);
01106 }
01107 }
01108 const vector<XML_Node*> &vsc = node_dest->children();
01109 for (int n = 0; n < m_nchildren; n++) {
01110 sc = m_children[n];
01111 ndc = node_dest->nChildren();
01112 dc = 0;
01113 if (! sc->m_iscomment) {
01114 for (idc = 0; idc < ndc; idc++) {
01115 XML_Node *dcc = vsc[idc];
01116 if (dcc->name() == sc->name()) {
01117 if (sc->hasAttrib("id")) {
01118 if (sc->attrib("id") != dcc->attrib("id")) break;
01119 }
01120 if (sc->hasAttrib("name")) {
01121 if (sc->attrib("name") != dcc->attrib("name")) break;
01122 }
01123 if (sc->hasAttrib("model")) {
01124 if (sc->attrib("model") != dcc->attrib("model")) break;
01125 }
01126 if (sc->hasAttrib("title")) {
01127 if (sc->attrib("title") != dcc->attrib("title")) break;
01128 }
01129 dc = vsc[idc];
01130 }
01131 }
01132 }
01133 if (!dc) {
01134 (void) node_dest->addChild(sc->name());
01135 dc = vsc[ndc];
01136 }
01137 sc->copyUnion(dc);
01138 }
01139 }
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150 void XML_Node::copy(XML_Node * const node_dest) const {
01151 XML_Node *sc, *dc;
01152 int ndc;
01153 node_dest->addValue(m_value);
01154 node_dest->setName(m_name);
01155 if (m_name == "") return;
01156 map<string,string>::const_iterator b = m_attribs.begin();
01157 for (; b != m_attribs.end(); ++b) {
01158 node_dest->addAttribute(b->first, b->second);
01159 }
01160 const vector<XML_Node*> &vsc = node_dest->children();
01161
01162 for (int n = 0; n < m_nchildren; n++) {
01163 sc = m_children[n];
01164 ndc = node_dest->nChildren();
01165 (void) node_dest->addChild(sc->name());
01166 dc = vsc[ndc];
01167 sc->copy(dc);
01168 }
01169 }
01170
01171
01172 void XML_Node::lock() {
01173 m_locked = true;
01174 for (int i = 0; i < m_nchildren; i++) {
01175 m_children[i]->lock();
01176 }
01177 }
01178
01179
01180 void XML_Node::unlock() {
01181 m_locked = false;
01182 for (int i = 0; i < m_nchildren; i++) {
01183 m_children[i]->unlock();
01184 }
01185 }
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195 void XML_Node::getChildren(const std::string &nm,
01196 std::vector<XML_Node*>& children) const {
01197 int i, n = nChildren();
01198 for (i = 0; i < n; i++) {
01199 if (child(i).name() == nm) {
01200 children.push_back(&child(i));
01201 }
01202 }
01203 }
01204
01205
01206
01207
01208
01209
01210 XML_Node& XML_Node::child(const std::string &aloc) const {
01211 string::size_type iloc;
01212 string cname;
01213 string loc = aloc;
01214 std::map<std::string,XML_Node*>::const_iterator i;
01215
01216 while (1) {
01217 iloc = loc.find('/');
01218 if (iloc != string::npos) {
01219 cname = loc.substr(0,iloc);
01220 loc = loc.substr(iloc+1, loc.size());
01221 i = m_childindex.find(cname);
01222 if (i != m_childindex.end()) return i->second->child(loc);
01223 else {
01224 throw XML_NoChild(this, m_name, cname, lineNumber());
01225 }
01226 }
01227 else {
01228 i = m_childindex.find(loc);
01229 if (i != m_childindex.end()) return *(i->second);
01230 else {
01231 throw XML_NoChild(this, m_name, loc, lineNumber());
01232 }
01233 }
01234 }
01235 }
01236
01237
01238
01239
01240
01241
01242 void XML_Node::write_int(std::ostream& s, int level) const {
01243
01244 if (m_name == "") return;
01245
01246 string indent(level, ' ');
01247 if (m_iscomment) {
01248
01249
01250
01251
01252
01253 s << endl << indent << "<!--";
01254 if (! isspace(m_value[0])) {
01255 s << " ";
01256 }
01257 s << m_value;
01258 int ll = static_cast<int>(m_value.size()) - 1;
01259 if (! isspace(m_value[ll])) {
01260 s << " ";
01261 }
01262 s << "-->";
01263 return;
01264 }
01265
01266 s << indent << "<" << m_name;
01267 map<string,string>::const_iterator b = m_attribs.begin();
01268 for (; b != m_attribs.end(); ++b) {
01269 s << " " << b->first << "=\"" << b->second << "\"";
01270 }
01271 if (m_value == "" && m_nchildren == 0) {
01272 s << "/>";
01273 }
01274 else {
01275 s << ">";
01276
01277 if (m_value != "") {
01278 string vv = m_value;
01279 string::size_type ieol = vv.find('\n');
01280 if (ieol != string::npos) {
01281 while (1 > 0) {
01282 ieol = vv.find('\n');
01283 if (ieol != string::npos) {
01284 if (ieol == 0) {
01285 s << endl << indent << " ";
01286 } else {
01287 int jf = ieol - 1;
01288 for (int j = 0; j < (int) ieol; j++) {
01289 if (! isspace(vv[j])) {
01290 jf = j;
01291 break;
01292 }
01293 }
01294 s << endl << indent << " " << vv.substr(jf,ieol-jf);
01295 }
01296 vv = vv.substr(ieol+1);
01297 }
01298 else {
01299 int lll = static_cast<int>(vv.size()) - 1;
01300 if (lll >= 0) {
01301 int jf = lll;
01302 for (int j = 0; j < lll; j++) {
01303 if (! isspace(vv[j])) {
01304 jf = j;
01305 break;
01306 }
01307 }
01308 if (jf < lll) {
01309 s << endl << indent << " " << vv.substr(jf);
01310 }
01311 }
01312 break;
01313 }
01314 }
01315 s << endl << indent;
01316 }
01317 else {
01318 bool doSpace = true;
01319 bool doNewLine = false;
01320 int ll = static_cast<int>(m_value.size()) - 1;
01321 if (ll > 15) {
01322 doNewLine = true;
01323 }
01324 if (m_name == "floatArray") {
01325 doNewLine = true;
01326 }
01327 if (doNewLine) doSpace = false;
01328
01329 if (doNewLine) {
01330 s << endl << indent << " ";
01331 }
01332
01333
01334
01335 if (doSpace && (! isspace(m_value[0]))) {
01336 s << " ";
01337 }
01338
01339
01340
01341 s << m_value;
01342
01343 if (doSpace && (! isspace(m_value[ll]))) {
01344 s << " ";
01345 }
01346 if (doNewLine) {
01347 s << endl << indent;
01348 }
01349 }
01350 }
01351 int i;
01352 for (i = 0; i < m_nchildren; i++) {
01353 s << endl;
01354 m_children[i]->write_int(s,level + 2);
01355 }
01356 if (m_nchildren > 0) s << endl << indent;
01357 s << "</" << m_name << ">";
01358 }
01359 }
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371 void XML_Node::write(std::ostream& s, const int level) const {
01372 if (m_name == "--" && m_root == this) {
01373 for (int i = 0; i < m_nchildren; i++) {
01374 m_children[i]->write_int(s,level);
01375 s << endl;
01376 }
01377 } else {
01378 write_int(s, level);
01379 s << endl;
01380 }
01381 }
01382
01383 XML_Node& XML_Node::root() const {
01384 return *m_root;
01385 }
01386
01387 void XML_Node::setRoot(const XML_Node& root) {
01388 m_root = const_cast<XML_Node*>(&root);
01389 }
01390
01391 XML_Node * findXMLPhase(XML_Node *root,
01392 const std::string &idtarget) {
01393 XML_Node *scResult = 0;
01394 XML_Node *sc;
01395 if (!root) return 0;
01396 string idattrib;
01397 string rname = root->name();
01398 if (rname == "phase") {
01399 if (idtarget == "") return root;
01400 idattrib = root->id();
01401 if (idtarget == idattrib) return root;
01402 else return 0;
01403 }
01404
01405 const vector<XML_Node*> &vsc = root->children();
01406 int n;
01407 for (n = 0; n < root->nChildren(); n++) {
01408 sc = vsc[n];
01409 if (sc->name() == "phase") {
01410 if (idtarget == "") return sc;
01411 idattrib = sc->id();
01412 if (idtarget == idattrib) return sc;
01413 }
01414 }
01415 for (n = 0; n < root->nChildren(); n++) {
01416 sc = vsc[n];
01417 if (sc->name() != "phase") {
01418 scResult = findXMLPhase(sc, idtarget);
01419 if (scResult) return scResult;
01420 }
01421 }
01422 return scResult;
01423 }
01424
01425 }
01426
01427