20#include "Teuchos_Assert.hpp"
102#define XMLPARSER_TFE( T , S ) \
103 TEUCHOS_TEST_FOR_EXCEPTION( T, std::runtime_error, "XML parse error at line " << _lineNo << ": " << S )
111 _entities[
"apos"] =
"'";
112 _entities[
"quot"] =
"\"";
113 _entities[
"lt"] =
"<";
114 _entities[
"gt"] =
">";
115 _entities[
"amp"] =
"&";
119 bool gotRoot =
false;
120 std::stack<long> tagLineStarts;
121 std::stack<string> tags;
125 std::string tag, cdata;
126 unsigned char c1, c2;
127 Teuchos::map<std::string,string> attrs;
133 if ( getSpace(c1) ) {
140 if (_is->readBytes(&c1,1) < 1) {
144 if (c1 ==
'\n') ++_lineNo;
150 XMLPARSER_TFE( _is->readBytes(&c2,1) < 1 ,
"stream ended in tag begin/end");
157 XMLPARSER_TFE( curopen == 0,
"document not well-formed: encountered end element '" << tag <<
"' while not enclosed." );
158 XMLPARSER_TFE( handler->endElement(tag)!=0,
"document not well-formed: end element tag = '" << tag <<
"'"
159 <<
" did not match start element '" << tags.top()
160 <<
"' from line " << tagLineStarts.top() );
165 else if (isLetter(c2) || c2==
':' || c2==
'_') {
168 tagLineStarts.push(_lineNo);
169 getSTag(c2, tag, attrs, emptytag);
171 handler->startElement(tag,attrs);
173 XMLPARSER_TFE(gotRoot ==
true,
"document not well-formed: more than one root element specified" );
179 XMLPARSER_TFE( handler->endElement(tag)!=0,
"unknown failure from handler while processing tag '" << tag <<
"'" );
185 else if (c2 ==
'?') {
187 XMLPARSER_TFE( assertChar(
'x') != 0 ,
"was expecting an XML declaration; element not well-formed or exploits unsupported feature" );
188 XMLPARSER_TFE( assertChar(
'm') != 0 ,
"was expecting an XML declaration; element not well-formed or exploits unsupported feature" );
189 XMLPARSER_TFE( assertChar(
'l') != 0 ,
"was expecting an XML declaration; element not well-formed or exploits unsupported feature" );
190 ignoreXMLDeclaration();
192 else if (c2 ==
'!') {
198 XMLPARSER_TFE( assertChar(
'-') != 0 ,
"element not well-formed or exploits unsupported feature" );
199 XMLPARSER_TFE( assertChar(
'-') != 0 ,
"element not well-formed or exploits unsupported feature" );
203 XMLPARSER_TFE(
true,
"element not well-formed or exploits unsupported feature" );
206 else if ( (curopen > 0) && (c1 ==
'&') ) {
207 std::string chars =
"";
209 handler->characters(chars);
211 else if ( (curopen > 0) ) {
212 std::string chars =
"";
214 handler->characters(chars);
217 XMLPARSER_TFE(1 ,
"document not well-formed: character data outside of an enclosing tag");
221 XMLPARSER_TFE( curopen != 0 ,
"file ended before closing element '" << tags.top() <<
"' from line " << tagLineStarts.top() );
223 return handler->getObject();
228void XMLParser::getETag(std::string &tag)
237 bool tagover =
false;
241 XMLPARSER_TFE( _is->readBytes(&c,1) < 1 ,
"EOF before end element was terminated");
242 XMLPARSER_TFE( !isLetter(c) && c!=
'_' && c!=
':' ,
"tag not well-formed");
245 XMLPARSER_TFE( _is->readBytes(&c,1) < 1 ,
"EOF before end element was terminated");
246 if ( isNameChar(c) ) {
248 XMLPARSER_TFE(1,
"end element not well-formed: expected '>'");
252 else if (isSpace(c)) {
255 if (c ==
'\n') ++_lineNo;
262 XMLPARSER_TFE(1,
"end element not well-formed");
268void XMLParser::getSTag(
unsigned char lookahead, std::string &tag, Teuchos::map<std::string,string> &attrs,
bool &emptytag)
296 XMLPARSER_TFE( _is->readBytes(&c,1) < 1 ,
"EOF before start element was terminated");
309 bool hadspace =
false;
314 XMLPARSER_TFE( getSpace(c)!=0,
"EOF before start element was terminated");
318 if ( (isLetter(c) || c==
'_' || c==
':') && hadspace ) {
322 std::string attname, attval;
325 XMLPARSER_TFE(_is->readBytes(&c,1) < 1,
"EOF before start element was terminated");
326 if ( isNameChar(c) ) {
327 attname.push_back(c);
329 else if ( isSpace(c) || c==
'=' ) {
333 XMLPARSER_TFE(1,
"attribute not well-formed: expected whitespace or '='");
343 XMLPARSER_TFE(1,
"attribute not well-formed: expected '='");
347 XMLPARSER_TFE(_is->readBytes(&c,1) < 1,
"EOF before start element was terminated");
358 else if (c ==
'\"') {
362 XMLPARSER_TFE(1,
"attribute value must be quoted with either ''' or '\"'");
365 XMLPARSER_TFE(_is->readBytes(&c,1) < 1,
"EOF before start element was terminated");
366 if (apost && c==
'\'') {
370 else if (!apost && c==
'\"') {
374 else if ( c ==
'&' ) {
377 getReference(refstr);
380 else if ( c ==
'\r' ) {
391 XMLPARSER_TFE(1,
"invalid character in attribute value");
396 XMLPARSER_TFE( attrs.find(attname) != attrs.end() ,
"cannot have two attributes with the same name");
397 attrs[attname] = attval;
404 XMLPARSER_TFE(assertChar(
'>')!=0,
"empty element tag not well-formed: expected '>'");
409 XMLPARSER_TFE(1,
"start element not well-formed: invalid character");
413 XMLPARSER_TFE(_is->readBytes(&c,1) < 1,
"EOF before start element was terminated");
419void XMLParser::getComment(
long )
430 XMLPARSER_TFE(_is->readBytes(&c,1) < 1,
"EOF before terminating comment begun at line " << _lineNo );
431 if (c ==
'\n') ++_lineNo;
435 XMLPARSER_TFE(_is->readBytes(&c,1) < 1,
"EOF before terminating comment begun at line " << _lineNo );
436 if (c ==
'\n') ++_lineNo;
439 XMLPARSER_TFE( assertChar(
'>')!=0,
"comment not well-formed: missing expected '>' at line " << _lineNo );
442 else if (!isChar(c)) {
443 XMLPARSER_TFE(1,
"comment not well-formed: invalid character at line " << _lineNo );
446 else if (!isChar(c)) {
447 XMLPARSER_TFE(1,
"comment not well-formed: invalid character at line " << _lineNo );
453void XMLParser::getReference(std::string &refstr) {
456 unsigned int num, base;
459 XMLPARSER_TFE(_is->readBytes(&c,1) < 1,
"EOF before reference was terminated");
465 XMLPARSER_TFE(_is->readBytes(&c,1) < 1,
"EOF before reference was terminated");
470 else if (
'0' <= c && c <=
'9') {
475 XMLPARSER_TFE(1,
"invalid character in character reference: expected 'x' or [0-9]");
477 bool haveDigit = (base == 10);
480 XMLPARSER_TFE(_is->readBytes(&c,1) < 1,
"EOF before reference was terminated");
482 XMLPARSER_TFE(!haveDigit,
"invalid character reference: expected at least one hex digit after '&#x'");
488 XMLPARSER_TFE(!(
'0' <= c && c <=
'9'),
"invalid character in character reference: expected [0-9] or ';'");
492 XMLPARSER_TFE(!(
'0' <= c && c <=
'9') && !(
'a' <= c && c <=
'f') && !(
'A' <= c && c <=
'F'),
"invalid character in character reference: expected [0-9a-fA-F] or ';'");
493 if (
'0' <= c && c <=
'9') digit = c -
'0';
494 else if (
'a' <= c && c <=
'f') digit = 10 + c -
'a';
495 else digit = 10 + c -
'A';
497 XMLPARSER_TFE(num > (0xFF - digit) / base,
"character reference value out of range");
498 num = num*base + digit;
500 XMLPARSER_TFE(num > 0xFF,
"character reference value out of range");
501 XMLPARSER_TFE(num == 0,
"character reference value 0 is not a legal XML character");
502 refstr.push_back( (
unsigned char)num );
504 else if (isLetter(c) || c==
'_' || c==
':') {
507 std::string entname =
"";
508 entname.push_back(c);
510 XMLPARSER_TFE(_is->readBytes(&c,1) < 1,
"EOF before reference was terminated");
514 else if ( isLetter(c) || (
'0' <= c && c <=
'9')
515 || c==
'.' || c==
'-' || c==
'_' || c==
':'
517 entname.push_back(c);
520 XMLPARSER_TFE(1,
"entity reference not well-formed: invalid character");
523 XMLPARSER_TFE( _entities.find(entname) == _entities.end(),
"entity reference not well-formed: undefined entity");
524 refstr = _entities[entname];
527 XMLPARSER_TFE(1,
"reference not well-formed: expected name or '#'");
532int XMLParser::getSpace(
unsigned char &lookahead) {
535 if (lookahead ==
'\n') ++_lineNo;
536 if (_is->readBytes(&lookahead,1) < 1) {
540 while (isSpace(lookahead));
545bool XMLParser::isLetter(
unsigned char c) {
546 if ( (0x41 <= c && c <= 0x5A) || (0x61 <= c && c <= 0x7A) ||
547 (0xC0 <= c && c <= 0xD6) || (0xD8 <= c && c <= 0xF6) ||
556bool XMLParser::isNameChar(
unsigned char c) {
557 if ( isLetter(c) || (
'0' <= c && c <=
'9') ||
558 c==
'.' || c==
'-' || c==
'_' || c==
':' || c==0xB7 )
566bool XMLParser::isSpace(
unsigned char c) {
567 if ( c==0x20 || c==0x9 || c==0xD || c==0xA )
575bool XMLParser::isChar(
unsigned char c) {
576 if ( c==0x9 || c==0xA || c==0xD || 0x20 <= c) {
583int XMLParser::assertChar(
unsigned char cexp)
589 if (_is->readBytes(&c,1) < 1) {
598void XMLParser::ignoreXMLDeclaration()
605 XMLPARSER_TFE(_is->readBytes(&c,1) < 1,
"EOF before terminating XML declaration begun at line " << _lineNo );
606 if (c ==
'\n') ++_lineNo;
610 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 assembles a XMLObject from your XML input.
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.