/*
Copyright (C) 2000-2004
Code contributed by Greg Collecutt, Joseph Hope and Paul Cochrane
This file is part of xmds.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
$Id: xmlparser.cc,v 1.11 2004/07/27 07:33:54 paultcochrane Exp $
*/
/*! @file xmlparser.cc
@brief XML parser classes and methods
More detailed explanation...
*/
#include<xmlbasics.h>
#include<dom3.h>
#include<kissdom.h>
#include<xmlparser.h>
#define DEBUGXMLPARSER 0 //!< Whether or not to debug the XML parser
#define DEBUGXMLENTITYSTREAMS 0 //!< Whether or not to debug the entity streams
// ******************************************************************************
// ******************************************************************************
// XMLParserException
// ******************************************************************************
// ******************************************************************************
long nXMLParserExceptions=0; //!< The number of XML parser exceptions
// ******************************************************************************
XMLParserException::XMLParserException() :
theError(UNKNOWN_ERR),
theXMLEntityStreamStack(0),
theErrorMessage("") {
if(DEBUGXMLPARSER) {
nXMLParserExceptions++;
printf("XMLParserException::XMLParserException\n");
printf("nXMLParserExceptions=%li\n",nXMLParserExceptions);
}
};
// ******************************************************************************
XMLParserException::XMLParserException(
const list<XMLEntityStream*> *const yourXMLEntityStreamStack,
const char *const yourErrorMessage,
const unsigned short& yourError) :
theError(yourError),
theXMLEntityStreamStack(yourXMLEntityStreamStack),
theErrorMessage(yourErrorMessage) {
if(DEBUGXMLPARSER) {
nXMLParserExceptions++;
printf("XMLParserException::XMLParserException\n");
printf("nXMLParserExceptions=%li\n",nXMLParserExceptions);
}
};
// ******************************************************************************
XMLParserException::~XMLParserException() {
if(DEBUGXMLPARSER) {
nXMLParserExceptions--;
printf("XMLParserException::~XMLParserException\n");
printf("nXMLParserExceptions=%li\n",nXMLParserExceptions);
}
};
// ******************************************************************************
const char* XMLParserException::getError() {
const char* errorName;
switch(theError) {
case BAD_XML_ERR:
errorName="XMLParserException::BAD_XML_ERR\n";
break;
case ENCODING_NOT_SUPPORTED_ERR:
errorName="XMLParserException::ENCODING_NOT_SUPPORTED_ERR\n";
break;
case INVALID_FILE_ERR :
errorName="XMLParserException::INVALID_FILE_ERR\n";
break;
case INTERNAL_ERR:
errorName="XMLParserException::INTERNAL_ERR\n";
break;
default :
errorName="XMLParserException::UNKNOWN_ERR\n";
}
if(theXMLEntityStreamStack != 0) {
s[0]=0;
if(theXMLEntityStreamStack->size()==0) {
return errorName;
}
char s2[256];
list<XMLEntityStream*>::const_iterator ppXMLEntityStream = theXMLEntityStreamStack->begin();
sprintf(s2,"%sIn stream '%s', line %li, column %li,",errorName,
(*ppXMLEntityStream)->name()->c_str(),
(*ppXMLEntityStream)->streamPos.lineNumber,
(*ppXMLEntityStream)->streamPos.columnNumber);
strcat(s,s2);
ppXMLEntityStream++;
while(ppXMLEntityStream!=theXMLEntityStreamStack->end()) {
sprintf(s2,"\n which was referenced from stream '%s', line %li, column %li,",
(*ppXMLEntityStream)->name()->c_str(),
(*ppXMLEntityStream)->streamPos.lineNumber,
(*ppXMLEntityStream)->streamPos.columnNumber);
strcat(s,s2);
ppXMLEntityStream++;
}
sprintf(s2,"\nthe following error occurred:\n %s\n",theErrorMessage);
strcat(s,s2);
return s;
}
else
return errorName;
};
// ******************************************************************************
// ******************************************************************************
// XMLEntityStream
// ******************************************************************************
// ******************************************************************************
long nXMLEntityStreams=0; //!< The number of XML entity streams
// ******************************************************************************
XMLEntityStream::XMLEntityStream(
XMLParser *const yourXMLParser,
XMLEntityStream *const yourParentXMLEntityStream,
const XMLString& yourName,
const XMLString& yourSystemID):
myXMLParser(yourXMLParser),
myName(yourName),
myParentXMLEntityStream(yourParentXMLEntityStream),
mySystemID(yourSystemID) {
if(DEBUGXMLENTITYSTREAMS) {
nXMLEntityStreams++;
printf("%s,XMLEntityStream::XMLEntityStream\n",myName.c_str());
printf(" nXMLEntityStreams=%li\n",nXMLEntityStreams);
}
streamPos.count=0;
streamPos.lineNumber=1;
streamPos.columnNumber=1;
errormessage[0]=0;
myTextStringValid=0;
};
// ******************************************************************************
XMLEntityStream::~XMLEntityStream() {
if(DEBUGXMLENTITYSTREAMS) {
nXMLEntityStreams--;
printf("%s,XMLEntityStream::~XMLEntityStream\n",myName.c_str());
printf(" nXMLEntityStreams=%li\n",nXMLEntityStreams);
}
list<XMLEntityStream*>::iterator ppXMLEntityStream = myXMLEntityStreamList.begin();
while(ppXMLEntityStream != myXMLEntityStreamList.end()) {
delete *ppXMLEntityStream;
ppXMLEntityStream++;
}
};
// ******************************************************************************
const XMLString* XMLEntityStream::name() const {
if(DEBUGXMLENTITYSTREAMS) {
printf("%s,XMLEntityStream::name\n",myName.c_str());
}
return &myName;
};
// ******************************************************************************
XMLEntityStream* XMLEntityStream::parentXMLEntityStream() {
if(DEBUGXMLENTITYSTREAMS) {
printf("%s,XMLEntityStream::parentXMLEntityStream\n",myName.c_str());
}
return myParentXMLEntityStream;
};
// ******************************************************************************
bool XMLEntityStream::atEnd() const {
if(DEBUGXMLENTITYSTREAMS) {
printf("%s,XMLEntityStream::atEnd\n",myName.c_str());
}
return streamPos.count >= myTextString.length();
};
// ******************************************************************************
//char XMLEntityStream::nextChar() {
signed char XMLEntityStream::nextChar() {
if(!myTextStringValid) {
makeTextString();
}
if(streamPos.count>=myTextString.length()) {
return EOF;
}
else {
char c=myTextString.data(streamPos.count);
streamPos.columnNumber++;
if(c==0x0A) {
streamPos.lineNumber++;
streamPos.columnNumber=1;
}
streamPos.count++;
if(DEBUGXMLENTITYSTREAMS) {
printf("%s:%li,%c\n",myName.c_str(),streamPos.count,c);
}
return c;
}
};
// ******************************************************************************
XMLEntityStream* XMLEntityStream::addParameterXMLEntityStream(
const XMLString& name,
const XMLString& PublicID,
const XMLString& SystemID) {
if(DEBUGXMLENTITYSTREAMS) {
printf("%s,XMLEntityStream::addParameterXMLEntityStream\n",myName.c_str());
}
XMLEntityStream* newXMLEntityStream = new ParameterXMLEntityStream(myXMLParser,this,name,PublicID,SystemID);
myXMLEntityStreamList.push_front(newXMLEntityStream);
return newXMLEntityStream;
};
// ******************************************************************************
XMLEntityStream* XMLEntityStream::addParameterXMLEntityStream(
const XMLString& name,
const XMLString& EntityLiteral) {
if(DEBUGXMLENTITYSTREAMS) {
printf("%s,XMLEntityStream::addParameterXMLEntityStream\n",myName.c_str());
}
XMLEntityStream* newXMLEntityStream = new ParameterXMLEntityStream(myXMLParser,this,name,EntityLiteral);
myXMLEntityStreamList.push_front(newXMLEntityStream);
return newXMLEntityStream;
};
// ******************************************************************************
XMLEntityStream* XMLEntityStream::addGeneralXMLEntityStream(
const XMLString& name,
const XMLString& PublicID,
const XMLString& SystemID) {
if(DEBUGXMLENTITYSTREAMS) {
printf("%s,XMLEntityStream::addGeneralXMLEntityStream\n",myName.c_str());
}
XMLEntityStream* newXMLEntityStream = new GeneralXMLEntityStream(myXMLParser,this,name,PublicID,SystemID);
myXMLEntityStreamList.push_front(newXMLEntityStream);
return newXMLEntityStream;
};
// ******************************************************************************
XMLEntityStream* XMLEntityStream::addGeneralXMLEntityStream(
const XMLString& name,
const XMLString& EntityLieteral) {
if(DEBUGXMLENTITYSTREAMS) {
printf("%s,XMLEntityStrea m::addGeneralXMLEntityStream\n",myName.c_str());
}
XMLEntityStream* newXMLEntityStream = new GeneralXMLEntityStream(myXMLParser,this,name,EntityLieteral);
myXMLEntityStreamList.push_front(newXMLEntityStream);
return newXMLEntityStream;
};
// ******************************************************************************
XMLEntityStream* XMLEntityStream::addUnparsedXMLEntityStream(
const XMLString& name,
const XMLString& PublicID,
const XMLString& SystemID,
const XMLString& NotationName) {
if(DEBUGXMLENTITYSTREAMS) {
printf("%s,XMLEntityStream::addUnparsedXMLEntityStream\n",myName.c_str());
}
XMLEntityStream* newXMLEntityStream =
new UnparsedXMLEntityStream(myXMLParser,this,name,PublicID,SystemID,NotationName);
myXMLEntityStreamList.push_front(newXMLEntityStream);
return newXMLEntityStream;
};
// ******************************************************************************
XMLEntityStream* XMLEntityStream::getXMLEntityStream(
const XMLString& getName,
const XMLEntityStreamType& ofEntityType) {
if(DEBUGXMLENTITYSTREAMS) {
printf("%s,XMLEntityStream::getXMLEntityStream\n",myName.c_str());
}
XMLEntityStream* testXMLEntityStream;
XMLEntityStream* nextXMLEntityStream;
list<XMLEntityStream*>::const_iterator ppXMLEntityStream;
// first try locally
testXMLEntityStream=0;
ppXMLEntityStream = myXMLEntityStreamList.begin();
while((testXMLEntityStream==0)&(ppXMLEntityStream != myXMLEntityStreamList.end())) {
if ((*(*ppXMLEntityStream)->name()==getName)&( (*ppXMLEntityStream)->entityType()==ofEntityType)) {
testXMLEntityStream = *ppXMLEntityStream;
}
ppXMLEntityStream++;
}
if(testXMLEntityStream==0) {
// now try the more general search tree downwards routine starting with
// the immediate parent and working our way up the ancestral line each time
// it fails, until it gets to Adam.
if(myParentXMLEntityStream==0) {
// I am the root element. Go straight to getXMLEntityStreamTreeWalkDown
testXMLEntityStream = getXMLEntityStreamTreeWalkDown(getName,ofEntityType);
}
else {
nextXMLEntityStream=myParentXMLEntityStream;
while((testXMLEntityStream==0)&(nextXMLEntityStream!=0)) {
testXMLEntityStream = nextXMLEntityStream->getXMLEntityStreamTreeWalkDown(getName,ofEntityType);
nextXMLEntityStream = nextXMLEntityStream->parentXMLEntityStream();
}
}
}
if(testXMLEntityStream!=0) {
for(list<XMLEntityStream*>::const_iterator ppXMLEntityStream =
myXMLParser->XMLEntityStreamStack.begin() ;
ppXMLEntityStream != myXMLParser->XMLEntityStreamStack.end();
ppXMLEntityStream++) {
if(testXMLEntityStream==*ppXMLEntityStream) {
sprintf(errormessage,"Circular reference to parameter entity '%s'",getName.c_str());
throw XMLParserException(&myXMLParser->XMLEntityStreamStack,errormessage,
XMLParserException::BAD_XML_ERR);
}
}
testXMLEntityStream->streamPos.count=0;
testXMLEntityStream->streamPos.columnNumber=1;
testXMLEntityStream->streamPos.lineNumber=1;
}
return testXMLEntityStream;
};
// ******************************************************************************
void XMLEntityStream::printStreamTree(
unsigned long level) const {
for(unsigned long i=0;i<level;i++) {
printf(" ");
}
printf("%s\n",myName.c_str());
list<XMLEntityStream*>::const_iterator ppXMLEntityStream = myXMLEntityStreamList.begin();
while(ppXMLEntityStream != myXMLEntityStreamList.end()) {
(*ppXMLEntityStream)->printStreamTree(level+1);
ppXMLEntityStream++;
}
};
// ******************************************************************************
XMLEntityStream* XMLEntityStream::getXMLEntityStreamTreeWalkDown(
const XMLString& name,
const XMLEntityStreamType& ofEntityType) {
if(DEBUGXMLENTITYSTREAMS) {
printf("%s,XMLEntityStream::getXMLEntityStreamTreeWalkDown\n",myName.c_str());
}
if((myName==name)&(entityType()==ofEntityType)) {
return this;
}
XMLEntityStream* testXMLEntityStream=0;
list<XMLEntityStream*>::const_iterator ppXMLEntityStream = myXMLEntityStreamList.begin();
while((testXMLEntityStream==0)&(ppXMLEntityStream != myXMLEntityStreamList.end())) {
testXMLEntityStream = (*ppXMLEntityStream)->getXMLEntityStreamTreeWalkDown(name,ofEntityType);
ppXMLEntityStream++;
}
return testXMLEntityStream;
};
// ******************************************************************************
void XMLEntityStream::loadExternalTextString() {
if(DEBUGXMLENTITYSTREAMS) {
printf("%s,XMLEntityStream::loadExternalTextString\n",myName.c_str());
}
// check that file exists
FILE *infile = fopen(mySystemID.c_str(),"r");
if(infile==0) {
sprintf(errormessage,"Cannot open '%s' for reading",mySystemID.c_str());
throw XMLParserException(&myXMLParser->XMLEntityStreamStack, errormessage,XMLParserException::INVALID_FILE_ERR);
}
// load file into myTextString;
myTextString.loadFromFile(infile);
fclose(infile);
};
// ******************************************************************************
// ******************************************************************************
// RootXMLEntityStream
// ******************************************************************************
// ******************************************************************************
// ******************************************************************************
RootXMLEntityStream::RootXMLEntityStream(
XMLParser *const yourXMLParser,
const XMLString& yourSystemID):
XMLEntityStream(yourXMLParser,0,"document_entity",yourSystemID) {
if(DEBUGXMLENTITYSTREAMS) {
printf("%s,RootXMLEntityStream::RootXMLEntityStream\n",myName.c_str());
}
};
// ******************************************************************************
XMLEntityStream::XMLEntityStreamType RootXMLEntityStream::entityType() const {
if(DEBUGXMLENTITYSTREAMS) {
printf("%s,RootXMLEntityStream::entityType\n",myName.c_str());
}
return ROOT_ENTITY;
};
// ******************************************************************************
XMLEntityStream::XMLEntityLocationType RootXMLEntityStream::entityLocation() const {
if(DEBUGXMLENTITYSTREAMS) {
printf("%s,RootXMLEntityStream::entityLocation\n",myName.c_str());
}
return INTERNAL_ENTITY;
};
// ******************************************************************************
const XMLString* RootXMLEntityStream::replacementText() {
throw XMLParserException(&myXMLParser->XMLEntityStreamStack, "RootXMLEntityStream::replacementText() called!",
XMLParserException::INTERNAL_ERR);
};
// ******************************************************************************
void RootXMLEntityStream::makeTextString() {
if(DEBUGXMLENTITYSTREAMS) {
printf("%s,RootXMLEntityStream::makeTextString\n",myName.c_str());
}
loadExternalTextString();
myTextStringValid=1;
};
// ******************************************************************************
// ******************************************************************************
// GPXMLEntityStream
// ******************************************************************************
// ******************************************************************************
// ******************************************************************************
// constructor for an internal entity
GPXMLEntityStream::GPXMLEntityStream(
XMLParser *const yourXMLParser,
XMLEntityStream *const yourParentXMLEntityStream,
const XMLString& yourName,
const XMLString& yourEntityLiteral):
XMLEntityStream(yourXMLParser,yourParentXMLEntityStream,yourName,""),
myPublicID(""),
myEntityLiteral(yourEntityLiteral),
myEntityLocation(INTERNAL_ENTITY) {
if(DEBUGXMLENTITYSTREAMS) {
printf("%s,GPXMLEntityStream::GPXMLEntityStream - internal\n",myName.c_str());
}
};
// ******************************************************************************
// constructor for an external entity
GPXMLEntityStream::GPXMLEntityStream(
XMLParser *const yourXMLParser,
XMLEntityStream *const yourParentXMLEntityStream,
const XMLString& yourName,
const XMLString& yourPublicID,
const XMLString& yourSystemID):
XMLEntityStream(yourXMLParser,yourParentXMLEntityStream,yourName,yourSystemID),
myPublicID(yourPublicID),
myEntityLiteral(""),
myEntityLocation(EXTERNAL_ENTITY) {
if(DEBUGXMLENTITYSTREAMS) {
printf("%s,GPXMLEntityStream::GPXMLEntityStream - external\n",myName.c_str());
}
};
// ******************************************************************************
XMLEntityStream::XMLEntityLocationType GPXMLEntityStream::entityLocation() const {
if(DEBUGXMLENTITYSTREAMS) {
printf("%s,GPXMLEntityStream::entityLocation\n",myName.c_str());
}
return myEntityLocation;
};
// ******************************************************************************
const XMLString* GPXMLEntityStream::replacementText() {
if(DEBUGXMLENTITYSTREAMS) {
printf("%s,GPXMLEntityStream::replacementText\n",myName.c_str());
}
if(!myTextStringValid) {
makeTextString();
}
return &myTextString;
};
// ******************************************************************************
void GPXMLEntityStream::makeTextString() {
if(DEBUGXMLENTITYSTREAMS) {
printf("%s,GPXMLEntityStream::makeTextString\n",myName.c_str());
}
myTextStringValid=1;
if(myEntityLocation==EXTERNAL_ENTITY) {
loadExternalTextString();
// parse for TextDecl
XMLString VersionNum;
XMLString EncName;
myXMLParser->matchProduction77TextDecl(this,VersionNum,EncName);
// now remove TextDecl from myTextString
myTextString.replaceData(0,streamPos.count,"");
streamPos.count=0;
return;
}
// if here, we must be an internal entity, in which case we ought to
// be preparsed for character and parameter entity refs
myTextString=myEntityLiteral;
//char c;
signed char c;
unsigned long refLength;
XMLString refName;
XMLEntityStream* refXMLEntityStream;
StreamPositionStruct lastPos;
lastPos=streamPos;
c=nextChar();
while(c!=EOF) {
if(c=='&') {
streamPos=lastPos;
refLength=myXMLParser->matchProduction66CharRef(this,c);
streamPos=lastPos;
if(refLength>0) {
const char s[2]={c,0};
myTextString.replaceData(streamPos.count,refLength,s);
streamPos.columnNumber += refLength;
streamPos.count++;
}
lastPos=streamPos;
c=nextChar();
}
if(c=='%') {
// might be the % in an <!ENTITY % name ...> declaration
// therefore check next character, and proceed only if not a WhiteSpace
c=nextChar();
if(!XMLChar::isWhiteSpace(c)) {
streamPos=lastPos;
refLength=myXMLParser->matchProduction69PEReference(this,refName);
streamPos=lastPos;
refXMLEntityStream = getXMLEntityStream(refName,XMLEntityStream::PARAMETER_ENTITY);
if(refXMLEntityStream==0) {
sprintf(errormessage,"Parameter entity '%s' unknown",refName.c_str());
throw XMLParserException(&myXMLParser->XMLEntityStreamStack,errormessage,XMLParserException::BAD_XML_ERR);
}
myXMLParser->XMLEntityStreamStack.push_front(refXMLEntityStream);
myTextString.replaceData(streamPos.count,refLength,
*refXMLEntityStream->replacementText());
myXMLParser->XMLEntityStreamStack.pop_front();
}
}
lastPos=streamPos;
c=nextChar();
}
streamPos.count=0;
streamPos.lineNumber=1;
streamPos.columnNumber=1;
if(DEBUGXMLENTITYSTREAMS) {
printf("myTextString=%s\n",myTextString.c_str());
}
};
// ******************************************************************************
// ******************************************************************************
// ParameterXMLEntityStream
// ******************************************************************************
// ******************************************************************************
// ******************************************************************************
// constructor for an internal entity
ParameterXMLEntityStream::ParameterXMLEntityStream(
XMLParser *const yourXMLParser,
XMLEntityStream *const yourParentXMLEntityStream,
const XMLString& yourName,
const XMLString& yourEntityLiteral):
GPXMLEntityStream(yourXMLParser,yourParentXMLEntityStream,yourName,yourEntityLiteral) {
if(DEBUGXMLENTITYSTREAMS) {
printf("%s,ParameterXMLEntityStream::ParameterXMLEntityStream - internal\n",myName.c_str());
}
};
// ******************************************************************************
// constructor for an external entity
ParameterXMLEntityStream::ParameterXMLEntityStream(
XMLParser *const yourXMLParser,
XMLEntityStream *const yourParentXMLEntityStream,
const XMLString& yourName,
const XMLString& yourPublicID,
const XMLString& yourSystemID):
GPXMLEntityStream(yourXMLParser,yourParentXMLEntityStream,yourName,yourPublicID,yourSystemID) {
if(DEBUGXMLENTITYSTREAMS) {
printf("%s,ParameterXMLEntityStream::ParameterXMLEntityStream - external\n",myName.c_str());
}
};
// ******************************************************************************
XMLEntityStream::XMLEntityStreamType ParameterXMLEntityStream::entityType() const {
if(DEBUGXMLENTITYSTREAMS) {
printf("%s,ParameterXMLEntityStream::entityType\n",myName.c_str());
}
return PARAMETER_ENTITY;
};
// ******************************************************************************
// ******************************************************************************
// GeneralXMLEntityStream
// ******************************************************************************
// ******************************************************************************
// ******************************************************************************
// constructor for an internal entity
GeneralXMLEntityStream::GeneralXMLEntityStream(
XMLParser *const yourXMLParser,
XMLEntityStream *const yourParentXMLEntityStream,
const XMLString& yourName,
const XMLString& yourEntityLiteral):
GPXMLEntityStream(yourXMLParser,yourParentXMLEntityStream,yourName,yourEntityLiteral) {
if(DEBUGXMLENTITYSTREAMS) {
printf("%s,GeneralXMLEntityStream::GeneralXMLEntityStream - internal\n",myName.c_str());
}
};
// ******************************************************************************
// constructor for an external entity
GeneralXMLEntityStream::GeneralXMLEntityStream(
XMLParser *const yourXMLParser,
XMLEntityStream *const yourParentXMLEntityStream,
const XMLString& yourName,
const XMLString& yourPublicID,
const XMLString& yourSystemID):
GPXMLEntityStream(yourXMLParser,yourParentXMLEntityStream,yourName,yourPublicID,yourSystemID) {
if(DEBUGXMLENTITYSTREAMS) {
printf("%s,GeneralXMLEntityStream::GeneralXMLEntityStream - external\n",myName.c_str());
}
};
// ******************************************************************************
XMLEntityStream::XMLEntityStreamType GeneralXMLEntityStream::entityType() const {
if(DEBUGXMLENTITYSTREAMS) {
printf("%s,GeneralXMLEntityStream::entityType\n",myName.c_str());
}
return GENERAL_ENTITY;
};
// ******************************************************************************
// ******************************************************************************
// UnparsedXMLEntityStream
// ******************************************************************************
// ******************************************************************************
// ******************************************************************************
UnparsedXMLEntityStream::UnparsedXMLEntityStream(
XMLParser *const yourXMLParser,
XMLEntityStream *const yourParentXMLEntityStream,
const XMLString& yourName,
const XMLString& yourPublicID,
const XMLString& yourSystemID,
const XMLString& yourNotationName):
XMLEntityStream(yourXMLParser,yourParentXMLEntityStream,yourName,yourSystemID),
myPublicID(yourPublicID),
myNotationName(yourNotationName) {
if(DEBUGXMLENTITYSTREAMS) {
printf("%s,UnparsedXMLEntityStream::UnparsedXMLEntityStream\n",myName.c_str());
}
};
// ******************************************************************************
XMLEntityStream::XMLEntityStreamType UnparsedXMLEntityStream::entityType() const {
if(DEBUGXMLENTITYSTREAMS) {
printf("%s,UnparsedXMLEntityStream::entityType\n",myName.c_str());
}
return UNPARSED_ENTITY;
};
// ******************************************************************************
XMLEntityStream::XMLEntityLocationType UnparsedXMLEntityStream::entityLocation() const {
if(DEBUGXMLENTITYSTREAMS) {
printf("%s,UnparsedXMLEntityStream::entityLocation\n",myName.c_str());
}
return EXTERNAL_ENTITY;
};
// ******************************************************************************
const XMLString* UnparsedXMLEntityStream::replacementText() {
throw XMLParserException(&myXMLParser->XMLEntityStreamStack,"UnparsedXMLEntityStream::replacementText() called!",
XMLParserException::INTERNAL_ERR);
};
// ******************************************************************************
bool UnparsedXMLEntityStream::atEnd() const {
return 1;
};
// ******************************************************************************
XMLEntityStream* UnparsedXMLEntityStream::addParameterXMLEntityStream(
const XMLString& name,
const XMLString& PublicID,
const XMLString& SystemID) {
throw XMLParserException(&myXMLParser->XMLEntityStreamStack,"UnparsedXMLEntityStream::addParameterXMLEntityStream() called!",
XMLParserException::INTERNAL_ERR);
};
// ******************************************************************************
XMLEntityStream* UnparsedXMLEntityStream::addParameterXMLEntityStream(
const XMLString& name,
const XMLString& EntityLiteral) {
throw XMLParserException(&myXMLParser->XMLEntityStreamStack,"UnparsedXMLEntityStream::addParameterXMLEntityStream() called!",
XMLParserException::INTERNAL_ERR);
};
// ******************************************************************************
XMLEntityStream* UnparsedXMLEntityStream::addGeneralXMLEntityStream(
const XMLString& name,
const XMLString& EntityLiteral) {
throw XMLParserException(&myXMLParser->XMLEntityStreamStack,"UnparsedXMLEntityStream::addGeneralXMLEntityStream() called!",
XMLParserException::INTERNAL_ERR);
};
// ******************************************************************************
XMLEntityStream* UnparsedXMLEntityStream::addGeneralXMLEntityStream(
const XMLString& name,
const XMLString& PublicID,
const XMLString& SystemID,
const XMLString& NotationName) {
throw XMLParserException(&myXMLParser->XMLEntityStreamStack,"UnparsedXMLEntityStream::addGeneralXMLEntityStream() called!",
XMLParserException::INTERNAL_ERR);
};
// ******************************************************************************
XMLEntityStream* UnparsedXMLEntityStream::addUnparsedXMLEntityStream(
const XMLString& name,
const XMLString& PublicID,
const XMLString& SystemID,
const XMLString& NotationName) {
throw XMLParserException(&myXMLParser->XMLEntityStreamStack,"UnparsedXMLEntityStream::addUnparsedXMLEntityStream() called!",
XMLParserException::INTERNAL_ERR);
};
// ******************************************************************************
XMLEntityStream* UnparsedXMLEntityStream::getXMLEntityStream(
const XMLString& getName,
const XMLEntityStreamType& ofEntityType) {
throw XMLParserException(&myXMLParser->XMLEntityStreamStack,"UnparsedXMLEntityStream::getXMLEntityStream() called!",
XMLParserException::INTERNAL_ERR);
};
// ******************************************************************************
void UnparsedXMLEntityStream::makeTextString() {
throw XMLParserException(&myXMLParser->XMLEntityStreamStack,"UnparsedXMLEntityStream::makeTextString() called!",
XMLParserException::INTERNAL_ERR);
};
// ******************************************************************************
// ******************************************************************************
// XMLParser
// ******************************************************************************
// ******************************************************************************
// ******************************************************************************
XMLParser::XMLParser() {
if(DEBUGXMLPARSER) {
printf("XMLParser::XMLParser()\n");
}
myxmdsBytePoint=0;
};
// ******************************************************************************
XMLParser::~XMLParser() {
if(DEBUGXMLPARSER) {
printf("XMLParser::~XMLParser()\n");
}
if(rootXMLEntityStream != 0) {
delete rootXMLEntityStream;
}
if(DEBUGXMLPARSER) {
printf(" ...XMLParser deleted\n");
}
};
// ******************************************************************************
Document* XMLParser::parseFromFile(
const char* fileName) {
if(DEBUGXMLPARSER) {
printf("XMLParser::parseFromFile\n");
}
XMLEntityStreamStack.clear();
rootXMLEntityStream = new RootXMLEntityStream(this,fileName);
XMLEntityStreamStack.push_front(rootXMLEntityStream);
// add default expansions for the general entities
// < > & ' and "
rootXMLEntityStream->addGeneralXMLEntityStream("lt","&#60;");
rootXMLEntityStream->addGeneralXMLEntityStream("gt","&#62;");
rootXMLEntityStream->addGeneralXMLEntityStream("amp","&#38;");
rootXMLEntityStream->addGeneralXMLEntityStream("apos","&#39;");
rootXMLEntityStream->addGeneralXMLEntityStream("quot","&#34;");
(*XMLEntityStreamStack.begin())=rootXMLEntityStream;
theDocumentType=0;
theDocument=0;
rootVersionNum="1.0";
rootEncName="";
StandAlone=0;
try {
matchProduction01Document();
}
catch (XMLException XMLErr) {
printf("Could not load Document\n");
printf("due to the following XMLException:\n");
printf("%s",XMLErr.getError());
}
catch (DOMException DOMErr) {
printf("Could not load Document\n");
printf("due to the following DOMException:\n");
printf("%s",DOMErr.getError());
}
if(DEBUGXMLPARSER) {
myDOMImplementation.printAll();
}
return(theDocument);
};
// ******************************************************************************
unsigned long XMLParser::xmdsBytePoint() const {
if(DEBUGXMLPARSER) {
printf("XMLParser::xmdsBytePoint\n");
}
return myxmdsBytePoint;
}
/* The folowwing routines are designed to parse the productions laid out in
XML 1.0 (second edition). These productions fall into three categories:
1. Required. An error at any stage of parsing a required production will
generate the XMLParserException BAD_XML_ERR. These routines are
declared with the return type void.
2. Optional. An error at the early stages of parsing will not be reported
and the routine will back out and return 0. If the parsing passes a
'critical point' (the point at which the intended production is uniquely
specified) the routine will generate the XMLParserException BAD_XML_ERR
so that the user may know where they are going wrong.
These routines are declared as type bool so that the calling routine
knows whether or not the attempted parse was successful.
3. Either of the above, in which case the routine is passed a bool parameter
'required' so that it knows which behaviour is expected.
The definition of where the 'critical point' should go is not easy, as many
productons are comprised of ORed subproductions, and yet it would be nice
to be able to feed reasonable error messages to the user if they have made
a reconisable attempt at a particular production. Therefore many productions
test for their subproductions in a particular order, with the last one to be
tested having a very early critical point, and yeilding error messages that
encompass all the other subproductions.
*/
// ******************************************************************************
void XMLParser::matchProduction01Document() {
// this production is required
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction01Document\n");
}
matchProduction22Prolog();
if(!matchProduction39Element(0)) {
// no root element
throw XMLParserException(&XMLEntityStreamStack, "Root element expected.",XMLParserException::BAD_XML_ERR);
}
while(matchProduction27Misc(0)); // what is this supposed to do?? PTC
//char c = (*XMLEntityStreamStack.begin())->nextChar();
signed char c = (*XMLEntityStreamStack.begin())->nextChar();
if(c!=EOF) {
// what is this extra stuff?
throw XMLParserException(&XMLEntityStreamStack, "End of file expected.",XMLParserException::BAD_XML_ERR);
}
};
// ******************************************************************************
long XMLParser::matchProduction03S(
XMLEntityStream *const thisStream,
const bool required) const {
// this production is sometimes required and sometimes optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction03S\n");
}
StreamPositionStruct lastStreamPos = thisStream->streamPos;
long length=0;
//char c=thisStream->nextChar();
signed char c=thisStream->nextChar();
while(XMLChar::isWhiteSpace(c)&(c!=EOF)) {
lastStreamPos = thisStream->streamPos;
length++;
c=thisStream->nextChar();
}
if(!XMLChar::isWhiteSpace(c)) {
thisStream->streamPos = lastStreamPos;
}
if((length==0)&required) {
throw XMLParserException(&XMLEntityStreamStack, "White space expected.",XMLParserException::BAD_XML_ERR);
}
return length;
};
// ******************************************************************************
long XMLParser::matchProduction03SDeep(
const bool required) {
// this production is like the normal whitespace production,
// except that it also descends and climbs PE streams, since
// allowable white space forms logical boundaries between atoms of a DTD
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction03SDeep\n");
}
if(XMLEntityStreamStack.size()==1) {
return matchProduction03S((*XMLEntityStreamStack.begin()),required);
}
StreamPositionStruct lastStreamPos = (*XMLEntityStreamStack.begin())->streamPos;
XMLEntityStream* nextXMLEntityStream;
long length=0;
//char c=(*XMLEntityStreamStack.begin())->nextChar();
signed char c=(*XMLEntityStreamStack.begin())->nextChar();
while(XMLChar::isWhiteSpace(c)|(c=='%')|(c==EOF)) {
if(c==EOF) {
if(XMLEntityStreamStack.size()==1) {
throw XMLParserException(&XMLEntityStreamStack,"Unexpected end of file",
XMLParserException::BAD_XML_ERR);
}
XMLEntityStreamStack.pop_front();
}
else if(c=='%') {
// might yet be the % in an <!ENTITY % name ...> declaration
// therefore check next character, and proceed only if not a WhiteSpace
c=(*XMLEntityStreamStack.begin())->nextChar();
if(!XMLChar::isWhiteSpace(c)) {
(*XMLEntityStreamStack.begin())->streamPos.count -= 2;
(*XMLEntityStreamStack.begin())->streamPos.columnNumber -= 2;
XMLString refName;
StreamPositionStruct lastStreamPos2 = (*XMLEntityStreamStack.begin())->streamPos;
matchProduction69PEReference((*XMLEntityStreamStack.begin()),refName);
nextXMLEntityStream = (*XMLEntityStreamStack.begin())->getXMLEntityStream(refName,XMLEntityStream::PARAMETER_ENTITY);
if(nextXMLEntityStream==0) {
(*XMLEntityStreamStack.begin())->streamPos = lastStreamPos2;
sprintf(errormessage,"Parameter entity '%s' unknown",refName.c_str());
throw XMLParserException(&XMLEntityStreamStack,errormessage,XMLParserException::BAD_XML_ERR);
}
XMLEntityStreamStack.push_front(nextXMLEntityStream);
}
else {
(*XMLEntityStreamStack.begin())->streamPos = lastStreamPos;
if((length==0)&required) {
throw XMLParserException(&XMLEntityStreamStack,"White space expected",XMLParserException::BAD_XML_ERR);
}
return length;
}
}
length++;
lastStreamPos = (*XMLEntityStreamStack.begin())->streamPos;
c=(*XMLEntityStreamStack.begin())->nextChar();
}
(*XMLEntityStreamStack.begin())->streamPos = lastStreamPos;
if((length==0)&required) {
throw XMLParserException(&XMLEntityStreamStack,"White space expected",XMLParserException::BAD_XML_ERR);
}
return length;
};
// ******************************************************************************
bool XMLParser::matchProduction05Name(
XMLEntityStream *const thisStream,
XMLString& Name) const {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction05Name\n");
}
if(!matchProduction07Nmtoken(thisStream,Name)) {
return 0;
}
// critical point
// and check that it is a valid name
if(!Name.isName()) {
thisStream->streamPos.columnNumber -= Name.length();
throw XMLParserException(&XMLEntityStreamStack,"Not a valid Name",XMLParserException::BAD_XML_ERR);
}
if(DEBUGXMLPARSER) {
printf("Name = '%s'\n",Name.c_str());
}
return 1;
};
// ******************************************************************************
bool XMLParser::matchProduction07Nmtoken(
XMLEntityStream *const thisStream,
XMLString& Nmtoken) const {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction07Nmtoken\n");
}
StreamPositionStruct lastStreamPos = thisStream->streamPos;
// first of all need to determine length of NMToken
unsigned long length=0;
//char c=thisStream->nextChar();
signed char c=thisStream->nextChar();
if(c==EOF) {
return 0;
}
while(XMLChar::isNameChar(c)) {
length++;
c=thisStream->nextChar();
}
thisStream->streamPos = lastStreamPos;
if(length==0) {
return 0;
}
char* s = new char[length+1];
for(unsigned long i=0; i<length; i++) {
s[i]=thisStream->nextChar();
}
s[length]=0;
Nmtoken=s;
delete s;
if(DEBUGXMLPARSER) {
printf("Nmtoken = '%s'\n",Nmtoken.c_str());
}
return 1;
};
// ******************************************************************************
void XMLParser::matchProduction09EntityLiteral(
XMLString& EntityLiteral) {
// this production is required
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction09EntityLiteral\n");
}
matchProductionQuotedString((*XMLEntityStreamStack.begin()),EntityLiteral);
};
// ******************************************************************************
void XMLParser::matchProduction10AttValue(
XMLString& AttValue) {
// this production is required
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction_AttVal\n");
}
matchProductionQuotedString((*XMLEntityStreamStack.begin()),AttValue);
// check it for "<"
for(unsigned long i=0;i<AttValue.length();i++) {
if(AttValue.data(i)=='<') {
// illegal '<'
throw XMLParserException(&XMLEntityStreamStack,"'<' not allowed in AttValue",XMLParserException::BAD_XML_ERR);
}
}
// now scan it for references and replace if known *MOREWORK
};
// ******************************************************************************
void XMLParser::matchProduction11SystemLiteral(
XMLString& SystemLiteral) {
// this production is required
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction11SystemLiteral\n");
}
matchProductionQuotedString((*XMLEntityStreamStack.begin()),SystemLiteral);
};
// ******************************************************************************
void XMLParser::matchProduction12PubidLiteral(
XMLString& PubidLiteral) {
// this production is required
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction12PubidLiteral\n");
}
matchProductionQuotedString((*XMLEntityStreamStack.begin()),PubidLiteral);
if(!PubidLiteral.isPubidLiteral()) {
(*XMLEntityStreamStack.begin())->streamPos.columnNumber -= PubidLiteral.length() + 1;
throw XMLParserException(&XMLEntityStreamStack,"not a valid PubidLiteral",XMLParserException::BAD_XML_ERR);
}
};
// ******************************************************************************
bool XMLParser::matchProduction14CharData(
Element* containingElement) {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction14CharData\n");
}
list<XMLEntityStream*> lastXMLEntityStreamStack;
list<StreamPositionStruct> lastStreamsPosition;
// store last position in this and all parent streams
storeStreamPos(lastXMLEntityStreamStack,lastStreamsPosition);
// need to get length and expand general entity
// and character references as we go
long length=sweepContent(0);
// now restore last position for this and all parent streams
restoreStreamPos(lastXMLEntityStreamStack,lastStreamsPosition);
if(length==0) {
return 0;
}
char* s=new char[length+1];
sweepContent(s);
XMLString CharData=s;
delete s;
Node* newTextNode = theDocument->createTextNode(CharData);
containingElement->appendChild(newTextNode);
if(DEBUGXMLPARSER) {
printf("CharData = '%s'\n",CharData.c_str());
}
return 1;
};
// ******************************************************************************
bool XMLParser::matchProduction15Comment(
Element* containingElement) {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction15Comment\n");
}
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),"<!--")) {
return 0;
}
StreamPositionStruct lastStreamPos = (*XMLEntityStreamStack.begin())->streamPos;
XMLString Comment;
long length = howFarTo("--");
(*XMLEntityStreamStack.begin())->streamPos = lastStreamPos;
loadNChar((*XMLEntityStreamStack.begin()),Comment,length);
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),"-->")) {
// comment incorrectly terminated
throw XMLParserException(&XMLEntityStreamStack,"'-->' expected",XMLParserException::BAD_XML_ERR);
}
if(!(containingElement==0)) {
Node* newCommentNode = theDocument->createComment(Comment);
containingElement->appendChild(newCommentNode);
}
if(DEBUGXMLPARSER) {
printf("Comment = '%s'\n",Comment.c_str());
}
return 1;
};
// ******************************************************************************
bool XMLParser::matchProduction16PI(
Element* containingElement) {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction16PI\n");
}
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),"<?")) {
return 0;
}
XMLString PITarget;
XMLString PIString;
matchProduction17PITarget(PITarget);
if(PITarget.eqxml()) {
(*XMLEntityStreamStack.begin())->streamPos.columnNumber -= PITarget.length();
throw XMLParserException(&XMLEntityStreamStack,
"illegal processing instruction target name",
XMLParserException::BAD_XML_ERR);
}
StreamPositionStruct lastStreamPos1 = (*XMLEntityStreamStack.begin())->streamPos;
long whiteSpace=matchProduction03S((*XMLEntityStreamStack.begin()),0);
StreamPositionStruct lastStreamPos2 = (*XMLEntityStreamStack.begin())->streamPos;
long length = howFarTo("?>");
if((length>0)&(whiteSpace==0)) {
(*XMLEntityStreamStack.begin())->streamPos = lastStreamPos1;
throw XMLParserException(&XMLEntityStreamStack,"white space expected",XMLParserException::BAD_XML_ERR);
}
(*XMLEntityStreamStack.begin())->streamPos = lastStreamPos2;
loadNChar((*XMLEntityStreamStack.begin()),PIString,length);
if(!(containingElement==0)) {
Node* newProcessingInstructionNode =
theDocument->createProcessingInstruction(PITarget,PIString);
containingElement->appendChild(newProcessingInstructionNode);
}
if(DEBUGXMLPARSER) {
printf("PITarget = '%s'\n",PITarget.c_str());
printf("PIString = '%s'\n",PIString.c_str());
}
// skip the '?>'
(*XMLEntityStreamStack.begin())->streamPos.count += 2;
(*XMLEntityStreamStack.begin())->streamPos.columnNumber += 2;
return 1;
};
// ******************************************************************************
void XMLParser::matchProduction17PITarget(
XMLString& PITarget) {
// this production is required
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction17PITarget\n");
}
matchProduction05Name((*XMLEntityStreamStack.begin()),PITarget);
};
// ******************************************************************************
bool XMLParser::matchProduction18CDSect(
Element* containingElement) {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction18CDSect\n");
}
if(!matchProduction19CDStart()) {
return 0;
}
// critical point
XMLString CData;
matchProduction20CData(CData);
matchProduction21CDEnd();
Node* newCDATASectionNode = theDocument->createCDATASection(CData);
containingElement->appendChild(newCDATASectionNode);
return 1;
};
// ******************************************************************************
bool XMLParser::matchProduction19CDStart() {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction19CDStart\n");
}
return(matchProductionFixedString((*XMLEntityStreamStack.begin()),"<![CDATA["));
};
// ******************************************************************************
bool XMLParser::matchProduction20CData(
XMLString& CData) {
// this production is required
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction20CData\n");
}
StreamPositionStruct lastStreamPos = (*XMLEntityStreamStack.begin())->streamPos;
long length = howFarTo("]]>");
(*XMLEntityStreamStack.begin())->streamPos = lastStreamPos;
loadNChar((*XMLEntityStreamStack.begin()),CData,length);
if(DEBUGXMLPARSER) {
printf("CData = '%s'\n",CData.c_str());
}
return 1;
};
// ******************************************************************************
bool XMLParser::matchProduction21CDEnd() {
// this production is required
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction21CDEnd\n");
}
return(matchProductionFixedString((*XMLEntityStreamStack.begin()),"]]>"));
};
// ******************************************************************************
void XMLParser::matchProduction22Prolog() {
// this production is required
// note, however, that all of its sub-productions are optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction22Prolog\n");
}
matchProduction23XMLDecl();
while(matchProduction27Misc(0)); // again, what is this doing?? PTC
matchProduction28doctypedecl();
if(!(theDocumentType==0)) {
while(matchProduction27Misc(0)); // and again... PTC
}
};
// ******************************************************************************
bool XMLParser::matchProduction23XMLDecl() {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction23XMLDecl\n");
}
StreamPositionStruct lastStreamPos = (*XMLEntityStreamStack.begin())->streamPos;
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),"<?xml")) {
return 0;
}
if(matchProduction03S((*XMLEntityStreamStack.begin()),0)==0) {
// no following white space => not an XMLDecl => back out
(*XMLEntityStreamStack.begin())->streamPos = lastStreamPos;
return 0;
}
// critical point
XMLString tempString;
if(matchProduction24VersionInfo((*XMLEntityStreamStack.begin()),tempString)) {
rootVersionNum=tempString;
}
{ if(matchProduction80EncodingDecl((*XMLEntityStreamStack.begin()),tempString))
rootEncName=tempString;
}
matchProduction32SDDecl();
matchProduction03S((*XMLEntityStreamStack.begin()),0);
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),"?>")) {
// XMLDecl incorrectly terminated
throw XMLParserException(&XMLEntityStreamStack,"'?>' expected",XMLParserException::BAD_XML_ERR);
}
return 0;
};
// ******************************************************************************
bool XMLParser::matchProduction24VersionInfo(
XMLEntityStream *const thisStream,
XMLString& VersionNum) {
// this production is required
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction24VersionInfo\n");
}
if(!matchProductionFixedString(thisStream,"version")) {
throw XMLParserException(&XMLEntityStreamStack,"'version' expected",XMLParserException::BAD_XML_ERR);
}
matchProduction25Eq(thisStream);
matchProductionQuotedString(thisStream,VersionNum);
if(!VersionNum.isVersionNum()) {
// isn't a VersionNum
thisStream->streamPos.columnNumber -= VersionNum.length() + 1;
throw XMLParserException(&XMLEntityStreamStack,"not a valid Version number",XMLParserException::BAD_XML_ERR);
}
if(DEBUGXMLPARSER) {
printf("VersionNum = '%s'\n",VersionNum.c_str());
}
return 1;
};
// ******************************************************************************
void XMLParser::matchProduction25Eq(
XMLEntityStream *const thisStream) {
// this production is required
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction25Eq\n");
}
matchProduction03S(thisStream,0);
if(!matchProductionFixedString(thisStream,"=")) {
throw XMLParserException(&XMLEntityStreamStack,"'=' expected",XMLParserException::BAD_XML_ERR);
}
matchProduction03S(thisStream,0);
};
// ******************************************************************************
bool XMLParser::matchProduction27Misc(
Element* containingElement) {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction27Misc\n");
}
if(matchProduction03SDeep(0)>0) {
return 1;
}
if(matchProduction15Comment(containingElement)) {
return 1;
}
if(matchProduction16PI(containingElement)) {
return 1;
}
return 0;
};
// ******************************************************************************
bool XMLParser::matchProduction28aDeclSep() {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction28aDeclSep\n");
}
if(matchProduction03SDeep(0)>0) {
return 1;
}
XMLString refName;
unsigned long refLength;
XMLEntityStream* refStream;
refLength=matchProduction69PEReference((*XMLEntityStreamStack.begin()),refName);
if(refLength==0) {
return 0;
}
// we have found a PEReference, now need to find its stream and descend
// into it
refStream =
(*XMLEntityStreamStack.begin())->getXMLEntityStream(refName,XMLEntityStream::PARAMETER_ENTITY);
if(refStream==0) {
(*XMLEntityStreamStack.begin())->streamPos.count -= refLength;
(*XMLEntityStreamStack.begin())->streamPos.columnNumber -= refLength;
sprintf(errormessage,"Parameter Entity '%s' unknown",refName.c_str());
throw XMLParserException(&XMLEntityStreamStack,errormessage,XMLParserException::BAD_XML_ERR);
}
XMLEntityStreamStack.push_front(refStream);
return 1;
};
// ******************************************************************************
bool XMLParser::matchProduction28doctypedecl() {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction28doctypedecl\n");
}
StreamPositionStruct lastStreamPos = (*XMLEntityStreamStack.begin())->streamPos;
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),"<!DOCTYPE")) {
return 0; // back out
}
if(matchProduction03S((*XMLEntityStreamStack.begin()),0)==0) {
// no white space following
// therefore not an doctypedecl
// back out
(*XMLEntityStreamStack.begin())->streamPos = lastStreamPos;
return 0;
}
// critical point
XMLString doctypeName;
XMLString SystemLiteral;
XMLString PubidLiteral;
if(!matchProduction05Name((*XMLEntityStreamStack.begin()),doctypeName)) {
throw XMLParserException(&XMLEntityStreamStack,"Name (for DTD) expected.",
XMLParserException::BAD_XML_ERR);
}
matchProduction03S((*XMLEntityStreamStack.begin()),0);
matchProduction75ExternalID(PubidLiteral,SystemLiteral);
matchProduction03S((*XMLEntityStreamStack.begin()),0);
// OK, now we can create 'theDocumentType'
theDocumentType = myDOMImplementation.createDocumentType(doctypeName,PubidLiteral,SystemLiteral);
// now if we have a SystemLiteral we need to create an XMLEntityStream for it, and
// descend into it in order to parse the external DTD before processing the
// internal subset
if(SystemLiteral.length()>0) {
if(StandAlone) {
throw XMLParserException(&XMLEntityStreamStack,"External DTD not allowed in standalone documents",
XMLParserException::BAD_XML_ERR);
}
XMLEntityStream* newXMLEntityStream = (*XMLEntityStreamStack.begin())->addParameterXMLEntityStream(
doctypeName,PubidLiteral,SystemLiteral);
XMLEntityStreamStack.push_front(newXMLEntityStream);
matchProduction31extSubsetDecl();
if(XMLEntityStreamStack.size()>1) {
throw XMLParserException(&XMLEntityStreamStack,
"markupdecl|conditionalSect|DeclSep expected",
XMLParserException::BAD_XML_ERR);
}
}
// now parse internal subset
if(matchProductionFixedString((*XMLEntityStreamStack.begin()),"[")) {
bool more2go = 1;
while(more2go) {
more2go = matchProduction29markupdecl();
if((*XMLEntityStreamStack.begin())!=rootXMLEntityStream) {
more2go = more2go|matchProduction61conditionalSect();
}
more2go = more2go|matchProduction28aDeclSep();
if(!more2go) {
if((*XMLEntityStreamStack.begin())!=rootXMLEntityStream) {
if((*XMLEntityStreamStack.begin())->atEnd()) {
(*XMLEntityStreamStack.begin()) = (*XMLEntityStreamStack.begin())->parentXMLEntityStream();
}
else {
throw XMLParserException(&XMLEntityStreamStack,
"markupdecl|conditionalSect|DeclSep expected",
XMLParserException::BAD_XML_ERR);
}
more2go=1;
}
}
}
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),"]")) {
// not correctly terminated
throw XMLParserException(&XMLEntityStreamStack,"']' expected",
XMLParserException::BAD_XML_ERR);
}
matchProduction03S((*XMLEntityStreamStack.begin()),0);
}
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),">")) {
// not correctly terminated
throw XMLParserException(&XMLEntityStreamStack,"'>'expected",
XMLParserException::BAD_XML_ERR);
}
return 1;
};
// ******************************************************************************
bool XMLParser::matchProduction29markupdecl() {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction29markupdecl\n");
}
if(matchProduction45elementdecl()) {
return 1;
}
if(matchProduction52AttlistDecl()) {
return 1;
}
if(matchProduction70EntityDecl()) {
return 1;
}
if(matchProduction82NotationDecl()) {
return 1;
}
if(matchProduction16PI(0)) {
return 1;
}
if(matchProduction15Comment(0)) {
return 1;
}
return 0;
};
// ******************************************************************************
void XMLParser::matchProduction31extSubsetDecl() {
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction31extSubsetDecl\n");
}
// this production is optional
const unsigned long enteringlevel = XMLEntityStreamStack.size();
while(1) {
if(matchProduction29markupdecl()) {}
else if(matchProduction61conditionalSect()) {}
else if(matchProduction28aDeclSep()) {}
else if(XMLEntityStreamStack.size()<=enteringlevel) {
return;
}
else {
throw XMLParserException(&XMLEntityStreamStack,"markupdecl|conditionalSect|DeclSep expected",
XMLParserException::BAD_XML_ERR);
}
}
};
// ******************************************************************************
bool XMLParser::matchProduction32SDDecl() {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction32SDDecl\n");
}
StreamPositionStruct lastStreamPos = (*XMLEntityStreamStack.begin())->streamPos;
if(matchProduction03S((*XMLEntityStreamStack.begin()),0)==0) {
return 0; // there was no white space
}
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),"standalone")) {
// back out
(*XMLEntityStreamStack.begin())->streamPos = lastStreamPos;
return 0;
}
// critical point
matchProduction25Eq((*XMLEntityStreamStack.begin()));
XMLString SDDecl;
lastStreamPos = (*XMLEntityStreamStack.begin())->streamPos;
matchProductionQuotedString((*XMLEntityStreamStack.begin()),SDDecl);
if(SDDecl=="yes") {
StandAlone = 1;
}
else if(SDDecl=="no") {
StandAlone = 0;
}
else {
// isn't an SDDecl
(*XMLEntityStreamStack.begin())->streamPos = lastStreamPos;
(*XMLEntityStreamStack.begin())->streamPos.columnNumber++;
throw XMLParserException(&XMLEntityStreamStack,"'yes' or 'no' expected for StandAlone declaration",
XMLParserException::BAD_XML_ERR);
}
if(DEBUGXMLPARSER) {
printf("SDDecl = '%s'\n",SDDecl.c_str());
}
return 1;
};
// ******************************************************************************
bool XMLParser::matchProduction39Element(
Element* containingElement) {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction39Element\n");
}
const XMLEntityStream *const enteringXMLEntityStream = (*XMLEntityStreamStack.begin());
StreamPositionStruct lastStreamPos = (*XMLEntityStreamStack.begin())->streamPos;
XMLString tagName;
list <XMLString> myAttributeNamesList;
list <XMLString> myAttributeValuesList;
Element* newElement;
bool isEmptyElement=0;
if(matchProduction44EmptyElementTag(&tagName,&myAttributeNamesList,&myAttributeValuesList)) {
isEmptyElement=1;
}
else if(!matchProduction40STag(&tagName,&myAttributeNamesList,&myAttributeValuesList)) {
return 0;
}
if((theDocument==0)&(theDocumentType!=0)) {
if(tagName != *theDocumentType->nodeName()) {
(*XMLEntityStreamStack.begin())->streamPos = lastStreamPos;
(*XMLEntityStreamStack.begin())->streamPos.columnNumber++;
sprintf(errormessage,
"Expecting root element to be '%s'\n",theDocumentType->nodeName()->c_str());
throw XMLParserException(&XMLEntityStreamStack,errormessage,
XMLParserException::BAD_XML_ERR);
}
}
// need to compile a list of local URI bindings
list<XMLString> localPrefixes;
list<XMLString> localURIs;
XMLString defaultURI;
list<XMLString>::const_iterator pAttName = myAttributeNamesList.begin();
list<XMLString>::const_iterator pAttValue = myAttributeValuesList.begin();
while(pAttName!=myAttributeNamesList.end()) {
if(pAttName->eqxmlns()) {
defaultURI = *pAttValue;
}
else {
XMLString attPrefix;
XMLString attLocalName;
if(pAttName->splitNSName(attPrefix,attLocalName)) {
if(attPrefix.eqxmlns()) {
localPrefixes.push_back(attLocalName);
localURIs.push_back(*pAttValue);
}
}
}
pAttName++;
pAttValue++;
}
// now find URI binding for element tagName
XMLString prefix;
XMLString localName;
XMLString namespaceURI;
if(tagName.splitNSName(prefix,localName)) {
// prefix exists, is it xml:?
if(prefix.eqxml()) {
if(DEBUGXMLPARSER) {
printf("my prefix is xml, will use XML_NAMESPACEURI binding\n");
}
namespaceURI = XML_NAMESPACEURI;
}
if(namespaceURI.length()==0) {
// not xml: => look for xmlns:prefix="..." binding
// firstly look for local binding
if(DEBUGXMLPARSER) {
printf("my prefix is not xml, looking for local binding\n");
}
list<XMLString>::const_iterator pLocalPrefix=localPrefixes.begin();
list<XMLString>::const_iterator pLocalURIs=localURIs.begin();
while((namespaceURI.length()==0)&(pLocalPrefix!=localPrefixes.end())) {
if(*pLocalPrefix==prefix) {
namespaceURI=*pLocalURIs;
}
pLocalPrefix++;
pLocalURIs++;
}
}
if((namespaceURI.length()==0)&!(containingElement==0)) {
// didn't find one in attributes, look in ancestor elements
if(DEBUGXMLPARSER) {
printf("my prefix is not xml, looking for binding in ancestor element\n");
}
const XMLString* pNamespaceURI=containingElement->lookupNamespaceURI(prefix);
if(!(pNamespaceURI==0)) {
namespaceURI=*pNamespaceURI;
}
}
if(namespaceURI.length()==0) {
// cannot find a URI binding
(*XMLEntityStreamStack.begin())->streamPos = lastStreamPos;
(*XMLEntityStreamStack.begin())->streamPos.columnNumber++;
throw XMLParserException(&XMLEntityStreamStack,
"Cannot find internal URI binding for this prefix",
XMLParserException::BAD_XML_ERR);
}
}
else {
// no prefix => look for default xmlns="..." binding
if(!(defaultURI.length()==0)) {
// a local default exists
if(DEBUGXMLPARSER) {
printf("there is a local default URI binding\n");
}
namespaceURI=defaultURI;
}
else if(!(containingElement==0)) {
// no local default, try in ancestor elements
if(DEBUGXMLPARSER) {
printf("looking for default binding in ancestor element\n");
}
const XMLString* pNamespaceURI=containingElement->lookupNamespaceURI("");
if(!(pNamespaceURI==0)) {
namespaceURI=*pNamespaceURI;
}
}
}
if(DEBUGXMLPARSER) {
printf("my namespaceURI binding is'%s'\n",namespaceURI.c_str());
}
if(theDocument==0) {
theDocument = myDOMImplementation.createDocument(namespaceURI,tagName,theDocumentType);
newElement = theDocument->documentElement();
}
else {
if (namespaceURI.length()==0) {
newElement = theDocument->createElement(tagName);
}
else {
newElement = theDocument->createElementNS(namespaceURI,tagName);
}
}
if(!(containingElement==0)) {
containingElement->appendChild(newElement);
}
// now add the attributes
pAttName = myAttributeNamesList.begin();
pAttValue = myAttributeValuesList.begin();
while(pAttName!=myAttributeNamesList.end()) {
if(DEBUGXMLPARSER) {
printf("examining attribute %s='%s'\n",pAttName->c_str(),pAttValue->c_str());
}
if(pAttName->splitNSName(prefix,localName)) {
// attribute has a prefix
if(DEBUGXMLPARSER) {
printf(" attribute has a prefix\n");
}
namespaceURI="";
if(prefix.eqxml()) {
namespaceURI = XML_NAMESPACEURI;
}
else if(prefix.eqxmlns()) {
namespaceURI = XMLNS_NAMESPACEURI;
}
else {
// need to look for local binding
if(DEBUGXMLPARSER) {
printf(" prefix is not xml or xmlns, looking for local binding\n");
}
list<XMLString>::const_iterator pLocalPrefix=localPrefixes.begin();
list<XMLString>::const_iterator pLocalURIs=localURIs.begin();
while((namespaceURI.length()==0)&(pLocalPrefix!=localPrefixes.end())) {
if(*pLocalPrefix==prefix) {
namespaceURI=*pLocalURIs;
}
pLocalPrefix++;
pLocalURIs++;
}
}
if((namespaceURI.length()==0)&!(containingElement==0)) {
// look for default in ancestor elements
if(DEBUGXMLPARSER) {
printf("no local binding found, looking for ancestral binding\n");
}
const XMLString* pNamespaceURI=containingElement->lookupNamespaceURI("");
if(!(pNamespaceURI==0)) {
namespaceURI=*pNamespaceURI;
}
}
if(namespaceURI.length()==0) {
sprintf(errormessage,"Cannot find internal URI binding for prefix '%s'\n",prefix.c_str());
throw XMLParserException(&XMLEntityStreamStack,errormessage,XMLParserException::BAD_XML_ERR);
}
// all is ok, can add NSAttribute
newElement->setAttributeNS(namespaceURI,*pAttName,*pAttValue);
}
else {
// attribute has no prefix
if(DEBUGXMLPARSER) {
printf(" attribute has no prefix\n");
}
if(pAttName->eqxmlns()) {
namespaceURI = XMLNS_NAMESPACEURI;
}
else {
namespaceURI = defaultURI;
}
if(namespaceURI.length()==0) {
newElement->setAttribute(*pAttName,*pAttValue);
}
else {
newElement->setAttributeNS(namespaceURI,*pAttName,*pAttValue);
}
}
pAttName++;
pAttValue++;
}
if(!isEmptyElement) {
matchProduction43content(newElement);
if((*XMLEntityStreamStack.begin()) != enteringXMLEntityStream) {
throw XMLParserException(&XMLEntityStreamStack,
"End tag without start tag in same entity",
XMLParserException::BAD_XML_ERR);
}
myxmdsBytePoint = (*XMLEntityStreamStack.begin())->streamPos.count;
matchProduction42ETag(tagName);
}
return 1;
};
// ******************************************************************************
bool XMLParser::matchProduction40STag(
XMLString* tagName,
list<XMLString>* myAttributeNamesList,
list<XMLString>* myAttributeValuesList) {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction40STag\n");
}
StreamPositionStruct lastStreamPos1 = (*XMLEntityStreamStack.begin())->streamPos;
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),"<")) {
return 0;
}
StreamPositionStruct lastStreamPos2 = (*XMLEntityStreamStack.begin())->streamPos;
//char c=(*XMLEntityStreamStack.begin())->nextChar();
signed char c=(*XMLEntityStreamStack.begin())->nextChar();
if(c==EOF) {
// back out
(*XMLEntityStreamStack.begin())->streamPos = lastStreamPos1;
return 0;
}
if(!XMLChar::isLetter(c)) {
// back out
(*XMLEntityStreamStack.begin())->streamPos = lastStreamPos1;
return 0;
}
// critical point
(*XMLEntityStreamStack.begin())->streamPos = lastStreamPos2;
matchProduction05Name((*XMLEntityStreamStack.begin()),*tagName);
while(matchProduction03S((*XMLEntityStreamStack.begin()),0)) {
XMLString nextAttributeName;
XMLString nextAttributeValue;
XMLString* newXMLString;
if(matchProduction41Attribute(nextAttributeName,nextAttributeValue)) {
newXMLString = new XMLString(nextAttributeName);
myAttributeNamesList->push_back(*newXMLString);
newXMLString = new XMLString(nextAttributeValue);
myAttributeValuesList->push_back(*newXMLString);
}
}
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),">")) {
// not correctly terminated
throw XMLParserException(&XMLEntityStreamStack,"'>' expected",XMLParserException::BAD_XML_ERR);
}
return 1;
};
// ******************************************************************************
bool XMLParser::matchProduction41Attribute(
XMLString& AttName,
XMLString& AttValue) {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction41Attribute\n");
}
StreamPositionStruct lastStreamPos;
lastStreamPos = (*XMLEntityStreamStack.begin())->streamPos;
//char c=(*XMLEntityStreamStack.begin())->nextChar();
signed char c=(*XMLEntityStreamStack.begin())->nextChar();
if(c==EOF) {
return 0;
}
if(!XMLChar::isLetter(c)) {
// not an attribute
(*XMLEntityStreamStack.begin())->streamPos = lastStreamPos;
return 0;
}
(*XMLEntityStreamStack.begin())->streamPos = lastStreamPos;
matchProduction05Name((*XMLEntityStreamStack.begin()),AttName);
// check that AttName is NS well formed
if(!AttName.isNSWellFormed()) {
(*XMLEntityStreamStack.begin())->streamPos = lastStreamPos;
throw XMLParserException(&XMLEntityStreamStack,"Attribute name not NameSpace well formed",
XMLParserException::BAD_XML_ERR);
}
// check that prefix and localName are valid
XMLString prefix;
XMLString localName;
if(AttName.splitNSName(prefix,localName)) {
if(!(prefix.eqxmlns()|prefix.eqxml())&prefix.beginsWithxml()) {
(*XMLEntityStreamStack.begin())->streamPos = lastStreamPos;
throw XMLParserException(&XMLEntityStreamStack,
"Prefix not allowed to begin with (X|x)(M|m)(L|l)",
XMLParserException::BAD_XML_ERR);
}
if(localName.length()==0) {
throw XMLParserException(&XMLEntityStreamStack,"Where is the local name?",
XMLParserException::BAD_XML_ERR);
}
}
else {
if(!AttName.eqxmlns()&AttName.beginsWithxml()) {
(*XMLEntityStreamStack.begin())->streamPos = lastStreamPos;
throw XMLParserException(&XMLEntityStreamStack,
"Atrribute name not allowed to begin with (X|x)(M|m)(L|l)",
XMLParserException::BAD_XML_ERR);
}
}
matchProduction25Eq((*XMLEntityStreamStack.begin()));
lastStreamPos=(*XMLEntityStreamStack.begin())->streamPos;
matchProduction10AttValue(AttValue);
(*XMLEntityStreamStack.begin())->streamPos = lastStreamPos;
// now parse the AttValue for character and general entity refs,
// checking for circular references as we go. See 14CharData for prior example
list<XMLEntityStream*> lastXMLEntityStreamStack;
list<StreamPositionStruct> lastStreamsPosition;
storeStreamPos(lastXMLEntityStreamStack,lastStreamsPosition);
long length=sweepAttValue(0);
restoreStreamPos(lastXMLEntityStreamStack,lastStreamsPosition);
char* s=new char[length+1];
sweepAttValue(s);
AttValue=s;
delete s;
return 1;
};
// ******************************************************************************
void XMLParser::matchProduction42ETag(
XMLString& RequiredName) {
// this production is required
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction42ETag\n");
}
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),"</")) {
// not correctly opened
throw XMLParserException(&XMLEntityStreamStack,"'</' expected",
XMLParserException::BAD_XML_ERR);
}
XMLString ETagName;
matchProduction05Name((*XMLEntityStreamStack.begin()),ETagName);
if(!(RequiredName==ETagName)) {
// not correctly terminated
(*XMLEntityStreamStack.begin())->streamPos.count -= ETagName.length();
(*XMLEntityStreamStack.begin())->streamPos.columnNumber -= ETagName.length();
sprintf(errormessage,
"End tag for element '%s' expected",RequiredName.c_str());
throw XMLParserException(&XMLEntityStreamStack,errormessage,
XMLParserException::BAD_XML_ERR);
}
matchProduction03S((*XMLEntityStreamStack.begin()),0);
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),">")) {
// not correctly terminated
throw XMLParserException(&XMLEntityStreamStack,"'>' expected",
XMLParserException::BAD_XML_ERR);
}
};
// ******************************************************************************
void XMLParser::matchProduction43content(
Element* containingElement) {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction43content\n");
}
bool contentFound=1;
while(contentFound) {
if (contentFound=matchProduction14CharData(containingElement)) {}
else if(contentFound=matchProduction39Element(containingElement)) {}
// else if(contentFound=matchProduction67Reference(containingElement)) {}
else if(contentFound=matchProduction18CDSect(containingElement)) {}
else if(contentFound=matchProduction16PI(containingElement)) {}
else {
(contentFound=matchProduction15Comment(containingElement));
}
}
};
// ******************************************************************************
bool XMLParser::matchProduction44EmptyElementTag(
XMLString* tagName,
list<XMLString>* myAttributeNamesList,
list<XMLString>* myAttributeValuesList) {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction44EmptyElementTag\n");
}
// this routine is a special case of the normal STag routine, in that
// it will go the end and then back out if no / found
StreamPositionStruct lastStreamPos1 = (*XMLEntityStreamStack.begin())->streamPos;
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),"<")) {
return 0;
}
StreamPositionStruct lastStreamPos2 = (*XMLEntityStreamStack.begin())->streamPos;
//char c=(*XMLEntityStreamStack.begin())->nextChar();
signed char c=(*XMLEntityStreamStack.begin())->nextChar();
if(c==EOF) {
// back out
(*XMLEntityStreamStack.begin())->streamPos = lastStreamPos1;
return 0;
}
if(!XMLChar::isLetter(c)) {
// back out
(*XMLEntityStreamStack.begin())->streamPos = lastStreamPos1;
return 0;
}
// while this routine will go to the end and then back out if no /> found
// it well test the tagName and the attribute list for errors anyway
(*XMLEntityStreamStack.begin())->streamPos = lastStreamPos2;
matchProduction05Name((*XMLEntityStreamStack.begin()),*tagName);
// check that tagName is NS well formed
if(!tagName->isNSWellFormed()) {
(*XMLEntityStreamStack.begin())->streamPos.columnNumber -= tagName->length();
throw XMLParserException(&XMLEntityStreamStack,"Element tagName not NameSpace well formed",XMLParserException::BAD_XML_ERR);
}
// check that prefix and localName are valid
XMLString prefix;
XMLString localName;
if(tagName->splitNSName(prefix,localName)) {
if((!prefix.eqxml())&prefix.beginsWithxml()) {
(*XMLEntityStreamStack.begin())->streamPos.columnNumber -= tagName->length();
throw XMLParserException(&XMLEntityStreamStack,
"Prefix not allowed to begin with (X|x)(M|m)(L|l)",
XMLParserException::BAD_XML_ERR);
}
if(localName.length()==0) {
throw XMLParserException(&XMLEntityStreamStack,"Where is the local name?",
XMLParserException::BAD_XML_ERR);
}
}
else {
if(tagName->beginsWithxml()) {
(*XMLEntityStreamStack.begin())->streamPos.columnNumber -= tagName->length();
throw XMLParserException(&XMLEntityStreamStack,
"Element name not allowed to begin with (X|x)(M|m)(L|l)",
XMLParserException::BAD_XML_ERR);
}
}
while(matchProduction03S((*XMLEntityStreamStack.begin()),0)) {
XMLString nextAttributeName;
XMLString nextAttributeValue;
XMLString* newXMLString;
if(matchProduction41Attribute(nextAttributeName,nextAttributeValue)) {
// test new attribute to see if its name is unique in this element tag
for(list<XMLString>::const_iterator pXMLString = myAttributeNamesList->begin(); pXMLString != myAttributeNamesList->end();pXMLString++) {
if(nextAttributeName==*pXMLString) {
throw XMLParserException(&XMLEntityStreamStack,"Duplicated attribute!",
XMLParserException::BAD_XML_ERR);
}
}
// add new attribute to list
newXMLString = new XMLString(nextAttributeName);
myAttributeNamesList->push_back(*newXMLString);
newXMLString = new XMLString(nextAttributeValue);
myAttributeValuesList->push_back(*newXMLString);
}
}
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),"/>")) {
// back out
myAttributeNamesList->clear();
myAttributeValuesList->clear();
(*XMLEntityStreamStack.begin())->streamPos = lastStreamPos1;
return 0;
}
return 1;
};
// ******************************************************************************
bool XMLParser::matchProduction45elementdecl() {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction45elementdecl\n");
}
const XMLEntityStream *const enteringStream = (*XMLEntityStreamStack.begin());
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),"<!ELEMENT")) {
return 0; // back out
}
// critical point
matchProduction03SDeep(1);
XMLString elementdeclName;
matchProduction05Name((*XMLEntityStreamStack.begin()),elementdeclName);
matchProduction03SDeep(1);
matchProduction46contentspec();
matchProduction03SDeep(0);
if((*XMLEntityStreamStack.begin()) != enteringStream) {
// Bad nesting
throw XMLParserException(&XMLEntityStreamStack,
"Parameter Entity Logical structures not properly nested.",
XMLParserException::BAD_XML_ERR);
}
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),">")) {
// not correctly terminated
throw XMLParserException(&XMLEntityStreamStack,"'>'expected",
XMLParserException::BAD_XML_ERR);
}
return 1;
};
// ******************************************************************************
void XMLParser::matchProduction46contentspec() {
// this production is required
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction46contentspec\n");
}
if(matchProduction51Mixed()) {
return;
}
if(matchProduction47children()) { // test for children after mixed
return;
}
if(matchProductionFixedString((*XMLEntityStreamStack.begin()),"EMPTY")) {
return;
}
if(matchProductionFixedString((*XMLEntityStreamStack.begin()),"ANY")) {
return;
}
throw XMLParserException(&XMLEntityStreamStack,
"'EMPTY' or 'ANY' or mixed or children productions expected",
XMLParserException::BAD_XML_ERR);
};
// ******************************************************************************
bool XMLParser::matchProduction47children() {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction47children\n");
}
StreamPositionStruct lastStreamPos = (*XMLEntityStreamStack.begin())->streamPos;
if(!matchProduction49choice()) {
if(!matchProduction50seq()) { // testing seq after choice is important!
// back out
(*XMLEntityStreamStack.begin())->streamPos = lastStreamPos;
return 0;
}
}
if(matchProductionFixedString((*XMLEntityStreamStack.begin()),"?")) {
return 1;
}
if(matchProductionFixedString((*XMLEntityStreamStack.begin()),"*")) {
return 1;
}
if(matchProductionFixedString((*XMLEntityStreamStack.begin()),"+")) {
return 1;
}
return 1;
};
// ******************************************************************************
bool XMLParser::matchProduction48cp() {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction48cp\n");
}
XMLString Name;
if(!matchProduction49choice()) {
if(!matchProduction50seq()) {
try {
matchProduction05Name((*XMLEntityStreamStack.begin()),Name);
}
catch(XMLParserException XMLRoutinesErr) {
return 0;
}
}
}
if(matchProduction03SDeep(0)>0) {
return 1;
}
if(matchProductionFixedString((*XMLEntityStreamStack.begin()),"?")) {
return 1;
}
if(matchProductionFixedString((*XMLEntityStreamStack.begin()),"*")) {
return 1;
}
matchProductionFixedString((*XMLEntityStreamStack.begin()),"+");
return 1;
};
// ******************************************************************************
bool XMLParser::matchProduction49choice() {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction49choice\n");
}
list<XMLEntityStream*> lastXMLEntityStreamStack;
list<StreamPositionStruct> lastStreamsPosition;
storeStreamPos(lastXMLEntityStreamStack,lastStreamsPosition);
bool foundOR=0;
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),"(")) {
return 0;
}
matchProduction03SDeep(0);
if(!matchProduction48cp()) {
// back out
restoreStreamPos(lastXMLEntityStreamStack,lastStreamsPosition);
return 0;
}
matchProduction03SDeep(0);
while(matchProductionFixedString((*XMLEntityStreamStack.begin()),"|")) {
// critical point
matchProduction03SDeep(0);
if(!matchProduction48cp()) {
throw XMLParserException(&XMLEntityStreamStack,
"Name or (choice) or (seq) expected",
XMLParserException::BAD_XML_ERR);
}
matchProduction03SDeep(0);
foundOR=1;
}
if(!foundOR) {
// back out
restoreStreamPos(lastXMLEntityStreamStack,lastStreamsPosition);
return 0;
}
if((*XMLEntityStreamStack.begin()) != (*lastXMLEntityStreamStack.begin())) {
// Bad nesting
throw XMLParserException(&XMLEntityStreamStack,
"Logical structures not properly nested.",
XMLParserException::BAD_XML_ERR);
}
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),")")) {
throw XMLParserException(&XMLEntityStreamStack,"'|' or ')' expected",
XMLParserException::BAD_XML_ERR);
}
return 1;
};
// ******************************************************************************
bool XMLParser::matchProduction50seq() {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction50seq\n");
}
const XMLEntityStream *const enteringStream = (*XMLEntityStreamStack.begin());
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),"(")) {
return 0;
}
// set critical point here, but test for seq after choice
// and children after mixed, this way at least opening with a bracket
// will generate informative error messages
matchProduction03SDeep(0);
if(!matchProduction48cp()) {
throw XMLParserException(&XMLEntityStreamStack,
"#PCDATA or Name or (choice) or (seq) expected",
XMLParserException::BAD_XML_ERR);
}
matchProduction03SDeep(0);
while(matchProductionFixedString((*XMLEntityStreamStack.begin()),",")) {
matchProduction03SDeep(0);
if(!matchProduction48cp()) {
throw XMLParserException(&XMLEntityStreamStack,
"Name or (choice) or (seq) expected",
XMLParserException::BAD_XML_ERR);
}
matchProduction03SDeep(0);
}
if((*XMLEntityStreamStack.begin()) != enteringStream) {
// Bad nesting
throw XMLParserException(&XMLEntityStreamStack,
"Logical structures not properly nested.",
XMLParserException::BAD_XML_ERR);
}
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),")")) {
throw XMLParserException(&XMLEntityStreamStack,"',' or '|' or ')' expected",
XMLParserException::BAD_XML_ERR);
}
return 1;
};
// ******************************************************************************
bool XMLParser::matchProduction51Mixed() {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction51Mixed\n");
}
list<XMLEntityStream*> lastXMLEntityStreamStack;
list<StreamPositionStruct> lastStreamsPosition;
storeStreamPos(lastXMLEntityStreamStack,lastStreamsPosition);
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),"(")) {
// back out
restoreStreamPos(lastXMLEntityStreamStack,lastStreamsPosition);
return 0;
}
matchProduction03SDeep(0);
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),"#PCDATA")) {
// back out
restoreStreamPos(lastXMLEntityStreamStack,lastStreamsPosition);
return 0;
}
// critcal point
matchProduction03SDeep(0);
XMLString Name;
bool hasNames=0;
while(matchProductionFixedString((*XMLEntityStreamStack.begin()),"|")) {
matchProduction03SDeep(0);
matchProduction05Name((*XMLEntityStreamStack.begin()),Name);
matchProduction03SDeep(0);
hasNames=1;
}
if((*XMLEntityStreamStack.begin()) != (*lastXMLEntityStreamStack.begin())) {
// Bad nesting
throw XMLParserException(&XMLEntityStreamStack,
"Logical structures not properly nested.",
XMLParserException::BAD_XML_ERR);
}
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),")")) {
throw XMLParserException(&XMLEntityStreamStack,"')' expected",
XMLParserException::BAD_XML_ERR);
}
if(hasNames) {
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),"*")) {
throw XMLParserException(&XMLEntityStreamStack,"'*' expected",
XMLParserException::BAD_XML_ERR);
}
}
return 1;
};
// ******************************************************************************
bool XMLParser::matchProduction52AttlistDecl() {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction52AttlistDecl\n");
}
const XMLEntityStream *const enteringStream = (*XMLEntityStreamStack.begin());
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),"<!ATTLIST")) {
return 0; // back out
}
// critical point
matchProduction03SDeep(1);
XMLString AttlistDeclName;
matchProduction05Name((*XMLEntityStreamStack.begin()),AttlistDeclName);
while(matchProduction53AttDef());
matchProduction03SDeep(0);
if((*XMLEntityStreamStack.begin()) != enteringStream) {
// PE stream hasn't resurfaced
throw XMLParserException(&XMLEntityStreamStack,
"PE Logical structures not properly nested.",
XMLParserException::BAD_XML_ERR);
}
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),">")) {
// not correctly terminated
throw XMLParserException(&XMLEntityStreamStack,"'>' expected",
XMLParserException::BAD_XML_ERR);
}
return 1;
};
// ******************************************************************************
bool XMLParser::matchProduction53AttDef() {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction53AttDef\n");
}
if(matchProduction03SDeep(0)==0) {
return 0;
}
char c=(*XMLEntityStreamStack.begin())->nextChar();
if(c=='>') {
// back out, but it doesn't matter that we have covered the white space
(*XMLEntityStreamStack.begin())->streamPos.count--;
(*XMLEntityStreamStack.begin())->streamPos.columnNumber--;
return 0;
}
// critical point
XMLString attName;
matchProduction05Name((*XMLEntityStreamStack.begin()),attName);
matchProduction03SDeep(1);
matchProduction54AttType();
matchProduction03SDeep(1);
matchProduction60DefaultDecl();
return 1;
};
// ******************************************************************************
void XMLParser::matchProduction54AttType() {
// this production is required
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction54AttType\n");
}
if(matchProduction55StringType()) {
return;
}
if(matchProduction56TokenizedType()) {
return;
}
if(matchProduction57EnumeratedType()) {
return;
}
throw XMLParserException(&XMLEntityStreamStack,"AttType expected",
XMLParserException::BAD_XML_ERR);
};
// ******************************************************************************
bool XMLParser::matchProduction55StringType() {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction55StringType\n");
}
return matchProductionFixedString((*XMLEntityStreamStack.begin()),"CDATA");
};
// ******************************************************************************
bool XMLParser::matchProduction56TokenizedType() {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction56TokenizedType\n");
}
if(matchProductionFixedString((*XMLEntityStreamStack.begin()),"NMTOKENS")) {
return 1;
}
if(matchProductionFixedString((*XMLEntityStreamStack.begin()),"NMTOKEN")) {
return 1;
}
if(matchProductionFixedString((*XMLEntityStreamStack.begin()),"ENTITIES")) {
return 1;
}
if(matchProductionFixedString((*XMLEntityStreamStack.begin()),"ENTITY")) {
return 1;
}
if(matchProductionFixedString((*XMLEntityStreamStack.begin()),"IDREFS")) {
return 1;
}
if(matchProductionFixedString((*XMLEntityStreamStack.begin()),"IDREF")) {
return 1;
}
if(matchProductionFixedString((*XMLEntityStreamStack.begin()),"ID")) {
return 1;
}
return 0;
};
// ******************************************************************************
bool XMLParser::matchProduction57EnumeratedType() {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction57EnumeratedType\n");
}
if(matchProduction58NotationType()) {
return 1;
}
if(matchProduction59Enumeration()) {
return 1;
}
return 0;
};
// ******************************************************************************
bool XMLParser::matchProduction58NotationType() {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction58NotationType\n");
}
XMLString Name;
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),"NOTATION")) {
return 0;
}
// critical point
matchProduction03SDeep(1);
const XMLEntityStream *const enteringStream = (*XMLEntityStreamStack.begin());
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),"(")) {
throw XMLParserException(&XMLEntityStreamStack,"'(' expected",
XMLParserException::BAD_XML_ERR);
}
matchProduction03SDeep(0);
matchProduction05Name((*XMLEntityStreamStack.begin()),Name);
matchProduction03SDeep(0);
while(matchProductionFixedString((*XMLEntityStreamStack.begin()),"|")) {
matchProduction03SDeep(0);
matchProduction05Name((*XMLEntityStreamStack.begin()),Name);
matchProduction03SDeep(0);
}
if((*XMLEntityStreamStack.begin()) != enteringStream) {
// Bad nesting
throw XMLParserException(&XMLEntityStreamStack,
"Logical structures not properly nested.",
XMLParserException::BAD_XML_ERR);
}
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),")")) {
throw XMLParserException(&XMLEntityStreamStack,"')' expected",
XMLParserException::BAD_XML_ERR);
}
return 1;
};
// ******************************************************************************
bool XMLParser::matchProduction59Enumeration() {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction59Enumeration\n");
}
XMLString Nmtoken;
const XMLEntityStream *const enteringStream = (*XMLEntityStreamStack.begin());
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),"(")) {
return 0;
}
// critical point
matchProduction03SDeep(0);
matchProduction07Nmtoken((*XMLEntityStreamStack.begin()),Nmtoken);
matchProduction03SDeep(0);
while(matchProductionFixedString((*XMLEntityStreamStack.begin()),"|")) {
matchProduction03SDeep(0);
matchProduction07Nmtoken((*XMLEntityStreamStack.begin()),Nmtoken);
matchProduction03SDeep(0);
}
if((*XMLEntityStreamStack.begin()) != enteringStream) {
// Bad nesting
throw XMLParserException(&XMLEntityStreamStack,
"Logical structures not properly nested.",
XMLParserException::BAD_XML_ERR);
}
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),")")) {
throw XMLParserException(&XMLEntityStreamStack,"')' expected",
XMLParserException::BAD_XML_ERR);
}
return 1;
};
// ******************************************************************************
void XMLParser::matchProduction60DefaultDecl() {
// this production is required
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction60DefaultDecl\n");
}
if(matchProductionFixedString((*XMLEntityStreamStack.begin()),"#REQUIRED")) {
return;
}
if(matchProductionFixedString((*XMLEntityStreamStack.begin()),"#IMPLIED")) {
return;
}
matchProductionFixedString((*XMLEntityStreamStack.begin()),"#FIXED");
matchProduction03SDeep(0);
XMLString AttValue;
try {
matchProduction10AttValue(AttValue);
}
catch(XMLParserException) {
throw XMLParserException(&XMLEntityStreamStack,
"'#REQUIRED' or '#IMPLIED' or '#FIXED AttValue' expected",
XMLParserException::BAD_XML_ERR);
}
};
// ******************************************************************************
bool XMLParser::matchProduction61conditionalSect() {
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction61conditionalSect\n");
}
// this production is optional
if(matchProduction62includeSect()) {
return 1;
}
if(matchProduction63ignoreSect()) {
return 1;
}
return 0;
};
// ******************************************************************************
bool XMLParser::matchProduction62includeSect() {
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction62includeSect\n");
}
// this production is optional
list<XMLEntityStream*> lastXMLEntityStreamStack;
list<StreamPositionStruct> lastStreamsPosition;
storeStreamPos(lastXMLEntityStreamStack,lastStreamsPosition);
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),"<![")) {
return 0;
}
matchProduction03SDeep(0);
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),"INCLUDE")) {
// back out
restoreStreamPos(lastXMLEntityStreamStack,lastStreamsPosition);
return 0;
}
// critical point
matchProduction03SDeep(0);
if((*XMLEntityStreamStack.begin()) != (*lastXMLEntityStreamStack.begin())) {
// Bad nesting
throw XMLParserException(&XMLEntityStreamStack,
"Logical structures not properly nested.",
XMLParserException::BAD_XML_ERR);
}
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),"[")) {
throw XMLParserException(&XMLEntityStreamStack,"'[' expected",
XMLParserException::BAD_XML_ERR);
}
matchProduction31extSubsetDecl();
if((*XMLEntityStreamStack.begin()) != (*lastXMLEntityStreamStack.begin())) {
// Bad nesting
throw XMLParserException(&XMLEntityStreamStack,
"Logical structures not properly nested.",
XMLParserException::BAD_XML_ERR);
}
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),"]]>")) {
throw XMLParserException(&XMLEntityStreamStack,"']]>' expected",
XMLParserException::BAD_XML_ERR);
}
return 1;
};
// ******************************************************************************
bool XMLParser::matchProduction63ignoreSect() {
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction63ignoreSect\n");
}
// this production is optional
list<XMLEntityStream*> lastXMLEntityStreamStack;
list<StreamPositionStruct> lastStreamsPosition;
storeStreamPos(lastXMLEntityStreamStack,lastStreamsPosition);
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),"<![")) {
return 0;
}
matchProduction03SDeep(0);
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),"IGNORE")) {
// back out
restoreStreamPos(lastXMLEntityStreamStack,lastStreamsPosition);
return 0;
}
// critical point
matchProduction03SDeep(0);
if((*XMLEntityStreamStack.begin()) != (*lastXMLEntityStreamStack.begin())) {
// Bad nesting
throw XMLParserException(&XMLEntityStreamStack,
"Logical structures not properly nested.",
XMLParserException::BAD_XML_ERR);
}
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),"[")) {
throw XMLParserException(&XMLEntityStreamStack,"'[' expected",
XMLParserException::BAD_XML_ERR);
}
matchProduction64ignoreSectContents();
if((*XMLEntityStreamStack.begin()) != (*lastXMLEntityStreamStack.begin())) {
// Bad nesting
throw XMLParserException(&XMLEntityStreamStack,
"Logical structures not properly nested.",
XMLParserException::BAD_XML_ERR);
}
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),"]]>")) {
throw XMLParserException(&XMLEntityStreamStack,"']]>' expected",
XMLParserException::BAD_XML_ERR);
}
return 1;
};
// ******************************************************************************
void XMLParser::matchProduction64ignoreSectContents() {
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction64ignoreSectContents\n");
}
// this production is optional
matchProduction65ignore();
while(matchProductionFixedString((*XMLEntityStreamStack.begin()),"<![")) {
matchProduction64ignoreSectContents();
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),"]]>")) {
throw XMLParserException(&XMLEntityStreamStack,"']]>' expected",
XMLParserException::BAD_XML_ERR);
}
matchProduction65ignore();
}
};
// ******************************************************************************
void XMLParser::matchProduction65ignore() {
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction65ignore\n");
}
// this production is optional
//char s[4]={0,0,0,0};
signed char s[4]={0,0,0,0};
StreamPositionStruct l[3];
l[0]=(*XMLEntityStreamStack.begin())->streamPos;
s[0]=(*XMLEntityStreamStack.begin())->nextChar();
l[1]=(*XMLEntityStreamStack.begin())->streamPos;
s[1]=(*XMLEntityStreamStack.begin())->nextChar();
if(s[0]==EOF) {
(*XMLEntityStreamStack.begin())->streamPos=l[0];
return;
}
l[2]=(*XMLEntityStreamStack.begin())->streamPos;
s[2]=(*XMLEntityStreamStack.begin())->nextChar();
while((s[2]!=EOF)&&strcmp((char *)s,"<![")&&strcmp((char *)s,"]]>")) {
s[0]=s[1];s[1]=s[2];
l[0]=l[1];l[1]=l[2];
l[2]=(*XMLEntityStreamStack.begin())->streamPos;
s[2]=(*XMLEntityStreamStack.begin())->nextChar();
}
(*XMLEntityStreamStack.begin())->streamPos=l[0];
};
// ******************************************************************************
unsigned long XMLParser::matchProduction66CharRef(
XMLEntityStream *const thisStream,
//char& cRef) const {
signed char& cRef) const {
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction66CharRef\n");
}
StreamPositionStruct lastStreamPos = thisStream->streamPos;
//char c;
signed char c;
c=thisStream->nextChar();
if(c!='&') {
thisStream->streamPos=lastStreamPos;
return 0;
};
c=thisStream->nextChar();
if(c!='#') {
thisStream->streamPos=lastStreamPos;
return 0;
};
// critcal point
bool hexNumber=0;
c=thisStream->nextChar();
if(c=='x') {
hexNumber=1;
c=thisStream->nextChar();
}
unsigned long length=0;
if(hexNumber) {
while(XMLChar::isLatinHexDigit(c)&(c!=EOF)) {
length++;
c=thisStream->nextChar();
}
}
else {
while(XMLChar::isLatinDigit(c)&(c!=EOF)) {
length++;
c=thisStream->nextChar();
}
}
if(length==0) {
if(hexNumber) {
throw XMLParserException(&XMLEntityStreamStack,
"hexadecimal reference expected",
XMLParserException::BAD_XML_ERR);
}
else {
throw XMLParserException(&XMLEntityStreamStack,
"decimal reference expected",
XMLParserException::BAD_XML_ERR);
}
}
thisStream->streamPos.count -= length+1;
thisStream->streamPos.columnNumber -= length+1;
char* CharRefString;
unsigned int CharRef;
CharRefString = new char[length+1];
for(unsigned long i=0; i<length; i++) {
CharRefString[i] = thisStream->nextChar();
}
CharRefString[length]=0;
if(hexNumber) {
sscanf(CharRefString,"%x",&CharRef);
}
else {
sscanf(CharRefString,"%u",&CharRef);
}
delete CharRefString;
// finally check termination
lastStreamPos = thisStream->streamPos;
c=thisStream->nextChar();
if(c!=';') {
// not correctly terminated
thisStream->streamPos=lastStreamPos;
throw XMLParserException(&XMLEntityStreamStack,"';' expected",
XMLParserException::BAD_XML_ERR);
};
if(CharRef&0xFF00) {
// UTF16 and higher encodings not supported
throw XMLParserException(&XMLEntityStreamStack,
"Reference to Unicode XML character unable to be processed",
XMLParserException::BAD_XML_ERR);
}
cRef = (char)CharRef;
if(!XMLChar::isChar(cRef)) {
// illegal character
throw XMLParserException(&XMLEntityStreamStack,
"Reference to Illegal XML character",
XMLParserException::BAD_XML_ERR);
}
if(DEBUGXMLPARSER) {
printf("CharRef = %c\n",CharRef);
}
if(hexNumber) {
return length+4;
}
return length+3;
};
// ******************************************************************************
unsigned long XMLParser::matchProduction68EntityRef(
XMLEntityStream *const thisStream,
XMLString& refName) const {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction68EntityRef\n");
}
StreamPositionStruct lastStreamPos = thisStream->streamPos;
char c;
c=thisStream->nextChar();
if(c!='&') {
thisStream->streamPos=lastStreamPos;
return 0;
};
//critical point
if(!matchProduction05Name(thisStream,refName)) {
throw XMLParserException(&XMLEntityStreamStack,"Name expected",
XMLParserException::BAD_XML_ERR);
}
lastStreamPos = thisStream->streamPos;
c=thisStream->nextChar();
if(c!=';') {
thisStream->streamPos=lastStreamPos;
throw XMLParserException(&XMLEntityStreamStack,"';' expected",
XMLParserException::BAD_XML_ERR);
}
return refName.length()+2;
};
// ******************************************************************************
unsigned long XMLParser::matchProduction69PEReference(
XMLEntityStream *const thisStream,
XMLString& PEName) const {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction69PEReference\n");
}
StreamPositionStruct lastStreamPos = thisStream->streamPos;
char c;
c=thisStream->nextChar();
if(c!='%') {
thisStream->streamPos=lastStreamPos;
return 0;
};
//critical point
if(!matchProduction05Name(thisStream,PEName)) {
throw XMLParserException(&XMLEntityStreamStack,"Name expected",
XMLParserException::BAD_XML_ERR);
}
lastStreamPos = thisStream->streamPos;
c=thisStream->nextChar();
if(c!=';') {
thisStream->streamPos=lastStreamPos;
throw XMLParserException(&XMLEntityStreamStack,"';' expected",
XMLParserException::BAD_XML_ERR);
}
return PEName.length()+2;
};
// ******************************************************************************
bool XMLParser::matchProduction70EntityDecl() {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction70EntityDecl\n");
}
if(matchProduction72PEDecl()) {
return 1;
}
if(matchProduction71GEDecl()) {
// do this one second for sake of error reporting
return 1;
}
return 0;
};
// ******************************************************************************
bool XMLParser::matchProduction71GEDecl() {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction71GEDecl\n");
}
const XMLEntityStream *const enteringStream = (*XMLEntityStreamStack.begin());
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),"<!ENTITY")) {
return 0; // back out
}
matchProduction03SDeep(1);
// critical point
XMLString EntityDeclName;
XMLString PubidLiteral;
XMLString SystemLiteral;
XMLString NotationName;
XMLString EntityLiteral;
matchProduction05Name((*XMLEntityStreamStack.begin()),EntityDeclName);
matchProduction03SDeep(1);
matchProduction73EntityDef(PubidLiteral,SystemLiteral,NotationName,EntityLiteral);
matchProduction03SDeep(0);
if((*XMLEntityStreamStack.begin()) != enteringStream) {
// Bad nesting
throw XMLParserException(&XMLEntityStreamStack,
"Logical structures not properly nested.",
XMLParserException::BAD_XML_ERR);
}
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),">")) {
// not correctly terminated
throw XMLParserException(&XMLEntityStreamStack,"'>' expected",
XMLParserException::BAD_XML_ERR);
}
// ok, now we have a new XMLEntityStream to load into storage:
if(NotationName.length()>0) {
(*XMLEntityStreamStack.begin())->addUnparsedXMLEntityStream(
EntityDeclName,PubidLiteral,SystemLiteral,NotationName);
}
else if(SystemLiteral.length()>0) {
(*XMLEntityStreamStack.begin())->addGeneralXMLEntityStream(
EntityDeclName,PubidLiteral,SystemLiteral);
}
else {
(*XMLEntityStreamStack.begin())->addGeneralXMLEntityStream(EntityDeclName,EntityLiteral);
}
return 1;
};
// ******************************************************************************
bool XMLParser::matchProduction72PEDecl() {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction72PEDecl\n");
}
list<XMLEntityStream*> lastXMLEntityStreamStack;
list<StreamPositionStruct> lastStreamsPosition;
storeStreamPos(lastXMLEntityStreamStack,lastStreamsPosition);
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),"<!ENTITY")) {
return 0; // back out
}
matchProduction03SDeep(1);
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),"%")) {
// no % therefore not a PEDecl, back out
restoreStreamPos(lastXMLEntityStreamStack,lastStreamsPosition);
return 0;
}
// critical point
XMLString EntityDeclName;
XMLString PubidLiteral;
XMLString SystemLiteral;
XMLString EntityLiteral;
matchProduction03SDeep(1);
matchProduction05Name((*XMLEntityStreamStack.begin()),EntityDeclName);
matchProduction03SDeep(1);
matchProduction74PEDef(PubidLiteral,SystemLiteral,EntityLiteral);
matchProduction03SDeep(0);
if((*XMLEntityStreamStack.begin()) != (*lastXMLEntityStreamStack.begin())) {
// Bad nesting
throw XMLParserException(&XMLEntityStreamStack,
"Logical structures not properly nested.",
XMLParserException::BAD_XML_ERR);
}
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),">")) {
// not correctly terminated
throw XMLParserException(&XMLEntityStreamStack,"'>' expected",
XMLParserException::BAD_XML_ERR);
}
// ok, now we have a new XMLEntityStream to load into storage:
if(SystemLiteral.length()>0) {
(*XMLEntityStreamStack.begin())->addParameterXMLEntityStream(
EntityDeclName,PubidLiteral,SystemLiteral);
}
else {
(*XMLEntityStreamStack.begin())->addParameterXMLEntityStream(EntityDeclName,EntityLiteral);
}
return 1;
};
// ******************************************************************************
void XMLParser::matchProduction73EntityDef(
XMLString& PubidLiteral,
XMLString& SystemLiteral,
XMLString& NotationName,
XMLString& EntityLiteral) {
// this production is required
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction73EntityDef\n");
}
if(matchProduction75ExternalID(PubidLiteral,SystemLiteral)) {
matchProduction76NDataDecl(NotationName);
}
else {
try {
matchProduction09EntityLiteral(EntityLiteral);
}
catch(XMLParserException) {
throw XMLParserException(&XMLEntityStreamStack,
"EntityLiteral or ExternalID expected",
XMLParserException::BAD_XML_ERR);
}
}
};
// ******************************************************************************
void XMLParser::matchProduction74PEDef(
XMLString& PubidLiteral,
XMLString& SystemLiteral,
XMLString& EntityLiteral) {
// this production is required
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction74PEDef\n");
}
if(!matchProduction75ExternalID(PubidLiteral,SystemLiteral)) {
try {
matchProduction09EntityLiteral(EntityLiteral);
}
catch(XMLParserException) {
throw XMLParserException(&XMLEntityStreamStack,
"EntityLiteral or ExternalID expected",
XMLParserException::BAD_XML_ERR);
}
}
};
// ******************************************************************************
bool XMLParser::matchProduction75ExternalID(
XMLString& PubidLiteral,
XMLString& SystemLiteral) {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction75ExternalID\n");
}
if(matchProductionFixedString((*XMLEntityStreamStack.begin()),"SYSTEM")) {
// it is a SYSTEM declaration
matchProduction03SDeep(1);
matchProduction11SystemLiteral(SystemLiteral);
}
else if(matchProductionFixedString((*XMLEntityStreamStack.begin()),"PUBLIC")) {
// it is a PUBLIC declaration
matchProduction03SDeep(1);
matchProduction12PubidLiteral(PubidLiteral);
matchProduction03SDeep(1);
matchProduction11SystemLiteral(SystemLiteral);
}
else
return 0;
return 1;
};
// ******************************************************************************
bool XMLParser::matchProduction76NDataDecl(
XMLString& NotationName) {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction76NDataDecl\n");
}
list<XMLEntityStream*> lastXMLEntityStreamStack;
list<StreamPositionStruct> lastStreamsPosition;
storeStreamPos(lastXMLEntityStreamStack,lastStreamsPosition);
if(matchProduction03SDeep(0)==0) {
return 0;
}
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),"NDATA")) {
// no NDATA therefore not a NDataDecl
restoreStreamPos(lastXMLEntityStreamStack,lastStreamsPosition);
return 0;
}
// critical point
matchProduction03SDeep(1);
matchProduction05Name((*XMLEntityStreamStack.begin()),NotationName);
return 1;
};
// ******************************************************************************
void XMLParser::matchProduction77TextDecl(
XMLEntityStream *const thisStream,
XMLString& VersionNum,
XMLString& EncName) {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction77TextDecl\n");
}
StreamPositionStruct lastStreamPos = thisStream->streamPos;
if(!matchProductionFixedString(thisStream,"<?xml")) {
return;
}
if(matchProduction03S(thisStream,0)==0) {
// no following white space => not a TextDecl => back out
thisStream->streamPos = lastStreamPos;
return;
}
// critical point
matchProduction24VersionInfo(thisStream,VersionNum);
matchProduction80EncodingDecl(thisStream,EncName);
matchProduction03S(thisStream,0);
if(!matchProductionFixedString(thisStream,"?>")) {
// TextDecl incorrectly terminated
throw XMLParserException(&XMLEntityStreamStack,"'?>' expected",
XMLParserException::BAD_XML_ERR);
}
};
// ******************************************************************************
bool XMLParser::matchProduction80EncodingDecl(
XMLEntityStream *const thisStream,
XMLString& EncName) {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction80EncodingDecl\n");
}
StreamPositionStruct lastStreamPos = thisStream->streamPos;
if(matchProduction03S(thisStream,0)==0) {
return 0; // there was no white space
}
if(!matchProductionFixedString(thisStream,"encoding")) {
// back out
thisStream->streamPos = lastStreamPos;
return 0;
}
// critical point
matchProduction25Eq(thisStream);
matchProduction81EncName(thisStream,EncName);
return 1;
};
// ******************************************************************************
void XMLParser::matchProduction81EncName(
XMLEntityStream *const thisStream,
XMLString& EncName) {
// this production is required
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction81EncName\n");
}
matchProductionQuotedString(thisStream,EncName);
if(!EncName.isEncName()) {
// isn't an EncName
thisStream->streamPos.columnNumber -= EncName.length() + 1;
throw XMLParserException(&XMLEntityStreamStack,"not a valid Encoding name",
XMLParserException::BAD_XML_ERR);
}
if(DEBUGXMLPARSER) {
printf("EncName = '%s'\n",EncName.c_str());
}
};
// ******************************************************************************
bool XMLParser::matchProduction82NotationDecl() {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction82NotationDecl\n");
}
const XMLEntityStream *const enteringStream = (*XMLEntityStreamStack.begin());
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),"<!NOTATION")) {
return 0;
}
// critical point
matchProduction03SDeep(1);
XMLString SystemLiteral;
XMLString PubidLiteral;
XMLString NotationName;
matchProduction05Name((*XMLEntityStreamStack.begin()),NotationName);
matchProduction03SDeep(1);
if(!matchProduction83PublicID(PubidLiteral)) {// note order important here!
if(!matchProduction75ExternalID(PubidLiteral,SystemLiteral)) {
throw XMLParserException(&XMLEntityStreamStack,
"'SYSTEM' or 'PUBLIC' expected",
XMLParserException::BAD_XML_ERR);
}
}
matchProduction03SDeep(0);
if((*XMLEntityStreamStack.begin()) != enteringStream) {
// Bad nesting
throw XMLParserException(&XMLEntityStreamStack,
"Logical structures not properly nested.",
XMLParserException::BAD_XML_ERR);
}
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),">")) {
// not correctly terminated
throw XMLParserException(&XMLEntityStreamStack,"'>' expected",
XMLParserException::BAD_XML_ERR);
}
return 1;
};
// ******************************************************************************
bool XMLParser::matchProduction83PublicID(
XMLString& PubidLiteral) {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProduction83PublicID\n");
}
// this production is a special case of the 75ExternalID production in which
// the systemliteral is not required -- a bit tricky to pick this one up!
list<XMLEntityStream*> lastXMLEntityStreamStack;
list<StreamPositionStruct> lastStreamsPosition;
storeStreamPos(lastXMLEntityStreamStack,lastStreamsPosition);
if(!matchProductionFixedString((*XMLEntityStreamStack.begin()),"PUBLIC")) {
return 0;
}
matchProduction03SDeep(1);
matchProduction12PubidLiteral(PubidLiteral);
matchProduction03SDeep(0);
char c=(*XMLEntityStreamStack.begin())->nextChar();
if(c!='>') {
// back out
restoreStreamPos(lastXMLEntityStreamStack,lastStreamsPosition);
return 0;
}
(*XMLEntityStreamStack.begin())->streamPos.count--;
(*XMLEntityStreamStack.begin())->streamPos.columnNumber--;
return 1;
};
// ******************************************************************************
long XMLParser::howFarTo(
const char* pattern) {
if(DEBUGXMLPARSER) {
printf("XMLParser::howFarTo '%s'\n",pattern);
}
StreamPositionStruct lastStreamPos = (*XMLEntityStreamStack.begin())->streamPos;
// return if pattern null pointer
if(pattern==0) {
return 0;
}
// get pattern length
long patternLength=0;
while(!(pattern[patternLength]==0)) {
patternLength++;
}
// return if pattern empty string
if(patternLength==0) {
return 0;
}
// create test pattern and load from file
long i;
//char c;
signed char c;
char* testPattern = new char[patternLength+1];
for(i=0;i<patternLength;i++) {
if((c=(*XMLEntityStreamStack.begin())->nextChar())==EOF) {
delete testPattern;
throw XMLException(XMLException::UNEXPECTED_EOF_ERR);
}
testPattern[i]=c;
}
testPattern[patternLength]=0;
// now step testpattern to the right until match is found
long distance=0;
while(strcmp(testPattern,pattern)) {
if((c=(*XMLEntityStreamStack.begin())->nextChar())==EOF) {
delete testPattern;
throw XMLException(XMLException::UNEXPECTED_EOF_ERR);
}
for(i=0;i<patternLength-1;i++) {
testPattern[i]=testPattern[i+1];
}
testPattern[patternLength-1]=c;
distance++;
}
delete testPattern;
(*XMLEntityStreamStack.begin())->streamPos = lastStreamPos;
return distance;
};
// ******************************************************************************
bool XMLParser::matchProductionFixedString(
XMLEntityStream *const thisStream,
const char* pattern) {
// this production is optional
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProductionFixedString '%s'\n",pattern);
}
long length=0;
while(!(pattern[length]==0)) {
length++;
}
if(length==0) {
return 1;
}
StreamPositionStruct lastStreamPos = thisStream->streamPos;
XMLString testString;
loadNChar(thisStream,testString,length);
if(testString==pattern) {
return 1;
}
thisStream->streamPos=lastStreamPos;
return 0;
};
// ******************************************************************************
void XMLParser::matchProductionQuotedString(
XMLEntityStream *const thisStream,
XMLString& quotedString) const {
// this production is required
if(DEBUGXMLPARSER) {
printf("XMLParser::matchProductionQuotedString\n");
}
StreamPositionStruct lastStreamPos1 = thisStream->streamPos;
//char c=thisStream->nextChar();
signed char c=thisStream->nextChar();
if(!((c==0x22)|(c==0x27))) {
thisStream->streamPos = lastStreamPos1;
throw XMLParserException(&XMLEntityStreamStack,"Single or double quote expected",
XMLParserException::BAD_XML_ERR);
}
//char quoteUsed = c;
signed char quoteUsed = c;
StreamPositionStruct lastStreamPos2 = thisStream->streamPos;
long length=0;
c=thisStream->nextChar();
while(!(c==quoteUsed)&(c!=EOF)) {
length++;
c=thisStream->nextChar();
}
if(c!=quoteUsed) {
throw XMLParserException(&XMLEntityStreamStack,"Unexpected end of stream",
XMLParserException::BAD_XML_ERR);
}
thisStream->streamPos = lastStreamPos2;
char* s = new char[length+1];
for(long i=0; i<length; i++) {
s[i] = thisStream->nextChar();
}
s[length]=0;
quotedString=s;
delete s;
c=thisStream->nextChar();
};
// ******************************************************************************
unsigned long XMLParser::sweepContent(
char* s) {
if(DEBUGXMLPARSER) {
printf("XMLParser::sweepContent\n");
}
// this routine sweeps through element content and returns the length of the
// content. It is then called a second time with the appropriate memory
// allocated to s, and loads the data into s
//char c;
signed char c;
XMLEntityStream* testNextXMLEntityStream;
unsigned long refLength;
XMLString refName;
StreamPositionStruct lastStreamPos;
unsigned long length = 0;
bool cont = 1;
while(cont) {
lastStreamPos = (*XMLEntityStreamStack.begin())->streamPos;
c=(*XMLEntityStreamStack.begin())->nextChar();
while(c==EOF) {
if(XMLEntityStreamStack.size()==1) {
throw XMLParserException(&XMLEntityStreamStack,"Unexpected end of file",
XMLParserException::BAD_XML_ERR);
}
XMLEntityStreamStack.pop_front();
lastStreamPos = (*XMLEntityStreamStack.begin())->streamPos;
c=(*XMLEntityStreamStack.begin())->nextChar();
}
while(c=='&') {
// need to expand character and general entity references
(*XMLEntityStreamStack.begin())->streamPos.count--;
(*XMLEntityStreamStack.begin())->streamPos.columnNumber--;
refLength=matchProduction66CharRef((*XMLEntityStreamStack.begin()),c);
if(refLength>0) {
// it was a character reference
if(s!=0) {
s[length]=c;
}
length++;
}
else {
// must be a general entity reference
refLength=matchProduction68EntityRef((*XMLEntityStreamStack.begin()),refName);
testNextXMLEntityStream = (*XMLEntityStreamStack.begin())->getXMLEntityStream(refName,
XMLEntityStream::GENERAL_ENTITY);
if(testNextXMLEntityStream==0) {
(*XMLEntityStreamStack.begin())->streamPos = lastStreamPos;
sprintf(errormessage,"General entity '%s' unknown",refName.c_str());
throw XMLParserException(&XMLEntityStreamStack,errormessage,
XMLParserException::BAD_XML_ERR);
}
XMLEntityStreamStack.push_front(testNextXMLEntityStream);
}
lastStreamPos = (*XMLEntityStreamStack.begin())->streamPos;
c=(*XMLEntityStreamStack.begin())->nextChar();
while(c==EOF) {
if(XMLEntityStreamStack.size()==1) {
throw XMLParserException(&XMLEntityStreamStack,"Unexpected end of file",
XMLParserException::BAD_XML_ERR);
}
XMLEntityStreamStack.pop_front();
lastStreamPos = (*XMLEntityStreamStack.begin())->streamPos;
c=(*XMLEntityStreamStack.begin())->nextChar();
}
}
cont = XMLChar::isCharData(c);
if(cont) {
if(s!=0) {
s[length]=c;
}
length++;
}
}
(*XMLEntityStreamStack.begin())->streamPos = lastStreamPos;
if(s!=0) {
s[length]=0;
}
return length;
};
// ******************************************************************************
unsigned long XMLParser::sweepAttValue(
char* s) {
if(DEBUGXMLPARSER) {
printf("XMLParser::sweepAttValue\n");
}
// this routine sweeps through the AttValue content and returns the length of
// the content. It is then called a second time with the appropriate memory
// allocated to s, and loads the data into s
// note it uses the current entity stream, assuming that it is already
// positioned just before the opening quote.
//char c;
signed char c;
XMLEntityStream* testNextXMLEntityStream;
unsigned long refLength;
XMLString refName;
StreamPositionStruct lastStreamPos;
unsigned long length = 0;
//char quoteUsed = (*XMLEntityStreamStack.begin())->nextChar();
signed char quoteUsed = (*XMLEntityStreamStack.begin())->nextChar();
const XMLEntityStream *const enteringStream = (*XMLEntityStreamStack.begin());
bool cont = 1;
while(cont) {
lastStreamPos = (*XMLEntityStreamStack.begin())->streamPos;
c=(*XMLEntityStreamStack.begin())->nextChar();
while(c==EOF) {
if(XMLEntityStreamStack.size()==1) {
throw XMLParserException(&XMLEntityStreamStack,"Unexpected end of file",
XMLParserException::BAD_XML_ERR);
}
XMLEntityStreamStack.pop_front();
lastStreamPos = (*XMLEntityStreamStack.begin())->streamPos;
c=(*XMLEntityStreamStack.begin())->nextChar();
}
while(c=='&') {
// need to expand character and general entity references
(*XMLEntityStreamStack.begin())->streamPos.count--;
(*XMLEntityStreamStack.begin())->streamPos.columnNumber--;
refLength=matchProduction66CharRef((*XMLEntityStreamStack.begin()),c);
if(refLength>0) {
// it was a character reference
if(s!=0) {
s[length]=c;
length++;
}
}
else {
// must be a general entity reference
refLength=matchProduction68EntityRef((*XMLEntityStreamStack.begin()),refName);
testNextXMLEntityStream = (*XMLEntityStreamStack.begin())->getXMLEntityStream(refName,XMLEntityStream::GENERAL_ENTITY);
if(testNextXMLEntityStream==0) {
(*XMLEntityStreamStack.begin())->streamPos = lastStreamPos;
sprintf(errormessage,"General entity '%s' unknown",refName.c_str());
throw XMLParserException(&XMLEntityStreamStack,errormessage,
XMLParserException::BAD_XML_ERR);
}
if(testNextXMLEntityStream->entityLocation()==XMLEntityStream::EXTERNAL_ENTITY) {
(*XMLEntityStreamStack.begin())->streamPos = lastStreamPos;
sprintf(errormessage,
"Reference to external entity '%s' not allowed in AttValue",
refName.c_str());
throw XMLParserException(&XMLEntityStreamStack,errormessage,
XMLParserException::BAD_XML_ERR);
}
XMLEntityStreamStack.push_front(testNextXMLEntityStream);
}
lastStreamPos = (*XMLEntityStreamStack.begin())->streamPos;
c=(*XMLEntityStreamStack.begin())->nextChar();
while(c==EOF) {
if(XMLEntityStreamStack.size()==1) {
throw XMLParserException(&XMLEntityStreamStack,"Unexpected end of file",
XMLParserException::BAD_XML_ERR);
}
XMLEntityStreamStack.pop_front();
lastStreamPos = (*XMLEntityStreamStack.begin())->streamPos;
c=(*XMLEntityStreamStack.begin())->nextChar();
}
}
cont = XMLChar::isCharData(c)
&!((c==quoteUsed)&((*XMLEntityStreamStack.begin())==enteringStream));
if(cont) {
if(s!=0) {
s[length]=c;
}
length++;
}
}
if(s!=0) {
s[length]=0;
}
return length;
};
// ******************************************************************************
void XMLParser::loadNChar(
XMLEntityStream *const thisStream,
XMLString& outString,
const unsigned long& length) const {
if(DEBUGXMLPARSER) {
printf("XMLParser::loadNChar\n");
}
char* s = new char[length+1];
for(unsigned long i=0;i<length;i++) {
s[i]=thisStream->nextChar();
}
s[length]=0;
outString=s;
delete s;
};
// ******************************************************************************
void XMLParser::storeStreamPos(
list<XMLEntityStream*>& lastXMLEntityStreamStack,
list<StreamPositionStruct>& andTheirPositions) {
if(DEBUGXMLPARSER) {
printf("XMLParser::storeStreamPos\n");
}
lastXMLEntityStreamStack.clear();
andTheirPositions.clear();
for(list<XMLEntityStream*>::const_iterator
ppXMLEntityStream = XMLEntityStreamStack.begin();
ppXMLEntityStream != XMLEntityStreamStack.end(); ppXMLEntityStream++) {
lastXMLEntityStreamStack.push_back(*ppXMLEntityStream);
andTheirPositions.push_back((*ppXMLEntityStream)->streamPos);
}
};
// ******************************************************************************
void XMLParser::restoreStreamPos(
const list<XMLEntityStream*>& lastXMLEntityStreamStack,
const list<StreamPositionStruct>& andTheirPositions) {
if(DEBUGXMLPARSER) {
printf("XMLParser::restoreStreamPos\n");
}
XMLEntityStreamStack.clear();
list<XMLEntityStream*>::const_iterator ppXMLEntityStream;
ppXMLEntityStream = lastXMLEntityStreamStack.begin();
list<StreamPositionStruct>::const_iterator pStreamPositionStruct;
pStreamPositionStruct = andTheirPositions.begin();
while(ppXMLEntityStream != lastXMLEntityStreamStack.end()) {
XMLEntityStreamStack.push_back(*ppXMLEntityStream);
(*ppXMLEntityStream)->streamPos = *pStreamPositionStruct;
ppXMLEntityStream++;
pStreamPositionStruct++;
}
};
// ******************************************************************************
void XMLParser::printEntityStreamStack() const {
if(DEBUGXMLPARSER) {
printf("XMLParser::printEntityStreamStack\n");
}
for(list<XMLEntityStream*>::const_iterator
ppXMLEntityStream = XMLEntityStreamStack.begin();
ppXMLEntityStream != XMLEntityStreamStack.end(); ppXMLEntityStream++) {
printf(" %s,%li,%li\n",(*ppXMLEntityStream)->name()->c_str(),(*ppXMLEntityStream)->streamPos.lineNumber,
(*ppXMLEntityStream)->streamPos.columnNumber);
}
};
syntax highlighted by Code2HTML, v. 0.9.1