source: icXML/icXML-devel/src/icxercesc/internal/SGXMLScanner.cpp @ 2721

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

Fix imports in icXML modified Xerces files

File size: 150.3 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: SGXMLScanner.cpp 925236 2010-03-19 14:29:47Z borisk $
20 */
21
22
23// ---------------------------------------------------------------------------
24//  Includes
25// ---------------------------------------------------------------------------
26#include <icxercesc/internal/SGXMLScanner.hpp>
27#include <xercesc/util/RuntimeException.hpp>
28#include <xercesc/util/UnexpectedEOFException.hpp>
29#include <xercesc/util/XMLUri.hpp>
30#include <xercesc/framework/LocalFileInputSource.hpp>
31#include <xercesc/framework/URLInputSource.hpp>
32#include <xercesc/framework/XMLDocumentHandler.hpp>
33#include <xercesc/framework/XMLEntityHandler.hpp>
34#include <xercesc/framework/XMLPScanToken.hpp>
35#include <xercesc/framework/MemoryManager.hpp>
36#include <icxercesc/framework/XMLGrammarPool.hpp>
37#include <xercesc/framework/psvi/PSVIElement.hpp>
38#include <xercesc/framework/psvi/PSVIHandler.hpp>
39#include <xercesc/framework/psvi/PSVIAttributeList.hpp>
40#include <xercesc/framework/psvi/XSAnnotation.hpp>
41#include <xercesc/internal/EndOfEntityException.hpp>
42#include <xercesc/validators/common/ContentLeafNameTypeVector.hpp>
43#include <xercesc/validators/schema/SchemaValidator.hpp>
44#include <xercesc/validators/schema/TraverseSchema.hpp>
45#include <xercesc/validators/schema/XSDDOMParser.hpp>
46#include <xercesc/validators/schema/SubstitutionGroupComparator.hpp>
47#include <xercesc/validators/schema/XMLSchemaDescriptionImpl.hpp>
48#include <xercesc/validators/schema/identity/IdentityConstraintHandler.hpp>
49#include <xercesc/validators/schema/identity/IC_Selector.hpp>
50#include <xercesc/validators/schema/identity/ValueStore.hpp>
51#include <xercesc/util/OutOfMemoryException.hpp>
52#include <xercesc/util/XMLStringTokenizer.hpp>
53
54XERCES_CPP_NAMESPACE_BEGIN
55
56#define SGXML_SCANNER_DEPRECATED
57
58inline XMLAttDefList& getAttDefList(ComplexTypeInfo* currType, XMLElementDecl* elemDecl);
59
60
61typedef JanitorMemFunCall<SGXMLScanner> CleanupType;
62typedef JanitorMemFunCall<ReaderMgr>    ReaderMgrResetType;
63
64
65// ---------------------------------------------------------------------------
66//  SGXMLScanner: Constructors and Destructor
67// ---------------------------------------------------------------------------
68SGXMLScanner::SGXMLScanner( XMLValidator* const valToAdopt
69                                                  , GrammarResolver* const grammarResolver
70                                                  , MemoryManager* const manager) :
71
72        XMLScanner(valToAdopt, grammarResolver, manager)
73        , fSeeXsi(false)
74        , fGrammarType(Grammar::UnKnown)
75        , fElemStateSize(16)
76        , fElemState(0)
77        , fElemLoopState(0)
78        , fContent(1023, manager)
79        , fEntityTable(0)
80        , fRawAttrList(0)
81        , fRawAttrColonListSize(32)
82        , fRawAttrColonList(0)
83        , fSchemaGrammar(0)
84        , fSchemaValidator(0)
85        , fICHandler(0)
86        , fElemNonDeclPool(0)
87        , fElemCount(0)
88        , fAttDefRegistry(0)
89        , fUndeclaredAttrRegistry(0)
90        , fPSVIAttrList(0)
91        , fModel(0)
92        , fPSVIElement(0)
93        , fErrorStack(0)
94        , fSchemaInfoList(0)
95        , fCachedSchemaInfoList(0)
96#ifdef MOVE_BUFFERS_OUT_OF_XMLSCANNER
97        , fAttNameBuf(1023, manager)
98        , fAttValueBuf(1023, manager)
99        , fCDataBuf(1023, manager)
100        , fQNameBuf(1023, manager)
101        , fPrefixBuf(1023, manager)
102        , fURIBuf(1023, manager)
103        , fWSNormalizeBuf(1023, manager)
104#endif
105{
106        CleanupType cleanup(this, &SGXMLScanner::cleanUp);
107
108        try
109        {
110                 commonInit();
111        }
112        catch(const OutOfMemoryException&)
113        {
114                // Don't cleanup when out of memory, since executing the
115                // code can cause problems.
116                cleanup.release();
117
118                throw;
119        }
120
121        cleanup.release();
122}
123
124SGXMLScanner::SGXMLScanner( XMLDocumentHandler* const docHandler
125                                                  , DocTypeHandler* const     docTypeHandler
126                                                  , XMLEntityHandler* const   entityHandler
127                                                  , XMLErrorReporter* const   errHandler
128                                                  , XMLValidator* const       valToAdopt
129                                                  , GrammarResolver* const    grammarResolver
130                                                  , MemoryManager* const      manager) :
131
132        XMLScanner(docHandler, docTypeHandler, entityHandler, errHandler, valToAdopt, grammarResolver, manager)
133        , fSeeXsi(false)
134        , fGrammarType(Grammar::UnKnown)
135        , fElemStateSize(16)
136        , fElemState(0)
137        , fElemLoopState(0)
138        , fContent(1023, manager)
139        , fEntityTable(0)
140        , fRawAttrList(0)
141        , fRawAttrColonListSize(32)
142        , fRawAttrColonList(0)
143        , fSchemaGrammar(0)
144        , fSchemaValidator(0)
145        , fICHandler(0)
146        , fElemNonDeclPool(0)
147        , fElemCount(0)
148        , fAttDefRegistry(0)
149        , fUndeclaredAttrRegistry(0)
150        , fPSVIAttrList(0)
151        , fModel(0)
152        , fPSVIElement(0)
153        , fErrorStack(0)
154        , fSchemaInfoList(0)
155        , fCachedSchemaInfoList(0)
156#ifdef MOVE_BUFFERS_OUT_OF_XMLSCANNER
157        , fAttNameBuf(1023, manager)
158        , fAttValueBuf(1023, manager)
159        , fCDataBuf(1023, manager)
160        , fQNameBuf(1023, manager)
161        , fPrefixBuf(1023, manager)
162        , fURIBuf(1023, manager)
163        , fWSNormalizeBuf(1023, manager)
164#endif
165{
166        CleanupType cleanup(this, &SGXMLScanner::cleanUp);
167
168        try
169        {
170                commonInit();
171        }
172        catch(const OutOfMemoryException&)
173        {
174                // Don't cleanup when out of memory, since executing the
175                // code can cause problems.
176                cleanup.release();
177
178                throw;
179        }
180
181        cleanup.release();
182}
183
184SGXMLScanner::~SGXMLScanner()
185{
186        cleanUp();
187}
188
189// ---------------------------------------------------------------------------
190//  XMLScanner: Getter methods
191// ---------------------------------------------------------------------------
192NameIdPool<DTDEntityDecl>* SGXMLScanner::getEntityDeclPool()
193{
194        return 0;
195}
196
197const NameIdPool<DTDEntityDecl>* SGXMLScanner::getEntityDeclPool() const
198{
199        return 0;
200}
201
202// ---------------------------------------------------------------------------
203//  SGXMLScanner: Main entry point to scan a document
204// ---------------------------------------------------------------------------
205void SGXMLScanner::scanDocument(const InputSource& src)
206{
207#ifdef SGXML_SCANNER_DEPRECATED
208        DEPRECATED_FEATURE_IN_ICXML;
209#else
210        //  Bump up the sequence id for this parser instance. This will invalidate
211        //  any previous progressive scan tokens.
212        fSequenceId++;
213
214        ReaderMgrResetType  resetReaderMgr(&fReaderMgr, &ReaderMgr::reset);
215
216        try
217        {
218                //  Reset the scanner and its plugged in stuff for a new run. This
219                //  resets all the data structures, creates the initial reader and
220                //  pushes it on the stack, and sets up the base document path.
221                scanReset(src);
222
223                // If we have a document handler, then call the start document
224                if (fDocHandler)
225                        fDocHandler->startDocument();
226
227                //  Scan the prolog part, which is everything before the root element
228                //  including the DTD subsets.
229                scanProlog();
230
231                //  If we got to the end of input, then its not a valid XML file.
232                //  Else, go on to scan the content.
233                if (fReaderMgr.atEOF())
234                {
235                        emitError(XMLErrs::EmptyMainEntity);
236                }
237                else
238                {
239                        // Scan content, and tell it its not an external entity
240                        if (scanContent())
241                        {
242                                // Do post-parse validation if required
243                                if (fValidate)
244                                {
245                                        //  We handle ID reference semantics at this level since
246                                        //  its required by XML 1.0.
247                                        checkIDRefs();
248
249                                        // Then allow the validator to do any extra stuff it wants
250//                    fValidator->postParseValidation();
251                                }
252
253                                // That went ok, so scan for any miscellaneous stuff
254                                if (!fReaderMgr.atEOF())
255                                        scanMiscellaneous();
256                        }
257                }
258
259                // If we have a document handler, then call the end document
260                if (fDocHandler)
261                        fDocHandler->endDocument();
262        }
263        //  NOTE:
264        //
265        //  In all of the error processing below, the emitError() call MUST come
266        //  before the flush of the reader mgr, or it will fail because it tries
267        //  to find out the position in the XML source of the error.
268        catch(const XMLErrs::Codes)
269        {
270                // This is a 'first failure' exception, so fall through
271        }
272        catch(const XMLValid::Codes)
273        {
274                // This is a 'first fatal error' type exit, so fall through
275        }
276        catch(const XMLException& excToCatch)
277        {
278                //  Emit the error and catch any user exception thrown from here. Make
279                //  sure in all cases we flush the reader manager.
280                fInException = true;
281                try
282                {
283                        if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning)
284                                emitError
285                                (
286                                        XMLErrs::XMLException_Warning
287                                        , excToCatch.getCode()
288                                        , excToCatch.getMessage()
289                                );
290                        else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal)
291                                emitError
292                                (
293                                        XMLErrs::XMLException_Fatal
294                                        , excToCatch.getCode()
295                                        , excToCatch.getMessage()
296                                );
297                        else
298                                emitError
299                                (
300                                        XMLErrs::XMLException_Error
301                                        , excToCatch.getCode()
302                                        , excToCatch.getMessage()
303                                );
304                }
305                catch(const OutOfMemoryException&)
306                {
307                        // This is a special case for out-of-memory
308                        // conditions, because resetting the ReaderMgr
309                        // can be problematic.
310                        resetReaderMgr.release();
311
312                        throw;
313                }
314        }
315        catch(const OutOfMemoryException&)
316        {
317                // This is a special case for out-of-memory
318                // conditions, because resetting the ReaderMgr
319                // can be problematic.
320                resetReaderMgr.release();
321
322                throw;
323        }
324#endif
325}
326
327
328bool SGXMLScanner::scanNext(XMLPScanToken& token)
329{
330#ifdef SGXML_SCANNER_DEPRECATED
331        DEPRECATED_FEATURE_IN_ICXML;
332#else
333        // Make sure this token is still legal
334        if (!isLegalToken(token))
335                ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Scan_BadPScanToken, fMemoryManager);
336
337        // Find the next token and remember the reader id
338        XMLSize_t orgReader;
339        XMLTokens curToken;
340
341        ReaderMgrResetType  resetReaderMgr(&fReaderMgr, &ReaderMgr::reset);
342
343        bool retVal = true;
344
345        try
346        {
347                while (true)
348                {
349                        //  We have to handle any end of entity exceptions that happen here.
350                        //  We could be at the end of X nested entities, each of which will
351                        //  generate an end of entity exception as we try to move forward.
352                        try
353                        {
354                                curToken = senseNextToken(orgReader);
355                                break;
356                        }
357                        catch(const EndOfEntityException& toCatch)
358                        {
359                                // Send an end of entity reference event
360                                if (fDocHandler)
361                                        fDocHandler->endEntityReference(toCatch.getEntity());
362                        }
363                }
364
365                if (curToken == Token_CharData)
366                {
367                        scanCharData(fCDataBuf);
368                }
369                else if (curToken == Token_EOF)
370                {
371                        if (!fElemStack.isEmpty())
372                        {
373                                const ElemStack::StackElem* topElem = fElemStack.popTop();
374                                emitError
375                                (
376                                        XMLErrs::EndedWithTagsOnStack
377                                        , topElem->fThisElement->getFullName()
378                                );
379                        }
380
381                        retVal = false;
382                }
383                else
384                {
385                        // Its some sort of markup
386                        bool gotData = true;
387                        switch(curToken)
388                        {
389                                case Token_CData :
390                                        // Make sure we are within content
391                                        if (fElemStack.isEmpty())
392                                                emitError(XMLErrs::CDATAOutsideOfContent);
393                                        scanCDSection();
394                                        break;
395
396                                case Token_Comment :
397                                        scanComment();
398                                        break;
399
400                                case Token_EndTag :
401                                        scanEndTag(gotData);
402                                        break;
403
404                                case Token_PI :
405                                        scanPI();
406                                        break;
407
408                                case Token_StartTag :
409                                        scanStartTag(gotData);
410                                        break;
411
412                                default :
413                                        fReaderMgr.skipToChar(chOpenAngle);
414                                        break;
415                        }
416
417                        if (orgReader != fReaderMgr.getCurrentReaderNum())
418                                emitError(XMLErrs::PartialMarkupInEntity);
419
420                        // If we hit the end, then do the miscellaneous part
421                        if (!gotData)
422                        {
423                                // Do post-parse validation if required
424                                if (fValidate)
425                                {
426                                        //  We handle ID reference semantics at this level since
427                                        //  its required by XML 1.0.
428                                        checkIDRefs();
429
430                                        // Then allow the validator to do any extra stuff it wants
431//                    fValidator->postParseValidation();
432                                }
433
434                                // That went ok, so scan for any miscellaneous stuff
435                                scanMiscellaneous();
436
437                                if (toCheckIdentityConstraint())
438                                        fICHandler->endDocument();
439
440                                if (fDocHandler)
441                                        fDocHandler->endDocument();
442                        }
443                }
444        }
445        //  NOTE:
446        //
447        //  In all of the error processing below, the emitError() call MUST come
448        //  before the flush of the reader mgr, or it will fail because it tries
449        //  to find out the position in the XML source of the error.
450        catch(const XMLErrs::Codes)
451        {
452                // This is a 'first failure' exception, so return failure
453                retVal = false;
454        }
455        catch(const XMLValid::Codes)
456        {
457                // This is a 'first fatal error' type exit, so return failure
458                retVal = false;
459        }
460        catch(const XMLException& excToCatch)
461        {
462                //  Emit the error and catch any user exception thrown from here. Make
463                //  sure in all cases we flush the reader manager.
464                fInException = true;
465                try
466                {
467                        if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning)
468                                emitError
469                                (
470                                        XMLErrs::XMLException_Warning
471                                        , excToCatch.getCode()
472                                        , excToCatch.getMessage()
473                                );
474                        else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal)
475                                emitError
476                                (
477                                        XMLErrs::XMLException_Fatal
478                                        , excToCatch.getCode()
479                                        , excToCatch.getMessage()
480                                );
481                        else
482                                emitError
483                                (
484                                        XMLErrs::XMLException_Error
485                                        , excToCatch.getCode()
486                                        , excToCatch.getMessage()
487                                );
488                }
489                catch(const OutOfMemoryException&)
490                {
491                        // This is a special case for out-of-memory
492                        // conditions, because resetting the ReaderMgr
493                        // can be problematic.
494                        resetReaderMgr.release();
495
496                        throw;
497                }
498
499                retVal = false;
500        }
501        catch(const OutOfMemoryException&)
502        {
503                // This is a special case for out-of-memory
504                // conditions, because resetting the ReaderMgr
505                // can be problematic.
506                resetReaderMgr.release();
507
508                throw;
509        }
510
511        // If we are not at the end, release the object that will
512        // reset the ReaderMgr.
513        if (retVal)
514                resetReaderMgr.release();
515
516        return retVal;
517#endif
518}
519
520// ---------------------------------------------------------------------------
521//  SGXMLScanner: Private scanning methods
522// ---------------------------------------------------------------------------
523
524//  This method will kick off the scanning of the primary content of the
525//  document, i.e. the elements.
526bool SGXMLScanner::scanContent()
527{
528#ifdef SGXML_SCANNER_DEPRECATED
529        DEPRECATED_FEATURE_IN_ICXML;
530#else
531
532#ifndef EXCLUDE_TRADITIONAL_XERCES_FUNCTIONS_AND_VARIABLES
533        //  Go into a loop until we hit the end of the root element, or we fall
534        //  out because there is no root element.
535        //
536        //  We have to do kind of a deeply nested double loop here in order to
537        //  avoid doing the setup/teardown of the exception handler on each
538        //  round. Doing it this way we only do it when an exception actually
539        //  occurs.
540        bool gotData = true;
541        bool inMarkup = false;
542        while (gotData)
543        {
544                try
545                {
546                        while (gotData)
547                        {
548                                //  Sense what the next top level token is. According to what
549                                //  this tells us, we will call something to handle that kind
550                                //  of thing.
551                                XMLSize_t orgReader;
552                                const XMLTokens curToken = senseNextToken(orgReader);
553
554                                //  Handle character data and end of file specially. Char data
555                                //  is not markup so we don't want to handle it in the loop
556                                //  below.
557                                if (curToken == Token_CharData)
558                                {
559                                        //  Scan the character data and call appropriate events. Let
560                                        //  him use our local character data buffer for efficiency.
561                                        scanCharData(fCDataBuf);
562                                        continue;
563                                }
564                                else if (curToken == Token_EOF)
565                                {
566                                        //  The element stack better be empty at this point or we
567                                        //  ended prematurely before all elements were closed.
568                                        if (!fElemStack.isEmpty())
569                                        {
570                                                const ElemStack::StackElem* topElem = fElemStack.popTop();
571                                                emitError
572                                                (
573                                                        XMLErrs::EndedWithTagsOnStack
574                                                        , topElem->fThisElement->getFullName()
575                                                );
576                                        }
577
578                                        // Its the end of file, so clear the got data flag
579                                        gotData = false;
580                                        continue;
581                                }
582
583                                // We are in some sort of markup now
584                                inMarkup = true;
585
586                                //  According to the token we got, call the appropriate
587                                //  scanning method.
588                                switch(curToken)
589                                {
590                                        case Token_CData :
591                                                // Make sure we are within content
592                                                if (fElemStack.isEmpty())
593                                                        emitError(XMLErrs::CDATAOutsideOfContent);
594                                                scanCDSection();
595                                                break;
596
597                                        case Token_Comment :
598                                                scanComment();
599                                                break;
600
601                                        case Token_EndTag :
602                                                scanEndTag(gotData);
603                                                break;
604
605                                        case Token_PI :
606                                                scanPI();
607                                                break;
608
609                                        case Token_StartTag :
610                                                scanStartTag(gotData);
611                                                break;
612
613                                        default :
614                                                fReaderMgr.skipToChar(chOpenAngle);
615                                                break;
616                                }
617
618                                if (orgReader != fReaderMgr.getCurrentReaderNum())
619                                        emitError(XMLErrs::PartialMarkupInEntity);
620
621                                // And we are back out of markup again
622                                inMarkup = false;
623                        }
624                }
625                catch(const EndOfEntityException& toCatch)
626                {
627                        //  If we were in some markup when this happened, then its a
628                        //  partial markup error.
629                        if (inMarkup)
630                                emitError(XMLErrs::PartialMarkupInEntity);
631
632                        // Send an end of entity reference event
633                        if (fDocHandler)
634                                fDocHandler->endEntityReference(toCatch.getEntity());
635
636                        inMarkup = false;
637                }
638        }
639#endif
640        // It went ok, so return success
641        return true;
642#endif
643}
644
645
646void SGXMLScanner::scanEndTag(bool& gotData)
647{
648#ifdef SGXML_SCANNER_DEPRECATED
649        DEPRECATED_FEATURE_IN_ICXML;
650#else
651
652#ifndef EXCLUDE_TRADITIONAL_XERCES_FUNCTIONS_AND_VARIABLES
653        //  Assume we will still have data until proven otherwise. It will only
654        //  ever be false if this is the end of the root element.
655        gotData = true;
656
657        //  Check if the element stack is empty. If so, then this is an unbalanced
658        //  element (i.e. more ends than starts, perhaps because of bad text
659        //  causing one to be skipped.)
660        if (fElemStack.isEmpty())
661        {
662                emitError(XMLErrs::MoreEndThanStartTags);
663                fReaderMgr.skipPastChar(chCloseAngle);
664                ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Scan_UnbalancedStartEnd, fMemoryManager);
665        }
666
667        //  Pop the stack of the element we are supposed to be ending. Remember
668        //  that we don't own this. The stack just keeps them and reuses them.
669        unsigned int uriId = (fDoNamespaces)
670                ? fElemStack.getCurrentURI() :
671                #ifdef TEST_NAMESPACE_RESOLVER
672                XMLNamespaceResolver::fEmptyUriId;
673                #else
674                fEmptyNamespaceId;
675                #endif
676        // Make sure that its the end of the element that we expect
677        const XMLCh *elemName = fElemStack.getCurrentSchemaElemName();
678        const ElemStack::StackElem* topElem = fElemStack.topElement();
679        if (!fReaderMgr.skippedStringLong(elemName))
680        {
681                emitError
682                (
683                        XMLErrs::ExpectedEndOfTagX
684                        , elemName
685                );
686                fReaderMgr.skipPastChar(chCloseAngle);
687                fElemStack.popTop();
688                return;
689        }
690
691        fPSVIElemContext.fErrorOccurred = fErrorStack->pop();
692
693        // Make sure we are back on the same reader as where we started
694        if (topElem->fReaderNum != fReaderMgr.getCurrentReaderNum())
695                emitError(XMLErrs::PartialTagMarkupError);
696
697        // Skip optional whitespace
698        fReaderMgr.skipPastSpaces();
699
700        // Make sure we find the closing bracket
701        if (!fReaderMgr.skippedChar(chCloseAngle))
702        {
703                emitError
704                (
705                        XMLErrs::UnterminatedEndTag
706                        , topElem->fThisElement->getFullName()
707                );
708        }
709
710        if (fValidate && topElem->fThisElement->isDeclared())
711        {
712                fPSVIElemContext.fCurrentTypeInfo = ((SchemaValidator*) fValidator)->getCurrentTypeInfo();
713                if(!fPSVIElemContext.fCurrentTypeInfo)
714                        fPSVIElemContext.fCurrentDV = ((SchemaValidator*) fValidator)->getCurrentDatatypeValidator();
715                else
716                        fPSVIElemContext.fCurrentDV = 0;
717                if (fPSVIHandler)
718                {
719                        fPSVIElemContext.fNormalizedValue = ((SchemaValidator*) fValidator)->getNormalizedValue();
720
721                        if (XMLString::equals(fPSVIElemContext.fNormalizedValue, XMLUni::fgZeroLenString))
722                                fPSVIElemContext.fNormalizedValue = 0;
723
724                }
725        }
726        else
727        {
728                fPSVIElemContext.fCurrentDV = 0;
729                fPSVIElemContext.fCurrentTypeInfo = 0;
730                fPSVIElemContext.fNormalizedValue = 0;
731        }
732
733        //  If validation is enabled, then lets pass him the list of children and
734        //  this element and let him validate it.
735        DatatypeValidator* psviMemberType = 0;
736        if (fValidate)
737        {
738                XMLSize_t failure;
739                bool res = fValidator->checkContent
740                (
741                        topElem->fThisElement
742                        , topElem->fChildren
743                        , topElem->fChildCount
744                        , &failure
745                );
746
747                if (!res)
748                {
749                        //  One of the elements is not valid for the content. NOTE that
750                        //  if no children were provided but the content model requires
751                        //  them, it comes back with a zero value. But we cannot use that
752                        //  to index the child array in this case, and have to put out a
753                        //  special message.
754                        if (!topElem->fChildCount)
755                        {
756                                fValidator->emitError
757                                (
758                                        XMLValid::EmptyNotValidForContent
759                                        , topElem->fThisElement->getFormattedContentModel()
760                                );
761                        }
762                        else if (failure >= topElem->fChildCount)
763                        {
764                                fValidator->emitError
765                                (
766                                        XMLValid::NotEnoughElemsForCM
767                                        , topElem->fThisElement->getFormattedContentModel()
768                                );
769                        }
770                        else
771                        {
772                                fValidator->emitError
773                                (
774                                        XMLValid::ElementNotValidForContent
775                                        , topElem->fChildren[failure]->getRawName()
776                                        , topElem->fThisElement->getFormattedContentModel()
777                                );
778                        }
779
780                }
781
782                // update PSVI info
783                if (((SchemaValidator*) fValidator)->getErrorOccurred())
784                        fPSVIElemContext.fErrorOccurred = true;
785                else if (fPSVIElemContext.fCurrentDV && fPSVIElemContext.fCurrentDV->getType() == DatatypeValidator::Union)
786                        psviMemberType = fValidationContext->getValidatingMemberType();
787                if (fPSVIHandler)
788                {
789                        fPSVIElemContext.fIsSpecified = ((SchemaValidator*) fValidator)->getIsElemSpecified();
790                        if(fPSVIElemContext.fIsSpecified)
791                                fPSVIElemContext.fNormalizedValue = ((SchemaElementDecl *)topElem->fThisElement)->getDefaultValue();
792                }
793
794                // call matchers and de-activate context
795                if (toCheckIdentityConstraint())
796                {
797                        fICHandler->deactivateContext
798                                                (
799                                                 (SchemaElementDecl *) topElem->fThisElement
800                                           , fContent.getRawBuffer()
801                                           , fValidationContext
802                                           , fPSVIElemContext.fCurrentDV
803                                                );
804                }
805
806        }
807
808        // QName dv needed topElem to resolve URIs on the checkContent
809        fElemStack.popTop();
810
811        // See if it was the root element, to avoid multiple calls below
812        const bool isRoot = fElemStack.isEmpty();
813
814        if (fPSVIHandler)
815        {
816                endElementPSVI
817                (
818                        (SchemaElementDecl*)topElem->fThisElement, psviMemberType
819                );
820        }
821        // now we can reset the datatype buffer, since the
822        // application has had a chance to copy the characters somewhere else
823        ((SchemaValidator *)fValidator)->clearDatatypeBuffer();
824
825        // If we have a doc handler, tell it about the end tag
826        if (fDocHandler)
827        {
828                fDocHandler->endElement
829                (
830                        *topElem->fThisElement
831                        , uriId
832                        , isRoot
833                        , topElem->fThisElement->getElementName()->getPrefix()
834                );
835        }
836
837        if (!isRoot)
838        {
839                // update error information
840                fErrorStack->push((fErrorStack->size() && fErrorStack->pop()) || fPSVIElemContext.fErrorOccurred);
841        }
842
843        // If this was the root, then done with content
844        gotData = !isRoot;
845
846        if (gotData) {
847
848                // Restore the grammar
849                fGrammar = fElemStack.getCurrentGrammar();
850                fGrammarType = fGrammar->getGrammarType();
851                fValidator->setGrammar(fGrammar);
852
853                // Restore the validation flag
854                fValidate = fElemStack.getValidationFlag();
855        }
856#endif
857#endif
858}
859
860
861//  This method handles the high level logic of scanning the DOCType
862//  declaration. This calls the DTDScanner and kicks off both the scanning of
863//  the internal subset and the scanning of the external subset, if any.
864//
865//  When we get here the '<!DOCTYPE' part has already been scanned, which is
866//  what told us that we had a doc type decl to parse.
867void SGXMLScanner::scanDocTypeDecl()
868{
869#ifdef SGXML_SCANNER_DEPRECATED
870        DEPRECATED_FEATURE_IN_ICXML;
871#else
872        // Just skips over it
873        // REVISIT: Should we issue a warning
874        static const XMLCh doctypeIE[] =
875        {
876                        chOpenSquare, chCloseAngle, chNull
877        };
878        XMLCh nextCh = fReaderMgr.skipUntilIn(doctypeIE);
879
880        if (nextCh == chOpenSquare)
881                fReaderMgr.skipPastChar(chCloseSquare);
882
883        fReaderMgr.skipPastChar(chCloseAngle);
884#endif
885}
886
887//  This method is called to scan a start tag when we are processing
888//  namespaces. This method is called after we've scanned the < of a
889//  start tag. So we have to get the element name, then scan the attributes,
890//  after which we are either going to see >, />, or attributes followed
891//  by one of those sequences.
892bool SGXMLScanner::scanStartTag(bool& gotData)
893{
894#ifdef SGXML_SCANNER_DEPRECATED
895        DEPRECATED_FEATURE_IN_ICXML;
896#else
897#ifndef EXCLUDE_TRADITIONAL_XERCES_FUNCTIONS_AND_VARIABLES
898        //  Assume we will still have data until proven otherwise. It will only
899        //  ever be false if this is the root and its empty.
900        gotData = true;
901
902        // Reset element content
903        fContent.reset();
904
905        //  The current position is after the open bracket, so we need to read in
906        //  in the element name.
907        int prefixColonPos;
908        if (!fReaderMgr.getQName(fQNameBuf, &prefixColonPos))
909        {
910                if (fQNameBuf.isEmpty())
911                        emitError(XMLErrs::ExpectedElementName);
912                else
913                        emitError(XMLErrs::InvalidElementName, fQNameBuf.getRawBuffer());
914                fReaderMgr.skipToChar(chOpenAngle);
915                return false;
916        }
917
918        // See if its the root element
919        const bool isRoot = fElemStack.isEmpty();
920
921        // Skip any whitespace after the name
922        fReaderMgr.skipPastSpaces();
923
924        //  First we have to do the rawest attribute scan. We don't do any
925        //  normalization of them at all, since we don't know yet what type they
926        //  might be (since we need the element decl in order to do that.)
927        const XMLCh* qnameRawBuf = fQNameBuf.getRawBuffer();
928        bool isEmpty;
929        XMLSize_t attCount = rawAttrScan
930        (
931                qnameRawBuf
932                , *fRawAttrList
933                , isEmpty
934        );
935
936        // save the contentleafname and currentscope before addlevel, for later use
937        ContentLeafNameTypeVector* cv = 0;
938        XMLContentModel* cm = 0;
939        unsigned int currentScope = Grammar::TOP_LEVEL_SCOPE;
940        bool laxValidation = false;
941        if (!isRoot)
942        {
943                // schema validator will have correct type if validating
944                SchemaElementDecl* tempElement = (SchemaElementDecl*)
945                        fElemStack.topElement()->fThisElement;
946                SchemaElementDecl::ModelTypes modelType = tempElement->getModelType();
947                ComplexTypeInfo *currType = 0;
948
949                if (fValidate)
950                {
951                        currType = ((SchemaValidator*)fValidator)->getCurrentTypeInfo();
952                        if (currType)
953                                modelType = (SchemaElementDecl::ModelTypes)currType->getContentType();
954                        else // something must have gone wrong
955                                modelType = SchemaElementDecl::Any;
956                }
957                else
958                {
959                        currType = tempElement->getComplexTypeInfo();
960                }
961
962                if ((modelType == SchemaElementDecl::Mixed_Simple)
963                  ||  (modelType == SchemaElementDecl::Mixed_Complex)
964                  ||  (modelType == SchemaElementDecl::Children))
965                {
966                        cm = currType->getContentModel();
967                        cv = cm->getContentLeafNameTypeVector();
968                        currentScope = fElemStack.getCurrentScope();
969                }
970                else if (modelType == SchemaElementDecl::Any) {
971                        laxValidation = true;
972                }
973        }
974
975        //  Now, since we might have to update the namespace map for this element,
976        //  but we don't have the element decl yet, we just tell the element stack
977        //  to expand up to get ready.
978        XMLSize_t elemDepth = fElemStack.addLevel();
979        fElemStack.setValidationFlag(fValidate);
980
981        //  Check if there is any external schema location specified, and if we are at root,
982        //  go through them first before scanning those specified in the instance document
983        if (isRoot
984                && (fExternalSchemaLocation || fExternalNoNamespaceSchemaLocation)) {
985
986                if (fExternalSchemaLocation)
987                        parseSchemaLocation(fExternalSchemaLocation, true);
988                if (fExternalNoNamespaceSchemaLocation)
989                        resolveSchemaGrammar(fExternalNoNamespaceSchemaLocation, XMLUni::fgZeroLenString, true);
990        }
991
992        //  Make an initial pass through the list and find any xmlns attributes or
993        //  schema attributes.
994        if (attCount)
995                scanRawAttrListforNameSpaces(attCount);
996
997        //  Resolve the qualified name to a URI and name so that we can look up
998        //  the element decl for this element. We have now update the prefix to
999        //  namespace map so we should get the correct element now.
1000        unsigned int uriId = resolveQNameWithColon
1001        (
1002                qnameRawBuf
1003                , fPrefixBuf
1004                , ElemStack::Mode_Element
1005                , prefixColonPos
1006        );
1007
1008        //if schema, check if we should lax or skip the validation of this element
1009        bool parentValidation = fValidate;
1010        if (cv)
1011        {
1012                QName element(fPrefixBuf.getRawBuffer(), &qnameRawBuf[prefixColonPos + 1], uriId, fMemoryManager);
1013                // elementDepth will be > 0, as cv is only constructed if element is not
1014                // root.
1015                laxValidation = laxElementValidation(&element, cv, cm, elemDepth - 1);
1016        }
1017
1018        //  Look up the element now in the grammar. This will get us back a
1019        //  generic element decl object. We tell him to fault one in if he does
1020        //  not find it.
1021        XMLElementDecl* elemDecl = 0;
1022        bool wasAdded = false;
1023        const XMLCh* nameRawBuf = &qnameRawBuf[prefixColonPos + 1];
1024        const XMLCh* original_uriStr = fGrammar->getTargetNamespace();
1025
1026
1027#ifdef TEST_NAMESPACE_RESOLVER
1028        if (uriId != XMLNamespaceResolver::fEmptyUriId)
1029#else
1030        if (uriId != fEmptyNamespaceId)
1031#endif
1032        {
1033                // Check in current grammar before switching if necessary
1034                elemDecl = fGrammar->getElemDecl
1035                (
1036                  uriId
1037                  , nameRawBuf
1038                  , qnameRawBuf
1039                  , currentScope
1040                );
1041
1042                if (!elemDecl)
1043                {
1044                        // look in the list of undeclared elements, as would have been done
1045                        // before we made grammars stateless:
1046                        elemDecl = fElemNonDeclPool->getByKey(nameRawBuf, uriId, currentScope);
1047                }
1048                // this is initialized correctly only if there is
1049                // no element decl.  The other uses in this scope will only
1050                // be encountered if there continues to be no element decl--which
1051                // implies that this will have been initialized correctly.
1052                unsigned int orgGrammarUri = uriId;
1053                if (!elemDecl)
1054                {
1055                        #ifdef TEST_NAMESPACE_RESOLVER
1056                        orgGrammarUri = fUriResolver->resolveUriId(original_uriStr);
1057                        #else
1058                        orgGrammarUri = fURIStringPool->getId(original_uriStr);
1059                        #endif
1060                        if (orgGrammarUri != uriId)
1061                        {
1062                                // not found, switch to the specified grammar
1063                                #ifdef TEST_NAMESPACE_RESOLVER
1064                                const XMLCh* uriStr = fUriResolver->getUriForId(uriId);
1065                                #else
1066                                const XMLCh* uriStr = getURIText(uriId);
1067                                #endif
1068                                bool errorCondition = !switchGrammar(uriStr) && fValidate;
1069                                if (errorCondition && !laxValidation)
1070                                {
1071                                        fValidator->emitError
1072                                        (
1073                                                XMLValid::GrammarNotFound
1074                                                ,uriStr
1075                                        );
1076                                }
1077
1078                                elemDecl = fGrammar->getElemDecl
1079                                (
1080                                  uriId
1081                                  , nameRawBuf
1082                                  , qnameRawBuf
1083                                  , currentScope
1084                                );
1085                        }
1086                }
1087
1088                if (!elemDecl && currentScope != Grammar::TOP_LEVEL_SCOPE) {
1089                        // if not found, then it may be a reference, try TOP_LEVEL_SCOPE
1090                        elemDecl = fGrammar->getElemDecl
1091                                           (
1092                                                   uriId
1093                                                   , nameRawBuf
1094                                                   , qnameRawBuf
1095                                                   , Grammar::TOP_LEVEL_SCOPE
1096                                           );
1097                        if(!elemDecl)
1098                        {
1099                                // look in the list of undeclared elements, as would have been done
1100                                // before we made grammars stateless:
1101                                elemDecl = fElemNonDeclPool->getByKey(nameRawBuf, uriId, (int)Grammar::TOP_LEVEL_SCOPE);
1102                        }
1103                        if(!elemDecl) {
1104                                // still not found in specified uri
1105                                // try emptyNamespace see if element should be un-qualified.
1106                                // Use a temp variable until we decide this is the case
1107                                XMLElementDecl* tempElemDecl = fGrammar->getElemDecl
1108                                                   (
1109                                                                #ifdef TEST_NAMESPACE_RESOLVER
1110                                                                XMLNamespaceResolver::fEmptyUriId
1111                                                                #else
1112                                                                fEmptyNamespaceId
1113                                                                #endif
1114                                                           , nameRawBuf
1115                                                           , qnameRawBuf
1116                                                           , currentScope
1117                                                   );
1118                                if (tempElemDecl && tempElemDecl->getCreateReason() != XMLElementDecl::JustFaultIn && fValidate)
1119                                {
1120                                        fValidator->emitError
1121                                        (
1122                                                XMLValid::ElementNotUnQualified
1123                                                , qnameRawBuf
1124                                        );
1125                                        elemDecl = tempElemDecl;
1126                                }
1127                        }
1128                }
1129
1130                if (!elemDecl)
1131                {
1132                        // still not found, fault this in and issue error later
1133                        // switch back to original grammar first (if necessary)
1134                        if(orgGrammarUri != uriId)
1135                        {
1136                                switchGrammar(original_uriStr);
1137                        }
1138                        elemDecl = new (fMemoryManager) SchemaElementDecl
1139                        (
1140                                fPrefixBuf.getRawBuffer()
1141                                , nameRawBuf
1142                                , uriId
1143                                , SchemaElementDecl::Any
1144                                , Grammar::TOP_LEVEL_SCOPE
1145                                , fMemoryManager
1146                        );
1147                        elemDecl->setId(fElemNonDeclPool->put((void*)elemDecl->getBaseName(), uriId, currentScope, (SchemaElementDecl*)elemDecl));
1148                        wasAdded = true;
1149                }
1150        }
1151        else if (!elemDecl)
1152        {
1153                //the element has no prefix,
1154                //thus it is either a non-qualified element defined in current targetNS
1155                //or an element that is defined in the globalNS
1156
1157                //try unqualifed first
1158                elemDecl = fGrammar->getElemDecl
1159                                        (
1160                                                  uriId
1161                                                , nameRawBuf
1162                                                , qnameRawBuf
1163                                                , currentScope
1164                                        );
1165                if(!elemDecl)
1166                {
1167                        // look in the list of undeclared elements, as would have been done
1168                        // before we made grammars stateless:
1169                        elemDecl = fElemNonDeclPool->getByKey(nameRawBuf, uriId, currentScope);
1170                }
1171                // this is initialized correctly only if there is
1172                // no element decl.  The other uses in this scope will only
1173                // be encountered if there continues to be no element decl--which
1174                // implies that this will have been initialized correctly.
1175                #ifdef TEST_NAMESPACE_RESOLVER
1176                unsigned int orgGrammarUri = XMLNamespaceResolver::fEmptyUriId;
1177                #else
1178                unsigned int orgGrammarUri = fEmptyNamespaceId;
1179                #endif
1180                if (!elemDecl)
1181                {
1182                        #ifdef TEST_NAMESPACE_RESOLVER
1183                        orgGrammarUri = fUriResolver->resolveUriId(original_uriStr);
1184                        #else
1185                        orgGrammarUri = fURIStringPool->getId(original_uriStr);
1186                        #endif
1187                        if (orgGrammarUri != fEmptyNamespaceId)
1188                        {
1189                                //not found, switch grammar and try globalNS
1190                                bool errorCondition = !switchGrammar(XMLUni::fgZeroLenString) && fValidate;
1191                                if (errorCondition && !laxValidation)
1192                                {
1193                                        fValidator->emitError
1194                                        (
1195                                                XMLValid::GrammarNotFound
1196                                          , XMLUni::fgZeroLenString
1197                                        );
1198                                }
1199
1200                                elemDecl = fGrammar->getElemDecl
1201                                (
1202                                  uriId
1203                                  , nameRawBuf
1204                                  , qnameRawBuf
1205                                  , currentScope
1206                                );
1207                        }
1208                }
1209
1210                if (!elemDecl && currentScope != Grammar::TOP_LEVEL_SCOPE)
1211                {
1212                        // if not found, then it may be a reference, try TOP_LEVEL_SCOPE
1213                        elemDecl = fGrammar->getElemDecl
1214                                           (
1215                                                   uriId
1216                                                   , nameRawBuf
1217                                                   , qnameRawBuf
1218                                                   , Grammar::TOP_LEVEL_SCOPE
1219                                           );
1220                        if(!elemDecl)
1221                        {
1222                                // look in the list of undeclared elements, as would have been done
1223                                // before we made grammars stateless:
1224                                elemDecl = fElemNonDeclPool->getByKey(nameRawBuf, uriId, (int)Grammar::TOP_LEVEL_SCOPE);
1225                        }
1226                        if (!elemDecl && orgGrammarUri != fEmptyNamespaceId) {
1227                                // still Not found in specified uri
1228                                // go to original Grammar again to see if element needs to be fully qualified.
1229                                bool errorCondition = !switchGrammar(original_uriStr) && fValidate;
1230                                if (errorCondition && !laxValidation)
1231                                {
1232                                        fValidator->emitError
1233                                        (
1234                                                XMLValid::GrammarNotFound
1235                                                ,original_uriStr
1236                                        );
1237                                }
1238
1239                                // Use a temp variable until we decide this is the case
1240                                XMLElementDecl* tempElemDecl = fGrammar->getElemDecl
1241                                                   (
1242                                                           orgGrammarUri
1243                                                           , nameRawBuf
1244                                                           , qnameRawBuf
1245                                                           , currentScope
1246                                                   );
1247                                if (tempElemDecl && tempElemDecl->getCreateReason() != XMLElementDecl::JustFaultIn && fValidate) {
1248                                        fValidator->emitError
1249                                        (
1250                                                XMLValid::ElementNotQualified
1251                                                , qnameRawBuf
1252                                        );
1253                                        elemDecl=tempElemDecl;
1254                                }
1255                        }
1256                }
1257
1258                if (!elemDecl)
1259                {
1260                        // still not found, fault this in and issue error later
1261                        // switch back to original grammar first (if necessary)
1262
1263                        if(orgGrammarUri != fEmptyNamespaceId)
1264                        {
1265                                switchGrammar(original_uriStr);
1266                        }
1267                        elemDecl = new (fMemoryManager) SchemaElementDecl
1268                        (
1269                                fPrefixBuf.getRawBuffer()
1270                                , nameRawBuf
1271                                , uriId
1272                                , SchemaElementDecl::Any
1273                                , Grammar::TOP_LEVEL_SCOPE
1274                                , fMemoryManager
1275                        );
1276                        elemDecl->setId(fElemNonDeclPool->put((void*)elemDecl->getBaseName(), uriId, currentScope, (SchemaElementDecl*)elemDecl));
1277                        wasAdded = true;
1278                }
1279        }
1280
1281        // this info needed for DOMTypeInfo
1282        fPSVIElemContext.fErrorOccurred = false;
1283
1284        //  We do something different here according to whether we found the
1285        //  element or not.
1286        bool bXsiTypeSet= (fValidator)?((SchemaValidator*)fValidator)->getIsXsiTypeSet():false;
1287        if (wasAdded)
1288        {
1289                if (laxValidation && !bXsiTypeSet) {
1290                        fValidate = false;
1291                        fElemStack.setValidationFlag(fValidate);
1292                }
1293
1294                // If validating then emit an error
1295                if (fValidate)
1296                {
1297                        // This is to tell the reuse Validator that this element was
1298                        // faulted-in, was not an element in the grammar pool originally
1299                        elemDecl->setCreateReason(XMLElementDecl::JustFaultIn);
1300
1301                        if(!bXsiTypeSet)
1302                        {
1303                                fValidator->emitError
1304                                (
1305                                        XMLValid::ElementNotDefined
1306                                        , elemDecl->getFullName()
1307                                );
1308                                fPSVIElemContext.fErrorOccurred = true;
1309                        }
1310                }
1311        }
1312        else
1313        {
1314                // If its not marked declared and validating, then emit an error
1315                if (!elemDecl->isDeclared()) {
1316                        if(elemDecl->getCreateReason() == XMLElementDecl::NoReason) {
1317                                if(!bXsiTypeSet)
1318                                        fPSVIElemContext.fErrorOccurred = true;
1319                        }
1320                        if (laxValidation) {
1321                                fValidate = false;
1322                                fElemStack.setValidationFlag(fValidate);
1323                        }
1324
1325                        if (fValidate && !bXsiTypeSet)
1326                        {
1327                                fValidator->emitError
1328                                (
1329                                        XMLValid::ElementNotDefined
1330                                        , elemDecl->getFullName()
1331                                );
1332                        }
1333                }
1334        }
1335
1336
1337        //  Now we can update the element stack to set the current element
1338        //  decl. We expanded the stack above, but couldn't store the element
1339        //  decl because we didn't know it yet.
1340        fElemStack.setElement(elemDecl, fReaderMgr.getCurrentReaderNum());
1341        fElemStack.setCurrentURI(uriId);
1342
1343        if (isRoot)
1344        {
1345                fRootGrammar = fGrammar;
1346                fRootElemName = XMLString::replicate(qnameRawBuf, fMemoryManager);
1347        }
1348
1349        if (fPSVIHandler)
1350        {
1351                fPSVIElemContext.fElemDepth++;
1352
1353                if (elemDecl->isDeclared())
1354                {
1355                        fPSVIElemContext.fNoneValidationDepth = fPSVIElemContext.fElemDepth;
1356                }
1357                else
1358                {
1359                        fPSVIElemContext.fFullValidationDepth = fPSVIElemContext.fElemDepth;
1360
1361                        /******
1362                         * While we report an error for historical reasons, this should
1363                         * actually result in lax assessment - NG.
1364                        if (isRoot && fValidate)
1365                                fPSVIElemContext.fErrorOccurred = true;
1366                        ******/
1367                }
1368        }
1369
1370        //  Validate the element
1371        if (fValidate)
1372        {
1373                fValidator->validateElement(elemDecl);
1374                if (((SchemaValidator*) fValidator)->getErrorOccurred())
1375                        fPSVIElemContext.fErrorOccurred = true;
1376        }
1377
1378        // squirrel away the element's QName, so that we can do an efficient
1379        // end-tag match
1380        fElemStack.setCurrentSchemaElemName(fQNameBuf.getRawBuffer());
1381
1382        ComplexTypeInfo* typeinfo = (fValidate)
1383                ? ((SchemaValidator*)fValidator)->getCurrentTypeInfo()
1384                : ((SchemaElementDecl*) elemDecl)->getComplexTypeInfo();
1385
1386        if (typeinfo) {
1387                currentScope = typeinfo->getScopeDefined();
1388
1389                // switch grammar if the typeinfo has a different grammar (happens when there is xsi:type)
1390                XMLCh* typeName = typeinfo->getTypeName();
1391                const int comma = XMLString::indexOf(typeName, chComma);
1392                if (comma > 0) {
1393                        XMLBuffer prefixBuf(comma+1, fMemoryManager);
1394                        prefixBuf.append(typeName, comma);
1395                        const XMLCh* uriStr = prefixBuf.getRawBuffer();
1396
1397                        bool errorCondition = !switchGrammar(uriStr) && fValidate;
1398                        if (errorCondition && !laxValidation)
1399                        {
1400                                fValidator->emitError
1401                                (
1402                                        XMLValid::GrammarNotFound
1403                                        , prefixBuf.getRawBuffer()
1404                                );
1405                        }
1406                }
1407                else if (comma == 0) {
1408                        bool errorCondition = !switchGrammar(XMLUni::fgZeroLenString) && fValidate;
1409                        if (errorCondition && !laxValidation)
1410                        {
1411                                fValidator->emitError
1412                                (
1413                                        XMLValid::GrammarNotFound
1414                                        , XMLUni::fgZeroLenString
1415                                );
1416                        }
1417                }
1418        }
1419        fElemStack.setCurrentScope(currentScope);
1420
1421        // Set element next state
1422        if (elemDepth >= fElemStateSize) {
1423                resizeElemState();
1424        }
1425
1426        fElemState[elemDepth] = 0;
1427        fElemLoopState[elemDepth] = 0;
1428        fElemStack.setCurrentGrammar(fGrammar);
1429
1430        //  If this is the first element and we are validating, check the root
1431        //  element.
1432        if (!isRoot && parentValidation)
1433        {
1434                //  If the element stack is not empty, then add this element as a
1435                //  child of the previous top element. If its empty, this is the root
1436                //  elem and is not the child of anything.
1437                fElemStack.addChild(elemDecl->getElementName(), true);
1438        }
1439
1440        // PSVI handling:  must reset this, even if no attributes...
1441        if(getPSVIHandler())
1442                fPSVIAttrList->reset();
1443
1444        //  Now lets get the fAttrList filled in. This involves faulting in any
1445        //  defaulted and fixed attributes and normalizing the values of any that
1446        //  we got explicitly.
1447        //
1448        //  We update the attCount value with the total number of attributes, but
1449        //  it goes in with the number of values we got during the raw scan of
1450        //  explictly provided attrs above.
1451        attCount = buildAttList(*fRawAttrList, attCount, elemDecl, fAttrList);
1452
1453        if(attCount)
1454        {
1455                // clean up after ourselves:
1456                // clear the map used to detect duplicate attributes
1457                fUndeclaredAttrRegistry->removeAll();
1458        }
1459
1460        // activate identity constraints
1461        if (toCheckIdentityConstraint())
1462        {
1463                fICHandler->activateIdentityConstraint
1464                                                (
1465                                                  (SchemaElementDecl*) elemDecl
1466                                                , (int) elemDepth
1467                                                , uriId
1468                                                , fPrefixBuf.getRawBuffer()
1469                                                , fAttrList
1470                                                , attCount
1471                                                , fValidationContext
1472                                                );
1473
1474        }
1475
1476        // Since the element may have default values, call start tag now regardless if it is empty or not
1477        // If we have a document handler, then tell it about this start tag
1478        if (fDocHandler)
1479        {
1480                fDocHandler->startElement
1481                (
1482                        *elemDecl
1483                        , uriId
1484                        , fPrefixBuf.getRawBuffer()
1485                        , fAttrList
1486                        , attCount
1487                        , false
1488                        , isRoot
1489                );
1490        } // may be where we output something...
1491
1492        // if we have a PSVIHandler, now's the time to call
1493        // its handleAttributesPSVI method:
1494        if(fPSVIHandler)
1495        {
1496                QName *eName = elemDecl->getElementName();
1497                fPSVIHandler->handleAttributesPSVI
1498                (
1499                        eName->getLocalPart()
1500                        #ifdef TEST_NAMESPACE_RESOLVER
1501                        , (*fUriResolver)[eName->getURI()]
1502                        #else
1503                        , fURIStringPool->getValueForId(eName->getURI())
1504                        #endif
1505                        , fPSVIAttrList
1506                );
1507        }
1508
1509        //  If empty, validate content right now if we are validating and then
1510        //  pop the element stack top. Else, we have to update the current stack
1511        //  top's namespace mapping elements.
1512        if (isEmpty)
1513        {
1514                // Pop the element stack back off since it'll never be used now
1515                fElemStack.popTop();
1516
1517                // reset current type info
1518                DatatypeValidator* psviMemberType = 0;
1519                if (fGrammarType == Grammar::SchemaGrammarType)
1520                {
1521                        if (fValidate && elemDecl->isDeclared())
1522                        {
1523                                fPSVIElemContext.fCurrentTypeInfo = ((SchemaValidator*) fValidator)->getCurrentTypeInfo();
1524                                if(!fPSVIElemContext.fCurrentTypeInfo)
1525                                        fPSVIElemContext.fCurrentDV = ((SchemaValidator*) fValidator)->getCurrentDatatypeValidator();
1526                                else
1527                                        fPSVIElemContext.fCurrentDV = 0;
1528                                if(fPSVIHandler)
1529                                {
1530                                        fPSVIElemContext.fNormalizedValue = ((SchemaValidator*) fValidator)->getNormalizedValue();
1531
1532                                        if (XMLString::equals(fPSVIElemContext.fNormalizedValue, XMLUni::fgZeroLenString))
1533                                                fPSVIElemContext.fNormalizedValue = 0;
1534                                }
1535                        }
1536                        else
1537                        {
1538                                fPSVIElemContext.fCurrentDV = 0;
1539                                fPSVIElemContext.fCurrentTypeInfo = 0;
1540                                fPSVIElemContext.fNormalizedValue = 0;
1541                        }
1542                }
1543
1544                // If validating, then insure that its legal to have no content
1545                if (fValidate)
1546                {
1547                        XMLSize_t failure;
1548                        bool res = fValidator->checkContent(elemDecl, 0, 0, &failure);
1549                        if (!res)
1550                        {
1551                                // REVISIT:  in the case of xsi:type, this may
1552                                // return the wrong string...
1553                                fValidator->emitError
1554                                (
1555                                        XMLValid::ElementNotValidForContent
1556                                        , elemDecl->getFullName()
1557                                        , elemDecl->getFormattedContentModel()
1558                                );
1559                        }
1560
1561                        if (((SchemaValidator*) fValidator)->getErrorOccurred())
1562                                fPSVIElemContext.fErrorOccurred = true;
1563                        // note that if we're empty, won't be a current DV
1564                        else
1565                        {
1566                                if (fPSVIHandler)
1567                                {
1568                                        fPSVIElemContext.fIsSpecified = ((SchemaValidator*) fValidator)->getIsElemSpecified();
1569                                        if(fPSVIElemContext.fIsSpecified)
1570                                                fPSVIElemContext.fNormalizedValue = ((SchemaElementDecl *)elemDecl)->getDefaultValue();
1571                                }
1572                                if (fPSVIElemContext.fCurrentDV && fPSVIElemContext.fCurrentDV->getType() == DatatypeValidator::Union)
1573                                        psviMemberType = fValidationContext->getValidatingMemberType();
1574                        }
1575
1576                        // call matchers and de-activate context
1577                        if (toCheckIdentityConstraint())
1578                        {
1579                                fICHandler->deactivateContext
1580                                           (
1581                                                (SchemaElementDecl *) elemDecl
1582                                          , fContent.getRawBuffer()
1583                                          , fValidationContext
1584                                          , fPSVIElemContext.fCurrentDV
1585                                           );
1586                        }
1587
1588                }
1589                else if (fGrammarType == Grammar::SchemaGrammarType) {
1590                        ((SchemaValidator*)fValidator)->resetNillable();
1591                }
1592
1593                if (fPSVIHandler)
1594                {
1595                        endElementPSVI
1596                        (
1597                                (SchemaElementDecl*)elemDecl, psviMemberType
1598                        );
1599                }
1600
1601                // If we have a doc handler, tell it about the end tag
1602                if (fDocHandler)
1603                {
1604                        fDocHandler->endElement
1605                        (
1606                                *elemDecl
1607                                , uriId
1608                                , isRoot
1609                                , fPrefixBuf.getRawBuffer()
1610                        );
1611                }
1612
1613                // If the elem stack is empty, then it was an empty root
1614                if (isRoot)
1615                        gotData = false;
1616                else
1617                {
1618                        // Restore the grammar
1619                        fGrammar = fElemStack.getCurrentGrammar();
1620                        fGrammarType = fGrammar->getGrammarType();
1621                        fValidator->setGrammar(fGrammar);
1622
1623                        // Restore the validation flag
1624                        fValidate = fElemStack.getValidationFlag();
1625                }
1626        }
1627        else    // not empty
1628        {
1629
1630                // send a partial element psvi
1631                if (fPSVIHandler)
1632                {
1633
1634                        ComplexTypeInfo*   curTypeInfo = 0;
1635                        DatatypeValidator* curDV = 0;
1636                        XSTypeDefinition*  typeDef = 0;
1637
1638                        if (fValidate && elemDecl->isDeclared())
1639                        {
1640                                curTypeInfo = ((SchemaValidator*) fValidator)->getCurrentTypeInfo();
1641
1642                                if (curTypeInfo)
1643                                {
1644                                        typeDef = (XSTypeDefinition*) fModel->getXSObject(curTypeInfo);
1645                                }
1646                                else
1647                                {
1648                                        curDV = ((SchemaValidator*) fValidator)->getCurrentDatatypeValidator();
1649
1650                                        if (curDV)
1651                                        {
1652                                                typeDef = (XSTypeDefinition*) fModel->getXSObject(curDV);
1653                                        }
1654                                }
1655                        }
1656
1657                        fPSVIElement->reset
1658                                (
1659                                  PSVIElement::VALIDITY_NOTKNOWN
1660                                , PSVIElement::VALIDATION_NONE
1661                                , fRootElemName
1662                                , ((SchemaValidator*) fValidator)->getIsElemSpecified()
1663                                , (elemDecl->isDeclared()) ? (XSElementDeclaration*) fModel->getXSObject(elemDecl) : 0
1664                                , typeDef
1665                                , 0 //memberType
1666                                , fModel
1667                                , ((SchemaElementDecl*)elemDecl)->getDefaultValue()
1668                                , 0
1669                                , 0
1670                                , 0
1671                                );
1672
1673
1674                        fPSVIHandler->handlePartialElementPSVI
1675                        (
1676                                elemDecl->getBaseName()
1677                                #ifdef TEST_NAMESPACE_RESOLVER
1678                                , (*fUriResolver)[elemDecl->getURI()]
1679                                #else
1680                                , fURIStringPool->getValueForId(elemDecl->getURI())
1681                                #endif
1682                                , fPSVIElement
1683                        );
1684
1685                }
1686
1687                fErrorStack->push(fPSVIElemContext.fErrorOccurred);
1688        }
1689#endif
1690        return true;
1691#endif
1692}
1693
1694// --------------------------------------------------------------------------------------------------------
1695
1696//  This method is called from scanStartTag() to handle the very raw initial
1697//  scan of the attributes. It just fills in the passed collection with
1698//  key/value pairs for each attribute. No processing is done on them at all.
1699XMLSize_t
1700SGXMLScanner::rawAttrScan(const   XMLCh* const                elemName
1701                                                  ,       RefVectorOf<KVStringPair>&  toFill
1702                                                  ,       bool&                       isEmpty)
1703{
1704#ifdef SGXML_SCANNER_DEPRECATED
1705        DEPRECATED_FEATURE_IN_ICXML;
1706#else
1707
1708// NOTE: all of the code within this function should be ignored in the Parabix version;
1709// it constructs name/value pairs (in the to fill buffer) and takes into account the namespace issues.
1710// this functionality is ignored and instead the final name value pair is constructed and validated.
1711
1712#ifndef EXCLUDE_TRADITIONAL_XERCES_FUNCTIONS_AND_VARIABLES
1713        //  Keep up with how many attributes we've seen so far, and how many
1714        //  elements are available in the vector. This way we can reuse old
1715        //  elements until we run out and then expand it.
1716        XMLSize_t attCount = 0;
1717        XMLSize_t curVecSize = toFill.size();
1718
1719        // Assume it is not empty
1720        isEmpty = false;
1721
1722        //  We loop until we either see a /> or >, handling key/value pairs util
1723        //  we get there. We place them in the passed vector, which we will expand
1724        //  as required to hold them.
1725        while (true)
1726        {
1727                // Get the next character, which should be non-space
1728                XMLCh nextCh = fReaderMgr.peekNextChar();
1729
1730                //  If the next character is not a slash or closed angle bracket,
1731                //  then it must be whitespace, since whitespace is required
1732                //  between the end of the last attribute and the name of the next
1733                //  one.
1734                //
1735                if (attCount)
1736                {
1737                        if ((nextCh != chForwardSlash) && (nextCh != chCloseAngle))
1738                        {
1739                                if (fReaderMgr.getCurrentReader()->isWhitespace(nextCh))
1740                                {
1741                                        // Ok, skip by them and get another char
1742                                        fReaderMgr.getNextChar();
1743                                        fReaderMgr.skipPastSpaces();
1744                                        nextCh = fReaderMgr.peekNextChar();
1745                                }
1746                                else
1747                                {
1748                                        // Emit the error but keep on going
1749                                        emitError(XMLErrs::ExpectedWhitespace);
1750                                }
1751                        }
1752                }
1753
1754                //  Ok, here we first check for any of the special case characters.
1755                //  If its not one, then we do the normal case processing, which
1756                //  assumes that we've hit an attribute value, Otherwise, we do all
1757                //  the special case checks.
1758                if (!fReaderMgr.getCurrentReader()->isSpecialStartTagChar(nextCh))
1759                {
1760                        //  Assume its going to be an attribute, so get a name from
1761                        //  the input.
1762                        int colonPosition;
1763                        if (!fReaderMgr.getQName(fAttNameBuf, &colonPosition))
1764                        {
1765                                if (fAttNameBuf.isEmpty())
1766                                        emitError(XMLErrs::ExpectedAttrName);
1767                                else
1768                                        emitError(XMLErrs::InvalidAttrName, fAttNameBuf.getRawBuffer());
1769                                fReaderMgr.skipPastChar(chCloseAngle);
1770                                return attCount;
1771                        }
1772
1773                        const XMLCh* curAttNameBuf = fAttNameBuf.getRawBuffer();
1774
1775                        // And next must be an equal sign
1776                        if (!scanEq())
1777                        {
1778                                static const XMLCh tmpList[] =
1779                                {
1780                                        chSingleQuote, chDoubleQuote, chCloseAngle
1781                                        , chOpenAngle, chForwardSlash, chNull
1782                                };
1783
1784                                emitError(XMLErrs::ExpectedEqSign);
1785
1786                                //  Try to sync back up by skipping forward until we either
1787                                //  hit something meaningful.
1788                                const XMLCh chFound = fReaderMgr.skipUntilInOrWS(tmpList);
1789
1790                                if ((chFound == chCloseAngle) || (chFound == chForwardSlash))
1791                                {
1792                                        // Jump back to top for normal processing of these
1793                                        continue;
1794                                }
1795                                else if ((chFound == chSingleQuote)
1796                                          ||  (chFound == chDoubleQuote)
1797                                          ||  fReaderMgr.getCurrentReader()->isWhitespace(chFound))
1798                                {
1799                                        // Just fall through assuming that the value is to follow
1800                                }
1801                                else if (chFound == chOpenAngle)
1802                                {
1803                                        // Assume a malformed tag and that new one is starting
1804                                        emitError(XMLErrs::UnterminatedStartTag, elemName);
1805                                        return attCount;
1806                                }
1807                                else
1808                                {
1809                                        // Something went really wrong
1810                                        return attCount;
1811                                }
1812                        }
1813
1814                        //  Next should be the quoted attribute value. We just do a simple
1815                        //  and stupid scan of this value. The only thing we do here
1816                        //  is to expand entity references.
1817                        if (!basicAttrValueScan(curAttNameBuf, fAttValueBuf))
1818                        {
1819                                static const XMLCh tmpList[] =
1820                                {
1821                                        chCloseAngle, chOpenAngle, chForwardSlash, chNull
1822                                };
1823
1824                                emitError(XMLErrs::ExpectedAttrValue);
1825
1826                                //  It failed, so lets try to get synced back up. We skip
1827                                //  forward until we find some whitespace or one of the
1828                                //  chars in our list.
1829                                const XMLCh chFound = fReaderMgr.skipUntilInOrWS(tmpList);
1830
1831                                if ((chFound == chCloseAngle)
1832                                ||  (chFound == chForwardSlash)
1833                                ||  fReaderMgr.getCurrentReader()->isWhitespace(chFound))
1834                                {
1835                                        //  Just fall through and process this attribute, though
1836                                        //  the value will be "".
1837                                }
1838                                else if (chFound == chOpenAngle)
1839                                {
1840                                        // Assume a malformed tag and that new one is starting
1841                                        emitError(XMLErrs::UnterminatedStartTag, elemName);
1842                                        return attCount;
1843                                }
1844                                else
1845                                {
1846                                        // Something went really wrong
1847                                        return attCount;
1848                                }
1849                        }
1850
1851                        //  And now lets add it to the passed collection. If we have not
1852                        //  filled it up yet, then we use the next element. Else we add
1853                        //  a new one.
1854                        KVStringPair* curPair = 0;
1855                        if (attCount >= curVecSize)
1856                        {
1857                                curPair = new (fMemoryManager) KVStringPair
1858                                (
1859                                        curAttNameBuf
1860                                        , fAttNameBuf.getLen()
1861                                        , fAttValueBuf.getRawBuffer()
1862                                        , fAttValueBuf.getLen()
1863                                        , fMemoryManager
1864                                );
1865                                toFill.addElement(curPair);
1866                        }
1867                         else
1868                        {
1869                                curPair = toFill.elementAt(attCount);
1870                                curPair->set
1871                                (
1872                                        curAttNameBuf
1873                                        , fAttNameBuf.getLen()
1874                                        , fAttValueBuf.getRawBuffer()
1875                                        , fAttValueBuf.getLen()
1876                                );
1877                        }
1878                        if (attCount >= fRawAttrColonListSize) {
1879                                resizeRawAttrColonList();
1880                        }
1881                        fRawAttrColonList[attCount] = colonPosition;
1882
1883                        // And bump the count of attributes we've gotten
1884                        attCount++;
1885
1886                        // And go to the top again for another attribute
1887                        continue;
1888                }
1889
1890                //  It was some special case character so do all of the checks and
1891                //  deal with it.
1892                if (!nextCh)
1893                        ThrowXMLwithMemMgr(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF, fMemoryManager);
1894
1895                if (nextCh == chForwardSlash)
1896                {
1897                        fReaderMgr.getNextChar();
1898                        isEmpty = true;
1899                        if (!fReaderMgr.skippedChar(chCloseAngle))
1900                                emitError(XMLErrs::UnterminatedStartTag, elemName);
1901                        break;
1902                }
1903                else if (nextCh == chCloseAngle)
1904                {
1905                        fReaderMgr.getNextChar();
1906                        break;
1907                }
1908                else if (nextCh == chOpenAngle)
1909                {
1910                        //  Check for this one specially, since its going to be common
1911                        //  and it is kind of auto-recovering since we've already hit the
1912                        //  next open bracket, which is what we would have seeked to (and
1913                        //  skipped this whole tag.)
1914                        emitError(XMLErrs::UnterminatedStartTag, elemName);
1915                        break;
1916                }
1917                else if ((nextCh == chSingleQuote) || (nextCh == chDoubleQuote))
1918                {
1919                        //  Check for this one specially, which is probably a missing
1920                        //  attribute name, e.g. ="value". Just issue expected name
1921                        //  error and eat the quoted string, then jump back to the
1922                        //  top again.
1923                        emitError(XMLErrs::ExpectedAttrName);
1924                        fReaderMgr.getNextChar();
1925                        fReaderMgr.skipQuotedString(nextCh);
1926                        fReaderMgr.skipPastSpaces();
1927                        continue;
1928                }
1929        }
1930
1931        return attCount;
1932#else
1933        return 0;
1934#endif
1935#endif
1936}
1937
1938// ---------------------------------------------------------------------------
1939//  SGXMLScanner: Grammar preparsing
1940// ---------------------------------------------------------------------------
1941Grammar* SGXMLScanner::loadGrammar(const   InputSource& src
1942                                                                   , const short        grammarType
1943                                                                   , const bool         toCache)
1944{
1945#ifdef SGXML_SCANNER_DEPRECATED
1946        DEPRECATED_FEATURE_IN_ICXML;
1947#else
1948        Grammar* loadedGrammar = 0;
1949
1950        ReaderMgrResetType  resetReaderMgr(&fReaderMgr, &ReaderMgr::reset);
1951
1952        try
1953        {
1954                fGrammarResolver->cacheGrammarFromParse(false);
1955                                // if the new grammar has to be cached, better use the already cached
1956                                // grammars, or the an exception will be thrown when caching an already
1957                                // cached grammar
1958                fGrammarResolver->useCachedGrammarInParse(toCache);
1959                fRootGrammar = 0;
1960
1961                if (fValScheme == Val_Auto) {
1962                        fValidate = true;
1963                }
1964
1965                // Reset some status flags
1966                fInException = false;
1967                fStandalone = false;
1968                fErrorCount = 0;
1969                fHasNoDTD = true;
1970                fSeeXsi = false;
1971
1972                if (grammarType == Grammar::SchemaGrammarType) {
1973                        loadedGrammar = loadXMLSchemaGrammar(src, toCache);
1974                }
1975        }
1976        //  NOTE:
1977        //
1978        //  In all of the error processing below, the emitError() call MUST come
1979        //  before the flush of the reader mgr, or it will fail because it tries
1980        //  to find out the position in the XML source of the error.
1981        catch(const XMLErrs::Codes)
1982        {
1983                // This is a 'first failure' exception, so fall through
1984        }
1985        catch(const XMLValid::Codes)
1986        {
1987                // This is a 'first fatal error' type exit, so fall through
1988        }
1989        catch(const XMLException& excToCatch)
1990        {
1991                //  Emit the error and catch any user exception thrown from here. Make
1992                //  sure in all cases we flush the reader manager.
1993                fInException = true;
1994                try
1995                {
1996                        if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning)
1997                                emitError
1998                                (
1999                                        XMLErrs::XMLException_Warning
2000                                        , excToCatch.getCode()
2001                                        , excToCatch.getMessage()
2002                                );
2003                        else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal)
2004                                emitError
2005                                (
2006                                        XMLErrs::XMLException_Fatal
2007                                        , excToCatch.getCode()
2008                                        , excToCatch.getMessage()
2009                                );
2010                        else
2011                                emitError
2012                                (
2013                                        XMLErrs::XMLException_Error
2014                                        , excToCatch.getCode()
2015                                        , excToCatch.getMessage()
2016                                );
2017                }
2018                catch(const OutOfMemoryException&)
2019                {
2020                        // This is a special case for out-of-memory
2021                        // conditions, because resetting the ReaderMgr
2022                        // can be problematic.
2023                        resetReaderMgr.release();
2024
2025                        throw;
2026                }
2027        }
2028        catch(const OutOfMemoryException&)
2029        {
2030                // This is a special case for out-of-memory
2031                // conditions, because resetting the ReaderMgr
2032                // can be problematic.
2033                resetReaderMgr.release();
2034
2035                throw;
2036        }
2037
2038        return loadedGrammar;
2039#endif
2040}
2041
2042void SGXMLScanner::resetCachedGrammar ()
2043{
2044#ifdef SGXML_SCANNER_DEPRECATED
2045        DEPRECATED_FEATURE_IN_ICXML;
2046#else
2047        fCachedSchemaInfoList->removeAll ();
2048#endif
2049}
2050
2051// ---------------------------------------------------------------------------
2052//  SGXMLScanner: Private helper methods
2053// ---------------------------------------------------------------------------
2054//  This method handles the common initialization, to avoid having to do
2055//  it redundantly in multiple constructors.
2056void SGXMLScanner::commonInit()
2057{
2058#ifdef SGXML_SCANNER_DEPRECATED
2059        DEPRECATED_FEATURE_IN_ICXML;
2060#else
2061        //  Create the element state array
2062        fElemState = (unsigned int*) fMemoryManager->allocate
2063        (
2064                fElemStateSize * sizeof(unsigned int)
2065        ); //new unsigned int[fElemStateSize];
2066        fElemLoopState = (unsigned int*) fMemoryManager->allocate
2067        (
2068                fElemStateSize * sizeof(unsigned int)
2069        ); //new unsigned int[fElemStateSize];
2070
2071        //  And we need one for the raw attribute scan. This just stores key/
2072        //  value string pairs (prior to any processing.)
2073        fRawAttrList = new (fMemoryManager) RefVectorOf<KVStringPair>(32, true, fMemoryManager);
2074        fRawAttrColonList = (int*) fMemoryManager->allocate
2075        (
2076                fRawAttrColonListSize * sizeof(int)
2077        );
2078
2079        //  Create the Validator and init them
2080        fSchemaValidator = new (fMemoryManager) SchemaValidator(0, fMemoryManager);
2081        initValidator(fSchemaValidator);
2082
2083        // Create IdentityConstraint info
2084        fICHandler = new (fMemoryManager) IdentityConstraintHandler(this, fMemoryManager);
2085
2086        //  Add the default entity entries for the character refs that must always
2087        //  be present.
2088        fEntityTable = new (fMemoryManager) ValueHashTableOf<XMLCh>(11, fMemoryManager);
2089        fEntityTable->put((void*) XMLUni::fgAmp, chAmpersand);
2090        fEntityTable->put((void*) XMLUni::fgLT, chOpenAngle);
2091        fEntityTable->put((void*) XMLUni::fgGT, chCloseAngle);
2092        fEntityTable->put((void*) XMLUni::fgQuot, chDoubleQuote);
2093        fEntityTable->put((void*) XMLUni::fgApos, chSingleQuote);
2094        fElemNonDeclPool = new (fMemoryManager) RefHash3KeysIdPool<SchemaElementDecl>(29, true, 128, fMemoryManager);
2095        fAttDefRegistry = new (fMemoryManager) RefHashTableOf<unsigned int, PtrHasher>
2096        (
2097                131, false, fMemoryManager
2098        );
2099        fUndeclaredAttrRegistry = new (fMemoryManager) Hash2KeysSetOf<StringHasher>(7, fMemoryManager);
2100        fPSVIAttrList = new (fMemoryManager) PSVIAttributeList(fMemoryManager);
2101
2102        fSchemaInfoList = new (fMemoryManager) RefHash2KeysTableOf<SchemaInfo>(29, fMemoryManager);
2103        fCachedSchemaInfoList = new (fMemoryManager) RefHash2KeysTableOf<SchemaInfo>(29, fMemoryManager);
2104
2105        if (fValidator)
2106        {
2107                if (!fValidator->handlesSchema())
2108                        ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoSchemaValidator, fMemoryManager);
2109        }
2110        else
2111        {
2112                fValidator = fSchemaValidator;
2113        }
2114#endif
2115}
2116
2117void SGXMLScanner::cleanUp()
2118{
2119#ifdef SGXML_SCANNER_DEPRECATED
2120        DEPRECATED_FEATURE_IN_ICXML;
2121#else
2122        fMemoryManager->deallocate(fElemState); //delete [] fElemState;
2123        fMemoryManager->deallocate(fElemLoopState); //delete [] fElemLoopState;
2124        delete fSchemaGrammar;
2125        delete fEntityTable;
2126        delete fRawAttrList;
2127        fMemoryManager->deallocate(fRawAttrColonList);
2128        delete fSchemaValidator;
2129        delete fICHandler;
2130        delete fElemNonDeclPool;
2131        delete fAttDefRegistry;
2132        delete fUndeclaredAttrRegistry;
2133        delete fPSVIAttrList;
2134        if (fPSVIElement)
2135                delete fPSVIElement;
2136
2137        if (fErrorStack)
2138                delete fErrorStack;
2139
2140        delete fSchemaInfoList;
2141        delete fCachedSchemaInfoList;
2142#endif
2143}
2144
2145void SGXMLScanner::resizeElemState()
2146{
2147#ifdef SGXML_SCANNER_DEPRECATED
2148        DEPRECATED_FEATURE_IN_ICXML;
2149#else
2150        unsigned int newSize = fElemStateSize * 2;
2151        unsigned int* newElemState = (unsigned int*) fMemoryManager->allocate
2152        (
2153                newSize * sizeof(unsigned int)
2154        ); //new unsigned int[newSize];
2155        unsigned int* newElemLoopState = (unsigned int*) fMemoryManager->allocate
2156        (
2157                newSize * sizeof(unsigned int)
2158        ); //new unsigned int[newSize];
2159
2160        // Copy the existing values
2161        unsigned int index = 0;
2162        for (; index < fElemStateSize; index++)
2163        {
2164                newElemState[index] = fElemState[index];
2165                newElemLoopState[index] = fElemLoopState[index];
2166        }
2167
2168        for (; index < newSize; index++)
2169                newElemLoopState[index] = newElemState[index] = 0;
2170
2171        // Delete the old array and udpate our members
2172        fMemoryManager->deallocate(fElemState); //delete [] fElemState;
2173        fMemoryManager->deallocate(fElemLoopState); //delete [] fElemLoopState;
2174        fElemState = newElemState;
2175        fElemLoopState = newElemLoopState;
2176        fElemStateSize = newSize;
2177#endif
2178}
2179
2180void SGXMLScanner::resizeRawAttrColonList()
2181{
2182#ifdef SGXML_SCANNER_DEPRECATED
2183        DEPRECATED_FEATURE_IN_ICXML;
2184#else
2185        unsigned int newSize = fRawAttrColonListSize * 2;
2186        int* newRawAttrColonList = (int*) fMemoryManager->allocate
2187        (
2188                newSize * sizeof(int)
2189        ); //new int[newSize];
2190
2191        // Copy the existing values
2192        unsigned int index = 0;
2193        for (; index < fRawAttrColonListSize; index++)
2194                newRawAttrColonList[index] = fRawAttrColonList[index];
2195
2196        // Delete the old array and udpate our members
2197        fMemoryManager->deallocate(fRawAttrColonList); //delete [] fRawAttrColonList;
2198        fRawAttrColonList = newRawAttrColonList;
2199        fRawAttrColonListSize = newSize;
2200#endif
2201}
2202
2203//  This method is called from scanStartTag() to build up the list of
2204//  XMLAttr objects that will be passed out in the start tag callout. We
2205//  get the key/value pairs from the raw scan of explicitly provided attrs,
2206//  which have not been normalized. And we get the element declaration from
2207//  which we will get any defaulted or fixed attribute defs and add those
2208//  in as well.
2209XMLSize_t
2210SGXMLScanner::buildAttList(const  RefVectorOf<KVStringPair>&  providedAttrs
2211                                                  , const XMLSize_t                   attCount
2212                                                  ,       XMLElementDecl*             elemDecl
2213                                                  ,       RefVectorOf<XMLAttr>&       toFill)
2214{
2215#ifdef SGXML_SCANNER_DEPRECATED
2216        DEPRECATED_FEATURE_IN_ICXML;
2217#else
2218        //  Ask the element to clear the 'provided' flag on all of the att defs
2219        //  that it owns, and to return us a boolean indicating whether it has
2220        //  any defs.
2221        DatatypeValidator *currDV = 0;
2222        ComplexTypeInfo *currType = 0;
2223
2224        if (fValidate)
2225        {
2226                currType = ((SchemaValidator*)fValidator)->getCurrentTypeInfo();
2227                if (!currType) {
2228                        currDV = ((SchemaValidator*)fValidator)->getCurrentDatatypeValidator();
2229                }
2230        }
2231
2232        const bool hasDefs = (currType && fValidate)
2233                        ? currType->hasAttDefs()
2234                        : elemDecl->hasAttDefs();
2235
2236        fElemCount++;
2237
2238        //  If there are no expliclitily provided attributes and there are no
2239        //  defined attributes for the element, the we don't have anything to do.
2240        //  So just return zero in this case.
2241        if (!hasDefs && !attCount)
2242                return 0;
2243
2244        // Keep up with how many attrs we end up with total
2245        XMLSize_t retCount = 0;
2246
2247        //  And get the current size of the output vector. This lets us use
2248        //  existing elements until we fill it, then start adding new ones.
2249        const XMLSize_t curAttListSize = toFill.size();
2250
2251        //  We need a buffer into which raw scanned attribute values will be
2252        //  normalized.
2253        XMLBufBid bbNormal(&fBufMgr);
2254        XMLBuffer& normBuf = bbNormal.getBuffer();
2255
2256        XMLBufBid bbPrefix(&fBufMgr);
2257        XMLBuffer& prefixBuf = bbPrefix.getBuffer();
2258
2259        //  Loop through our explicitly provided attributes, which are in the raw
2260        //  scanned form, and build up XMLAttr objects.
2261        XMLSize_t index;
2262        const XMLCh* prefPtr, *suffPtr;
2263        for (index = 0; index < attCount; index++)
2264        {
2265                PSVIItem::VALIDITY_STATE attrValid = PSVIItem::VALIDITY_VALID;
2266                PSVIItem::ASSESSMENT_TYPE attrAssessed = PSVIItem::VALIDATION_FULL;
2267                const KVStringPair* curPair = providedAttrs.elementAt(index);
2268
2269                //  We have to split the name into its prefix and name parts. Then
2270                //  we map the prefix to its URI.
2271                const XMLCh* const namePtr = curPair->getKey();
2272
2273                const int colonInd = fRawAttrColonList[index];
2274                unsigned int uriId;
2275                if (colonInd != -1)
2276                {
2277                        prefixBuf.set(namePtr, colonInd);
2278                        prefPtr = prefixBuf.getRawBuffer();
2279                        suffPtr = namePtr + colonInd + 1;
2280                        //  Map the prefix to a URI id
2281                        uriId = resolvePrefix(prefPtr, ElemStack::Mode_Attribute);
2282                }
2283                else
2284                {
2285                        // No colon, so we just have a name with no prefix
2286                        prefPtr = XMLUni::fgZeroLenString;
2287                        suffPtr = namePtr;
2288                        // an empty prefix is always the empty namespace, when dealing with attributes
2289                        #ifdef TEST_NAMESPACE_RESOLVER
2290                        uriId = XMLNamespaceResolver::fEmptyUriId;
2291                        #else
2292                        uriId = fEmptyNamespaceId;
2293                        #endif
2294                }
2295
2296                //  If the uri comes back as the xmlns or xml URI or its just a name
2297                //  and that name is 'xmlns', then we handle it specially. So set a
2298                //  boolean flag that lets us quickly below know which we are dealing
2299                //  with.
2300                const bool isNSAttr =
2301                        #ifdef TEST_NAMESPACE_RESOLVER
2302                        (uriId == XMLNamespaceResolver::fEmptyUriId)
2303                        ? XMLString::equals(suffPtr, XMLUni::fgXMLNSString)
2304                        : (uriId == XMLNamespaceResolver::fXMLNSUriId || uriId == XMLNamespaceResolver::fSchemaUriId);
2305                        #else
2306                        (uriId == fEmptyNamespaceId)
2307                        ? XMLString::equals(suffPtr, XMLUni::fgXMLNSString)
2308                        : (uriId == fXMLNSNamespaceId || XMLString::equals(getURIText(uriId), SchemaSymbols::fgURI_XSI));
2309                        #endif
2310
2311
2312                //  If its not a special case namespace attr of some sort, then we
2313                //  do normal checking and processing.
2314                XMLAttDef::AttTypes attType = XMLAttDef::CData;
2315                DatatypeValidator *attrValidator = 0;
2316                PSVIAttribute *psviAttr = 0;
2317                bool otherXSI = false;
2318
2319                if (isNSAttr)
2320                {
2321                        if(!fUndeclaredAttrRegistry->putIfNotPresent(suffPtr, uriId))
2322                        {
2323                                emitError
2324                                (
2325                                        XMLErrs::AttrAlreadyUsedInSTag
2326                                        , namePtr
2327                                        , elemDecl->getFullName()
2328                                );
2329                                fPSVIElemContext.fErrorOccurred = true;
2330                        }
2331                        else
2332                        {
2333                                bool ValueValidate = false;
2334                                bool tokenizeBuffer = false;
2335                                #ifdef TEST_NAMESPACE_RESOLVER
2336                                if (uriId == XMLNamespaceResolver::fXMLNSUriId)
2337                                #else
2338                                if (uriId == fXMLNSNamespaceId)
2339                                #endif
2340                                {
2341                                        attrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYURI);
2342                                }
2343                                else if (XMLString::equals(getURIText(uriId), SchemaSymbols::fgURI_XSI))
2344                                {
2345                                        if (XMLString::equals(suffPtr, SchemaSymbols::fgATT_NILL))
2346                                        {
2347                                                attrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_BOOLEAN);
2348
2349                                                ValueValidate = true;
2350                                        }
2351                                        else if (XMLString::equals(suffPtr, SchemaSymbols::fgXSI_SCHEMALOCATION))
2352                                        {
2353                                                // use anyURI as the validator
2354                                                // tokenize the data and use the anyURI data for each piece
2355                                                attrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYURI);
2356                                                //We should validate each value in the schema location however
2357                                                //this lead to a performance degradation of around 4%.  Since
2358                                                //the first value of each pair needs to match what is in the
2359                                                //schema document and the second value needs to be valid in
2360                                                //order to open the document we won't validate it.  Need to
2361                                                //do performance analysis of the anyuri datatype.
2362                                                //ValueValidate = true;
2363                                                ValueValidate = false;
2364                                                tokenizeBuffer = true;
2365                                        }
2366                                        else if (XMLString::equals(suffPtr, SchemaSymbols::fgXSI_NONAMESPACESCHEMALOCATION))
2367                                        {
2368                                                attrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYURI);
2369                                                //We should validate this value however
2370                                                //this lead to a performance degradation of around 4%.  Since
2371                                                //the value needs to be valid in
2372                                                //order to open the document we won't validate it.  Need to
2373                                                //do performance analysis of the anyuri datatype.
2374                                                //ValueValidate = true;
2375                                                ValueValidate = false;
2376                                        }
2377                                        else if (XMLString::equals(suffPtr, SchemaSymbols::fgXSI_TYPE))
2378                                        {
2379                                                attrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_QNAME);
2380
2381                                                ValueValidate = true;
2382                                        }
2383                                        else {
2384                                                otherXSI = true;
2385                                        }
2386                                }
2387
2388                                if (!otherXSI) {
2389                                        normalizeAttRawValue
2390                                        (
2391                                                namePtr
2392                                                , curPair->getValue()
2393                                                , normBuf
2394                                        );
2395
2396                                        if (fValidate && attrValidator && ValueValidate)
2397                                        {
2398                                                ((SchemaValidator*) fValidator)->normalizeWhiteSpace(attrValidator, normBuf.getRawBuffer(), normBuf, true);
2399
2400                                                ValidationContext* const    theContext =
2401                                                        getValidationContext();
2402
2403                                                if (theContext)
2404                                                {
2405                                                        try
2406                                                        {
2407                                                                if (tokenizeBuffer) {
2408                                                                        XMLStringTokenizer tokenizer(normBuf.getRawBuffer(), fMemoryManager);
2409                                                                        while (tokenizer.hasMoreTokens()) {
2410                                                                                attrValidator->validate(
2411                                                                                        tokenizer.nextToken(),
2412                                                                                        theContext,
2413                                                                                        fMemoryManager);
2414                                                                        }
2415                                                                }
2416                                                                else {
2417                                                                        attrValidator->validate(
2418                                                                                normBuf.getRawBuffer(),
2419                                                                                theContext,
2420                                                                                fMemoryManager);
2421                                                                }
2422                                                        }
2423                                                        catch (const XMLException& idve)
2424                                                        {
2425                                                                fValidator->emitError (XMLValid::DatatypeError, idve.getCode(), idve.getMessage());
2426                                                        }
2427                                                }
2428                                        }
2429
2430                                        if(getPSVIHandler() && fGrammarType == Grammar::SchemaGrammarType)
2431                                        {
2432                                                psviAttr = fPSVIAttrList->getPSVIAttributeToFill
2433                                                (
2434                                                        suffPtr
2435                                                        #ifdef TEST_NAMESPACE_RESOLVER
2436                                                        , (*fUriResolver)[elemDecl->getURI()]
2437                                                        #else
2438                                                        , fURIStringPool->getValueForId(elemDecl->getURI())
2439                                                        #endif
2440                                                );
2441                                                XSSimpleTypeDefinition *validatingType =
2442                                                                (attrValidator) ? (XSSimpleTypeDefinition *)fModel->getXSObject(attrValidator) : 0;
2443                                                // no attribute declarations for these...
2444                                                psviAttr->reset
2445                                                (
2446                                                        fRootElemName
2447                                                        , PSVIItem::VALIDITY_NOTKNOWN
2448                                                        , PSVIItem::VALIDATION_NONE
2449                                                        , validatingType
2450                                                        , 0
2451                                                        , 0
2452                                                        , false
2453                                                        , 0
2454                                                        , attrValidator
2455                                                );
2456                                        }
2457                                }
2458                        }
2459                }
2460
2461                if (!isNSAttr || otherXSI)
2462                {
2463                        // Some checking for attribute wild card first (for schema)
2464                        bool laxValidation = false;
2465                        bool skipThisOne = false;
2466
2467                        XMLAttDef* attDefForWildCard = 0;
2468                        XMLAttDef*  attDef = 0;
2469
2470                        if (fGrammarType == Grammar::SchemaGrammarType)
2471                        {
2472                                //retrieve the att def
2473                                SchemaAttDef* attWildCard = 0;
2474                                if (currType)
2475                                {
2476                                        attDef = currType->getAttDef(suffPtr, uriId);
2477                                        attWildCard = currType->getAttWildCard();
2478                                }
2479                                else if (!currDV)
2480                                { // check explicitly-set wildcard
2481                                        attWildCard = ((SchemaElementDecl*)elemDecl)->getAttWildCard();
2482                                }
2483
2484                                // if not found or faulted in - check for a matching wildcard attribute
2485                                // if no matching wildcard attribute, check (un)qualifed cases and flag
2486                                // appropriate errors
2487                                if (!attDef || (attDef->getCreateReason() == XMLAttDef::JustFaultIn))
2488                                {
2489                                        if (attWildCard)
2490                                        {
2491                                                //if schema, see if we should lax or skip the validation of this attribute
2492                                                if (anyAttributeValidation(attWildCard, uriId, skipThisOne, laxValidation))
2493                                                {
2494                                                        if(!skipThisOne)
2495                                                        {
2496                                                                SchemaGrammar* sGrammar = (SchemaGrammar*) fGrammarResolver->getGrammar(getURIText(uriId));
2497                                                                if (sGrammar && sGrammar->getGrammarType() == Grammar::SchemaGrammarType) {
2498                                                                        RefHashTableOf<XMLAttDef>* attRegistry = sGrammar->getAttributeDeclRegistry();
2499                                                                        if (attRegistry) {
2500                                                                                attDefForWildCard = attRegistry->get(suffPtr);
2501                                                                        }
2502                                                                }
2503                                                        }
2504                                                }
2505                                        }
2506                                        else if (currType)
2507                                        {
2508                                                // not found, see if the attDef should be qualified or not
2509                                                #ifdef TEST_NAMESPACE_RESOLVER
2510                                                if (uriId == XMLNamespaceResolver::fEmptyUriId)
2511                                                #else
2512                                                if (uriId == fEmptyNamespaceId)
2513                                                #endif
2514                                                {
2515                                                        attDef = currType->getAttDef
2516                                                        (
2517                                                                suffPtr
2518                                                                #ifdef TEST_NAMESPACE_RESOLVER
2519                                                                , fUriResolver->resolveUriId(fGrammar->getTargetNamespace())
2520                                                                #else
2521                                                                , fURIStringPool->getId(fGrammar->getTargetNamespace())
2522                                                                #endif
2523                                                        );
2524                                                        if (fValidate
2525                                                                && attDef
2526                                                                && attDef->getCreateReason() != XMLAttDef::JustFaultIn) {
2527                                                                // the attribute should be qualified
2528                                                                fValidator->emitError
2529                                                                (
2530                                                                        XMLValid::AttributeNotQualified
2531                                                                        , attDef->getFullName()
2532                                                                );
2533                                                                fPSVIElemContext.fErrorOccurred = true;
2534                                                                if (getPSVIHandler())
2535                                                                {
2536                                                                        attrValid = PSVIItem::VALIDITY_INVALID;
2537                                                                }
2538                                                        }
2539                                                }
2540                                                else
2541                                                {
2542                                                        attDef = currType->getAttDef(suffPtr, fEmptyNamespaceId);
2543                                                        if (fValidate
2544                                                                && attDef
2545                                                                && attDef->getCreateReason() != XMLAttDef::JustFaultIn) {
2546                                                                // the attribute should be qualified
2547                                                                fValidator->emitError
2548                                                                (
2549                                                                        XMLValid::AttributeNotUnQualified
2550                                                                        , attDef->getFullName()
2551                                                                );
2552                                                                fPSVIElemContext.fErrorOccurred = true;
2553                                                                if (getPSVIHandler())
2554                                                                {
2555                                                                        attrValid = PSVIItem::VALIDITY_INVALID;
2556                                                                }
2557                                                        }
2558                                                }
2559                                        }
2560                                }
2561                        }
2562
2563                        // now need to prepare for duplicate detection
2564                        if(attDef)
2565                        {
2566                                unsigned int *curCountPtr = fAttDefRegistry->get(attDef);
2567                                if(!curCountPtr)
2568                                {
2569                                        curCountPtr = getNewUIntPtr();
2570                                        *curCountPtr = fElemCount;
2571                                        fAttDefRegistry->put(attDef, curCountPtr);
2572                                }
2573                                else if(*curCountPtr < fElemCount)
2574                                        *curCountPtr = fElemCount;
2575                                else
2576                                {
2577                                        emitError
2578                                        (
2579                                                XMLErrs::AttrAlreadyUsedInSTag
2580                                                , attDef->getFullName()
2581                                                , elemDecl->getFullName()
2582                                        );
2583                                        fPSVIElemContext.fErrorOccurred = true;
2584                                }
2585                        }
2586                        else
2587                        {
2588                                if(!fUndeclaredAttrRegistry->putIfNotPresent(suffPtr, uriId))
2589                                {
2590                                        emitError
2591                                        (
2592                                                XMLErrs::AttrAlreadyUsedInSTag
2593                                                , namePtr
2594                                                , elemDecl->getFullName()
2595                                        );
2596                                        fPSVIElemContext.fErrorOccurred = true;
2597                                }
2598                        }
2599
2600                        // if we've found either an attDef or an attDefForWildCard,
2601                        // then we're doing full validation and it may still be valid.
2602                        if(!attDef && !attDefForWildCard)
2603                        {
2604                                if(!laxValidation && !skipThisOne)
2605                                {
2606                                        fPSVIElemContext.fErrorOccurred = true;
2607                                }
2608                                if(getPSVIHandler())
2609                                {
2610                                        if(!laxValidation && !skipThisOne)
2611                                        {
2612                                                attrValid = PSVIItem::VALIDITY_INVALID;
2613                                        }
2614                                        else if(laxValidation)
2615                                        {
2616                                                attrValid = PSVIItem::VALIDITY_NOTKNOWN;
2617                                                attrAssessed = PSVIItem::VALIDATION_PARTIAL;
2618                                        }
2619                                        else
2620                                        {
2621                                                attrValid = PSVIItem::VALIDITY_NOTKNOWN;
2622                                                attrAssessed = PSVIItem::VALIDATION_NONE;
2623                                        }
2624                                }
2625                        }
2626
2627                        bool errorCondition = fValidate && !attDefForWildCard && !attDef;
2628                        if (errorCondition && !skipThisOne && !laxValidation)
2629                        {
2630                                //
2631                                //  Its not valid for this element, so issue an error if we are
2632                                //  validating.
2633                                //
2634                                XMLBufBid bbMsg(&fBufMgr);
2635                                XMLBuffer& bufMsg = bbMsg.getBuffer();
2636
2637                                #ifdef TEST_NAMESPACE_RESOLVER
2638                                if (uriId != XMLNamespaceResolver::fEmptyUriId)
2639                                #else
2640                                if (uriId != fEmptyNamespaceId)
2641                                #endif
2642                                {
2643                                        XMLBufBid bbURI(&fBufMgr);
2644                                        XMLBuffer& bufURI = bbURI.getBuffer();
2645
2646                                        getURIText(uriId, bufURI);
2647
2648                                        bufMsg.append(chOpenCurly);
2649                                        bufMsg.append(bufURI.getRawBuffer());
2650                                        bufMsg.append(chCloseCurly);
2651                                }
2652                                bufMsg.append(suffPtr);
2653                                fValidator->emitError
2654                                (
2655                                        XMLValid::AttNotDefinedForElement
2656                                        , bufMsg.getRawBuffer()
2657                                        , elemDecl->getFullName()
2658                                );
2659                        }
2660
2661                        //  Now normalize the raw value since we have the attribute type. We
2662                        //  don't care about the return status here. If it failed, an error
2663                        //  was issued, which is all we care about.
2664                        if (attDefForWildCard) {
2665                                normalizeAttValue(
2666                                        attDefForWildCard, namePtr, curPair->getValue(), normBuf
2667                                );
2668
2669                                //  If we found an attdef for this one, then lets validate it.
2670                                const XMLCh* xsNormalized = normBuf.getRawBuffer();
2671                                DatatypeValidator* tempDV = ((SchemaAttDef*) attDefForWildCard)->getDatatypeValidator();
2672                                if (tempDV && tempDV->getWSFacet() != DatatypeValidator::PRESERVE)
2673                                {
2674                                        // normalize the attribute according to schema whitespace facet
2675                                        ((SchemaValidator*) fValidator)->normalizeWhiteSpace(tempDV, xsNormalized, fWSNormalizeBuf, true);
2676                                        xsNormalized = fWSNormalizeBuf.getRawBuffer();
2677                                        if (fNormalizeData && fValidate) {
2678                                                normBuf.set(xsNormalized);
2679                                        }
2680                                }
2681
2682                                if (fValidate ) {
2683                                        fValidator->validateAttrValue(
2684                                                attDefForWildCard, xsNormalized, false, elemDecl
2685                                        );
2686                                        attrValidator = ((SchemaValidator *)fValidator)->getMostRecentAttrValidator();
2687                                        if(((SchemaValidator *)fValidator)->getErrorOccurred())
2688                                        {
2689                                                fPSVIElemContext.fErrorOccurred = true;
2690                                                if(getPSVIHandler())
2691                                                        attrValid = PSVIItem::VALIDITY_INVALID;
2692                                        }
2693                                }
2694                                else { // no decl; default DOMTypeInfo to anySimpleType
2695                                        attrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYSIMPLETYPE);
2696                                }
2697
2698                                // Save the type for later use
2699                                attType = attDefForWildCard->getType();
2700                        }
2701                        else {
2702                                normalizeAttValue(
2703                                        attDef, namePtr, curPair->getValue(), normBuf
2704                                );
2705
2706                                //  If we found an attdef for this one, then lets validate it.
2707                                if (attDef)
2708                                {
2709                                        const XMLCh* xsNormalized = normBuf.getRawBuffer();
2710                                        if (fGrammarType == Grammar::SchemaGrammarType)
2711                                        {
2712                                                DatatypeValidator* tempDV = ((SchemaAttDef*) attDef)->getDatatypeValidator();
2713                                                if (tempDV && tempDV->getWSFacet() != DatatypeValidator::PRESERVE)
2714                                                {
2715                                                        // normalize the attribute according to schema whitespace facet
2716                                                        ((SchemaValidator*) fValidator)->normalizeWhiteSpace(tempDV, xsNormalized, fWSNormalizeBuf, true);
2717                                                        xsNormalized = fWSNormalizeBuf.getRawBuffer();
2718                                                        if (fNormalizeData && fValidate && !skipThisOne) {
2719                                                                normBuf.set(xsNormalized);
2720                                                        }
2721                                                }
2722                                        }
2723
2724                                        if (fValidate && !skipThisOne)
2725                                        {
2726                                                fValidator->validateAttrValue(
2727                                                        attDef, xsNormalized, false, elemDecl
2728                                                );
2729                                                attrValidator = ((SchemaValidator *)fValidator)->getMostRecentAttrValidator();
2730                                                if(((SchemaValidator *)fValidator)->getErrorOccurred())
2731                                                {
2732                                                        fPSVIElemContext.fErrorOccurred = true;
2733                                                        if(getPSVIHandler())
2734                                                                attrValid = PSVIItem::VALIDITY_INVALID;
2735                                                }
2736                                        }
2737                                        else {
2738                                                attrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYSIMPLETYPE);
2739                                        }
2740                                }
2741                                else {
2742                                        attrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYSIMPLETYPE);
2743                                }
2744
2745                                // Save the type for later use
2746                                if (attDef)
2747                                {
2748                                        attType = attDef->getType();
2749                                }
2750                        }
2751
2752                        // now fill in the PSVIAttributes entry for this attribute:
2753                                if(getPSVIHandler())
2754                                {
2755                                        psviAttr = fPSVIAttrList->getPSVIAttributeToFill
2756                                        (
2757                                                suffPtr
2758                                                #ifdef TEST_NAMESPACE_RESOLVER
2759                                                , (*fUriResolver)[uriId]
2760                                                #else
2761                                                , fURIStringPool->getValueForId(uriId)
2762                                                #endif
2763                                        );
2764                                        SchemaAttDef *actualAttDef = 0;
2765                                        if(attDef)
2766                                                actualAttDef = (SchemaAttDef *)attDef;
2767                                        else if (attDefForWildCard)
2768                                                actualAttDef = (SchemaAttDef *)attDefForWildCard;
2769                                if(actualAttDef)
2770                                {
2771                                                XSAttributeDeclaration *attrDecl = (XSAttributeDeclaration *)fModel->getXSObject(actualAttDef);
2772                                        DatatypeValidator * attrDataType = actualAttDef->getDatatypeValidator();
2773                                                XSSimpleTypeDefinition *validatingType = (XSSimpleTypeDefinition *)fModel->getXSObject(attrDataType);
2774                                                if(attrValid != PSVIItem::VALIDITY_VALID)
2775                                                {
2776                                                        psviAttr->reset
2777                                                (
2778                                                                fRootElemName
2779                                                                , attrValid
2780                                                                , attrAssessed
2781                                                                , validatingType
2782                                                                , 0
2783                                                                , actualAttDef->getValue()
2784                                                                , false
2785                                                                , attrDecl
2786                                                        , 0
2787                                                        );
2788                                                }
2789                                                else
2790                                                {
2791                                                        XSSimpleTypeDefinition *memberType = 0;
2792                                                        if(validatingType->getVariety() == XSSimpleTypeDefinition::VARIETY_UNION)
2793                                                                memberType = (XSSimpleTypeDefinition *)fModel->getXSObject(attrValidator);
2794                                                        psviAttr->reset
2795                                                (
2796                                                                fRootElemName
2797                                                                , attrValid
2798                                                                , attrAssessed
2799                                                                , validatingType
2800                                                                , memberType
2801                                                                , actualAttDef->getValue()
2802                                                                , false
2803                                                                , attrDecl
2804                                                        , (memberType)?attrValidator:attrDataType
2805                                                        );
2806                                                }
2807                                }
2808                                else
2809                                {
2810                                                psviAttr->reset
2811                                        (
2812                                                        fRootElemName
2813                                                        , attrValid
2814                                                        , attrAssessed
2815                                                        , 0
2816                                                        , 0
2817                                                , 0
2818                                                        , false
2819                                                        , 0
2820                                                , 0
2821                                                );
2822                                }
2823                                }
2824                }
2825
2826                //  Add this attribute to the attribute list that we use to pass them
2827                //  to the handler. We reuse its existing elements but expand it as
2828                //  required.
2829                XMLAttr* curAttr;
2830                if (retCount >= curAttListSize)
2831                {
2832                        curAttr = new (fMemoryManager) XMLAttr
2833                        (
2834                                uriId
2835                                , suffPtr
2836                                , prefPtr
2837                                , normBuf.getRawBuffer()
2838                                , attType
2839                                , true
2840                                , fMemoryManager
2841                        );
2842                        toFill.addElement(curAttr);
2843                }
2844                else
2845                {
2846                        curAttr = toFill.elementAt(retCount);
2847                        curAttr->set
2848                        (
2849                                uriId
2850                                , suffPtr
2851                                , prefPtr
2852                                , normBuf.getRawBuffer()
2853                                , attType
2854                        );
2855                        curAttr->setSpecified(true);
2856                }
2857                if(psviAttr)
2858                        psviAttr->setValue(curAttr->getValue());
2859
2860                // Bump the count of attrs in the list
2861                retCount++;
2862        }
2863
2864        //  Now, if there are any attributes declared by this element, let's
2865        //  go through them and make sure that any required ones are provided,
2866        //  and fault in any fixed ones and defaulted ones that are not provided
2867        //  literally.
2868        if (hasDefs)
2869        {
2870                // Check after all specified attrs are scanned
2871                // (1) report error for REQUIRED attrs that are missing (V_TAGc)
2872                // (2) add default attrs if missing (FIXED and NOT_FIXED)
2873
2874                XMLAttDefList& attDefList = getAttDefList(currType, elemDecl);
2875
2876                for(XMLSize_t i=0; i<attDefList.getAttDefCount(); i++)
2877                {
2878                        // Get the current att def, for convenience and its def type
2879                        XMLAttDef *curDef = &attDefList.getAttDef(i);
2880                        const XMLAttDef::DefAttTypes defType = curDef->getDefaultType();
2881
2882                        unsigned int *attCountPtr = fAttDefRegistry->get(curDef);
2883                        if (!attCountPtr || *attCountPtr < fElemCount)
2884                        { // did not occur
2885                                // note that since there is no attribute information
2886                                // item present, there is no PSVI infoset to augment here *except*
2887                                // that the element is invalid
2888
2889                                //the attribute is not provided
2890                                if (fValidate)
2891                                {
2892                                        // If we are validating and its required, then an error
2893                                        if ((defType == XMLAttDef::Required) ||
2894                                                (defType == XMLAttDef::Required_And_Fixed)  )
2895
2896                                        {
2897                                                fValidator->emitError
2898                                                (
2899                                                        XMLValid::RequiredAttrNotProvided
2900                                                        , curDef->getFullName()
2901                                                );
2902                                                fPSVIElemContext.fErrorOccurred = true;
2903                                        }
2904                                        else if ((defType == XMLAttDef::Default) ||
2905                                                         (defType == XMLAttDef::Fixed)  )
2906                                        {
2907                                                if (fStandalone && curDef->isExternal())
2908                                                {
2909                                                        // XML 1.0 Section 2.9
2910                                                        // Document is standalone, so attributes must not be defaulted.
2911                                                        fValidator->emitError(XMLValid::NoDefAttForStandalone, curDef->getFullName(), elemDecl->getFullName());
2912                                                }
2913                                        }
2914                                }
2915
2916                                //  Fault in the value if needed, and bump the att count.
2917                                if ((defType == XMLAttDef::Default)
2918                                        ||  (defType == XMLAttDef::Fixed))
2919                                {
2920                                        // Let the validator pass judgement on the attribute value
2921                                        if (fValidate)
2922                                        {
2923                                                fValidator->validateAttrValue
2924                                                (
2925                                                        curDef
2926                                                        , curDef->getValue()
2927                                                        , false
2928                                                        , elemDecl
2929                                                );
2930                                        }
2931
2932                                        XMLAttr* curAtt;
2933                                        if (retCount >= curAttListSize)
2934                                        {
2935                                                curAtt = new (fMemoryManager) XMLAttr(fMemoryManager);
2936                                                fValidator->faultInAttr(*curAtt, *curDef);
2937                                                fAttrList.addElement(curAtt);
2938                                        }
2939                                        else
2940                                        {
2941                                                curAtt = fAttrList.elementAt(retCount);
2942                                                fValidator->faultInAttr(*curAtt, *curDef);
2943                                        }
2944
2945                                        // Indicate it was not explicitly specified and bump count
2946                                        curAtt->setSpecified(false);
2947                                        retCount++;
2948                                        if(getPSVIHandler())
2949                                        {
2950                                                QName *attName = ((SchemaAttDef *)curDef)->getAttName();
2951                                                PSVIAttribute *defAttrToFill = fPSVIAttrList->getPSVIAttributeToFill
2952                                                (
2953                                                        attName->getLocalPart()
2954                                                        #ifdef TEST_NAMESPACE_RESOLVER
2955                                                        , (*fUriResolver)[attName->getURI()]
2956                                                        #else
2957                                                        , fURIStringPool->getValueForId(attName->getURI())
2958                                                        #endif
2959                                                );
2960                                                XSAttributeDeclaration *defAttrDecl = (XSAttributeDeclaration *)fModel->getXSObject((void *)curDef);
2961                                                DatatypeValidator * attrDataType = ((SchemaAttDef *)curDef)->getDatatypeValidator();
2962                                                XSSimpleTypeDefinition *defAttrType =
2963                                                        (XSSimpleTypeDefinition*)fModel->getXSObject(attrDataType);
2964                                                // would have occurred during validation of default value
2965                                                if(((SchemaValidator *)fValidator)->getErrorOccurred())
2966                                                {
2967                                                        defAttrToFill->reset(
2968                                                                fRootElemName
2969                                                                , PSVIItem::VALIDITY_INVALID
2970                                                                , PSVIItem::VALIDATION_FULL
2971                                                                , defAttrType
2972                                                                , 0
2973                                                                , curDef->getValue()
2974                                                                , true
2975                                                                , defAttrDecl
2976                                                                , 0
2977                                                        );
2978                                                }
2979                                                else
2980                                                {
2981                                                        XSSimpleTypeDefinition *defAttrMemberType = 0;
2982                                                        if(defAttrType->getVariety() == XSSimpleTypeDefinition::VARIETY_UNION)
2983                                                        {
2984                                                                defAttrMemberType = (XSSimpleTypeDefinition *)fModel->getXSObject
2985                                                                (
2986                                                                        ((SchemaValidator*)fValidator)->getMostRecentAttrValidator()
2987                                                                );
2988                                                        }
2989                                                        defAttrToFill->reset
2990                                                        (
2991                                                                fRootElemName
2992                                                                , PSVIItem::VALIDITY_VALID
2993                                                                , PSVIItem::VALIDATION_FULL
2994                                                                , defAttrType
2995                                                                , defAttrMemberType
2996                                                                , curDef->getValue()
2997                                                                , true
2998                                                                , defAttrDecl
2999                                                                , (defAttrMemberType)?((SchemaValidator *)fValidator)->getMostRecentAttrValidator():attrDataType
3000                                                        );
3001                                                }
3002                                                defAttrToFill->setValue(curDef->getValue());
3003                                        }
3004                                }
3005                        }
3006                        else if (attCountPtr)
3007                        {
3008                                //attribute is provided
3009                                // (schema) report error for PROHIBITED attrs that are present (V_TAGc)
3010                                if (defType == XMLAttDef::Prohibited && fValidate)
3011                                {
3012                                        fValidator->emitError
3013                                        (
3014                                                XMLValid::ProhibitedAttributePresent
3015                                                , curDef->getFullName()
3016                                        );
3017                                        fPSVIElemContext.fErrorOccurred = true;
3018                                        if (getPSVIHandler())
3019                                        {
3020                                                QName *attQName = ((SchemaAttDef *)curDef)->getAttName();
3021                                                // bad luck...
3022                                                PSVIAttribute *prohibitedAttr = fPSVIAttrList->getAttributePSVIByName
3023                                                (
3024                                                        attQName->getLocalPart()
3025                                                        #ifdef TEST_NAMESPACE_RESOLVER
3026                                                        , (*fUriResolver)[attQName->getURI()]
3027                                                        #else
3028                                                        , fURIStringPool->getValueForId(attQName->getURI())
3029                                                        #endif
3030                                                );
3031                                                prohibitedAttr->updateValidity(PSVIItem::VALIDITY_INVALID);
3032                                        }
3033                                }
3034                        }
3035                }
3036        }
3037
3038        return retCount;
3039#endif
3040}
3041
3042
3043//  This method will take a raw attribute value and normalize it according to
3044//  the rules of the attribute type. It will put the resulting value into the
3045//  passed buffer.
3046//
3047//  This code assumes that escaped characters in the original value (via char
3048//  refs) are prefixed by a 0xFFFF character. This is because some characters
3049//  are legal if escaped only. And some escape chars are not subject to
3050//  normalization rules.
3051bool SGXMLScanner::normalizeAttValue( const   XMLAttDef* const    attDef
3052                                                                          , const XMLCh* const        attName
3053                                                                          , const XMLCh* const        value
3054                                                                          ,       XMLBuffer&          toFill)
3055{
3056#ifdef SGXML_SCANNER_DEPRECATED
3057        DEPRECATED_FEATURE_IN_ICXML;
3058#else
3059        // A simple state value for a whitespace processing state machine
3060        enum States
3061        {
3062                InWhitespace
3063                , InContent
3064        };
3065
3066        // Get the type and name
3067        const XMLAttDef::AttTypes type = (attDef)
3068                                                        ?attDef->getType()
3069                                                        :XMLAttDef::CData;
3070
3071        // Assume its going to go fine, and empty the target buffer in preperation
3072        bool retVal = true;
3073        toFill.reset();
3074
3075        // Get attribute def - to check to see if it's declared externally or not
3076        bool  isAttExternal = (attDef)
3077                                                ?attDef->isExternal()
3078                                                :false;
3079
3080        //  Loop through the chars of the source value and normalize it according
3081        //  to the type.
3082        States curState = InContent;
3083        bool firstNonWS = false;
3084        XMLCh nextCh;
3085        const XMLCh* srcPtr = value;
3086
3087        if (type == XMLAttDef::CData || type > XMLAttDef::Notation) {
3088                while (*srcPtr) {
3089                        //  Get the next character from the source. We have to watch for
3090                        //  escaped characters (which are indicated by a 0xFFFF value followed
3091                        //  by the char that was escaped.)
3092                        nextCh = *srcPtr;
3093
3094                        // Do we have an escaped character ?
3095                        if (nextCh == 0xFFFF)
3096                        {
3097                                nextCh = *++srcPtr;
3098                        }
3099                        else if ( (nextCh <= 0x0D) && (nextCh == 0x09 || nextCh == 0x0A || nextCh == 0x0D) ) {
3100                                // Check Validity Constraint for Standalone document declaration
3101                                // XML 1.0, Section 2.9
3102                                if (fStandalone && fValidate && isAttExternal)
3103                                {
3104                                         // Can't have a standalone document declaration of "yes" if  attribute
3105                                         // values are subject to normalisation
3106                                         fValidator->emitError(XMLValid::NoAttNormForStandalone, attName);
3107                                }
3108                                nextCh = chSpace;
3109                        }
3110                        else if (nextCh == chOpenAngle) {
3111                                //  If its not escaped, then make sure its not a < character, which is
3112                                //  not allowed in attribute values.
3113                                emitError(XMLErrs::BracketInAttrValue, attName);
3114                                retVal = false;
3115                        }
3116
3117                        // Add this char to the target buffer
3118                        toFill.append(nextCh);
3119
3120                        // And move up to the next character in the source
3121                        srcPtr++;
3122                }
3123        }
3124        else {
3125                while (*srcPtr)
3126                {
3127                        //  Get the next character from the source. We have to watch for
3128                        //  escaped characters (which are indicated by a 0xFFFF value followed
3129                        //  by the char that was escaped.)
3130                        nextCh = *srcPtr;
3131
3132                        // Do we have an escaped character ?
3133                        if (nextCh == 0xFFFF)
3134                        {
3135                                nextCh = *++srcPtr;
3136                        }
3137                        else if (nextCh == chOpenAngle) {
3138                                //  If its not escaped, then make sure its not a < character, which is
3139                                //  not allowed in attribute values.
3140                                emitError(XMLErrs::BracketInAttrValue, attName);
3141                                retVal = false;
3142                        }
3143
3144                        if (curState == InWhitespace)
3145                        {
3146                                if (!fReaderMgr.getCurrentReader()->isWhitespace(nextCh))
3147                                {
3148                                        if (firstNonWS)
3149                                                toFill.append(chSpace);
3150                                        curState = InContent;
3151                                        firstNonWS = true;
3152                                }
3153                                else
3154                                {
3155                                        srcPtr++;
3156                                        continue;
3157                                }
3158                        }
3159                        else if (curState == InContent)
3160                        {
3161                                if (fReaderMgr.getCurrentReader()->isWhitespace(nextCh))
3162                                {
3163                                        curState = InWhitespace;
3164                                        srcPtr++;
3165
3166                                        // Check Validity Constraint for Standalone document declaration
3167                                        // XML 1.0, Section 2.9
3168                                        if (fStandalone && fValidate && isAttExternal)
3169                                        {
3170                                                if (!firstNonWS || (nextCh != chSpace) || (!*srcPtr) || fReaderMgr.getCurrentReader()->isWhitespace(*srcPtr))
3171                                                {
3172                                                        // Can't have a standalone document declaration of "yes" if  attribute
3173                                                        // values are subject to normalisation
3174                                                        fValidator->emitError(XMLValid::NoAttNormForStandalone, attName);
3175                                                }
3176                                        }
3177                                        continue;
3178                                }
3179                                firstNonWS = true;
3180                        }
3181
3182                        // Add this char to the target buffer
3183                        toFill.append(nextCh);
3184
3185                        // And move up to the next character in the source
3186                        srcPtr++;
3187                }
3188        }
3189
3190        return retVal;
3191#endif
3192}
3193
3194//  This method will just normalize the input value as CDATA without
3195//  any standalone checking.
3196bool SGXMLScanner::normalizeAttRawValue( const   XMLCh* const        attrName
3197                                                                          , const XMLCh* const        value
3198                                                                          ,       XMLBuffer&          toFill)
3199{
3200#ifdef SGXML_SCANNER_DEPRECATED
3201        DEPRECATED_FEATURE_IN_ICXML;
3202#else
3203        // Assume its going to go fine, and empty the target buffer in preperation
3204        bool retVal = true;
3205        toFill.reset();
3206
3207        //  Loop through the chars of the source value and normalize it according
3208        //  to the type.
3209        bool escaped;
3210        XMLCh nextCh;
3211        const XMLCh* srcPtr = value;
3212        while (*srcPtr)
3213        {
3214                //  Get the next character from the source. We have to watch for
3215                //  escaped characters (which are indicated by a 0xFFFF value followed
3216                //  by the char that was escaped.)
3217                nextCh = *srcPtr;
3218                escaped = (nextCh == 0xFFFF);
3219                if (escaped)
3220                        nextCh = *++srcPtr;
3221
3222                //  If its not escaped, then make sure its not a < character, which is
3223                //  not allowed in attribute values.
3224                if (!escaped && (*srcPtr == chOpenAngle))
3225                {
3226                        emitError(XMLErrs::BracketInAttrValue, attrName);
3227                        retVal = false;
3228                }
3229
3230                if (!escaped)
3231                {
3232                        //  NOTE: Yes this is a little redundant in that a 0x20 is
3233                        //  replaced with an 0x20. But its faster to do this (I think)
3234                        //  than checking for 9, A, and D separately.
3235                        if (fReaderMgr.getCurrentReader()->isWhitespace(nextCh))
3236                                nextCh = chSpace;
3237                }
3238
3239                // Add this char to the target buffer
3240                toFill.append(nextCh);
3241
3242                // And move up to the next character in the source
3243                srcPtr++;
3244        }
3245        return retVal;
3246#endif
3247}
3248
3249//  This method will reset the scanner data structures, and related plugged
3250//  in stuff, for a new scan session. We get the input source for the primary
3251//  XML entity, create the reader for it, and push it on the stack so that
3252//  upon successful return from here we are ready to go.
3253void SGXMLScanner::scanReset(const InputSource& src)
3254{
3255#ifdef SGXML_SCANNER_DEPRECATED
3256        DEPRECATED_FEATURE_IN_ICXML;
3257#else
3258        //  This call implicitly tells us that we are going to reuse the scanner
3259        //  if it was previously used. So tell the validator to reset itself.
3260        //
3261        //  But, if the fUseCacheGrammar flag is set, then don't reset it.
3262        //
3263        //  NOTE:   The ReaderMgr is flushed on the way out, because that is
3264        //          required to insure that files are closed.
3265        fGrammarResolver->cacheGrammarFromParse(fToCacheGrammar);
3266        fGrammarResolver->useCachedGrammarInParse(fUseCachedGrammar);
3267
3268        // Clear transient schema info list.
3269        //
3270        fSchemaInfoList->removeAll ();
3271
3272        // fModel may need updating, as fGrammarResolver could have cleaned it
3273        if(fModel && getPSVIHandler())
3274                fModel = fGrammarResolver->getXSModel();
3275
3276        // Create dummy schema grammar
3277        if (!fSchemaGrammar) {
3278                fSchemaGrammar = new (fGrammarPoolMemoryManager) SchemaGrammar(fGrammarPoolMemoryManager);
3279        }
3280
3281        fGrammar = fSchemaGrammar;
3282        fGrammarType = Grammar::DTDGrammarType;
3283        fRootGrammar = 0;
3284
3285        fValidator->setGrammar(fGrammar);
3286        if (fValidatorFromUser) {
3287
3288                ((SchemaValidator*) fValidator)->setErrorReporter(fErrorReporter);
3289                ((SchemaValidator*) fValidator)->setGrammarResolver(fGrammarResolver);
3290                ((SchemaValidator*) fValidator)->setExitOnFirstFatal(fExitOnFirstFatal);
3291        }
3292
3293        // Reset validation
3294        fValidate = (fValScheme == Val_Always) ? true : false;
3295
3296        //  And for all installed handlers, send reset events. This gives them
3297        //  a chance to flush any cached data.
3298        if (fDocHandler)
3299                fDocHandler->resetDocument();
3300        if (fEntityHandler)
3301                fEntityHandler->resetEntities();
3302        if (fErrorReporter)
3303                fErrorReporter->resetErrors();
3304
3305        // Clear out the id reference list
3306        resetValidationContext();
3307
3308        // Reset the Root Element Name
3309        fRootElemName = 0;
3310
3311        // Reset IdentityConstraints
3312        if (fICHandler)
3313                fICHandler->reset();
3314
3315        #ifndef TEST_NAMESPACE_RESOLVER
3316        //  Reset the element stack, and give it the latest ids for the special
3317        //  URIs it has to know about.
3318        fElemStack.reset
3319        (
3320                fEmptyNamespaceId
3321                , fUnknownNamespaceId
3322                , fXMLNamespaceId
3323                , fXMLNSNamespaceId
3324        );
3325
3326        if (!fSchemaNamespaceId)
3327                fSchemaNamespaceId  = fURIStringPool->addOrFind(SchemaSymbols::fgURI_XSI);
3328        #endif
3329
3330        // Reset some status flags
3331        fInException = false;
3332        fStandalone = false;
3333        fErrorCount = 0;
3334        fHasNoDTD = true;
3335        fSeeXsi = false;
3336        fDoNamespaces = true;
3337        fDoSchema = true;
3338
3339        // Reset PSVI context
3340        // Note that we always need this around for DOMTypeInfo
3341        if (!fPSVIElement)
3342                fPSVIElement = new (fMemoryManager) PSVIElement(fMemoryManager);
3343
3344        if (!fErrorStack)
3345        {
3346                fErrorStack = new (fMemoryManager) ValueStackOf<bool>(8, fMemoryManager);
3347        }
3348        else
3349        {
3350                fErrorStack->removeAllElements();
3351        }
3352
3353        resetPSVIElemContext();
3354
3355        // Reset the validators
3356        fSchemaValidator->reset();
3357        fSchemaValidator->setErrorReporter(fErrorReporter);
3358        fSchemaValidator->setExitOnFirstFatal(fExitOnFirstFatal);
3359        fSchemaValidator->setGrammarResolver(fGrammarResolver);
3360        if (fValidatorFromUser)
3361                fValidator->reset();
3362
3363        //  Handle the creation of the XML reader object for this input source.
3364        //  This will provide us with transcoding and basic lexing services.
3365        XMLReader* newReader = fReaderMgr.createReader
3366        (
3367                src
3368                , true
3369                , XMLReader::RefFrom_NonLiteral
3370                , XMLReader::Type_General
3371                , XMLReader::Source_External
3372                , fCalculateSrcOfs
3373                , fLowWaterMark
3374        );
3375
3376        if (!newReader) {
3377                if (src.getIssueFatalErrorIfNotFound())
3378                        ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource, src.getSystemId(), fMemoryManager);
3379                else
3380                        ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource_Warning, src.getSystemId(), fMemoryManager);
3381        }
3382
3383        // Push this read onto the reader manager
3384        fReaderMgr.pushReader(newReader, 0);
3385
3386        // and reset security-related things if necessary:
3387        if(fSecurityManager != 0)
3388        {
3389                fEntityExpansionLimit = fSecurityManager->getEntityExpansionLimit();
3390                fEntityExpansionCount = 0;
3391        }
3392        fElemCount = 0;
3393#ifndef REMOVE_UINT_POOL
3394        if(fUIntPoolRowTotal >= 32)
3395        { // 8 KB tied up with validating attributes...
3396                fAttDefRegistry->removeAll();
3397                recreateUIntPool();
3398        }
3399        else
3400        {
3401                // note that this will implicitly reset the values of the hashtables,
3402                // though their buckets will still be tied up
3403                resetUIntPool();
3404        }
3405#endif
3406        fUndeclaredAttrRegistry->removeAll();
3407#endif
3408}
3409
3410
3411//  This method is called between markup in content. It scans for character
3412//  data that is sent to the document handler. It watches for any markup
3413//  characters that would indicate that the character data has ended. It also
3414//  handles expansion of general and character entities.
3415//
3416//  sendData() is a local static helper for this method which handles some
3417//  code that must be done in three different places here.
3418void SGXMLScanner::sendCharData(XMLBuffer& toSend)
3419{
3420#ifdef SGXML_SCANNER_DEPRECATED
3421        DEPRECATED_FEATURE_IN_ICXML;
3422#else
3423        // If no data in the buffer, then nothing to do
3424        if (toSend.isEmpty())
3425                return;
3426
3427        //  We do different things according to whether we are validating or
3428        //  not. If not, its always just characters; else, it depends on the
3429        //  current element's content model.
3430        if (fValidate)
3431        {
3432                // Get the raw data we need for the callback
3433                const XMLCh* rawBuf = toSend.getRawBuffer();
3434                const XMLSize_t len = toSend.getLen();
3435
3436                // Get the character data opts for the current element
3437                XMLElementDecl::CharDataOpts charOpts = XMLElementDecl::AllCharData;
3438                // And see if the current element is a 'Children' style content model
3439                ComplexTypeInfo *currType = ((SchemaValidator*)fValidator)->getCurrentTypeInfo();
3440                if(currType)
3441                {
3442                        SchemaElementDecl::ModelTypes modelType = (SchemaElementDecl::ModelTypes) currType->getContentType();
3443                        if(modelType == SchemaElementDecl::Children ||
3444                           modelType == SchemaElementDecl::ElementOnlyEmpty)
3445                                charOpts = XMLElementDecl::SpacesOk;
3446                        else if(modelType == SchemaElementDecl::Empty)
3447                                charOpts = XMLElementDecl::NoCharData;
3448                }
3449
3450                // should not be necessary once PSVI method on element decls
3451                // are removed
3452                if (charOpts == XMLElementDecl::NoCharData)
3453                {
3454                        // They definitely cannot handle any type of char data
3455                        fValidator->emitError(XMLValid::NoCharDataInCM);
3456                        if (getPSVIHandler())
3457                        {
3458                                // REVISIT:
3459                                // PSVIElement->setValidity(PSVIItem::VALIDITY_INVALID);
3460                        }
3461                }
3462                else if (fReaderMgr.getCurrentReader()->isAllSpaces(rawBuf, len))
3463                {
3464                        //  Its all spaces. So, if they can take spaces, then send it
3465                        //  as ignorable whitespace. If they can handle any char data
3466                        //  send it as characters.
3467                        if (charOpts == XMLElementDecl::SpacesOk) {
3468                                if (fDocHandler)
3469                                        fDocHandler->ignorableWhitespace(rawBuf, len, false);
3470                        }
3471                        else if (charOpts == XMLElementDecl::AllCharData)
3472                        {
3473                                XMLSize_t xsLen;
3474                                const XMLCh* xsNormalized;
3475                                DatatypeValidator* tempDV = ((SchemaValidator*) fValidator)->getCurrentDatatypeValidator();
3476                                if (tempDV && tempDV->getWSFacet() != DatatypeValidator::PRESERVE)
3477                                {
3478                                        // normalize the character according to schema whitespace facet
3479                                        ((SchemaValidator*) fValidator)->normalizeWhiteSpace(tempDV, rawBuf, fWSNormalizeBuf);
3480                                        xsNormalized = fWSNormalizeBuf.getRawBuffer();
3481                                        xsLen = fWSNormalizeBuf.getLen();
3482                                }
3483                                else {
3484                                        xsNormalized = rawBuf;
3485                                        xsLen = len;
3486                                }
3487
3488                                // tell the schema validation about the character data for checkContent later
3489                                ((SchemaValidator*)fValidator)->setDatatypeBuffer(xsNormalized);
3490
3491                                // call all active identity constraints
3492                                if (toCheckIdentityConstraint() && fICHandler->getMatcherCount()) {
3493                                        fContent.append(xsNormalized, xsLen);
3494                                }
3495
3496                                if (fDocHandler) {
3497                                        if (fNormalizeData) {
3498                                                fDocHandler->docCharacters(xsNormalized, xsLen, false);
3499                                        }
3500                                        else {
3501                                                fDocHandler->docCharacters(rawBuf, len, false);
3502                                        }
3503                                }
3504                        }
3505                }
3506                else
3507                {
3508                        //  If they can take any char data, then send it. Otherwise, they
3509                        //  can only handle whitespace and can't handle this stuff so
3510                        //  issue an error.
3511                        if (charOpts == XMLElementDecl::AllCharData)
3512                        {
3513                                XMLSize_t xsLen;
3514                                const XMLCh *xsNormalized;
3515                                DatatypeValidator* tempDV = ((SchemaValidator*) fValidator)->getCurrentDatatypeValidator();
3516                                if (tempDV && tempDV->getWSFacet() != DatatypeValidator::PRESERVE)
3517                                {
3518                                        ((SchemaValidator*) fValidator)->normalizeWhiteSpace(tempDV, rawBuf, fWSNormalizeBuf);
3519                                        xsNormalized = fWSNormalizeBuf.getRawBuffer();
3520                                        xsLen = fWSNormalizeBuf.getLen();
3521                                }
3522                                else {
3523                                        xsNormalized = rawBuf;
3524                                        xsLen = len;
3525                                }
3526
3527                                // tell the schema validation about the character data for checkContent later
3528                                ((SchemaValidator*)fValidator)->setDatatypeBuffer(xsNormalized);
3529
3530                                // call all active identity constraints
3531                                if (toCheckIdentityConstraint() && fICHandler->getMatcherCount()) {
3532                                        fContent.append(xsNormalized, xsLen);
3533                                }
3534
3535                                if (fDocHandler) {
3536                                        if (fNormalizeData) {
3537                                                fDocHandler->docCharacters(xsNormalized, xsLen, false);
3538                                        }
3539                                        else {
3540                                                fDocHandler->docCharacters(rawBuf, len, false);
3541                                        }
3542                                }
3543                        }
3544                        else
3545                        {
3546                                fValidator->emitError(XMLValid::NoCharDataInCM);
3547                                if (getPSVIHandler())
3548                                {
3549                                        // REVISIT:
3550                                        // PSVIElement->setValidity(PSVIItem::VALIDITY_INVALID);
3551                                }
3552                        }
3553                }
3554        }
3555        else
3556        {
3557                // call all active identity constraints
3558                if (toCheckIdentityConstraint() && fICHandler->getMatcherCount())
3559                        fContent.append(toSend.getRawBuffer(), toSend.getLen());
3560
3561                // Always assume its just char data if not validating
3562                if (fDocHandler)
3563                        fDocHandler->docCharacters(toSend.getRawBuffer(), toSend.getLen(), false);
3564        }
3565
3566        // Reset buffer
3567        toSend.reset();
3568#endif
3569}
3570
3571
3572
3573//  This method is called with a key/value string pair that represents an
3574//  xmlns="yyy" or xmlns:xxx="yyy" attribute. This method will update the
3575//  current top of the element stack based on this data. We know that when
3576//  we get here, that it is one of these forms, so we don't bother confirming
3577//  it.
3578//
3579//  But we have to ensure
3580//      1. xxx is not xmlns
3581//      2. if xxx is xml, then yyy must match XMLUni::fgXMLURIName, and vice versa
3582//      3. yyy is not XMLUni::fgXMLNSURIName
3583//      4. if xxx is not null, then yyy cannot be an empty string.
3584void SGXMLScanner::updateNSMap(const  XMLCh* const    attrName
3585                                                          , const XMLCh* const    attrValue)
3586{
3587#if defined(TEST_NAMESPACE_RESOLVER) || defined(SGXML_SCANNER_DEPRECATED)
3588        DEPRECATED_FEATURE_IN_ICXML;
3589#else
3590        updateNSMap(attrName, attrValue, XMLString::indexOf(attrName, chColon));
3591#endif
3592}
3593
3594void SGXMLScanner::updateNSMap(const  XMLCh* const    attrName
3595                                                          , const XMLCh* const    attrValue
3596                                                          , const int colonOfs)
3597{
3598#if defined(TEST_NAMESPACE_RESOLVER) || defined(SGXML_SCANNER_DEPRECATED)
3599        DEPRECATED_FEATURE_IN_ICXML;
3600#else
3601        // We need a buffer to normalize the attribute value into
3602        XMLBufBid bbNormal(&fBufMgr);
3603        XMLBuffer& normalBuf = bbNormal.getBuffer();
3604
3605        //  Normalize the value into the passed buffer. In this case, we don't
3606        //  care about the return value. An error was issued for the error, which
3607        //  is all we care about here.
3608        normalizeAttRawValue(attrName, attrValue, normalBuf);
3609        XMLCh* namespaceURI = normalBuf.getRawBuffer();
3610
3611        //  We either have the default prefix (""), or we point it into the attr
3612        //  name parameter. Note that the xmlns is not the prefix we care about
3613        //  here. To us, the 'prefix' is really the local part of the attrName
3614        //  parameter.
3615        //
3616        //  Check 1. xxx is not xmlns
3617        //        2. if xxx is xml, then yyy must match XMLUni::fgXMLURIName, and vice versa
3618        //        3. yyy is not XMLUni::fgXMLNSURIName
3619        //        4. if xxx is not null, then yyy cannot be an empty string.
3620        const XMLCh* prefPtr = XMLUni::fgZeroLenString;
3621        if (colonOfs != -1) {
3622                prefPtr = &attrName[colonOfs + 1];
3623
3624                if (XMLString::equals(prefPtr, XMLUni::fgXMLNSString))
3625                        emitError(XMLErrs::NoUseOfxmlnsAsPrefix);
3626                else if (XMLString::equals(prefPtr, XMLUni::fgXMLString)) {
3627                        if (!XMLString::equals(namespaceURI, XMLUni::fgXMLURIName))
3628                                emitError(XMLErrs::PrefixXMLNotMatchXMLURI);
3629                }
3630
3631                if (!namespaceURI)
3632                        emitError(XMLErrs::NoEmptyStrNamespace, attrName);
3633                else if(!*namespaceURI && fXMLVersion == XMLReader::XMLV1_0)
3634                        emitError(XMLErrs::NoEmptyStrNamespace, attrName);
3635        }
3636
3637        if (XMLString::equals(namespaceURI, XMLUni::fgXMLNSURIName))
3638                emitError(XMLErrs::NoUseOfxmlnsURI);
3639        else if (XMLString::equals(namespaceURI, XMLUni::fgXMLURIName)) {
3640                if (!XMLString::equals(prefPtr, XMLUni::fgXMLString))
3641                        emitError(XMLErrs::XMLURINotMatchXMLPrefix);
3642        }
3643
3644        //  Ok, we have to get the unique id for the attribute value, which is the
3645        //  URI that this value should be mapped to. The validator has the
3646        //  namespace string pool, so we ask him to find or add this new one. Then
3647        //  we ask the element stack to add this prefix to URI Id mapping.
3648        fElemStack.addPrefix
3649        (
3650                prefPtr
3651                #ifdef TEST_NAMESPACE_RESOLVER
3652                , fUriResolver->resolveUriId(namespaceURI)
3653                #else
3654                , fURIStringPool->addOrFind(namespaceURI)
3655                #endif
3656        );
3657#endif
3658}
3659
3660void SGXMLScanner::scanRawAttrListforNameSpaces(XMLSize_t attCount)
3661{
3662#if defined(SGXML_SCANNER_DEPRECATED)
3663        DEPRECATED_FEATURE_IN_ICXML;
3664#else
3665        //  Make an initial pass through the list and find any xmlns attributes or
3666        //  schema attributes.
3667        //  When we find one, send it off to be used to update the element stack's
3668        //  namespace mappings.
3669        for (XMLSize_t index = 0; index < attCount; index++)
3670        {
3671                // each attribute has the prefix:suffix="value"
3672                const KVStringPair* curPair = fRawAttrList->elementAt(index);
3673                const XMLCh* rawPtr = curPair->getKey();
3674
3675                //  If either the key begins with "xmlns:" or its just plain
3676                //  "xmlns", then use it to update the map.
3677                if (!XMLString::compareNString(rawPtr, XMLUni::fgXMLNSColonString, 6)
3678                ||  XMLString::equals(rawPtr, XMLUni::fgXMLNSString))
3679                {
3680                        const XMLCh* valuePtr = curPair->getValue();
3681
3682                        updateNSMap(rawPtr, valuePtr, fRawAttrColonList[index]);
3683
3684                        // if the schema URI is seen in the the valuePtr, set the boolean seeXsi
3685                        if (XMLString::equals(valuePtr, SchemaSymbols::fgURI_XSI)) {
3686                                fSeeXsi = true;
3687                        }
3688                }
3689        }
3690
3691        // walk through the list again to deal with "xsi:...."
3692        if (fSeeXsi)
3693        {
3694                //  Schema Xsi Type yyyy (e.g. xsi:type="yyyyy")
3695                XMLBufBid bbXsi(&fBufMgr);
3696                XMLBuffer& fXsiType = bbXsi.getBuffer();
3697
3698                for (XMLSize_t index = 0; index < attCount; index++)
3699                {
3700                        // each attribute has the prefix:suffix="value"
3701                        const KVStringPair* curPair = fRawAttrList->elementAt(index);
3702                        const XMLCh* rawPtr = curPair->getKey();
3703                        const XMLCh* prefPtr;
3704
3705                        int   colonInd = fRawAttrColonList[index];
3706
3707                        if (colonInd != -1) {
3708                                fURIBuf.set(rawPtr, colonInd);
3709                                prefPtr = fURIBuf.getRawBuffer();
3710                        }
3711                        else {
3712                                prefPtr = XMLUni::fgZeroLenString;
3713                        }
3714
3715                        // if schema URI has been seen, scan for the schema location and uri
3716                        // and resolve the schema grammar; or scan for schema type
3717                        if (resolvePrefix(prefPtr, ElemStack::Mode_Attribute) == fSchemaNamespaceId)
3718                        {
3719
3720                                const XMLCh* valuePtr = curPair->getValue();
3721                                const XMLCh*  suffPtr = &rawPtr[colonInd + 1];
3722
3723                                if (XMLString::equals(suffPtr, SchemaSymbols::fgXSI_SCHEMALOCATION))
3724                                        parseSchemaLocation(valuePtr);
3725                                else if (XMLString::equals(suffPtr, SchemaSymbols::fgXSI_NONAMESPACESCHEMALOCATION))
3726                                        resolveSchemaGrammar(valuePtr, XMLUni::fgZeroLenString);
3727
3728                                if( fValidator && fValidator->handlesSchema() )
3729                                {
3730                                        if (XMLString::equals(suffPtr, SchemaSymbols::fgXSI_TYPE))
3731                                        {
3732                                                // normalize the attribute according to schema whitespace facet
3733                                                DatatypeValidator* tempDV = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_QNAME);
3734                                                ((SchemaValidator*) fValidator)->normalizeWhiteSpace(tempDV, valuePtr, fXsiType, true);
3735                                        }
3736                                        else if (XMLString::equals(suffPtr, SchemaSymbols::fgATT_NILL))
3737                                        {
3738                                                // normalize the attribute according to schema whitespace facet
3739                                                XMLBuffer& fXsiNil = fBufMgr.bidOnBuffer();
3740                                                DatatypeValidator* tempDV = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_BOOLEAN);
3741                                                ((SchemaValidator*) fValidator)->normalizeWhiteSpace(tempDV, valuePtr, fXsiNil, true);
3742                                                if(XMLString::equals(fXsiNil.getRawBuffer(), SchemaSymbols::fgATTVAL_TRUE))
3743                                                        ((SchemaValidator*)fValidator)->setNillable(true);
3744                                                else if(XMLString::equals(fXsiNil.getRawBuffer(), SchemaSymbols::fgATTVAL_FALSE))
3745                                                        ((SchemaValidator*)fValidator)->setNillable(false);
3746                                                else
3747                                                        emitError(XMLErrs::InvalidAttValue, fXsiNil.getRawBuffer(), valuePtr);
3748                                                fBufMgr.releaseBuffer(fXsiNil);
3749                                        }
3750                                }
3751                        }
3752                }
3753
3754                if (fValidator && fValidator->handlesSchema()) {
3755                        if (!fXsiType.isEmpty()) {
3756                                int colonPos = -1;
3757                                unsigned int uriId = resolveQName (
3758                                          fXsiType.getRawBuffer()
3759                                        , fPrefixBuf
3760                                        , ElemStack::Mode_Element
3761                                        , colonPos
3762                                );
3763                                ((SchemaValidator*)fValidator)->setXsiType(fPrefixBuf.getRawBuffer(), fXsiType.getRawBuffer() + colonPos + 1, uriId);
3764                        }
3765                }
3766        }
3767#endif
3768}
3769
3770void SGXMLScanner::parseSchemaLocation(const XMLCh* const schemaLocationStr, bool ignoreLoadSchema)
3771{
3772#if defined(SGXML_SCANNER_DEPRECATED)
3773        DEPRECATED_FEATURE_IN_ICXML;
3774#else
3775        BaseRefVectorOf<XMLCh>* schemaLocation = XMLString::tokenizeString(schemaLocationStr, fMemoryManager);
3776        Janitor<BaseRefVectorOf<XMLCh> > janLoc(schemaLocation);
3777
3778        XMLSize_t size = schemaLocation->size();
3779        if (size % 2 != 0 ) {
3780                emitError(XMLErrs::BadSchemaLocation);
3781        } else {
3782                // We need a buffer to normalize the attribute value into
3783                XMLBuffer normalBuf(1023, fMemoryManager);
3784                for(XMLSize_t i=0; i<size; i=i+2) {
3785                        normalizeAttRawValue(SchemaSymbols::fgXSI_SCHEMALOCATION, schemaLocation->elementAt(i), normalBuf);
3786                        resolveSchemaGrammar(schemaLocation->elementAt(i+1), normalBuf.getRawBuffer(), ignoreLoadSchema);
3787                }
3788        }
3789#endif
3790}
3791
3792void SGXMLScanner::resolveSchemaGrammar(const XMLCh* const loc, const XMLCh* const uri, bool ignoreLoadSchema)
3793{
3794#if defined(SGXML_SCANNER_DEPRECATED)
3795        DEPRECATED_FEATURE_IN_ICXML;
3796#else
3797        Grammar* grammar = 0;
3798
3799        {
3800                XMLSchemaDescriptionImpl    theSchemaDescription(uri, fMemoryManager);
3801                theSchemaDescription.setLocationHints(loc);
3802                grammar = fGrammarResolver->getGrammar(&theSchemaDescription);
3803        }
3804
3805        // If multi-import is enabled, make sure the existing grammar came
3806        // from the import directive. Otherwise we may end up reloading
3807        // the same schema that came from the external grammar pool. Ideally,
3808        // we would move fSchemaInfoList to XMLGrammarPool so that it survives
3809        // the destruction of the scanner in which case we could rely on the
3810        // same logic we use to weed out duplicate schemas below.
3811        //
3812        if (!grammar || grammar->getGrammarType() == Grammar::DTDGrammarType ||
3813                (getHandleMultipleImports() &&
3814                 ((XMLSchemaDescription*)grammar->getGrammarDescription())->
3815                 getContextType () == XMLSchemaDescription::CONTEXT_IMPORT))
3816        {
3817          if (fLoadSchema || ignoreLoadSchema)
3818          {
3819                XSDDOMParser parser(0, fMemoryManager, 0);
3820
3821                parser.setValidationScheme(XercesDOMParser::Val_Never);
3822                parser.setDoNamespaces(true);
3823                parser.setUserEntityHandler(fEntityHandler);
3824                parser.setUserErrorReporter(fErrorReporter);
3825
3826                //Normalize sysId
3827                XMLBufBid nnSys(&fBufMgr);
3828                XMLBuffer& normalizedSysId = nnSys.getBuffer();
3829                XMLString::removeChar(loc, 0xFFFF, normalizedSysId);
3830                const XMLCh* normalizedURI = normalizedSysId.getRawBuffer();
3831
3832                // Create a buffer for expanding the system id
3833                XMLBufBid bbSys(&fBufMgr);
3834                XMLBuffer& expSysId = bbSys.getBuffer();
3835
3836                //  Allow the entity handler to expand the system id if they choose
3837                //  to do so.
3838                InputSource* srcToFill = 0;
3839                if (fEntityHandler)
3840                {
3841                        if (!fEntityHandler->expandSystemId(normalizedURI, expSysId))
3842                                expSysId.set(normalizedURI);
3843
3844                        ReaderMgr::LastExtEntityInfo lastInfo;
3845                        fReaderMgr.getLastExtEntityInfo(lastInfo);
3846                        XMLResourceIdentifier resourceIdentifier(XMLResourceIdentifier::SchemaGrammar,
3847                                                        expSysId.getRawBuffer(), uri, XMLUni::fgZeroLenString, lastInfo.systemId,
3848                                                        &fReaderMgr);
3849                        srcToFill = fEntityHandler->resolveEntity(&resourceIdentifier);
3850                }
3851                else
3852                {
3853                        expSysId.set(normalizedURI);
3854                }
3855
3856                //  If they didn't create a source via the entity handler, then we
3857                //  have to create one on our own.
3858                if (!srcToFill)
3859                {
3860                        if (fDisableDefaultEntityResolution)
3861                                return;
3862
3863                        ReaderMgr::LastExtEntityInfo lastInfo;
3864                        fReaderMgr.getLastExtEntityInfo(lastInfo);
3865
3866                        XMLURL urlTmp(fMemoryManager);
3867                        if ((!urlTmp.setURL(lastInfo.systemId, expSysId.getRawBuffer(), urlTmp)) ||
3868                                (urlTmp.isRelative()))
3869                        {
3870                                if (!fStandardUriConformant)
3871                                {
3872                                        XMLBufBid  ddSys(&fBufMgr);
3873                                        XMLBuffer& resolvedSysId = ddSys.getBuffer();
3874                                        XMLUri::normalizeURI(expSysId.getRawBuffer(), resolvedSysId);
3875
3876                                        srcToFill = new (fMemoryManager) LocalFileInputSource
3877                                        (
3878                                                lastInfo.systemId
3879                                                , resolvedSysId.getRawBuffer()
3880                                                , fMemoryManager
3881                                        );
3882                                }
3883                                else
3884                                        ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_MalformedURL, fMemoryManager);
3885                        }
3886                        else
3887                        {
3888                                if (fStandardUriConformant && urlTmp.hasInvalidChar())
3889                                        ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_MalformedURL, fMemoryManager);
3890
3891                                srcToFill = new (fMemoryManager) URLInputSource(urlTmp, fMemoryManager);
3892                        }
3893                }
3894
3895                // Put a janitor on the input source
3896                Janitor<InputSource> janSrc(srcToFill);
3897
3898                // Check if this exact schema has already been seen.
3899                const XMLCh* sysId = srcToFill->getSystemId();
3900                #ifdef TEST_NAMESPACE_RESOLVER
3901                unsigned int uriId = fUriResolver->resolveUriId(uri);
3902                #else
3903                unsigned int uriId = (uri && *uri) ? fURIStringPool->addOrFind(uri) : fEmptyNamespaceId;
3904                #endif
3905                SchemaInfo* importSchemaInfo = 0;
3906
3907                if (fUseCachedGrammar)
3908                  importSchemaInfo = fCachedSchemaInfoList->get(sysId, uriId);
3909
3910                if (!importSchemaInfo && !fToCacheGrammar)
3911                  importSchemaInfo = fSchemaInfoList->get(sysId, uriId);
3912
3913                if (importSchemaInfo)
3914                {
3915                  // We haven't added any new grammars so it is safe to just
3916                  // return.
3917                  //
3918                  return;
3919                }
3920
3921                // Should just issue warning if the schema is not found
3922                bool flag = srcToFill->getIssueFatalErrorIfNotFound();
3923                srcToFill->setIssueFatalErrorIfNotFound(false);
3924
3925                parser.parse(*srcToFill);
3926
3927                // Reset the InputSource
3928                srcToFill->setIssueFatalErrorIfNotFound(flag);
3929
3930                if (parser.getSawFatal() && fExitOnFirstFatal)
3931                        emitError(XMLErrs::SchemaScanFatalError);
3932
3933                DOMDocument* document = parser.getDocument(); //Our Grammar
3934
3935                if (document != 0) {
3936
3937                        DOMElement* root = document->getDocumentElement();// This is what we pass to TraverserSchema
3938                        if (root != 0)
3939                        {
3940                                const XMLCh* newUri = root->getAttribute(SchemaSymbols::fgATT_TARGETNAMESPACE);
3941                                bool newGrammar = false;
3942                                if (!XMLString::equals(newUri, uri)) {
3943                                        if (fValidate || fValScheme == Val_Auto) {
3944                                                fValidator->emitError(XMLValid::WrongTargetNamespace, loc, uri);
3945                                        }
3946
3947                                        grammar = fGrammarResolver->getGrammar(newUri);
3948                                        newGrammar = true;
3949                                }
3950
3951                                if (!grammar ||
3952                                        grammar->getGrammarType() == Grammar::DTDGrammarType ||
3953                                        (getHandleMultipleImports() &&
3954                                         ((XMLSchemaDescription*) grammar->getGrammarDescription())->
3955                                         getContextType () == XMLSchemaDescription::CONTEXT_IMPORT))
3956                                {
3957                                        // If we switched namespace URI, recheck the schema info.
3958                                        //
3959                                        if (newGrammar)
3960                                        {
3961                                                #ifdef TEST_NAMESPACE_RESOLVER
3962                                                unsigned int newUriId = fUriResolver->resolveUriId(newUri);
3963                                                #else
3964                                                unsigned int newUriId = (newUri && *newUri) ? fURIStringPool->addOrFind(newUri) : fEmptyNamespaceId;
3965                                                #endif
3966                                                if (fUseCachedGrammar)
3967                                                        importSchemaInfo = fCachedSchemaInfoList->get(sysId, newUriId);
3968
3969                                                if (!importSchemaInfo && !fToCacheGrammar)
3970                                                        importSchemaInfo = fSchemaInfoList->get(sysId, newUriId);
3971
3972                                                if (importSchemaInfo)
3973                                                        return;
3974                                        }
3975
3976                                        //  Since we have seen a grammar, set our validation flag
3977                                        //  at this point if the validation scheme is auto
3978                                        if (fValScheme == Val_Auto && !fValidate) {
3979                                                fValidate = true;
3980                                                fElemStack.setValidationFlag(fValidate);
3981                                        }
3982
3983                                        bool grammarFound = grammar &&
3984                                          grammar->getGrammarType() == Grammar::SchemaGrammarType;
3985
3986                                        SchemaGrammar* schemaGrammar;
3987
3988                                        if (grammarFound) {
3989                                          schemaGrammar = (SchemaGrammar*) grammar;
3990                                        }
3991                                        else {
3992                                          schemaGrammar = new (fGrammarPoolMemoryManager) SchemaGrammar(fGrammarPoolMemoryManager);
3993                                        }
3994
3995                                        XMLSchemaDescription* gramDesc = (XMLSchemaDescription*) schemaGrammar->getGrammarDescription();
3996
3997                                        gramDesc->setContextType(XMLSchemaDescription::CONTEXT_PREPARSE);
3998                                        gramDesc->setLocationHints(sysId);
3999
4000                                        TraverseSchema traverseSchema
4001                                        (
4002                                                root
4003                                                #ifdef TEST_NAMESPACE_RESOLVER
4004                                                , NULL
4005                                                #else
4006                                                , fURIStringPool
4007                                                #endif
4008                                                , schemaGrammar
4009                                                , fGrammarResolver
4010                                                , fUseCachedGrammar ? fCachedSchemaInfoList : fSchemaInfoList
4011                                                , fToCacheGrammar ? fCachedSchemaInfoList : fSchemaInfoList
4012                                                , this
4013                                                , sysId
4014                                                , fEntityHandler
4015                                                , fErrorReporter
4016                                                , fMemoryManager
4017                                                , grammarFound
4018                                        );
4019
4020                                        // Reset the now invalid schema roots in the collected
4021                                        // schema info entries.
4022                                        //
4023                                        {
4024                                          RefHash2KeysTableOfEnumerator<SchemaInfo> i (
4025                                                fToCacheGrammar ? fCachedSchemaInfoList : fSchemaInfoList);
4026
4027                                          while (i.hasMoreElements ())
4028                                                i.nextElement().resetRoot ();
4029                                        }
4030
4031                                        if (fGrammarType == Grammar::DTDGrammarType) {
4032                                                fGrammar = schemaGrammar;
4033                                                fGrammarType = Grammar::SchemaGrammarType;
4034                                                fValidator->setGrammar(fGrammar);
4035                                        }
4036
4037                                        if (fValidate) {
4038                                                //  validate the Schema scan so far
4039                                                fValidator->preContentValidation(false);
4040                                        }
4041                                }
4042                        }
4043                }
4044          }
4045        }
4046        else
4047        {
4048                //  Since we have seen a grammar, set our validation flag
4049                //  at this point if the validation scheme is auto
4050                if (fValScheme == Val_Auto && !fValidate) {
4051                        fValidate = true;
4052                        fElemStack.setValidationFlag(fValidate);
4053                }
4054
4055                // we have seen a schema, so set up the fValidator as fSchemaValidator
4056                if (fGrammarType == Grammar::DTDGrammarType) {
4057                        fGrammar = grammar;
4058                        fGrammarType = Grammar::SchemaGrammarType;
4059                        fValidator->setGrammar(fGrammar);
4060                }
4061        }
4062        // update fModel; rely on the grammar resolver to do this
4063        // efficiently
4064        if(getPSVIHandler())
4065                fModel = fGrammarResolver->getXSModel();
4066#endif
4067}
4068
4069InputSource* SGXMLScanner::resolveSystemId(const XMLCh* const sysId
4070                                                                                  ,const XMLCh* const pubId)
4071{
4072#if defined(SGXML_SCANNER_DEPRECATED)
4073        DEPRECATED_FEATURE_IN_ICXML;
4074#else
4075        //Normalize sysId
4076        XMLBufBid nnSys(&fBufMgr);
4077        XMLBuffer& normalizedSysId = nnSys.getBuffer();
4078        XMLString::removeChar(sysId, 0xFFFF, normalizedSysId);
4079        const XMLCh* normalizedURI = normalizedSysId.getRawBuffer();
4080
4081        // Create a buffer for expanding the system id
4082        XMLBufBid bbSys(&fBufMgr);
4083        XMLBuffer& expSysId = bbSys.getBuffer();
4084
4085        //  Allow the entity handler to expand the system id if they choose
4086        //  to do so.
4087        InputSource* srcToFill = 0;
4088        if (fEntityHandler)
4089        {
4090                if (!fEntityHandler->expandSystemId(normalizedURI, expSysId))
4091                        expSysId.set(normalizedURI);
4092
4093                ReaderMgr::LastExtEntityInfo lastInfo;
4094                fReaderMgr.getLastExtEntityInfo(lastInfo);
4095                XMLResourceIdentifier resourceIdentifier(XMLResourceIdentifier::ExternalEntity,
4096                                                        expSysId.getRawBuffer(), 0, pubId, lastInfo.systemId,
4097                                                        &fReaderMgr);
4098                srcToFill = fEntityHandler->resolveEntity(&resourceIdentifier);
4099        }
4100        else
4101        {
4102                expSysId.set(normalizedURI);
4103        }
4104
4105        //  If they didn't create a source via the entity handler, then we
4106        //  have to create one on our own.
4107        if (!srcToFill)
4108        {
4109                if (fDisableDefaultEntityResolution)
4110                        return 0;
4111
4112                ReaderMgr::LastExtEntityInfo lastInfo;
4113                fReaderMgr.getLastExtEntityInfo(lastInfo);
4114
4115                XMLURL urlTmp(fMemoryManager);
4116                if ((!urlTmp.setURL(lastInfo.systemId, expSysId.getRawBuffer(), urlTmp)) ||
4117                        (urlTmp.isRelative()))
4118                {
4119                        if (!fStandardUriConformant)
4120                        {
4121                                XMLBufBid  ddSys(&fBufMgr);
4122                                XMLBuffer& resolvedSysId = ddSys.getBuffer();
4123                                XMLUri::normalizeURI(expSysId.getRawBuffer(), resolvedSysId);
4124
4125                                srcToFill = new (fMemoryManager) LocalFileInputSource
4126                                (
4127                                        lastInfo.systemId
4128                                        , resolvedSysId.getRawBuffer()
4129                                        , fMemoryManager
4130                                );
4131                        }
4132                        else
4133                                ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_MalformedURL, fMemoryManager);
4134                }
4135                else
4136                {
4137                        if (fStandardUriConformant && urlTmp.hasInvalidChar())
4138                                ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_MalformedURL, fMemoryManager);
4139                        srcToFill = new (fMemoryManager) URLInputSource(urlTmp, fMemoryManager);
4140                }
4141        }
4142
4143        return srcToFill;
4144#endif
4145}
4146
4147
4148// ---------------------------------------------------------------------------
4149//  SGXMLScanner: Private grammar preparsing methods
4150// ---------------------------------------------------------------------------
4151Grammar* SGXMLScanner::loadXMLSchemaGrammar(const InputSource& src,
4152                                                                                  const bool toCache)
4153{
4154#if defined(SGXML_SCANNER_DEPRECATED)
4155        DEPRECATED_FEATURE_IN_ICXML;
4156#else
4157   // Reset the validators
4158        fSchemaValidator->reset();
4159        fSchemaValidator->setErrorReporter(fErrorReporter);
4160        fSchemaValidator->setExitOnFirstFatal(fExitOnFirstFatal);
4161        fSchemaValidator->setGrammarResolver(fGrammarResolver);
4162
4163        if (fValidatorFromUser)
4164                fValidator->reset();
4165
4166        XSDDOMParser parser(0, fMemoryManager, 0);
4167
4168        parser.setValidationScheme(XercesDOMParser::Val_Never);
4169        parser.setDoNamespaces(true);
4170        parser.setUserEntityHandler(fEntityHandler);
4171        parser.setUserErrorReporter(fErrorReporter);
4172
4173        // Should just issue warning if the schema is not found
4174        bool flag = src.getIssueFatalErrorIfNotFound();
4175        ((InputSource&) src).setIssueFatalErrorIfNotFound(false);
4176
4177        parser.parse(src);
4178
4179        // Reset the InputSource
4180        ((InputSource&) src).setIssueFatalErrorIfNotFound(flag);
4181
4182        if (parser.getSawFatal() && fExitOnFirstFatal)
4183                emitError(XMLErrs::SchemaScanFatalError);
4184
4185        DOMDocument* document = parser.getDocument(); //Our Grammar
4186
4187        if (document != 0) {
4188
4189                DOMElement* root = document->getDocumentElement();// This is what we pass to TraverserSchema
4190                if (root != 0)
4191                {
4192                        const XMLCh* nsUri = root->getAttribute(SchemaSymbols::fgATT_TARGETNAMESPACE);
4193                        Grammar* grammar = fGrammarResolver->getGrammar(nsUri);
4194
4195                        // Check if this exact schema has already been seen.
4196                        //
4197                        const XMLCh* sysId = src.getSystemId();
4198                        SchemaInfo* importSchemaInfo = 0;
4199
4200                        if (grammar)
4201                        {
4202                                if (nsUri && *nsUri)
4203                                {
4204                                        #ifdef TEST_NAMESPACE_RESOLVER
4205                                        unsigned int nsUriId = fUriResolver->resolveUriId(nsUri);
4206                                        #else
4207                                        unsigned int nsUriId = fURIStringPool->addOrFind(nsUri);
4208                                        #endif
4209                                        importSchemaInfo = fCachedSchemaInfoList->get(sysId, nsUriId);
4210                                }
4211                                else
4212                                {
4213                                        #ifdef TEST_NAMESPACE_RESOLVER
4214                                        importSchemaInfo = fCachedSchemaInfoList->get(sysId, XMLNamespaceResolver::fEmptyUriId);
4215                                        #else
4216                                        importSchemaInfo = fCachedSchemaInfoList->get(sysId, fEmptyNamespaceId);
4217                                        #endif
4218                                }
4219                        }
4220
4221                        if (!importSchemaInfo)
4222                        {
4223                          bool grammarFound = grammar &&
4224                                grammar->getGrammarType() == Grammar::SchemaGrammarType &&
4225                                getHandleMultipleImports();
4226
4227                          SchemaGrammar* schemaGrammar;
4228
4229                          if (grammarFound)
4230                                schemaGrammar = (SchemaGrammar*) grammar;
4231                          else
4232                                schemaGrammar = new (fGrammarPoolMemoryManager) SchemaGrammar(fGrammarPoolMemoryManager);
4233
4234                          XMLSchemaDescription* gramDesc = (XMLSchemaDescription*) schemaGrammar->getGrammarDescription();
4235                          gramDesc->setContextType(XMLSchemaDescription::CONTEXT_PREPARSE);
4236                          gramDesc->setLocationHints(sysId);
4237
4238                          TraverseSchema traverseSchema
4239                                (
4240                                  root
4241                                  #ifdef TEST_NAMESPACE_RESOLVER
4242                                  , NULL
4243                                  #else
4244                                  , fURIStringPool
4245                                  #endif
4246                                  , schemaGrammar
4247                                  , fGrammarResolver
4248                                  , fCachedSchemaInfoList
4249                                  , toCache ? fCachedSchemaInfoList : fSchemaInfoList
4250                                  , this
4251                                  , sysId
4252                                  , fEntityHandler
4253                                  , fErrorReporter
4254                                  , fMemoryManager
4255                                  , grammarFound
4256                                );
4257
4258                          grammar = schemaGrammar;
4259
4260                          // Reset the now invalid schema roots in the collected
4261                          // schema info entries.
4262                          //
4263                          {
4264                                RefHash2KeysTableOfEnumerator<SchemaInfo> i (
4265                                  toCache ? fCachedSchemaInfoList : fSchemaInfoList);
4266
4267                                while (i.hasMoreElements ())
4268                                  i.nextElement().resetRoot ();
4269                          }
4270                        }
4271
4272                        if (fValidate) {
4273                          //  validate the Schema scan so far
4274                          fValidator->setGrammar(grammar);
4275                          fValidator->preContentValidation(false);
4276                        }
4277
4278                        if (toCache) {
4279                          fGrammarResolver->cacheGrammars();
4280                        }
4281
4282                        if(getPSVIHandler())
4283                          fModel = fGrammarResolver->getXSModel();
4284
4285                        return grammar;
4286                }
4287        }
4288
4289        return 0;
4290#endif
4291}
4292
4293
4294
4295// ---------------------------------------------------------------------------
4296//  SGXMLScanner: Private parsing methods
4297// ---------------------------------------------------------------------------
4298
4299//  This method is called to do a raw scan of an attribute value. It does not
4300//  do normalization (since we don't know their types yet.) It just scans the
4301//  value and does entity expansion.
4302//
4303//  End of entity's must be dealt with here. During DTD scan, they can come
4304//  from external entities. During content, they can come from any entity.
4305//  We just eat the end of entity and continue with our scan until we come
4306//  to the closing quote. If an unterminated value causes us to go through
4307//  subsequent entities, that will cause errors back in the calling code,
4308//  but there's little we can do about it here.
4309bool SGXMLScanner::basicAttrValueScan(const XMLCh* const attrName, XMLBuffer& toFill)
4310{
4311#if defined(SGXML_SCANNER_DEPRECATED)
4312        DEPRECATED_FEATURE_IN_ICXML;
4313#else
4314        // Reset the target buffer
4315        toFill.reset();
4316
4317        // Get the next char which must be a single or double quote
4318        XMLCh quoteCh;
4319        if (!fReaderMgr.skipIfQuote(quoteCh))
4320                return false;
4321
4322        //  We have to get the current reader because we have to ignore closing
4323        //  quotes until we hit the same reader again.
4324        const XMLSize_t curReader = fReaderMgr.getCurrentReaderNum();
4325
4326        //  Loop until we get the attribute value. Note that we use a double
4327        //  loop here to avoid the setup/teardown overhead of the exception
4328        //  handler on every round.
4329        while (true)
4330        {
4331                try
4332                {
4333                        while(true)
4334                        {
4335                                XMLCh nextCh = fReaderMgr.getNextChar();
4336
4337                                if (nextCh != quoteCh)
4338                                {
4339                                        if (nextCh != chAmpersand)
4340                                        {
4341                                                if ((nextCh < 0xD800) || (nextCh > 0xDFFF))
4342                                                {
4343                                                        // Its got to at least be a valid XML character
4344                                                        if (!fReaderMgr.getCurrentReader()->isXMLChar(nextCh))
4345                                                        {
4346                                                                if (nextCh == 0)
4347                                                                        ThrowXMLwithMemMgr(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF, fMemoryManager);
4348
4349                                                                XMLCh tmpBuf[9];
4350                                                                XMLString::binToText
4351                                                                (
4352                                                                        nextCh
4353                                                                        , tmpBuf
4354                                                                        , 8
4355                                                                        , 16
4356                                                                        , fMemoryManager
4357                                                                );
4358                                                                emitError(XMLErrs::InvalidCharacterInAttrValue, attrName, tmpBuf);
4359                                                        }
4360                                                }
4361                                                else // its a surrogate
4362                                                {
4363                                                        // Deal with surrogate pairs
4364
4365                                                        //  we expect a a leading surrogate.
4366                                                        if (nextCh <= 0xDBFF)
4367                                                        {
4368                                                                toFill.append(nextCh);
4369
4370                                                                //  process the trailing surrogate
4371                                                                nextCh = fReaderMgr.getNextChar();
4372
4373                                                                //  it should be a trailing surrogate.
4374                                                                if ((nextCh < 0xDC00) || (nextCh > 0xDFFF))
4375                                                                {
4376                                                                        emitError(XMLErrs::Expected2ndSurrogateChar);
4377                                                                }
4378                                                        } else
4379                                                        {
4380                                                                //  Its a trailing surrogate, but we are not expecting it
4381                                                                emitError(XMLErrs::Unexpected2ndSurrogateChar);
4382                                                        }
4383                                                }
4384                                        }
4385                                        else // its a chAmpersand
4386                                        {
4387                                                //  Check for an entity ref . We ignore the empty flag in
4388                                                //  this one.
4389
4390                                                bool    escaped;
4391                                                XMLCh   firstCh;
4392                                                XMLCh   secondCh
4393                                                        ;
4394                                                // If it was not returned directly, then jump back up
4395                                                if (scanEntityRef(true, firstCh, secondCh, escaped) == EntityExp_Returned)
4396                                                {
4397                                                        //  If it was escaped, then put in a 0xFFFF value. This will
4398                                                        //  be used later during validation and normalization of the
4399                                                        //  value to know that the following character was via an
4400                                                        //  escape char.
4401                                                        if (escaped)
4402                                                                toFill.append(0xFFFF);
4403
4404                                                        toFill.append(firstCh);
4405                                                        if (secondCh)
4406                                                                toFill.append(secondCh);
4407                                                }
4408                                                continue;
4409                                        }
4410                                } else // its a quoteCh
4411                                {
4412                                        //  Check for our ending quote. It has to be in the same entity
4413                                        //  as where we started. Quotes in nested entities are ignored.
4414
4415                                        if (curReader == fReaderMgr.getCurrentReaderNum())
4416                                        {
4417                                                return true;
4418                                        }
4419
4420                                        // Watch for spillover into a previous entity
4421                                        if (curReader > fReaderMgr.getCurrentReaderNum())
4422                                        {
4423                                                emitError(XMLErrs::PartialMarkupInEntity);
4424                                                return false;
4425                                        }
4426                                }
4427
4428                                // add it to the buffer
4429                                toFill.append(nextCh);
4430
4431                        }
4432                }
4433                catch(const EndOfEntityException&)
4434                {
4435                        // Just eat it and continue.
4436                }
4437        }
4438        return true;
4439#endif
4440}
4441
4442
4443//  This method scans a CDATA section. It collects the character into one
4444//  of the temp buffers and calls the document handler, if any, with the
4445//  characters. It assumes that the <![CDATA string has been scanned before
4446//  this call.
4447void SGXMLScanner::scanCDSection()
4448{
4449#if defined(SGXML_SCANNER_DEPRECATED)
4450        DEPRECATED_FEATURE_IN_ICXML;
4451#else
4452        static const XMLCh CDataClose[] =
4453        {
4454                        chCloseSquare, chCloseAngle, chNull
4455        };
4456
4457        //  The next character should be the opening square bracket. If not
4458        //  issue an error, but then try to recover by skipping any whitespace
4459        //  and checking again.
4460        if (!fReaderMgr.skippedChar(chOpenSquare))
4461        {
4462                emitError(XMLErrs::ExpectedOpenSquareBracket);
4463                fReaderMgr.skipPastSpaces();
4464
4465                // If we still don't find it, then give up, else keep going
4466                if (!fReaderMgr.skippedChar(chOpenSquare))
4467                        return;
4468        }
4469
4470        // Get a buffer for this
4471        XMLBufBid bbCData(&fBufMgr);
4472
4473        //  We just scan forward until we hit the end of CDATA section sequence.
4474        //  CDATA is effectively a big escape mechanism so we don't treat markup
4475        //  characters specially here.
4476        bool            emittedError = false;
4477        bool    gotLeadingSurrogate = false;
4478
4479        // Get the character data opts for the current element
4480        XMLElementDecl::CharDataOpts charOpts = XMLElementDecl::AllCharData;
4481        // And see if the current element is a 'Children' style content model
4482        ComplexTypeInfo *currType = ((SchemaValidator*)fValidator)->getCurrentTypeInfo();
4483        if(currType)
4484        {
4485                SchemaElementDecl::ModelTypes modelType = (SchemaElementDecl::ModelTypes) currType->getContentType();
4486                if(modelType == SchemaElementDecl::Children ||
4487                   modelType == SchemaElementDecl::ElementOnlyEmpty)
4488                        charOpts = XMLElementDecl::SpacesOk;
4489                else if(modelType == SchemaElementDecl::Empty)
4490                        charOpts = XMLElementDecl::NoCharData;
4491        }
4492
4493        // should not be necessary when PSVI on element decl removed
4494        const ElemStack::StackElem* topElem = fElemStack.topElement();
4495
4496        while (true)
4497        {
4498                const XMLCh nextCh = fReaderMgr.getNextChar();
4499
4500                // Watch for unexpected end of file
4501                if (!nextCh)
4502                {
4503                        emitError(XMLErrs::UnterminatedCDATASection);
4504                        ThrowXMLwithMemMgr(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF, fMemoryManager);
4505                }
4506
4507                if (fValidate && fStandalone && (fReaderMgr.getCurrentReader()->isWhitespace(nextCh)))
4508                {
4509                        // This document is standalone; this ignorable CDATA whitespace is forbidden.
4510                        // XML 1.0, Section 2.9
4511                        // And see if the current element is a 'Children' style content model
4512                        if (topElem->fThisElement->isExternal()) {
4513
4514                                if (charOpts == XMLElementDecl::SpacesOk) // Element Content
4515                                {
4516                                        // Error - standalone should have a value of "no" as whitespace detected in an
4517                                        // element type with element content whose element declaration was external
4518                                        fValidator->emitError(XMLValid::NoWSForStandalone);
4519                                        if (getPSVIHandler())
4520                                        {
4521                                                // REVISIT:
4522                                                // PSVIElement->setValidity(PSVIItem::VALIDITY_INVALID);
4523                                        }
4524                                }
4525                        }
4526                }
4527
4528                //  If this is a close square bracket it could be our closing
4529                //  sequence.
4530                if (nextCh == chCloseSquare && fReaderMgr.skippedString(CDataClose))
4531                {
4532                        //  make sure we were not expecting a trailing surrogate.
4533                        if (gotLeadingSurrogate) {
4534                                emitError(XMLErrs::Expected2ndSurrogateChar);
4535                        }
4536
4537                        XMLSize_t xsLen = bbCData.getLen();
4538                        const XMLCh* xsNormalized = bbCData.getRawBuffer();
4539                        if (fValidate) {
4540
4541                                DatatypeValidator* tempDV = ((SchemaValidator*) fValidator)->getCurrentDatatypeValidator();
4542                                if (tempDV && tempDV->getWSFacet() != DatatypeValidator::PRESERVE)
4543                                {
4544                                        // normalize the character according to schema whitespace facet
4545                                        ((SchemaValidator*) fValidator)->normalizeWhiteSpace(tempDV, xsNormalized, fWSNormalizeBuf);
4546                                        xsNormalized = fWSNormalizeBuf.getRawBuffer();
4547                                        xsLen = fWSNormalizeBuf.getLen();
4548                                }
4549
4550                                // tell the schema validation about the character data for checkContent later
4551                                ((SchemaValidator*)fValidator)->setDatatypeBuffer(xsNormalized);
4552
4553                                if (charOpts != XMLElementDecl::AllCharData)
4554                                {
4555                                        // They definitely cannot handle any type of char data
4556                                        fValidator->emitError(XMLValid::NoCharDataInCM);
4557                                        if (getPSVIHandler())
4558                                        {
4559                                                // REVISIT:
4560                                                // PSVIElement->setValidity(PSVIItem::VALIDITY_INVALID);
4561                                        }
4562                                }
4563                        }
4564
4565                        // call all active identity constraints
4566                        if (toCheckIdentityConstraint() && fICHandler->getMatcherCount()) {
4567                                fContent.append(xsNormalized, xsLen);
4568                        }
4569
4570                        // If we have a doc handler, call it
4571                        if (fDocHandler)
4572                        {
4573                                if (fNormalizeData) {
4574                                        fDocHandler->docCharacters(xsNormalized, xsLen, true);
4575                                }
4576                                else {
4577                                        fDocHandler->docCharacters(
4578                                                bbCData.getRawBuffer(), bbCData.getLen(), true
4579                                        );
4580                                }
4581                        }
4582
4583                        // And we are done
4584                        break;
4585                }
4586
4587                //  Make sure its a valid character. But if we've emitted an error
4588                //  already, don't bother with the overhead since we've already told
4589                //  them about it.
4590                if (!emittedError)
4591                {
4592                        // Deal with surrogate pairs
4593                        if ((nextCh >= 0xD800) && (nextCh <= 0xDBFF))
4594                        {
4595                                //  Its a leading surrogate. If we already got one, then
4596                                //  issue an error, else set leading flag to make sure that
4597                                //  we look for a trailing next time.
4598                                if (gotLeadingSurrogate)
4599                                        emitError(XMLErrs::Expected2ndSurrogateChar);
4600                                else
4601                                        gotLeadingSurrogate = true;
4602                        }
4603                        else
4604                        {
4605                                //  If its a trailing surrogate, make sure that we are
4606                                //  prepared for that. Else, its just a regular char so make
4607                                //  sure that we were not expected a trailing surrogate.
4608                                if ((nextCh >= 0xDC00) && (nextCh <= 0xDFFF))
4609                                {
4610                                        // Its trailing, so make sure we were expecting it
4611                                        if (!gotLeadingSurrogate)
4612                                                emitError(XMLErrs::Unexpected2ndSurrogateChar);
4613                                }
4614                                else
4615                                {
4616                                        //  Its just a char, so make sure we were not expecting a
4617                                        //  trailing surrogate.
4618                                        if (gotLeadingSurrogate)
4619                                                emitError(XMLErrs::Expected2ndSurrogateChar);
4620
4621                                        // Its got to at least be a valid XML character
4622                                        else if (!fReaderMgr.getCurrentReader()->isXMLChar(nextCh))
4623                                        {
4624                                                XMLCh tmpBuf[9];
4625                                                XMLString::binToText
4626                                                (
4627                                                        nextCh
4628                                                        , tmpBuf
4629                                                        , 8
4630                                                        , 16
4631                                                        , fMemoryManager
4632                                                );
4633                                                emitError(XMLErrs::InvalidCharacter, tmpBuf);
4634                                                emittedError = true;
4635                                        }
4636                                }
4637                                gotLeadingSurrogate = false;
4638                        }
4639                }
4640
4641                // Add it to the buffer
4642                bbCData.append(nextCh);
4643        }
4644#endif
4645}
4646
4647
4648void SGXMLScanner::scanCharData(XMLBuffer& toUse)
4649{
4650#if defined(SGXML_SCANNER_DEPRECATED)
4651        DEPRECATED_FEATURE_IN_ICXML;
4652#else
4653        //  We have to watch for the stupid ]]> sequence, which is illegal in
4654        //  character data. So this is a little state machine that handles that.
4655        enum States
4656        {
4657                State_Waiting
4658                , State_GotOne
4659                , State_GotTwo
4660        };
4661
4662        // Reset the buffer before we start
4663        toUse.reset();
4664
4665        // Turn on the 'throw at end' flag of the reader manager
4666        ThrowEOEJanitor jan(&fReaderMgr, true);
4667
4668        //  In order to be more efficient we have to use kind of a deeply nested
4669        //  set of blocks here. The outer block puts on a try and catches end of
4670        //  entity exceptions. The inner loop is the per-character loop. If we
4671        //  put the try inside the inner loop, it would work but would require
4672        //  the exception handling code setup/teardown code to be invoked for
4673        //  each character.
4674        XMLCh   nextCh;
4675        XMLCh   secondCh = 0;
4676        States  curState = State_Waiting;
4677        bool    escaped = false;
4678        bool    gotLeadingSurrogate = false;
4679        bool    notDone = true;
4680        while (notDone)
4681        {
4682                try
4683                {
4684                        while (true)
4685                        {
4686                                //  Eat through as many plain content characters as possible without
4687                                //  needing special handling.  Moving most content characters here,
4688                                //  in this one call, rather than running the overall loop once
4689                                //  per content character, is a speed optimization.
4690                                if (curState == State_Waiting  &&  !gotLeadingSurrogate)
4691                                {
4692                                         fReaderMgr.movePlainContentChars(toUse);
4693                                }
4694
4695                                // Try to get another char from the source
4696                                //   The code from here on down covers all contengencies,
4697                                if (!fReaderMgr.getNextCharIfNot(chOpenAngle, nextCh))
4698                                {
4699                                        // If we were waiting for a trailing surrogate, its an error
4700                                        if (gotLeadingSurrogate)
4701                                                emitError(XMLErrs::Expected2ndSurrogateChar);
4702
4703                                        notDone = false;
4704                                        break;
4705                                }
4706
4707                                //  Watch for a reference. Note that the escapement mechanism
4708                                //  is ignored in this content.
4709                                escaped = false;
4710                                if (nextCh == chAmpersand)
4711                                {
4712                                        sendCharData(toUse);
4713
4714                                        // Turn off the throwing at the end of entity during this
4715                                        ThrowEOEJanitor jan(&fReaderMgr, false);
4716
4717                                        if (scanEntityRef(false, nextCh, secondCh, escaped) != EntityExp_Returned)
4718                                        {
4719                                                gotLeadingSurrogate = false;
4720                                                continue;
4721                                        }
4722                                }
4723                                else if ((nextCh >= 0xD800) && (nextCh <= 0xDBFF))
4724                                {
4725                                        // Deal with surrogate pairs
4726                                        //  Its a leading surrogate. If we already got one, then
4727                                        //  issue an error, else set leading flag to make sure that
4728                                        //  we look for a trailing next time.
4729                                        if (gotLeadingSurrogate)
4730                                                emitError(XMLErrs::Expected2ndSurrogateChar);
4731                                        else
4732                                                gotLeadingSurrogate = true;
4733                                }
4734                                else
4735                                {
4736                                        //  If its a trailing surrogate, make sure that we are
4737                                        //  prepared for that. Else, its just a regular char so make
4738                                        //  sure that we were not expected a trailing surrogate.
4739                                        if ((nextCh >= 0xDC00) && (nextCh <= 0xDFFF))
4740                                        {
4741                                                // Its trailing, so make sure we were expecting it
4742                                                if (!gotLeadingSurrogate)
4743                                                        emitError(XMLErrs::Unexpected2ndSurrogateChar);
4744                                        }
4745                                        else
4746                                        {
4747                                                //  Its just a char, so make sure we were not expecting a
4748                                                //  trailing surrogate.
4749                                                if (gotLeadingSurrogate)
4750                                                        emitError(XMLErrs::Expected2ndSurrogateChar);
4751
4752                                                // Make sure the returned char is a valid XML char
4753                                                if (!fReaderMgr.getCurrentReader()->isXMLChar(nextCh))
4754                                                {
4755                                                        XMLCh tmpBuf[9];
4756                                                        XMLString::binToText
4757                                                        (
4758                                                                nextCh
4759                                                                , tmpBuf
4760                                                                , 8
4761                                                                , 16
4762                                                                , fMemoryManager
4763                                                        );
4764                                                        emitError(XMLErrs::InvalidCharacter, tmpBuf);
4765                                                }
4766                                        }
4767                                        gotLeadingSurrogate = false;
4768                                }
4769
4770                                // Keep the state machine up to date
4771                                if (!escaped)
4772                                {
4773                                        if (nextCh == chCloseSquare)
4774                                        {
4775                                                if (curState == State_Waiting)
4776                                                        curState = State_GotOne;
4777                                                else if (curState == State_GotOne)
4778                                                        curState = State_GotTwo;
4779                                        }
4780                                        else if (nextCh == chCloseAngle)
4781                                        {
4782                                                if (curState == State_GotTwo)
4783                                                        emitError(XMLErrs::BadSequenceInCharData);
4784                                                curState = State_Waiting;
4785                                        }
4786                                        else
4787                                        {
4788                                                curState = State_Waiting;
4789                                        }
4790                                }
4791                                else
4792                                {
4793                                        curState = State_Waiting;
4794                                }
4795
4796                                // Add this char to the buffer
4797                                toUse.append(nextCh);
4798
4799                                if (secondCh)
4800                                {
4801                                        toUse.append(secondCh);
4802                                        secondCh=0;
4803                                }
4804                        }
4805                }
4806                catch(const EndOfEntityException& toCatch)
4807                {
4808                        //  Some entity ended, so we have to send any accumulated
4809                        //  chars and send an end of entity event.
4810                        sendCharData(toUse);
4811                        gotLeadingSurrogate = false;
4812
4813                        if (fDocHandler)
4814                                fDocHandler->endEntityReference(toCatch.getEntity());
4815                }
4816        }
4817
4818        // Check the validity constraints as per XML 1.0 Section 2.9
4819        if (fValidate && fStandalone)
4820        {
4821                // See if the text contains whitespace
4822                // Get the raw data we need for the callback
4823                const XMLCh* rawBuf = toUse.getRawBuffer();
4824                const XMLSize_t len = toUse.getLen();
4825                const bool isSpaces = fReaderMgr.getCurrentReader()->containsWhiteSpace(rawBuf, len);
4826
4827                if (isSpaces)
4828                {
4829                        // And see if the current element is a 'Children' style content model
4830                        const ElemStack::StackElem* topElem = fElemStack.topElement();
4831
4832                        if (topElem->fThisElement->isExternal()) {
4833
4834                                // Get the character data opts for the current element
4835                                XMLElementDecl::CharDataOpts charOpts = XMLElementDecl::AllCharData;
4836                                // And see if the current element is a 'Children' style content model
4837                                ComplexTypeInfo *currType = ((SchemaValidator*)fValidator)->getCurrentTypeInfo();
4838                                if(currType)
4839                                {
4840                                        SchemaElementDecl::ModelTypes modelType = (SchemaElementDecl::ModelTypes) currType->getContentType();
4841                                        if(modelType == SchemaElementDecl::Children ||
4842                                           modelType == SchemaElementDecl::ElementOnlyEmpty)
4843                                                charOpts = XMLElementDecl::SpacesOk;
4844                                }
4845
4846                                if (charOpts == XMLElementDecl::SpacesOk)  // => Element Content
4847                                {
4848                                        // Error - standalone should have a value of "no" as whitespace detected in an
4849                                        // element type with element content whose element declaration was external
4850                                        //
4851                                        fValidator->emitError(XMLValid::NoWSForStandalone);
4852                                        if (getPSVIHandler())
4853                                        {
4854                                                // REVISIT:
4855                                                // PSVIElement->setValidity(PSVIItem::VALIDITY_INVALID);
4856                                        }
4857                                }
4858                        }
4859                }
4860        }
4861        // Send any char data that we accumulated into the buffer
4862        sendCharData(toUse);
4863#endif
4864}
4865
4866
4867//  This method will scan a general/character entity ref. It will either
4868//  expand a char ref and return it directly, or push a reader for a general
4869//  entity.
4870//
4871//  The return value indicates whether the char parameters hold the value
4872//  or whether the value was pushed as a reader, or that it failed.
4873//
4874//  The escaped flag tells the caller whether the returned parameter resulted
4875//  from a character reference, which escapes the character in some cases. It
4876//  only makes any difference if the return value indicates the value was
4877//  returned directly.
4878SGXMLScanner::EntityExpRes
4879SGXMLScanner::scanEntityRef(  const   bool
4880                                                        ,       XMLCh&  firstCh
4881                                                        ,       XMLCh&  secondCh
4882                                                        ,       bool&   escaped)
4883{
4884#if defined(SGXML_SCANNER_DEPRECATED)
4885        DEPRECATED_FEATURE_IN_ICXML;
4886#else
4887        // Assume no escape
4888        secondCh = 0;
4889        escaped = false;
4890
4891        // We have to insure that its all in one entity
4892        const XMLSize_t curReader = fReaderMgr.getCurrentReaderNum();
4893
4894        //  If the next char is a pound, then its a character reference and we
4895        //  need to expand it always.
4896        if (fReaderMgr.skippedChar(chPound))
4897        {
4898                //  Its a character reference, so scan it and get back the numeric
4899                //  value it represents.
4900                if (!scanCharRef(firstCh, secondCh))
4901                        return EntityExp_Failed;
4902
4903                escaped = true;
4904
4905                if (curReader != fReaderMgr.getCurrentReaderNum())
4906                        emitError(XMLErrs::PartialMarkupInEntity);
4907
4908                return EntityExp_Returned;
4909        }
4910
4911        // Expand it since its a normal entity ref
4912        XMLBufBid bbName(&fBufMgr);
4913        int colonPosition;
4914        if (!fReaderMgr.getQName(bbName.getBuffer(), &colonPosition))
4915        {
4916                if (bbName.isEmpty())
4917                        emitError(XMLErrs::ExpectedEntityRefName);
4918                else
4919                        emitError(XMLErrs::InvalidEntityRefName, bbName.getRawBuffer());
4920                return EntityExp_Failed;
4921        }
4922
4923        //  Next char must be a semi-colon. But if its not, just emit
4924        //  an error and try to continue.
4925        if (!fReaderMgr.skippedChar(chSemiColon))
4926                emitError(XMLErrs::UnterminatedEntityRef, bbName.getRawBuffer());
4927
4928        // Make sure we ended up on the same entity reader as the & char
4929        if (curReader != fReaderMgr.getCurrentReaderNum())
4930                emitError(XMLErrs::PartialMarkupInEntity);
4931
4932        // Look up the name in the general entity pool
4933        // If it does not exist, then obviously an error
4934        if (!fEntityTable->containsKey(bbName.getRawBuffer()))
4935        {
4936                // XML 1.0 Section 4.1
4937                // Well-formedness Constraint for entity not found:
4938                //   In a document without any DTD, a document with only an internal DTD subset which contains no parameter entity references,
4939                //      or a document with "standalone='yes'", for an entity reference that does not occur within the external subset
4940                //      or a parameter entity
4941                if (fStandalone || fHasNoDTD)
4942                        emitError(XMLErrs::EntityNotFound, bbName.getRawBuffer());
4943
4944                return EntityExp_Failed;
4945        }
4946
4947        // here's where we need to check if there's a SecurityManager,
4948        // how many entity references we've had
4949        if(fSecurityManager != 0 && ++fEntityExpansionCount > fEntityExpansionLimit) {
4950                XMLCh expLimStr[32];
4951                XMLString::sizeToText(fEntityExpansionLimit, expLimStr, 31, 10, fMemoryManager);
4952                emitError
4953                (
4954                        XMLErrs::EntityExpansionLimitExceeded
4955                        , expLimStr
4956                );
4957                // there seems nothing better to be done than to reset the entity expansion limit
4958                fEntityExpansionCount = 0;
4959        }
4960
4961        firstCh = fEntityTable->get(bbName.getRawBuffer());
4962        escaped = true;
4963        return EntityExp_Returned;
4964#endif
4965}
4966
4967
4968bool SGXMLScanner::switchGrammar(const XMLCh* const newGrammarNameSpace)
4969{
4970#if defined(SGXML_SCANNER_DEPRECATED)
4971        DEPRECATED_FEATURE_IN_ICXML;
4972#else
4973        Grammar* tempGrammar = fGrammarResolver->getGrammar(newGrammarNameSpace);
4974
4975        if (!tempGrammar) {
4976                tempGrammar = fSchemaGrammar;
4977        }
4978
4979        if (!tempGrammar)
4980                return false;
4981        else {
4982                fGrammar = tempGrammar;
4983                fGrammarType = fGrammar->getGrammarType();
4984                if (fGrammarType == Grammar::DTDGrammarType) {
4985                        ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoDTDValidator, fMemoryManager);
4986                }
4987
4988                fValidator->setGrammar(fGrammar);
4989                return true;
4990        }
4991#endif
4992}
4993
4994// check if we should skip or lax the validation of the element
4995// if skip - no validation
4996// if lax - validate only if the element if found
4997bool SGXMLScanner::laxElementValidation(QName* element, ContentLeafNameTypeVector* cv,
4998                                                                                const XMLContentModel* const cm,
4999                                                                                const XMLSize_t parentElemDepth)
5000{
5001#if defined(SGXML_SCANNER_DEPRECATED)
5002        DEPRECATED_FEATURE_IN_ICXML;
5003#else
5004        bool skipThisOne = false;
5005        bool laxValidation = false;
5006        unsigned int elementURI = element->getURI();
5007        unsigned int currState = fElemState[parentElemDepth];
5008        unsigned int currLoop = fElemLoopState[parentElemDepth];
5009
5010        if (currState == XMLContentModel::gInvalidTrans) {
5011                return laxValidation;
5012        }
5013
5014        #ifdef TEST_NAMESPACE_RESOLVER
5015        SubstitutionGroupComparator comparator(fGrammarResolver, fUriResolver);
5016        #else
5017        SubstitutionGroupComparator comparator(fGrammarResolver, fURIStringPool);
5018        #endif
5019
5020        if (cv) {
5021                XMLSize_t i = 0;
5022                XMLSize_t leafCount = cv->getLeafCount();
5023                unsigned int nextState = 0;
5024
5025                for (; i < leafCount; i++) {
5026
5027                        QName* fElemMap = cv->getLeafNameAt(i);
5028                        unsigned int uri = fElemMap->getURI();
5029                        ContentSpecNode::NodeTypes type = cv->getLeafTypeAt(i);
5030
5031                        if (type == ContentSpecNode::Leaf)
5032                        {
5033                                if (((uri == elementURI)
5034                                        && XMLString::equals(fElemMap->getLocalPart(), element->getLocalPart()))
5035                                        || comparator.isEquivalentTo(element, fElemMap))
5036                                {
5037
5038                                        nextState = cm->getNextState(currState, i);
5039
5040                                        if (nextState != XMLContentModel::gInvalidTrans)
5041                                                break;
5042                                }
5043                        }
5044                        else if ((type & 0x0f) == ContentSpecNode::Any)
5045                        {
5046                                nextState = cm->getNextState(currState, i);
5047                                if (nextState != XMLContentModel::gInvalidTrans)
5048                                        break;
5049                        }
5050                        else if ((type & 0x0f) == ContentSpecNode::Any_Other)
5051                        {
5052                                #ifdef TEST_NAMESPACE_RESOLVER
5053                                if (uri != elementURI && elementURI != XMLNamespaceResolver::fEmptyUriId)
5054                                #else
5055                                if (uri != elementURI && elementURI != fEmptyNamespaceId)
5056                                #endif
5057                                {
5058                                        nextState = cm->getNextState(currState, i);
5059                                        if (nextState != XMLContentModel::gInvalidTrans)
5060                                                break;
5061                                }
5062                        }
5063                        else if ((type & 0x0f) == ContentSpecNode::Any_NS)
5064                        {
5065                                if (uri == elementURI)
5066                                {
5067                                        nextState = cm->getNextState(currState, i);
5068                                        if (nextState != XMLContentModel::gInvalidTrans)
5069                                                break;
5070                                }
5071                        }
5072
5073                } // for
5074
5075                if (i == leafCount) { // no match
5076                        fElemState[parentElemDepth] = XMLContentModel::gInvalidTrans;
5077                        fElemLoopState[parentElemDepth] = 0;
5078                        return laxValidation;
5079                }
5080
5081                ContentSpecNode::NodeTypes type = cv->getLeafTypeAt(i);
5082                if ((type & 0x0f) == ContentSpecNode::Any ||
5083                        (type & 0x0f) == ContentSpecNode::Any_Other ||
5084                        (type & 0x0f) == ContentSpecNode::Any_NS)
5085                {
5086                        if (type == ContentSpecNode::Any_Skip ||
5087                                type == ContentSpecNode::Any_NS_Skip ||
5088                                type == ContentSpecNode::Any_Other_Skip) {
5089                                skipThisOne = true;
5090                        }
5091                        else if (type == ContentSpecNode::Any_Lax ||
5092                                         type == ContentSpecNode::Any_NS_Lax ||
5093                                         type == ContentSpecNode::Any_Other_Lax) {
5094                                laxValidation = true;
5095                        }
5096                }
5097                fElemState[parentElemDepth] = nextState;
5098                fElemLoopState[parentElemDepth] = currLoop;
5099        } // if
5100
5101        if (skipThisOne) {
5102                fValidate = false;
5103                fElemStack.setValidationFlag(fValidate);
5104        }
5105
5106        return laxValidation;
5107#endif
5108}
5109
5110
5111// check if there is an AnyAttribute, and if so, see if we should lax or skip
5112// if skip - no validation
5113// if lax - validate only if the attribute if found
5114bool SGXMLScanner::anyAttributeValidation(SchemaAttDef* attWildCard, unsigned int uriId, bool& skipThisOne, bool& laxValidation)
5115{
5116#if defined(SGXML_SCANNER_DEPRECATED)
5117        DEPRECATED_FEATURE_IN_ICXML;
5118#else
5119        XMLAttDef::AttTypes wildCardType = attWildCard->getType();
5120        bool anyEncountered = false;
5121        skipThisOne = false;
5122        laxValidation = false;
5123        if (wildCardType == XMLAttDef::Any_Any)
5124                anyEncountered = true;
5125        else if (wildCardType == XMLAttDef::Any_Other)
5126        {
5127                #ifdef TEST_NAMESPACE_RESOLVER
5128                anyEncountered = (attWildCard->getAttName()->getURI() != uriId) && (uriId != XMLNamespaceResolver::fEmptyUriId);
5129                #else
5130                anyEncountered = (attWildCard->getAttName()->getURI() != uriId) && (uriId != fEmptyNamespaceId);
5131                #endif
5132        }
5133        else if (wildCardType == XMLAttDef::Any_List)
5134        {
5135                ValueVectorOf<unsigned int>* nameURIList = attWildCard->getNamespaceList();
5136                XMLSize_t listSize = (nameURIList) ? nameURIList->size() : 0;
5137                for (XMLSize_t i = 0; i < listSize; i++)
5138                {
5139                        if (nameURIList->elementAt(i) == uriId)
5140                        {
5141                                anyEncountered = true;
5142                                break;
5143                        }
5144                }
5145        }
5146
5147        if (anyEncountered)
5148        {
5149                XMLAttDef::DefAttTypes   defType   = attWildCard->getDefaultType();
5150                if (defType == XMLAttDef::ProcessContents_Skip)
5151                {
5152                        // attribute should just be bypassed,
5153                        skipThisOne = true;
5154                        if (getPSVIHandler())
5155                        {
5156                                // REVISIT:
5157                                // PSVIAttribute->setValidationAttempted(PSVIItem::VALIDATION_NONE);
5158                        }
5159                }
5160                else if (defType == XMLAttDef::ProcessContents_Lax)
5161                {
5162                        laxValidation = true;
5163                }
5164        }
5165
5166        return anyEncountered;
5167#endif
5168}
5169
5170inline XMLAttDefList& getAttDefList(ComplexTypeInfo* currType, XMLElementDecl* elemDecl)
5171{
5172#if defined(SGXML_SCANNER_DEPRECATED)
5173        DEPRECATED_FEATURE_IN_ICXML;
5174#else
5175        if (currType)
5176                return currType->getAttDefList();
5177        else
5178                return elemDecl->getAttDefList();
5179#endif
5180}
5181
5182void SGXMLScanner::endElementPSVI(SchemaElementDecl* const elemDecl,
5183                                                                  DatatypeValidator* const memberDV)
5184{
5185#if defined(SGXML_SCANNER_DEPRECATED)
5186        DEPRECATED_FEATURE_IN_ICXML;
5187#else
5188        PSVIElement::ASSESSMENT_TYPE validationAttempted;
5189        PSVIElement::VALIDITY_STATE validity = PSVIElement::VALIDITY_NOTKNOWN;
5190
5191        if (fPSVIElemContext.fElemDepth > fPSVIElemContext.fFullValidationDepth)
5192                validationAttempted = PSVIElement::VALIDATION_FULL;
5193        else if (fPSVIElemContext.fElemDepth > fPSVIElemContext.fNoneValidationDepth)
5194                validationAttempted = PSVIElement::VALIDATION_NONE;
5195        else
5196        {
5197                validationAttempted  = PSVIElement::VALIDATION_PARTIAL;
5198                                fPSVIElemContext.fFullValidationDepth =
5199                        fPSVIElemContext.fNoneValidationDepth = fPSVIElemContext.fElemDepth - 1;
5200        }
5201
5202        if (fValidate && elemDecl->isDeclared())
5203        {
5204                validity = (fPSVIElemContext.fErrorOccurred)
5205                        ? PSVIElement::VALIDITY_INVALID : PSVIElement::VALIDITY_VALID;
5206        }
5207
5208        XSTypeDefinition* typeDef = 0;
5209        bool isMixed = false;
5210        if (fPSVIElemContext.fCurrentTypeInfo)
5211        {
5212                typeDef = (XSTypeDefinition*) fModel->getXSObject(fPSVIElemContext.fCurrentTypeInfo);
5213                SchemaElementDecl::ModelTypes modelType = (SchemaElementDecl::ModelTypes)fPSVIElemContext.fCurrentTypeInfo->getContentType();
5214                isMixed = (modelType == SchemaElementDecl::Mixed_Simple
5215                                || modelType == SchemaElementDecl::Mixed_Complex);
5216        }
5217        else if (fPSVIElemContext.fCurrentDV)
5218                typeDef = (XSTypeDefinition*) fModel->getXSObject(fPSVIElemContext.fCurrentDV);
5219
5220        XMLCh* canonicalValue = 0;
5221        if (fPSVIElemContext.fNormalizedValue && !isMixed &&
5222                        validity == PSVIElement::VALIDITY_VALID)
5223        {
5224                if (memberDV)
5225                        canonicalValue = (XMLCh*) memberDV->getCanonicalRepresentation(fPSVIElemContext.fNormalizedValue, fMemoryManager);
5226                else if (fPSVIElemContext.fCurrentDV)
5227                        canonicalValue = (XMLCh*) fPSVIElemContext.fCurrentDV->getCanonicalRepresentation(fPSVIElemContext.fNormalizedValue, fMemoryManager);
5228        }
5229
5230        fPSVIElement->reset
5231        (
5232                validity
5233                , validationAttempted
5234                , fRootElemName
5235                , fPSVIElemContext.fIsSpecified
5236                , (elemDecl->isDeclared())
5237                        ? (XSElementDeclaration*) fModel->getXSObject(elemDecl) : 0
5238                , typeDef
5239                , (memberDV) ? (XSSimpleTypeDefinition*) fModel->getXSObject(memberDV) : 0
5240                , fModel
5241                , elemDecl->getDefaultValue()
5242                , fPSVIElemContext.fNormalizedValue
5243                , canonicalValue
5244        );
5245
5246        fPSVIHandler->handleElementPSVI
5247        (
5248                elemDecl->getBaseName()
5249                #ifdef TEST_NAMESPACE_RESOLVER
5250                , (*fUriResolver)[elemDecl->getURI()]
5251                #else
5252                , fURIStringPool->getValueForId(elemDecl->getURI())
5253                #endif
5254                , fPSVIElement
5255        );
5256
5257        // decrease element depth
5258        fPSVIElemContext.fElemDepth--;
5259#endif
5260}
5261
5262void SGXMLScanner::resetPSVIElemContext()
5263{
5264#if defined(SGXML_SCANNER_DEPRECATED)
5265        DEPRECATED_FEATURE_IN_ICXML;
5266#else
5267        fPSVIElemContext.fIsSpecified = false;
5268        fPSVIElemContext.fErrorOccurred = false;
5269        fPSVIElemContext.fElemDepth = -1;
5270        fPSVIElemContext.fFullValidationDepth = -1;
5271        fPSVIElemContext.fNoneValidationDepth = -1;
5272        fPSVIElemContext.fCurrentDV = 0;
5273        fPSVIElemContext.fCurrentTypeInfo = 0;
5274        fPSVIElemContext.fNormalizedValue = 0;
5275#endif
5276}
5277
5278XERCES_CPP_NAMESPACE_END
Note: See TracBrowser for help on using the repository browser.