00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00045
00046 #include "xmlparser.h"
00047
00048
00049 namespace cppdom
00050 {
00051
00052 XMLParser::XMLParser(std::istream& in, XMLLocation& loc)
00053 : mInput(in), mTokenizer(in, loc)
00054 {}
00055
00056 bool XMLParser::parseDocument(XMLDocument& doc, XMLContextPtr& context)
00057 {
00058
00059 doc.mContext = context;
00060 std::string rootstr("root");
00061 doc.mNodeNameHandle = context->insertTagname(rootstr);
00062
00063 bool handle = context->handleEvents();
00064
00065
00066 if (handle)
00067 {
00068 context->getEventHandler().startDocument();
00069 }
00070
00071 parseHeader(doc, context);
00072
00073
00074 XMLNodePtr new_subnode(new XMLNode(context));
00075
00076 bool ret = parseNode(*new_subnode, context);
00077
00078
00079 if (ret)
00080 {
00081 doc.addChild(new_subnode);
00082 }
00083
00084 if (handle)
00085 {
00086 context->getEventHandler().endDocument();
00087 }
00088
00089 return ret;
00090 }
00091
00092
00094
00095 {
00096 while(true)
00097 {
00098 ++mTokenizer;
00099 XMLToken token1 = *mTokenizer;
00100 if (token1 != '<')
00101 {
00102 throw XMLError(xml_opentag_expected);
00103 }
00104
00105
00106 mTokenizer++;
00107 XMLToken token2 = *mTokenizer;
00108 if (!token2.isLiteral())
00109 {
00110
00111 mTokenizer.putBack();
00112 mTokenizer.putBack(token1);
00113 return false;
00114 }
00115
00116
00117 switch(token2.getLiteral())
00118 {
00119
00120 case '!':
00121 {
00122 ++mTokenizer;
00123 XMLToken token3 = *mTokenizer;
00124
00125 if (!token3.isLiteral())
00126 {
00127
00128 if (token3.getGeneric().at(0) == '-' &&
00129 token3.getGeneric().at(1) == '-')
00130 {
00131 parseComment(context);
00132 }
00133 else
00134 {
00135 std::string doctypestr(token3.getGeneric());
00136
00137 std::transform(doctypestr.begin(), doctypestr.end(), doctypestr.begin(), toupper);
00138
00139 if (doctypestr == "DOCTYPE")
00140 {
00141
00142
00143
00144 while (*(mTokenizer++) != '>');
00145 }
00146 else
00147 {
00148 throw XMLError(xml_unknown);
00149 }
00150 }
00151 }
00152 else
00153 {
00154 throw XMLError(xml_pi_doctype_expected);
00155 }
00156
00157 break;
00158 }
00159 case '?':
00160 {
00161 ++mTokenizer;
00162 XMLToken token3 = *mTokenizer;
00163
00164 if (token3.isLiteral())
00165 {
00166 throw XMLError(xml_pi_doctype_expected);
00167 }
00168
00169
00170 XMLNode pinode(context);
00171
00172 std::string tagname(token3.getGeneric());
00173 pinode.mNodeNameHandle = context->insertTagname(tagname);
00174
00175 parseAttributes(pinode.getAttrMap());
00176
00177 XMLNodePtr nodeptr(new XMLNode(pinode));
00178 doc.mProcInstructions.push_back(nodeptr);
00179
00180 if (context->handleEvents())
00181 {
00182 context->getEventHandler().processingInstruction(pinode);
00183 }
00184
00185 ++mTokenizer;
00186 if (*mTokenizer != '?')
00187 {
00188 throw XMLError(xml_pi_doctype_expected);
00189 }
00190
00191 ++mTokenizer;
00192 if (*mTokenizer != '>')
00193 {
00194 throw XMLError(xml_closetag_expected);
00195 }
00196 break;
00197 }
00198 default:
00199
00200 throw XMLError(xml_pi_doctype_expected);
00201
00202 }
00203
00204 }
00205 }
00206
00207
00208 bool XMLParser::parseNode(XMLNode& node, XMLContextPtr& context)
00209 {
00210 node.mContext = context;
00211 bool handle = context->handleEvents();
00212
00213 ++mTokenizer;
00214 XMLToken token1 = *mTokenizer;
00215
00216 if (token1.isEndOfStream())
00217 {
00218 return false;
00219 }
00220
00221 XMLToken token2;
00222
00223
00224 bool again;
00225 do
00226 {
00227 again = false;
00228
00229
00230 if (!token1.isLiteral())
00231 {
00232 std::string cdataname("cdata");
00233 node.mNodeNameHandle = context->insertTagname(cdataname);
00234
00235
00236 node.mNodeType = xml_nt_cdata;
00237 node.mCdata.empty();
00238
00239 while(!token1.isLiteral())
00240 {
00241 node.mCdata += token1.getGeneric();
00242 ++mTokenizer;
00243 token1 = *mTokenizer;
00244 }
00245 mTokenizer.putBack();
00246
00247 if (handle)
00248 {
00249 context->getEventHandler().gotCdata( node.mCdata );
00250 }
00251
00252 return true;
00253 }
00254
00255
00256
00257 if (token1 != '<')
00258 {
00259 throw XMLError(xml_opentag_cdata_expected);
00260 }
00261
00262
00263 ++mTokenizer;
00264 token2 = *mTokenizer;
00265 if (token2.isLiteral())
00266 {
00267
00268 switch(token2.getLiteral())
00269 {
00270
00271 case '/':
00272
00273 mTokenizer.putBack();
00274 mTokenizer.putBack(token1);
00275 return false;
00276
00277
00278 case '!':
00279 this->parseComment(context);
00280
00281
00282 ++mTokenizer;
00283 token1 = *mTokenizer;
00284
00285
00286 again = true;
00287 break;
00288
00289 default:
00290 throw XMLError(xml_tagname_expected);
00291 }
00292 }
00293 } while (again);
00294
00295
00296 std::string tagname(token2.getGeneric());
00297 node.mNodeNameHandle = context->insertTagname(tagname);
00298
00299
00300 if (handle)
00301 {
00302 context->getEventHandler().startNode(tagname);
00303 }
00304
00305
00306 this->parseAttributes(node.getAttrMap());
00307
00308 if (handle)
00309 {
00310 context->getEventHandler().parsedAttributes(node.getAttrMap());
00311 }
00312
00313
00314 ++mTokenizer;
00315 XMLToken token3 = *mTokenizer;
00316 if (token3 == '/' )
00317 {
00318
00319 ++mTokenizer;
00320 XMLToken token4 = *mTokenizer;
00321 if (token4 != '>' )
00322 {
00323 throw XMLError(xml_closetag_expected);
00324 }
00325
00326 node.mNodeType = xml_nt_leaf;
00327
00328
00329 return true;
00330 }
00331
00332
00333 if (token3 != '>')
00334 {
00335 throw XMLError(xml_closetag_expected);
00336 }
00337
00338
00339 while (true)
00340 {
00341
00342 XMLNodePtr new_subnode(new XMLNode(context));
00343
00344
00345 if (this->parseNode(*new_subnode, context))
00346 {
00347
00348
00349 node.addChild(new_subnode);
00350 }
00351 else
00352 {
00353 break;
00354 }
00355 }
00356
00357
00358 XMLToken token5 = *mTokenizer++;
00359 ++mTokenizer;
00360 if (token5 != '<' && *mTokenizer != '/')
00361 {
00362 throw XMLError(xml_opentag_expected);
00363 }
00364
00365 ++mTokenizer;
00366 token1 = *mTokenizer;
00367 if (token1.isLiteral())
00368 {
00369 throw XMLError(xml_tagname_expected);
00370 }
00371
00372
00373 if (token1.getGeneric() != token2.getGeneric())
00374 {
00375 throw XMLError(xml_tagname_close_mismatch);
00376 }
00377
00378 ++mTokenizer;
00379 if (*mTokenizer != '>')
00380 {
00381 throw XMLError(xml_opentag_expected);
00382 }
00383
00384 if (handle)
00385 {
00386 context->getEventHandler().endNode(node);
00387 }
00388
00389 return true;
00390 }
00391
00392
00393 bool XMLParser::parseAttributes(XMLAttributes& attr)
00394 {
00395 while(true)
00396 {
00397 ++mTokenizer;
00398 XMLToken token1 = *mTokenizer;
00399
00400 if (token1.isLiteral())
00401 {
00402 mTokenizer.putBack();
00403 return false;
00404 }
00405
00406
00407 std::string name = token1.getGeneric();
00408
00409 ++mTokenizer;
00410 if (*mTokenizer != '=')
00411 {
00412 throw XMLError(xml_attr_equal_expected);
00413 }
00414
00415 ++mTokenizer;
00416 XMLToken token2 = *mTokenizer;
00417
00418 if (token2.isLiteral())
00419 {
00420 throw XMLError(xml_attr_value_expected);
00421 }
00422
00423
00424 std::string value(token2.getGeneric());
00425 value.erase(0, 1);
00426 value.erase(value.length()-1, 1);
00427
00428
00429
00430 XMLAttributes::value_type attrpair(name, value);
00431 attr.insert(attrpair);
00432 }
00433 return true;
00434 }
00435
00436 void XMLParser::parseComment(XMLContextPtr& context)
00437 {
00438
00439 while (true)
00440 {
00441 ++mTokenizer;
00442 if (*mTokenizer == "--")
00443 {
00444 ++mTokenizer;
00445 if (*mTokenizer == '>')
00446 {
00447 break;
00448 }
00449 }
00450 }
00451 }
00452 }