52#include "Teuchos_Assert.hpp"
134#define XMLPARSER_TFE( T , S ) \
135 TEUCHOS_TEST_FOR_EXCEPTION( T, std::runtime_error, "XML parse error at line " << _lineNo << ": " << S )
143 _entities[
"apos"] =
"'";
144 _entities[
"quot"] =
"\"";
145 _entities[
"lt"] =
"<";
146 _entities[
"gt"] =
">";
147 _entities[
"amp"] =
"&";
151 bool gotRoot =
false;
152 std::stack<long> tagLineStarts;
153 std::stack<string> tags;
157 std::string tag, cdata;
158 unsigned char c1, c2;
159 Teuchos::map<std::string,string> attrs;
165 if ( getSpace(c1) ) {
172 if (_is->readBytes(&c1,1) < 1) {
176 if (c1 ==
'\n') ++_lineNo;
182 XMLPARSER_TFE( _is->readBytes(&c2,1) < 1 ,
"stream ended in tag begin/end");
189 XMLPARSER_TFE( curopen == 0,
"document not well-formed: encountered end element '" << tag <<
"' while not enclosed." );
190 XMLPARSER_TFE( handler->endElement(tag)!=0,
"document not well-formed: end element tag = '" << tag <<
"'"
191 <<
" did not match start element '" << tags.top()
192 <<
"' from line " << tagLineStarts.top() );
197 else if (isLetter(c2) || c2==
':' || c2==
'_') {
200 tagLineStarts.push(_lineNo);
201 getSTag(c2, tag, attrs, emptytag);
203 handler->startElement(tag,attrs);
205 XMLPARSER_TFE(gotRoot ==
true,
"document not well-formed: more than one root element specified" );
211 XMLPARSER_TFE( handler->endElement(tag)!=0,
"unknown failure from handler while processing tag '" << tag <<
"'" );
217 else if (c2 ==
'?') {
219 XMLPARSER_TFE( assertChar(
'x') != 0 ,
"was expecting an XML declaration; element not well-formed or exploits unsupported feature" );
220 XMLPARSER_TFE( assertChar(
'm') != 0 ,
"was expecting an XML declaration; element not well-formed or exploits unsupported feature" );
221 XMLPARSER_TFE( assertChar(
'l') != 0 ,
"was expecting an XML declaration; element not well-formed or exploits unsupported feature" );
222 ignoreXMLDeclaration();
224 else if (c2 ==
'!') {
230 XMLPARSER_TFE( assertChar(
'-') != 0 ,
"element not well-formed or exploits unsupported feature" );
231 XMLPARSER_TFE( assertChar(
'-') != 0 ,
"element not well-formed or exploits unsupported feature" );
235 XMLPARSER_TFE(
true,
"element not well-formed or exploits unsupported feature" );
238 else if ( (curopen > 0) && (c1 ==
'&') ) {
239 std::string chars =
"";
241 handler->characters(chars);
243 else if ( (curopen > 0) ) {
244 std::string chars =
"";
246 handler->characters(chars);
249 XMLPARSER_TFE(1 ,
"document not well-formed: character data outside of an enclosing tag");
253 XMLPARSER_TFE( curopen != 0 ,
"file ended before closing element '" << tags.top() <<
"' from line " << tagLineStarts.top() );
255 return handler->getObject();
260void XMLParser::getETag(std::string &tag)
269 bool tagover =
false;
273 XMLPARSER_TFE( _is->readBytes(&c,1) < 1 ,
"EOF before end element was terminated");
274 XMLPARSER_TFE( !isLetter(c) && c!=
'_' && c!=
':' ,
"tag not well-formed");
277 XMLPARSER_TFE( _is->readBytes(&c,1) < 1 ,
"EOF before end element was terminated");
278 if ( isNameChar(c) ) {
280 XMLPARSER_TFE(1,
"end element not well-formed: expected '>'");
284 else if (isSpace(c)) {
287 if (c ==
'\n') ++_lineNo;
294 XMLPARSER_TFE(1,
"end element not well-formed");
300void XMLParser::getSTag(
unsigned char lookahead, std::string &tag, Teuchos::map<std::string,string> &attrs,
bool &emptytag)
328 XMLPARSER_TFE( _is->readBytes(&c,1) < 1 ,
"EOF before start element was terminated");
341 bool hadspace =
false;
346 XMLPARSER_TFE( getSpace(c)!=0,
"EOF before start element was terminated");
350 if ( (isLetter(c) || c==
'_' || c==
':') && hadspace ) {
354 std::string attname, attval;
357 XMLPARSER_TFE(_is->readBytes(&c,1) < 1,
"EOF before start element was terminated");
358 if ( isNameChar(c) ) {
359 attname.push_back(c);
361 else if ( isSpace(c) || c==
'=' ) {
365 XMLPARSER_TFE(1,
"attribute not well-formed: expected whitespace or '='");
375 XMLPARSER_TFE(1,
"attribute not well-formed: expected '='");
379 XMLPARSER_TFE(_is->readBytes(&c,1) < 1,
"EOF before start element was terminated");
390 else if (c ==
'\"') {
394 XMLPARSER_TFE(1,
"attribute value must be quoted with either ''' or '\"'");
397 XMLPARSER_TFE(_is->readBytes(&c,1) < 1,
"EOF before start element was terminated");
398 if (apost && c==
'\'') {
402 else if (!apost && c==
'\"') {
406 else if ( c ==
'&' ) {
409 getReference(refstr);
417 XMLPARSER_TFE(1,
"invalid character in attribute value");
422 XMLPARSER_TFE( attrs.find(attname) != attrs.end() ,
"cannot have two attributes with the same name");
423 attrs[attname] = attval;
430 XMLPARSER_TFE(assertChar(
'>')!=0,
"empty element tag not well-formed: expected '>'");
435 XMLPARSER_TFE(1,
"start element not well-formed: invalid character");
439 XMLPARSER_TFE(_is->readBytes(&c,1) < 1,
"EOF before start element was terminated");
445void XMLParser::getComment(
long )
456 XMLPARSER_TFE(_is->readBytes(&c,1) < 1,
"EOF before terminating comment begun at line " << _lineNo );
457 if (c ==
'\n') ++_lineNo;
461 XMLPARSER_TFE(_is->readBytes(&c,1) < 1,
"EOF before terminating comment begun at line " << _lineNo );
462 if (c ==
'\n') ++_lineNo;
465 XMLPARSER_TFE( assertChar(
'>')!=0,
"comment not well-formed: missing expected '>' at line " << _lineNo );
468 else if (!isChar(c)) {
469 XMLPARSER_TFE(1,
"comment not well-formed: invalid character at line " << _lineNo );
472 else if (!isChar(c)) {
473 XMLPARSER_TFE(1,
"comment not well-formed: invalid character at line " << _lineNo );
479void XMLParser::getReference(std::string &refstr) {
482 unsigned int num, base;
485 XMLPARSER_TFE(_is->readBytes(&c,1) < 1,
"EOF before reference was terminated");
491 XMLPARSER_TFE(_is->readBytes(&c,1) < 1,
"EOF before reference was terminated");
496 else if (
'0' <= c && c <=
'9') {
501 XMLPARSER_TFE(1,
"invalid character in character reference: expected 'x' or [0-9]");
505 XMLPARSER_TFE(_is->readBytes(&c,1) < 1,
"EOF before reference was terminated");
506 XMLPARSER_TFE( c !=
';' && !(
'0' <= c && c <=
'9') ,
"invalid character in character reference: expected [0-9] or ';'");
510 num = num*base + (c-
'0');
512 XMLPARSER_TFE(num > 0xFF,
"character reference value out of range");
513 refstr.push_back( (
unsigned char)num );
515 else if (isLetter(c) || c==
'_' || c==
':') {
518 std::string entname =
"";
519 entname.push_back(c);
521 XMLPARSER_TFE(_is->readBytes(&c,1) < 1,
"EOF before reference was terminated");
525 else if ( isLetter(c) || (
'0' <= c && c <=
'9')
526 || c==
'.' || c==
'-' || c==
'_' || c==
':'
528 entname.push_back(c);
531 XMLPARSER_TFE(1,
"entity reference not well-formed: invalid character");
534 XMLPARSER_TFE( _entities.find(entname) == _entities.end(),
"entity reference not well-formed: undefined entity");
535 refstr = _entities[entname];
538 XMLPARSER_TFE(1,
"reference not well-formed: expected name or '#'");
543int XMLParser::getSpace(
unsigned char &lookahead) {
546 if (lookahead ==
'\n') ++_lineNo;
547 if (_is->readBytes(&lookahead,1) < 1) {
551 while (isSpace(lookahead));
556bool XMLParser::isLetter(
unsigned char c) {
557 if ( (0x41 <= c && c <= 0x5A) || (0x61 <= c && c <= 0x7A) ||
558 (0xC0 <= c && c <= 0xD6) || (0xD8 <= c && c <= 0xF6) ||
567bool XMLParser::isNameChar(
unsigned char c) {
568 if ( isLetter(c) || (
'0' <= c && c <=
'9') ||
569 c==
'.' || c==
'-' || c==
'_' || c==
':' || c==0xB7 )
577bool XMLParser::isSpace(
unsigned char c) {
578 if ( c==0x20 || c==0x9 || c==0xD || c==0xA )
586bool XMLParser::isChar(
unsigned char c) {
587 if ( c==0x9 || c==0xA || c==0xD || 0x20 <= c) {
594int XMLParser::assertChar(
unsigned char cexp)
600 if (_is->readBytes(&c,1) < 1) {
609void XMLParser::ignoreXMLDeclaration()
616 XMLPARSER_TFE(_is->readBytes(&c,1) < 1,
"EOF before terminating XML declaration begun at line " << _lineNo );
617 if (c ==
'\n') ++_lineNo;
621 XMLPARSER_TFE( assertChar(
'>')!=0,
"XML declaration not well-formed: missing expected '>' at line " << _lineNo );
Defines a class for assembling an XMLObject from XML input.
A class providing a simple XML parser. Methods can be overloaded to exploit external XML parsing libr...
Smart reference counting pointer class for automatic garbage collection.
TreeBuildingXMLHandler()
Empty constructor.
Representation of an XML data tree. XMLObject is a ref-counted handle to a XMLObjectImplem object,...
XMLObject parse()
Consume the XMLInputStream to build an XMLObject.
The Teuchos namespace contains all of the classes, structs and enums used by Teuchos,...
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Deprecated.