source: icXML/icXML-devel/src/icxercesc/internal/IGXMLScanner.cpp @ 2720

Last change on this file since 2720 was 2720, checked in by cameron, 6 years ago

Initial check-in of icXML 0.8 source files

File size: 95.2 KB
Line 
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18/*
19 * $Id: IGXMLScanner.cpp 882548 2009-11-20 13:44:14Z borisk $
20 */
21
22// ---------------------------------------------------------------------------
23//  Includes
24// ---------------------------------------------------------------------------
25#include <xercesc/internal/IGXMLScanner.hpp>
26#include <xercesc/util/RuntimeException.hpp>
27#include <xercesc/util/UnexpectedEOFException.hpp>
28#include <xercesc/sax/InputSource.hpp>
29#include <xercesc/framework/XMLDocumentHandler.hpp>
30#include <xercesc/framework/XMLEntityHandler.hpp>
31#include <xercesc/framework/XMLPScanToken.hpp>
32#include <xercesc/internal/EndOfEntityException.hpp>
33#include <xercesc/framework/MemoryManager.hpp>
34#include <xercesc/framework/XMLGrammarPool.hpp>
35#include <xercesc/framework/XMLDTDDescription.hpp>
36#include <xercesc/framework/psvi/PSVIElement.hpp>
37#include <xercesc/framework/psvi/PSVIHandler.hpp>
38#include <xercesc/framework/psvi/PSVIAttributeList.hpp>
39#include <xercesc/validators/common/GrammarResolver.hpp>
40#include <xercesc/validators/DTD/DocTypeHandler.hpp>
41#include <xercesc/validators/DTD/DTDScanner.hpp>
42#include <xercesc/validators/DTD/DTDValidator.hpp>
43#include <xercesc/validators/schema/SchemaValidator.hpp>
44#include <xercesc/validators/schema/identity/IdentityConstraintHandler.hpp>
45#include <xercesc/validators/schema/identity/IC_Selector.hpp>
46#include <xercesc/util/OutOfMemoryException.hpp>
47#include <xercesc/util/XMLString.hpp>
48#include <icxmlc/XMLNamespaceResolver.hpp>
49#include <icxmlc/XMLStringU.hpp>
50
51XERCES_CPP_NAMESPACE_BEGIN
52
53typedef JanitorMemFunCall<IGXMLScanner> CleanupType;
54typedef JanitorMemFunCall<ReaderMgr>    ReaderMgrResetType;
55
56// ---------------------------------------------------------------------------
57//  IGXMLScanner: Constructors and Destructor
58// ---------------------------------------------------------------------------
59IGXMLScanner::IGXMLScanner( XMLValidator* const  valToAdopt
60                                                  , GrammarResolver* const grammarResolver
61                                                  , MemoryManager* const manager) :
62
63        XMLScanner(valToAdopt, grammarResolver, manager)
64        , fGrammarType(Grammar::UnKnown)
65        , fElemStateSize(16)
66        , fElemState(0)
67        , fElemLoopState(0)
68        , fContent(1023, manager)
69        , fWSNormalizeBuf(1023, manager)
70        , fDTDValidator(0)
71        , fSchemaValidator(0)
72        , fDTDGrammar(0)
73        , fICHandler(0)
74        , fDTDElemNonDeclPool(0)
75        , fSchemaElemNonDeclPool(0)
76        , fPSVIAttrList(0)
77        , fModel(0)
78        , fPSVIElement(0)
79        , fErrorStack(0)
80        , fSchemaInfoList(0)
81        , fCachedSchemaInfoList (0)
82    , fAnySimpleTypeValidator(0)
83        , fProgressiveParser(0)
84{
85        CleanupType cleanup(this, &IGXMLScanner::cleanUp);
86
87        try
88        {
89                commonInit();
90        }
91        catch(const OutOfMemoryException&)
92        {
93                // Don't cleanup when out of memory, since executing the
94                // code can cause problems.
95                cleanup.release();
96
97                throw;
98        }
99
100        cleanup.release();
101}
102
103IGXMLScanner::IGXMLScanner( XMLDocumentHandler* const docHandler
104                                                  , DocTypeHandler* const     docTypeHandler
105                                                  , XMLEntityHandler* const   entityHandler
106                                                  , XMLErrorReporter* const   errHandler
107                                                  , XMLValidator* const       valToAdopt
108                                                  , GrammarResolver* const    grammarResolver
109                                                  , MemoryManager* const      manager) :
110
111        XMLScanner(docHandler, docTypeHandler, entityHandler, errHandler, valToAdopt, grammarResolver, manager)
112        , fGrammarType(Grammar::UnKnown)
113        , fElemStateSize(16)
114        , fElemState(0)
115        , fElemLoopState(0)
116        , fContent(1023, manager)
117        , fWSNormalizeBuf(1023, manager)
118        , fDTDValidator(0)
119        , fSchemaValidator(0)
120        , fDTDGrammar(0)
121        , fICHandler(0)
122        , fDTDElemNonDeclPool(0)
123        , fSchemaElemNonDeclPool(0)
124        , fPSVIAttrList(0)
125        , fModel(0)
126        , fPSVIElement(0)
127        , fErrorStack(0)
128        , fSchemaInfoList(0)
129        , fCachedSchemaInfoList (0)
130    , fAnySimpleTypeValidator(0)
131        , fProgressiveParser(0)
132{
133        CleanupType cleanup(this, &IGXMLScanner::cleanUp);
134
135        try
136        {
137                commonInit();
138        }
139        catch(const OutOfMemoryException&)
140        {
141                // Don't cleanup when out of memory, since executing the
142                // code can cause problems.
143                cleanup.release();
144
145                throw;
146        }
147
148        cleanup.release();
149}
150
151IGXMLScanner::~IGXMLScanner()
152{
153        cleanUp();
154}
155
156// ---------------------------------------------------------------------------
157//  XMLScanner: Getter methods
158// ---------------------------------------------------------------------------
159NameIdPool<DTDEntityDecl>* IGXMLScanner::getEntityDeclPool()
160{
161        if(!fDTDGrammar)
162                return 0;
163        return fDTDGrammar->getEntityDeclPool();
164}
165
166const NameIdPool<DTDEntityDecl>* IGXMLScanner::getEntityDeclPool() const
167{
168        if(!fDTDGrammar)
169                return 0;
170        return fDTDGrammar->getEntityDeclPool();
171}
172
173// ---------------------------------------------------------------------------
174//  IGXMLScanner: Main entry point to scan a document
175// ---------------------------------------------------------------------------
176void IGXMLScanner::scanDocument( const InputSource & src )
177{
178        //  Bump up the sequence id for this parser instance. This will invalidate
179        //  any previous progressive scan tokens.
180        fSequenceId++;
181        ReaderMgrResetType  resetReaderMgr(&fReaderMgr, &ReaderMgr::reset);
182
183        try
184        {
185                //  Reset the scanner and its plugged in stuff for a new run. This
186                //  resets all the data structures, creates the initial reader and
187                //  pushes it on the stack, and sets up the base document path.
188                scanReset(src);
189
190                // If we have a document handler, then call the start document
191                if (fDocHandler)
192                        fDocHandler->startDocument();
193
194                if (fReaderMgr.getCurrentReader()->scanDocument<IGXMLScanner>(this))
195                {
196                        // Do post-parse validation if required
197                        if (fValidate)
198                        {
199                                //  We handle ID reference semantics at this level since
200                                //  its required by XML 1.0.
201                                checkIDRefs();
202                        }
203                }
204
205                // If we have a document handler, then call the end document
206                if (fDocHandler)
207                        fDocHandler->endDocument();
208        }
209        //  NOTE:
210        //
211        //  In all of the error processing below, the emitError() call MUST come
212        //  before the flush of the reader mgr, or it will fail because it tries
213        //  to find out the position in the XML source of the error.
214        catch(const XMLErrs::Codes)
215        {
216                // This is a 'first failure' exception, so fall through
217        }
218        catch(const XMLValid::Codes)
219        {
220                // This is a 'first fatal error' type exit, so fall through
221        }
222        catch(const XMLException& excToCatch)
223        {
224                //  Emit the error and catch any user exception thrown from here. Make
225                //  sure in all cases we flush the reader manager.
226                fInException = true;
227                try
228                {
229                        if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning)
230                                emitError
231                                (
232                                        XMLErrs::XMLException_Warning
233                                        , excToCatch.getCode()
234                                        , excToCatch.getMessage()
235                                );
236                        else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal)
237                                emitError
238                                (
239                                        XMLErrs::XMLException_Fatal
240                                        , excToCatch.getCode()
241                                        , excToCatch.getMessage()
242                                );
243                        else
244                                emitError
245                                (
246                                        XMLErrs::XMLException_Error
247                                        , excToCatch.getCode()
248                                        , excToCatch.getMessage()
249                                );
250                }
251                catch(const OutOfMemoryException&)
252                {
253                        // This is a special case for out-of-memory
254                        // conditions, because resetting the ReaderMgr
255                        // can be problematic.
256                        resetReaderMgr.release();
257
258                        throw;
259                }
260        }
261        catch(const OutOfMemoryException&)
262        {
263                // This is a special case for out-of-memory
264                // conditions, because resetting the ReaderMgr
265                // can be problematic.
266                resetReaderMgr.release();
267
268                throw;
269        }
270}
271
272void IGXMLScanner::scanFirst()
273{
274        fProgressiveParser = fReaderMgr.getCurrentReader()->scanFirst<IGXMLScanner>(this);
275}
276
277bool IGXMLScanner::scanNext(XMLPScanToken& token)
278{
279        // Make sure this token is still legal
280        if (!isLegalToken(token))
281                ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Scan_BadPScanToken, fMemoryManager);
282
283        try
284        {
285                const bool gotData =
286                        fReaderMgr.getCurrentReader()->scanNext<IGXMLScanner>(*fProgressiveParser);
287
288                // If we hit the end, then do the miscellaneous part
289                if (!gotData)
290                {
291                        // Do post-parse validation if required
292                        if (fValidate)
293                        {
294                                //  We handle ID reference semantics at this level since
295                                //  its required by XML 1.0.
296                                checkIDRefs();
297                        }
298
299                        if (toCheckIdentityConstraint())
300                                fICHandler->endDocument();
301
302                        if (fDocHandler)
303                                fDocHandler->endDocument();
304                }
305
306                return gotData;
307        }
308        catch(const XMLErrs::Codes)
309        {
310
311        }
312        catch(const XMLValid::Codes)
313        {
314
315        }
316        catch(const XMLException& excToCatch)
317        {
318                //  Emit the error and catch any user exception thrown from here. Make
319                //  sure in all cases we flush the reader manager.
320                fInException = true;
321                try
322                {
323                        if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning)
324                                emitError
325                                (
326                                        XMLErrs::XMLException_Warning
327                                        , excToCatch.getCode()
328                                        , excToCatch.getMessage()
329                                );
330                        else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal)
331                                emitError
332                                (
333                                        XMLErrs::XMLException_Fatal
334                                        , excToCatch.getCode()
335                                        , excToCatch.getMessage()
336                                );
337                        else
338                                emitError
339                                (
340                                        XMLErrs::XMLException_Error
341                                        , excToCatch.getCode()
342                                        , excToCatch.getMessage()
343                                );
344                }
345                catch(const OutOfMemoryException&)
346                {
347                        throw;
348                }
349        }
350        catch(const OutOfMemoryException&)
351        {
352                throw;
353        }
354
355        fReaderMgr.reset();
356
357        return false;
358}
359
360// ---------------------------------------------------------------------------
361//  IGXMLScanner: Private helper methods. Most of these are implemented in
362//  IGXMLScanner2.Cpp.
363// ---------------------------------------------------------------------------
364
365//  This method handles the common initialization, to avoid having to do
366//  it redundantly in multiple constructors.
367void IGXMLScanner::commonInit()
368{
369
370        //  Create the element state array
371        fElemState = (unsigned int*) fMemoryManager->allocate
372        (
373                fElemStateSize * sizeof(unsigned int)
374        ); //new unsigned int[fElemStateSize];
375        fElemLoopState = (unsigned int*) fMemoryManager->allocate
376        (
377                fElemStateSize * sizeof(unsigned int)
378        ); //new unsigned int[fElemStateSize];
379
380        //  Create the Validator and init them
381        fDTDValidator = new (fMemoryManager) DTDValidator();
382        initValidator(fDTDValidator);
383        fSchemaValidator = new (fMemoryManager) SchemaValidator(0, fMemoryManager);
384        initValidator(fSchemaValidator);
385
386        // Create IdentityConstraint info
387        fICHandler = new (fMemoryManager) IdentityConstraintHandler(this, fMemoryManager);
388
389        // create pools for undeclared elements
390        fDTDElemNonDeclPool = new (fMemoryManager) NameIdPool<DTDElementDecl>(29, 128, fMemoryManager);
391        fSchemaElemNonDeclPool = new (fMemoryManager) RefHash3KeysIdPool<SchemaElementDecl>(29, false, 128, fMemoryManager);
392        fPSVIAttrList = new (fMemoryManager) PSVIAttributeList(fMemoryManager);
393
394        fSchemaInfoList = new (fMemoryManager) RefHash2KeysTableOf<SchemaInfo>(29, fMemoryManager);
395        fCachedSchemaInfoList = new (fMemoryManager) RefHash2KeysTableOf<SchemaInfo>(29, fMemoryManager);
396
397    fAnySimpleTypeValidator = 0;
398
399        // use fDTDValidator as the default validator
400        if (!fValidator)
401        {
402                fValidator = fDTDValidator;
403        }
404}
405
406void IGXMLScanner::cleanUp()
407{
408        fMemoryManager->deallocate(fElemState);
409        fMemoryManager->deallocate(fElemLoopState);
410        delete fDTDValidator;
411        delete fSchemaValidator;
412        delete fICHandler;
413        delete fDTDElemNonDeclPool;
414        delete fSchemaElemNonDeclPool;
415        delete fPSVIAttrList;
416        delete fPSVIElement;
417        delete fErrorStack;
418        delete fSchemaInfoList;
419        delete fCachedSchemaInfoList;
420        delete fProgressiveParser;
421}
422
423// ---------------------------------------------------------------------------
424//  IGXMLScanner: Private scanning methods
425// ---------------------------------------------------------------------------
426
427// --------------------------------------------------------------------------------------------------------
428// HANDLE START / EMPTY TAG FUNCTIONS
429// --------------------------------------------------------------------------------------------------------
430
431XMLElementDecl * IGXMLScanner::handleStartTag
432(
433          const XMLSymbol * const               element
434        , const XMLAttributeList &              attributeList
435        , XMLSize_t                                             attributeCount
436        , const bool                                    isRoot
437        , const bool                                    isEmpty
438        , const XMLSize_t                               readerNum
439)
440{
441        #ifdef __GNUC__
442        #warning "optimize the fDoNamespaces branches? may or may not help depending on what the compiler is able to do"
443        #endif
444
445        /// ----------------------------- DETERMINE THE ELEMENT DECLARATION -----------------------------------
446
447        fContent.reset();
448        XMLElementDecl * elemDecl = 0;
449
450        if (!fDoNamespaces)
451        {
452                //  Lets try to look up the element in the validator's element decl pool
453                //  We can pass bogus values for the URI id and the base name. We know that
454                //  this can only be called if we are doing a DTD style validator and that
455                //  he will only look at the QName.
456                //
457                //  We tell him to fault in a decl if he does not find one.
458                //  Actually, we *don't* tell him to fault in a decl if he does not find one- NG
459
460                elemDecl = element->getElemDecl();
461
462                if (!elemDecl)
463                {
464                        const XMLCh * qName = element->getName();
465                        elemDecl = element->getElemDecl(XMLNamespaceResolver::fEmptyUriId, Grammar::TOP_LEVEL_SCOPE, fGrammar);
466
467                        // look for it in the undeclared pool:
468                        if (!elemDecl)
469                        {
470                                elemDecl = fDTDElemNonDeclPool->getByKey(qName);
471                                bool notDeclared = false;
472
473                                if (!elemDecl)
474                                {
475                                        // we're assuming this must be a DTD element.  DTD's can be
476                                        // used with or without namespaces, but schemas cannot be used without
477                                        // namespaces.
478                                        elemDecl = new (fMemoryManager) DTDElementDecl
479                                        (
480                                                element->fQName
481                                                , DTDElementDecl::Any
482                                                , fMemoryManager
483                                        );
484                                        elemDecl->setId(fDTDElemNonDeclPool->put((DTDElementDecl*)elemDecl));
485                                        if (fValidate)
486                                        {
487                                                elemDecl->setCreateReason(XMLElementDecl::JustFaultIn);
488                                                notDeclared = true;
489                                        }
490                                }
491                                else
492                                {
493                                        notDeclared = !elemDecl->isDeclared();
494                                }
495
496                                // If its not marked declared and validating, then emit an error
497                                if (notDeclared)
498                                {
499                                        fValidator->emitError(XMLValid::ElementNotDefined, qName);
500                                }
501                        }
502
503                        element->setElemDecl(elemDecl);
504                }
505
506                // Expand the element stack and add the new element
507                fElemStack.addLevel(elemDecl, readerNum);
508                fElemStack.setValidationFlag(fValidate);
509
510                //  Validate the element
511                if (fValidate)
512                {
513                        fValidator->validateElement(elemDecl);
514                }
515
516                //  If this is the first element and we are validating, check the root
517                //  element.
518                if (unlikely(isRoot))
519                {
520                        fRootGrammar = fGrammar;
521                        if (fValidate)
522                        {
523                                //  If a DocType exists, then check if it matches the root name there.
524                                if (unlikely(fRootElemName && !XMLString::equals(element->getName(), fRootElemName)))
525                                {
526                                        fValidator->emitError(XMLValid::RootElemNotLikeDocType);
527                                }
528                        }
529                }
530        }
531        else
532        {
533                // save the contentleafname and currentscope before addlevel, for later use
534                ContentLeafNameTypeVector* cv = 0;
535                XMLContentModel* cm = 0;
536                unsigned int currentScope = Grammar::TOP_LEVEL_SCOPE;
537                bool laxThisOne = false;
538                const unsigned int elementUriId = element->getQName()->getURI();
539
540                if ((!isRoot) && (fGrammarType == Grammar::SchemaGrammarType))
541                {
542                        // schema validator will have correct type if validating
543                        SchemaElementDecl* tempElement = (SchemaElementDecl*)fElemStack.topElement()->fThisElement;
544                        SchemaElementDecl::ModelTypes modelType = tempElement->getModelType();
545                        ComplexTypeInfo *currType = 0;
546
547                        if (fValidate)
548                        {
549                                currType = fSchemaValidator->getCurrentTypeInfo();
550                                if (likely(currType != 0))
551                                        modelType = (SchemaElementDecl::ModelTypes)currType->getContentType();
552                                else // something must have gone wrong
553                                        modelType = SchemaElementDecl::Any;
554                        }
555                        else
556                        {
557                                currType = tempElement->getComplexTypeInfo();
558                        }
559
560                        switch (modelType)
561                        {
562                                case SchemaElementDecl::Mixed_Simple:
563                                case SchemaElementDecl::Mixed_Complex:
564                                case SchemaElementDecl::Children:
565                                        cm = currType->getContentModel();
566                                        cv = cm->getContentLeafNameTypeVector();
567                                        currentScope = fElemStack.getCurrentScope();
568                                        break;
569                                case SchemaElementDecl::Any:
570                                        laxThisOne = true;
571                        }
572                }
573
574                //  Check if there is any external schema location specified, and if we are at root,
575                //  go through them first before scanning those specified in the instance document
576                if (unlikely(isRoot && fDoSchema && (fExternalSchemaLocation || fExternalNoNamespaceSchemaLocation)))
577                {
578                        if (fExternalSchemaLocation)
579                                parseSchemaLocation(fExternalSchemaLocation, true);
580                        if (fExternalNoNamespaceSchemaLocation)
581                                resolveSchemaGrammar(fExternalNoNamespaceSchemaLocation, XMLUni::fgZeroLenString, true);
582                }
583
584                //if schema, check if we should lax or skip the validation of this element
585                if (cv)
586                {
587                        // elementDepth will be > 0, as cv is only constructed if element is not root.
588                        laxThisOne = laxElementValidation(element->getQName(), cv, cm, fElemStack.getLevel());
589                }
590
591                // this info needed for DOMTypeInfo
592                fPSVIElemContext.fErrorOccurred = false;
593
594                if (fGrammarType == Grammar::DTDGrammarType)
595                {
596                        if (!fSkipDTDValidation)
597                        {
598                                elemDecl = element->getElemDecl(XMLNamespaceResolver::fEmptyUriId, Grammar::TOP_LEVEL_SCOPE, fGrammar);
599                                if (elemDecl && elemDecl->hasAttDefs())
600                                {
601                                        XMLAttDefList & attDefList = elemDecl->getAttDefList();
602                                        for (XMLSize_t i = 0; i < attDefList.getAttDefCount(); i++)
603                                        {
604                                                // Get the current att def, for convenience and its def type
605                                                const XMLAttDef & curDef = attDefList.getAttDef(i);
606                                                const XMLAttDef::DefAttTypes defType = curDef.getDefaultType();
607
608                                                // update the NSMap if there are any default/fixed xmlns attributes
609                                                if ((defType == XMLAttDef::Default) || (defType == XMLAttDef::Fixed))
610                                                {
611                                                        const XMLCh * rawPtr = curDef.getFullName();
612                                                        if (XMLStringU::isXMLNS(rawPtr))
613                                                        {
614                                                                #ifdef __GNUC__
615                                                                #warning "IGXMLScanner::beginStartTag cannot handle default xmlns attributes in the DTD."
616                                                                #endif
617                                                        }
618                                                }
619                                        }
620                                }
621                        }
622
623                        if (!elemDecl)
624                        {
625                                elemDecl = fDTDElemNonDeclPool->getByKey(element->getName());
626                                if (elemDecl)
627                                {
628                                        element->setElemDecl(XMLNamespaceResolver::fEmptyUriId, Grammar::TOP_LEVEL_SCOPE, elemDecl, fGrammar);
629                                }
630                        }
631                }
632
633                if (fDoSchema)
634                {
635                        if (fGrammarType == Grammar::DTDGrammarType)
636                        {
637                                if (!switchGrammar(elementUriId))
638                                {
639                                        fValidator->emitError
640                                        (
641                                                XMLValid::GrammarNotFound, fUriResolver->getUriForId(elementUriId)
642                                        );
643                                }
644                        }
645                        else if (fGrammarType == Grammar::SchemaGrammarType)
646                        {
647                                Grammar * grammar = fGrammar;
648                                elemDecl = element->getElemDecl(elementUriId, currentScope, grammar);
649                                if (likely(elemDecl != 0))
650                                {
651                                        if (unlikely(grammar != fGrammar))
652                                        {
653                                                fGrammar = grammar;
654                                                fGrammarType = grammar->getGrammarType();
655                                                fValidator->setGrammar(grammar);
656                                        }
657                                }
658                                else // if not found, then it may be a reference, try TOP_LEVEL_SCOPE
659                                {
660                                        assert (grammar == fGrammar);
661
662                                        bool checkTopLevel = (currentScope != Grammar::TOP_LEVEL_SCOPE);
663
664                                        const unsigned int grammarUriId =
665                                                fUriResolver->resolveUriId(fGrammar->getTargetNamespace());
666
667                                        if (grammarUriId != elementUriId)
668                                        {
669                                                checkTopLevel = switchGrammar(elementUriId);
670
671                                                // the laxElementValidation routine (called above) will
672                                                // set fValidate to false for a "skipped" element
673                                                if (unlikely(!laxThisOne && fValidate && !checkTopLevel))
674                                                {
675                                                        fValidator->emitError
676                                                        (
677                                                                XMLValid::GrammarNotFound, fUriResolver->getUriForId(elementUriId)
678                                                        );
679                                                }
680
681                                        }
682
683                                        if (checkTopLevel)
684                                        {
685                                                elemDecl = element->getElemDecl(elementUriId, Grammar::TOP_LEVEL_SCOPE, fGrammar);
686                                        }
687
688                                        if (!elemDecl && currentScope != Grammar::TOP_LEVEL_SCOPE)
689                                        {
690                                                if (grammarUriId == elementUriId)
691                                                {
692                                                        // still not found in specified uri; try emptyNamespace see if element should be un-qualified.
693                                                        if (elementUriId != XMLNamespaceResolver::fEmptyUriId)
694                                                        {
695                                                                XMLElementDecl* tempElemDecl =
696                                                                        element->getElemDecl(XMLNamespaceResolver::fEmptyUriId, currentScope, fGrammar);
697
698                                                                if (tempElemDecl && tempElemDecl->getCreateReason() != XMLElementDecl::JustFaultIn && fValidate)
699                                                                {
700                                                                        fValidator->emitError
701                                                                        (
702                                                                                XMLValid::ElementNotUnQualified, element->getName()
703                                                                        );
704                                                                        elemDecl = tempElemDecl;
705                                                                }
706                                                        }
707                                                }
708                                                else if (elementUriId == XMLNamespaceResolver::fEmptyUriId)
709                                                {
710                                                        // still Not found in specified uri
711                                                        // go to original Grammar again to see if element needs
712                                                        // to be fully qualified.
713                                                        // Use a temp variable until we decide this is the case
714
715                                                        if (setCurrentGrammar(grammar))
716                                                        {
717                                                                XMLElementDecl* tempElemDecl = element->getElemDecl(grammarUriId, currentScope, fGrammar);
718                                                                if (tempElemDecl && tempElemDecl->getCreateReason() != XMLElementDecl::JustFaultIn && fValidate)
719                                                                {
720                                                                        fValidator->emitError(XMLValid::ElementNotQualified, element->getName());
721                                                                        elemDecl = tempElemDecl;
722                                                                }
723                                                        }
724                                                        else if (!laxThisOne && fValidate)
725                                                        {
726                                                                fValidator->emitError(XMLValid::GrammarNotFound, fGrammar->getTargetNamespace());
727                                                        }
728                                                }
729                                        }
730
731                                        if (!elemDecl)
732                                        {
733                                                // still not found
734                                                // switch back to original grammar first if necessary
735                                                if (grammarUriId != elementUriId)
736                                                {
737                                                        setCurrentGrammar(grammar);
738                                                }
739
740                                                // look in the list of undeclared elements, as would have been
741                                                // done before we made grammars stateless:
742                                                elemDecl = fSchemaElemNonDeclPool->getByKey(element->getQName()->getLocalPart(), elementUriId, (int)Grammar::TOP_LEVEL_SCOPE);
743                                        }
744
745                                        if (elemDecl)
746                                        {
747                                                element->setElemDecl(elementUriId, currentScope, elemDecl, fGrammar);
748                                        }
749                                }
750                        }
751                }
752
753                //  Look up the element now in the grammar. This will get us back a
754                //  generic element decl object. We tell him to fault one in if he does
755                //  not find it.
756                bool wasAdded = false;
757
758                if (!elemDecl)
759                {
760                        if (fGrammarType == Grammar::DTDGrammarType)
761                        {
762                                elemDecl = new (fMemoryManager) DTDElementDecl(element->getQName(), DTDElementDecl::Any, fMemoryManager);
763                                elemDecl->setId(fDTDElemNonDeclPool->put((DTDElementDecl*)elemDecl));
764                        }
765                        else if (fGrammarType == Grammar::SchemaGrammarType)
766                        {
767                                elemDecl = new (fMemoryManager) SchemaElementDecl
768                                (
769                                        element->getQName()
770                                        , SchemaElementDecl::Any
771                                        , Grammar::TOP_LEVEL_SCOPE
772                                        , fMemoryManager
773                                );
774                                elemDecl->setId
775                                (
776                                        fSchemaElemNonDeclPool->put
777                                        (
778                                                (void*)elemDecl->getBaseName()
779                                                , elementUriId
780                                                , (int)Grammar::TOP_LEVEL_SCOPE
781                                                , (SchemaElementDecl*)elemDecl
782                                        )
783                                );
784                        }
785
786                        element->setElemDecl(elementUriId, Grammar::TOP_LEVEL_SCOPE, elemDecl, fGrammar);
787
788                        wasAdded = true;
789                }
790
791                //  We do something different here according to whether we found the element or not.
792                const bool bXsiTypeSet = (fGrammarType == Grammar::SchemaGrammarType) && fSchemaValidator->getIsXsiTypeSet();
793
794                if (wasAdded)
795                {
796                        if (laxThisOne && !bXsiTypeSet)
797                        {
798                                fValidate = false;
799                        }
800                        else if (fValidate)
801                        {
802                                // If validating then emit an error
803
804                                // This is to tell the reuse Validator that this element was
805                                // faulted-in, was not an element in the grammar pool originally
806                                elemDecl->setCreateReason(XMLElementDecl::JustFaultIn);
807
808                                // xsi:type was specified, don't complain about missing definition
809                                if (!bXsiTypeSet)
810                                {
811                                        fValidator->emitError(XMLValid::ElementNotDefined, elemDecl->getFullName());
812
813                                        if (fGrammarType == Grammar::SchemaGrammarType)
814                                        {
815                                                fPSVIElemContext.fErrorOccurred = true;
816                                        }
817                                }
818                        }
819                }
820                else if (!elemDecl->isDeclared())
821                {
822                        // If its not marked declared and validating, then emit an error
823                        if (elemDecl->getCreateReason() == XMLElementDecl::NoReason)
824                        {
825                                if (!bXsiTypeSet && fGrammarType == Grammar::SchemaGrammarType)
826                                {
827                                        fPSVIElemContext.fErrorOccurred = true;
828                                }
829                        }
830
831                        if (laxThisOne)
832                        {
833                                fValidate = false;
834                        }
835                        else if (fValidate && !bXsiTypeSet)
836                        {
837                                fValidator->emitError(XMLValid::ElementNotDefined, elemDecl->getFullName());
838                        }
839                }
840
841                //  Now we can update the element stack to set the current element decl.
842                const XMLSize_t elemDepth = fElemStack.addLevel(elemDecl, fReaderMgr.getCurrentReaderNum());
843
844                if (isRoot)
845                {
846                        fRootGrammar = fGrammar;
847                        if (fGrammarType == Grammar::SchemaGrammarType && !fRootElemName)
848                        {
849                                fRootElemName = XMLString::replicate(element->getName(), element->getLength());
850                        }
851                }
852
853                if (fGrammarType == Grammar::SchemaGrammarType && fPSVIHandler)
854                {
855                        fPSVIElemContext.fElemDepth++;
856                        if (elemDecl->isDeclared())
857                        {
858                                fPSVIElemContext.fNoneValidationDepth = fPSVIElemContext.fElemDepth;
859                        }
860                        else
861                        {
862                                fPSVIElemContext.fFullValidationDepth = fPSVIElemContext.fElemDepth;
863                        }
864                }
865
866                //  Validate the element
867                if (fValidate)
868                {
869                        fValidator->validateElement(elemDecl);
870                        if (fValidator->handlesSchema())
871                        {
872                                if (fSchemaValidator->getErrorOccurred())
873                                {
874                                        fPSVIElemContext.fErrorOccurred = true;
875                                }
876                        }
877                }
878
879                if (fGrammarType == Grammar::SchemaGrammarType)
880                {
881                        ComplexTypeInfo* typeinfo = (fValidate)
882                                ? fSchemaValidator->getCurrentTypeInfo()
883                                : ((SchemaElementDecl*)elemDecl)->getComplexTypeInfo();
884
885                        if (typeinfo)
886                        {
887                                currentScope = typeinfo->getScopeDefined();
888
889                                // switch grammar if the typeinfo has a different grammar (happens when there is xsi:type)
890                                XMLCh* typeName = typeinfo->getTypeName();
891                                const int comma = XMLString::indexOf(typeName, chComma);
892                                if (comma > 0)
893                                {
894                                        XMLBuffer prefixBuf(comma + 1, fMemoryManager);
895                                        prefixBuf.append(typeName, comma);
896                                        const XMLCh* uriStr = prefixBuf.getRawBuffer();
897
898                                        bool errorCondition = !switchGrammar(uriStr) && fValidate;
899                                        if (errorCondition && !laxThisOne)
900                                        {
901                                                fValidator->emitError
902                                                (
903                                                        XMLValid::GrammarNotFound
904                                                        , prefixBuf.getRawBuffer()
905                                                );
906                                        }
907                                }
908                                else if (comma == 0)
909                                {
910                                        bool errorCondition = !switchGrammar(XMLNamespaceResolver::fEmptyUriId) && fValidate;
911                                        if (errorCondition && !laxThisOne)
912                                        {
913                                                fValidator->emitError
914                                                (
915                                                        XMLValid::GrammarNotFound
916                                                        , XMLUni::fgZeroLenString
917                                                );
918                                        }
919                                }
920                        }
921
922                        fElemStack.setCurrentScope(currentScope);
923
924                        // Set element next state
925                        if (elemDepth >= fElemStateSize)
926                        {
927                                resizeElemState();
928                        }
929
930                        fElemState[elemDepth] = 0;
931                        fElemLoopState[elemDepth] = 0;
932                }
933
934                fElemStack.setCurrentGrammar(fGrammar);
935                fElemStack.setValidationFlag(fValidate);
936
937                //  If this is the first element and we are validating, check the root
938                //  element.
939                if (unlikely(isRoot && fValidate && fRootElemName))
940                {
941                        //  If a DocType exists, then check if it matches the root name there.
942                        if (!XMLString::equals(element->getName(), fRootElemName))
943                        {
944                                fValidator->emitError(XMLValid::RootElemNotLikeDocType);
945                        }
946                }
947
948                // PSVI handling:  even if it turns out there are
949                // no attributes, we need to reset this list...
950                if (getPSVIHandler() && fGrammarType == Grammar::SchemaGrammarType )
951                {
952                        fPSVIAttrList->reset();
953                }
954        }
955
956        /// -------------------------------- HANDLE ATTRIBUTES -----------------------------------
957
958        for (XMLSize_t index = 0; index < attributeCount; index++)
959        {
960                const XMLSymbol * const attribute = attributeList[index].getAttribute();
961                const XMLCh * value = attributeList[index].getValue();
962                // const XMLSize_t length = attributeList[index].getLength();
963
964                XMLAttDef::AttTypes attType = XMLAttDef::CData;
965
966                if (!fDoNamespaces)
967                {
968                        //  See if this attribute is declared for this element. If we are
969                        //  not validating of course it will not be at first, but we will
970                        //  fault it into the pool (to avoid lots of redundant errors.)
971                        DTDElementDecl * const dtdElemDecl = reinterpret_cast<DTDElementDecl*>(elemDecl);
972
973                        XMLAttDef * attDef = dtdElemDecl->getAttDef(attribute->getName());
974
975                        //  Add this attribute to the attribute list that we use to
976                        //  pass them to the handler. We reuse its existing elements
977                        //  but expand it as required.
978
979                        // Note that we want to this first since this will
980                        // make a copy of the namePtr; we can then make use of
981                        // that copy in the hashtable lookup that checks
982                        // for duplicates.  This will mean we may have to update
983                        // the type of the XMLAttr later.
984
985                        if (unlikely(!attDef))
986                        {
987                                //  If there is a validation handler, then we are validating so emit an error.
988                                if (fValidate)
989                                {
990                                        fValidator->emitError
991                                        (
992                                                XMLValid::AttNotDefinedForElement
993                                                , attribute->getName()
994                                                , element->getName()
995                                        );
996                                }
997                        }
998                        else
999                        {
1000                                // prepare for duplicate detection
1001                                attDef->setLastOccurrence(attribute->fLastOccurence);
1002
1003                                //  Now that its all stretched out, lets look at its type and
1004                                //  determine if it has a valid value. It will output any needed
1005                                //  errors, but we just keep going. We only need to do this if
1006                                //  we are validating.
1007                                if (fValidate)
1008                                {
1009                                        // Let the validator pass judgement on the attribute value
1010                                        fValidator->validateAttrValue
1011                                        (
1012                                                attDef
1013                                                , value
1014                                                , false
1015                                                , dtdElemDecl
1016                                        );
1017                                }
1018                        }
1019                }
1020                else // if (fDoNamespaces)
1021                {
1022                        //  If its not a special case namespace attr of some sort, then we
1023                        //  do normal checking and processing.
1024                        DatatypeValidator * attrValidator = 0;
1025                        PSVIAttribute *psviAttr = 0;
1026                        bool otherXSI = false;
1027                        const unsigned int attributeUriId = attribute->getQName()->getURI();
1028
1029                        // moving some of the processAttList code here....
1030
1031                        PSVIItem::VALIDITY_STATE attrValid = PSVIItem::VALIDITY_VALID;
1032                        PSVIItem::ASSESSMENT_TYPE attrAssessed = PSVIItem::VALIDATION_FULL;
1033
1034                        const QName* const qName = attribute->getQName();
1035                        // const XMLCh* const prefPtr = qName->getPrefix();
1036                        const XMLCh* const localPart = qName->getLocalPart();
1037
1038                        //  If the uri comes back as the xmlns or xml URI or its just a name
1039                        //  and that name is 'xmlns', then we handle it specially. So set a
1040                        //  boolean flag that lets us quickly below know which we are dealing
1041                        //  with.
1042
1043                        const bool isXSI = (attributeUriId == XMLNamespaceResolver::fSchemaInstanceUriId);
1044                        const bool isNamespaceAttribute = (isXSI | attribute->isXMLNS());
1045
1046                        if (unlikely(isNamespaceAttribute && fGrammarType == Grammar::SchemaGrammarType))
1047                        {
1048                                bool ValueValidate = false;
1049                                bool tokenizeBuffer = false;
1050
1051                                if (attributeUriId == XMLNamespaceResolver::fXMLNSUriId)
1052                                {
1053                                        attrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYURI);
1054                                }
1055                                else if (isXSI)
1056                                {
1057                                        if (XMLString::equals(localPart, SchemaSymbols::fgATT_NILL))
1058                                        {
1059                                                attrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_BOOLEAN);
1060                                                ValueValidate = true;
1061                                        }
1062                                        else if (XMLString::equals(localPart, SchemaSymbols::fgXSI_SCHEMALOCATION))
1063                                        {
1064                                                // use anyURI as the validator
1065                                                // tokenize the data and use the anyURI data for each piece
1066                                                attrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYURI);
1067                                                ValueValidate = false;
1068                                                tokenizeBuffer = true;
1069                                        }
1070                                        else if (XMLString::equals(localPart, SchemaSymbols::fgXSI_NONAMESPACESCHEMALOCATION))
1071                                        {
1072                                                attrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYURI);
1073                                                ValueValidate = false;
1074                                        }
1075                                        else if (XMLString::equals(localPart, SchemaSymbols::fgXSI_TYPE))
1076                                        {
1077                                                attrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_QNAME);
1078                                                ValueValidate = true;
1079                                        }
1080                                        else
1081                                        {
1082                                                otherXSI = true;
1083                                        }
1084                                }
1085
1086                                if (!otherXSI)
1087                                {
1088                                        if (fValidate && attrValidator && ValueValidate)
1089                                        {
1090                                                ValidationContext* const theContext = getValidationContext();
1091
1092                                                if (theContext)
1093                                                {
1094                                                        try
1095                                                        {
1096                                                                if (tokenizeBuffer)
1097                                                                {
1098                                                                        XMLStringTokenizer tokenizer(value, fMemoryManager);
1099                                                                        while (tokenizer.hasMoreTokens())
1100                                                                        {
1101                                                                                attrValidator->validate
1102                                                                                (
1103                                                                                        tokenizer.nextToken(),
1104                                                                                        theContext,
1105                                                                                        fMemoryManager
1106                                                                                );
1107                                                                        }
1108                                                                }
1109                                                                else
1110                                                                {
1111                                                                        attrValidator->validate
1112                                                                        (
1113                                                                                value,
1114                                                                                theContext,
1115                                                                                fMemoryManager
1116                                                                        );
1117                                                                }
1118                                                        }
1119                                                        catch (const XMLException& idve)
1120                                                        {
1121                                                                fValidator->emitError(XMLValid::DatatypeError, idve.getCode(), idve.getMessage());
1122                                                        }
1123                                                }
1124                                        }
1125
1126                                        if (getPSVIHandler())
1127                                        {
1128                                                psviAttr = fPSVIAttrList->getPSVIAttributeToFill(localPart, fUriResolver->getUriForId(attributeUriId));
1129
1130                                                XSSimpleTypeDefinition *validatingType = (attrValidator)
1131                                                        ? (XSSimpleTypeDefinition *)fModel->getXSObject(attrValidator)
1132                                                        : 0;
1133                                                // no attribute declarations for these...
1134                                                psviAttr->reset
1135                                                (
1136                                                        fRootElemName
1137                                                        , PSVIItem::VALIDITY_NOTKNOWN
1138                                                        , PSVIItem::VALIDATION_NONE
1139                                                        , validatingType
1140                                                        , 0
1141                                                        , 0
1142                                                        , false
1143                                                        , 0
1144                                                        , attrValidator
1145                                                );
1146                                        }
1147                                }
1148                        } // if (isNamespaceAttribute && (fGrammarType == Grammar::SchemaGrammarType))
1149
1150                        if (likely(!isNamespaceAttribute || fGrammarType == Grammar::DTDGrammarType || otherXSI))
1151                        {
1152                                // Some checking for attribute wild card first (for schema)
1153                                bool laxThisOne = false;
1154                                bool skipThisOne = false;
1155
1156                                XMLAttDef * attDefForWildCard = 0;
1157                                XMLAttDef * attDef = 0;
1158
1159                                if (fGrammarType == Grammar::SchemaGrammarType)
1160                                {
1161                                        ComplexTypeInfo *currType = 0;
1162                                        DatatypeValidator *currDV = 0;
1163
1164                                        if (fValidate)
1165                                        {
1166                                                currType = fSchemaValidator->getCurrentTypeInfo();
1167                                                if (!currType)
1168                                                {
1169                                                        currDV = fSchemaValidator->getCurrentDatatypeValidator();
1170                                                }
1171                                        }
1172
1173                                        //retrieve the att def
1174                                        SchemaAttDef* attWildCard = 0;
1175                                        if (currType)
1176                                        {
1177                                                attDef = currType->getAttDef(localPart, attributeUriId);
1178                                                attWildCard = currType->getAttWildCard();
1179                                        }
1180                                        else if (!currDV)
1181                                        { // check explicitly-set wildcard
1182                                                attDef = ((SchemaElementDecl*)elemDecl)->getAttDef(localPart, attributeUriId);
1183                                                attWildCard = ((SchemaElementDecl*)elemDecl)->getAttWildCard();
1184                                        }
1185
1186                                        // if not found or faulted in - check for a matching wildcard attribute
1187                                        // if no matching wildcard attribute, check (un)qualifed cases and flag
1188                                        // appropriate errors
1189                                        if (!attDef || (attDef->getCreateReason() == XMLAttDef::JustFaultIn))
1190                                        {
1191                                                if (attWildCard)
1192                                                {
1193                                                        //if schema, see if we should lax or skip the validation of this attribute
1194                                                        if (anyAttributeValidation(attWildCard, attributeUriId, skipThisOne, laxThisOne))
1195                                                        {
1196                                                                if (!skipThisOne)
1197                                                                {
1198                                                                        Grammar* sGrammar = fGrammarList.getGrammar(attributeUriId);
1199                                                                        if (unlikely(sGrammar == NULL))
1200                                                                        {
1201                                                                                sGrammar = fGrammarResolver->getGrammar((*fUriResolver)[attributeUriId]);
1202                                                                                fGrammarList.setGrammar(attributeUriId, sGrammar);
1203                                                                        }
1204
1205                                                                        if (sGrammar && sGrammar->getGrammarType() == Grammar::SchemaGrammarType)
1206                                                                        {
1207                                                                                RefHashTableOf<XMLAttDef>* attRegistry =
1208                                                                                        ((SchemaGrammar*)sGrammar)->getAttributeDeclRegistry();
1209
1210                                                                                if (attRegistry)
1211                                                                                {
1212                                                                                        attDefForWildCard = attRegistry->get(localPart);
1213                                                                                }
1214                                                                        }
1215                                                                }
1216                                                        }
1217                                                }
1218                                                else if (currType)
1219                                                {
1220                                                        // not found, see if the attDef should be qualified or not
1221                                                        attDef = currType->getAttDef
1222                                                        (
1223                                                                localPart
1224                                                                , attributeUriId == XMLNamespaceResolver::fEmptyUriId
1225                                                                ? fUriResolver->resolveUriId(fGrammar->getTargetNamespace())
1226                                                                : XMLNamespaceResolver::fEmptyUriId
1227                                                        );
1228
1229                                                        if (fValidate && attDef && attDef->getCreateReason() != XMLAttDef::JustFaultIn)
1230                                                        {
1231                                                                XMLValid::Codes errCode =
1232                                                                        (attributeUriId == XMLNamespaceResolver::fEmptyUriId)
1233                                                                        ? XMLValid::AttributeNotQualified
1234                                                                        : XMLValid::AttributeNotUnQualified;
1235
1236                                                                fValidator->emitError(errCode, attDef->getFullName());
1237
1238                                                                fPSVIElemContext.fErrorOccurred = true;
1239                                                                if (getPSVIHandler())
1240                                                                {
1241                                                                        attrValid = PSVIItem::VALIDITY_INVALID;
1242                                                                }
1243                                                        }
1244                                                }
1245                                        } // if (!attDef || (attDef->getCreateReason() == XMLAttDef::JustFaultIn))
1246                                }
1247                                else // if (fGrammarType == Grammar::DTDGrammarType)
1248                                {
1249                                        //  Find this attribute within the parent element. We pass both
1250                                        //  the uriID/name and the raw QName buffer, since we don't know
1251                                        //  how the derived validator and its elements store attributes.
1252                                        attDef = ((DTDElementDecl*)elemDecl)->getAttDef(qName->getRawName());
1253                                }
1254
1255                DEBUG_TRANSITION_MESSAGE(qName << ":attDef=" << attDef)
1256
1257                                if (attDef)
1258                                {
1259                                        attDef->setLastOccurrence(attribute->fLastOccurence);
1260                                }
1261                                else
1262                                {
1263                                        if (fGrammarType == Grammar::SchemaGrammarType)
1264                                        {
1265                                                // if we've found either an attDef or an attDefForWildCard,
1266                                                // then we're doing full validation and it may still be valid.
1267                                                if (!attDefForWildCard)
1268                                                {
1269                                                        fPSVIElemContext.fErrorOccurred |= !(laxThisOne & skipThisOne);
1270
1271                                                        if (getPSVIHandler())
1272                                                        {
1273                                                                if (!laxThisOne && !skipThisOne)
1274                                                                {
1275                                                                        attrValid = PSVIItem::VALIDITY_INVALID;
1276                                                                }
1277                                                                else
1278                                                                {
1279                                                                        attrValid = PSVIItem::VALIDITY_NOTKNOWN;
1280                                                                        attrAssessed = (laxThisOne) ? PSVIItem::VALIDATION_PARTIAL : PSVIItem::VALIDATION_NONE;
1281                                                                }
1282                                                        }
1283                                                }
1284                                        }
1285
1286                                        if (unlikely(fValidate && !attDefForWildCard && !skipThisOne && !laxThisOne))
1287                                        {
1288                                                //
1289                                                //  Its not valid for this element, so issue an error if we are
1290                                                //  validating.
1291                                                //
1292                                                XMLBuffer bufMsg;
1293                                                if (attributeUriId != XMLNamespaceResolver::fEmptyUriId)
1294                                                {
1295                                                        bufMsg.append(chOpenCurly);
1296                                                        bufMsg.append(fUriResolver->getUriForId(attributeUriId));
1297                                                        bufMsg.append(chCloseCurly);
1298                                                }
1299                                                bufMsg.append(localPart);
1300                                                fValidator->emitError
1301                                                (
1302                                                        XMLValid::AttNotDefinedForElement
1303                                                        , bufMsg.getRawBuffer()
1304                                                        , element->getQName()->getLocalPart()
1305                                                );
1306                                        }
1307                                }
1308
1309                /// VALIDATE THE ATTRIBUTE VALUE BASED ON THE DEFINITION
1310
1311                if (attDefForWildCard)
1312                {
1313                    validateAttValue(elemDecl, attDefForWildCard, value, attrValidator, attrValid, attType);
1314                }
1315                else if (attDef)
1316                {
1317                    validateAttValue(elemDecl, attDef, value, attrValidator, attrValid, attType);
1318                }
1319                else if (fGrammarType == Grammar::SchemaGrammarType)
1320                {
1321                    attrValidator = getAnySimpleTypeValidator();
1322                }
1323
1324
1325                                // now fill in the PSVIAttributes entry for this attribute:
1326                                if (getPSVIHandler() && (fGrammarType == Grammar::SchemaGrammarType))
1327                                {
1328                                        psviAttr = fPSVIAttrList->getPSVIAttributeToFill(localPart, fUriResolver->getUriForId(attributeUriId));
1329                                        SchemaAttDef * actualAttDef = 0;
1330                                        if (attDef)
1331                                                actualAttDef = (SchemaAttDef*)attDef;
1332                                        else if (attDefForWildCard)
1333                                                actualAttDef = (SchemaAttDef*)attDefForWildCard;
1334
1335                                        if (actualAttDef)
1336                                        {
1337                                                XSAttributeDeclaration *attrDecl = (XSAttributeDeclaration *)fModel->getXSObject(actualAttDef);
1338                                                DatatypeValidator * attrDataType = actualAttDef->getDatatypeValidator();
1339                                                XSSimpleTypeDefinition *validatingType = (XSSimpleTypeDefinition *)fModel->getXSObject(attrDataType);
1340                        if (attrValid != PSVIItem::VALIDITY_VALID)
1341                                                {
1342                                                        psviAttr->reset
1343                                                        (
1344                                                                fRootElemName
1345                                                                , attrValid
1346                                                                , attrAssessed
1347                                                                , validatingType
1348                                                                , 0
1349                                                                , actualAttDef->getValue()
1350                                                                , false
1351                                                                , attrDecl
1352                                                                , 0
1353                                                        );
1354                                                }
1355                                                else
1356                                                {
1357                                                        XSSimpleTypeDefinition *memberType = 0;
1358                                                        if (validatingType->getVariety() == XSSimpleTypeDefinition::VARIETY_UNION)
1359                                                                memberType = (XSSimpleTypeDefinition *)fModel->getXSObject(attrValidator);
1360                                                        psviAttr->reset
1361                                                        (
1362                                                                fRootElemName
1363                                                                , attrValid
1364                                                                , attrAssessed
1365                                                                , validatingType
1366                                                                , memberType
1367                                                                , actualAttDef->getValue()
1368                                                                , false
1369                                                                , attrDecl
1370                                                                , (memberType) ? attrValidator : attrDataType
1371                                                        );
1372                                                }
1373                                        }
1374                                        else
1375                                        {
1376                                                psviAttr->reset
1377                                                (
1378                                                        fRootElemName
1379                                                        , attrValid
1380                                                        , attrAssessed
1381                                                        , 0
1382                                                        , 0
1383                                                        , 0
1384                                                        , false
1385                                                        , 0
1386                                                        , 0
1387                                                );
1388                                        }
1389                                }
1390                        }
1391                } // end of if (fDoNamespaces) { ... } else { ... }
1392
1393        #ifdef __GNUC__
1394        #warning "TODO: move the fAttrList into the XMLParserImpl and construct them directly there with all the non-derived values set"
1395        #endif
1396                XMLAttr * curAttr;
1397
1398        const XMLSize_t length = attributeList[index].getLength();
1399
1400                if (unlikely(index >= fAttrList.size()))
1401                {
1402                        curAttr = new (fMemoryManager) XMLAttr
1403                        (
1404                                attribute->getQName()
1405                                , value
1406                , length
1407                                , attType
1408                                , true
1409                                , fMemoryManager
1410                        );
1411
1412                        fAttrList.addElement(curAttr);
1413                }
1414                else
1415                {
1416                        curAttr = fAttrList.elementAt(index);
1417                        curAttr->set
1418                        (
1419                                attribute->getQName()
1420                , value
1421                , length
1422                                , attType
1423                        );
1424                        curAttr->setSpecified(true);
1425                }
1426
1427        }
1428
1429        /// ------------------------------ POST ATTRIBUTE VALIDATION ---------------------------------
1430
1431        if (!fDoNamespaces)
1432        {
1433                //  Ok, so lets get an enumerator for the attributes of this element
1434                //  and run through them for well formedness and validity checks. But
1435                //  make sure that we had any attributes before we do it, since the list
1436                //  would have have gotten faulted in anyway.
1437                if (elemDecl->hasAttDefs())
1438                {
1439                        // N.B.:  this assumes DTD validation.
1440                        XMLAttDefList & attDefList = elemDecl->getAttDefList();
1441                        for(XMLSize_t i = 0; i < attDefList.getAttDefCount(); i++)
1442                        {
1443                                // Get the current att def, for convenience and its def type
1444                                const XMLAttDef & curDef = attDefList.getAttDef(i);
1445                                const XMLAttDef::DefAttTypes defType = curDef.getDefaultType();
1446
1447                if (unlikely(curDef.getLastOccurrence() < element->fLastOccurence))
1448                                { // did not occur
1449                                        if (fValidate)
1450                                        {
1451                                                // If we are validating and its required, then an error
1452                                                if (defType == XMLAttDef::Required)
1453                                                {
1454                                                        fValidator->emitError(XMLValid::RequiredAttrNotProvided, curDef.getFullName());
1455                                                }
1456                                                else if ((defType == XMLAttDef::Default) || (defType == XMLAttDef::Fixed))
1457                                                {
1458                                                        if (fStandalone && curDef.isExternal())
1459                                                        {
1460                                                                // XML 1.0 Section 2.9
1461                                                                // Document is standalone, so attributes must not be defaulted.
1462                                                                fValidator->emitError(XMLValid::NoDefAttForStandalone, curDef.getFullName(), elemDecl->getFullName());
1463
1464                                                        }
1465                                                }
1466                                        }
1467
1468                                        // Fault in the value if needed, and bump the att count
1469                                        if ((defType == XMLAttDef::Default) || (defType == XMLAttDef::Fixed))
1470                                        {
1471                                                // Let the validator pass judgement on the attribute value
1472                                                if (fValidate)
1473                                                {
1474                                                        fValidator->validateAttrValue
1475                                                        (
1476                                                                &curDef
1477                                                                , curDef.getValue()
1478                                                                , false
1479                                                                , elemDecl
1480                                                        );
1481                                                }
1482
1483                                                XMLAttr * curAtt;
1484                                                if (attributeCount >= fAttrList.size())
1485                                                {
1486                                                        curAtt = new (fMemoryManager) XMLAttr
1487                                                        (
1488                                                                curDef.getAttName()
1489                                                                , curDef.getValue()
1490                                                                , curDef.getType()
1491                                                                , false
1492                                                                , fMemoryManager
1493                                                        );
1494                                                        fAttrList.addElement(curAtt);
1495                                                }
1496                                                else
1497                                                {
1498                                                        curAtt = fAttrList.elementAt(attributeCount);
1499                                                        curAtt->set
1500                                                        (
1501                                                                curDef.getAttName()
1502                                                                , curDef.getValue()
1503                                                                , curDef.getType()
1504                                                        );
1505                                                        curAtt->setSpecified(false);
1506                                                }
1507                                                attributeCount++;
1508                                        }
1509                                }
1510                        }
1511                }
1512
1513                //  If empty, validate content right now if we are validating and then
1514                //  pop the element stack top. Else, we have to update the current stack
1515                //  top's namespace mapping elements.
1516                if (isEmpty)
1517                {
1518                        // If validating, then insure that its legal to have no content
1519                        if (fValidate)
1520                        {
1521                                XMLSize_t failure;
1522                                bool res = fValidator->checkContent(elemDecl, ((XMLElementDecl**)0), 0, &failure);
1523                                if (!res)
1524                                {
1525                                        fValidator->emitError
1526                                        (
1527                                                XMLValid::ElementNotValidForContent
1528                                                , elemDecl->getFullName()
1529                                                , elemDecl->getFormattedContentModel()
1530                                        );
1531                                }
1532                        }
1533
1534                        // Pop the element stack back off since it'll never be used now
1535                        fElemStack.popTop();
1536
1537                        // If the elem stack is empty, then it was an empty root
1538                        if (!isRoot)
1539                        {
1540                                // Restore the validation flag
1541                                fValidate = fElemStack.getValidationFlag();
1542                        }
1543                }
1544
1545                //  If we have a document handler, then tell it about this start tag. We
1546                //  don't have any URI id to send along, so send fEmptyNamespaceId. We also do not send
1547                //  any prefix since its just one big name if we are not doing namespaces.
1548                if (fDocHandler)
1549                {
1550                        QName * origQName = elemDecl->getElementName();
1551                        elemDecl->setElementName(element->fQName);
1552
1553                        fDocHandler->startElement
1554                        (
1555                                *elemDecl
1556                                , XMLNamespaceResolver::fEmptyUriId
1557                                , 0
1558                                , fAttrList
1559                                , attributeCount
1560                                , isEmpty
1561                                , isRoot
1562                        );
1563
1564                        elemDecl->setElementName(origQName);
1565                }
1566        }
1567        else // if (fDoNamespaces)
1568        {
1569                const QName * qName = element->getQName();
1570
1571                //  If doing DTD's, Ask the element to clear the 'provided' flag on all of the att defs
1572                //  that it owns, and to return us a boolean indicating whether it has
1573                //  any defs.  If schemas are being validated, the complexType
1574                // at the top of the SchemaValidator's stack will
1575                // know what's best.  REVISIT:  don't modify grammar at all; eliminate
1576                // this step...
1577                ComplexTypeInfo *currType = 0;
1578                DatatypeValidator *currDV = 0;
1579                //if (fGrammar->getGrammarType() == Grammar::SchemaGrammarType && fValidate)
1580                if ((fGrammarType == Grammar::SchemaGrammarType) && fValidate)
1581                {
1582                        currType = fSchemaValidator->getCurrentTypeInfo();
1583                        if (!currType)
1584                        {
1585                                currDV = fSchemaValidator->getCurrentDatatypeValidator();
1586                        }
1587                }
1588
1589                const bool hasDefs = (currType && fValidate) ? currType->hasAttDefs() : elemDecl->hasAttDefs();
1590
1591                //  Now, if there are any attributes declared by this element, let's
1592                //  go through them and make sure that any required ones are provided,
1593                //  and fault in any fixed ones and defaulted ones that are not provided
1594                //  literally.
1595                if (unlikely(hasDefs))
1596                {
1597                        // Check after all specified attrs are scanned
1598                        // (1) report error for REQUIRED attrs that are missing (V_TAGc)
1599                        // (2) add default attrs if missing (FIXED and NOT_FIXED)
1600
1601                        XMLAttDefList & attDefList =
1602                                getAttDefList((fGrammarType == Grammar::SchemaGrammarType), currType, elemDecl);
1603
1604                        for(XMLSize_t i = 0; i < attDefList.getAttDefCount(); i++)
1605                        {
1606                                // Get the current att def, for convenience and its def type
1607                                const XMLAttDef *curDef = &attDefList.getAttDef(i);
1608                                const XMLAttDef::DefAttTypes defType = curDef->getDefaultType();
1609
1610                                // if this attribute is not present within the element
1611                                if (unlikely(curDef->getLastOccurrence() < element->fLastOccurence))
1612                                {
1613                                        // note that since there is no attribute information
1614                                        // item present, there is no PSVI infoset to augment here *except*
1615                                        // that the element is invalid
1616
1617                                        //the attribute is not provided
1618                                        if (fValidate)
1619                                        {
1620                                                // If we are validating and its required, then an error
1621                                                if ((defType == XMLAttDef::Required) || (defType == XMLAttDef::Required_And_Fixed))
1622                                                {
1623                                                        fValidator->emitError(XMLValid::RequiredAttrNotProvided, curDef->getFullName());
1624
1625                                                        if ((fGrammarType == Grammar::SchemaGrammarType))
1626                                                        {
1627                                                                fPSVIElemContext.fErrorOccurred = true;
1628                                                        }
1629                                                }
1630                                                else if ((defType == XMLAttDef::Default) || (defType == XMLAttDef::Fixed))
1631                                                {
1632                                                        if (fStandalone && curDef->isExternal())
1633                                                        {
1634                                                                // XML 1.0 Section 2.9
1635                                                                // Document is standalone, so attributes must not be defaulted.
1636                                                                fValidator->emitError(XMLValid::NoDefAttForStandalone, curDef->getFullName(), elemDecl->getFullName());
1637                                                                if ((fGrammarType == Grammar::SchemaGrammarType))
1638                                                                {
1639                                                                        fPSVIElemContext.fErrorOccurred = true;
1640                                                                }
1641                                                        }
1642                                                }
1643                                        }
1644
1645                                        //  Fault in the value if needed, and bump the att count.
1646                                        if ((defType == XMLAttDef::Default) || (defType == XMLAttDef::Fixed))
1647                                        {
1648                                                // Let the validator pass judgement on the attribute value
1649                                                if (fValidate)
1650                                                {
1651                                                        fValidator->validateAttrValue
1652                                                        (
1653                                                                curDef
1654                                                                , curDef->getValue()
1655                                                                , false
1656                                                                , elemDecl
1657                                                        );
1658                                                }
1659
1660                                                XMLAttr * curAttr;
1661                                                if (attributeCount >= fAttrList.size())
1662                                                {
1663                                                        curAttr = new (fMemoryManager) XMLAttr(fMemoryManager);
1664                                                        fValidator->faultInAttr(*curAttr, *curDef);
1665                                                        fAttrList.addElement(curAttr);
1666                                                }
1667                                                else
1668                                                {
1669                                                        curAttr = fAttrList.elementAt(attributeCount);
1670                                                        fValidator->faultInAttr(*curAttr, *curDef);
1671                                                }
1672
1673                                                if (fGrammarType == Grammar::DTDGrammarType)
1674                                                {
1675                                                        //  Map the new attribute's prefix to a URI id and store that in the attribute object.
1676                                                        curAttr->setURIId(fUriResolver->getUriIdForPrefix(curAttr->getPrefix(), fContextId));
1677                                                }
1678
1679                                                // Indicate it was not explicitly specified and bump count
1680                                                curAttr->setSpecified(false);
1681
1682                                                // increase the attributeCount
1683                                                attributeCount++;
1684
1685                                                if (getPSVIHandler() && (fGrammarType == Grammar::SchemaGrammarType))
1686                                                {
1687                                                        QName * attName = ((SchemaAttDef *)curDef)->getAttName();
1688                                                        PSVIAttribute *defAttrToFill = fPSVIAttrList->getPSVIAttributeToFill
1689                                                        (
1690                                                                attName->getLocalPart()
1691                                                                , fUriResolver->getUriForId(attName->getURI())
1692                                                        );
1693                                                        XSAttributeDeclaration *defAttrDecl = (XSAttributeDeclaration *)fModel->getXSObject((void *)curDef);
1694                                                        DatatypeValidator * attrDataType = ((SchemaAttDef *)curDef)->getDatatypeValidator();
1695                                                        XSSimpleTypeDefinition *defAttrType =
1696                                                                (XSSimpleTypeDefinition*)fModel->getXSObject(attrDataType);
1697                                                        // would have occurred during validation of default value
1698                                                        if(fSchemaValidator->getErrorOccurred())
1699                                                        {
1700                                                                defAttrToFill->reset
1701                                                                (
1702                                                                        fRootElemName
1703                                                                        , PSVIItem::VALIDITY_INVALID
1704                                                                        , PSVIItem::VALIDATION_FULL
1705                                                                        , defAttrType
1706                                                                        , 0
1707                                                                        , curDef->getValue()
1708                                                                        , true
1709                                                                        , defAttrDecl
1710                                                                        , 0
1711                                                                );
1712                                                        }
1713                                                        else
1714                                                        {
1715                                                                XSSimpleTypeDefinition *defAttrMemberType = 0;
1716                                                                if (defAttrType->getVariety() == XSSimpleTypeDefinition::VARIETY_UNION)
1717                                                                {
1718                                                                        defAttrMemberType = (XSSimpleTypeDefinition *)fModel->getXSObject
1719                                                                        (
1720                                                                                fSchemaValidator->getMostRecentAttrValidator()
1721                                                                        );
1722                                                                }
1723                                                                defAttrToFill->reset(
1724                                                                        fRootElemName
1725                                                                        , PSVIItem::VALIDITY_VALID
1726                                                                        , PSVIItem::VALIDATION_FULL
1727                                                                        , defAttrType
1728                                                                        , defAttrMemberType
1729                                                                        , curDef->getValue()
1730                                                                        , true
1731                                                                        , defAttrDecl
1732                                                                        , (defAttrMemberType)?fSchemaValidator->getMostRecentAttrValidator():attrDataType
1733                                                                );
1734                                                        }
1735                                                        defAttrToFill->setValue(curDef->getValue());
1736                                                }
1737                                        }
1738                                }
1739                                else // attribute was provided for this definition
1740                                {
1741                                        // TODO: is it safe to move the prohibited attribute validation into the attribute scan?
1742
1743                                        // (schema) report error for PROHIBITED attrs that are present (V_TAGc)
1744                                        if (defType == XMLAttDef::Prohibited && fValidate)
1745                                        {
1746                                                fValidator->emitError
1747                                                (
1748                                                        XMLValid::ProhibitedAttributePresent
1749                                                        , curDef->getFullName()
1750                                                );
1751                                                if ((fGrammarType == Grammar::SchemaGrammarType))
1752                                                {
1753                                                        fPSVIElemContext.fErrorOccurred = true;
1754                                                        if (getPSVIHandler())
1755                                                        {
1756                                                                QName * attQName = ((SchemaAttDef *)curDef)->getAttName();
1757                                                                // bad luck...
1758                                                                PSVIAttribute *prohibitedAttr = fPSVIAttrList->getAttributePSVIByName
1759                                                                (
1760                                                                        attQName->getLocalPart()
1761                                                                        , fUriResolver->getUriForId(attQName->getURI())
1762                                                                );
1763                                                                prohibitedAttr->updateValidity(PSVIItem::VALIDITY_INVALID);
1764                                                        }
1765                                                }
1766                                        }
1767                                }
1768                        }
1769                }
1770
1771                const unsigned int uriId = element->getQName()->getURI();
1772
1773                if (fGrammarType == Grammar::SchemaGrammarType)
1774                {
1775                        // activate identity constraints
1776                        if (fGrammar && toCheckIdentityConstraint())
1777                        {
1778                                fICHandler->activateIdentityConstraint
1779                                (
1780                                          (SchemaElementDecl*)elemDecl
1781                                        , (int)fElemStack.getLevel()
1782                                        , uriId
1783                                        , qName->getPrefix()
1784                                        , fAttrList
1785                                        , attributeCount
1786                                        , fValidationContext
1787                                );
1788                        }
1789                }
1790
1791                // Since the element may have default values, call start tag now regardless if it is empty or not
1792                // If we have a document handler, then tell it about this start tag
1793                if (fDocHandler)
1794                {
1795                        QName * origQName = elemDecl->getElementName();
1796                        elemDecl->setElementName(qName);
1797
1798                        fDocHandler->startElement
1799                        (
1800                                *elemDecl
1801                                , uriId
1802                                , qName->getPrefix()
1803                                , fAttrList
1804                                , attributeCount
1805                                , false
1806                                , isRoot
1807                        );
1808
1809                        elemDecl->setElementName(origQName);
1810                }
1811
1812                // if we have a PSVIHandler, now's the time to call
1813                // its handleAttributesPSVI method:
1814                if (fPSVIHandler && fGrammarType == Grammar::SchemaGrammarType)
1815                {
1816                        QName * eName = elemDecl->getElementName();
1817                        fPSVIHandler->handleAttributesPSVI
1818                        (
1819                                eName->getLocalPart()
1820                                , fUriResolver->getUriForId(eName->getURI())
1821                                , fPSVIAttrList
1822                        );
1823                }
1824
1825                //  If empty, validate content right now if we are validating and then
1826                //  pop the element stack top. Else, we have to update the current stack
1827                //  top's namespace mapping elements.
1828                if (isEmpty)
1829                {
1830                        // Pop the element stack back off since it'll never be used now
1831                        fElemStack.popTop();
1832
1833                        // reset current type info
1834                        DatatypeValidator* psviMemberType = 0;
1835                        if (fGrammarType == Grammar::SchemaGrammarType)
1836                        {
1837                                if (fValidate && elemDecl->isDeclared())
1838                                {
1839                                        fPSVIElemContext.fCurrentTypeInfo = fSchemaValidator->getCurrentTypeInfo();
1840                                        if (!fPSVIElemContext.fCurrentTypeInfo)
1841                                                fPSVIElemContext.fCurrentDV = fSchemaValidator->getCurrentDatatypeValidator();
1842                                        else
1843                                                fPSVIElemContext.fCurrentDV = 0;
1844                                        if (fPSVIHandler)
1845                                        {
1846                                                if (XMLString::stringLen(fPSVIElemContext.fNormalizedValue) == 0)
1847                                                        fPSVIElemContext.fNormalizedValue = 0;
1848                                        }
1849                                }
1850                                else
1851                                {
1852                                        fPSVIElemContext.fCurrentDV = 0;
1853                                        fPSVIElemContext.fCurrentTypeInfo = 0;
1854                                        fPSVIElemContext.fNormalizedValue = 0;
1855                                }
1856                        }
1857
1858                        // If validating, then insure that its legal to have no content
1859                        if (fValidate)
1860                        {
1861                                XMLSize_t failure;
1862                                bool res = fValidator->checkContent(elemDecl, ((XMLElementDecl**)0), 0, &failure);
1863                                if (!res)
1864                                {
1865                                        fValidator->emitError
1866                                        (
1867                                                XMLValid::ElementNotValidForContent
1868                                                , elemDecl->getFullName()
1869                                                , elemDecl->getFormattedContentModel()
1870                                        );
1871                                }
1872
1873                                if (fGrammarType == Grammar::SchemaGrammarType)
1874                                {
1875                                        if (fSchemaValidator->getErrorOccurred())
1876                                        {
1877                                                fPSVIElemContext.fErrorOccurred = true;
1878                                        }
1879                                        else
1880                                        {
1881                                                if (fPSVIHandler)
1882                                                {
1883                                                        fPSVIElemContext.fIsSpecified = fSchemaValidator->getIsElemSpecified();
1884                                                        if(fPSVIElemContext.fIsSpecified)
1885                                                                fPSVIElemContext.fNormalizedValue = ((SchemaElementDecl *)elemDecl)->getDefaultValue();
1886                                                }
1887                                                // note that if we're empty, won't be a current DV
1888                                                if (fPSVIElemContext.fCurrentDV && fPSVIElemContext.fCurrentDV->getType() == DatatypeValidator::Union)
1889                                                        psviMemberType = fValidationContext->getValidatingMemberType();
1890                                        }
1891
1892                                        // call matchers and de-activate context
1893                                        if (toCheckIdentityConstraint())
1894                                        {
1895                                                fICHandler->deactivateContext
1896                                                (
1897                                                        (SchemaElementDecl *)elemDecl
1898                                                        , fContent.getRawBuffer()
1899                                                        , fValidationContext
1900                                                        , fPSVIElemContext.fCurrentDV
1901                                                );
1902                                        }
1903
1904                                }
1905                        }
1906                        else if (fGrammarType == Grammar::SchemaGrammarType)
1907                        {
1908                                fSchemaValidator->resetNillable();
1909                        }
1910
1911                        if (fGrammarType == Grammar::SchemaGrammarType)
1912                        {
1913                                if (fPSVIHandler)
1914                                {
1915                                        endElementPSVI((SchemaElementDecl*)elemDecl, psviMemberType);
1916                                }
1917                        }
1918
1919                        // If we have a doc handler, tell it about the end tag
1920                        if (fDocHandler)
1921                        {
1922                                QName * origQName = elemDecl->getElementName();
1923                                elemDecl->setElementName(qName);
1924
1925                                fDocHandler->endElement
1926                                (
1927                                        *elemDecl
1928                                        , uriId
1929                                        , isRoot
1930                                        , qName->getPrefix()
1931                                );
1932
1933                                elemDecl->setElementName(origQName);
1934                        }
1935
1936                        // If the elem stack is empty, then it was an empty root
1937                        if (!isRoot)
1938                        {
1939                                // Restore the grammar
1940                                fGrammar = fElemStack.getCurrentGrammar();
1941                                fGrammarType = fGrammar->getGrammarType();
1942
1943                                if (fGrammarType == Grammar::SchemaGrammarType && !fValidator->handlesSchema())
1944                                {
1945                                        if (fValidatorFromUser)
1946                                                ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoSchemaValidator, fMemoryManager);
1947                                        else
1948                                        {
1949                                                fValidator = fSchemaValidator;
1950                                        }
1951                                }
1952                                else if (fGrammarType == Grammar::DTDGrammarType && !fValidator->handlesDTD())
1953                                {
1954                                        if (fValidatorFromUser)
1955                                                ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoDTDValidator, fMemoryManager);
1956                                        else
1957                                        {
1958                                                fValidator = fDTDValidator;
1959                                        }
1960                                }
1961
1962                                fValidator->setGrammar(fGrammar);
1963
1964                                // Restore the validation flag
1965                                fValidate = fElemStack.getValidationFlag();
1966                        }
1967                }
1968
1969                if (fGrammarType == Grammar::SchemaGrammarType)
1970                {
1971                        // send a partial element psvi
1972                        if (fPSVIHandler)
1973                        {
1974                                ComplexTypeInfo   * curTypeInfo = 0;
1975                                DatatypeValidator * curDV = 0;
1976                                XSTypeDefinition  * typeDef = 0;
1977
1978                                if (fValidate && elemDecl->isDeclared())
1979                                {
1980                                        curTypeInfo = fSchemaValidator->getCurrentTypeInfo();
1981
1982                                        if (curTypeInfo)
1983                                        {
1984                                                typeDef = (XSTypeDefinition*) fModel->getXSObject(curTypeInfo);
1985                                        }
1986                                        else
1987                                        {
1988                                                curDV = fSchemaValidator->getCurrentDatatypeValidator();
1989
1990                                                if (curDV)
1991                                                {
1992                                                        typeDef = (XSTypeDefinition*) fModel->getXSObject(curDV);
1993                                                }
1994                                        }
1995                                }
1996
1997                                fPSVIElement->reset
1998                                (
1999                                          PSVIElement::VALIDITY_NOTKNOWN
2000                                        , PSVIElement::VALIDATION_NONE
2001                                        , fRootElemName
2002                                        , fSchemaValidator->getIsElemSpecified()
2003                                        , (elemDecl->isDeclared()) ? (XSElementDeclaration*) fModel->getXSObject(elemDecl) : 0
2004                                        , typeDef
2005                                        , 0 //memberType
2006                                        , fModel
2007                                        , ((SchemaElementDecl*)elemDecl)->getDefaultValue()
2008                                        , 0
2009                                        , 0
2010                                        , 0
2011                                );
2012
2013
2014                                fPSVIHandler->handlePartialElementPSVI
2015                                (
2016                                        elemDecl->getBaseName()
2017                                        , fUriResolver->getUriForId(elemDecl->getURI())
2018                                        , fPSVIElement
2019                                );
2020
2021                        }
2022
2023                        // not empty
2024                        fErrorStack->push(fPSVIElemContext.fErrorOccurred);
2025                }
2026        }
2027
2028        return elemDecl;
2029}
2030
2031// --------------------------------------------------------------------------------------------------------
2032// HANDLE END TAG
2033// --------------------------------------------------------------------------------------------------------
2034
2035void IGXMLScanner::handleEndTag
2036(
2037        XMLElementDecl * const                  elemDecl
2038        , const unsigned int                    uriId
2039        , const XMLSize_t                               readerNum
2040        , const bool                                    isRoot
2041        , XMLElementDecl **                             children
2042        , const XMLSize_t                               childCount
2043)
2044{
2045//      //  Pop the stack of the element we are supposed to be ending. Remember
2046//      //  that we don't own this. The stack just keeps them and reuses them.
2047
2048        // these get initialized below
2049        const ElemStack::StackElem * topElem = 0;
2050
2051        // Make sure that its the end of the element that we expect
2052        // special case for schema validation, whose element decls,
2053        // obviously don't contain prefix information
2054
2055        topElem = fElemStack.topElement();
2056
2057        // Make sure we are back on the same reader as where we started
2058        if (unlikely(topElem->fReaderNum != readerNum))
2059        {
2060                emitError(XMLErrs::PartialTagMarkupError);
2061        }
2062
2063        if (fGrammarType == Grammar::SchemaGrammarType)
2064        {
2065                // reset error occurred
2066                fPSVIElemContext.fErrorOccurred = fErrorStack->pop();
2067                if (fValidate && elemDecl->isDeclared())
2068                {
2069                        fPSVIElemContext.fCurrentTypeInfo = fSchemaValidator->getCurrentTypeInfo();
2070                        if(!fPSVIElemContext.fCurrentTypeInfo)
2071                                fPSVIElemContext.fCurrentDV = fSchemaValidator->getCurrentDatatypeValidator();
2072                        else
2073                                fPSVIElemContext.fCurrentDV = 0;
2074
2075                        if(fPSVIHandler)
2076                        {
2077                                //fPSVIElemContext.fNormalizedValue = fSchemaValidator->getNormalizedValue();
2078                                if (fPSVIElemContext.fNormalizedValue && *fPSVIElemContext.fNormalizedValue == 0)
2079                                        fPSVIElemContext.fNormalizedValue = 0;
2080                        }
2081                }
2082                else
2083                {
2084                        fPSVIElemContext.fCurrentDV = 0;
2085                        fPSVIElemContext.fCurrentTypeInfo = 0;
2086                        fPSVIElemContext.fNormalizedValue = 0;
2087                }
2088        }
2089
2090        //  If validation is enabled, then lets pass him the list of children and
2091        //  this element and let him validate it.
2092        DatatypeValidator* psviMemberType = 0;
2093
2094        if (fValidate)
2095        {
2096                // XML1.0-3rd
2097                // Validity Constraint:
2098                // The declaration matches EMPTY and the element has no content (not even
2099                // entity references, comments, PIs or white space).
2100                //
2101                if (fGrammarType == Grammar::DTDGrammarType
2102                && (topElem->fCommentOrPISeen)
2103                && ((DTDElementDecl*)elemDecl)->getModelType() == DTDElementDecl::Empty)
2104                {
2105                        fValidator->emitError(XMLValid::EmptyElemHasContent, elemDecl->getFullName());
2106                }
2107
2108                XMLSize_t failure;
2109                bool res = fValidator->checkContent
2110                (
2111                   elemDecl
2112                   , children
2113                   , childCount
2114                   , &failure
2115                );
2116
2117                if (unlikely(!res))
2118                {
2119                        //  One of the elements is not valid for the content. NOTE that
2120                        //  if no children were provided but the content model requires
2121                        //  them, it comes back with a zero value. But we cannot use that
2122                        //  to index the child array in this case, and have to put out a
2123                        //  special message.
2124                        if (!childCount)
2125                        {
2126                                fValidator->emitError
2127                                (
2128                                        XMLValid::EmptyNotValidForContent
2129                                        , elemDecl->getFormattedContentModel()
2130                                );
2131                        }
2132                        else if (failure >= childCount)
2133                        {
2134                                fValidator->emitError
2135                                (
2136                                        XMLValid::NotEnoughElemsForCM
2137                                        , elemDecl->getFormattedContentModel()
2138                                );
2139                        }
2140                        else
2141                        {
2142                                fValidator->emitError
2143                                (
2144                                        XMLValid::ElementNotValidForContent
2145                                        , children[failure]->getFullName()
2146                                        , elemDecl->getFormattedContentModel()
2147                                );
2148                        }
2149                }
2150
2151                if (fGrammarType == Grammar::SchemaGrammarType)
2152                {
2153                        if (fSchemaValidator->getErrorOccurred())
2154                                fPSVIElemContext.fErrorOccurred = true;
2155                        else if (fPSVIElemContext.fCurrentDV && fPSVIElemContext.fCurrentDV->getType() == DatatypeValidator::Union)
2156                                psviMemberType = fValidationContext->getValidatingMemberType();
2157
2158                        if (fPSVIHandler)
2159                        {
2160                                fPSVIElemContext.fIsSpecified = fSchemaValidator->getIsElemSpecified();
2161                                if (fPSVIElemContext.fIsSpecified)
2162                                {
2163                                        fPSVIElemContext.fNormalizedValue = ((SchemaElementDecl *)elemDecl)->getDefaultValue();
2164                                }
2165                        }
2166
2167                        // call matchers and de-activate context
2168                        if (toCheckIdentityConstraint())
2169                        {
2170                                fICHandler->deactivateContext
2171                                (
2172                                        (SchemaElementDecl *)elemDecl
2173                                        , fContent.getRawBuffer()
2174                                        , fValidationContext
2175                                        , fPSVIElemContext.fCurrentDV
2176                                );
2177                        }
2178                }
2179        }
2180
2181        // QName dv needed topElem to resolve URIs on the checkContent
2182        fElemStack.popTop();
2183
2184        if (fGrammarType == Grammar::SchemaGrammarType)
2185        {
2186                if (fPSVIHandler)
2187                {
2188                        endElementPSVI((SchemaElementDecl*)topElem->fThisElement, psviMemberType);
2189                }
2190                // now we can reset the datatype buffer, since the
2191                // application has had a chance to copy the characters somewhere else
2192                // fSchemaValidator->clearDatatypeBuffer();
2193                fPSVIElemContext.fNormalizedValue = 0;
2194        }
2195
2196        // If we have a doc handler, tell it about the end tag
2197        if (fDocHandler)
2198        {
2199                fDocHandler->endElement
2200                (
2201                        * elemDecl
2202                        , uriId
2203                        , isRoot
2204                        , elemDecl->getElementName()->getPrefix()
2205                );
2206        }
2207
2208        // If this was the root, then done with content
2209        if (likely(!isRoot))
2210        {
2211                if (fGrammarType == Grammar::SchemaGrammarType)
2212                {
2213                        // update error information
2214                        fErrorStack->push((fErrorStack->size() && fErrorStack->pop()) || fPSVIElemContext.fErrorOccurred);
2215                }
2216
2217                if (fDoNamespaces)
2218                {
2219                        // Restore the grammar
2220                        fGrammar = fElemStack.getCurrentGrammar();
2221                        fGrammarType = fGrammar->getGrammarType();
2222
2223                        if (fGrammarType == Grammar::SchemaGrammarType && !fValidator->handlesSchema())
2224                        {
2225                                if (fValidatorFromUser)
2226                                {
2227                                        ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoSchemaValidator, fMemoryManager);
2228                                }
2229                                else
2230                                {
2231                                        fValidator = fSchemaValidator;
2232                                }
2233                        }
2234                        else if (fGrammarType == Grammar::DTDGrammarType && !fValidator->handlesDTD())
2235                        {
2236                                if (fValidatorFromUser)
2237                                {
2238                                        ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoDTDValidator, fMemoryManager);
2239                                }
2240                                else
2241                                {
2242                                        fValidator = fDTDValidator;
2243                                }
2244                        }
2245                        fValidator->setGrammar(fGrammar);
2246                }
2247
2248                // Restore the validation flag
2249                fValidate = fElemStack.getValidationFlag();
2250        }
2251}
2252
2253//  This method handles the high level logic of scanning the DOCType
2254//  declaration. This calls the DTDScanner and kicks off both the scanning of
2255//  the internal subset and the scanning of the external subset, if any.
2256//
2257//  When we get here the '<!DOCTYPE' part has already been scanned, which is
2258//  what told us that we had a doc type decl to parse.
2259void IGXMLScanner::scanDocTypeDecl()
2260{
2261        //  We have a doc type. So, switch the Grammar.
2262        switchGrammar(XMLUni::fgDTDEntityString);
2263
2264        if (fDocTypeHandler)
2265                fDocTypeHandler->resetDocType();
2266
2267        // There must be some space after DOCTYPE
2268        bool skippedSomething;
2269        fReaderMgr.skipPastSpaces(skippedSomething);
2270        if (!skippedSomething)
2271        {
2272                emitError(XMLErrs::ExpectedWhitespace);
2273
2274                // Just skip the Doctype declaration and return
2275                fReaderMgr.skipPastChar(chCloseAngle);
2276                return;
2277        }
2278
2279        // Get a buffer for the root element
2280        XMLBufBid bbRootName(&fBufMgr);
2281
2282        //  Get a name from the input, which should be the name of the root
2283        //  element of the upcoming content.
2284        int  colonPosition;
2285        bool validName = fDoNamespaces ?
2286                        fReaderMgr.getQName(bbRootName.getBuffer(), &colonPosition) :
2287                        fReaderMgr.getName(bbRootName.getBuffer());
2288
2289        if (!validName)
2290        {
2291                if (bbRootName.isEmpty())
2292                        emitError(XMLErrs::NoRootElemInDOCTYPE);
2293                else
2294                        emitError(XMLErrs::InvalidRootElemInDOCTYPE, bbRootName.getRawBuffer());
2295                fReaderMgr.skipPastChar(chCloseAngle);
2296                return;
2297        }
2298
2299        //  Store the root element name for later check
2300        setRootElemName(bbRootName.getRawBuffer());
2301
2302        //  This element obviously is not going to exist in the element decl
2303        //  pool yet, but we need to call docTypeDecl. So force it into
2304        //  the element decl pool, marked as being there because it was in
2305        //  the DOCTYPE. Later, when its declared, the status will be updated.
2306        //
2307        //  Only do this if we are not reusing the validator! If we are reusing,
2308        //  then look it up instead. It has to exist!
2309        MemoryManager* const  rootDeclMgr =
2310                fUseCachedGrammar ? fMemoryManager : fGrammarPoolMemoryManager;
2311
2312        DTDElementDecl* rootDecl = new (rootDeclMgr) DTDElementDecl
2313        (
2314                bbRootName.getRawBuffer()
2315                , XMLNamespaceResolver::fEmptyUriId
2316                , DTDElementDecl::Any
2317                , rootDeclMgr
2318        );
2319
2320        Janitor<DTDElementDecl> rootDeclJanitor(rootDecl);
2321        rootDecl->setCreateReason(DTDElementDecl::AsRootElem);
2322        rootDecl->setExternalElemDeclaration(true);
2323        if(!fUseCachedGrammar)
2324        {
2325                fGrammar->putElemDecl(rootDecl);
2326                rootDeclJanitor.release();
2327        }
2328        else
2329        {
2330                // attach this to the undeclared element pool so that it gets deleted
2331                XMLElementDecl* elemDecl = fDTDElemNonDeclPool->getByKey(bbRootName.getRawBuffer());
2332                if (elemDecl)
2333                {
2334                        rootDecl->setId(elemDecl->getId());
2335                }
2336                else
2337                {
2338                        rootDecl->setId(fDTDElemNonDeclPool->put((DTDElementDecl*)rootDecl));
2339                        rootDeclJanitor.release();
2340                }
2341        }
2342
2343        // Skip any spaces after the name
2344        fReaderMgr.skipPastSpaces();
2345
2346        //  And now if we are looking at a >, then we are done. It is not
2347        //  required to have an internal or external subset, though why you
2348        //  would not escapes me.
2349        if (fReaderMgr.skippedChar(chCloseAngle))
2350        {
2351                //  If we have a doc type handler and advanced callbacks are enabled,
2352                //  call the doctype event.
2353                if (fDocTypeHandler)
2354                        fDocTypeHandler->doctypeDecl(*rootDecl, 0, 0, false);
2355                return;
2356        }
2357
2358        // either internal/external subset
2359        if (fValScheme == Val_Auto && !fValidate)
2360                fValidate = true;
2361
2362        bool    hasIntSubset = false;
2363        bool    hasExtSubset = false;
2364        XMLCh*  sysId = 0;
2365        XMLCh*  pubId = 0;
2366
2367        DTDScanner dtdScanner
2368        (
2369                (DTDGrammar*) fGrammar
2370                , fDocTypeHandler
2371                , fGrammarPoolMemoryManager
2372                , fMemoryManager
2373        );
2374
2375        dtdScanner.setScannerInfo(this, &fReaderMgr, &fBufMgr);
2376
2377        //  If the next character is '[' then we have no external subset cause
2378        //  there is no system id, just the opening character of the internal
2379        //  subset. Else, has to be an id.
2380        //
2381        // Just look at the next char, don't eat it.
2382        if (fReaderMgr.peekNextChar() == chOpenSquare)
2383        {
2384                hasIntSubset = true;
2385        }
2386        else
2387        {
2388                // Indicate we have an external subset
2389                hasExtSubset = true;
2390                fHasNoDTD = false;
2391
2392                // Get buffers for the ids
2393                XMLBufBid bbPubId(&fBufMgr);
2394                XMLBufBid bbSysId(&fBufMgr);
2395
2396                // Get the external subset id
2397                if (!dtdScanner.scanId(bbPubId.getBuffer(), bbSysId.getBuffer(), DTDScanner::IDType_External))
2398                {
2399                        fReaderMgr.skipPastChar(chCloseAngle);
2400                        return;
2401                }
2402
2403                // Get copies of the ids we got
2404                pubId = XMLString::replicate(bbPubId.getRawBuffer(), fMemoryManager);
2405                sysId = XMLString::replicate(bbSysId.getRawBuffer(), fMemoryManager);
2406
2407                // Skip spaces and check again for the opening of an internal subset
2408                fReaderMgr.skipPastSpaces();
2409
2410                // Just look at the next char, don't eat it.
2411                if (fReaderMgr.peekNextChar() == chOpenSquare)
2412                {
2413                        hasIntSubset = true;
2414                }
2415        }
2416
2417        // Insure that the ids get cleaned up, if they got allocated
2418        ArrayJanitor<XMLCh> janSysId(sysId, fMemoryManager);
2419        ArrayJanitor<XMLCh> janPubId(pubId, fMemoryManager);
2420
2421        //  If we have a doc type handler and advanced callbacks are enabled,
2422        //  call the doctype event.
2423        if (fDocTypeHandler)
2424                fDocTypeHandler->doctypeDecl(*rootDecl, pubId, sysId, hasIntSubset, hasExtSubset);
2425
2426        //  Ok, if we had an internal subset, we are just past the [ character
2427        //  and need to parse that first.
2428        if (hasIntSubset)
2429        {
2430                // Eat the opening square bracket
2431                fReaderMgr.getNextChar();
2432
2433                checkInternalDTD(hasExtSubset, sysId, pubId);
2434
2435                //  And try to scan the internal subset. If we fail, try to recover
2436                //  by skipping forward tot he close angle and returning.
2437                if (!dtdScanner.scanInternalSubset())
2438                {
2439                        fReaderMgr.skipPastChar(chCloseAngle);
2440                        return;
2441                }
2442
2443                //  Do a sanity check that some expanded PE did not propogate out of
2444                //  the doctype. This could happen if it was terminated early by bad
2445                //  syntax.
2446                if (fReaderMgr.getReaderDepth() > 1)
2447                {
2448                        emitError(XMLErrs::PEPropogated);
2449
2450                        // Ask the reader manager to pop back down to the main level
2451                        fReaderMgr.cleanStackBackTo(1);
2452                }
2453
2454                fReaderMgr.skipPastSpaces();
2455        }
2456
2457        // And that should leave us at the closing > of the DOCTYPE line
2458        if (!fReaderMgr.skippedChar(chCloseAngle))
2459        {
2460                //  Do a special check for the common scenario of an extra ] char at
2461                //  the end. This is easy to recover from.
2462                if (fReaderMgr.skippedChar(chCloseSquare) && fReaderMgr.skippedChar(chCloseAngle))
2463                {
2464                        emitError(XMLErrs::ExtraCloseSquare);
2465                }
2466                 else
2467                {
2468                        emitError(XMLErrs::UnterminatedDOCTYPE);
2469                        fReaderMgr.skipPastChar(chCloseAngle);
2470                }
2471        }
2472
2473        //  If we had an external subset, then we need to deal with that one
2474        //  next. If we are reusing the validator, then don't scan it.
2475        if (hasExtSubset)
2476        {
2477                InputSource* srcUsed=0;
2478                Janitor<InputSource> janSrc(srcUsed);
2479                // If we had an internal subset and we're using the cached grammar, it
2480                // means that the ignoreCachedDTD is set, so we ignore the cached
2481                // grammar
2482                if (fUseCachedGrammar && !hasIntSubset)
2483                {
2484                        srcUsed = resolveSystemId(sysId, pubId);
2485                        if (srcUsed)
2486                        {
2487                                janSrc.reset(srcUsed);
2488                                Grammar* grammar = fGrammarResolver->getGrammar(srcUsed->getSystemId());
2489
2490                                if (grammar && grammar->getGrammarType() == Grammar::DTDGrammarType)
2491                                {
2492                                        fDTDGrammar = (DTDGrammar*) grammar;
2493                                        fGrammar = fDTDGrammar;
2494                                        fValidator->setGrammar(fGrammar);
2495                                        // If we don't report at least the external subset boundaries,
2496                                        // an advanced document handler cannot know when the DTD end,
2497                                        // since we've already sent a doctype decl that indicates there's
2498                                        // there's an external subset.
2499                                        if (fDocTypeHandler)
2500                                        {
2501                                                fDocTypeHandler->startExtSubset();
2502                                                fDocTypeHandler->endExtSubset();
2503                                        }
2504
2505                                        return;
2506                                }
2507                        }
2508                }
2509
2510                if (fLoadExternalDTD || fValidate)
2511                {
2512                        // And now create a reader to read this entity
2513                        XMLReader* reader;
2514                        if (srcUsed)
2515                        {
2516                                reader = fReaderMgr.createReader
2517                                (
2518                                        *srcUsed
2519                                        , false
2520                                        , XMLReader::RefFrom_NonLiteral
2521                                        , XMLReader::Type_General
2522                                        , XMLReader::Source_External
2523                                        , fCalculateSrcOfs
2524                                        , fLowWaterMark
2525                                );
2526                        }
2527                        else
2528                        {
2529                                reader = fReaderMgr.createReader
2530                                (
2531                                        sysId
2532                                        , pubId
2533                                        , false
2534                                        , XMLReader::RefFrom_NonLiteral
2535                                        , XMLReader::Type_General
2536                                        , XMLReader::Source_External
2537                                        , srcUsed
2538                                        , fCalculateSrcOfs
2539                                        , fLowWaterMark
2540                                        , fDisableDefaultEntityResolution
2541                                );
2542                                janSrc.reset(srcUsed);
2543                        }
2544                        //  If it failed then throw an exception
2545                        if (!reader)
2546                                ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Gen_CouldNotOpenDTD, srcUsed ? srcUsed->getSystemId() : sysId, fMemoryManager);
2547
2548                        if (fToCacheGrammar)
2549                        {
2550                                unsigned int stringId = fGrammarResolver->getStringPool()->addOrFind(srcUsed->getSystemId());
2551                                const XMLCh* sysIdStr = fGrammarResolver->getStringPool()->getValueForId(stringId);
2552
2553                                fGrammarResolver->orphanGrammar(XMLUni::fgDTDEntityString);
2554                                ((XMLDTDDescription*) (fGrammar->getGrammarDescription()))->setSystemId(sysIdStr);
2555                                fGrammarResolver->putGrammar(fGrammar);
2556                        }
2557
2558                        //  In order to make the processing work consistently, we have to
2559                        //  make this look like an external entity. So create an entity
2560                        //  decl and fill it in and push it with the reader, as happens
2561                        //  with an external entity. Put a janitor on it to insure it gets
2562                        //  cleaned up. The reader manager does not adopt them.
2563                        const XMLCh gDTDStr[] = { chLatin_D, chLatin_T, chLatin_D , chNull };
2564                        DTDEntityDecl* declDTD = new (fMemoryManager) DTDEntityDecl(gDTDStr, false, fMemoryManager);
2565                        declDTD->setSystemId(sysId);
2566                        declDTD->setIsExternal(true);
2567                        Janitor<DTDEntityDecl> janDecl(declDTD);
2568
2569                        // Mark this one as a throw at end
2570                        reader->setThrowAtEnd(true);
2571
2572                        // And push it onto the stack, with its pseudo name
2573                        fReaderMgr.pushReader(reader, declDTD);
2574
2575                        // Tell it its not in an include section
2576                        dtdScanner.scanExtSubsetDecl(false, true);
2577                }
2578        }
2579}
2580
2581// --------------------------------------------------------------------------------------------------------
2582// HANDLE CONTENT
2583// --------------------------------------------------------------------------------------------------------
2584
2585void IGXMLScanner::handleContent
2586(
2587        const XMLCh       * content
2588        , const XMLSize_t   contentLength
2589)
2590{
2591        //  We do different things according to whether we are validating or
2592        //  not. If not, its always just characters; else, it depends on the
2593        //  current element's content model.
2594        if (fValidate)
2595        {
2596                // And see if the current element is a 'Children' style content model
2597                const ElemStack::StackElem * topElem = fElemStack.topElement();
2598
2599                // Get the character data opts for the current element
2600                XMLElementDecl::CharDataOpts charOpts = XMLElementDecl::AllCharData;
2601                // fGrammar->getGrammarType()
2602                if (fGrammarType == Grammar::SchemaGrammarType)
2603                {
2604                        // And see if the current element is a 'Children' style content model
2605                        ComplexTypeInfo * currType = fSchemaValidator->getCurrentTypeInfo();
2606                        if (currType)
2607                        {
2608                                switch ((SchemaElementDecl::ModelTypes)currType->getContentType())
2609                                {
2610                                        case SchemaElementDecl::Empty:
2611                                                charOpts = XMLElementDecl::NoCharData;
2612                                                break;
2613                                        case SchemaElementDecl::Children:
2614                                        case SchemaElementDecl::ElementOnlyEmpty:
2615                                                charOpts = XMLElementDecl::SpacesOk;
2616                                }
2617                        }
2618                }
2619                else // DTD grammar
2620                {
2621                        charOpts = topElem->fThisElement->getCharDataOpts();
2622                }
2623
2624                if (charOpts == XMLElementDecl::AllCharData)
2625                {
2626                        XMLSize_t normLength = contentLength;
2627                        const XMLCh * normContent = content;
2628
2629                        if (fGrammarType == Grammar::SchemaGrammarType)
2630                        {
2631                                DatatypeValidator * tempDV =
2632                                        fSchemaValidator->getCurrentDatatypeValidator();
2633
2634                                if (tempDV)
2635                                {
2636                                        if (tempDV->getWSFacet() != DatatypeValidator::PRESERVE)
2637                                        {
2638                                                // normalize the character according to schema whitespace facet
2639                                                fSchemaValidator->normalizeWhiteSpace(tempDV, content, fWSNormalizeBuf);
2640                                                normContent = fWSNormalizeBuf.getRawBuffer();
2641                                                normLength = fWSNormalizeBuf.getLen();
2642                                        }
2643                                }
2644                                // tell the schema validation about the character data for checkContent later
2645                                fSchemaValidator->setDatatypeBuffer(normContent);
2646
2647                                // call all active identity constraints
2648                                if (toCheckIdentityConstraint() && fICHandler->getMatcherCount())
2649                                {
2650                                        fContent.append(normContent, normLength);
2651                                }
2652                        }
2653
2654                        if (fDocHandler)
2655                        {
2656                                if (fNormalizeData)
2657                                {
2658                                        fDocHandler->docCharacters(normContent, normLength, false);
2659                                }
2660                                else
2661                                {
2662                                        fDocHandler->docCharacters(content, contentLength, false);
2663                                }
2664                        }
2665                        return;
2666                }
2667                else if (charOpts == XMLElementDecl::SpacesOk)
2668                {
2669                        if (XMLString::isAllSpaces(content, contentLength))
2670                        {
2671                                if (fDocHandler)
2672                                {
2673                                        fDocHandler->ignorableWhitespace(content, contentLength, false);
2674                                }
2675                                return;
2676                        }
2677                }
2678                // either there is an error or no char data is allowed
2679                fValidator->emitError(XMLValid::NoCharDataInCM);
2680        }
2681        else
2682        {
2683
2684                // Always assume it's just char data if we're not validating
2685                if (fDocHandler)
2686                {
2687                        fDocHandler->docCharacters(content, contentLength, false);
2688                }
2689        }
2690
2691}
2692
2693// --------------------------------------------------------------------------------------------------------
2694
2695void IGXMLScanner::handleCDATA
2696(
2697        const XMLCh       * cdata
2698        , const XMLSize_t   cdataLength
2699)
2700{
2701        if (fElemStack.isEmpty())
2702        {
2703                emitError(XMLErrs::CDATAOutsideOfContent);
2704        }
2705
2706        const ElemStack::StackElem* topElem = fElemStack.topElement();
2707
2708        // Get the character data opts for the current element
2709        XMLElementDecl::CharDataOpts charOpts = XMLElementDecl::AllCharData;
2710
2711        if (fGrammarType == Grammar::SchemaGrammarType)
2712        {
2713                // And see if the current element is a 'Children' style content model
2714                ComplexTypeInfo *currType = fSchemaValidator->getCurrentTypeInfo();
2715                if(currType)
2716                {
2717                        SchemaElementDecl::ModelTypes modelType = (SchemaElementDecl::ModelTypes) currType->getContentType();
2718                        if (modelType == SchemaElementDecl::Children || modelType == SchemaElementDecl::ElementOnlyEmpty)
2719                                charOpts = XMLElementDecl::SpacesOk;
2720                        else if(modelType == SchemaElementDecl::Empty)
2721                                charOpts = XMLElementDecl::NoCharData;
2722                }
2723
2724                const XMLCh* xsNormalized = cdata;
2725                const XMLSize_t xsLen = cdataLength;
2726
2727                if (fValidate)
2728                {
2729                        // tell the schema validation about the character data for checkContent later
2730                        fPSVIElemContext.fNormalizedValue = xsNormalized;
2731
2732                        if (charOpts != XMLElementDecl::AllCharData)
2733                        {
2734                                // They definitely cannot handle any type of char data
2735                                fValidator->emitError(XMLValid::NoCharDataInCM);
2736                                if (getPSVIHandler())
2737                                {
2738                                        // REVISIT:
2739                                        // PSVIElement->setValidity(PSVIItem::VALIDITY_INVALID);
2740                                }
2741                        }
2742                }
2743
2744                // call all active identity constraints
2745                if (toCheckIdentityConstraint() && fICHandler->getMatcherCount())
2746                {
2747                        fContent.append(xsNormalized, xsLen);
2748                }
2749        }
2750        else // DTD grammar
2751        {
2752                if (fValidate)
2753                {
2754                        charOpts = topElem->fThisElement->getCharDataOpts();
2755                        if (charOpts != XMLElementDecl::AllCharData)
2756                        {
2757                                // They definitely cannot handle any type of char data
2758                                fValidator->emitError(XMLValid::NoCharDataInCM);
2759                        }
2760                }
2761        }
2762
2763        if (fDocHandler)
2764        {
2765                fDocHandler->docCharacters(cdata, cdataLength, true);
2766        }
2767}
2768
2769// ---------------------------------------------------------------------------
2770//  IGXMLScanner: Helper methods
2771// ---------------------------------------------------------------------------
2772void IGXMLScanner::resizeElemState()
2773{
2774        unsigned int newSize = fElemStateSize * 2;
2775        unsigned int* newElemState = (unsigned int*) fMemoryManager->allocate
2776        (
2777                newSize * sizeof(unsigned int)
2778        ); //new unsigned int[newSize];
2779        unsigned int* newElemLoopState = (unsigned int*) fMemoryManager->allocate
2780        (
2781                newSize * sizeof(unsigned int)
2782        ); //new unsigned int[newSize];
2783
2784        // Copy the existing values
2785        unsigned int index = 0;
2786        for (; index < fElemStateSize; index++)
2787        {
2788                newElemState[index] = fElemState[index];
2789                newElemLoopState[index] = fElemLoopState[index];
2790        }
2791
2792        for (; index < newSize; index++)
2793                newElemLoopState[index] = newElemState[index] = 0;
2794
2795        // Delete the old array and udpate our members
2796        fMemoryManager->deallocate(fElemState); //delete [] fElemState;
2797        fMemoryManager->deallocate(fElemLoopState); //delete [] fElemState;
2798        fElemState = newElemState;
2799        fElemLoopState = newElemLoopState;
2800        fElemStateSize = newSize;
2801}
2802
2803// ---------------------------------------------------------------------------
2804//  IGXMLScanner: Grammar preparsing
2805// ---------------------------------------------------------------------------
2806Grammar* IGXMLScanner::loadGrammar(const   InputSource& src
2807                                                                   , const short        grammarType
2808                                                                   , const bool         toCache)
2809{
2810        Grammar* loadedGrammar = 0;
2811
2812        ReaderMgrResetType  resetReaderMgr(&fReaderMgr, &ReaderMgr::reset);
2813
2814        try
2815        {
2816                fGrammarResolver->cacheGrammarFromParse(false);
2817                // if the new grammar has to be cached, better use the already cached
2818                // grammars, or the an exception will be thrown when caching an already
2819                // cached grammar
2820                fGrammarResolver->useCachedGrammarInParse(toCache);
2821                fRootGrammar = 0;
2822
2823                // If fValScheme is set to auto, turn validation on.
2824                fValidate = fValidate | (fValScheme == Val_Auto);
2825
2826                // Reset some status flags
2827                fInException = false;
2828                fStandalone = false;
2829                fErrorCount = 0;
2830                fHasNoDTD = true;
2831                if (grammarType == Grammar::SchemaGrammarType)
2832                {
2833                        loadedGrammar = loadXMLSchemaGrammar(src, toCache);
2834                }
2835                else if (grammarType == Grammar::DTDGrammarType)
2836                {
2837                        loadedGrammar = loadDTDGrammar(src, toCache);
2838                }
2839        }
2840        //  NOTE:
2841        //
2842        //  In all of the error processing below, the emitError() call MUST come
2843        //  before the flush of the reader mgr, or it will fail because it tries
2844        //  to find out the position in the XML source of the error.
2845        catch(const XMLErrs::Codes)
2846        {
2847                // This is a 'first fatal error' type exit, so fall through
2848        }
2849        catch(const XMLValid::Codes)
2850        {
2851                // This is a 'first fatal error' type exit, so fall through
2852        }
2853        catch(const XMLException& excToCatch)
2854        {
2855                //  Emit the error and catch any user exception thrown from here. Make
2856                //  sure in all cases we flush the reader manager.
2857                fInException = true;
2858                try
2859                {
2860                        if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning)
2861                                emitError
2862                                (
2863                                        XMLErrs::XMLException_Warning
2864                                        , excToCatch.getCode()
2865                                        , excToCatch.getMessage()
2866                                );
2867                        else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal)
2868                                emitError
2869                                (
2870                                        XMLErrs::XMLException_Fatal
2871                                        , excToCatch.getCode()
2872                                        , excToCatch.getMessage()
2873                                );
2874                        else
2875                                emitError
2876                                (
2877                                        XMLErrs::XMLException_Error
2878                                        , excToCatch.getCode()
2879                                        , excToCatch.getMessage()
2880                                );
2881                }
2882                catch(const OutOfMemoryException&)
2883                {
2884                        // This is a special case for out-of-memory
2885                        // conditions, because resetting the ReaderMgr
2886                        // can be problematic.
2887                        resetReaderMgr.release();
2888
2889                        throw;
2890                }
2891        }
2892        catch(const OutOfMemoryException&)
2893        {
2894                // This is a special case for out-of-memory
2895                // conditions, because resetting the ReaderMgr
2896                // can be problematic.
2897                resetReaderMgr.release();
2898
2899                throw;
2900        }
2901
2902        return loadedGrammar;
2903}
2904
2905// ---------------------------------------------------------------------------
2906//  IGXMLScanner: Grammar preparsing
2907// ---------------------------------------------------------------------------
2908void IGXMLScanner::resetCachedGrammar ()
2909{
2910        fCachedSchemaInfoList->removeAll();
2911}
2912
2913// ---------------------------------------------------------------------------
2914//  IGXMLScanner: Grammar preparsing
2915// ---------------------------------------------------------------------------
2916Grammar* IGXMLScanner::loadDTDGrammar( const InputSource& src,
2917                                                                           const bool toCache)
2918{
2919        // Reset the validators
2920        fDTDValidator->reset();
2921        if (fValidatorFromUser)
2922                fValidator->reset();
2923
2924        if (!fValidator->handlesDTD())
2925        {
2926                if (fValidatorFromUser && fValidate)
2927                        ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoDTDValidator, fMemoryManager);
2928                else
2929                {
2930                        fValidator = fDTDValidator;
2931                }
2932        }
2933
2934        fDTDGrammar = (DTDGrammar*) fGrammarResolver->getGrammar(XMLUni::fgDTDEntityString);
2935
2936        if (fDTDGrammar)
2937        {
2938                fDTDGrammar->reset();
2939        }
2940        else
2941        {
2942                fDTDGrammar = new (fGrammarPoolMemoryManager) DTDGrammar(fGrammarPoolMemoryManager);
2943                fGrammarResolver->putGrammar(fDTDGrammar);
2944        }
2945
2946        fGrammar = fDTDGrammar;
2947        fGrammarType = fGrammar->getGrammarType();
2948        fValidator->setGrammar(fGrammar);
2949
2950        //  And for all installed handlers, send reset events. This gives them
2951        //  a chance to flush any cached data.
2952        if (fDocHandler)
2953                fDocHandler->resetDocument();
2954        if (fEntityHandler)
2955                fEntityHandler->resetEntities();
2956        if (fErrorReporter)
2957                fErrorReporter->resetErrors();
2958
2959        // Clear out the id reference list
2960        resetValidationContext();
2961        // and clear out the darned undeclared DTD element pool...
2962        fDTDElemNonDeclPool->removeAll();
2963
2964        if (toCache)
2965        {
2966                unsigned int sysId = fGrammarResolver->getStringPool()->addOrFind(src.getSystemId());
2967                const XMLCh* sysIdStr = fGrammarResolver->getStringPool()->getValueForId(sysId);
2968
2969                fGrammarResolver->orphanGrammar(XMLUni::fgDTDEntityString);
2970                ((XMLDTDDescription*) (fGrammar->getGrammarDescription()))->setSystemId(sysIdStr);
2971                fGrammarResolver->putGrammar(fGrammar);
2972        }
2973
2974        //  Handle the creation of the XML reader object for this input source.
2975        //  This will provide us with transcoding and basic lexing services.
2976        XMLReader* newReader = fReaderMgr.createReader
2977        (
2978                src
2979                , false
2980                , XMLReader::RefFrom_NonLiteral
2981                , XMLReader::Type_General
2982                , XMLReader::Source_External
2983                , fCalculateSrcOfs
2984                , fLowWaterMark
2985        );
2986
2987        if (!newReader)
2988        {
2989                if (src.getIssueFatalErrorIfNotFound())
2990                        ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource, src.getSystemId(), fMemoryManager);
2991                else
2992                        ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource_Warning, src.getSystemId(), fMemoryManager);
2993        }
2994
2995        //  In order to make the processing work consistently, we have to
2996        //  make this look like an external entity. So create an entity
2997        //  decl and fill it in and push it with the reader, as happens
2998        //  with an external entity. Put a janitor on it to insure it gets
2999        //  cleaned up. The reader manager does not adopt them.
3000        const XMLCh gDTDStr[] = { chLatin_D, chLatin_T, chLatin_D , chNull };
3001        DTDEntityDecl* declDTD = new (fMemoryManager) DTDEntityDecl(gDTDStr, false, fMemoryManager);
3002        declDTD->setSystemId(src.getSystemId());
3003        declDTD->setIsExternal(true);
3004        Janitor<DTDEntityDecl> janDecl(declDTD);
3005
3006        // Mark this one as a throw at end
3007        newReader->setThrowAtEnd(true);
3008
3009        // And push it onto the stack, with its pseudo name
3010        fReaderMgr.pushReader(newReader, declDTD);
3011
3012        //  If we have a doc type handler and advanced callbacks are enabled,
3013        //  call the doctype event.
3014        if (fDocTypeHandler)
3015        {
3016                // Create a dummy root
3017                DTDElementDecl* rootDecl = new (fGrammarPoolMemoryManager) DTDElementDecl
3018                (
3019                        gDTDStr
3020                        , XMLNamespaceResolver::fEmptyUriId
3021                        , DTDElementDecl::Any
3022                        , fGrammarPoolMemoryManager
3023                );
3024                rootDecl->setCreateReason(DTDElementDecl::AsRootElem);
3025                rootDecl->setExternalElemDeclaration(true);
3026                Janitor<DTDElementDecl> janSrc(rootDecl);
3027
3028                fDocTypeHandler->doctypeDecl(*rootDecl, src.getPublicId(), src.getSystemId(), false, true);
3029        }
3030
3031        // Create DTDScanner
3032        DTDScanner dtdScanner
3033        (
3034                (DTDGrammar*) fGrammar
3035                , fDocTypeHandler
3036                , fGrammarPoolMemoryManager
3037                , fMemoryManager
3038        );
3039        dtdScanner.setScannerInfo(this, &fReaderMgr, &fBufMgr);
3040
3041        // Tell it its not in an include section
3042        dtdScanner.scanExtSubsetDecl(false, true);
3043
3044        if (fValidate)
3045        {
3046                //  validate the DTD scan so far
3047                fValidator->preContentValidation(false, true);
3048        }
3049
3050        if (toCache)
3051                fGrammarResolver->cacheGrammars();
3052
3053        return fDTDGrammar;
3054}
3055
3056// ---------------------------------------------------------------------------
3057//  IGXMLScanner: Helper methods
3058// ---------------------------------------------------------------------------
3059
3060void IGXMLScanner::endElementPSVI(SchemaElementDecl* const elemDecl,
3061                                                                  DatatypeValidator* const memberDV)
3062{
3063        PSVIElement::ASSESSMENT_TYPE validationAttempted;
3064        PSVIElement::VALIDITY_STATE validity = PSVIElement::VALIDITY_NOTKNOWN;
3065
3066        if (fPSVIElemContext.fElemDepth > fPSVIElemContext.fFullValidationDepth)
3067                validationAttempted = PSVIElement::VALIDATION_FULL;
3068        else if (fPSVIElemContext.fElemDepth > fPSVIElemContext.fNoneValidationDepth)
3069                validationAttempted = PSVIElement::VALIDATION_NONE;
3070        else
3071        {
3072                validationAttempted  = PSVIElement::VALIDATION_PARTIAL;
3073                                fPSVIElemContext.fFullValidationDepth =
3074                        fPSVIElemContext.fNoneValidationDepth = fPSVIElemContext.fElemDepth - 1;
3075        }
3076
3077        if (fValidate && elemDecl->isDeclared())
3078        {
3079                validity = (fPSVIElemContext.fErrorOccurred)
3080                        ? PSVIElement::VALIDITY_INVALID : PSVIElement::VALIDITY_VALID;
3081        }
3082
3083        XSTypeDefinition* typeDef = 0;
3084        bool isMixed = false;
3085        if (fPSVIElemContext.fCurrentTypeInfo)
3086        {
3087                typeDef = (XSTypeDefinition*) fModel->getXSObject(fPSVIElemContext.fCurrentTypeInfo);
3088                SchemaElementDecl::ModelTypes modelType = (SchemaElementDecl::ModelTypes)fPSVIElemContext.fCurrentTypeInfo->getContentType();
3089                isMixed = (modelType == SchemaElementDecl::Mixed_Simple
3090                                || modelType == SchemaElementDecl::Mixed_Complex);
3091        }
3092        else if (fPSVIElemContext.fCurrentDV)
3093                typeDef = (XSTypeDefinition*) fModel->getXSObject(fPSVIElemContext.fCurrentDV);
3094
3095        XMLCh* canonicalValue = 0;
3096        if (fPSVIElemContext.fNormalizedValue && !isMixed &&
3097                        validity == PSVIElement::VALIDITY_VALID)
3098        {
3099                if (memberDV)
3100                        canonicalValue = (XMLCh*) memberDV->getCanonicalRepresentation(fPSVIElemContext.fNormalizedValue, fMemoryManager);
3101                else if (fPSVIElemContext.fCurrentDV)
3102                        canonicalValue = (XMLCh*) fPSVIElemContext.fCurrentDV->getCanonicalRepresentation(fPSVIElemContext.fNormalizedValue, fMemoryManager);
3103        }
3104
3105        fPSVIElement->reset
3106        (
3107                validity
3108                , validationAttempted
3109                , fRootElemName
3110                , fPSVIElemContext.fIsSpecified
3111                , (elemDecl->isDeclared())
3112                        ? (XSElementDeclaration*) fModel->getXSObject(elemDecl) : 0
3113                , typeDef
3114                , (memberDV) ? (XSSimpleTypeDefinition*) fModel->getXSObject(memberDV) : 0
3115                , fModel
3116                , elemDecl->getDefaultValue()
3117                , fPSVIElemContext.fNormalizedValue
3118                , canonicalValue
3119        );
3120
3121        fPSVIHandler->handleElementPSVI
3122        (
3123                elemDecl->getBaseName()
3124                , fUriResolver->getUriForId(elemDecl->getURI())
3125                , fPSVIElement
3126        );
3127
3128        // decrease element depth
3129        fPSVIElemContext.fElemDepth--;
3130}
3131
3132void IGXMLScanner::resetPSVIElemContext()
3133{
3134        fPSVIElemContext.fIsSpecified = false;
3135        fPSVIElemContext.fErrorOccurred = false;
3136        fPSVIElemContext.fElemDepth = -1;
3137        fPSVIElemContext.fFullValidationDepth = -1;
3138        fPSVIElemContext.fNoneValidationDepth = -1;
3139        fPSVIElemContext.fCurrentDV = 0;
3140        fPSVIElemContext.fCurrentTypeInfo = 0;
3141        fPSVIElemContext.fNormalizedValue = 0;
3142}
3143
3144#ifdef __GNUC__
3145#warning "note: currently we cannot trigger the fDocHandler->startEntityReference callback"
3146#endif
3147
3148bool IGXMLScanner::expandEntityRef
3149(
3150        const XMLCh *                   entityRef
3151        , const bool                    inAttributeValue
3152        , XMLBuffer &                   toFill
3153)
3154{
3155    assert (entityRef != 0);
3156
3157        //  If the next char is a pound, then its a character reference...
3158        if (*entityRef == chPound)
3159        {
3160                if (inAttributeValue)
3161                {
3162                        XMLCh charVal[2];
3163                        XMLSize_t len = expandCharRef(entityRef + 1, &charVal[0], chNull);
3164
3165                        if (likely(len == 1))
3166                        {
3167                                // if we're in an attribute, add it but tag it with an escape character so we do not accidently
3168                                // normalize it...
3169                                toFill.append(0xFFFF);
3170                                toFill.append(charVal[0]);
3171                        }
3172                        else if (len == 2)
3173                        {
3174                                toFill.append(charVal[0]);
3175                                toFill.append(charVal[1]);
3176                        }
3177                }
3178                else
3179                {
3180                        // ...just bypass it for now
3181                        toFill.append(chAmpersand);
3182                        toFill.append(entityRef);
3183                        toFill.append(chSemiColon);
3184                }
3185                return 1;
3186        }
3187
3188        // here's where we need to check if there's a SecurityManager,
3189        // how many entity references we've had
3190        if (fSecurityManager != 0 && ++fEntityExpansionCount > fEntityExpansionLimit)
3191        {
3192                XMLCh expLimStr[32];
3193                XMLString::sizeToText(fEntityExpansionLimit, expLimStr, 31, 10, fMemoryManager);
3194                emitError
3195                (
3196                        XMLErrs::EntityExpansionLimitExceeded
3197                        , expLimStr
3198                );
3199                // there seems nothing  better to be done than to reset the entity expansion counter
3200                fEntityExpansionCount = 0;
3201        }
3202
3203        // Look up the name in the general entity pool
3204        XMLEntityDecl * decl = fDTDGrammar->getEntityDecl(entityRef);
3205        InputSource * srcUsed;
3206
3207        // If it does not exist, then obviously an error
3208        if (unlikely(!decl))
3209        {
3210                // XML 1.0 Section 4.1
3211                // Well-formedness Constraint for entity not found:
3212                //   In a document without any DTD, a document with only an internal DTD subset which contains no parameter entity references,
3213                //      or a document with "standalone='yes'", for an entity reference that does not occur within the external subset
3214                //      or a parameter entity
3215                //
3216                // Else it's Validity Constraint
3217                if (fStandalone || fHasNoDTD)
3218                {
3219                        emitError(XMLErrs::EntityNotFound, entityRef);
3220                }
3221                else if (fValidate)
3222                {
3223                        fValidator->emitError(XMLValid::VC_EntityNotFound, entityRef);
3224                }
3225                return 0;
3226        }
3227
3228        // XML 1.0 Section 4.1
3229        //  If we are a standalone document, then it has to have been declared
3230        //  in the internal subset.
3231        if (unlikely(fStandalone && !decl->getDeclaredInIntSubset()))
3232        {
3233                emitError(XMLErrs::IllegalRefInStandalone, entityRef);
3234        }
3235
3236        XMLReader * reader;
3237
3238        if (unlikely(decl->isExternal()))
3239        {
3240                // If its unparsed, then its not valid here
3241                if (unlikely(decl->isUnparsed()))
3242                {
3243                        emitError(XMLErrs::NoUnparsedEntityRefs, entityRef);
3244                        return 0;
3245                }
3246
3247                // And now create a reader to read this entity
3248                reader = fReaderMgr.createReader
3249                (
3250                        decl->getBaseURI()
3251                        , decl->getSystemId()
3252                        , decl->getPublicId()
3253                        , false
3254                        , XMLReader::RefFrom_NonLiteral
3255                        , XMLReader::Type_General
3256                        , XMLReader::Source_External
3257                        , srcUsed
3258                        , fCalculateSrcOfs
3259                        , fLowWaterMark
3260                        , fDisableDefaultEntityResolution
3261                );
3262
3263                // Put a janitor on the source so it gets cleaned up on exit
3264                Janitor<InputSource> janSrc(srcUsed);
3265
3266                //  If the creation failed, and its not because the source was empty,
3267                //  then emit an error and return.
3268                if (!reader)
3269                {
3270                        ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Gen_CouldNotOpenExtEntity, srcUsed ? srcUsed->getSystemId() : decl->getSystemId(), fMemoryManager);
3271                }
3272
3273                // Push the reader. If its a recursive expansion, then emit an error
3274                // and return an failure.
3275                if (!fReaderMgr.pushReader(reader, decl))
3276                {
3277                        emitError(XMLErrs::RecursiveEntity, decl->getName());
3278                        return 0;
3279                }
3280
3281                // If it starts with the XML string, then parse a text decl
3282                if (checkXMLDecl(true))
3283                {
3284                        scanXMLDecl(Decl_Text);
3285                }
3286
3287                XMLCh nextCh;
3288
3289                // now expand the value out
3290                while (fReaderMgr.getNextCharOfCurrentReader(nextCh))
3291                {
3292                        if (unlikely(nextCh == chAmpersand))
3293                        {
3294                                XMLBuffer entity(1023, fMemoryManager);
3295                                while (fReaderMgr.getNextCharOfCurrentReader(nextCh))
3296                                {
3297                                        if (unlikely(nextCh == chSemiColon))
3298                                        {
3299                                                if (!expandEntityRef(entity.getRawBuffer(), inAttributeValue, toFill))
3300                                                {
3301                                                        return 0;
3302                                                }
3303                                                break;
3304                                        }
3305                                        entity.append(nextCh);
3306                                }
3307                        }
3308                        else
3309                        {
3310                                // add it to the buffer
3311                                toFill.append(nextCh);
3312                        }
3313                }
3314        }
3315        else // internal entity
3316        {
3317                const XMLCh * entityValue = decl->getValue();
3318
3319                //  If its a predefined entity reference...
3320                if (decl->getIsSpecialChar())
3321                {
3322                        if (inAttributeValue)
3323                        {
3324                                // and we're in an attribute, add it directly
3325                                toFill.append(decl->getValue()[0]);
3326                        }
3327                        else
3328                        {
3329                                // else just bypass it for now
3330                                toFill.append(chAmpersand);
3331                                toFill.append(entityRef);
3332                                toFill.append(chSemiColon);
3333                        }
3334                        return 1;
3335                }
3336
3337                XMLSize_t length;
3338
3339                // now expand the value out
3340                for (;;)
3341                {
3342                        // is there another entity in this entity value?
3343                        length = XMLStringU::stringLenOrIndexOf<chAmpersand>(entityValue);
3344
3345                        if (likely(length != 0))
3346                        {
3347                                toFill.append(entityValue, length);
3348                        }
3349
3350                        if (likely(entityValue[length] == 0))
3351                        {
3352                                // nope; so we're done!
3353                                break;
3354                        }
3355                        entityValue += length + 1;
3356
3357                        length = XMLStringU::stringLenOrIndexOf<chSemiColon>(entityValue);
3358
3359                        if (unlikely(entityValue[length] == 0))
3360                        {
3361                                return 0;
3362                        }
3363
3364                        const_cast<XMLCh*>(entityValue)[length] = chNull;
3365                        const bool expandedSuccessfully = expandEntityRef(entityValue, inAttributeValue, toFill);
3366                        const_cast<XMLCh*>(entityValue)[length] = chSemiColon;
3367
3368                        if (!expandedSuccessfully)
3369                        {
3370                                return 0;
3371                        }
3372
3373                        entityValue += length + 1;
3374                }
3375        }
3376
3377        return 1;
3378}
3379
3380XERCES_CPP_NAMESPACE_END
Note: See TracBrowser for help on using the repository browser.