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

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

Additional files for icXML 0.9

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