You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xerces.apache.org by kn...@apache.org on 2002/12/04 02:41:15 UTC

cvs commit: xml-xerces/c/src/xercesc/internal XMLScanner.hpp XMLScanner.cpp

knoaman     2002/12/03 17:41:15

  Modified:    c/src/xercesc/internal XMLScanner.hpp XMLScanner.cpp
  Log:
  Scanner re-organization.
  
  Revision  Changes    Path
  1.13      +116 -283  xml-xerces/c/src/xercesc/internal/XMLScanner.hpp
  
  Index: XMLScanner.hpp
  ===================================================================
  RCS file: /home/cvs/xml-xerces/c/src/xercesc/internal/XMLScanner.hpp,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- XMLScanner.hpp	4 Nov 2002 14:58:19 -0000	1.12
  +++ XMLScanner.hpp	4 Dec 2002 01:41:14 -0000	1.13
  @@ -1,7 +1,7 @@
   /*
    * The Apache Software License, Version 1.1
    *
  - * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
  + * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
    * reserved.
    *
    * Redistribution and use in source and binary forms, with or without
  @@ -56,6 +56,9 @@
   
   /*
    * $Log$
  + * Revision 1.13  2002/12/04 01:41:14  knoaman
  + * Scanner re-organization.
  + *
    * Revision 1.12  2002/11/04 14:58:19  tng
    * C++ Namespace Support.
    *
  @@ -236,41 +239,33 @@
   #if !defined(XMLSCANNER_HPP)
   #define XMLSCANNER_HPP
   
  -#include <xercesc/util/KVStringPair.hpp>
  -#include <xercesc/util/RefVectorOf.hpp>
  -#include <xercesc/util/XMLString.hpp>
  -#include <xercesc/framework/XMLAttr.hpp>
   #include <xercesc/framework/XMLBufferMgr.hpp>
   #include <xercesc/framework/XMLErrorCodes.hpp>
   #include <xercesc/framework/XMLRefInfo.hpp>
  -#include <xercesc/framework/XMLPScanToken.hpp>
  -#include <xercesc/internal/ElemStack.hpp>
  +#include <xercesc/util/NameIdPool.hpp>
  +#include <xercesc/util/RefHashTableOf.hpp>
   #include <xercesc/internal/ReaderMgr.hpp>
   #include <xercesc/validators/DTD/DTDEntityDecl.hpp>
  -#include <xercesc/validators/DTD/DTDValidator.hpp>
  -#include <xercesc/validators/schema/SchemaValidator.hpp>
  +#include <xercesc/framework/XMLAttr.hpp>
  +
   
   XERCES_CPP_NAMESPACE_BEGIN
   
   class InputSource;
   class XMLDocumentHandler;
  -class DocTypeHandler;
  -class XMLElementDecl;
   class XMLEntityHandler;
  -class XMLErrorReporter;
   class ErrorHandler;
  -class XMLMsgLoader;
  +class DocTypeHandler;
  +class XMLPScanToken;
  +class XMLStringPool;
  +class Grammar;
  +class GrammarResolver;
   class XMLValidator;
  -class ValueStoreCache;
  -class XPathMatcherStack;
  -class FieldActivator;
  -class IdentityConstraint;
   
  -//
  +
   //  This is the mondo scanner class, which does the vast majority of the
   //  work of parsing. It handles reading in input and spitting out events
   //  to installed handlers.
  -//
   class XMLPARSER_EXPORT XMLScanner
   {
   public :
  @@ -345,7 +340,7 @@
           , XMLErrorReporter* const  errReporter
           , XMLValidator* const      valToAdopt
       );
  -    ~XMLScanner();
  +    virtual ~XMLScanner();
   
   
       // -----------------------------------------------------------------------
  @@ -369,6 +364,31 @@
           , const char* const         text4 = 0
       );
   
  +    // -----------------------------------------------------------------------
  +    //  Public pure virtual methods
  +    // -----------------------------------------------------------------------
  +    virtual const XMLCh* getName() const = 0;
  +    virtual NameIdPool<DTDEntityDecl>* getEntityDeclPool() = 0;
  +    virtual const NameIdPool<DTDEntityDecl>* getEntityDeclPool() const = 0;
  +    virtual unsigned int resolveQName
  +    (
  +        const   XMLCh* const        qName
  +        ,       XMLBuffer&          prefixBufToFill
  +        , const short               mode
  +        ,       int&                prefixColonPos
  +    ) = 0;
  +    virtual void scanDocument
  +    (
  +        const   InputSource&    src
  +    ) = 0;
  +    virtual bool scanNext(XMLPScanToken& toFill) = 0;
  +    virtual Grammar* loadGrammar
  +    (
  +        const   InputSource&    src
  +        , const short           grammarType
  +        , const bool            toCache = false
  +    ) = 0;
  +
   
       // -----------------------------------------------------------------------
       //  Getter methods
  @@ -390,7 +410,7 @@
       RefHashTableOf<XMLRefInfo>* getIDRefList();
       const RefHashTableOf<XMLRefInfo>* getIDRefList() const;
       bool getInException() const;
  -    bool getLastExtLocation
  +    /*bool getLastExtLocation
       (
                   XMLCh* const    sysIdToFill
           , const unsigned int    maxSysIdChars
  @@ -398,7 +418,7 @@
           , const unsigned int    maxPubIdChars
           ,       XMLSSize_t&     lineToFill
           ,       XMLSSize_t&     colToFill
  -    ) const;
  +    ) const;*/
       const Locator* getLocator() const;
       const ReaderMgr* getReaderMgr() const;
       unsigned int getSrcOffset() const;
  @@ -406,8 +426,6 @@
       const XMLValidator* getValidator() const;
       XMLValidator* getValidator();
       int getErrorCount();
  -    NameIdPool<DTDEntityDecl>* getEntityDeclPool();
  -    const NameIdPool<DTDEntityDecl>* getEntityDeclPool() const;
       const XMLStringPool* getURIStringPool() const;
       XMLStringPool* getURIStringPool();
       bool getHasNoDTD() const;
  @@ -417,12 +435,12 @@
       bool getNormalizeData() const;
       bool isCachingGrammarFromParse() const;
       bool isUsingCachedGrammarInParse() const;
  +    bool getCalculateSrcOfs() const;
       Grammar* getRootGrammar() const;
   
       // -----------------------------------------------------------------------
       //  Getter methods
       // -----------------------------------------------------------------------
  -
       /**
         * When an attribute name has no prefix, unlike elements, it is not mapped
         * to the global namespace. So, in order to have something to map it to
  @@ -474,23 +492,6 @@
   
       const XMLCh* getURIText(const   unsigned int    uriId) const;
   
  -    /**
  -      * This method separate the passed QName into prefix
  -      * and local part, and then return the URI id by resolving
  -      * the prefix.
  -      *
  -      * mode: Indicate if this QName comes from an Element or Attribute
  -      */
  -    unsigned int resolveQName
  -    (
  -        const   XMLCh* const        qName
  -        ,       XMLBuffer&          nameBufToFill
  -        ,       XMLBuffer&          prefixBufToFill
  -        , const ElemStack::MapModes mode
  -    );
  -
  -    Grammar* getGrammar(const XMLCh* const nameSpaceKey);
  -
       /* tell if the validator comes from user */
       bool isValidatorFromUser();
   
  @@ -504,6 +505,8 @@
       void setEntityHandler(XMLEntityHandler* const docTypeHandler);
       void setErrorReporter(XMLErrorReporter* const errHandler);
       void setErrorHandler(ErrorHandler* const handler);
  +    void setGrammarResolver(GrammarResolver* const grammarResolver);
  +    void setURIStringPool(XMLStringPool* const stringPool);
       void setExitOnFirstFatal(const bool newValue);
       void setValidationConstraintFatal(const bool newValue);
       void setValidationScheme(const ValSchemes newScheme);
  @@ -520,6 +523,7 @@
       void setExternalNoNamespaceSchemaLocation(const char* const noNamespaceSchemaLocation);
       void setLoadExternalDTD(const bool loadDTD);
       void setNormalizeData(const bool normalizeData);
  +    void setCalculateSrcOfs(const bool newValue);
   
       // -----------------------------------------------------------------------
       //  Mutator methods
  @@ -533,7 +537,6 @@
       bool getDoValidation() const;
       void setDoValidation(const bool validate);
   
  -
       // -----------------------------------------------------------------------
       //  Document scanning methods
       //
  @@ -542,10 +545,6 @@
       // -----------------------------------------------------------------------
       void scanDocument
       (
  -        const   InputSource&    src
  -    );
  -    void scanDocument
  -    (
           const   XMLCh* const    systemId
       );
       void scanDocument
  @@ -569,21 +568,13 @@
           ,       XMLPScanToken&  toFill
       );
   
  -    bool scanNext(XMLPScanToken& toFill);
  -
       void scanReset(XMLPScanToken& toFill);
   
       bool checkXMLDecl(bool startWithAngle);
   
       // -----------------------------------------------------------------------
       //  Grammar preparsing methods
  -    // -----------------------------------------------------------------------
  -    Grammar* loadGrammar
  -    (
  -        const   InputSource&    src
  -        , const short           grammarType
  -        , const bool            toCache = false
  -    );
  +    // -----------------------------------------------------------------------    
       Grammar* loadGrammar
       (
           const   XMLCh* const    systemId
  @@ -598,159 +589,46 @@
       );
   
       // -----------------------------------------------------------------------
  -    //  Reset pool of cached grammars
  -    // -----------------------------------------------------------------------
  -    void resetCachedGrammarPool();
  -
  -    // -----------------------------------------------------------------------
       //  Notification that lazy data has been deleted
       // -----------------------------------------------------------------------
   	static void reinitScannerMutex();
  -
   	static void reinitMsgLoader();
   
  -private :
  -    // -----------------------------------------------------------------------
  -    //  Unimplemented constructors and operators
  -    // -----------------------------------------------------------------------
  -    XMLScanner();
  -    XMLScanner(const XMLScanner&);
  -    void operator=(const XMLScanner&);
  -
  -
  -    // -----------------------------------------------------------------------
  -    //  Private helper methods
  -    // -----------------------------------------------------------------------
  -    void commonInit();
  -    void initValidator(XMLValidator* theValidator);
  -    void resetURIStringPool();
  -    InputSource* resolveSystemId(const XMLCh* const sysId); // return owned by caller
  -
  -    // Spaces are not allowed in URI, so %20 is used instead.
  -    // Convert %20 to spaces before resolving the URI
  -    void normalizeURI(const XMLCh* const systemURI, XMLBuffer& normalizedURI);
  -
  +protected:
       // -----------------------------------------------------------------------
  -    //  Private helper methods
  -    //
  -    //  These are implemented in XMLScanner2.cpp, to keep the main file from
  -    //  becoming so bloated. We can't have any bloated files.
  +    //  Protected pure virtual methods
       // -----------------------------------------------------------------------
  -    unsigned int buildAttList
  -    (
  -        const   RefVectorOf<KVStringPair>&  providedAttrs
  -        , const unsigned int                attCount
  -        ,       XMLElementDecl*             elemDecl
  -        ,       RefVectorOf<XMLAttr>&       toFill
  -    );
  -    void checkIDRefs();
  -    bool isLegalToken(const XMLPScanToken& toCheck);
  -    bool normalizeAttValue
  -    (
  -        const   XMLAttDef* const    attDef
  -        , const XMLCh* const        value
  -        ,       XMLBuffer&          toFill
  -    );
  -    bool normalizeAttRawValue
  -    (
  -        const   XMLCh* const        attrName
  -        , const XMLCh* const        value
  -        ,       XMLBuffer&          toFill
  -    );
  -
  -    unsigned int resolvePrefix
  -    (
  -        const   XMLCh* const        prefix
  -        , const ElemStack::MapModes mode
  -    );
  -    unsigned int resolvePrefix
  -    (
  -        const   XMLCh* const        prefix
  -        ,       XMLBuffer&          uriBufToFill
  -        , const ElemStack::MapModes mode
  -    );
  -    void scanReset(const InputSource& src);
  -    void sendCharData(XMLBuffer& toSend);
  -    XMLTokens senseNextToken(unsigned int& orgReader);
  -    void updateNSMap
  +    virtual void scanCDSection() = 0;
  +    virtual void scanCharData(XMLBuffer& toToUse) = 0;
  +    virtual EntityExpRes scanEntityRef
       (
  -        const   XMLCh* const    attrName
  -        , const XMLCh* const    attrValue
  -    );
  -    void scanRawAttrListforNameSpaces(const RefVectorOf<KVStringPair>* theRawAttrList, int attCount);
  -    void parseSchemaLocation(const XMLCh* const schemaLocationStr);
  -    void resolveSchemaGrammar(const XMLCh* const loc, const XMLCh* const uri);
  -    bool switchGrammar(const XMLCh* const newGrammarNameSpace);
  -    bool laxElementValidation(QName* element, ContentLeafNameTypeVector* cv,
  -                              const XMLContentModel* const cm,
  -                              const unsigned int parentElemDepth);
  -    bool anyAttributeValidation(SchemaAttDef* attWildCard,
  -                                unsigned int uriId,
  -                                bool& skipThisOne,
  -                                bool& laxThisOne);
  +        const   bool    inAttVal
  +        ,       XMLCh&  firstCh
  +        ,       XMLCh&  secondCh
  +        ,       bool&   escaped
  +    ) = 0;
  +    virtual void scanDocTypeDecl() = 0;
  +    virtual void scanReset(const InputSource& src) = 0;
  +    virtual void sendCharData(XMLBuffer& toSend) = 0;
   
       // -----------------------------------------------------------------------
  -    //  Private scanning methods
  +    //  Protected scanning methods
       // -----------------------------------------------------------------------
  -    bool basicAttrValueScan
  -    (
  -        const   XMLCh* const    attrName
  -        ,       XMLBuffer&      toFill
  -    );
  -    bool getQuotedString(XMLBuffer& toFill);
  -    unsigned int rawAttrScan
  -    (
  -        const   XMLCh* const                elemName
  -        ,       RefVectorOf<KVStringPair>&  toFill
  -        ,       bool&                       isEmpty
  -    );
  -    bool scanAttValue
  -    (
  -        const   XMLAttDef* const    attDef
  -        ,       XMLBuffer&          toFill
  -    );
  -    void scanCDSection();
  -    void scanCharData(XMLBuffer& toToUse);
       bool scanCharRef(XMLCh& toFill, XMLCh& second);
       void scanComment();
  -    bool scanContent(const bool extEntity);
  -    void scanEndTag(bool& gotData);
  -    EntityExpRes scanEntityRef
  -    (
  -        const   bool    inAttVal
  -        ,       XMLCh&  firstCh
  -        ,       XMLCh&  secondCh
  -        ,       bool&   escaped
  -    );
       bool scanEq();
       void scanMiscellaneous();
       void scanPI();
       void scanProlog();
  -    bool scanStartTag(bool& gotData);
  -    bool scanStartTagNS(bool& gotData);
       void scanXMLDecl(const DeclTypes type);
  -    unsigned int scanUpToWSOr
  -    (
  -                XMLBuffer&  toFill
  -        , const XMLCh       chEndChar
  -    );
  -    void scanDocTypeDecl();
   
       // -----------------------------------------------------------------------
       //  Private helper methods
       // -----------------------------------------------------------------------
  -    void resizeElemState();
  -
  -    // -----------------------------------------------------------------------
  -    //  IdentityConstraints Activation methods
  -    // -----------------------------------------------------------------------
  -    void activateSelectorFor(IdentityConstraint* const ic, const int initialDepth);
  -
  -    // -----------------------------------------------------------------------
  -    //  Grammar preparsing methods
  -    // -----------------------------------------------------------------------
  -    Grammar* loadXMLSchemaGrammar(const InputSource& src, const bool toCache = false);
  -    Grammar* loadDTDGrammar(const InputSource& src, const bool toCache = false);
  +    void checkIDRefs();
  +    bool isLegalToken(const XMLPScanToken& toCheck);
  +    XMLTokens senseNextToken(unsigned int& orgReader);
  +    void initValidator(XMLValidator* theValidator);
   
       // -----------------------------------------------------------------------
       //  Data members
  @@ -780,10 +658,6 @@
       //      namespaces or not. If the installed validator indicates that it
       //      has to do namespaces, then this is ignored.
       //
  -    //  fElemStack
  -    //      This is the element stack that is used to track the elements that
  -    //      are currently being worked on.
  -    //
       //  fEntityHandler
       //      The client code's entity handler. If zero, then no entity handler
       //      callouts are done. We don't adopt it.
  @@ -814,11 +688,6 @@
       //      it, which would normally throw again if the 'fail on first error'
       //      flag is one.
       //
  -    //  fRawAttrList
  -    //      During the initial scan of the attributes we can only do a raw
  -    //      scan for key/value pairs. So this vector is used to store them
  -    //      until they can be processed (and put into fAttrList.)
  -    //
       //  fReaderMgr
       //      This is the reader manager, from which we get characters. It
       //      manages the reader stack for us, and provides a lot of convenience
  @@ -848,12 +717,6 @@
       //      Either point to user's installed validator, or fDTDValidator
       //      or fSchemaValidator.
       //
  -    //  fDTDValidator
  -    //      The DTD validator instance.
  -    //
  -    //  fSchemaValidator
  -    //      The Schema validator instance.
  -    //
       //  fValidatorFromUser
       //      This flag indicates whether the validator was installed from
       //      user.  If false, then the validator was created by the Scanner.
  @@ -873,9 +736,6 @@
       //      This flag indicates whether the client code wants full Schema
       //      constraint checking.
       //
  -    //  fSeeXsi
  -    //      This flag indicates a schema has been seen.
  -    //
       //  fAttName
       //  fAttValue
       //  fCDataBuf
  @@ -908,11 +768,6 @@
       //  fSchemaNamespaceId
       //      This is the id of the schema namespace URI.
       //
  -    //  fElemState
  -    //  fElemStateSize
  -    //      Stores an element next state from DFA content model - used for
  -    //      wildcard validation
  -    //
       //  fGrammarResolver
       //      Grammar Pool that stores all the grammars. Key is namespace for
       //      schema and system id for external DTD. When caching a grammar, if
  @@ -934,18 +789,6 @@
       //      string pool class.  This pool is going to be shared by all Grammar.
       //      Use only if namespace is turned on.
       //
  -    //  fMatcherStack
  -    //      Stack of active XPath matchers for identity constraints. All
  -    //      active XPath matchers are notified of startElement, characters
  -    //      and endElement callbacks in order to perform their matches.
  -    //
  -    //  fValueStoreCache
  -    //      Cache of value stores for identity constraint fields.
  -    //
  -    //  fFieldActivator
  -    //      Activates fields within a certain scope when a selector matches
  -    //      its xpath.
  -    //
       //  fRootElemName
       //      No matter we are using DTD or Schema Grammar, if a DOCTYPE exists,
       //      we need to verify the root element name.  So store the rootElement
  @@ -968,6 +811,7 @@
       //      normalization that is defined in the schema.
       //
       // -----------------------------------------------------------------------
  +    bool                        fCalculateSrcOfs;
       bool                        fDoNamespaces;
       bool                        fExitOnFirstFatal;
       bool                        fValidationConstraintFatal;
  @@ -978,58 +822,66 @@
       bool                        fValidatorFromUser;
       bool                        fDoSchema;
       bool                        fSchemaFullChecking;
  -    bool                        fSeeXsi;
       bool                        fToCacheGrammar;
       bool                        fUseCachedGrammar;
  +    bool                        fLoadExternalDTD;
  +    bool                        fNormalizeData;
       int                         fErrorCount;
       unsigned int                fEmptyNamespaceId;
       unsigned int                fUnknownNamespaceId;
       unsigned int                fXMLNamespaceId;
       unsigned int                fXMLNSNamespaceId;
       unsigned int                fSchemaNamespaceId;
  -    unsigned int                fElemStateSize;
       XMLUInt32                   fScannerId;
       XMLUInt32                   fSequenceId;
  -    unsigned int*               fElemState;
       RefVectorOf<XMLAttr>*       fAttrList;
       XMLBufferMgr                fBufMgr;
       XMLDocumentHandler*         fDocHandler;
       DocTypeHandler*             fDocTypeHandler;
  -    ElemStack                   fElemStack;
       XMLEntityHandler*           fEntityHandler;
       XMLErrorReporter*           fErrorReporter;
       ErrorHandler*               fErrorHandler;
       RefHashTableOf<XMLRefInfo>* fIDRefList;
  -    RefVectorOf<KVStringPair>*  fRawAttrList;
       ReaderMgr                   fReaderMgr;
       XMLValidator*               fValidator;
  -    DTDValidator*               fDTDValidator;
  -    SchemaValidator*            fSchemaValidator;
       ValSchemes                  fValScheme;
       XMLBuffer                   fAttNameBuf;
       XMLBuffer                   fAttValueBuf;
       XMLBuffer                   fCDataBuf;
  -    XMLBuffer                   fNameBuf;
       XMLBuffer                   fQNameBuf;
       XMLBuffer                   fPrefixBuf;
       XMLBuffer                   fURIBuf;
       GrammarResolver*            fGrammarResolver;
       Grammar*                    fGrammar;
       Grammar*                    fRootGrammar;
  -    DTDGrammar*                 fDTDGrammar;
  -    Grammar::GrammarType        fGrammarType;
       XMLStringPool*              fURIStringPool;
  -    XPathMatcherStack*          fMatcherStack;
  -    ValueStoreCache*            fValueStoreCache;
  -    FieldActivator*             fFieldActivator;
       XMLCh*                      fRootElemName;
       XMLCh*                      fExternalSchemaLocation;
       XMLCh*                      fExternalNoNamespaceSchemaLocation;
  -    bool                        fLoadExternalDTD;
  -    bool                        fNormalizeData;
  -};
   
  +private :
  +    // -----------------------------------------------------------------------
  +    //  Unimplemented constructors and operators
  +    // -----------------------------------------------------------------------
  +    XMLScanner();
  +    XMLScanner(const XMLScanner&);
  +    void operator=(const XMLScanner&);
   
  +    // -----------------------------------------------------------------------
  +    //  Private helper methods
  +    // -----------------------------------------------------------------------
  +    void commonInit();
  +
  +    // -----------------------------------------------------------------------
  +    //  Private scanning methods
  +    // -----------------------------------------------------------------------
  +    bool getQuotedString(XMLBuffer& toFill);
  +    unsigned int scanUpToWSOr
  +    (
  +                XMLBuffer&  toFill
  +        , const XMLCh       chEndChar
  +    );
  +};
   
   // ---------------------------------------------------------------------------
   //  XMLScanner: Getter methods
  @@ -1089,14 +941,14 @@
       return fValidationConstraintFatal;
   }
   
  -inline RefHashTableOf<XMLRefInfo>* XMLScanner::getIDRefList()
  +inline bool XMLScanner::getInException() const
   {
  -    return fIDRefList;
  +    return fInException;
   }
   
  -inline bool XMLScanner::getInException() const
  +inline RefHashTableOf<XMLRefInfo>* XMLScanner::getIDRefList()
   {
  -    return fInException;
  +    return fIDRefList;
   }
   
   inline const RefHashTableOf<XMLRefInfo>* XMLScanner::getIDRefList() const
  @@ -1179,16 +1031,6 @@
       return fXMLNSNamespaceId;
   }
   
  -inline NameIdPool<DTDEntityDecl>* XMLScanner::getEntityDeclPool()
  -{
  -    return fDTDGrammar->getEntityDeclPool();
  -}
  -
  -inline const NameIdPool<DTDEntityDecl>* XMLScanner::getEntityDeclPool() const
  -{
  -    return fDTDGrammar->getEntityDeclPool();
  -}
  -
   inline const XMLStringPool* XMLScanner::getURIStringPool() const
   {
       return fURIStringPool;
  @@ -1234,14 +1076,14 @@
       return fUseCachedGrammar;
   }
   
  -inline Grammar* XMLScanner::getRootGrammar() const
  +inline bool XMLScanner::getCalculateSrcOfs() const
   {
  -    return fRootGrammar;
  +    return fCalculateSrcOfs;
   }
   
  -inline Grammar* XMLScanner::getGrammar(const XMLCh* const nameSpaceKey)
  +inline Grammar* XMLScanner::getRootGrammar() const
   {
  -    return fGrammarResolver->getGrammar(nameSpaceKey);
  +    return fRootGrammar;
   }
   
   // ---------------------------------------------------------------------------
  @@ -1257,41 +1099,33 @@
       fDocTypeHandler = docTypeHandler;
   }
   
  -inline void XMLScanner::setDoNamespaces(const bool doNamespaces)
  +inline void XMLScanner::setErrorHandler(ErrorHandler* const handler)
   {
  -    fDoNamespaces = doNamespaces;
  -    if (fDoNamespaces) {
  -        if (!fURIStringPool) {
  -            fURIStringPool = new XMLStringPool();
  -            resetURIStringPool();
  -        }
  -    }
  +    fErrorHandler = handler;
   }
   
  -inline void XMLScanner::setErrorReporter(XMLErrorReporter* const errHandler)
  +inline void XMLScanner::setEntityHandler(XMLEntityHandler* const entityHandler)
   {
  -    fErrorReporter = errHandler;
  -    fDTDValidator->setErrorReporter(fErrorReporter);
  -    fSchemaValidator->setErrorReporter(fErrorReporter);
  +    fEntityHandler = entityHandler;
  +    fReaderMgr.setEntityHandler(entityHandler);
   }
   
  -inline void XMLScanner::setErrorHandler(ErrorHandler* const handler)
  +inline void XMLScanner::setErrorReporter(XMLErrorReporter* const errHandler)
   {
  -    fErrorHandler = handler;
  +    fErrorReporter = errHandler;
   }
   
  -inline void XMLScanner::setEntityHandler(XMLEntityHandler* const entityHandler)
  +inline void XMLScanner::setGrammarResolver(GrammarResolver* const grammarResolver)
   {
  -    fEntityHandler = entityHandler;
  -    fReaderMgr.setEntityHandler(entityHandler);
  +    fGrammarResolver = grammarResolver;
   }
   
   inline void XMLScanner::setExitOnFirstFatal(const bool newValue)
   {
       fExitOnFirstFatal = newValue;
  -    fSchemaValidator->setExitOnFirstFatal(newValue);
   }
   
  +
   inline void XMLScanner::setValidationConstraintFatal(const bool newValue)
   {
       fValidationConstraintFatal = newValue;
  @@ -1309,18 +1143,14 @@
           fValidate = false;
   }
   
  -inline void XMLScanner::setValidator(XMLValidator* const valToAdopt)
  +inline void XMLScanner::setDoSchema(const bool doSchema)
   {
  -    if (fValidatorFromUser)
  -        delete fValidator;
  -    fValidator = valToAdopt;
  -    fValidatorFromUser = true;
  -    initValidator(fValidator);
  +    fDoSchema = doSchema;
   }
   
  -inline void XMLScanner::setDoSchema(const bool doSchema)
  +inline void XMLScanner::setDoNamespaces(const bool doNamespaces)
   {
  -    fDoSchema = doSchema;
  +    fDoNamespaces = doNamespaces;
   }
   
   inline void XMLScanner::setValidationSchemaFullChecking(const bool schemaFullChecking)
  @@ -1383,6 +1213,10 @@
       fUseCachedGrammar = newValue;
   }
   
  +inline void XMLScanner::setCalculateSrcOfs(const bool newValue)
  +{
  +    fCalculateSrcOfs = newValue;
  +}
   
   // ---------------------------------------------------------------------------
   //  XMLScanner: Mutator methods
  @@ -1391,7 +1225,6 @@
   {
       ++fErrorCount;
   }
  -
   
   // ---------------------------------------------------------------------------
   //  XMLScanner: Deprecated methods
  
  
  
  1.27      +705 -3384 xml-xerces/c/src/xercesc/internal/XMLScanner.cpp
  
  Index: XMLScanner.cpp
  ===================================================================
  RCS file: /home/cvs/xml-xerces/c/src/xercesc/internal/XMLScanner.cpp,v
  retrieving revision 1.26
  retrieving revision 1.27
  diff -u -r1.26 -r1.27
  --- XMLScanner.cpp	26 Nov 2002 20:20:42 -0000	1.26
  +++ XMLScanner.cpp	4 Dec 2002 01:41:14 -0000	1.27
  @@ -1,7 +1,7 @@
   /*
    * The Apache Software License, Version 1.1
    *
  - * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
  + * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
    * reserved.
    *
    * Redistribution and use in source and binary forms, with or without
  @@ -55,44 +55,31 @@
    */
   
   /*
  -  * $Id$
  + * $Id$
    */
   
   
   // ---------------------------------------------------------------------------
   //  Includes
   // ---------------------------------------------------------------------------
  +#include <xercesc/internal/XMLScanner.hpp>
   #include <xercesc/util/Janitor.hpp>
   #include <xercesc/util/Mutexes.hpp>
   #include <xercesc/util/PlatformUtils.hpp>
  -#include <xercesc/util/RefVectorOf.hpp>
   #include <xercesc/util/RuntimeException.hpp>
   #include <xercesc/util/UnexpectedEOFException.hpp>
   #include <xercesc/util/XMLMsgLoader.hpp>
   #include <xercesc/util/XMLRegisterCleanup.hpp>
   #include <xercesc/util/XMLUniDefs.hpp>
  -#include <xercesc/util/XMLUni.hpp>
  -#include <xercesc/util/XMLURL.hpp>
  -#include <xercesc/sax/InputSource.hpp>
  -#include <xercesc/sax/SAXException.hpp>
   #include <xercesc/framework/LocalFileInputSource.hpp>
   #include <xercesc/framework/URLInputSource.hpp>
   #include <xercesc/framework/XMLDocumentHandler.hpp>
  -#include <xercesc/framework/XMLErrorReporter.hpp>
   #include <xercesc/framework/XMLEntityHandler.hpp>
   #include <xercesc/framework/XMLPScanToken.hpp>
   #include <xercesc/framework/XMLValidator.hpp>
  -#include <xercesc/framework/XMLValidityCodes.hpp>
  -#include <xercesc/internal/XMLScanner.hpp>
   #include <xercesc/internal/EndOfEntityException.hpp>
   #include <xercesc/validators/DTD/DocTypeHandler.hpp>
  -#include <xercesc/validators/DTD/DTDScanner.hpp>
  -#include <xercesc/validators/schema/SchemaSymbols.hpp>
  -#include <xercesc/validators/schema/identity/FieldActivator.hpp>
  -#include <xercesc/validators/schema/identity/XPathMatcherStack.hpp>
  -#include <xercesc/validators/schema/identity/ValueStoreCache.hpp>
  -#include <xercesc/validators/schema/identity/IC_Selector.hpp>
  -#include <xercesc/validators/schema/identity/ValueStore.hpp>
  +#include <xercesc/validators/common/GrammarResolver.hpp>
   
   XERCES_CPP_NAMESPACE_BEGIN
   
  @@ -108,35 +95,19 @@
   static XMLMsgLoader*   gMsgLoader = 0;
   static XMLRegisterCleanup cleanupMsgLoader;
   
  -// ---------------------------------------------------------------------------
  -//  Local const data
  -//
  -//  These are the text for the require char refs that must always be present.
  -//  We init these into the entity pool upon construction.
  -// ---------------------------------------------------------------------------
  -static const XMLCh gAmp[] = { chLatin_a, chLatin_m, chLatin_p, chNull };
  -static const XMLCh gLT[] = { chLatin_l, chLatin_t, chNull };
  -static const XMLCh gGT[] = { chLatin_g, chLatin_t, chNull };
  -static const XMLCh gQuot[] = { chLatin_q, chLatin_u, chLatin_o, chLatin_t, chNull };
  -static const XMLCh gApos[] = { chLatin_a, chLatin_p, chLatin_o, chLatin_s, chNull };
  -
   
   // ---------------------------------------------------------------------------
   //  Local, static functions
   // ---------------------------------------------------------------------------
   
  -// -----------------------------------------------------------------------
   //  Cleanup for the message loader
  -// -----------------------------------------------------------------------
   void XMLScanner::reinitMsgLoader()
   {
   	delete gMsgLoader;
   	gMsgLoader = 0;
   }
   
  -// -----------------------------------------------------------------------
   //  Cleanup for the scanner mutex
  -// -----------------------------------------------------------------------
   void XMLScanner::reinitScannerMutex()
   {
       delete sScannerMutex;
  @@ -179,7 +150,8 @@
   // ---------------------------------------------------------------------------
   XMLScanner::XMLScanner(XMLValidator* const valToAdopt) :
   
  -    fDoNamespaces(false)
  +    fCalculateSrcOfs(true)
  +    , fDoNamespaces(false)
       , fExitOnFirstFatal(true)
       , fValidationConstraintFatal(false)
       , fInException(false)
  @@ -189,19 +161,18 @@
       , fValidatorFromUser(false)
       , fDoSchema(false)
       , fSchemaFullChecking(false)
  -    , fSeeXsi(false)
       , fToCacheGrammar(false)
       , fUseCachedGrammar(false)
  +    , fLoadExternalDTD(true)
  +    , fNormalizeData(true)
       , fErrorCount(0)
       , fEmptyNamespaceId(0)
       , fUnknownNamespaceId(0)
       , fXMLNamespaceId(0)
       , fXMLNSNamespaceId(0)
       , fSchemaNamespaceId(0)
  -    , fElemStateSize(16)
       , fScannerId(0)
       , fSequenceId(0)
  -    , fElemState(0)
       , fAttrList(0)
       , fDocHandler(0)
       , fDocTypeHandler(0)
  @@ -209,24 +180,15 @@
       , fErrorReporter(0)
       , fErrorHandler(0)
       , fIDRefList(0)
  -    , fRawAttrList(0)
       , fValidator(valToAdopt)
  -    , fDTDValidator(0)
  -    , fSchemaValidator(0)
       , fValScheme(Val_Never)
       , fGrammarResolver(0)
       , fGrammar(0)
       , fRootGrammar(0)
  -    , fDTDGrammar(0)
       , fURIStringPool(0)
  -    , fMatcherStack(0)
  -    , fValueStoreCache(0)
  -    , fFieldActivator(0)
       , fRootElemName(0)
       , fExternalSchemaLocation(0)
       , fExternalNoNamespaceSchemaLocation(0)
  -    , fLoadExternalDTD(true)
  -    , fNormalizeData(true)
   {
      commonInit();
   
  @@ -234,19 +196,16 @@
          fValidatorFromUser = true;
          initValidator(fValidator);
      }
  -   else {
  -       //use fDTDValidator as the default validator
  -       fValidator = fDTDValidator;
  -   }
   }
   
   XMLScanner::XMLScanner( XMLDocumentHandler* const  docHandler
  -                        , DocTypeHandler* const    docTypeHandler
  -                        , XMLEntityHandler* const  entityHandler
  -                        , XMLErrorReporter* const  errHandler
  -                        , XMLValidator* const      valToAdopt) :
  +                          , DocTypeHandler* const    docTypeHandler
  +                          , XMLEntityHandler* const  entityHandler
  +                          , XMLErrorReporter* const  errHandler
  +                          , XMLValidator* const      valToAdopt) :
   
  -    fDoNamespaces(false)
  +    fCalculateSrcOfs(true)
  +    , fDoNamespaces(false)
       , fExitOnFirstFatal(true)
       , fValidationConstraintFatal(false)
       , fInException(false)
  @@ -256,19 +215,18 @@
       , fValidatorFromUser(false)
       , fDoSchema(false)
       , fSchemaFullChecking(false)
  -    , fSeeXsi(false)
       , fToCacheGrammar(false)
       , fUseCachedGrammar(false)
  +	, fLoadExternalDTD(true)
  +    , fNormalizeData(true)
       , fErrorCount(0)
       , fEmptyNamespaceId(0)
       , fUnknownNamespaceId(0)
       , fXMLNamespaceId(0)
       , fXMLNSNamespaceId(0)
       , fSchemaNamespaceId(0)
  -    , fElemStateSize(16)
       , fScannerId(0)
       , fSequenceId(0)
  -    , fElemState(0)
       , fAttrList(0)
       , fDocHandler(docHandler)
       , fDocTypeHandler(docTypeHandler)
  @@ -276,24 +234,15 @@
       , fErrorReporter(errHandler)
       , fErrorHandler(0)
       , fIDRefList(0)
  -    , fRawAttrList(0)
       , fValidator(valToAdopt)
  -    , fDTDValidator(0)
  -    , fSchemaValidator(0)
       , fValScheme(Val_Never)
       , fGrammarResolver(0)
       , fGrammar(0)
       , fRootGrammar(0)
  -    , fDTDGrammar(0)
       , fURIStringPool(0)
  -    , fMatcherStack(0)
  -    , fValueStoreCache(0)
  -    , fFieldActivator(0)
       , fRootElemName(0)
       , fExternalSchemaLocation(0)
       , fExternalNoNamespaceSchemaLocation(0)
  -    , fLoadExternalDTD(true)
  -    , fNormalizeData(true)
   {
      commonInit();
   
  @@ -301,57 +250,42 @@
          fValidatorFromUser = true;
          initValidator(fValidator);
      }
  -   else {
  -       //use fDTDValidator as the default validator
  -       fValidator = fDTDValidator;
  -   }
   }
   
   XMLScanner::~XMLScanner()
   {
  -    delete [] fElemState;
       delete fAttrList;
       delete fIDRefList;
  -    delete fRawAttrList;
  -    if (fValidatorFromUser)
  -        delete fValidator;
  -
  -    delete fDTDValidator;
  -    delete fSchemaValidator;
  -
  -    //fGrammarResolver will delete the fGrammar as well
  -    delete fGrammarResolver;
  -
  -    delete fURIStringPool;
  -
  -    delete fFieldActivator;
  -    delete fMatcherStack;
  -    delete fValueStoreCache;
  -
       delete [] fRootElemName;
       delete [] fExternalSchemaLocation;
       delete [] fExternalNoNamespaceSchemaLocation;
   }
   
   
  +void XMLScanner::setValidator(XMLValidator* const valToAdopt)
  +{
  +    if (fValidatorFromUser)
  +        delete fValidator;
  +    fValidator = valToAdopt;
  +    fValidatorFromUser = true;
  +    initValidator(fValidator);
  +}
  +
  +
  +
   // ---------------------------------------------------------------------------
   //  XMLScanner: Main entry point to scan a document
   // ---------------------------------------------------------------------------
   void XMLScanner::scanDocument(  const   XMLCh* const    systemId)
   {
  -    //
       //  First we try to parse it as a URL. If that fails, we assume its
       //  a file and try it that way.
  -    //
       InputSource* srcToUse = 0;
       try
       {
  -        //
           //  Create a temporary URL. Since this is the primary document,
           //  it has to be fully qualified. If not, then assume we are just
           //  mistaking a file for a URL.
  -        //
  -
           XMLURL tmpURL(systemId);
           if (tmpURL.isRelative()) {
               srcToUse = new LocalFileInputSource(systemId);
  @@ -362,7 +296,6 @@
           }
   
       }
  -
       catch(const MalformedURLException&)
       {
           srcToUse = new LocalFileInputSource(systemId);
  @@ -370,10 +303,8 @@
   
       catch(const XMLException& excToCatch)
       {
  -        //
           //  For any other XMLException,
           //  emit the error and catch any user exception thrown from here.
  -        //
           fInException = true;
           if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning)
               emitError
  @@ -398,7 +329,6 @@
               );
           return;
       }
  -
       catch(...)
       {
           // Just rethrow this, since its not our problem
  @@ -418,172 +348,22 @@
   }
   
   
  -void XMLScanner::scanDocument(const InputSource& src)
  -{
  -    //
  -    //  Bump up the sequence id for this parser instance. This will invalidate
  -    //  any previous progressive scan tokens.
  -    //
  -    fSequenceId++;
  -
  -    try
  -    {
  -        //
  -        //  Reset the scanner and its plugged in stuff for a new run. This
  -        //  resets all the data structures, creates the initial reader and
  -        //  pushes it on the stack, and sets up the base document path.
  -        //
  -        scanReset(src);
  -
  -        // If we have a document handler, then call the start document
  -        if (fDocHandler)
  -            fDocHandler->startDocument();
  -
  -        fValueStoreCache->startDocument();
  -
  -        //
  -        //  Scan the prolog part, which is everything before the root element
  -        //  including the DTD subsets.
  -        //
  -        scanProlog();
  -
  -        //
  -        //  If we got to the end of input, then its not a valid XML file.
  -        //  Else, go on to scan the content.
  -        //
  -        if (fReaderMgr.atEOF())
  -        {
  -            emitError(XMLErrs::EmptyMainEntity);
  -        }
  -         else
  -        {
  -            // Scan content, and tell it its not an external entity
  -            if (scanContent(false))
  -            {
  -                // Do post-parse validation if required
  -                if (fValidate)
  -                {
  -                    //
  -                    //  We handle ID reference semantics at this level since
  -                    //  its required by XML 1.0.
  -                    //
  -                    checkIDRefs();
  -
  -                    // Then allow the validator to do any extra stuff it wants
  -                    fValidator->postParseValidation();
  -                }
  -
  -                // That went ok, so scan for any miscellaneous stuff
  -                if (!fReaderMgr.atEOF())
  -                    scanMiscellaneous();
  -            }
  -        }
  -
  -        if (fValidate)
  -            fValueStoreCache->endDocument();
  -
  -        // If we have a document handler, then call the end document
  -        if (fDocHandler)
  -            fDocHandler->endDocument();
  -
  -        // Reset the reader manager to close all files, sockets, etc...
  -        fReaderMgr.reset();
  -    }
  -
  -    //
  -    //  NOTE:
  -    //
  -    //  In all of the error processing below, the emitError() call MUST come
  -    //  before the flush of the reader mgr, or it will fail because it tries
  -    //  to find out the position in the XML source of the error.
  -    //
  -    catch(const XMLErrs::Codes)
  -    {
  -        // This is a 'first fatal error' type exit, so reset and fall through
  -        fReaderMgr.reset();
  -    }
  -
  -    catch(const XMLValid::Codes)
  -    {
  -        // This is a 'first fatal error' type exit, so reset and fall through
  -        fReaderMgr.reset();
  -    }
  -
  -    catch(const XMLException& excToCatch)
  -    {
  -        //
  -        //  Emit the error and catch any user exception thrown from here. Make
  -        //  sure in all cases we flush the reader manager.
  -        //
  -        fInException = true;
  -        try
  -        {
  -            if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning)
  -                emitError
  -                (
  -                    XMLErrs::XMLException_Warning
  -                    , excToCatch.getType()
  -                    , excToCatch.getMessage()
  -                );
  -            else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal)
  -                emitError
  -                (
  -                    XMLErrs::XMLException_Fatal
  -                    , excToCatch.getType()
  -                    , excToCatch.getMessage()
  -                );
  -            else
  -                emitError
  -                (
  -                    XMLErrs::XMLException_Error
  -                    , excToCatch.getType()
  -                    , excToCatch.getMessage()
  -                );
  -        }
  -
  -        catch(...)
  -        {
  -            // Flush the reader manager and rethrow user's error
  -            fReaderMgr.reset();
  -            throw;
  -        }
  -
  -        // If it returned, then reset the reader manager and fall through
  -        fReaderMgr.reset();
  -    }
  -
  -    catch(...)
  -    {
  -        // Reset and rethrow
  -        fReaderMgr.reset();
  -        throw;
  -    }
  -}
  -
  -
  -//
   //  This method begins a progressive parse. It scans through the prolog and
   //  returns a token to be used on subsequent scanNext() calls. If the return
   //  value is true, then the token is legal and ready for further use. If it
   //  returns false, then the scan of the prolog failed and the token is not
   //  going to work on subsequent scanNext() calls.
  -//
   bool XMLScanner::scanFirst( const   XMLCh* const    systemId
                               ,       XMLPScanToken&  toFill)
   {
  -    //
       //  First we try to parse it as a URL. If that fails, we assume its
       //  a file and try it that way.
  -    //
       InputSource* srcToUse = 0;
       try
       {
  -        //
           //  Create a temporary URL. Since this is the primary document,
           //  it has to be fully qualified. If not, then assume we are just
           //  mistaking a file for a URL.
  -        //
  -
           XMLURL tmpURL(systemId);
           if (tmpURL.isRelative()) {
               srcToUse = new LocalFileInputSource(systemId);
  @@ -593,18 +373,14 @@
               srcToUse = new URLInputSource(tmpURL);
           }
       }
  -
       catch(const MalformedURLException&)
       {
           srcToUse = new LocalFileInputSource(systemId);
       }
  -
       catch(const XMLException& excToCatch)
       {
  -        //
           //  For any other XMLException,
           //  emit the error and catch any user exception thrown from here.
  -        //
           fInException = true;
           if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning)
               emitError
  @@ -629,7 +405,6 @@
               );
           return false;
       }
  -
       catch(...)
       {
           // Just rethrow this, since its not our problem
  @@ -650,73 +425,56 @@
   }
   
   bool XMLScanner::scanFirst( const   InputSource&    src
  -                            ,       XMLPScanToken&  toFill)
  +                           ,       XMLPScanToken&  toFill)
   {
  -    //
       //  Bump up the sequence id for this new scan cycle. This will invalidate
       //  any previous tokens we've returned.
  -    //
       fSequenceId++;
   
  -    //
       // Reset the scanner and its plugged in stuff for a new run.  This
       // resets all the data structures, creates the initial reader and
       // pushes it on the stack, and sets up the base document path
  -    //
       scanReset(src);
   
       // If we have a document handler, then call the start document
       if (fDocHandler)
           fDocHandler->startDocument();
   
  -    fValueStoreCache->startDocument();
  -
       try
       {
  -        //
           //  Scan the prolog part, which is everything before the root element
           //  including the DTD subsets. This is all that is done on the scan
           //  first.
  -        //
           scanProlog();
   
  -        //
           //  If we got to the end of input, then its not a valid XML file.
           //  Else, go on to scan the content.
  -        //
           if (fReaderMgr.atEOF())
           {
               emitError(XMLErrs::EmptyMainEntity);
           }
       }
  -
  -    //
       //  NOTE:
       //
       //  In all of the error processing below, the emitError() call MUST come
       //  before the flush of the reader mgr, or it will fail because it tries
       //  to find out the position in the XML source of the error.
  -    //
       catch(const XMLErrs::Codes)
       {
           // This is a 'first failure' exception so reset and return a failure
           fReaderMgr.reset();
           return false;
       }
  -
       catch(const XMLValid::Codes)
       {
           // This is a 'first fatal error' type exit, so reset and reuturn failure
           fReaderMgr.reset();
           return false;
       }
  -
       catch(const XMLException& excToCatch)
       {
  -        //
           //  Emit the error and catch any user exception thrown from here. Make
           //  sure in all cases we flush the reader manager.
  -        //
           fInException = true;
           try
           {
  @@ -742,7 +500,6 @@
                       , excToCatch.getMessage()
                   );
           }
  -
           catch(...)
           {
               // Reset and rethrow the user error
  @@ -754,7 +511,6 @@
           fReaderMgr.reset();
           return false;
       }
  -
       catch(...)
       {
           // Reset and rethrow original error
  @@ -768,367 +524,102 @@
   }
   
   
  -bool XMLScanner::scanNext(XMLPScanToken& token)
  +void XMLScanner::scanReset(XMLPScanToken& token)
   {
       // Make sure this token is still legal
       if (!isLegalToken(token))
           ThrowXML(RuntimeException, XMLExcepts::Scan_BadPScanToken);
   
  -    // Find the next token and remember the reader id
  -    unsigned int orgReader;
  -    XMLTokens curToken;
  +    // Reset the reader manager
  +    fReaderMgr.reset();
   
  -    bool retVal = true;
  +    // And invalidate any tokens by bumping our sequence number
  +    fSequenceId++;
   
  -    try
  -    {
  -        while (true)
  -        {
  -            //
  -            //  We have to handle any end of entity exceptions that happen here.
  -            //  We could be at the end of X nested entities, each of which will
  -            //  generate an end of entity exception as we try to move forward.
  -            //
  +    // Reset our error count
  +    fErrorCount = 0;
  +}
   
  -            try
  -            {
  -                curToken = senseNextToken(orgReader);
  -                break;
  -            }
   
  -            catch(const EndOfEntityException& toCatch)
  -            {
  -                // Send an end of entity reference event
  -                if (fDocHandler)
  -                    fDocHandler->endEntityReference(toCatch.getEntity());
  -            }
  -        }
   
  -        if (curToken == Token_CharData)
  -        {
  -            scanCharData(fCDataBuf);
  -        }
  -         else if (curToken == Token_EOF)
  +// ---------------------------------------------------------------------------
  +//  XMLScanner: Private helper methods.
  +// ---------------------------------------------------------------------------
  +
  +//  This method handles the common initialization, to avoid having to do
  +//  it redundantly in multiple constructors.
  +void XMLScanner::commonInit()
  +{
  +    //  We have to do a little init that involves statics, so we have to
  +    //  use the mutex to protect it.
  +    {
  +        XMLMutexLock lockInit(&gScannerMutex());
  +
  +        // If we haven't loaded our message yet, then do that
  +        if (!gMsgLoader)
           {
  -            if (!fElemStack.isEmpty())
  -            {
  -                const ElemStack::StackElem* topElem = fElemStack.popTop();
  -                emitError
  -                (
  -                    XMLErrs::EndedWithTagsOnStack
  -                    , topElem->fThisElement->getFullName()
  -                );
  -            }
  +            gMsgLoader = XMLPlatformUtils::loadMsgSet(XMLUni::fgXMLErrDomain);
  +            if (!gMsgLoader)
  +                XMLPlatformUtils::panic(XMLPlatformUtils::Panic_CantLoadMsgDomain);
   
  -            retVal = false;
  +            // Register this object to be cleaned up at termination
  +			cleanupMsgLoader.registerCleanup(reinitMsgLoader);
           }
  -         else
  -        {
  -            // Its some sort of markup
  -            bool gotData = true;
  -            switch(curToken)
  -            {
  -                case Token_CData :
  -                    // Make sure we are within content
  -                    if (fElemStack.isEmpty())
  -                        emitError(XMLErrs::CDATAOutsideOfContent);
  -                    scanCDSection();
  -                    break;
   
  -                case Token_Comment :
  -                    scanComment();
  -                    break;
  +        // And assign ourselves the next available scanner id
  +        fScannerId = ++gScannerId;
  +    }
   
  -                case Token_EndTag :
  -                    scanEndTag(gotData);
  -                    break;
  +    //  Create the attribute list, which is used to store attribute values
  +    //  during start tag processing. Give it a reasonable initial size that
  +    //  will serve for most folks, though it will grow as required.
  +    fAttrList = new RefVectorOf<XMLAttr>(32);
   
  -                case Token_PI :
  -                    scanPI();
  -                    break;
  +    //  Create the id ref list. This is used to enforce XML 1.0 ID ref
  +    //  semantics, i.e. all id refs must refer to elements that exist
  +    fIDRefList = new RefHashTableOf<XMLRefInfo>(109);
   
  -                case Token_StartTag :
  -                    if (fDoNamespaces)
  -                        scanStartTagNS(gotData);
  -                    else
  -                        scanStartTag(gotData);
  -                    break;
  +    //  Create the GrammarResolver
  +    //fGrammarResolver = new GrammarResolver();
  +}
   
  -                default :
  -                    fReaderMgr.skipToChar(chOpenAngle);
  -                    break;
  -            }
   
  -            if (orgReader != fReaderMgr.getCurrentReaderNum())
  -                emitError(XMLErrs::PartialMarkupInEntity);
  +void XMLScanner::initValidator(XMLValidator* theValidator) {
   
  -            // If we hit the end, then do the miscellaneous part
  -            if (!gotData)
  -            {
  -                // Do post-parse validation if required
  -                if (fValidate)
  -                {
  -                    //
  -                    //  We handle ID reference semantics at this level since
  -                    //  its required by XML 1.0.
  -                    //
  -                    checkIDRefs();
  +    //  Tell the validator about the stuff it needs to know in order to
  +    //  do its work.
  +    theValidator->setScannerInfo(this, &fReaderMgr, &fBufMgr);
  +    theValidator->setErrorReporter(fErrorReporter);
  +}
   
  -                    // Then allow the validator to do any extra stuff it wants
  -                    fValidator->postParseValidation();
  -                }
  +// ---------------------------------------------------------------------------
  +//  XMLScanner: Error emitting methods
  +// ---------------------------------------------------------------------------
   
  -                // That went ok, so scan for any miscellaneous stuff
  -                scanMiscellaneous();
  +//  These methods are called whenever the scanner wants to emit an error.
  +//  It handles getting the message loaded, doing token replacement, etc...
  +//  and then calling the error handler, if its installed.
  +void XMLScanner::emitError(const XMLErrs::Codes toEmit)
  +{
  +    // Bump the error count if it is not a warning
  +    if (XMLErrs::errorType(toEmit) != XMLErrorReporter::ErrType_Warning)
  +        incrementErrorCount();
   
  -                if (fValidate)
  -                    fValueStoreCache->endDocument();
  +    if (fErrorReporter)
  +    {
  +        // Load the message into a local for display
  +        const unsigned int msgSize = 1023;
  +        XMLCh errText[msgSize + 1];
   
  -                if (fDocHandler)
  -                    fDocHandler->endDocument();
  -            }
  +        if (!gMsgLoader->loadMsg(toEmit, errText, msgSize))
  +        {
  +                // <TBD> Probably should load a default msg here
           }
  -    }
   
  -    //
  -    //  NOTE:
  -    //
  -    //  In all of the error processing below, the emitError() call MUST come
  -    //  before the flush of the reader mgr, or it will fail because it tries
  -    //  to find out the position in the XML source of the error.
  -    //
  -    catch(const XMLErrs::Codes)
  -    {
  -        // This is a 'first failure' exception, so reset and return failure
  -        fReaderMgr.reset();
  -        return false;
  -    }
  -
  -    catch(const XMLValid::Codes)
  -    {
  -        // This is a 'first fatal error' type exit, so reset and reuturn failure
  -        fReaderMgr.reset();
  -        return false;
  -    }
  -
  -    // We have to propogate SAX exceptions
  -    catch(const SAXException&)
  -    {
  -        // Just reset our reader manager and rethrow SAX exception
  -        fReaderMgr.reset();
  -        throw;
  -    }
  -
  -    catch(const XMLException& excToCatch)
  -    {
  -        //
  -        //  Emit the error and catch any user exception thrown from here. Make
  -        //  sure in all cases we flush the reader manager.
  -        //
  -        fInException = true;
  -        try
  -        {
  -            if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning)
  -                emitError
  -                (
  -                    XMLErrs::XMLException_Warning
  -                    , excToCatch.getType()
  -                    , excToCatch.getMessage()
  -                );
  -            else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal)
  -                emitError
  -                (
  -                    XMLErrs::XMLException_Fatal
  -                    , excToCatch.getType()
  -                    , excToCatch.getMessage()
  -                );
  -            else
  -                emitError
  -                (
  -                    XMLErrs::XMLException_Error
  -                    , excToCatch.getType()
  -                    , excToCatch.getMessage()
  -                );
  -        }
  -
  -        catch(...)
  -        {
  -            // Reset and rethrow user error
  -            fReaderMgr.reset();
  -            throw;
  -        }
  -
  -        // Reset and return failure
  -        fReaderMgr.reset();
  -        return false;
  -    }
  -
  -    catch(...)
  -    {
  -        // Reset and rethrow original error
  -        fReaderMgr.reset();
  -        throw;
  -    }
  -
  -    // If we hit the end, then flush the reader manager
  -    if (!retVal)
  -        fReaderMgr.reset();
  -
  -    return retVal;
  -}
  -
  -
  -void XMLScanner::scanReset(XMLPScanToken& token)
  -{
  -    // Make sure this token is still legal
  -    if (!isLegalToken(token))
  -        ThrowXML(RuntimeException, XMLExcepts::Scan_BadPScanToken);
  -
  -    // Reset the reader manager
  -    fReaderMgr.reset();
  -
  -    // And invalidate any tokens by bumping our sequence number
  -    fSequenceId++;
  -
  -    // Reset our error count
  -    fErrorCount = 0;
  -}
  -
  -
  -
  -// ---------------------------------------------------------------------------
  -//  XMLScanner: Private helper methods. Most of these are implemented in
  -//  XMLScanner2.Cpp.
  -// ---------------------------------------------------------------------------
  -
  -//
  -//  This method handles the common initialization, to avoid having to do
  -//  it redundantly in multiple constructors.
  -//
  -void XMLScanner::commonInit()
  -{
  -
  -    //
  -    //  We have to do a little init that involves statics, so we have to
  -    //  use the mutex to protect it.
  -    //
  -    {
  -        XMLMutexLock lockInit(&gScannerMutex());
  -
  -        // If we haven't loaded our message yet, then do that
  -        if (!gMsgLoader)
  -        {
  -            gMsgLoader = XMLPlatformUtils::loadMsgSet(XMLUni::fgXMLErrDomain);
  -            if (!gMsgLoader)
  -                XMLPlatformUtils::panic(XMLPlatformUtils::Panic_CantLoadMsgDomain);
  -
  -            // Register this object to be cleaned up at termination
  -			cleanupMsgLoader.registerCleanup(reinitMsgLoader);
  -        }
  -
  -        // And assign ourselves the next available scanner id
  -        fScannerId = ++gScannerId;
  -    }
  -
  -    //
  -    //  Create the element state array
  -    //
  -    fElemState = new unsigned int[fElemStateSize];
  -
  -    //
  -    //  Create the attribute list, which is used to store attribute values
  -    //  during start tag processing. Give it a reasonable initial size that
  -    //  will serve for most folks, though it will grow as required.
  -    //
  -    fAttrList = new RefVectorOf<XMLAttr>(32);
  -
  -    //
  -    //  And we need one for the raw attribute scan. This just stores key/
  -    //  value string pairs (prior to any processing.)
  -    //
  -    fRawAttrList = new RefVectorOf<KVStringPair>(32);
  -
  -    //
  -    //  Create the id ref list. This is used to enforce XML 1.0 ID ref
  -    //  semantics, i.e. all id refs must refer to elements that exist
  -    //
  -    fIDRefList = new RefHashTableOf<XMLRefInfo>(109);
  -
  -    //  Create the GrammarResolver
  -    fGrammarResolver = new GrammarResolver();
  -
  -    //  Create the Validator and init them
  -    fDTDValidator = new DTDValidator();
  -    initValidator(fDTDValidator);
  -    fSchemaValidator = new SchemaValidator();
  -    initValidator(fSchemaValidator);
  -
  -    // Create IdentityConstraint info
  -    fMatcherStack = new XPathMatcherStack();
  -    fValueStoreCache = new ValueStoreCache();
  -    fFieldActivator = new FieldActivator(fValueStoreCache, fMatcherStack);
  -    fValueStoreCache->setScanner(this);
  -}
  -
  -
  -
  -void XMLScanner::initValidator(XMLValidator* theValidator) {
  -    //
  -    //  Tell the validator about the stuff it needs to know in order to
  -    //  do its work.
  -    //
  -    theValidator->setScannerInfo(this, &fReaderMgr, &fBufMgr);
  -    theValidator->setErrorReporter(fErrorReporter);
  -
  -    if (theValidator->handlesSchema()) {
  -
  -        ((SchemaValidator*) theValidator)->setGrammarResolver(fGrammarResolver);
  -        ((SchemaValidator*) theValidator)->setExitOnFirstFatal(fExitOnFirstFatal);
  -    }
  -}
  -
  -void XMLScanner::resetURIStringPool() {
  -    fURIStringPool->flushAll();
  -
  -    fEmptyNamespaceId   = fURIStringPool->addOrFind(XMLUni::fgZeroLenString);
  -    fUnknownNamespaceId = fURIStringPool->addOrFind(XMLUni::fgUnknownURIName);
  -    fXMLNamespaceId     = fURIStringPool->addOrFind(XMLUni::fgXMLURIName);
  -    fXMLNSNamespaceId   = fURIStringPool->addOrFind(XMLUni::fgXMLNSURIName);
  -    fSchemaNamespaceId  = fURIStringPool->addOrFind(SchemaSymbols::fgURI_XSI);
  -}
  -
  -// ---------------------------------------------------------------------------
  -//  XMLScanner: Error emitting methods
  -// ---------------------------------------------------------------------------
  -
  -//
  -//  These methods are called whenever the scanner wants to emit an error.
  -//  It handles getting the message loaded, doing token replacement, etc...
  -//  and then calling the error handler, if its installed.
  -//
  -void XMLScanner::emitError(const XMLErrs::Codes toEmit)
  -{
  -    // Bump the error count if it is not a warning
  -    if (XMLErrs::errorType(toEmit) != XMLErrorReporter::ErrType_Warning)
  -        incrementErrorCount();
  -
  -    if (fErrorReporter)
  -    {
  -        // Load the message into a local for display
  -        const unsigned int msgSize = 1023;
  -        XMLCh errText[msgSize + 1];
  -
  -        if (!gMsgLoader->loadMsg(toEmit, errText, msgSize))
  -        {
  -                // <TBD> Probably should load a default msg here
  -        }
  -
  -        //
           //  Create a LastExtEntityInfo structure and get the reader manager
           //  to fill it in for us. This will give us the information about
           //  the last reader on the stack that was an external entity of some
           //  sort (i.e. it will ignore internal entities.
  -        //
           ReaderMgr::LastExtEntityInfo lastInfo;
           fReaderMgr.getLastExtEntityInfo(lastInfo);
   
  @@ -1162,10 +653,8 @@
   
       if (fErrorReporter)
       {
  -        //
           //  Load the message into alocal and replace any tokens found in
           //  the text.
  -        //
           const unsigned int maxChars = 2047;
           XMLCh errText[maxChars + 1];
   
  @@ -1174,12 +663,10 @@
                   // <TBD> Should probably load a default message here
           }
   
  -        //
           //  Create a LastExtEntityInfo structure and get the reader manager
           //  to fill it in for us. This will give us the information about
           //  the last reader on the stack that was an external entity of some
           //  sort (i.e. it will ignore internal entities.
  -        //
           ReaderMgr::LastExtEntityInfo lastInfo;
           fReaderMgr.getLastExtEntityInfo(lastInfo);
   
  @@ -1213,10 +700,8 @@
   
       if (fErrorReporter)
       {
  -        //
           //  Load the message into alocal and replace any tokens found in
           //  the text.
  -        //
           const unsigned int maxChars = 2047;
           XMLCh errText[maxChars + 1];
   
  @@ -1225,12 +710,10 @@
                   // <TBD> Should probably load a default message here
           }
   
  -        //
           //  Create a LastExtEntityInfo structure and get the reader manager
           //  to fill it in for us. This will give us the information about
           //  the last reader on the stack that was an external entity of some
           //  sort (i.e. it will ignore internal entities.
  -        //
           ReaderMgr::LastExtEntityInfo lastInfo;
           fReaderMgr.getLastExtEntityInfo(lastInfo);
   
  @@ -1257,7 +740,6 @@
   //  XMLScanner: Getter methods
   // ---------------------------------------------------------------------------
   
  -//
   //  This method allows the caller to query the current location of the scanner.
   //  It will return the sys/public ids of the current entity, and the line/col
   //  position within it.
  @@ -1266,7 +748,7 @@
   //  currently scanning an entity, the position returned will be the end of
   //  the entity reference in the file that had the reference.
   //
  -bool
  +/*bool
   XMLScanner::getLastExtLocation(         XMLCh* const    sysIdToFill
                                   , const unsigned int    maxSysIdChars
                                   ,       XMLCh* const    pubIdToFill
  @@ -1299,2553 +781,334 @@
           XMLString::copyString(pubIdToFill, lastInfo.publicId);
       }
       return true;
  -}
  +}*/
   
   
   // ---------------------------------------------------------------------------
   //  XMLScanner: Private scanning methods
   // ---------------------------------------------------------------------------
   
  -//
  -//  This method is called from scanStartTag() to handle the very raw initial
  -//  scan of the attributes. It just fills in the passed collection with
  -//  key/value pairs for each attribute. No processing is done on them at all.
  -//
  -unsigned int
  -XMLScanner::rawAttrScan(const   XMLCh* const                elemName
  -                        ,       RefVectorOf<KVStringPair>&  toFill
  -                        ,       bool&                       isEmpty)
  +//  This method is called after the end of the root element, to handle
  +//  any miscellaneous stuff hanging around.
  +void XMLScanner::scanMiscellaneous()
   {
  -    //
  -    //  Keep up with how many attributes we've seen so far, and how many
  -    //  elements are available in the vector. This way we can reuse old
  -    //  elements until we run out and then expand it.
  -    //
  -    unsigned int attCount = 0;
  -    unsigned int curVecSize = toFill.size();
  -
  -    // Assume it is not empty
  -    isEmpty = false;
  +    // Get a buffer for this work
  +    XMLBufBid bbCData(&fBufMgr);
   
  -    //
  -    //  We loop until we either see a /> or >, handling key/value pairs util
  -    //  we get there. We place them in the passed vector, which we will expand
  -    //  as required to hold them.
  -    //
       while (true)
       {
  -        // Get the next character, which should be non-space
  -        XMLCh nextCh = fReaderMgr.peekNextChar();
  -
  -        //
  -        //  If the next character is not a slash or closed angle bracket,
  -        //  then it must be whitespace, since whitespace is required
  -        //  between the end of the last attribute and the name of the next
  -        //  one.
  -        //
  -        if (attCount)
  +        try
           {
  -            if ((nextCh != chForwardSlash) && (nextCh != chCloseAngle))
  -            {
  -                if (XMLReader::isWhitespace(nextCh))
  -                {
  -                    // Ok, skip by them and get another char
  -                    fReaderMgr.getNextChar();
  -                    fReaderMgr.skipPastSpaces();
  -                    nextCh = fReaderMgr.peekNextChar();
  -                }
  -                 else
  -                {
  -                    // Emit the error but keep on going
  -                    emitError(XMLErrs::ExpectedWhitespace);
  -                }
  -            }
  -        }
  +            const XMLCh nextCh = fReaderMgr.peekNextChar();
   
  -        //
  -        //  Ok, here we first check for any of the special case characters.
  -        //  If its not one, then we do the normal case processing, which
  -        //  assumes that we've hit an attribute value, Otherwise, we do all
  -        //  the special case checks.
  -        //
  -        if (!XMLReader::isSpecialStartTagChar(nextCh))
  -        {
  -            //
  -            //  Assume its going to be an attribute, so get a name from
  -            //  the input.
  -            //
  -            if (!fReaderMgr.getName(fAttNameBuf))
  -            {
  -                emitError(XMLErrs::ExpectedAttrName);
  -                fReaderMgr.skipPastChar(chCloseAngle);
  -                return attCount;
  -            }
  +            // Watch for end of file and break out
  +            if (!nextCh)
  +                break;
   
  -            // And next must be an equal sign
  -            if (!scanEq())
  +            if (nextCh == chOpenAngle)
               {
  -                static const XMLCh tmpList[] =
  -                {
  -                    chSingleQuote, chDoubleQuote, chCloseAngle
  -                    , chOpenAngle, chForwardSlash, chNull
  -                };
  -
  -                emitError(XMLErrs::ExpectedEqSign);
  -
  -                //
  -                //  Try to sync back up by skipping forward until we either
  -                //  hit something meaningful.
  -                //
  -                const XMLCh chFound = fReaderMgr.skipUntilInOrWS(tmpList);
  -
  -                if ((chFound == chCloseAngle) || (chFound == chForwardSlash))
  +                if (checkXMLDecl(true))
                   {
  -                    // Jump back to top for normal processing of these
  -                    continue;
  +                    // Can't have an XML decl here
  +                    emitError(XMLErrs::NotValidAfterContent);
  +                    fReaderMgr.skipPastChar(chCloseAngle);
                   }
  -                 else if ((chFound == chSingleQuote)
  -                      ||  (chFound == chDoubleQuote)
  -                      ||  XMLReader::isWhitespace(chFound))
  +                else if (fReaderMgr.skippedString(XMLUni::fgPIString))
                   {
  -                    // Just fall through assuming that the value is to follow
  +                    scanPI();
                   }
  -                 else if (chFound == chOpenAngle)
  +                 else if (fReaderMgr.skippedString(XMLUni::fgCommentString))
                   {
  -                    // Assume a malformed tag and that new one is starting
  -                    emitError(XMLErrs::UnterminatedStartTag, elemName);
  -                    return attCount;
  +                    scanComment();
                   }
  -                 else
  +                else
                   {
  -                    // Something went really wrong
  -                    return attCount;
  +                    // This can't be possible, so just give up
  +                    emitError(XMLErrs::ExpectedCommentOrPI);
  +                    fReaderMgr.skipPastChar(chCloseAngle);
                   }
               }
  -
  -            //
  -            //  Next should be the quoted attribute value. We just do a simple
  -            //  and stupid scan of this value. The only thing we do here
  -            //  is to expand entity references.
  -            //
  -            if (!basicAttrValueScan(fAttNameBuf.getRawBuffer(), fAttValueBuf))
  +            else if (XMLReader::isWhitespace(nextCh))
               {
  -                static const XMLCh tmpList[] =
  -                {
  -                    chCloseAngle, chOpenAngle, chForwardSlash, chNull
  -                };
  -
  -                emitError(XMLErrs::ExpectedAttrValue);
  -
  -                //
  -                //  It failed, so lets try to get synced back up. We skip
  -                //  forward until we find some whitespace or one of the
  -                //  chars in our list.
  -                //
  -                const XMLCh chFound = fReaderMgr.skipUntilInOrWS(tmpList);
  -
  -                if ((chFound == chCloseAngle)
  -                ||  (chFound == chForwardSlash)
  -                ||  XMLReader::isWhitespace(chFound))
  -                {
  -                    //
  -                    //  Just fall through and process this attribute, though
  -                    //  the value will be "".
  -                    //
  -                }
  -                 else if (chFound == chOpenAngle)
  +                //  If we have a doc handler, then gather up the spaces and
  +                //  call back. Otherwise, just skip over whitespace.
  +                if (fDocHandler)
                   {
  -                    // Assume a malformed tag and that new one is starting
  -                    emitError(XMLErrs::UnterminatedStartTag, elemName);
  -                    return attCount;
  -                }
  -                 else
  -                {
  -                    // Something went really wrong
  -                    return attCount;
  -                }
  -            }
  -
  -            //
  -            //  Make sure that the name is basically well formed for namespace
  -            //  enabled rules. It either has no colons, or it has one which
  -            //  is neither the first or last char.
  -            //
  -            const int colonFirst = XMLString::indexOf(fAttNameBuf.getRawBuffer(), chColon);
  -            if (colonFirst != -1)
  -            {
  -                const int colonLast = XMLString::lastIndexOf(fAttNameBuf.getRawBuffer(), chColon);
  -
  -                if (colonFirst != colonLast)
  -                {
  -                    emitError(XMLErrs::TooManyColonsInName);
  -                    continue;
  -                }
  -                 else if ((colonFirst == 0)
  -                      ||  (colonLast == (int)fAttNameBuf.getLen() - 1))
  -                {
  -                    emitError(XMLErrs::InvalidColonPos);
  -                    continue;
  -                }
  -            }
  -
  -
  -            //
  -            //  And now lets add it to the passed collection. If we have not
  -            //  filled it up yet, then we use the next element. Else we add
  -            //  a new one.
  -            //
  -            KVStringPair* curPair = 0;
  -            if (attCount >= curVecSize)
  -            {
  -                curPair = new KVStringPair
  -                (
  -                    fAttNameBuf.getRawBuffer()
  -                    , fAttValueBuf.getRawBuffer()
  -                );
  -                toFill.addElement(curPair);
  -            }
  -             else
  -            {
  -                curPair = toFill.elementAt(attCount);
  -                curPair->set(fAttNameBuf.getRawBuffer(), fAttValueBuf.getRawBuffer());
  -            }
  -
  -            // And bump the count of attributes we've gotten
  -            attCount++;
  -
  -            // And go to the top again for another attribute
  -            continue;
  -        }
  -
  -        //
  -        //  It was some special case character so do all of the checks and
  -        //  deal with it.
  -        //
  -        if (!nextCh)
  -            ThrowXML(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF);
  -
  -        if (nextCh == chForwardSlash)
  -        {
  -            fReaderMgr.getNextChar();
  -            isEmpty = true;
  -            if (!fReaderMgr.skippedChar(chCloseAngle))
  -                emitError(XMLErrs::UnterminatedStartTag, elemName);
  -            break;
  -        }
  -         else if (nextCh == chCloseAngle)
  -        {
  -            fReaderMgr.getNextChar();
  -            break;
  -        }
  -         else if (nextCh == chOpenAngle)
  -        {
  -            //
  -            //  Check for this one specially, since its going to be common
  -            //  and it is kind of auto-recovering since we've already hit the
  -            //  next open bracket, which is what we would have seeked to (and
  -            //  skipped this whole tag.)
  -            //
  -            emitError(XMLErrs::UnterminatedStartTag, elemName);
  -            break;
  -        }
  -         else if ((nextCh == chSingleQuote) || (nextCh == chDoubleQuote))
  -        {
  -            //
  -            //  Check for this one specially, which is probably a missing
  -            //  attribute name, e.g. ="value". Just issue expected name
  -            //  error and eat the quoted string, then jump back to the
  -            //  top again.
  -            //
  -            emitError(XMLErrs::ExpectedAttrName);
  -            fReaderMgr.getNextChar();
  -            fReaderMgr.skipQuotedString(nextCh);
  -            fReaderMgr.skipPastSpaces();
  -            continue;
  -        }
  -    }
  -
  -    return attCount;
  -}
  -
  -
  -//
  -//  This method will kick off the scanning of the primary content of the
  -//  document, i.e. the elements.
  -//
  -bool XMLScanner::scanContent(const bool extEntity)
  -{
  -    //
  -    //  Go into a loop until we hit the end of the root element, or we fall
  -    //  out because there is no root element.
  -    //
  -    //  We have to do kind of a deeply nested double loop here in order to
  -    //  avoid doing the setup/teardown of the exception handler on each
  -    //  round. Doing it this way we only do it when an exception actually
  -    //  occurs.
  -    //
  -    bool gotData = true;
  -    bool inMarkup = false;
  -    while (gotData)
  -    {
  -        try
  -        {
  -            while (gotData)
  -            {
  -                //  Sense what the next top level token is. According to what
  -                //  this tells us, we will call something to handle that kind
  -                //  of thing.
  -                //
  -                unsigned int orgReader;
  -                const XMLTokens curToken = senseNextToken(orgReader);
  -
  -                //
  -                //  Handle character data and end of file specially. Char data
  -                //  is not markup so we don't want to handle it in the loop
  -                //  below.
  -                //
  -                if (curToken == Token_CharData)
  -                {
  -                    //
  -                    //  Scan the character data and call appropriate events. Let
  -                    //  him use our local character data buffer for efficiency.
  -                    //
  -                    scanCharData(fCDataBuf);
  -                    continue;
  -                }
  -                 else if (curToken == Token_EOF)
  -                {
  -                    //
  -                    //  The element stack better be empty at this point or we
  -                    //  ended prematurely before all elements were closed.
  -                    //
  -                    if (!fElemStack.isEmpty())
  -                    {
  -                        const ElemStack::StackElem* topElem = fElemStack.popTop();
  -                        emitError
  -                        (
  -                            XMLErrs::EndedWithTagsOnStack
  -                            , topElem->fThisElement->getFullName()
  -                        );
  -                    }
  -
  -                    // Its the end of file, so clear the got data flag
  -                    gotData = false;
  -                    continue;
  -                }
  -
  -                // We are in some sort of markup now
  -                inMarkup = true;
  -
  -                //
  -                //  According to the token we got, call the appropriate
  -                //  scanning method.
  -                //
  -                switch(curToken)
  -                {
  -                    case Token_CData :
  -                        // Make sure we are within content
  -                        if (fElemStack.isEmpty())
  -                            emitError(XMLErrs::CDATAOutsideOfContent);
  -                        scanCDSection();
  -                        break;
  -
  -                    case Token_Comment :
  -                        scanComment();
  -                        break;
  -
  -                    case Token_EndTag :
  -                        scanEndTag(gotData);
  -                        break;
  -
  -                    case Token_PI :
  -                        scanPI();
  -                        break;
  -
  -                    case Token_StartTag :
  -                        if (fDoNamespaces)
  -                            scanStartTagNS(gotData);
  -                        else
  -                            scanStartTag(gotData);
  -                        break;
  -
  -                    default :
  -                        fReaderMgr.skipToChar(chOpenAngle);
  -                        break;
  -                }
  -
  -                if (orgReader != fReaderMgr.getCurrentReaderNum())
  -                    emitError(XMLErrs::PartialMarkupInEntity);
  -
  -                // And we are back out of markup again
  -                inMarkup = false;
  -            }
  -        }
  -
  -        catch(const EndOfEntityException& toCatch)
  -        {
  -            //
  -            //  If we were in some markup when this happened, then its a
  -            //  partial markup error.
  -            //
  -            if (inMarkup)
  -                emitError(XMLErrs::PartialMarkupInEntity);
  -
  -            // Send an end of entity reference event
  -            if (fDocHandler)
  -                fDocHandler->endEntityReference(toCatch.getEntity());
  -
  -            inMarkup = false;
  -        }
  -    }
  -
  -    // It went ok, so return success
  -    return true;
  -}
  -
  -
  -void XMLScanner::scanEndTag(bool& gotData)
  -{
  -    //
  -    //  Assume we will still have data until proven otherwise. It will only
  -    //  ever be false if this is the end of the root element.
  -    //
  -    gotData = true;
  -
  -    //
  -    //  Check if the element stack is empty. If so, then this is an unbalanced
  -    //  element (i.e. more ends than starts, perhaps because of bad text
  -    //  causing one to be skipped.)
  -    //
  -    if (fElemStack.isEmpty())
  -    {
  -        emitError(XMLErrs::MoreEndThanStartTags);
  -        fReaderMgr.skipPastChar(chCloseAngle);
  -        ThrowXML(RuntimeException, XMLExcepts::Scan_UnbalancedStartEnd);
  -    }
  -
  -    // After the </ is the element QName, so get a name from the input
  -    XMLBufBid bbQName(&fBufMgr);
  -    XMLBuffer& qnameBuf = bbQName.getBuffer();
  -    if (!fReaderMgr.getName(qnameBuf))
  -    {
  -        // It failed so we can't really do anything with it
  -        emitError(XMLErrs::ExpectedElementName);
  -        fReaderMgr.skipPastChar(chCloseAngle);
  -        return;
  -    }
  -
  -    unsigned int uriId = fEmptyNamespaceId;
  -    XMLBufBid bbName(&fBufMgr);
  -    XMLBufBid bbPrefix(&fBufMgr);
  -    if (fDoNamespaces)
  -    {
  -        uriId = resolveQName
  -        (
  -            qnameBuf.getRawBuffer()
  -            , bbName.getBuffer()
  -            , bbPrefix.getBuffer()
  -            , ElemStack::Mode_Element
  -        );
  -    }
  -
  -    //
  -    //  Pop the stack of the element we are supposed to be ending. Remember
  -    //  that we don't own this. The stack just keeps them and reuses them.
  -    //
  -    //  NOTE: We CANNOT do this until we've resolved the element name because
  -    //  the element stack top contains the prefix to URI mappings for this
  -    //  element.
  -    //
  -    unsigned int topUri = fElemStack.getCurrentURI();
  -    const ElemStack::StackElem* topElem = fElemStack.popTop();
  -
  -    // See if it was the root element, to avoid multiple calls below
  -    const bool isRoot = fElemStack.isEmpty();
  -
  -    // Make sure that its the end of the element that we expect
  -    XMLElementDecl* tempElement = topElem->fThisElement;
  -    if (fDoNamespaces && fGrammarType == Grammar::SchemaGrammarType) {
  -        if ((topUri != uriId) || (!XMLString::equals(tempElement->getBaseName(), bbName.getRawBuffer())))
  -        {
  -            emitError
  -            (
  -                XMLErrs::ExpectedEndOfTagX
  -                , topElem->fThisElement->getFullName()
  -            );
  -        }
  -    }
  -    else {
  -        if (!XMLString::equals(tempElement->getFullName(), qnameBuf.getRawBuffer()))
  -        {
  -            emitError
  -            (
  -                XMLErrs::ExpectedEndOfTagX
  -                , topElem->fThisElement->getFullName()
  -            );
  -        }
  -    }
  -
  -
  -    // Make sure we are back on the same reader as where we started
  -    if (topElem->fReaderNum != fReaderMgr.getCurrentReaderNum())
  -        emitError(XMLErrs::PartialTagMarkupError);
  -
  -    // Skip optional whitespace
  -    fReaderMgr.skipPastSpaces();
  -
  -    // Make sure we find the closing bracket
  -    if (!fReaderMgr.skippedChar(chCloseAngle))
  -    {
  -        emitError
  -        (
  -            XMLErrs::UnterminatedEndTag
  -            , topElem->fThisElement->getFullName()
  -        );
  -    }
  -
  -    //
  -    //  If validation is enabled, then lets pass him the list of children and
  -    //  this element and let him validate it.
  -    //
  -    if (fValidate)
  -    {
  -        int res = fValidator->checkContent
  -        (
  -            topElem->fThisElement
  -            , topElem->fChildren
  -            , topElem->fChildCount
  -        );
  -
  -        if (res >= 0)
  -        {
  -            //
  -            //  One of the elements is not valid for the content. NOTE that
  -            //  if no children were provided but the content model requires
  -            //  them, it comes back with a zero value. But we cannot use that
  -            //  to index the child array in this case, and have to put out a
  -            //  special message.
  -            //
  -            if (!topElem->fChildCount)
  -            {
  -                fValidator->emitError
  -                (
  -                    XMLValid::EmptyNotValidForContent
  -                    , topElem->fThisElement->getFormattedContentModel()
  -                );
  -            }
  -             else if ((unsigned int)res >= topElem->fChildCount)
  -            {
  -                fValidator->emitError
  -                (
  -                    XMLValid::NotEnoughElemsForCM
  -                    , topElem->fThisElement->getFormattedContentModel()
  -                );
  -            }
  -             else
  -            {
  -                fValidator->emitError
  -                (
  -                    XMLValid::ElementNotValidForContent
  -                    , topElem->fChildren[res]->getRawName()
  -                    , topElem->fThisElement->getFormattedContentModel()
  -                );
  -            }
  -        }
  -
  -        // reset xsi:type ComplexTypeInfo
  -        if (fGrammarType == Grammar::SchemaGrammarType) {
  -            ((SchemaElementDecl*)topElem->fThisElement)->setXsiComplexTypeInfo(0);
  -
  -            // call matchers and de-activate context
  -            int oldCount = fMatcherStack->getMatcherCount();
  -
  -            if (oldCount ||
  -                ((SchemaElementDecl*)topElem->fThisElement)->getIdentityConstraintCount()) {
  -
  -                for (int i = oldCount - 1; i >= 0; i--) {
  -
  -                    XPathMatcher* matcher = fMatcherStack->getMatcherAt(i);
  -                    matcher->endElement(*(topElem->fThisElement));
  -                }
  -
  -                if (fMatcherStack->size() > 0) {
  -                    fMatcherStack->popContext();
  -                }
  -
  -                // handle everything *but* keyref's.
  -                int newCount = fMatcherStack->getMatcherCount();
  -
  -                for (int j = oldCount - 1; j >= newCount; j--) {
  -
  -                    XPathMatcher* matcher = fMatcherStack->getMatcherAt(j);
  -                    IdentityConstraint* ic = matcher->getIdentityConstraint();
  -
  -                    if (ic  && (ic->getType() != IdentityConstraint::KEYREF)) {
  -
  -                        matcher->endDocumentFragment();
  -                        fValueStoreCache->transplant(ic, matcher->getInitialDepth());
  -                    }
  -                    else if (!ic) {
  -                        matcher->endDocumentFragment();
  -                    }
  -                }
  -
  -                // now handle keyref's...
  -                for (int k = oldCount - 1; k >= newCount; k--) {
  -
  -                    XPathMatcher* matcher = fMatcherStack->getMatcherAt(k);
  -                    IdentityConstraint* ic = matcher->getIdentityConstraint();
  -
  -                    if (ic && (ic->getType() == IdentityConstraint::KEYREF)) {
  -
  -                        ValueStore* values = fValueStoreCache->getValueStoreFor(ic, matcher->getInitialDepth());
  -
  -                        if (values) { // nothing to do if nothing matched!
  -                            values->endDcocumentFragment(fValueStoreCache);
  -                        }
  -
  -                        matcher->endDocumentFragment();
  -                    }
  -                }
  -
  -                fValueStoreCache->endElement();
  -            }
  -        }
  -    }
  -
  -    // If we have a doc handler, tell it about the end tag
  -    if (fDocHandler)
  -    {
  -        fDocHandler->endElement
  -        (
  -            *topElem->fThisElement
  -            , uriId
  -            , isRoot
  -            , bbPrefix.getRawBuffer()
  -        );
  -    }
  -
  -    // If this was the root, then done with content
  -    gotData = !isRoot;
  -
  -    if (gotData) {
  -        if (fDoNamespaces) {
  -            // Restore the grammar
  -            fGrammar = fElemStack.getCurrentGrammar();
  -            fGrammarType = fGrammar->getGrammarType();
  -            if (fGrammarType == Grammar::SchemaGrammarType && !fValidator->handlesSchema()) {
  -                if (fValidatorFromUser)
  -                    ThrowXML(RuntimeException, XMLExcepts::Gen_NoSchemaValidator);
  -                else {
  -                    fValidator = fSchemaValidator;
  -                }
  -            }
  -            else if (fGrammarType == Grammar::DTDGrammarType && !fValidator->handlesDTD()) {
  -                if (fValidatorFromUser)
  -                    ThrowXML(RuntimeException, XMLExcepts::Gen_NoDTDValidator);
  -                else {
  -                    fValidator = fDTDValidator;
  -                }
  -            }
  -
  -            fValidator->setGrammar(fGrammar);
  -        }
  -
  -        // Restore the validation flag
  -        fValidate = fElemStack.getValidationFlag();
  -    }
  -}
  -
  -
  -//
  -//  This method is called after the end of the root element, to handle
  -//  any miscellaneous stuff hanging around.
  -//
  -void XMLScanner::scanMiscellaneous()
  -{
  -    // Get a buffer for this work
  -    XMLBufBid bbCData(&fBufMgr);
  -
  -    while (true)
  -    {
  -        try
  -        {
  -            const XMLCh nextCh = fReaderMgr.peekNextChar();
  -
  -            // Watch for end of file and break out
  -            if (!nextCh)
  -                break;
  -
  -            if (nextCh == chOpenAngle)
  -            {
  -                if (checkXMLDecl(true))
  -                {
  -                    // Can't have an XML decl here
  -                    emitError(XMLErrs::NotValidAfterContent);
  -                    fReaderMgr.skipPastChar(chCloseAngle);
  -                }
  -                 else if (fReaderMgr.skippedString(XMLUni::fgPIString))
  -                {
  -                    scanPI();
  -                }
  -                 else if (fReaderMgr.skippedString(XMLUni::fgCommentString))
  -                {
  -                    scanComment();
  -                }
  -                 else
  -                {
  -                    // This can't be possible, so just give up
  -                    emitError(XMLErrs::ExpectedCommentOrPI);
  -                    fReaderMgr.skipPastChar(chCloseAngle);
  -                }
  -            }
  -             else if (XMLReader::isWhitespace(nextCh))
  -            {
  -                //
  -                //  If we have a doc handler, then gather up the spaces and
  -                //  call back. Otherwise, just skip over whitespace.
  -                //
  -                if (fDocHandler)
  -                {
  -                    fReaderMgr.getSpaces(bbCData.getBuffer());
  -                    fDocHandler->ignorableWhitespace
  -                    (
  -                        bbCData.getRawBuffer()
  -                        , bbCData.getLen()
  -                        , false
  -                    );
  -                }
  -                 else
  -                {
  -                    fReaderMgr.skipPastSpaces();
  -                }
  -            }
  -             else
  -            {
  -                emitError(XMLErrs::ExpectedCommentOrPI);
  -                fReaderMgr.skipPastChar(chCloseAngle);
  -            }
  -        }
  -
  -        catch(const EndOfEntityException&)
  -        {
  -            //
  -            //  Some entity leaked out of the content part of the document. Issue
  -            //  a warning and keep going.
  -            //
  -            emitError(XMLErrs::EntityPropogated);
  -        }
  -    }
  -}
  -
  -
  -//
  -//  Scans a PI and calls the appropriate callbacks. At entry we have just
  -//  scanned the <? part, and need to now start on the PI target name.
  -//
  -void XMLScanner::scanPI()
  -{
  -    const XMLCh* namePtr = 0;
  -    const XMLCh* targetPtr = 0;
  -
  -    //
  -    //  If there are any spaces here, then warn about it. If we aren't in
  -    //  'first error' mode, then we'll come back and can easily pick up
  -    //  again by just skipping them.
  -    //
  -    if (fReaderMgr.lookingAtSpace())
  -    {
  -        emitError(XMLErrs::PINameExpected);
  -        fReaderMgr.skipPastSpaces();
  -    }
  -
  -    // Get a buffer for the PI name and scan it in
  -    XMLBufBid bbName(&fBufMgr);
  -    if (!fReaderMgr.getName(bbName.getBuffer()))
  -    {
  -        emitError(XMLErrs::PINameExpected);
  -        fReaderMgr.skipPastChar(chCloseAngle);
  -        return;
  -    }
  -
  -    // Point the name pointer at the raw data
  -    namePtr = bbName.getRawBuffer();
  -
  -    // See if it is some form of 'xml' and emit a warning
  -    if (!XMLString::compareIString(namePtr, XMLUni::fgXMLString))
  -        emitError(XMLErrs::NoPIStartsWithXML);
  -
  -    // If namespaces are enabled, then no colons allowed
  -    if (fDoNamespaces)
  -    {
  -        if (XMLString::indexOf(namePtr, chColon) != -1)
  -            emitError(XMLErrs::ColonNotLegalWithNS);
  -    }
  -
  -    //
  -    //  If we don't hit a space next, then the PI has no target. If we do
  -    //  then get out the target. Get a buffer for it as well
  -    //
  -    XMLBufBid bbTarget(&fBufMgr);
  -    if (fReaderMgr.skippedSpace())
  -    {
  -        // Skip any leading spaces
  -        fReaderMgr.skipPastSpaces();
  -
  -        bool gotLeadingSurrogate = false;
  -
  -        // It does have a target, so lets move on to deal with that.
  -        while (1)
  -        {
  -            const XMLCh nextCh = fReaderMgr.getNextChar();
  -
  -            // Watch for an end of file, which is always bad here
  -            if (!nextCh)
  -            {
  -                emitError(XMLErrs::UnterminatedPI);
  -                ThrowXML(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF);
  -            }
  -
  -            // Watch for potential terminating character
  -            if (nextCh == chQuestion)
  -            {
  -                // It must be followed by '>' to be a termination of the target
  -                if (fReaderMgr.skippedChar(chCloseAngle))
  -                    break;
  -            }
  -
  -            // Check for correct surrogate pairs
  -            if ((nextCh >= 0xD800) && (nextCh <= 0xDBFF))
  -            {
  -                if (gotLeadingSurrogate)
  -                    emitError(XMLErrs::Expected2ndSurrogateChar);
  -                else
  -                    gotLeadingSurrogate = true;
  -            }
  -             else
  -            {
  -                if (gotLeadingSurrogate)
  -                {
  -                    if ((nextCh < 0xDC00) || (nextCh > 0xDFFF))
  -                        emitError(XMLErrs::Expected2ndSurrogateChar);
  -                }
  -                // Its got to at least be a valid XML character
  -                else if (!XMLReader::isXMLChar(nextCh)) {
  -
  -                    XMLCh tmpBuf[9];
  -                    XMLString::binToText
  -                    (
  -                        nextCh
  -                        , tmpBuf
  -                        , 8
  -                        , 16
  -                    );
  -                    emitError(XMLErrs::InvalidCharacter, tmpBuf);
  -                }
  -
  -                gotLeadingSurrogate = false;
  -            }
  -
  -            bbTarget.append(nextCh);
  -        }
  -    }
  -     else
  -    {
  -        // No target, but make sure its terminated ok
  -        if (!fReaderMgr.skippedChar(chQuestion))
  -        {
  -            emitError(XMLErrs::UnterminatedPI);
  -            fReaderMgr.skipPastChar(chCloseAngle);
  -            return;
  -        }
  -
  -        if (!fReaderMgr.skippedChar(chCloseAngle))
  -        {
  -            emitError(XMLErrs::UnterminatedPI);
  -            fReaderMgr.skipPastChar(chCloseAngle);
  -            return;
  -        }
  -    }
  -
  -    // Point the target pointer at the raw data
  -    targetPtr = bbTarget.getRawBuffer();
  -
  -    // If we have a handler, then call it
  -    if (fDocHandler)
  -    {
  -        fDocHandler->docPI
  -        (
  -            namePtr
  -            , targetPtr
  -       );
  -    }
  -}
  -
  -//
  -//  Scans all the input from the start of the file to the root element.
  -//  There does not have to be anything in the prolog necessarily, but usually
  -//  there is at least an XMLDecl.
  -//
  -//  On exit from here we are either at the end of the file or about to read
  -//  the opening < of the root element.
  -//
  -void XMLScanner::scanProlog()
  -{
  -    // Get a buffer for whitespace processing
  -    XMLBufBid bbCData(&fBufMgr);
  -
  -    //
  -    //  Loop through the prolog. If there is no content, this could go all
  -    //  the way to the end of the file.
  -    //
  -    try
  -    {
  -        while (true)
  -        {
  -            const XMLCh nextCh = fReaderMgr.peekNextChar();
  -
  -            if (nextCh == chOpenAngle)
  -            {
  -                //
  -                //  Ok, it could be the xml decl, a comment, the doc type line,
  -                //  or the start of the root element.
  -                //
  -                if (checkXMLDecl(true))
  -                {
  -                    // There shall be at lease --ONE-- space in between
  -                    // the tag '<?xml' and the VersionInfo.
  -                    //
  -                    //
  -                    //  If we are not at line 1, col 6, then the decl was not
  -                    //  the first text, so its invalid.
  -                    //
  -                    const XMLReader* curReader = fReaderMgr.getCurrentReader();
  -                    if ((curReader->getLineNumber() != 1)
  -                    ||  (curReader->getColumnNumber() != 7))
  -                    {
  -                        emitError(XMLErrs::XMLDeclMustBeFirst);
  -                    }
  -
  -                    scanXMLDecl(Decl_XML);
  -                }
  -                 else if (fReaderMgr.skippedString(XMLUni::fgPIString))
  -                {
  -                    scanPI();
  -                }
  -                 else if (fReaderMgr.skippedString(XMLUni::fgCommentString))
  -                {
  -                    scanComment();
  -                }
  -                 else if (fReaderMgr.skippedString(XMLUni::fgDocTypeString))
  -                {
  -                    scanDocTypeDecl();
  -
  -                    // if reusing grammar, this has been validated already in first scan
  -                    // skip for performance
  -                    if (fValidate && !fGrammar->getValidated()) {
  -                        //  validate the DTD scan so far
  -                        fValidator->preContentValidation(fUseCachedGrammar, true);
  -                    }
  -                }
  -                 else
  -                {
  -                    // Assume its the start of the root element
  -                    return;
  -                }
  -            }
  -             else if (XMLReader::isWhitespace(nextCh))
  -            {
  -                //
  -                //  If we have a document handler then gather up the
  -                //  whitespace and call back. Otherwise just skip over spaces.
  -                //
  -                if (fDocHandler)
  -                {
  -                    fReaderMgr.getSpaces(bbCData.getBuffer());
  -                    fDocHandler->ignorableWhitespace
  -                    (
  -                        bbCData.getRawBuffer()
  -                        , bbCData.getLen()
  -                        , false
  -                    );
  -                }
  -                 else
  -                {
  -                    fReaderMgr.skipPastSpaces();
  -                }
  -            }
  -             else
  -            {
  -                emitError(XMLErrs::InvalidDocumentStructure);
  -
  -                // Watch for end of file and break out
  -                if (!nextCh)
  -                    break;
  -                else
  -                    fReaderMgr.skipPastChar(chCloseAngle);
  -            }
  -
  -        }
  -    }
  -
  -    catch(const EndOfEntityException&)
  -    {
  -        //
  -        //  We should never get an end of entity here. They should only
  -        //  occur within the doc type scanning method, and not leak out to
  -        //  here.
  -        //
  -        emitError
  -        (
  -            XMLErrs::UnexpectedEOE
  -            , "in prolog"
  -        );
  -    }
  -}
  -
  -//
  -//  This method handles the high level logic of scanning the DOCType
  -//  declaration. This calls the DTDScanner and kicks off both the scanning of
  -//  the internal subset and the scanning of the external subset, if any.
  -//
  -//  When we get here the '<!DOCTYPE' part has already been scanned, which is
  -//  what told us that we had a doc type decl to parse.
  -//
  -
  -void XMLScanner::scanDocTypeDecl()
  -{
  -    //
  -    //  We have a doc type. So, switch the Grammar.
  -    //
  -    switchGrammar(XMLUni::fgDTDEntityString);
  -
  -    if (fDocTypeHandler)
  -        fDocTypeHandler->resetDocType();
  -
  -    // There must be some space after DOCTYPE
  -    if (!fReaderMgr.skipPastSpaces())
  -    {
  -        emitError(XMLErrs::ExpectedWhitespace);
  -
  -        // Just skip the Doctype declaration and return
  -        fReaderMgr.skipPastChar(chCloseAngle);
  -        return;
  -    }
  -
  -    // Get a buffer for the root element
  -    XMLBufBid bbRootName(&fBufMgr);
  -
  -    //
  -    //  Get a name from the input, which should be the name of the root
  -    //  element of the upcoming content.
  -    //
  -    fReaderMgr.getName(bbRootName.getBuffer());
  -    if (bbRootName.isEmpty())
  -    {
  -        emitError(XMLErrs::NoRootElemInDOCTYPE);
  -        fReaderMgr.skipPastChar(chCloseAngle);
  -        return;
  -    }
  -
  -    //
  -    //  Store the root element name for later check
  -    //
  -    setRootElemName(bbRootName.getRawBuffer());
  -
  -    //
  -    //  This element obviously is not going to exist in the element decl
  -    //  pool yet, but we need to call docTypeDecl. So force it into
  -    //  the element decl pool, marked as being there because it was in
  -    //  the DOCTYPE. Later, when its declared, the status will be updated.
  -    //
  -    //  Only do this if we are not reusing the validator! If we are reusing,
  -    //  then look it up instead. It has to exist!
  -    //
  -    DTDElementDecl* rootDecl = new DTDElementDecl(bbRootName.getRawBuffer(), fEmptyNamespaceId);
  -
  -    rootDecl->setCreateReason(DTDElementDecl::AsRootElem);
  -    rootDecl->setExternalElemDeclaration(true);
  -    ((DTDGrammar*)fGrammar)->setRootElemId(fGrammar->putElemDecl(rootDecl));
  -
  -    // Skip any spaces after the name
  -    fReaderMgr.skipPastSpaces();
  -
  -    //
  -    //  And now if we are looking at a >, then we are done. It is not
  -    //  required to have an internal or external subset, though why you
  -    //  would not escapes me.
  -    //
  -    if (fReaderMgr.skippedChar(chCloseAngle)) {
  -        //
  -        //  If we have a doc type handler and advanced callbacks are enabled,
  -        //  call the doctype event.
  -        //
  -        if (fDocTypeHandler)
  -            fDocTypeHandler->doctypeDecl(*rootDecl, 0, 0, false);
  -        return;
  -    }
  -
  -    // either internal/external subset
  -    if (fValScheme == Val_Auto && !fValidate)
  -        fValidate = true;
  -
  -    bool    hasIntSubset = false;
  -    bool    hasExtSubset = false;
  -    XMLCh*  sysId = 0;
  -    XMLCh*  pubId = 0;
  -
  -    DTDScanner dtdScanner((DTDGrammar*)fGrammar, fDocTypeHandler);
  -    dtdScanner.setScannerInfo(this, &fReaderMgr, &fBufMgr);
  -
  -    //
  -    //  If the next character is '[' then we have no external subset cause
  -    //  there is no system id, just the opening character of the internal
  -    //  subset. Else, has to be an id.
  -    //
  -    // Just look at the next char, don't eat it.
  -    if (fReaderMgr.peekNextChar() == chOpenSquare)
  -    {
  -        hasIntSubset = true;
  -    }
  -     else
  -    {
  -        // Indicate we have an external subset
  -        hasExtSubset = true;
  -        fHasNoDTD = false;
  -
  -        // Get buffers for the ids
  -        XMLBufBid bbPubId(&fBufMgr);
  -        XMLBufBid bbSysId(&fBufMgr);
  -
  -        // Get the external subset id
  -        if (!dtdScanner.scanId(bbPubId.getBuffer(), bbSysId.getBuffer(), DTDScanner::IDType_External))
  -        {
  -            fReaderMgr.skipPastChar(chCloseAngle);
  -            return;
  -        }
  -
  -        // Get copies of the ids we got
  -        pubId = XMLString::replicate(bbPubId.getRawBuffer());
  -        sysId = XMLString::replicate(bbSysId.getRawBuffer());
  -
  -        // Skip spaces and check again for the opening of an internal subset
  -        fReaderMgr.skipPastSpaces();
  -
  -        // Just look at the next char, don't eat it.
  -        if (fReaderMgr.peekNextChar() == chOpenSquare) {
  -            hasIntSubset = true;
  -        }
  -    }
  -
  -    // Insure that the ids get cleaned up, if they got allocated
  -    ArrayJanitor<XMLCh> janSysId(sysId);
  -    ArrayJanitor<XMLCh> janPubId(pubId);
  -
  -    //
  -    //  If we have a doc type handler and advanced callbacks are enabled,
  -    //  call the doctype event.
  -    //
  -    if (fDocTypeHandler)
  -        fDocTypeHandler->doctypeDecl(*rootDecl, pubId, sysId, hasIntSubset, hasExtSubset);
  -
  -    //
  -    //  Ok, if we had an internal subset, we are just past the [ character
  -    //  and need to parse that first.
  -    //
  -    if (hasIntSubset)
  -    {
  -        // Eat the opening square bracket
  -        fReaderMgr.getNextChar();
  -
  -        // We can't have any internal subset if we are reusing the validator
  -        if (fUseCachedGrammar || fToCacheGrammar)
  -            ThrowXML(RuntimeException, XMLExcepts::Val_CantHaveIntSS);
  -
  -        //
  -        //  And try to scan the internal subset. If we fail, try to recover
  -        //  by skipping forward tot he close angle and returning.
  -        //
  -        if (!dtdScanner.scanInternalSubset())
  -        {
  -            fReaderMgr.skipPastChar(chCloseAngle);
  -            return;
  -        }
  -
  -        //
  -        //  Do a sanity check that some expanded PE did not propogate out of
  -        //  the doctype. This could happen if it was terminated early by bad
  -        //  syntax.
  -        //
  -        if (fReaderMgr.getReaderDepth() > 1)
  -        {
  -            emitError(XMLErrs::PEPropogated);
  -
  -            // Ask the reader manager to pop back down to the main level
  -            fReaderMgr.cleanStackBackTo(1);
  -        }
  -
  -        fReaderMgr.skipPastSpaces();
  -    }
  -
  -    // And that should leave us at the closing > of the DOCTYPE line
  -    if (!fReaderMgr.skippedChar(chCloseAngle))
  -    {
  -        //
  -        //  Do a special check for the common scenario of an extra ] char at
  -        //  the end. This is easy to recover from.
  -        //
  -        if (fReaderMgr.skippedChar(chCloseSquare)
  -        &&  fReaderMgr.skippedChar(chCloseAngle))
  -        {
  -            emitError(XMLErrs::ExtraCloseSquare);
  -        }
  -         else
  -        {
  -            emitError(XMLErrs::UnterminatedDOCTYPE);
  -            fReaderMgr.skipPastChar(chCloseAngle);
  -        }
  -    }
  -
  -    //
  -    //  If we had an external subset, then we need to deal with that one
  -    //  next. If we are reusing the validator, then don't scan it.
  -    //
  -    if (hasExtSubset) {
  -
  -        if (fUseCachedGrammar)
  -        {
  -            InputSource* sysIdSrc = resolveSystemId(sysId);
  -            Janitor<InputSource> janSysIdSrc(sysIdSrc);
  -            Grammar* grammar = fGrammarResolver->getGrammar(sysIdSrc->getSystemId());
  -
  -            if (grammar && grammar->getGrammarType() == Grammar::DTDGrammarType) {
  -
  -                fDTDGrammar = (DTDGrammar*) grammar;
  -                fGrammar = fDTDGrammar;
  -                fValidator->setGrammar(fGrammar);
  -                rootDecl = (DTDElementDecl*) fGrammar->getElemDecl(fEmptyNamespaceId, 0, bbRootName.getRawBuffer(), Grammar::TOP_LEVEL_SCOPE);
  -
  -                if (rootDecl)
  -                    ((DTDGrammar*)fGrammar)->setRootElemId(rootDecl->getId());
  -                else {
  -                    rootDecl = new DTDElementDecl(bbRootName.getRawBuffer(), fEmptyNamespaceId);
  -                    rootDecl->setCreateReason(DTDElementDecl::AsRootElem);
  -                    rootDecl->setExternalElemDeclaration(true);
  -                    ((DTDGrammar*)fGrammar)->setRootElemId(fGrammar->putElemDecl(rootDecl));
  -                }
  -
  -                return;
  -            }
  -        }
  -
  -        if (fLoadExternalDTD || fValidate)
  -        {
  -            // And now create a reader to read this entity
  -            InputSource* srcUsed;
  -            XMLReader* reader = fReaderMgr.createReader
  -            (
  -                sysId
  -                , pubId
  -                , false
  -                , XMLReader::RefFrom_NonLiteral
  -                , XMLReader::Type_General
  -                , XMLReader::Source_External
  -                , srcUsed
  -            );
  -
  -            // Put a janitor on the input source
  -            Janitor<InputSource> janSrc(srcUsed);
  -
  -            //
  -            //  If it failed then throw an exception
  -            //
  -            if (!reader)
  -                ThrowXML1(RuntimeException, XMLExcepts::Gen_CouldNotOpenDTD, srcUsed->getSystemId());
  -
  -            if (fToCacheGrammar) {
  -
  -                unsigned int stringId = fGrammarResolver->getStringPool()->addOrFind(srcUsed->getSystemId());
  -                const XMLCh* sysIdStr = fGrammarResolver->getStringPool()->getValueForId(stringId);
  -
  -                fGrammarResolver->orphanGrammar(XMLUni::fgDTDEntityString);
  -                fGrammarResolver->putGrammar(sysIdStr, fGrammar);
  -            }
  -
  -            //
  -            //  In order to make the processing work consistently, we have to
  -            //  make this look like an external entity. So create an entity
  -            //  decl and fill it in and push it with the reader, as happens
  -            //  with an external entity. Put a janitor on it to insure it gets
  -            //  cleaned up. The reader manager does not adopt them.
  -            //
  -            const XMLCh gDTDStr[] = { chLatin_D, chLatin_T, chLatin_D , chNull };
  -            DTDEntityDecl* declDTD = new DTDEntityDecl(gDTDStr);
  -            declDTD->setSystemId(sysId);
  -            Janitor<DTDEntityDecl> janDecl(declDTD);
  -
  -            // Mark this one as a throw at end
  -            reader->setThrowAtEnd(true);
  -
  -            // And push it onto the stack, with its pseudo name
  -            fReaderMgr.pushReader(reader, declDTD);
  -
  -            // Tell it its not in an include section
  -            dtdScanner.scanExtSubsetDecl(false);
  -        }
  -    }
  -}
  -
  -bool XMLScanner::scanStartTag(bool& gotData)
  -{
  -    //
  -    //  Assume we will still have data until proven otherwise. It will only
  -    //  ever be false if this is the root and its empty.
  -    //
  -    gotData = true;
  -
  -    //
  -    //  Get the QName. In this case, we are not doing namespaces, so we just
  -    //  use it as is and don't have to break it into parts.
  -    //
  -    if (!fReaderMgr.getName(fQNameBuf))
  -    {
  -        emitError(XMLErrs::ExpectedElementName);
  -        fReaderMgr.skipToChar(chOpenAngle);
  -        return false;
  -    }
  -
  -    // Assume it won't be an empty tag
  -    bool isEmpty = false;
  -
  -    //
  -    //  Lets try to look up the element in the validator's element decl pool
  -    //  We can pass bogus values for the URI id and the base name. We know that
  -    //  this can only be called if we are doing a DTD style validator and that
  -    //  he will only look at the QName.
  -    //
  -    //  We tell him to fault in a decl if he does not find one.
  -    //
  -    bool wasAdded = false;
  -    XMLElementDecl* elemDecl = fGrammar->findOrAddElemDecl
  -    (
  -        fEmptyNamespaceId
  -        , 0
  -        , 0
  -        , fQNameBuf.getRawBuffer()
  -        , Grammar::TOP_LEVEL_SCOPE
  -        , wasAdded
  -    );
  -
  -    //
  -    //  We do something different here according to whether we found the
  -    //  element or not.
  -    //
  -    if (wasAdded)
  -    {
  -        // If validating then emit an error
  -        if (fValidate)
  -        {
  -            // This is to tell the reuse Validator that this element was
  -            // faulted-in, was not an element in the validator pool originally
  -            elemDecl->setCreateReason(XMLElementDecl::JustFaultIn);
  -
  -            fValidator->emitError
  -            (
  -                XMLValid::ElementNotDefined
  -                , elemDecl->getFullName()
  -            );
  -        }
  -    }
  -     else
  -    {
  -        // If its not marked declared and validating, then emit an error
  -        if (fValidate && !elemDecl->isDeclared())
  -        {
  -            fValidator->emitError
  -            (
  -                XMLValid::ElementNotDefined
  -                , elemDecl->getFullName()
  -            );
  -        }
  -    }
  -
  -    // See if its the root element
  -    const bool isRoot = fElemStack.isEmpty();
  -
  -    // Expand the element stack and add the new element
  -    fElemStack.addLevel(elemDecl, fReaderMgr.getCurrentReaderNum());
  -    fElemStack.setValidationFlag(fValidate);
  -
  -    //  Validate the element
  -    if (fValidate)
  -        fValidator->validateElement(elemDecl);
  -
  -    //
  -    //  If this is the first element and we are validating, check the root
  -    //  element.
  -    //
  -    if (isRoot)
  -    {
  -        fRootGrammar = fGrammar;
  -
  -        if (fValidate)
  -        {
  -            //  If a DocType exists, then check if it matches the root name there.
  -            if (fRootElemName && !XMLString::equals(fQNameBuf.getRawBuffer(), fRootElemName))
  -                fValidator->emitError(XMLValid::RootElemNotLikeDocType);
  -
  -            //  Some validators may also want to check the root, call the
  -            //  XMLValidator::checkRootElement
  -            if (fValidatorFromUser && !fValidator->checkRootElement(elemDecl->getId()))
  -                fValidator->emitError(XMLValid::RootElemNotLikeDocType);
  -        }
  -    }
  -     else
  -    {
  -        //
  -        //  If the element stack is not empty, then add this element as a
  -        //  child of the previous top element. If its empty, this is the root
  -        //  elem and is not the child of anything.
  -        //
  -        fElemStack.addChild(elemDecl->getElementName(), true);
  -    }
  -
  -    //
  -    //  Ask the element decl to clear out the 'provided' flag on all of its
  -    //  att defs.
  -    //
  -    elemDecl->resetDefs();
  -
  -    // Skip any whitespace after the name
  -    fReaderMgr.skipPastSpaces();
  -
  -    //
  -    //  We loop until we either see a /> or >, handling attribute/value
  -    //  pairs until we get there.
  -    //
  -    unsigned int    attCount = 0;
  -    unsigned int    curAttListSize = fAttrList->size();
  -    while (true)
  -    {
  -        // And get the next non-space character
  -        XMLCh nextCh = fReaderMgr.peekNextChar();
  -
  -        //
  -        //  If the next character is not a slash or closed angle bracket,
  -        //  then it must be whitespace, since whitespace is required
  -        //  between the end of the last attribute and the name of the next
  -        //  one.
  -        //
  -        if (attCount)
  -        {
  -            if ((nextCh != chForwardSlash) && (nextCh != chCloseAngle))
  -            {
  -                if (XMLReader::isWhitespace(nextCh))
  -                {
  -                    // Ok, skip by them and peek another char
  -                    fReaderMgr.skipPastSpaces();
  -                    nextCh = fReaderMgr.peekNextChar();
  -                }
  -                 else
  -                {
  -                    // Emit the error but keep on going
  -                    emitError(XMLErrs::ExpectedWhitespace);
  -                }
  -            }
  -        }
  -
  -        //
  -        //  Ok, here we first check for any of the special case characters.
  -        //  If its not one, then we do the normal case processing, which
  -        //  assumes that we've hit an attribute value, Otherwise, we do all
  -        //  the special case checks.
  -        //
  -        if (!XMLReader::isSpecialStartTagChar(nextCh))
  -        {
  -            //
  -            //  Assume its going to be an attribute, so get a name from
  -            //  the input.
  -            //
  -            if (!fReaderMgr.getName(fAttNameBuf))
  -            {
  -                emitError(XMLErrs::ExpectedAttrName);
  -                fReaderMgr.skipPastChar(chCloseAngle);
  -                return false;
  -            }
  -
  -            // And next must be an equal sign
  -            if (!scanEq())
  -            {
  -                static const XMLCh tmpList[] =
  -                {
  -                    chSingleQuote, chDoubleQuote, chCloseAngle
  -                    , chOpenAngle, chForwardSlash, chNull
  -                };
  -
  -                emitError(XMLErrs::ExpectedEqSign);
  -
  -                //
  -                //  Try to sync back up by skipping forward until we either
  -                //  hit something meaningful.
  -                //
  -                const XMLCh chFound = fReaderMgr.skipUntilInOrWS(tmpList);
  -
  -                if ((chFound == chCloseAngle) || (chFound == chForwardSlash))
  -                {
  -                    // Jump back to top for normal processing of these
  -                    continue;
  -                }
  -                 else if ((chFound == chSingleQuote)
  -                      ||  (chFound == chDoubleQuote)
  -                      ||  XMLReader::isWhitespace(chFound))
  -                {
  -                    // Just fall through assuming that the value is to follow
  -                }
  -                 else if (chFound == chOpenAngle)
  -                {
  -                    // Assume a malformed tag and that new one is starting
  -                    emitError(XMLErrs::UnterminatedStartTag, elemDecl->getFullName());
  -                    return false;
  -                }
  -                 else
  -                {
  -                    // Something went really wrong
  -                    return false;
  -                }
  -            }
  -
  -            //
  -            //  See if this attribute is declared for this element. If we are
  -            //  not validating of course it will not be at first, but we will
  -            //  fault it into the pool (to avoid lots of redundant errors.)
  -            //
  -            wasAdded = false;
  -            XMLAttDef* attDef = elemDecl->findAttr
  -            (
  -                fAttNameBuf.getRawBuffer()
  -                , 0
  -                , 0
  -                , 0
  -                , XMLElementDecl::AddIfNotFound
  -                , wasAdded
  -            );
  -
  -            if (wasAdded)
  -            {
  -                //
  -                //  If there is a validation handler, then we are validating
  -                //  so emit an error.
  -                //
  -                if (fValidate)
  -                {
  -                    // This is to tell the Validator that this attribute was
  -                    // faulted-in, was not an attribute in the attdef originally
  -                    attDef->setCreateReason(XMLAttDef::JustFaultIn);
  -
  -                    fValidator->emitError
  -                    (
  -                        XMLValid::AttNotDefinedForElement
  -                        , fAttNameBuf.getRawBuffer()
  -                        , elemDecl->getFullName()
  -                    );
  -                }
  -            }
  -            else
  -            {
  -                // If this attribute was faulted-in and first occurence,
  -                // then emit an error
  -                if (fValidate && attDef->getCreateReason() == XMLAttDef::JustFaultIn
  -                    && !attDef->getProvided())
  -                {
  -                    fValidator->emitError
  -                    (
  -                        XMLValid::AttNotDefinedForElement
  -                        , fAttNameBuf.getRawBuffer()
  -                        , elemDecl->getFullName()
  -                    );
  -                }
  -            }
  -
  -            //
  -            //  If its already provided, then there are more than one of
  -            //  this attribute in this start tag, so emit an error.
  -            //
  -            if (attDef->getProvided())
  -            {
  -                emitError
  -                (
  -                    XMLErrs::AttrAlreadyUsedInSTag
  -                    , attDef->getFullName()
  -                    , elemDecl->getFullName()
  -                );
  -            }
  -             else
  -            {
  -                // Mark this one as already seen
  -                attDef->setProvided(true);
  -            }
  -
  -            //
  -            //  Skip any whitespace before the value and then scan the att
  -            //  value. This will come back normalized with entity refs and
  -            //  char refs expanded.
  -            //
  -            fReaderMgr.skipPastSpaces();
  -            if (!scanAttValue(attDef, fAttValueBuf))
  -            {
  -                static const XMLCh tmpList[] =
  -                {
  -                    chCloseAngle, chOpenAngle, chForwardSlash, chNull
  -                };
  -
  -                emitError(XMLErrs::ExpectedAttrValue);
  -
  -                //
  -                //  It failed, so lets try to get synced back up. We skip
  -                //  forward until we find some whitespace or one of the
  -                //  chars in our list.
  -                //
  -                const XMLCh chFound = fReaderMgr.skipUntilInOrWS(tmpList);
  -
  -                if ((chFound == chCloseAngle)
  -                ||  (chFound == chForwardSlash)
  -                ||  XMLReader::isWhitespace(chFound))
  -                {
  -                    //
  -                    //  Just fall through and process this attribute, though
  -                    //  the value will be "".
  -                    //
  -                }
  -                 else if (chFound == chOpenAngle)
  -                {
  -                    // Assume a malformed tag and that new one is starting
  -                    emitError(XMLErrs::UnterminatedStartTag, elemDecl->getFullName());
  -                    return false;
  -                }
  -                 else
  -                {
  -                    // Something went really wrong
  -                    return false;
  -                }
  -            }
  -
  -            //
  -            //  Now that its all stretched out, lets look at its type and
  -            //  determine if it has a valid value. It will output any needed
  -            //  errors, but we just keep going. We only need to do this if
  -            //  we are validating.
  -            //
  -            if (!wasAdded && attDef->getCreateReason() != XMLAttDef::JustFaultIn)
  -            {
  -                // Let the validator pass judgement on the attribute value
  -                if (fValidate)
  -                {
  -                    fValidator->validateAttrValue
  +                    fReaderMgr.getSpaces(bbCData.getBuffer());
  +                    fDocHandler->ignorableWhitespace
                       (
  -                        attDef
  -                        , fAttValueBuf.getRawBuffer()
  +                        bbCData.getRawBuffer()
  +                        , bbCData.getLen()
                           , false
  -                        , elemDecl
                       );
                   }
  -            }
  -
  -            //
  -            //  Add this attribute to the attribute list that we use to
  -            //  pass them to the handler. We reuse its existing elements
  -            //  but expand it as required.
  -            //
  -            XMLAttr* curAtt;
  -            if (attCount >= curAttListSize)
  -            {
  -                curAtt = new XMLAttr
  -                (
  -                    -1
  -                    , fAttNameBuf.getRawBuffer()
  -                    , XMLUni::fgZeroLenString
  -                    , fAttValueBuf.getRawBuffer()
  -                    , attDef->getType()
  -                    , true
  -                );
  -                fAttrList->addElement(curAtt);
  -            }
  -             else
  -            {
  -                curAtt = fAttrList->elementAt(attCount);
  -                curAtt->set
  -                (
  -                    -1
  -                    , fAttNameBuf.getRawBuffer()
  -                    , XMLUni::fgZeroLenString
  -                    , fAttValueBuf.getRawBuffer()
  -                    , attDef->getType()
  -                );
  -                curAtt->setSpecified(true);
  -            }
  -            attCount++;
  -
  -            // And jump back to the top of the loop
  -            continue;
  -        }
  -
  -        //
  -        //  It was some special case character so do all of the checks and
  -        //  deal with it.
  -        //
  -        if (!nextCh)
  -            ThrowXML(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF);
  -
  -        if (nextCh == chForwardSlash)
  -        {
  -            fReaderMgr.getNextChar();
  -            isEmpty = true;
  -            if (!fReaderMgr.skippedChar(chCloseAngle))
  -                emitError(XMLErrs::UnterminatedStartTag, elemDecl->getFullName());
  -            break;
  -        }
  -         else if (nextCh == chCloseAngle)
  -        {
  -            fReaderMgr.getNextChar();
  -            break;
  -        }
  -         else if (nextCh == chOpenAngle)
  -        {
  -            //
  -            //  Check for this one specially, since its going to be common
  -            //  and it is kind of auto-recovering since we've already hit the
  -            //  next open bracket, which is what we would have seeked to (and
  -            //  skipped this whole tag.)
  -            //
  -            emitError(XMLErrs::UnterminatedStartTag, elemDecl->getFullName());
  -            break;
  -        }
  -         else if ((nextCh == chSingleQuote) || (nextCh == chDoubleQuote))
  -        {
  -            //
  -            //  Check for this one specially, which is probably a missing
  -            //  attribute name, e.g. ="value". Just issue expected name
  -            //  error and eat the quoted string, then jump back to the
  -            //  top again.
  -            //
  -            emitError(XMLErrs::ExpectedAttrName);
  -            fReaderMgr.getNextChar();
  -            fReaderMgr.skipQuotedString(nextCh);
  -            fReaderMgr.skipPastSpaces();
  -            continue;
  -        }
  -    }
  -
  -    //
  -    //  Ok, so lets get an enumerator for the attributes of this element
  -    //  and run through them for well formedness and validity checks. But
  -    //  make sure that we had any attributes before we do it, since the list
  -    //  would have have gotten faulted in anyway.
  -    //
  -    if (elemDecl->hasAttDefs())
  -    {
  -        XMLAttDefList& attDefList = elemDecl->getAttDefList();
  -        while (attDefList.hasMoreElements())
  -        {
  -            // Get the current att def, for convenience and its def type
  -            const XMLAttDef& curDef = attDefList.nextElement();
  -            const XMLAttDef::DefAttTypes defType = curDef.getDefaultType();
  -
  -            if (!curDef.getProvided())
  -            {
  -                if (fValidate)
  -                {
  -                    // If we are validating and its required, then an error
  -                    if (defType == XMLAttDef::Required)
  -                    {
  -                        fValidator->emitError
  -                        (
  -                            XMLValid::RequiredAttrNotProvided
  -                            , curDef.getFullName()
  -                        );
  -                    }
  -                    else if ((defType == XMLAttDef::Default) ||
  -		                       (defType == XMLAttDef::Fixed)  )
  -                    {
  -                        if (fStandalone && curDef.isExternal())
  -                        {
  -                            //
  -                            // XML 1.0 Section 2.9
  -                            // Document is standalone, so attributes must not be defaulted.
  -                            //
  -                            fValidator->emitError(XMLValid::NoDefAttForStandalone, curDef.getFullName(), elemDecl->getFullName());
  -                        }
  -                    }
  -                }
  -
  -                // Fault in the value if needed, and bump the att count
  -                if ((defType == XMLAttDef::Default)
  -                ||  (defType == XMLAttDef::Fixed))
  +                else
                   {
  -                    // Let the validator pass judgement on the attribute value
  -                    if (fValidate)
  -                    {
  -                        fValidator->validateAttrValue
  -                        (
  -                            &curDef
  -                            , curDef.getValue()
  -                            , false
  -                            , elemDecl
  -                        );
  -                    }
  -
  -                    XMLAttr* curAtt;
  -                    if (attCount >= curAttListSize)
  -                    {
  -                        curAtt = new XMLAttr
  -                        (
  -                            -1
  -                            , curDef.getFullName()
  -                            , XMLUni::fgZeroLenString
  -                            , curDef.getValue()
  -                            , curDef.getType()
  -                            , false
  -                        );
  -                        fAttrList->addElement(curAtt);
  -                        curAttListSize++;
  -                    }
  -                     else
  -                    {
  -                        curAtt = fAttrList->elementAt(attCount);
  -                        curAtt->set
  -                        (
  -                            -1
  -                            , curDef.getFullName()
  -                            , XMLUni::fgZeroLenString
  -                            , curDef.getValue()
  -                            , curDef.getType()
  -                        );
  -                        curAtt->setSpecified(false);
  -                    }
  -                    attCount++;
  +                    fReaderMgr.skipPastSpaces();
                   }
               }
  -        }
  -    }
  -
  -    //
  -    //  If empty, validate content right now if we are validating and then
  -    //  pop the element stack top. Else, we have to update the current stack
  -    //  top's namespace mapping elements.
  -    //
  -    if (isEmpty)
  -    {
  -        // If validating, then insure that its legal to have no content
  -        if (fValidate)
  -        {
  -            const int res = fValidator->checkContent(elemDecl, 0, 0);
  -            if (res >= 0)
  +            else
               {
  -                fValidator->emitError
  -                (
  -                    XMLValid::ElementNotValidForContent
  -                    , elemDecl->getFullName()
  -                    , elemDecl->getFormattedContentModel()
  -                );
  +                emitError(XMLErrs::ExpectedCommentOrPI);
  +                fReaderMgr.skipPastChar(chCloseAngle);
               }
           }
  -
  -        // Pop the element stack back off since it'll never be used now
  -        fElemStack.popTop();
  -
  -        // If the elem stack is empty, then it was an empty root
  -        if (isRoot)
  -            gotData = false;
  -        else {
  -            // Restore the validation flag
  -            fValidate = fElemStack.getValidationFlag();
  +        catch(const EndOfEntityException&)
  +        {
  +            //  Some entity leaked out of the content part of the document. Issue
  +            //  a warning and keep going.
  +            emitError(XMLErrs::EntityPropogated);
           }
       }
  -
  -    //
  -    //  If we have a document handler, then tell it about this start tag. We
  -    //  don't have any URI id to send along, so send fEmptyNamespaceId. We also do not send
  -    //  any prefix since its just one big name if we are not doing namespaces.
  -    //
  -    if (fDocHandler)
  -    {
  -        fDocHandler->startElement
  -        (
  -            *elemDecl
  -            , fEmptyNamespaceId
  -            , 0
  -            , *fAttrList
  -            , attCount
  -            , isEmpty
  -            , isRoot
  -        );
  -    }
  -
  -    return true;
   }
   
   
  -//
  -//
  -//  This method is called to scan a start tag when we are processing
  -//  namespaces. There are two different versions of this method, one for
  -//  namespace aware processing an done for non-namespace aware processing.
  -//
  -//  This method is called after we've scanned the < of a start tag. So we
  -//  have to get the element name, then scan the attributes, after which
  -//  we are either going to see >, />, or attributes followed by one of those
  -//  sequences.
  -//
  -bool XMLScanner::scanStartTagNS(bool& gotData)
  +//  Scans a PI and calls the appropriate callbacks. At entry we have just
  +//  scanned the <? part, and need to now start on the PI target name.
  +void XMLScanner::scanPI()
   {
  -    //
  -    //  Assume we will still have data until proven otherwise. It will only
  -    //  ever be false if this is the root and its empty.
  -    //
  -    gotData = true;
  +    const XMLCh* namePtr = 0;
  +    const XMLCh* targetPtr = 0;
   
  -    //
  -    //  The current position is after the open bracket, so we need to read in
  -    //  in the element name.
  -    //
  -    if (!fReaderMgr.getName(fQNameBuf))
  +    //  If there are any spaces here, then warn about it. If we aren't in
  +    //  'first error' mode, then we'll come back and can easily pick up
  +    //  again by just skipping them.
  +    if (fReaderMgr.lookingAtSpace())
       {
  -        emitError(XMLErrs::ExpectedElementName);
  -        fReaderMgr.skipToChar(chOpenAngle);
  -        return false;
  +        emitError(XMLErrs::PINameExpected);
  +        fReaderMgr.skipPastSpaces();
       }
   
  -    //
  -    //  Do a little sanity check here. One common problem is that
  -    //  badly encoded files cause getName() to exit above on a
  -    //  non-name char (an invalid XML char), then the scan start
  -    //  tag below fails. This is misleading, so check here that
  -    //  we are looking at a valid XML char.
  -    //
  -    if (!XMLReader::isXMLChar(fReaderMgr.peekNextChar()))
  +    // Get a buffer for the PI name and scan it in
  +    XMLBufBid bbName(&fBufMgr);
  +    if (!fReaderMgr.getName(bbName.getBuffer()))
       {
  -        XMLCh tmpBuf[9];
  -        XMLString::binToText
  -        (
  -            fReaderMgr.getNextChar()
  -            , tmpBuf
  -            , 8
  -            , 16
  -        );
  -        emitError(XMLErrs::InvalidCharacter, tmpBuf);
  -    }
  -
  -    // See if its the root element
  -    const bool isRoot = fElemStack.isEmpty();
  -
  -    // Skip any whitespace after the name
  -    fReaderMgr.skipPastSpaces();
  -
  -    //
  -    //  First we have to do the rawest attribute scan. We don't do any
  -    //  normalization of them at all, since we don't know yet what type they
  -    //  might be (since we need the element decl in order to do that.)
  -    //
  -    bool isEmpty;
  -    unsigned int attCount = rawAttrScan
  -    (
  -        fQNameBuf.getRawBuffer()
  -        , *fRawAttrList
  -        , isEmpty
  -    );
  -    const bool gotAttrs = (attCount != 0);
  -
  -    // save the contentleafname and currentscope before addlevel, for later use
  -    ContentLeafNameTypeVector* cv = 0;
  -    XMLContentModel* cm = 0;
  -    int currentScope = Grammar::TOP_LEVEL_SCOPE;
  -    if (!isRoot && fGrammarType == Grammar::SchemaGrammarType) {
  -        SchemaElementDecl* tempElement = (SchemaElementDecl*) fElemStack.topElement()->fThisElement;
  -        SchemaElementDecl::ModelTypes modelType = tempElement->getModelType();
  -
  -        if ((modelType == SchemaElementDecl::Mixed_Simple)
  -          ||  (modelType == SchemaElementDecl::Mixed_Complex)
  -          ||  (modelType == SchemaElementDecl::Children))
  -        {
  -            cm = tempElement->getContentModel();
  -            cv = cm->getContentLeafNameTypeVector();
  -            currentScope = fElemStack.getCurrentScope();
  -        }
  -    }
  -
  -    //
  -    //  Now, since we might have to update the namespace map for this element,
  -    //  but we don't have the element decl yet, we just tell the element stack
  -    //  to expand up to get ready.
  -    //
  -    unsigned int elemDepth = fElemStack.addLevel();
  -    fElemStack.setValidationFlag(fValidate);
  -
  -    //  Check if there is any external schema location specified, and if we are at root,
  -    //  go through them first before scanning those specified in the instance document
  -    if (isRoot
  -        && fDoSchema
  -        && (fExternalSchemaLocation || fExternalNoNamespaceSchemaLocation)) {
  -
  -        if (fExternalSchemaLocation)
  -            parseSchemaLocation(fExternalSchemaLocation);
  -        if (fExternalNoNamespaceSchemaLocation)
  -            resolveSchemaGrammar(fExternalNoNamespaceSchemaLocation, XMLUni::fgZeroLenString);
  -    }
  -
  -    //
  -    //  Make an initial pass through the list and find any xmlns attributes or
  -    //  schema attributes.
  -    //
  -    if (attCount)
  -      scanRawAttrListforNameSpaces(fRawAttrList, attCount);
  -
  -    //
  -    //  Also find any default or fixed xmlns attributes in DTD defined for
  -    //  this element.
  -    //
  -    if (fGrammarType == Grammar::DTDGrammarType) {
  -        XMLElementDecl* elemDecl = fGrammar->getElemDecl
  -        (
  -            fEmptyNamespaceId
  -            , 0
  -            , fQNameBuf.getRawBuffer()
  -            , Grammar::TOP_LEVEL_SCOPE
  -        );
  -        if (elemDecl) {
  -            if (elemDecl->hasAttDefs()) {
  -                XMLAttDefList& attDefList = elemDecl->getAttDefList();
  -                while (attDefList.hasMoreElements())
  -                {
  -                    // Get the current att def, for convenience and its def type
  -                    const XMLAttDef& curDef = attDefList.nextElement();
  -                    const XMLAttDef::DefAttTypes defType = curDef.getDefaultType();
  -
  -                    // update the NSMap if there are any default/fixed xmlns attributes
  -                    if ((defType == XMLAttDef::Default)
  -                    ||  (defType == XMLAttDef::Fixed))
  -                    {
  -                        const XMLCh* rawPtr = curDef.getFullName();
  -                        if (!XMLString::compareNString(rawPtr, XMLUni::fgXMLNSColonString, 6)
  -                        ||  XMLString::equals(rawPtr, XMLUni::fgXMLNSString))
  -                            updateNSMap(rawPtr, curDef.getValue());
  -                    }
  -                }
  -            }
  -        }
  -    }
  -
  -    //
  -    //  Resolve the qualified name to a URI and name so that we can look up
  -    //  the element decl for this element. We have now update the prefix to
  -    //  namespace map so we should get the correct element now.
  -    //
  -    unsigned int uriId = resolveQName
  -        (
  -            fQNameBuf.getRawBuffer()
  -            , fNameBuf
  -            , fPrefixBuf
  -            , ElemStack::Mode_Element
  -        );
  -
  -    //if schema, check if we should lax or skip the validation of this element
  -    bool laxThisOne = false;
  -    if (cv) {
  -        QName element(fPrefixBuf.getRawBuffer(), fNameBuf.getRawBuffer(), uriId);
  -        // elementDepth will be > 0, as cv is only constructed if element is not
  -        // root.
  -        laxThisOne = laxElementValidation(&element, cv, cm, elemDepth - 1);
  -    }
  -
  -    //
  -    //  Look up the element now in the grammar. This will get us back a
  -    //  generic element decl object. We tell him to fault one in if he does
  -    //  not find it.
  -    //
  -    bool wasAdded = false;
  -    XMLElementDecl* elemDecl;
  -    const XMLCh* nameRawBuf = fNameBuf.getRawBuffer();
  -    const XMLCh* qnameRawBuf = fQNameBuf.getRawBuffer();
  -
  -    if (uriId != fEmptyNamespaceId) {
  -
  -        // Check in current grammar before switching if necessary
  -        elemDecl = fGrammar->getElemDecl
  -        (
  -          uriId
  -          , nameRawBuf
  -          , qnameRawBuf
  -          , currentScope
  -        );
  -
  -        if (!elemDecl && (fURIStringPool->getId(fGrammar->getTargetNamespace()) != uriId)) {
  -            // not found, switch to the specified grammar
  -            const XMLCh* uriStr = getURIText(uriId);
  -            if (!switchGrammar(uriStr) && fValidate && !laxThisOne)
  -            {
  -                fValidator->emitError
  -                (
  -                    XMLValid::GrammarNotFound
  -                    ,uriStr
  -                );
  -            }
  -
  -            elemDecl = fGrammar->getElemDecl
  -            (
  -              uriId
  -              , nameRawBuf
  -              , qnameRawBuf
  -              , currentScope
  -            );
  -        }
  -
  -        if (!elemDecl && currentScope != Grammar::TOP_LEVEL_SCOPE) {
  -            // if not found, then it may be a reference, try TOP_LEVEL_SCOPE
  -            elemDecl = fGrammar->getElemDecl
  -                       (
  -                           uriId
  -                           , nameRawBuf
  -                           , qnameRawBuf
  -                           , Grammar::TOP_LEVEL_SCOPE
  -                       );
  -
  -            if(!elemDecl) {
  -                // still not found in specified uri
  -                // try emptyNamesapce see if element should be un-qualified.
  -                elemDecl = fGrammar->getElemDecl
  -                           (
  -                               fEmptyNamespaceId
  -                               , nameRawBuf
  -                               , qnameRawBuf
  -                               , currentScope
  -                           );
  -
  -                if (elemDecl && elemDecl->getCreateReason() != XMLElementDecl::JustFaultIn && fValidate) {
  -                    fValidator->emitError
  -                    (
  -                        XMLValid::ElementNotUnQualified
  -                        , elemDecl->getFullName()
  -                    );
  -                }
  -            }
  -        }
  -
  -        if (!elemDecl) {
  -            // still not found, fault this in and issue error later
  -            elemDecl = fGrammar->putElemDecl(uriId
  -                        , nameRawBuf
  -                        , fPrefixBuf.getRawBuffer()
  -                        , qnameRawBuf
  -                        , currentScope
  -                        , true);
  -            wasAdded = true;
  -        }
  +        emitError(XMLErrs::PINameExpected);
  +        fReaderMgr.skipPastChar(chCloseAngle);
  +        return;
       }
  -    else
  -    {
  -        //the element has no prefix,
  -        //thus it is either a non-qualified element defined in current targetNS
  -        //or an element that is defined in the globalNS
  -
  -        //try unqualifed first
  -        elemDecl = fGrammar->getElemDecl
  -                   (
  -                      uriId
  -                    , nameRawBuf
  -                    , qnameRawBuf
  -                    , currentScope
  -                    );
  -
  -        unsigned orgGrammarUri = fURIStringPool->getId(fGrammar->getTargetNamespace());
  -
  -        if (!elemDecl && orgGrammarUri != fEmptyNamespaceId) {
  -            //not found, switch grammar and try globalNS
  -            if (!switchGrammar(XMLUni::fgZeroLenString) && fValidate && !laxThisOne)
  -            {
  -                fValidator->emitError
  -                (
  -                    XMLValid::GrammarNotFound
  -                  , XMLUni::fgZeroLenString
  -                );
  -            }
  -
  -            elemDecl = fGrammar->getElemDecl
  -            (
  -              uriId
  -              , nameRawBuf
  -              , qnameRawBuf
  -              , currentScope
  -            );
  -        }
  -
  -        if (!elemDecl && currentScope != Grammar::TOP_LEVEL_SCOPE) {
  -            // if not found, then it may be a reference, try TOP_LEVEL_SCOPE
  -            elemDecl = fGrammar->getElemDecl
  -                       (
  -                           uriId
  -                           , nameRawBuf
  -                           , qnameRawBuf
  -                           , Grammar::TOP_LEVEL_SCOPE
  -                       );
  -
  -            if (!elemDecl && orgGrammarUri != fEmptyNamespaceId) {
  -                // still Not found in specified uri
  -                // go to original Grammar again to see if element needs to be fully qualified.
  -                const XMLCh* uriStr = getURIText(orgGrammarUri);
  -                if (!switchGrammar(uriStr) && fValidate && !laxThisOne)
  -                {
  -                    fValidator->emitError
  -                    (
  -                        XMLValid::GrammarNotFound
  -                        ,uriStr
  -                    );
  -                }
   
  -                elemDecl = fGrammar->getElemDecl
  -                           (
  -                               orgGrammarUri
  -                               , nameRawBuf
  -                               , qnameRawBuf
  -                               , currentScope
  -                           );
  +    // Point the name pointer at the raw data
  +    namePtr = bbName.getRawBuffer();
   
  -                if (elemDecl && elemDecl->getCreateReason() != XMLElementDecl::JustFaultIn && fValidate) {
  -                    fValidator->emitError
  -                    (
  -                        XMLValid::ElementNotQualified
  -                        , elemDecl->getFullName()
  -                    );
  -                }
  -            }
  -        }
  +    // See if it is some form of 'xml' and emit a warning
  +    if (!XMLString::compareIString(namePtr, XMLUni::fgXMLString))
  +        emitError(XMLErrs::NoPIStartsWithXML);
   
  -        if (!elemDecl) {
  -            // still not found, fault this in and issue error later
  -            elemDecl = fGrammar->putElemDecl(uriId
  -                        , nameRawBuf
  -                        , fPrefixBuf.getRawBuffer()
  -                        , qnameRawBuf
  -                        , currentScope
  -                        , true);
  -            wasAdded = true;
  -        }
  +    // If namespaces are enabled, then no colons allowed
  +    if (fDoNamespaces)
  +    {
  +        if (XMLString::indexOf(namePtr, chColon) != -1)
  +            emitError(XMLErrs::ColonNotLegalWithNS);
       }
   
  -    //
  -    //  We do something different here according to whether we found the
  -    //  element or not.
  -    //
  -    if (wasAdded)
  +    //  If we don't hit a space next, then the PI has no target. If we do
  +    //  then get out the target. Get a buffer for it as well
  +    XMLBufBid bbTarget(&fBufMgr);
  +    if (fReaderMgr.skippedSpace())
       {
  -        if (laxThisOne) {
  -            fValidate = false;
  -            fElemStack.setValidationFlag(fValidate);
  -        }
  +        // Skip any leading spaces
  +        fReaderMgr.skipPastSpaces();
  +
  +        bool gotLeadingSurrogate = false;
   
  -        // If validating then emit an error
  -        if (fValidate)
  +        // It does have a target, so lets move on to deal with that.
  +        while (1)
           {
  -            // This is to tell the reuse Validator that this element was
  -            // faulted-in, was not an element in the grammar pool originally
  -            elemDecl->setCreateReason(XMLElementDecl::JustFaultIn);
  +            const XMLCh nextCh = fReaderMgr.getNextChar();
   
  -            fValidator->emitError
  -            (
  -                XMLValid::ElementNotDefined
  -                , elemDecl->getFullName()
  -            );
  -        }
  -    }
  -     else
  -    {
  -        // If its not marked declared and validating, then emit an error
  -        if (!elemDecl->isDeclared()) {
  -            if (laxThisOne) {
  -                fValidate = false;
  -                fElemStack.setValidationFlag(fValidate);
  +            // Watch for an end of file, which is always bad here
  +            if (!nextCh)
  +            {
  +                emitError(XMLErrs::UnterminatedPI);
  +                ThrowXML(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF);
               }
   
  -             if (fValidate)
  +            // Watch for potential terminating character
  +            if (nextCh == chQuestion)
               {
  -                fValidator->emitError
  -                (
  -                    XMLValid::ElementNotDefined
  -                    , elemDecl->getFullName()
  -                );
  +                // It must be followed by '>' to be a termination of the target
  +                if (fReaderMgr.skippedChar(chCloseAngle))
  +                    break;
               }
  -        }
   
  -        if (fGrammarType == Grammar::SchemaGrammarType)
  -            ((SchemaElementDecl*)elemDecl)->setXsiComplexTypeInfo(0);
  -    }
  -
  -    //
  -    //  Now we can update the element stack to set the current element
  -    //  decl. We expanded the stack above, but couldn't store the element
  -    //  decl because we didn't know it yet.
  -    //
  -    fElemStack.setElement(elemDecl, fReaderMgr.getCurrentReaderNum());
  -    fElemStack.setCurrentURI(uriId);
  -
  -    if (isRoot)
  -        fRootGrammar = fGrammar;
  +            // Check for correct surrogate pairs
  +            if ((nextCh >= 0xD800) && (nextCh <= 0xDBFF))
  +            {
  +                if (gotLeadingSurrogate)
  +                    emitError(XMLErrs::Expected2ndSurrogateChar);
  +                else
  +                    gotLeadingSurrogate = true;
  +            }
  +             else
  +            {
  +                if (gotLeadingSurrogate)
  +                {
  +                    if ((nextCh < 0xDC00) || (nextCh > 0xDFFF))
  +                        emitError(XMLErrs::Expected2ndSurrogateChar);
  +                }
  +                // Its got to at least be a valid XML character
  +                else if (!XMLReader::isXMLChar(nextCh)) {
   
  -    //  Validate the element
  -    if (fValidate)
  -        fValidator->validateElement(elemDecl);
  -
  -    if (fGrammarType == Grammar::SchemaGrammarType) {
  -        ComplexTypeInfo* typeinfo = ((SchemaElementDecl*)elemDecl)->getComplexTypeInfo();
  -        if (typeinfo) {
  -            currentScope = typeinfo->getScopeDefined();
  -
  -            // switch grammar if the typeinfo has a different grammar (happens when there is xsi:type)
  -            XMLCh* typeName = typeinfo->getTypeName();
  -            const XMLCh poundStr[] = {chPound, chNull};
  -            if (!XMLString::startsWith(typeName, poundStr)) {
  -                const int comma = XMLString::indexOf(typeName, chComma);
  -                if (comma > 0) {
  -                    XMLBuffer prefixBuf(comma+1);
  -                    prefixBuf.append(typeName, comma);
  -                    const XMLCh* uriStr = prefixBuf.getRawBuffer();
  -                    if (!switchGrammar(uriStr) && fValidate && !laxThisOne)
  -                    {
  -                        fValidator->emitError
  -                        (
  -                            XMLValid::GrammarNotFound
  -                            , prefixBuf.getRawBuffer()
  -                        );
  -                    }
  +                    XMLCh tmpBuf[9];
  +                    XMLString::binToText
  +                    (
  +                        nextCh
  +                        , tmpBuf
  +                        , 8
  +                        , 16
  +                    );
  +                    emitError(XMLErrs::InvalidCharacter, tmpBuf);
                   }
  +
  +                gotLeadingSurrogate = false;
               }
  -        }
  -        fElemStack.setCurrentScope(currentScope);
   
  -        // Set element next state
  -        if (elemDepth >= fElemStateSize) {
  -            resizeElemState();
  +            bbTarget.append(nextCh);
           }
  -
  -        fElemState[elemDepth] = 0;
  -
       }
  -
  -    fElemStack.setCurrentGrammar(fGrammar);
  -
  -    //
  -    //  If this is the first element and we are validating, check the root
  -    //  element.
  -    //
  -    if (isRoot)
  +    else
       {
  -        if (fValidate)
  +        // No target, but make sure its terminated ok
  +        if (!fReaderMgr.skippedChar(chQuestion))
           {
  -            //  If a DocType exists, then check if it matches the root name there.
  -            if (fRootElemName && !XMLString::equals(qnameRawBuf, fRootElemName))
  -                fValidator->emitError(XMLValid::RootElemNotLikeDocType);
  -
  -            //  Some validators may also want to check the root, call the
  -            //  XMLValidator::checkRootElement
  -            if (fValidatorFromUser && !fValidator->checkRootElement(elemDecl->getId()))
  -                fValidator->emitError(XMLValid::RootElemNotLikeDocType);
  +            emitError(XMLErrs::UnterminatedPI);
  +            fReaderMgr.skipPastChar(chCloseAngle);
  +            return;
           }
  -    }
  -     else
  -    {
  -        //
  -        //  If the element stack is not empty, then add this element as a
  -        //  child of the previous top element. If its empty, this is the root
  -        //  elem and is not the child of anything.
  -        //
  -        fElemStack.addChild(elemDecl->getElementName(), true);
  -    }
  -
  -    //
  -    //  Now lets get the fAttrList filled in. This involves faulting in any
  -    //  defaulted and fixed attributes and normalizing the values of any that
  -    //  we got explicitly.
  -    //
  -    //  We update the attCount value with the total number of attributes, but
  -    //  it goes in with the number of values we got during the raw scan of
  -    //  explictly provided attrs above.
  -    //
  -    attCount = buildAttList(*fRawAttrList, attCount, elemDecl, *fAttrList);
   
  -    //
  -    // activate identity constraints
  -    //
  -    if (fValidate && fGrammar && fGrammarType == Grammar::SchemaGrammarType) {
  -
  -        unsigned int count = ((SchemaElementDecl*) elemDecl)->getIdentityConstraintCount();
  -
  -        if (count || fMatcherStack->getMatcherCount()) {
  -
  -            fValueStoreCache->startElement();
  -            fMatcherStack->pushContext();
  -            fValueStoreCache->initValueStoresFor((SchemaElementDecl*) elemDecl, (int) elemDepth);
  -
  -            for (unsigned int i = 0; i < count; i++) {
  -                activateSelectorFor(((SchemaElementDecl*) elemDecl)->getIdentityConstraintAt(i), (int) elemDepth);
  -            }
  -
  -            // call all active identity constraints
  -            count = fMatcherStack->getMatcherCount();
  -
  -            for (unsigned int j = 0; j < count; j++) {
  -
  -                XPathMatcher* matcher = fMatcherStack->getMatcherAt(j);
  -                matcher->startElement(*elemDecl, uriId, fPrefixBuf.getRawBuffer(), *fAttrList, attCount);
  -            }
  +        if (!fReaderMgr.skippedChar(chCloseAngle))
  +        {
  +            emitError(XMLErrs::UnterminatedPI);
  +            fReaderMgr.skipPastChar(chCloseAngle);
  +            return;
           }
       }
   
  -    // Since the element may have default values, call start tag now regardless if it is empty or not
  -    // If we have a document handler, then tell it about this start tag
  +    // Point the target pointer at the raw data
  +    targetPtr = bbTarget.getRawBuffer();
  +
  +    // If we have a handler, then call it
       if (fDocHandler)
       {
  -        fDocHandler->startElement
  +        fDocHandler->docPI
           (
  -            *elemDecl
  -            , uriId
  -            , fPrefixBuf.getRawBuffer()
  -            , *fAttrList
  -            , attCount
  -            , false
  -            , isRoot
  -        );
  +            namePtr
  +            , targetPtr
  +       );
       }
  +}
   
  -    //
  -    //  If empty, validate content right now if we are validating and then
  -    //  pop the element stack top. Else, we have to update the current stack
  -    //  top's namespace mapping elements.
  -    //
  -    if (isEmpty)
  -    {
  -        // Pop the element stack back off since it'll never be used now
  -        fElemStack.popTop();
  +//  Scans all the input from the start of the file to the root element.
  +//  There does not have to be anything in the prolog necessarily, but usually
  +//  there is at least an XMLDecl.
  +//
  +//  On exit from here we are either at the end of the file or about to read
  +//  the opening < of the root element.
  +void XMLScanner::scanProlog()
  +{
  +    // Get a buffer for whitespace processing
  +    XMLBufBid bbCData(&fBufMgr);
   
  -        // If validating, then insure that its legal to have no content
  -        if (fValidate)
  +    //  Loop through the prolog. If there is no content, this could go all
  +    //  the way to the end of the file.
  +    try
  +    {
  +        while (true)
           {
  -            const int res = fValidator->checkContent(elemDecl, 0, 0);
  -            if (res >= 0)
  -            {
  -                fValidator->emitError
  -                (
  -                    XMLValid::ElementNotValidForContent
  -                    , elemDecl->getFullName()
  -                    , elemDecl->getFormattedContentModel()
  -                );
  -            }
  -
  -            if (fGrammarType == Grammar::SchemaGrammarType) {
  -
  -                // reset xsi:type ComplexTypeInfo
  -                ((SchemaElementDecl*)elemDecl)->setXsiComplexTypeInfo(0);
  -
  -                // call matchers and de-activate context
  -                int oldCount = fMatcherStack->getMatcherCount();
  -
  -                if (oldCount || ((SchemaElementDecl*) elemDecl)->getIdentityConstraintCount()) {
  -
  -                    for (int i = oldCount - 1; i >= 0; i--) {
  -
  -                        XPathMatcher* matcher = fMatcherStack->getMatcherAt(i);
  -                        matcher->endElement(*elemDecl);
  -                    }
  -
  -                    if (fMatcherStack->size() > 0) {
  -                        fMatcherStack->popContext();
  -                    }
  -
  -                    // handle everything *but* keyref's.
  -                    int newCount = fMatcherStack->getMatcherCount();
  -
  -                    for (int j = oldCount - 1; j >= newCount; j--) {
  -
  -                        XPathMatcher* matcher = fMatcherStack->getMatcherAt(j);
  -                        IdentityConstraint* ic = matcher->getIdentityConstraint();
  +            const XMLCh nextCh = fReaderMgr.peekNextChar();
   
  -                        if (ic  && (ic->getType() != IdentityConstraint::KEYREF)) {
  -
  -                            matcher->endDocumentFragment();
  -                            fValueStoreCache->transplant(ic, matcher->getInitialDepth());
  -                        }
  -                        else if (!ic) {
  -                            matcher->endDocumentFragment();
  -                        }
  +            if (nextCh == chOpenAngle)
  +            {
  +                //  Ok, it could be the xml decl, a comment, the doc type line,
  +                //  or the start of the root element.
  +                if (checkXMLDecl(true))
  +                {
  +                    // There shall be at lease --ONE-- space in between
  +                    // the tag '<?xml' and the VersionInfo.
  +                    //
  +                    //  If we are not at line 1, col 6, then the decl was not
  +                    //  the first text, so its invalid.
  +                    const XMLReader* curReader = fReaderMgr.getCurrentReader();
  +                    if ((curReader->getLineNumber() != 1)
  +                    ||  (curReader->getColumnNumber() != 7))
  +                    {
  +                        emitError(XMLErrs::XMLDeclMustBeFirst);
                       }
   
  -                    // now handle keyref's...
  -                    for (int k = oldCount - 1; k >= newCount; k--) {
  -
  -                        XPathMatcher* matcher = fMatcherStack->getMatcherAt(k);
  -                        IdentityConstraint* ic = matcher->getIdentityConstraint();
  -
  -                        if (ic && (ic->getType() == IdentityConstraint::KEYREF)) {
  -
  -                            ValueStore* values = fValueStoreCache->getValueStoreFor(ic, matcher->getInitialDepth());
  -
  -                            if (values) { // nothing to do if nothing matched!
  -                                values->endDcocumentFragment(fValueStoreCache);
  -                            }
  +                    scanXMLDecl(Decl_XML);
  +                }
  +                else if (fReaderMgr.skippedString(XMLUni::fgPIString))
  +                {
  +                    scanPI();
  +                }
  +                 else if (fReaderMgr.skippedString(XMLUni::fgCommentString))
  +                {
  +                    scanComment();
  +                }
  +                 else if (fReaderMgr.skippedString(XMLUni::fgDocTypeString))
  +                {
  +                    scanDocTypeDecl();
   
  -                            matcher->endDocumentFragment();
  -                        }
  +                    // if reusing grammar, this has been validated already in first scan
  +                    // skip for performance
  +                    if (fValidate && !fGrammar->getValidated()) {
  +                        //  validate the DTD scan so far
  +                        fValidator->preContentValidation(fUseCachedGrammar, true);
                       }
  -
  -                    fValueStoreCache->endElement();
                   }
  -            }
  -        }
  -
  -        // If we have a doc handler, tell it about the end tag
  -        if (fDocHandler)
  -        {
  -            fDocHandler->endElement
  -            (
  -                *elemDecl
  -                , uriId
  -                , isRoot
  -                , fPrefixBuf.getRawBuffer()
  -            );
  -        }
  -
  -        // If the elem stack is empty, then it was an empty root
  -        if (isRoot)
  -            gotData = false;
  -        else
  -        {
  -            // Restore the grammar
  -            fGrammar = fElemStack.getCurrentGrammar();
  -            fGrammarType = fGrammar->getGrammarType();
  -            if (fGrammarType == Grammar::SchemaGrammarType && !fValidator->handlesSchema()) {
  -                if (fValidatorFromUser)
  -                    ThrowXML(RuntimeException, XMLExcepts::Gen_NoSchemaValidator);
  -                else {
  -                    fValidator = fSchemaValidator;
  +                else
  +                {
  +                    // Assume its the start of the root element
  +                    return;
                   }
               }
  -            else if (fGrammarType == Grammar::DTDGrammarType && !fValidator->handlesDTD()) {
  -                if (fValidatorFromUser)
  -                    ThrowXML(RuntimeException, XMLExcepts::Gen_NoDTDValidator);
  -                else {
  -                    fValidator = fDTDValidator;
  +            else if (XMLReader::isWhitespace(nextCh))
  +            {
  +                //  If we have a document handler then gather up the
  +                //  whitespace and call back. Otherwise just skip over spaces.
  +                if (fDocHandler)
  +                {
  +                    fReaderMgr.getSpaces(bbCData.getBuffer());
  +                    fDocHandler->ignorableWhitespace
  +                    (
  +                        bbCData.getRawBuffer()
  +                        , bbCData.getLen()
  +                        , false
  +                    );
  +                }
  +                 else
  +                {
  +                    fReaderMgr.skipPastSpaces();
                   }
               }
  +             else
  +            {
  +                emitError(XMLErrs::InvalidDocumentStructure);
   
  -            fValidator->setGrammar(fGrammar);
  +                // Watch for end of file and break out
  +                if (!nextCh)
  +                    break;
  +                else
  +                    fReaderMgr.skipPastChar(chCloseAngle);
  +            }
   
  -            // Restore the validation flag
  -            fValidate = fElemStack.getValidationFlag();
           }
       }
  -
  -    return true;
  +    catch(const EndOfEntityException&)
  +    {
  +        //  We should never get an end of entity here. They should only
  +        //  occur within the doc type scanning method, and not leak out to
  +        //  here.
  +        emitError
  +        (
  +            XMLErrs::UnexpectedEOE
  +            , "in prolog"
  +        );
  +    }
   }
   
   
  -//
   //  Scans the <?xml .... ?> line. This stuff is all sequential so we don't
   //  do any state machine loop here. We just bull straight through it. It ends
   //  past the closing bracket. If there is a document handler, then its called
  @@ -3860,7 +1123,6 @@
   //  The parameter tells us which type of decl we should expect, Text or XML.
   //    [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
   //    [77] TextDecl::= '<?xml' VersionInfo? EncodingDecl S? '?>'
  -//
   void XMLScanner::scanXMLDecl(const DeclTypes type)
   {
       // Get us some buffers to use
  @@ -3870,12 +1132,10 @@
       XMLBufBid bbDummy(&fBufMgr);
       XMLBufBid bbName(&fBufMgr);
   
  -    //
       //  We use this little enum and array to keep up with what we found
       //  and what order we found them in. This lets us get them free form
       //  without too much overhead, but still know that they were in the
       //  wrong order.
  -    //
       enum Strings
       {
           VersionString
  @@ -3887,10 +1147,8 @@
       };
       int flags[StringCount] = { -1, -1, -1, -1 };
   
  -    //
       //  Also set up a list of buffers in the right order so that we know
       //  where to put stuff.
  -    //
       XMLBuffer* buffers[StringCount] ;
       buffers[0] = &bbVersion.getBuffer();
       buffers[1] = &bbEncoding.getBuffer();
  @@ -3913,9 +1171,7 @@
           if (!spaceCount && curCount)
               emitError(XMLErrs::ExpectedWhitespace);
   
  -        //
           //  Get characters up to the next whitespace or equal's sign.
  -        //
           if (!scanUpToWSOr(nameBuf, chEqual))
               emitError(XMLErrs::ExpectedDeclString);
   
  @@ -3929,10 +1185,8 @@
           else
               curString = UnknownString;
   
  -        //
           //  If its an unknown string, then give that error. Else check to
           //  see if this one has been done already and give that error.
  -        //
           if (curString == UnknownString)
               emitError(XMLErrs::ExpectedDeclString, nameBuf.getRawBuffer());
           else if (flags[curString] != -1)
  @@ -3940,17 +1194,13 @@
           else if (flags[curString] == -1)
               flags[curString] = ++curCount;
   
  -        //
           //  Scan for an equal's sign. If we don't find it, issue an error
           //  but keep trying to go on.
  -        //
           if (!scanEq())
               emitError(XMLErrs::ExpectedEqSign);
   
  -        //
           //  Get a quote string into the buffer for the string that we are
           //  currently working on.
  -        //
           if (!getQuotedString(*buffers[curString]))
           {
               emitError(XMLErrs::ExpectedQuotedString);
  @@ -3987,11 +1237,9 @@
           }
       }
   
  -    //
       //  Make sure that the strings present are in order. We don't care about
       //  which ones are present at this point, just that any there are in the
       //  right order.
  -    //
       int curTop = 0;
       for (int index = VersionString; index < StandaloneString; index++)
       {
  @@ -4006,10 +1254,8 @@
           }
       }
   
  -    //
       //  If its an XML decl, the version must be present.
       //  If its a Text decl, then encoding must be present AND standalone must not be present.
  -    //
       if ((type == Decl_XML) && (flags[VersionString] == -1))
           emitError(XMLErrs::XMLVersionRequired);
       else if (type == Decl_Text) {
  @@ -4035,7 +1281,6 @@
       //  for the last parameter!
       const XMLCh* actualEnc = fReaderMgr.getCurrentEncodingStr();
   
  -    //
       //  Ok, we've now seen the real encoding string, if there was one, so
       //  lets call back on the current reader and tell it what the real
       //  encoding string was. If it fails, that's because it represents some
  @@ -4045,7 +1290,6 @@
       //  NOTE: This can fail for a number of reasons, such as a bogus encoding
       //  name or because its in flagrant contradiction of the auto-sensed
       //  format.
  -    //
       if (flags[EncodingString] != -1)
       {
           if (!fReaderMgr.getCurrentReader()->setEncoding(bbEncoding.getRawBuffer()))
  @@ -4054,10 +1298,7 @@
               actualEnc = bbEncoding.getRawBuffer();
       }
   
  -    //
       //  If we have a document handler then call the XML Decl callback.
  -    //
  -    //
       if (fDocHandler)
       {
           fDocHandler->XMLDecl
  @@ -4100,87 +1341,12 @@
           return false;
   }
   
  -unsigned int
  -XMLScanner::resolveQName(   const   XMLCh* const        qName
  -                            ,       XMLBuffer&          nameBuf
  -                            ,       XMLBuffer&          prefixBuf
  -                            , const ElemStack::MapModes mode)
  -{
  -    // Reset both target buffers in case we don't get anything for either
  -    nameBuf.reset();
  -    prefixBuf.reset();
  -
  -    //
  -    //  Lets split out the qName into a URI and name buffer first. The URI
  -    //  can be empty.
  -    //
  -    const int colonPos = XMLString::indexOf(qName, chColon);
  -    unsigned int uriId = 0;
  -    if (colonPos == -1)
  -    {
  -        //
  -        //  Its all name with no prefix, so put the whole thing into the name
  -        //  buffer. Then map the empty string to a URI, since the empty string
  -        //  represents the default namespace. This will either return some
  -        //  explicit URI which the default namespace is mapped to, or the
  -        //  the default global namespace.
  -        //
  -        nameBuf.append(qName);
  -        bool unknown;
  -        uriId = fElemStack.mapPrefixToURI(prefixBuf.getRawBuffer(), mode, unknown);
  -
  -        #if defined(XERCES_DEBUG)
  -        if (unknown)
  -        {
  -            // <TBD> This one should never be unknown
  -        }
  -        #endif
  -    }
  -     else
  -    {
  -        //
  -        //  Copy the chars up to but not including the colon into the prefix
  -        //  buffer.
  -        //
  -        prefixBuf.append(qName, colonPos);
  -
  -        // And copy over the rest of the chars to the name buffer
  -        nameBuf.append(&qName[colonPos+1]);
  -
  -        //
  -        //  Watch for the special namespace prefixes. We always map these to
  -        //  special URIs. 'xml' gets mapped to the official URI that its defined
  -        //  to map to by the NS spec. xmlns gets mapped to a special place holder
  -        //  URI that we define (so that it maps to something checkable.)
  -        //
  -        if (XMLString::equals(prefixBuf.getRawBuffer(), XMLUni::fgXMLNSString)) {
  -            uriId = fXMLNSNamespaceId;
  -
  -            // if this is an element, it is an error to have xmlns as prefix
  -            if (mode == ElemStack::Mode_Element)
  -                emitError(XMLErrs::NoXMLNSAsElementPrefix, qName);
  -        }
  -        else if (XMLString::equals(prefixBuf.getRawBuffer(), XMLUni::fgXMLString))
  -            uriId = fXMLNamespaceId;
  -        else
  -        {
  -            bool unknown;
  -            uriId = fElemStack.mapPrefixToURI(prefixBuf.getRawBuffer(), mode, unknown);
  -            if (unknown)
  -                emitError(XMLErrs::UnknownPrefix, prefixBuf.getRawBuffer());
  -        }
  -    }
  -    return uriId;
  -}
  -
   bool XMLScanner::checkXMLDecl(bool startWithAngle) {
  -    //
  +
       // [23] XMLDecl     ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
       // [24] VersionInfo ::= S 'version' Eq ("'" VersionNum "'" | '"' VersionNum '"')
       //
       // [3]  S           ::= (#x20 | #x9 | #xD | #xA)+
  -    //
  -
       if (startWithAngle) {
           if (fReaderMgr.peekString(XMLUni::fgXMLDeclString)) {
               if (fReaderMgr.skippedString(XMLUni::fgXMLDeclStringSpace)
  @@ -4195,10 +1361,8 @@
                  || fReaderMgr.skippedString(XMLUni::fgXMLDeclStringLFU)
                  || fReaderMgr.skippedString(XMLUni::fgXMLDeclStringCRU))
               {
  -                //
                   //  Just in case, check for upper case. If found, issue
                   //  an error, but keep going.
  -                //
                   emitError(XMLErrs::XMLDeclMustBeLowerCase);
                   return true;
               }
  @@ -4218,10 +1382,8 @@
                  || fReaderMgr.skippedString(XMLUni::fgXMLStringLFU)
                  || fReaderMgr.skippedString(XMLUni::fgXMLStringCRU))
               {
  -                //
                   //  Just in case, check for upper case. If found, issue
                   //  an error, but keep going.
  -                //
                   emitError(XMLErrs::XMLDeclMustBeLowerCase);
                   return true;
               }
  @@ -4233,44 +1395,6 @@
   
   
   // ---------------------------------------------------------------------------
  -//  XMLScanner: Helper methos
  -// ---------------------------------------------------------------------------
  -void XMLScanner::resizeElemState() {
  -
  -    unsigned int newSize = fElemStateSize * 2;
  -    unsigned int* newElemState = new unsigned int[newSize];
  -
  -    // Copy the existing values
  -    unsigned int index = 0;
  -    for (; index < fElemStateSize; index++)
  -        newElemState[index] = fElemState[index];
  -
  -    for (; index < newSize; index++)
  -        newElemState[index] = 0;
  -
  -    // Delete the old array and udpate our members
  -    delete [] fElemState;
  -    fElemState = newElemState;
  -    fElemStateSize = newSize;
  -}
  -
  -// ---------------------------------------------------------------------------
  -//  XMLScanner: IC activation methos
  -// ---------------------------------------------------------------------------
  -void XMLScanner::activateSelectorFor(IdentityConstraint* const ic, const int initialDepth) {
  -
  -    IC_Selector* selector = ic->getSelector();
  -
  -    if (!selector)
  -        return;
  -
  -    XPathMatcher* matcher = selector->createMatcher(fFieldActivator, initialDepth);
  -
  -    fMatcherStack->addMatcher(matcher);
  -    matcher->startDocumentFragment();
  -}
  -
  -// ---------------------------------------------------------------------------
   //  XMLScanner: Grammar preparsing
   // ---------------------------------------------------------------------------
   Grammar* XMLScanner::loadGrammar(const   XMLCh* const systemId
  @@ -4283,21 +1407,18 @@
           srcToUse = fEntityHandler->resolveEntity(XMLUni::fgZeroLenString, systemId);
       }
   
  -    //
       //  First we try to parse it as a URL. If that fails, we assume its
       //  a file and try it that way.
  -    //
       if (!srcToUse) {
   
           try
           {
  -            //
               //  Create a temporary URL. Since this is the primary document,
               //  it has to be fully qualified. If not, then assume we are just
               //  mistaking a file for a URL.
  -            //
               XMLURL tmpURL(systemId);
  -            if (tmpURL.isRelative()) {
  +            if (tmpURL.isRelative())
  +            {
                   srcToUse = new LocalFileInputSource(systemId);
               }
               else
  @@ -4331,231 +1452,431 @@
   }
   
   
  -Grammar* XMLScanner::loadGrammar(const   InputSource& src
  -                                 , const short        grammarType
  -                                 , const bool         toCache)
  +// ---------------------------------------------------------------------------
  +//  XMLScanner: Setter methods
  +// ---------------------------------------------------------------------------
  +void XMLScanner::setURIStringPool(XMLStringPool* const stringPool)
   {
  -    try
  +    fURIStringPool = stringPool;
  +    fEmptyNamespaceId   = fURIStringPool->addOrFind(XMLUni::fgZeroLenString);
  +    fUnknownNamespaceId = fURIStringPool->addOrFind(XMLUni::fgUnknownURIName);
  +    fXMLNamespaceId     = fURIStringPool->addOrFind(XMLUni::fgXMLURIName);
  +    fXMLNSNamespaceId   = fURIStringPool->addOrFind(XMLUni::fgXMLNSURIName);
  +}
  +
  +// ---------------------------------------------------------------------------
  +//  XMLScanner: Private helper methods
  +// ---------------------------------------------------------------------------
  +
  +//  This method is called after the content scan to insure that all the
  +//  ID/IDREF attributes match up (i.e. that all IDREFs refer to IDs.) This is
  +//  an XML 1.0 rule, so we can do here in the core.
  +void XMLScanner::checkIDRefs()
  +{
  +    //  Iterate the id ref list. If we find any entries here which are used
  +    //  but not declared, then that's an error.
  +    RefHashTableOfEnumerator<XMLRefInfo> refEnum(fIDRefList);
  +    while (refEnum.hasMoreElements())
       {
  -        fGrammarResolver->cacheGrammarFromParse(false);
  -        fGrammarResolver->useCachedGrammarInParse(false);
  -        fRootGrammar = 0;
  +        // Get a ref to the current element
  +        const XMLRefInfo& curRef = refEnum.nextElement();
   
  -        if (fValScheme == Val_Auto) {
  -            fValidate = true;
  -        }
  +        // If its used but not declared, then its an error
  +        if (!curRef.getDeclared() && curRef.getUsed() && fValidate)
  +            fValidator->emitError(XMLValid::IDNotDeclared, curRef.getRefName());
  +    }
  +}
   
  -        // Reset some status flags
  -        fInException = false;
  -        fStandalone = false;
  -        fErrorCount = 0;
  -        fHasNoDTD = true;
  -        fSeeXsi = false;
   
  -        if (grammarType == Grammar::SchemaGrammarType) {
  -            return loadXMLSchemaGrammar(src, toCache);
  -        }
  -        else if (grammarType == Grammar::DTDGrammarType) {
  -            return loadDTDGrammar(src, toCache);
  -        }
  +//  This just does a simple check that the passed progressive scan token is
  +//  legal for this scanner.
  +bool XMLScanner::isLegalToken(const XMLPScanToken& toCheck)
  +{
  +    return ((fScannerId == toCheck.fScannerId)
  +    &&      (fSequenceId == toCheck.fSequenceId));
  +}
   
  -        // Reset the reader manager to close all files, sockets, etc...
  -        fReaderMgr.reset();
  -    }
   
  -    //
  -    //  NOTE:
  -    //
  -    //  In all of the error processing below, the emitError() call MUST come
  -    //  before the flush of the reader mgr, or it will fail because it tries
  -    //  to find out the position in the XML source of the error.
  -    //
  -    catch(const XMLErrs::Codes)
  +//  This method will handle figuring out what the next top level token is
  +//  in the input stream. It will return an enumerated value that indicates
  +//  what it believes the next XML level token must be. It will eat as many
  +//  chars are required to figure out what is next.
  +XMLScanner::XMLTokens XMLScanner::senseNextToken(unsigned int& orgReader)
  +{
  +    //  Get the next character and use it to guesstimate what the next token
  +    //  is going to be. We turn on end of entity exceptions when we do this
  +    //  in order to catch the scenario where the current entity ended at
  +    //  the > of some markup.
  +    XMLCh nextCh;
       {
  -        // This is a 'first fatal error' type exit, so reset and fall through
  -        fReaderMgr.reset();
  +        ThrowEOEJanitor janMgr(&fReaderMgr, true);
  +        nextCh = fReaderMgr.peekNextChar();
       }
   
  -    catch(const XMLValid::Codes)
  -    {
  -        // This is a 'first fatal error' type exit, so reset and fall through
  -        fReaderMgr.reset();
  +    //  Check for special chars. Start with the most
  +    //  obvious end of file, which should be legal here at top level.
  +    if (!nextCh)
  +        return Token_EOF;
   
  -    }
   
  -    catch(const XMLException& excToCatch)
  +    //  If it's not a '<' we must be in content.
  +    //
  +    //  This includes entity references '&' of some sort. These must
  +    //  be character data because that's the only place a reference can
  +    //  occur in content.
  +    if (nextCh != chOpenAngle)
  +        return Token_CharData;
  +
  +    //  Ok it had to have been a '<' character. So get it out of the reader
  +    //  and store the reader number where we saw it, passing it back to the
  +    //  caller.
  +    fReaderMgr.getNextChar();
  +    orgReader = fReaderMgr.getCurrentReaderNum();
  +
  +    //  Ok, so lets go through the things that it could be at this point which
  +    //  are all some form of markup.
  +    nextCh = fReaderMgr.peekNextChar();
  +
  +    if (nextCh == chForwardSlash)
       {
  -        //
  -        //  Emit the error and catch any user exception thrown from here. Make
  -        //  sure in all cases we flush the reader manager.
  -        //
  -        fInException = true;
  -        try
  +        fReaderMgr.getNextChar();
  +        return Token_EndTag;
  +    }
  +    else if (nextCh == chBang)
  +    {
  +        static const XMLCh gCDATAStr[] =
           {
  -            if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning)
  -                emitError
  -                (
  -                    XMLErrs::DisplayErrorMessage
  -                    , excToCatch.getMessage()
  -                );
  -            else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal)
  -                emitError
  -                (
  -                    XMLErrs::XMLException_Fatal
  -                    , excToCatch.getType()
  -                    , excToCatch.getMessage()
  -                );
  -            else
  -                emitError
  -                (
  -                    XMLErrs::XMLException_Error
  -                    , excToCatch.getType()
  -                    , excToCatch.getMessage()
  -                );
  -        }
  +                chBang, chOpenSquare, chLatin_C, chLatin_D, chLatin_A
  +            ,   chLatin_T, chLatin_A, chNull
  +        };
   
  -        catch(...)
  +        static const XMLCh gCommentString[] =
           {
  -            // Flush the reader manager and rethrow user's error
  -            fReaderMgr.reset();
  -            throw;
  -        }
  +            chBang, chDash, chDash, chNull
  +        };
   
  -        // If it returned, then reset the reader manager and fall through
  -        fReaderMgr.reset();
  -    }
  +        if (fReaderMgr.skippedString(gCDATAStr))
  +            return Token_CData;
   
  -    catch(...)
  +        if (fReaderMgr.skippedString(gCommentString))
  +            return Token_Comment;
  +
  +        emitError(XMLErrs::ExpectedCommentOrCDATA);
  +        return Token_Unknown;
  +    }
  +    else if (nextCh == chQuestion)
       {
  -        // Reset and rethrow
  -        fReaderMgr.reset();
  -        throw;
  +        // It must be a PI
  +        fReaderMgr.getNextChar();
  +        return Token_PI;
       }
   
  -    return 0;
  +    //  Assume its an element name, so return with a start tag token. If it
  +    //  turns out not to be, then it will fail when it cannot get a valid tag.
  +    return Token_StartTag;
   }
   
  -Grammar* XMLScanner::loadDTDGrammar(const InputSource& src,
  -                                    const bool toCache)
  +// ---------------------------------------------------------------------------
  +//  XMLScanner: Private parsing methods
  +// ---------------------------------------------------------------------------
  +
  +//  This guy just scans out a single or double quoted string of characters.
  +//  It does not pass any judgement on the contents and assumes that it is
  +//  illegal to have another quote of the same kind inside the string's
  +//  contents.
  +//
  +//  NOTE: This is for simple stuff like the strings in the XMLDecl which
  +//  cannot have any entities inside them. So this guy does not handle any
  +//  end of entity stuff.
  +bool XMLScanner::getQuotedString(XMLBuffer& toFill)
   {
  -   // Reset the validators
  -    fDTDValidator->reset();
  -    if (fValidatorFromUser)
  -        fValidator->reset();
  +    // Reset the target buffer
  +    toFill.reset();
   
  -    if (!fValidator->handlesDTD()) {
  -        if (fValidatorFromUser && fValidate)
  -            ThrowXML(RuntimeException, XMLExcepts::Gen_NoDTDValidator);
  -        else {
  -            fValidator = fDTDValidator;
  -        }
  -    }
  +    // Get the next char which must be a single or double quote
  +    XMLCh quoteCh;
  +    if (!fReaderMgr.skipIfQuote(quoteCh))
  +        return false;
   
  -    fDTDGrammar = new DTDGrammar();
  -    fGrammarResolver->putGrammar(XMLUni::fgDTDEntityString, fDTDGrammar);
  -    fGrammar = fDTDGrammar;
  -    fGrammarType = fGrammar->getGrammarType();
  -    fValidator->setGrammar(fGrammar);
  +    while (true)
  +    {
  +        // Get another char
  +        const XMLCh nextCh = fReaderMgr.getNextChar();
   
  -    //
  -    //  And for all installed handlers, send reset events. This gives them
  -    //  a chance to flush any cached data.
  -    //
  -    if (fDocHandler)
  -        fDocHandler->resetDocument();
  -    if (fEntityHandler)
  -        fEntityHandler->resetEntities();
  -    if (fErrorReporter)
  -        fErrorReporter->resetErrors();
  +        // See if it matches the starting quote char
  +        if (nextCh == quoteCh)
  +            break;
   
  -    // Clear out the id reference list
  -    fIDRefList->removeAll();
  +        //  We should never get either an end of file null char here. If we
  +        //  do, just fail. It will be handled more gracefully in the higher
  +        //  level code that called us.
  +        if (!nextCh)
  +            return false;
   
  -    if (toCache) {
  +        // Else add it to the buffer
  +        toFill.append(nextCh);
  +    }
  +    return true;
  +}
   
  -        unsigned int sysId = fGrammarResolver->getStringPool()->addOrFind(src.getSystemId());
  -        const XMLCh* sysIdStr = fGrammarResolver->getStringPool()->getValueForId(sysId);
   
  -        fGrammarResolver->orphanGrammar(XMLUni::fgDTDEntityString);
  -        fGrammarResolver->putGrammar(sysIdStr, fGrammar);
  +//  This method scans a character reference and returns the character that
  +//  was refered to. It assumes that we've already scanned the &# characters
  +//  that prefix the numeric code.
  +bool XMLScanner::scanCharRef(XMLCh& toFill, XMLCh& second)
  +{
  +    bool gotOne = false;
  +    unsigned int value = 0;
  +
  +    //  Set the radix. Its supposed to be a lower case x if hex. But, in
  +    //  order to recover well, we check for an upper and put out an error
  +    //  for that.
  +    unsigned int radix = 10;
  +    if (fReaderMgr.skippedChar(chLatin_x))
  +    {
  +        radix = 16;
  +    }
  +    else if (fReaderMgr.skippedChar(chLatin_X))
  +    {
  +        emitError(XMLErrs::HexRadixMustBeLowerCase);
  +        radix = 16;
       }
   
  -    //
  -    //  Handle the creation of the XML reader object for this input source.
  -    //  This will provide us with transcoding and basic lexing services.
  -    //
  -    XMLReader* newReader = fReaderMgr.createReader
  -    (
  -        src
  -        , false
  -        , XMLReader::RefFrom_NonLiteral
  -        , XMLReader::Type_General
  -        , XMLReader::Source_External
  -    );
  -    if (!newReader) {
  -        if (src.getIssueFatalErrorIfNotFound())
  -            ThrowXML1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource, src.getSystemId());
  +    while (true)
  +    {
  +        const XMLCh nextCh = fReaderMgr.peekNextChar();
  +
  +        // Watch for EOF
  +        if (!nextCh)
  +            ThrowXML(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF);
  +
  +        // Break out on the terminating semicolon
  +        if (nextCh == chSemiColon)
  +        {
  +            fReaderMgr.getNextChar();
  +            break;
  +        }
  +
  +        //  Convert this char to a binary value, or bail out if its not
  +        //  one.
  +        unsigned int nextVal;
  +        if ((nextCh >= chDigit_0) && (nextCh <= chDigit_9))
  +            nextVal = (unsigned int)(nextCh - chDigit_0);
  +        else if ((nextCh >= chLatin_A) && (nextCh <= chLatin_F))
  +            nextVal= (unsigned int)(10 + (nextCh - chLatin_A));
  +        else if ((nextCh >= chLatin_a) && (nextCh <= chLatin_f))
  +            nextVal = (unsigned int)(10 + (nextCh - chLatin_a));
           else
  -            ThrowXML1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource_Warning, src.getSystemId());
  -    }
  +        {
  +            // Return a zero
  +            toFill = 0;
   
  -    //
  -    //  In order to make the processing work consistently, we have to
  -    //  make this look like an external entity. So create an entity
  -    //  decl and fill it in and push it with the reader, as happens
  -    //  with an external entity. Put a janitor on it to insure it gets
  -    //  cleaned up. The reader manager does not adopt them.
  -    //
  -    const XMLCh gDTDStr[] = { chLatin_D, chLatin_T, chLatin_D , chNull };
  -    DTDEntityDecl* declDTD = new DTDEntityDecl(gDTDStr);
  -    declDTD->setSystemId(src.getSystemId());
  -    Janitor<DTDEntityDecl> janDecl(declDTD);
  +            //  If we got at least a sigit, then do an unterminated ref error.
  +            //  Else, do an expected a numerical ref thing.
  +            if (gotOne)
  +                emitError(XMLErrs::UnterminatedCharRef);
  +            else
  +                emitError(XMLErrs::ExpectedNumericalCharRef);
   
  -    // Mark this one as a throw at end
  -    newReader->setThrowAtEnd(true);
  +            // Return failure
  +            return false;
  +        }
   
  -    // And push it onto the stack, with its pseudo name
  -    fReaderMgr.pushReader(newReader, declDTD);
  +        //  Make sure its valid for the radix. If not, then just eat the
  +        //  digit and go on after issueing an error. Else, update the
  +        //  running value with this new digit.
  +        if (nextVal >= radix)
  +        {
  +            XMLCh tmpStr[2];
  +            tmpStr[0] = nextCh;
  +            tmpStr[1] = chNull;
  +            emitError(XMLErrs::BadDigitForRadix, tmpStr);
  +        }
  +        else
  +        {
  +            value = (value * radix) + nextVal;
  +        }
   
  -    //
  -    //  If we have a doc type handler and advanced callbacks are enabled,
  -    //  call the doctype event.
  -    //
  -    if (fDocTypeHandler) {
  +        // Indicate that we got at least one good digit
  +        gotOne = true;
  +
  +        // And eat the last char
  +        fReaderMgr.getNextChar();
  +    }
  +
  +    //  [2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF]        // any Unicode character, excluding the
  +    //               | [#xE000-#xFFFD] | [#x10000-#x10FFFF] // surrogate blocks, FFFE, and FFFF.
  +    bool validChar = false;
  +    if (value < 0x20)
  +    {
  +      if (value == 0x09 || value == 0x0A || value == 0x0D)
  +      {
  +          validChar = true;
  +      }
  +    }
  +    else if (value <= 0xD7FF || (value >= 0xE000 && (value <= 0xFFFD || (value >= 0x10000 && value <= 0x10FFFF))))
  +    {
  +          validChar = true;
  +    }
   
  -        // Create a dummy root
  -        DTDElementDecl* rootDecl = new DTDElementDecl(gDTDStr, fEmptyNamespaceId);
  -        rootDecl->setCreateReason(DTDElementDecl::AsRootElem);
  -        rootDecl->setExternalElemDeclaration(true);
  -        Janitor<DTDElementDecl> janSrc(rootDecl);
  +    if (!validChar)
  +    {
  +        // Character reference was not in the valid range
  +        emitError(XMLErrs::InvalidCharacterRef);
  +        return false;
  +    }
   
  -        fDocTypeHandler->doctypeDecl(*rootDecl, src.getPublicId(), src.getSystemId(), false, true);
  +    // Return the char (or chars)
  +    if (value >= 0x10000)
  +    {
  +        value -= 0x10000;
  +        toFill = XMLCh((value >> 10) + 0xD800);
  +        second = XMLCh((value & 0x3FF) + 0xDC00);
  +    }
  +    else
  +    {
  +        toFill = XMLCh(value);
  +        second = 0;
       }
   
  -    // Create DTDScanner
  -    DTDScanner dtdScanner((DTDGrammar*)fGrammar, fDocTypeHandler);
  -    dtdScanner.setScannerInfo(this, &fReaderMgr, &fBufMgr);
  +    return true;
  +}
  +
  +
  +//  We get here after the '<!--' part of the comment. We scan past the
  +//  terminating '-->' It will calls the appropriate handler with the comment
  +//  text, if one is provided. A comment can be in either the document or
  +//  the DTD, so the fInDocument flag is used to know which handler to send
  +//  it to.
  +void XMLScanner::scanComment()
  +{
  +    enum States
  +    {
  +        InText
  +        , OneDash
  +        , TwoDashes
  +    };
  +
  +    // Get a buffer for this
  +    XMLBufBid bbComment(&fBufMgr);
  +
  +    //  Get the comment text into a temp buffer. Be sure to use temp buffer
  +    //  two here, since its to be used for stuff that is potentially longer
  +    //  than just a name.
  +    States curState = InText;
  +    bool gotLeadingSurrogate = false;
  +    while (true)
  +    {
  +        // Get the next character
  +        const XMLCh nextCh = fReaderMgr.getNextChar();
  +
  +        //  Watch for an end of file
  +        if (!nextCh)
  +        {
  +            emitError(XMLErrs::UnterminatedComment);
  +            ThrowXML(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF);
  +        }
  +
  +        // Check for correct surrogate pairs
  +        if ((nextCh >= 0xD800) && (nextCh <= 0xDBFF))
  +        {
  +            if (gotLeadingSurrogate)
  +                emitError(XMLErrs::Expected2ndSurrogateChar);
  +            else
  +                gotLeadingSurrogate = true;
  +        }
  +        else
  +        {
  +            if (gotLeadingSurrogate)
  +            {
  +                if ((nextCh < 0xDC00) || (nextCh > 0xDFFF))
  +                    emitError(XMLErrs::Expected2ndSurrogateChar);
  +            }
  +            // Its got to at least be a valid XML character
  +            else if (!XMLReader::isXMLChar(nextCh)) {
  +
  +                XMLCh tmpBuf[9];
  +                XMLString::binToText
  +                (
  +                    nextCh
  +                    , tmpBuf
  +                    , 8
  +                    , 16
  +                );
  +                emitError(XMLErrs::InvalidCharacter, tmpBuf);
  +            }
  +
  +            gotLeadingSurrogate = false;
  +        }
   
  -    // Tell it its not in an include section
  -    dtdScanner.scanExtSubsetDecl(false);
  +        if (curState == InText)
  +        {
  +            // If its a dash, go to OneDash state. Otherwise take as text
  +            if (nextCh == chDash)
  +                curState = OneDash;
  +            else
  +                bbComment.append(nextCh);
  +        }
  +        else if (curState == OneDash)
  +        {
  +            //  If its another dash, then we change to the two dashes states.
  +            //  Otherwise, we have to put in the deficit dash and the new
  +            //  character and go back to InText.
  +            if (nextCh == chDash)
  +            {
  +                curState = TwoDashes;
  +            }
  +            else
  +            {
  +                bbComment.append(chDash);
  +                bbComment.append(nextCh);
  +                curState = InText;
  +            }
  +        }
  +        else if (curState == TwoDashes)
  +        {
  +            // The next character must be the closing bracket
  +            if (nextCh != chCloseAngle)
  +            {
  +                emitError(XMLErrs::IllegalSequenceInComment);
  +                fReaderMgr.skipPastChar(chCloseAngle);
  +                return;
  +            }
  +            break;
  +        }
  +    }
   
  -    if (fValidate) {
  -        //  validate the DTD scan so far
  -        fValidator->preContentValidation(false, true);
  +    // If we have an available handler, call back with the comment.
  +    if (fDocHandler)
  +    {
  +        fDocHandler->docComment
  +        (
  +            bbComment.getRawBuffer()
  +        );
       }
  +}
   
  -    if (toCache)
  -        fGrammarResolver->cacheGrammars();
   
  -    return fDTDGrammar;
  +//  Most equal signs can have white space around them, so this little guy
  +//  just makes the calling code cleaner by eating whitespace.
  +bool XMLScanner::scanEq()
  +{
  +    fReaderMgr.skipPastSpaces();
  +    if (fReaderMgr.skippedChar(chEqual))
  +    {
  +        fReaderMgr.skipPastSpaces();
  +        return true;
  +    }
  +    return false;
   }
   
  -// ---------------------------------------------------------------------------
  -//  XMLScanner: Rest pool of cached grammars
  -// ---------------------------------------------------------------------------
  -void XMLScanner::resetCachedGrammarPool()
  +
  +unsigned int
  +XMLScanner::scanUpToWSOr(XMLBuffer& toFill, const XMLCh chEndChar)
   {
  -    fGrammarResolver->resetCachedGrammar();
  +    fReaderMgr.getUpToCharOrWS(toFill, chEndChar);
  +    return toFill.getLen();
   }
  +
   
   XERCES_CPP_NAMESPACE_END
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: xerces-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: xerces-cvs-help@xml.apache.org