00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifdef HAVE_CONFIG_H
00020 # include <config.h>
00021 #endif
00022
00023 #ifndef ALPHA_LINUX_CXX
00024 # include <cassert>
00025 #endif
00026 #include "common_types.h"
00027 #include "XMLEntity.h"
00028 #include <iostream>
00029
00030 using std::string;
00031 using std::vector;
00032 using std::ostream;
00033 using std::endl;
00034
00035 static string encode_entity(const string &s);
00036 static string close_tag(const string &s);
00037
00038 XMLnode::~XMLnode()
00039 {
00040 for(std::vector<XMLnode *>::iterator i=nodelist.begin(); i!=nodelist.end(); ++i)
00041 delete *i;
00042 }
00043
00044 const string &XMLnode::reference(const string &h,bool &exists)
00045 {
00046 if(h.find('/')==string::npos)
00047 {
00048
00049 if(id==h)
00050 {
00051 exists = true;
00052 return content;
00053 }
00054 }
00055 else
00056 {
00057
00058
00059
00060
00061 string k;
00062 k=h.substr(h.find('/')+1);
00063 string k2=k.substr(0,k.find('/'));
00064 for(std::vector<XMLnode*>::iterator it=nodelist.begin();
00065 it!=nodelist.end();++it)
00066 {
00067 if((*it)->id==k2)
00068 return (*it)->reference(k,exists);
00069 }
00070 }
00071
00072 exists = false;
00073 return c_empty_string;
00074 }
00075
00076
00077 const XMLnode *XMLnode::subtree(const string &h) const
00078 {
00079 if(h.find('/') == string::npos)
00080 {
00081
00082 if(id == h)
00083 return this;
00084 }
00085 else
00086 {
00087
00088
00089
00090
00091 string k;
00092 k=h.substr(h.find('/')+1);
00093 string k2=k.substr(0,k.find('/'));
00094 for(std::vector<XMLnode*>::const_iterator it=nodelist.begin();
00095 it!=nodelist.end();++it)
00096 {
00097 if((*it)->id==k2)
00098 return (*it)->subtree(k);
00099 }
00100 }
00101
00102 return 0;
00103 }
00104
00105
00106 string XMLnode::dump(int depth)
00107 {
00108 string s(depth,' ');
00109
00110 s+="<";
00111 s+=id;
00112 s+=">\n";
00113 if(id[id.length()-1]!='/')
00114 {
00115 for(std::vector<XMLnode*>::const_iterator it=nodelist.begin();
00116 it!=nodelist.end();
00117 ++it)
00118 {
00119 s += (**it).dump(depth+1);
00120 }
00121
00122 if(content.length())
00123 {
00124 s += string(depth,' ');
00125 s += encode_entity(content);
00126 }
00127 if(id[0]=='?')
00128 {
00129 return s;
00130 }
00131 if(content.length())
00132 s += "\n";
00133
00134 if(!no_close)
00135 {
00136 s += string(depth,' ');
00137
00138 s += "</";
00139 s += close_tag(id);
00140 s += ">\n";
00141 }
00142 }
00143
00144 return s;
00145 }
00146
00147
00148
00149 void XMLnode::dump(ostream &o, const string &indentstr, const unsigned int depth) const
00150 {
00151
00152 for(unsigned int i=0; i<depth; i++)
00153 o << indentstr;
00154
00155
00156 o << '<' << id << '>';
00157
00158
00159 if(id[id.length()-1]!='/')
00160 {
00161
00162 if(nodelist.size())
00163 {
00164 o << endl;
00165
00166
00167 for(std::vector<XMLnode *>::const_iterator it=nodelist.begin(); it!=nodelist.end(); ++it)
00168 (*it)->dump(o, indentstr, depth+1);
00169 }
00170
00171 else if(content.length())
00172 o << ' ' << encode_entity(content) << ' ';
00173
00174
00175 if(id[0]=='?')
00176 return;
00177
00178
00179 if(!no_close)
00180 {
00181
00182 if(nodelist.size())
00183 for(unsigned int i=0; i<depth; i++)
00184 o << indentstr;
00185
00186 o << "</" << close_tag(id) << '>';
00187 }
00188 }
00189 o << endl;
00190 }
00191
00192
00193 void XMLnode::xmlassign(const string &key, const string &value)
00194 {
00195 if(key.find('/')==string::npos)
00196 {
00197
00198 if(id==key)
00199 content = value;
00200 else
00201 CERR("Walking the XML tree failed to create a final node.");
00202 return;
00203 }
00204 string k;
00205 k=key.substr(key.find('/')+1);
00206 string k2=k.substr(0,k.find('/'));
00207 for(std::vector<XMLnode*>::iterator it=nodelist.begin();it!=nodelist.end();++it)
00208 {
00209 if((*it)->id==k2)
00210 {
00211 (**it).xmlassign(k,value);
00212 return;
00213 }
00214 }
00215
00216
00217 XMLnode *t = new XMLnode(k2);
00218 nodelist.push_back(t);
00219 (*t).xmlassign(k,value);
00220 }
00221
00222
00223 void XMLnode::listkeys(const string &key,vector<string> &vs, bool longformat) const
00224 {
00225 string s(key);
00226 s+="/";
00227
00228 for(std::vector<XMLnode*>::const_iterator it=nodelist.begin();
00229 it!=nodelist.end(); ++it)
00230 {
00231 if(!longformat)
00232 vs.push_back((*it)->id);
00233 else
00234 vs.push_back(s + (*it)->id);
00235 }
00236 }
00237
00238 static string encode_entity(const string &s)
00239 {
00240 string ret;
00241
00242 for(string::const_iterator it=s.begin();it!=s.end();++it)
00243 {
00244 switch(*it)
00245 {
00246 case '<':
00247 ret+="<";
00248 break;
00249 case '>':
00250 ret+=">";
00251 break;
00252 case '"':
00253 ret+=""";
00254 break;
00255 case '\'':
00256 ret+="'";
00257 break;
00258 case '&':
00259 ret+="&";
00260 break;
00261 default:
00262 ret += *it;
00263 }
00264 }
00265 return ret;
00266 }
00267
00268 static string decode_entity(const string &s, std::size_t &pos)
00269 {
00270 std::size_t old_pos = pos;
00271 string::size_type entity_name_len = s.find_first_of("; \t\r\n", pos) -pos -1;
00272
00273
00274
00275 assert(s[pos+entity_name_len+1]==';');
00276
00277 string entity_name = s.substr(pos+1, entity_name_len);
00278
00279 pos += entity_name_len + 2;
00280
00281
00282
00283 if (entity_name == "amp") return string("&");
00284 else if(entity_name == "apos") return string("'");
00285 else if(entity_name == "quot") return string("\"");
00286 else if(entity_name == "lt") return string("<");
00287 else if(entity_name == "gt") return string(">");
00288
00289 return s.substr(old_pos, entity_name_len+2);
00290 }
00291
00292 static string close_tag(const string &s)
00293 {
00294 if(s.find(" ")==string::npos)
00295 return s;
00296
00297 return s.substr(0,s.find(" "));
00298 }
00299
00300
00301 static void trim(string &s)
00302 {
00303
00304 while(s.length()&&s[0]<=32)
00305 {
00306 s=s.substr(1);
00307 }
00308
00309 while(s.length()&&s[s.length()-1]<=32)
00310 {
00311 s.erase(s.length()-1);
00312 }
00313 }
00314
00315 void XMLnode::xmlparse(const string &s,std::size_t &pos)
00316 {
00317 bool intag = true;
00318
00319 id = "";
00320 while(pos<s.length())
00321 {
00322 switch(s[pos])
00323 {
00324 case '<':
00325 {
00326
00327 if(s[pos+1]=='/')
00328 {
00329
00330 while(s[pos]!='>')
00331 pos++;
00332 ++pos;
00333 trim(content);
00334 return;
00335 }
00336 XMLnode *t = new XMLnode;
00337 ++pos;
00338 t->xmlparse(s,pos);
00339 nodelist.push_back(t);
00340 break;
00341 }
00342 case '>':
00343
00344 if(s[pos-1]=='/')
00345 {
00346 if(s[pos-2]=='<')
00347 {
00348 ++pos;
00349 return;
00350 }
00351 else
00352 {
00353 ++pos;
00354 no_close=true;
00355 return;
00356 }
00357 }
00358 else if((id[0]=='!') && (id[1]=='-') && (id[2]=='-'))
00359 {
00360 ++pos;
00361 no_close=true;
00362 return;
00363 }
00364 ++pos;
00365 intag = false;
00366 if(s[pos]<32)
00367 ++pos;
00368 break;
00369 case '&':
00370 content+=decode_entity(s,pos);
00371 break;
00372 default:
00373 if(intag)
00374 id += s[pos++];
00375 else
00376 content += s[pos++];
00377 }
00378 }
00379 trim(content);
00380 }
00381
00382
00383
00384
00385 bool XMLnode::searchpairs(KeyTypeList &ktl, const string &basekey, const string currkey, const unsigned int pos)
00386 {
00387
00388
00389
00390 if((currkey.size()<=basekey.size()) && (id[0]!='!'))
00391 {
00392
00393
00394 if(basekey==currkey+id)
00395 {
00396 for(std::vector<XMLnode *>::iterator i=nodelist.begin(); i!=nodelist.end(); ++i)
00397 if((*i)->id[0]!='!')
00398 (*i)->selectpairs(ktl, "");
00399 return true;
00400 }
00401
00402 else
00403 for(std::vector<XMLnode *>::iterator i=nodelist.begin(); i!=nodelist.end(); ++i)
00404 if((*i)->searchpairs(ktl, basekey, currkey + id + '/', pos)==true)
00405 return true;
00406 }
00407 return false;
00408 }
00409
00410
00411 void XMLnode::selectpairs(KeyTypeList &ktl, const std::string currkey)
00412 {
00413 ktl.push_back(KeyType(currkey + id, content));
00414
00415 for(std::vector<XMLnode *>::iterator i=nodelist.begin(); i!=nodelist.end(); ++i)
00416 (*i)->selectpairs(ktl, currkey + id + '/');
00417 }
00418
00419
00420
00421
00422