#include <xmlparser.h>
Collaboration diagram for cppdom::XMLParser:
Public Methods | |
XMLParser (std::istream &inputstream, XMLLocation &loc) | |
ctor. More... | |
bool | parseDocument (XMLDocument &doc, XMLContextPtr &context) |
parses the node as the document root. More... | |
bool | parseNode (XMLNode &node, XMLContextPtr &context) |
parses a node, without processing instructions. More... | |
Protected Methods | |
bool | parseHeader (XMLDocument &doc, XMLContextPtr &context) |
bool | parseAttributes (XMLAttributes &attr) |
parses an xml tag attribute list. More... | |
void | parseComment (XMLContextPtr &context) |
parses a comment. More... | |
Protected Attributes | |
std::istream & | mInput |
input stream. More... | |
xmlstream_iterator | mTokenizer |
stream iterator. More... |
Definition at line 58 of file xmlparser.h.
|
ctor.
Definition at line 52 of file xmlparser.cpp.
00053 : mInput(in), mTokenizer(in, loc) 00054 {} |
|
parses an xml tag attribute list.
Definition at line 393 of file xmlparser.cpp. References cppdom::XMLToken::getGeneric(), cppdom::XMLToken::isLiteral(), mTokenizer, cppdom::xml_attr_equal_expected, and cppdom::xml_attr_value_expected. Referenced by parseNode().
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 // guru: get value name here 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 // remove "" from attribute value 00424 std::string value(token2.getGeneric()); 00425 value.erase(0, 1); 00426 value.erase(value.length()-1, 1); 00427 00428 // insert attribute into the map 00429 // guru: we got the name already 00430 XMLAttributes::value_type attrpair(name, value); 00431 attr.insert(attrpair); 00432 } 00433 return true; 00434 } |
|
parses a comment.
Definition at line 436 of file xmlparser.cpp. References mTokenizer. Referenced by parseNode().
00437 { 00438 // get tokens until comment is over 00439 while (true) 00440 { 00441 ++mTokenizer; 00442 if (*mTokenizer == "--") 00443 { 00444 ++mTokenizer; 00445 if (*mTokenizer == '>') 00446 { 00447 break; 00448 } 00449 } 00450 } 00451 } |
|
parses the node as the document root.
Definition at line 56 of file xmlparser.cpp. References cppdom::XMLNode::addChild(), cppdom::XMLNode::mContext, cppdom::XMLNode::mNodeNameHandle, parseHeader(), and parseNode(). Referenced by cppdom::XMLDocument::load().
00057 { 00058 // set root nodename 00059 doc.mContext = context; 00060 std::string rootstr("root"); 00061 doc.mNodeNameHandle = context->insertTagname(rootstr); 00062 00063 bool handle = context->handleEvents(); 00064 00065 // start parsing 00066 if (handle) 00067 { 00068 context->getEventHandler().startDocument(); 00069 } 00070 00071 parseHeader(doc, context); 00072 00073 // parse the only one subnode 00074 XMLNodePtr new_subnode(new XMLNode(context)); 00075 00076 bool ret = parseNode(*new_subnode, context); 00077 00078 // if successful, put node into nodelist 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 } |
|
Definition at line 94 of file xmlparser.cpp. References cppdom::XMLNode::getAttrMap(), cppdom::XMLToken::getGeneric(), cppdom::XMLToken::getLiteral(), cppdom::XMLToken::isLiteral(), cppdom::XMLNode::mNodeNameHandle, cppdom::xml_closetag_expected, cppdom::xml_opentag_expected, cppdom::xml_pi_doctype_expected, and cppdom::xml_unknown. Referenced by parseDocument().
00095 { 00096 while(true) 00097 { 00098 ++mTokenizer; 00099 XMLToken token1 = *mTokenizer; 00100 if (token1 != '<') 00101 { 00102 throw XMLError(xml_opentag_expected); 00103 } 00104 00105 // token after opening < is a literal? 00106 mTokenizer++; 00107 XMLToken token2 = *mTokenizer; 00108 if (!token2.isLiteral()) 00109 { 00110 // generic string encountered: assume no pi and doctype tags 00111 mTokenizer.putBack(); 00112 mTokenizer.putBack(token1); 00113 return false; 00114 } 00115 00116 // now check for the literal 00117 switch(token2.getLiteral()) 00118 { 00119 // comment or doctype tag 00120 case '!': 00121 { 00122 ++mTokenizer; 00123 XMLToken token3 = *mTokenizer; 00124 00125 if (!token3.isLiteral()) 00126 { 00127 // now a doctype tag or a comment may follow 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 // \todo parse doctype tag 00142 00143 // read the complete tag till the closing > 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 // parse processing instruction 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 // unknown literal encountered 00200 throw XMLError(xml_pi_doctype_expected); 00201 00202 } // end switch 00203 00204 } // end while 00205 } |
|
parses a node, without processing instructions.
Definition at line 208 of file xmlparser.cpp. References cppdom::XMLNode::addChild(), cppdom::XMLNode::getAttrMap(), cppdom::XMLToken::getGeneric(), cppdom::XMLToken::getLiteral(), cppdom::XMLToken::isEndOfStream(), cppdom::XMLToken::isLiteral(), cppdom::XMLNode::mCdata, cppdom::XMLNode::mContext, cppdom::XMLNode::mNodeNameHandle, cppdom::XMLNode::mNodeType, mTokenizer, parseAttributes(), parseComment(), cppdom::xml_closetag_expected, cppdom::xml_nt_cdata, cppdom::xml_nt_leaf, cppdom::xml_opentag_cdata_expected, cppdom::xml_opentag_expected, cppdom::xml_tagname_close_mismatch, and cppdom::xml_tagname_expected. Referenced by cppdom::XMLNode::load(), and parseDocument().
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 // loop when we encounter a comment 00224 bool again; 00225 do 00226 { 00227 again = false; 00228 00229 // check if we have cdata 00230 if (!token1.isLiteral()) 00231 { 00232 std::string cdataname("cdata"); 00233 node.mNodeNameHandle = context->insertTagname(cdataname); 00234 00235 // parse cdata section(s) and return 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 // no cdata, try to continue parsing node content 00256 // Must be a start of a node (ie. < literal) 00257 if (token1 != '<') 00258 { 00259 throw XMLError(xml_opentag_cdata_expected); 00260 } 00261 00262 // get node name 00263 ++mTokenizer; 00264 token2 = *mTokenizer; 00265 if (token2.isLiteral()) 00266 { 00267 // check the following literal 00268 switch(token2.getLiteral()) 00269 { 00270 // closing '</...>' follows 00271 case '/': 00272 // return, we have a closing node with no more content 00273 mTokenizer.putBack(); 00274 mTokenizer.putBack(token1); 00275 return false; 00276 00277 // comment follows 00278 case '!': 00279 this->parseComment(context); 00280 00281 // get next token 00282 ++mTokenizer; 00283 token1 = *mTokenizer; 00284 00285 // parse again, until we encounter some useful data 00286 again = true; 00287 break; 00288 00289 default: 00290 throw XMLError(xml_tagname_expected); 00291 } 00292 } 00293 } while (again); 00294 00295 // insert tag name and set handle for it 00296 std::string tagname(token2.getGeneric()); 00297 node.mNodeNameHandle = context->insertTagname(tagname); 00298 00299 // notify event handler 00300 if (handle) 00301 { 00302 context->getEventHandler().startNode(tagname); 00303 } 00304 00305 // parse attributes 00306 this->parseAttributes(node.getAttrMap()); 00307 00308 if (handle) 00309 { 00310 context->getEventHandler().parsedAttributes(node.getAttrMap()); 00311 } 00312 00313 // check for leaf 00314 ++mTokenizer; 00315 XMLToken token3 = *mTokenizer; 00316 if (token3 == '/' ) 00317 { 00318 // node has finished 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 // return, let the caller continue to parse 00329 return true; 00330 } 00331 00332 // now a closing bracket must follow 00333 if (token3 != '>') 00334 { 00335 throw XMLError(xml_closetag_expected); 00336 } 00337 00338 // loop to parse all subnodes 00339 while (true) 00340 { 00341 // create subnode 00342 XMLNodePtr new_subnode(new XMLNode(context)); 00343 00344 // try to parse possible sub nodes 00345 if (this->parseNode(*new_subnode, context)) 00346 { 00347 // if successful, put node into nodelist 00348 // XMLNodePtr nodeptr( new XMLNode(subnode) ); 00349 node.addChild(new_subnode); 00350 } 00351 else 00352 { 00353 break; 00354 } 00355 } 00356 00357 // parse end tag 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 // check if open and close tag names are identical 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 } |
|
input stream.
Definition at line 82 of file xmlparser.h. |
|
stream iterator.
Definition at line 85 of file xmlparser.h. Referenced by parseAttributes(), parseComment(), and parseNode(). |