blob: be0d4475430f7e6aa85a4cfcfc25bbe871e65588 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id: SAX2XMLReaderImpl.cpp 568078 2007-08-21 11:43:25Z amassari $
*/
#include <xercesc/util/IOException.hpp>
#include <xercesc/util/RefStackOf.hpp>
#include <xercesc/util/XMLUniDefs.hpp>
#include <xercesc/util/Janitor.hpp>
#include <xercesc/sax2/ContentHandler.hpp>
#include <xercesc/sax2/LexicalHandler.hpp>
#include <xercesc/sax2/DeclHandler.hpp>
#include <xercesc/sax2/XMLReaderFactory.hpp>
#include <xercesc/sax/DTDHandler.hpp>
#include <xercesc/sax/ErrorHandler.hpp>
#include <xercesc/sax/EntityResolver.hpp>
#include <xercesc/sax/SAXParseException.hpp>
#include <xercesc/sax/SAXException.hpp>
#include <xercesc/internal/XMLScannerResolver.hpp>
#include <xercesc/parsers/SAX2XMLReaderImpl.hpp>
#include <xercesc/validators/common/GrammarResolver.hpp>
#include <xercesc/framework/XMLGrammarPool.hpp>
#include <xercesc/framework/XMLSchemaDescription.hpp>
#include <xercesc/util/OutOfMemoryException.hpp>
#include <xercesc/util/XMLEntityResolver.hpp>
#include <string.h>
XERCES_CPP_NAMESPACE_BEGIN
SAX2XMLReader * XMLReaderFactory::createXMLReader( MemoryManager* const manager
, XMLGrammarPool* const gramPool)
{
SAX2XMLReaderImpl* pImpl=new (manager) SAX2XMLReaderImpl(manager, gramPool);
return pImpl;
}
const XMLCh gDTDEntityStr[] =
{
chOpenSquare, chLatin_d, chLatin_t, chLatin_d, chCloseSquare, chNull
};
typedef JanitorMemFunCall<SAX2XMLReaderImpl> CleanupType;
typedef JanitorMemFunCall<SAX2XMLReaderImpl> ResetInProgressType;
SAX2XMLReaderImpl::SAX2XMLReaderImpl(MemoryManager* const manager
, XMLGrammarPool* const gramPool):
fNamespacePrefix(false)
, fAutoValidation(false)
, fValidation(false)
, fParseInProgress(false)
, fHasExternalSubset(false)
, fElemDepth(0)
, fAdvDHCount(0)
, fAdvDHListSize(32)
, fDocHandler(0)
, fTempAttrVec(0)
, fPrefixesStorage(0)
, fPrefixes(0)
, fPrefixCounts(0)
, fDTDHandler(0)
, fEntityResolver(0)
, fXMLEntityResolver(0)
, fErrorHandler(0)
, fPSVIHandler(0)
, fLexicalHandler(0)
, fDeclHandler(0)
, fAdvDHList(0)
, fScanner(0)
, fGrammarResolver(0)
, fURIStringPool(0)
, fValidator(0)
, fMemoryManager(manager)
, fGrammarPool(gramPool)
{
CleanupType cleanup(this, &SAX2XMLReaderImpl::cleanUp);
try
{
initialize();
}
catch(const OutOfMemoryException&)
{
// Don't cleanup when out of memory, since executing the
// code can cause problems.
cleanup.release();
throw;
}
cleanup.release();
}
SAX2XMLReaderImpl::~SAX2XMLReaderImpl()
{
cleanUp();
}
// ---------------------------------------------------------------------------
// SAX2XMLReaderImpl: Initialize/Cleanup methods
// ---------------------------------------------------------------------------
void SAX2XMLReaderImpl::initialize()
{
// Create grammar resolver and string pool that we pass to the scanner
fGrammarResolver = new (fMemoryManager) GrammarResolver(fGrammarPool, fMemoryManager);
fURIStringPool = fGrammarResolver->getStringPool();
// Create a scanner and tell it what validator to use. Then set us
// as the document event handler so we can fill the DOM document.
fScanner = XMLScannerResolver::getDefaultScanner(0, fGrammarResolver, fMemoryManager);
fScanner->setURIStringPool(fURIStringPool);
// Create the initial advanced handler list array and zero it out
fAdvDHList = (XMLDocumentHandler**) fMemoryManager->allocate
(
fAdvDHListSize * sizeof(XMLDocumentHandler*)
);//new XMLDocumentHandler*[fAdvDHListSize];
memset(fAdvDHList, 0, sizeof(void*) * fAdvDHListSize);
// SAX2 default is for namespaces (feature http://xml.org/sax/features/namespaces) to be on
setDoNamespaces(true) ;
// default: schema is on
setDoSchema(true);
fPrefixesStorage = new (fMemoryManager) XMLStringPool(109, fMemoryManager) ;
fPrefixes = new (fMemoryManager) ValueStackOf<unsigned int> (30, fMemoryManager) ;
fTempAttrVec = new (fMemoryManager) RefVectorOf<XMLAttr> (10, false, fMemoryManager) ;
fPrefixCounts = new (fMemoryManager) ValueStackOf<unsigned int>(10, fMemoryManager) ;
}
void SAX2XMLReaderImpl::cleanUp()
{
fMemoryManager->deallocate(fAdvDHList);//delete [] fAdvDHList;
delete fScanner;
delete fPrefixesStorage;
delete fPrefixes;
delete fTempAttrVec;
delete fPrefixCounts;
delete fGrammarResolver;
// grammar pool must do this
//delete fURIStringPool;
}
// ---------------------------------------------------------------------------
// SAX2XMLReaderImpl: Advanced document handler list maintenance methods
// ---------------------------------------------------------------------------
void SAX2XMLReaderImpl::installAdvDocHandler(XMLDocumentHandler* const toInstall)
{
// See if we need to expand and do so now if needed
if (fAdvDHCount == fAdvDHListSize)
{
// Calc a new size and allocate the new temp buffer
const unsigned int newSize = (unsigned int)(fAdvDHListSize * 1.5);
XMLDocumentHandler** newList = (XMLDocumentHandler**) fMemoryManager->allocate
(
newSize * sizeof(XMLDocumentHandler*)
);//new XMLDocumentHandler*[newSize];
// Copy over the old data to the new list and zero out the rest
memcpy(newList, fAdvDHList, sizeof(void*) * fAdvDHListSize);
memset
(
&newList[fAdvDHListSize]
, 0
, sizeof(void*) * (newSize - fAdvDHListSize)
);
// And now clean up the old array and store the new stuff
fMemoryManager->deallocate(fAdvDHList);//delete [] fAdvDHList;
fAdvDHList = newList;
fAdvDHListSize = newSize;
}
// Add this new guy into the empty slot
fAdvDHList[fAdvDHCount++] = toInstall;
//
// Install ourself as the document handler with the scanner. We might
// already be, but its not worth checking, just do it.
//
fScanner->setDocHandler(this);
}
bool SAX2XMLReaderImpl::removeAdvDocHandler(XMLDocumentHandler* const toRemove)
{
// If our count is zero, can't be any installed
if (!fAdvDHCount)
return false;
//
// Search the array until we find this handler. If we find a null entry
// first, we can stop there before the list is kept contiguous.
//
unsigned int index;
for (index = 0; index < fAdvDHCount; index++)
{
//
// We found it. We have to keep the list contiguous, so we have to
// copy down any used elements after this one.
//
if (fAdvDHList[index] == toRemove)
{
//
// Optimize if only one entry (pretty common). Otherwise, we
// have to copy them down to compact them.
//
if (fAdvDHCount > 1)
{
index++;
while (index < fAdvDHCount)
fAdvDHList[index - 1] = fAdvDHList[index];
}
// Bump down the count and zero out the last one
fAdvDHCount--;
fAdvDHList[fAdvDHCount] = 0;
//
// If this leaves us with no advanced handlers and there is
// no SAX doc handler installed on us, then remove us from the
// scanner as the document handler.
//
if (!fAdvDHCount && !fDocHandler)
fScanner->setDocHandler(0);
return true;
}
}
// Never found it
return false;
}
// ---------------------------------------------------------------------------
// SAX2XMLReaderImpl Validator functions
// ---------------------------------------------------------------------------
void SAX2XMLReaderImpl::setValidator(XMLValidator* valueToAdopt)
{
fValidator = valueToAdopt;
fScanner->setValidator(valueToAdopt);
}
XMLValidator* SAX2XMLReaderImpl::getValidator() const
{
return fScanner->getValidator();
}
// ---------------------------------------------------------------------------
// SAX2XMLReader Interface
// ---------------------------------------------------------------------------
int SAX2XMLReaderImpl::getErrorCount() const
{
return fScanner->getErrorCount();
}
void SAX2XMLReaderImpl::setContentHandler(ContentHandler* const handler)
{
fDocHandler = handler;
if (fDocHandler)
{
//
// Make sure we are set as the document handler with the scanner.
// We may already be (if advanced handlers are installed), but its
// not worthing checking, just do it.
//
fScanner->setDocHandler(this);
}
else
{
//
// If we don't have any advanced handlers either, then deinstall us
// from the scanner because we don't need document events anymore.
//
if (!fAdvDHCount)
fScanner->setDocHandler(0);
}
}
void SAX2XMLReaderImpl::setDTDHandler(DTDHandler* const handler)
{
fDTDHandler = handler;
if (fDTDHandler)
fScanner->setDocTypeHandler(this);
else
fScanner->setDocTypeHandler(0);
}
void SAX2XMLReaderImpl::setErrorHandler(ErrorHandler* const handler)
{
//
// Store the handler. Then either install or deinstall us as the
// error reporter on the scanner.
//
fErrorHandler = handler;
if (fErrorHandler) {
fScanner->setErrorReporter(this);
fScanner->setErrorHandler(fErrorHandler);
}
else {
fScanner->setErrorReporter(0);
fScanner->setErrorHandler(0);
}
}
void SAX2XMLReaderImpl::setPSVIHandler(PSVIHandler* const handler)
{
fPSVIHandler = handler;
if (fPSVIHandler) {
fScanner->setPSVIHandler(fPSVIHandler);
}
else {
fScanner->setPSVIHandler(0);
}
}
void SAX2XMLReaderImpl::setLexicalHandler(LexicalHandler* const handler)
{
fLexicalHandler = handler;
if (fLexicalHandler)
fScanner->setDocTypeHandler(this);
else
fScanner->setDocTypeHandler(0);
}
void SAX2XMLReaderImpl::setDeclarationHandler(DeclHandler* const handler)
{
fDeclHandler = handler;
if (fDeclHandler)
fScanner->setDocTypeHandler(this);
else
fScanner->setDocTypeHandler(0);
}
void SAX2XMLReaderImpl::setEntityResolver(EntityResolver* const resolver)
{
fEntityResolver = resolver;
if (fEntityResolver) {
fScanner->setEntityHandler(this);
fXMLEntityResolver = 0;
}
else {
fScanner->setEntityHandler(0);
}
}
void SAX2XMLReaderImpl::setXMLEntityResolver(XMLEntityResolver* const resolver)
{
fXMLEntityResolver = resolver;
if (fXMLEntityResolver) {
fScanner->setEntityHandler(this);
fEntityResolver = 0;
}
else {
fScanner->setEntityHandler(0);
}
}
void SAX2XMLReaderImpl::setExitOnFirstFatalError(const bool newState)
{
fScanner->setExitOnFirstFatal(newState);
}
void SAX2XMLReaderImpl::setValidationConstraintFatal(const bool newState)
{
fScanner->setValidationConstraintFatal(newState);
}
void SAX2XMLReaderImpl::parse (const InputSource& source)
{
// Avoid multiple entrance
if (fParseInProgress)
ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager);
ResetInProgressType resetInProgress(this, &SAX2XMLReaderImpl::resetInProgress);
try
{
fParseInProgress = true;
fScanner->scanDocument(source);
}
catch(const OutOfMemoryException&)
{
resetInProgress.release();
throw;
}
}
void SAX2XMLReaderImpl::parse (const XMLCh* const systemId)
{
// Avoid multiple entrance
if (fParseInProgress)
ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager);
ResetInProgressType resetInProgress(this, &SAX2XMLReaderImpl::resetInProgress);
try
{
fParseInProgress = true;
fScanner->scanDocument(systemId);
}
catch(const OutOfMemoryException&)
{
resetInProgress.release();
throw;
}
}
void SAX2XMLReaderImpl::parse (const char* const systemId)
{
// Avoid multiple entrance
if (fParseInProgress)
ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager);
ResetInProgressType resetInProgress(this, &SAX2XMLReaderImpl::resetInProgress);
try
{
fParseInProgress = true;
fScanner->scanDocument(systemId);
fParseInProgress = false;
}
catch(const OutOfMemoryException&)
{
resetInProgress.release();
throw;
}
}
// ---------------------------------------------------------------------------
// SAX2XMLReaderImpl: Progressive parse methods
// ---------------------------------------------------------------------------
bool SAX2XMLReaderImpl::parseFirst( const XMLCh* const systemId
, XMLPScanToken& toFill)
{
//
// Avoid multiple entrance. We cannot enter here while a regular parse
// is in progress.
//
if (fParseInProgress)
ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager);
return fScanner->scanFirst(systemId, toFill);
}
bool SAX2XMLReaderImpl::parseFirst( const char* const systemId
, XMLPScanToken& toFill)
{
//
// Avoid multiple entrance. We cannot enter here while a regular parse
// is in progress.
//
if (fParseInProgress)
ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager);
return fScanner->scanFirst(systemId, toFill);
}
bool SAX2XMLReaderImpl::parseFirst( const InputSource& source
, XMLPScanToken& toFill)
{
//
// Avoid multiple entrance. We cannot enter here while a regular parse
// is in progress.
//
if (fParseInProgress)
ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager);
return fScanner->scanFirst(source, toFill);
}
bool SAX2XMLReaderImpl::parseNext(XMLPScanToken& token)
{
return fScanner->scanNext(token);
}
void SAX2XMLReaderImpl::parseReset(XMLPScanToken& token)
{
// Reset the scanner
fScanner->scanReset(token);
}
// ---------------------------------------------------------------------------
// SAX2XMLReaderImpl: Overrides of the XMLDocumentHandler interface
// ---------------------------------------------------------------------------
void SAX2XMLReaderImpl::docCharacters( const XMLCh* const chars
, const unsigned int length
, const bool cdataSection)
{
// Suppress the chars before the root element.
if (fElemDepth)
{
// Call the installed LexicalHandler.
if (cdataSection && fLexicalHandler)
fLexicalHandler->startCDATA();
// Just map to the SAX document handler
if (fDocHandler)
fDocHandler->characters(chars, length);
// Call the installed LexicalHandler.
if (cdataSection && fLexicalHandler)
fLexicalHandler->endCDATA();
}
//
// If there are any installed advanced handlers, then lets call them
// with this info.
//
for (unsigned int index = 0; index < fAdvDHCount; index++)
fAdvDHList[index]->docCharacters(chars, length, cdataSection);
}
void SAX2XMLReaderImpl::docComment(const XMLCh* const commentText)
{
// Call the installed LexicalHandler.
if (fLexicalHandler)
{
// SAX2 reports comment text like characters -- as an
// array with a length.
fLexicalHandler->comment(commentText, XMLString::stringLen(commentText));
}
//
// OK, if there are any installed advanced handlers,
// then let's call them with this info.
//
for (unsigned int index = 0; index < fAdvDHCount; index++)
fAdvDHList[index]->docComment(commentText);
}
void SAX2XMLReaderImpl::XMLDecl( const XMLCh* const versionStr
, const XMLCh* const encodingStr
, const XMLCh* const standaloneStr
, const XMLCh* const actualEncodingStr
)
{
// SAX has no way to report this event. But, if there are any installed
// advanced handlers, then lets call them with this info.
//
for (unsigned int index = 0; index < fAdvDHCount; index++)
fAdvDHList[index]->XMLDecl( versionStr,
encodingStr,
standaloneStr,
actualEncodingStr );
}
void SAX2XMLReaderImpl::docPI( const XMLCh* const target
, const XMLCh* const data)
{
// Just map to the SAX document handler
if (fDocHandler)
fDocHandler->processingInstruction(target, data);
//
// If there are any installed advanced handlers, then lets call them
// with this info.
//
for (unsigned int index = 0; index < fAdvDHCount; index++)
fAdvDHList[index]->docPI(target, data);
}
void SAX2XMLReaderImpl::endDocument()
{
if (fDocHandler)
fDocHandler->endDocument();
//
// If there are any installed advanced handlers, then lets call them
// with this info.
//
for (unsigned int index = 0; index < fAdvDHCount; index++)
fAdvDHList[index]->endDocument();
}
void SAX2XMLReaderImpl::endEntityReference(const XMLEntityDecl& entityDecl)
{
// Call the installed LexicalHandler.
if (fLexicalHandler)
fLexicalHandler->endEntity(entityDecl.getName());
//
// SAX has no way to report this event. But, if there are any installed
// advanced handlers, then lets call them with this info.
//
for (unsigned int index = 0; index < fAdvDHCount; index++)
fAdvDHList[index]->endEntityReference(entityDecl);
}
void SAX2XMLReaderImpl::ignorableWhitespace(const XMLCh* const chars
, const unsigned int length
, const bool cdataSection)
{
// Do not report the whitespace before the root element.
if (!fElemDepth)
return;
// Just map to the SAX document handler
if (fDocHandler)
fDocHandler->ignorableWhitespace(chars, length);
//
// If there are any installed advanced handlers, then lets call them
// with this info.
//
for (unsigned int index = 0; index < fAdvDHCount; index++)
fAdvDHList[index]->ignorableWhitespace(chars, length, cdataSection);
}
void SAX2XMLReaderImpl::resetDocument()
{
//
// If there are any installed advanced handlers, then lets call them
// with this info.
//
for (unsigned int index = 0; index < fAdvDHCount; index++)
fAdvDHList[index]->resetDocument();
// Make sure our element depth flag gets set back to zero
fElemDepth = 0;
// reset prefix counters and prefix map
fPrefixCounts->removeAllElements();
fPrefixes->removeAllElements();
fPrefixesStorage->flushAll();
}
void SAX2XMLReaderImpl::startDocument()
{
// Just map to the SAX document handler
if (fDocHandler)
{
fDocHandler->setDocumentLocator(fScanner->getLocator());
fDocHandler->startDocument();
}
//
// If there are any installed advanced handlers, then lets call them
// with this info.
//
for (unsigned int index = 0; index < fAdvDHCount; index++)
fAdvDHList[index]->startDocument();
}
void SAX2XMLReaderImpl::
startElement( const XMLElementDecl& elemDecl
, const unsigned int elemURLId
, const XMLCh* const elemPrefix
, const RefVectorOf<XMLAttr>& attrList
, const unsigned int attrCount
, const bool isEmpty
, const bool isRoot)
{
// Bump the element depth counter if not empty
if (!isEmpty)
fElemDepth++;
if (fDocHandler)
{
ArrayJanitor<XMLCh> janElemName(NULL);
XMLCh* elemQName = NULL;
if(elemPrefix==0 || *elemPrefix==0)
elemQName=(XMLCh*)elemDecl.getBaseName();
else if(XMLString::equals(elemPrefix, elemDecl.getElementName()->getPrefix()))
elemQName=(XMLCh*)elemDecl.getElementName()->getRawName();
else
{
unsigned int prefixLen=XMLString::stringLen(elemPrefix);
elemQName=(XMLCh*)fMemoryManager->allocate((prefixLen+1+XMLString::stringLen(elemDecl.getBaseName())+1)*sizeof(XMLCh));
XMLString::moveChars(elemQName, elemPrefix, prefixLen);
elemQName[prefixLen] = chColon;
XMLString::copyString(&elemQName[prefixLen+1], elemDecl.getBaseName());
janElemName.reset(elemQName, fMemoryManager);
}
if (getDoNamespaces())
{
unsigned int numPrefix = 0;
const XMLCh* nsString = XMLUni::fgXMLNSString;
const XMLAttr* tempAttr = 0;
if (!fNamespacePrefix)
{
fTempAttrVec->removeAllElements();
}
for (unsigned int i = 0; i < attrCount; i++)
{
const XMLCh* nsPrefix = 0;
const XMLCh* nsURI = 0;
tempAttr = attrList.elementAt(i);
if (XMLString::equals(tempAttr->getQName(), nsString))
nsURI = tempAttr->getValue();
if (XMLString::equals(tempAttr->getPrefix(), nsString))
{
nsPrefix = tempAttr->getName();
nsURI = tempAttr->getValue();
}
if (!fNamespacePrefix)
{
if (nsURI == 0)
fTempAttrVec->addElement((XMLAttr*)tempAttr);
}
if (nsURI != 0)
{
if (nsPrefix == 0)
nsPrefix = XMLUni::fgZeroLenString;
fDocHandler->startPrefixMapping(nsPrefix, nsURI);
unsigned int nPrefixId=fPrefixesStorage->addOrFind(nsPrefix);
fPrefixes->push(nPrefixId) ;
numPrefix++;
}
}
fPrefixCounts->push(numPrefix) ;
if (!fNamespacePrefix)
fAttrList.setVector(fTempAttrVec, fTempAttrVec->size(), fScanner);
else
fAttrList.setVector(&attrList, attrCount, fScanner);
// call startElement() with namespace declarations
fDocHandler->startElement
(
fScanner->getURIText(elemURLId)
, elemDecl.getBaseName()
, elemQName
, fAttrList
);
}
else // no namespace
{
fAttrList.setVector(&attrList, attrCount, fScanner);
fDocHandler->startElement(XMLUni::fgZeroLenString,
elemDecl.getBaseName(),
elemQName,
fAttrList);
}
// If its empty, send the end tag event now
if (isEmpty)
{
// call endPrefixMapping appropriately.
if (getDoNamespaces())
{
fDocHandler->endElement
(
fScanner->getURIText(elemURLId)
, elemDecl.getBaseName()
, elemQName
);
unsigned int numPrefix = fPrefixCounts->pop();
for (unsigned int i = 0; i < numPrefix; ++i)
{
unsigned int nPrefixId = fPrefixes->pop() ;
fDocHandler->endPrefixMapping( fPrefixesStorage->getValueForId(nPrefixId) );
}
}
else
{
fDocHandler->endElement(XMLUni::fgZeroLenString,
elemDecl.getBaseName(),
elemQName);
}
}
}
//
// If there are any installed advanced handlers, then lets call them
// with this info.
//
for (unsigned int index = 0; index < fAdvDHCount; index++)
{
fAdvDHList[index]->startElement
(
elemDecl
, elemURLId
, elemPrefix
, attrList
, attrCount
, isEmpty
, isRoot
);
}
}
void SAX2XMLReaderImpl::endElement( const XMLElementDecl& elemDecl
, const unsigned int uriId
, const bool isRoot
, const XMLCh* const elemPrefix)
{
// Just map to the SAX document handler
if (fDocHandler)
{
ArrayJanitor<XMLCh> janElemName(NULL);
XMLCh* elemQName = NULL;
if(elemPrefix==0 || *elemPrefix==0)
elemQName=(XMLCh*)elemDecl.getBaseName();
else if(XMLString::equals(elemPrefix, elemDecl.getElementName()->getPrefix()))
elemQName=(XMLCh*)elemDecl.getElementName()->getRawName();
else
{
unsigned int prefixLen=XMLString::stringLen(elemPrefix);
elemQName=(XMLCh*)fMemoryManager->allocate((prefixLen+1+XMLString::stringLen(elemDecl.getBaseName())+1)*sizeof(XMLCh));
XMLString::moveChars(elemQName, elemPrefix, prefixLen);
elemQName[prefixLen] = chColon;
XMLString::copyString(&elemQName[prefixLen+1], elemDecl.getBaseName());
janElemName.reset(elemQName, fMemoryManager);
}
if (getDoNamespaces())
{
fDocHandler->endElement
(
fScanner->getURIText(uriId)
, elemDecl.getBaseName()
, elemQName
);
// get the prefixes back so that we can call endPrefixMapping()
unsigned int numPrefix = fPrefixCounts->pop();
for (unsigned int i = 0; i < numPrefix; i++)
{
unsigned int nPrefixId = fPrefixes->pop() ;
fDocHandler->endPrefixMapping( fPrefixesStorage->getValueForId(nPrefixId) );
}
}
else
{
fDocHandler->endElement
(
XMLUni::fgZeroLenString,
elemDecl.getBaseName(),
elemQName
);
}
}
//
// If there are any installed advanced handlers, then lets call them
// with this info.
//
for (unsigned int index = 0; index < fAdvDHCount; index++)
fAdvDHList[index]->endElement(elemDecl, uriId, isRoot, elemPrefix);
//
// Dump the element depth down again. Don't let it underflow in case
// of malformed XML.
//
if (fElemDepth)
fElemDepth--;
}
void SAX2XMLReaderImpl::startEntityReference(const XMLEntityDecl& entityDecl)
{
// Call the installed LexicalHandler.
if (fLexicalHandler)
fLexicalHandler->startEntity(entityDecl.getName());
//
// SAX has no way to report this. But, If there are any installed
// advanced handlers, then lets call them with this info.
//
for (unsigned int index = 0; index < fAdvDHCount; index++)
fAdvDHList[index]->startEntityReference(entityDecl);
}
// ---------------------------------------------------------------------------
// SAX2XMLReaderImpl: Overrides of the DocTypeHandler interface
// ---------------------------------------------------------------------------
void SAX2XMLReaderImpl::attDef( const DTDElementDecl& elemDecl
, const DTDAttDef& attDef
, const bool ignoring)
{
if (fDeclHandler && !ignoring) {
XMLAttDef::AttTypes attType = attDef.getType();
XMLAttDef::DefAttTypes defAttType = attDef.getDefaultType();
const XMLCh* defAttTypeStr = XMLUni::fgNullString;
bool isEnumeration = (attType == XMLAttDef::Notation || attType == XMLAttDef::Enumeration);
XMLBuffer enumBuf(128, fMemoryManager);
if (defAttType == XMLAttDef::Fixed ||
defAttType == XMLAttDef::Implied ||
defAttType == XMLAttDef::Required) {
defAttTypeStr = attDef.getDefAttTypeString(defAttType, fMemoryManager);
}
if (isEnumeration) {
const XMLCh* enumString = attDef.getEnumeration();
unsigned int enumLen = XMLString::stringLen(enumString);
if (attType == XMLAttDef::Notation) {
enumBuf.set(XMLUni::fgNotationString);
enumBuf.append(chSpace);
}
enumBuf.append(chOpenParen);
for (unsigned int i=0; i<enumLen; i++) {
if (enumString[i] == chSpace)
enumBuf.append(chPipe);
else
enumBuf.append(enumString[i]);
}
enumBuf.append(chCloseParen);
}
fDeclHandler->attributeDecl(elemDecl.getFullName(),
attDef.getFullName(),
(isEnumeration) ? enumBuf.getRawBuffer()
: attDef.getAttTypeString(attDef.getType(), fMemoryManager),
defAttTypeStr,
attDef.getValue());
}
}
void SAX2XMLReaderImpl::doctypeComment(const XMLCh* const commentText)
{
if (fLexicalHandler)
{
// SAX2 reports comment text like characters -- as an
// array with a length.
fLexicalHandler->comment(commentText, XMLString::stringLen(commentText));
}
}
void SAX2XMLReaderImpl::doctypeDecl(const DTDElementDecl& elemDecl
, const XMLCh* const publicId
, const XMLCh* const systemId
, const bool hasIntSubset
, const bool hasExtSubset)
{
// Call the installed LexicalHandler.
if (fLexicalHandler && (hasIntSubset || hasExtSubset))
fLexicalHandler->startDTD(elemDecl.getFullName(), publicId, systemId);
fHasExternalSubset = hasExtSubset;
// Unused by SAX DTDHandler interface at this time
}
void SAX2XMLReaderImpl::doctypePI( const XMLCh* const
, const XMLCh* const)
{
// Unused by SAX DTDHandler interface at this time
}
void SAX2XMLReaderImpl::doctypeWhitespace( const XMLCh* const
, const unsigned int)
{
// Unused by SAX DTDHandler interface at this time
}
void SAX2XMLReaderImpl::elementDecl(const DTDElementDecl& elemDecl,
const bool isIgnored)
{
if (fDeclHandler && !isIgnored)
fDeclHandler->elementDecl(elemDecl.getFullName(),
elemDecl.getFormattedContentModel());
}
void SAX2XMLReaderImpl::endAttList(const DTDElementDecl&)
{
// Unused by SAX DTDHandler interface at this time
}
void SAX2XMLReaderImpl::endIntSubset()
{
// Call the installed LexicalHandler.
if (!fHasExternalSubset && fLexicalHandler)
fLexicalHandler->endDTD();
// Unused by SAX DTDHandler interface at this time
}
void SAX2XMLReaderImpl::endExtSubset()
{
// Call the installed LexicalHandler.
if (fLexicalHandler) {
fLexicalHandler->endEntity(gDTDEntityStr);
fLexicalHandler->endDTD();
}
// Unused by SAX DTDHandler interface at this time
}
void SAX2XMLReaderImpl::entityDecl( const DTDEntityDecl& entityDecl
, const bool isPEDecl
, const bool isIgnored)
{
//
// If we have a DTD handler, and this entity is not ignored, and
// its an unparsed entity, then send this one, else if we have a Decl
// handler then send this one.
//
if (!isIgnored) {
if (entityDecl.isUnparsed()) {
if (fDTDHandler) {
fDTDHandler->unparsedEntityDecl
(
entityDecl.getName()
, entityDecl.getPublicId()
, entityDecl.getSystemId()
, entityDecl.getNotationName()
);
}
}
else if (fDeclHandler) {
const XMLCh* entityName = entityDecl.getName();
ArrayJanitor<XMLCh> tmpNameJan(0);
if (isPEDecl) {
unsigned int nameLen = XMLString::stringLen(entityName);
XMLCh* tmpName = (XMLCh*) fMemoryManager->allocate
(
(nameLen + 2) * sizeof(XMLCh)
);//new XMLCh[nameLen + 2];
tmpNameJan.reset(tmpName, fMemoryManager);
tmpName[0] = chPercent;
XMLString::copyString(tmpName + 1, entityName);
entityName = tmpName;
}
if (entityDecl.isExternal()) {
fDeclHandler->externalEntityDecl
(
entityName
, entityDecl.getPublicId()
, entityDecl.getSystemId()
);
}
else {
fDeclHandler->internalEntityDecl
(
entityName
, entityDecl.getValue()
);
}
}
}
}
void SAX2XMLReaderImpl::resetDocType()
{
fHasExternalSubset = false;
// Just map to the DTD handler
if (fDTDHandler)
fDTDHandler->resetDocType();
}
void SAX2XMLReaderImpl::notationDecl( const XMLNotationDecl& notDecl
, const bool isIgnored)
{
if (fDTDHandler && !isIgnored)
{
fDTDHandler->notationDecl
(
notDecl.getName()
, notDecl.getPublicId()
, notDecl.getSystemId()
);
}
}
void SAX2XMLReaderImpl::startAttList(const DTDElementDecl&)
{
// Unused by SAX DTDHandler interface at this time
}
void SAX2XMLReaderImpl::startIntSubset()
{
// Unused by SAX DTDHandler interface at this time
}
void SAX2XMLReaderImpl::startExtSubset()
{
if (fLexicalHandler)
fLexicalHandler->startEntity(gDTDEntityStr);
}
void SAX2XMLReaderImpl::TextDecl( const XMLCh* const
, const XMLCh* const)
{
// Unused by SAX DTDHandler interface at this time
}
// ---------------------------------------------------------------------------
// SAX2XMLReaderImpl: Handlers for the XMLEntityHandler interface
// ---------------------------------------------------------------------------
void SAX2XMLReaderImpl::endInputSource(const InputSource&)
{
}
bool SAX2XMLReaderImpl::expandSystemId(const XMLCh* const, XMLBuffer&)
{
return false;
}
void SAX2XMLReaderImpl::resetEntities()
{
// Nothing to do for this one
}
InputSource* SAX2XMLReaderImpl::resolveEntity( const XMLCh* const publicId
, const XMLCh* const systemId
, const XMLCh* const)
{
// Just map to the SAX entity resolver handler
if (fEntityResolver)
return fEntityResolver->resolveEntity(publicId, systemId);
return 0;
}
InputSource* SAX2XMLReaderImpl::resolveEntity(XMLResourceIdentifier* resourceIdentifier)
{
//
// Just map it to the SAX entity resolver. If there is not one installed,
// return a null pointer to cause the default resolution.
//
if (fEntityResolver)
return fEntityResolver->resolveEntity(resourceIdentifier->getPublicId(),
resourceIdentifier->getSystemId());
if (fXMLEntityResolver)
return fXMLEntityResolver->resolveEntity(resourceIdentifier);
return 0;
}
void SAX2XMLReaderImpl::startInputSource(const InputSource&)
{
// Nothing to do for this one
}
// ---------------------------------------------------------------------------
// SAX2XMLReaderImpl: Overrides of the XMLErrorReporter interface
// ---------------------------------------------------------------------------
void SAX2XMLReaderImpl::resetErrors()
{
if (fErrorHandler)
fErrorHandler->resetErrors();
}
void SAX2XMLReaderImpl::error( const unsigned int
, const XMLCh* const
, const XMLErrorReporter::ErrTypes errType
, const XMLCh* const errorText
, const XMLCh* const systemId
, const XMLCh* const publicId
, const XMLSSize_t lineNum
, const XMLSSize_t colNum)
{
SAXParseException toThrow = SAXParseException
(
errorText
, publicId
, systemId
, lineNum
, colNum
, fMemoryManager
);
if (!fErrorHandler)
{
if (errType == XMLErrorReporter::ErrType_Fatal)
throw toThrow;
else
return;
}
if (errType == XMLErrorReporter::ErrType_Warning)
fErrorHandler->warning(toThrow);
else if (errType == XMLErrorReporter::ErrType_Fatal)
fErrorHandler->fatalError(toThrow);
else
fErrorHandler->error(toThrow);
}
// ---------------------------------------------------------------------------
// SAX2XMLReaderImpl: Features and Properties
// ---------------------------------------------------------------------------
void SAX2XMLReaderImpl::setFeature(const XMLCh* const name, const bool value)
{
if (fParseInProgress)
throw SAXNotSupportedException("Feature modification is not supported during parse.", fMemoryManager);
if (XMLString::compareIStringASCII(name, XMLUni::fgSAX2CoreNameSpaces) == 0)
{
setDoNamespaces(value);
}
else if (XMLString::compareIStringASCII(name, XMLUni::fgSAX2CoreValidation) == 0)
{
fValidation = value;
if (fValidation)
if (fAutoValidation)
setValidationScheme(Val_Auto);
else
setValidationScheme(Val_Always);
else
setValidationScheme(Val_Never);
}
else if (XMLString::compareIStringASCII(name, XMLUni::fgSAX2CoreNameSpacePrefixes) == 0)
{
fNamespacePrefix = value;
}
else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesDynamic) == 0)
{
fAutoValidation = value;
// for auto validation, the sax2 core validation feature must also be enabled.
if (fValidation)
if (fAutoValidation)
setValidationScheme(Val_Auto);
else
setValidationScheme(Val_Always);
else
setValidationScheme(Val_Never);
}
else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSchema) == 0)
{
setDoSchema(value);
}
else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSchemaFullChecking) == 0)
{
fScanner->setValidationSchemaFullChecking(value);
}
else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesIdentityConstraintChecking) == 0)
{
fScanner->setIdentityConstraintChecking(value);
}
else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesLoadExternalDTD) == 0)
{
fScanner->setLoadExternalDTD(value);
}
else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesContinueAfterFatalError) == 0)
{
fScanner->setExitOnFirstFatal(!value);
}
else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesValidationErrorAsFatal) == 0)
{
fScanner->setValidationConstraintFatal(value);
}
else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesCacheGrammarFromParse) == 0)
{
fScanner->cacheGrammarFromParse(value);
if (value)
fScanner->useCachedGrammarInParse(value);
}
else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesUseCachedGrammarInParse) == 0)
{
if (value || !fScanner->isCachingGrammarFromParse())
fScanner->useCachedGrammarInParse(value);
}
else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesCalculateSrcOfs) == 0)
{
fScanner->setCalculateSrcOfs(value);
}
else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesStandardUriConformant) == 0)
{
fScanner->setStandardUriConformant(value);
}
else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesGenerateSyntheticAnnotations) == 0)
{
fScanner->setGenerateSyntheticAnnotations(value);
}
else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesValidateAnnotations) == 0)
{
fScanner->setValidateAnnotations(value);
}
else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesIgnoreCachedDTD) == 0)
{
fScanner->setIgnoredCachedDTD(value);
}
else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesIgnoreAnnotations) == 0)
{
fScanner->setIgnoreAnnotations(value);
}
else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesDisableDefaultEntityResolution) == 0)
{
fScanner->setDisableDefaultEntityResolution(value);
}
else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSkipDTDValidation) == 0)
{
fScanner->setSkipDTDValidation(value);
}
else
throw SAXNotRecognizedException("Unknown Feature", fMemoryManager);
}
bool SAX2XMLReaderImpl::getFeature(const XMLCh* const name) const
{
if (XMLString::compareIStringASCII(name, XMLUni::fgSAX2CoreNameSpaces) == 0)
return getDoNamespaces();
else if (XMLString::compareIStringASCII(name, XMLUni::fgSAX2CoreValidation) == 0)
return fValidation;
else if (XMLString::compareIStringASCII(name, XMLUni::fgSAX2CoreNameSpacePrefixes) == 0)
return fNamespacePrefix;
else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesDynamic) == 0)
return fAutoValidation;
else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSchema) == 0)
return getDoSchema();
else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSchemaFullChecking) == 0)
return fScanner->getValidationSchemaFullChecking();
else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesIdentityConstraintChecking) == 0)
return fScanner->getIdentityConstraintChecking();
else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesLoadExternalDTD) == 0)
return fScanner->getLoadExternalDTD();
else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesContinueAfterFatalError) == 0)
return !fScanner->getExitOnFirstFatal();
else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesValidationErrorAsFatal) == 0)
return fScanner->getValidationConstraintFatal();
else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesCacheGrammarFromParse) == 0)
return fScanner->isCachingGrammarFromParse();
else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesUseCachedGrammarInParse) == 0)
return fScanner->isUsingCachedGrammarInParse();
else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesCalculateSrcOfs) == 0)
return fScanner->getCalculateSrcOfs();
else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesStandardUriConformant) == 0)
return fScanner->getStandardUriConformant();
else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesGenerateSyntheticAnnotations) == 0)
return fScanner->getGenerateSyntheticAnnotations();
else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesValidateAnnotations) == 0)
return fScanner->getValidateAnnotations();
else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesIgnoreCachedDTD) == 0)
return fScanner->getIgnoreCachedDTD();
else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesIgnoreAnnotations) == 0)
return fScanner->getIgnoreAnnotations();
else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesDisableDefaultEntityResolution) == 0)
return fScanner->getDisableDefaultEntityResolution();
else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSkipDTDValidation) == 0)
return fScanner->getSkipDTDValidation();
else
throw SAXNotRecognizedException("Unknown Feature", fMemoryManager);
return false;
}
void SAX2XMLReaderImpl::setProperty(const XMLCh* const name, void* value)
{
if (fParseInProgress)
throw SAXNotSupportedException("Property modification is not supported during parse.", fMemoryManager);
if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSchemaExternalSchemaLocation) == 0)
{
fScanner->setExternalSchemaLocation((XMLCh*)value);
}
else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSchemaExternalNoNameSpaceSchemaLocation) == 0)
{
fScanner->setExternalNoNamespaceSchemaLocation((XMLCh*)value);
}
else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSecurityManager) == 0)
{
fScanner->setSecurityManager((SecurityManager*)value);
}
else if (XMLString::equals(name, XMLUni::fgXercesScannerName))
{
XMLScanner* tempScanner = XMLScannerResolver::resolveScanner
(
(const XMLCh*) value
, fValidator
, fGrammarResolver
, fMemoryManager
);
if (tempScanner) {
tempScanner->setParseSettings(fScanner);
tempScanner->setURIStringPool(fURIStringPool);
delete fScanner;
fScanner = tempScanner;
}
}
else
throw SAXNotRecognizedException("Unknown Property", fMemoryManager);
}
void* SAX2XMLReaderImpl::getProperty(const XMLCh* const name) const
{
if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSchemaExternalSchemaLocation) == 0)
return (void*)fScanner->getExternalSchemaLocation();
else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSchemaExternalNoNameSpaceSchemaLocation) == 0)
return (void*)fScanner->getExternalNoNamespaceSchemaLocation();
else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSecurityManager) == 0)
return (void*)fScanner->getSecurityManager();
else if (XMLString::equals(name, XMLUni::fgXercesScannerName))
return (void*)fScanner->getName();
else
throw SAXNotRecognizedException("Unknown Property", fMemoryManager);
return 0;
}
// ---------------------------------------------------------------------------
// SAX2XMLReaderImpl: Private getters and setters for conveniences
// ---------------------------------------------------------------------------
void SAX2XMLReaderImpl::setValidationScheme(const ValSchemes newScheme)
{
if (newScheme == Val_Never)
fScanner->setValidationScheme(XMLScanner::Val_Never);
else if (newScheme == Val_Always)
fScanner->setValidationScheme(XMLScanner::Val_Always);
else
fScanner->setValidationScheme(XMLScanner::Val_Auto);
}
void SAX2XMLReaderImpl::setDoNamespaces(const bool newState)
{
fScanner->setDoNamespaces(newState);
}
bool SAX2XMLReaderImpl::getDoNamespaces() const
{
return fScanner->getDoNamespaces();
}
void SAX2XMLReaderImpl::setDoSchema(const bool newState)
{
fScanner->setDoSchema(newState);
}
bool SAX2XMLReaderImpl::getDoSchema() const
{
return fScanner->getDoSchema();
}
// ---------------------------------------------------------------------------
// SAX2XMLReaderImpl: Grammar preparsing
// ---------------------------------------------------------------------------
Grammar* SAX2XMLReaderImpl::loadGrammar(const char* const systemId,
const short grammarType,
const bool toCache)
{
// Avoid multiple entrance
if (fParseInProgress)
ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager);
ResetInProgressType resetInProgress(this, &SAX2XMLReaderImpl::resetInProgress);
Grammar* grammar = 0;
try
{
fParseInProgress = true;
grammar = fScanner->loadGrammar(systemId, grammarType, toCache);
}
catch(const OutOfMemoryException&)
{
resetInProgress.release();
throw;
}
return grammar;
}
Grammar* SAX2XMLReaderImpl::loadGrammar(const XMLCh* const systemId,
const short grammarType,
const bool toCache)
{
// Avoid multiple entrance
if (fParseInProgress)
ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager);
ResetInProgressType resetInProgress(this, &SAX2XMLReaderImpl::resetInProgress);
Grammar* grammar = 0;
try
{
fParseInProgress = true;
grammar = fScanner->loadGrammar(systemId, grammarType, toCache);
}
catch(const OutOfMemoryException&)
{
resetInProgress.release();
throw;
}
return grammar;
}
Grammar* SAX2XMLReaderImpl::loadGrammar(const InputSource& source,
const short grammarType,
const bool toCache)
{
// Avoid multiple entrance
if (fParseInProgress)
ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager);
ResetInProgressType resetInProgress(this, &SAX2XMLReaderImpl::resetInProgress);
Grammar* grammar = 0;
try
{
fParseInProgress = true;
grammar = fScanner->loadGrammar(source, grammarType, toCache);
}
catch(const OutOfMemoryException&)
{
resetInProgress.release();
throw;
}
return grammar;
}
void SAX2XMLReaderImpl::resetInProgress()
{
fParseInProgress = false;
}
void SAX2XMLReaderImpl::resetCachedGrammarPool()
{
fGrammarResolver->resetCachedGrammar();
}
void SAX2XMLReaderImpl::setInputBufferSize(const size_t bufferSize)
{
fScanner->setInputBufferSize(bufferSize);
}
Grammar* SAX2XMLReaderImpl::getGrammar(const XMLCh* const nameSpaceKey)
{
return fGrammarResolver->getGrammar(nameSpaceKey);
}
XERCES_CPP_NAMESPACE_END