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

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

Changes to icxercesc files

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