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

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

Various fixes

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