source: icXML/icXML-devel/src/icxercesc/internal/IGXMLScanner.hpp

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

Changes to icxercesc files

File size: 87.3 KB
Line 
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18/*
19 * $Id: IGXMLScanner.hpp 882548 2009-11-20 13:44:14Z borisk $
20 */
21
22#if !defined(XERCESC_INCLUDE_GUARD_IGXMLSCANNER_HPP)
23#define XERCESC_INCLUDE_GUARD_IGXMLSCANNER_HPP
24
25#include <icxercesc/internal/XMLScanner.hpp>
26#include <xercesc/util/KVStringPair.hpp>
27#include <xercesc/util/NameIdPool.hpp>
28#include <xercesc/util/RefHash2KeysTableOf.hpp>
29#include <xercesc/util/RefHash3KeysIdPool.hpp>
30#include <xercesc/util/Hash2KeysSetOf.hpp>
31#include <icxercesc/validators/common/Grammar.hpp>
32#include <icxercesc/validators/schema/SchemaInfo.hpp>
33#include <icxercesc/validators/schema/SchemaElementDecl.hpp>
34
35#include <xercesc/validators/DTD/DTDGrammar.hpp>
36#include <icxercesc/validators/DTD/DTDValidator.hpp>
37#include <icxercesc/validators/schema/SchemaGrammar.hpp>
38#include <icxercesc/validators/schema/SchemaValidator.hpp>
39#include <icxercesc/validators/schema/SchemaAttDefList.hpp>
40#include <xercesc/framework/psvi/PSVIAttributeList.hpp>
41#include <xercesc/framework/psvi/PSVIElement.hpp>
42
43#include <icxercesc/validators/schema/SubstitutionGroupComparator.hpp>
44#include <xercesc/validators/common/ContentLeafNameTypeVector.hpp>
45
46#include <xercesc/framework/psvi/PSVIHandler.hpp>
47#include <icxercesc/validators/schema/identity/IdentityConstraintHandler.hpp>
48#include <icxercesc/internal/ValidationContextImpl.hpp>
49
50#include <xercesc/util/XMLStringTokenizer.hpp>
51#include <icxmlc/XMLGrammarResolver.hpp>
52#include <icxmlc/XMLSymbolTable.hpp>
53#include <icxmlc/XMLParserImpl.hpp>
54#include <icxmlc/XMLParserDefs.hpp>
55#include <icxmlc/parsers/XMLDocumentAccumulator.hpp>
56#include <icxmlc/XMLConfig.hpp>
57
58XERCES_CPP_NAMESPACE_BEGIN
59
60class DTDElementDecl;
61class DTDGrammar;
62class DTDValidator;
63class SchemaValidator;
64class IdentityConstraint;
65class ContentLeafNameTypeVector;
66class SchemaAttDef;
67class XMLContentModel;
68class XSModel;
69class PSVIAttributeList;
70class PSVIElement;
71template<class ScannerType> class XMLGrammarValidator;
72
73// TODO: remove fValidator from this class; use ONLY fSchemaValidator or fDTDValidator directly
74// depending on fGrammarType
75
76// This is an integrated scanner class, which does DTD/XML Schema grammar processing.
77class XMLPARSER_EXPORT IGXMLScanner : public XMLScanner
78{
79        template<class IGXMLScanner> friend class XMLParserImpl;
80    template<class IGXMLScanner> friend class XMLGrammarValidator;
81    template<class IGXMLScanner> friend class XMLSchemaLoader;
82
83    typedef XMLElementDecl ElementDeclType;
84
85public :
86        // -----------------------------------------------------------------------
87        //  Constructors and Destructor
88        // -----------------------------------------------------------------------
89        IGXMLScanner
90        (
91                XMLValidator* const valToAdopt
92                , GrammarResolver* const grammarResolver
93                , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
94        );
95        IGXMLScanner
96        (
97                  XMLDocumentHandler* const docHandler
98                , DocTypeHandler* const     docTypeHandler
99                , XMLEntityHandler* const   entityHandler
100                , XMLErrorReporter* const   errReporter
101                , XMLValidator* const       valToAdopt
102                , GrammarResolver* const    grammarResolver
103                , MemoryManager* const      manager = XMLPlatformUtils::fgMemoryManager
104        );
105        virtual ~IGXMLScanner();
106
107        // -----------------------------------------------------------------------
108        //  XMLScanner public virtual methods
109        // -----------------------------------------------------------------------
110        virtual const XMLCh* getName() const;
111        virtual NameIdPool<DTDEntityDecl>* getEntityDeclPool();
112        virtual const NameIdPool<DTDEntityDecl>* getEntityDeclPool() const;
113        virtual void scanDocument
114        (
115                const   InputSource&    src
116        );
117        virtual bool scanNext(XMLPScanToken& toFill);
118        virtual Grammar* loadGrammar
119        (
120                const   InputSource&    src
121                , const short           grammarType
122                , const bool            toCache = false
123        );
124
125        virtual void resetCachedGrammar ();
126        virtual Grammar::GrammarType getCurrentGrammarType() const;
127
128        // -----------------------------------------------------------------------
129    //  XMLScanner parabix methods
130        // -----------------------------------------------------------------------
131
132    IDISA_ALWAYS_INLINE
133    void validateContent
134        (
135        const XMLCh *                   content
136        , XMLSize_t                     length
137        , const XMLContentFlag          flags
138        , const bool                    doPSVI
139        , XMLDocumentAccumulator &      parser
140        , const bool                    write = false
141        );
142
143    IDISA_ALWAYS_INLINE
144    void validateCDATA
145    (
146        const XMLCh       *             cdata
147        , XMLSize_t                     length
148        , const bool                    doPSVI
149        , XMLDocumentAccumulator &      parser
150    );
151
152    /// START / EMPTY TAG VALIDATION
153
154    IDISA_ALWAYS_INLINE
155    XMLElementDecl & getElementDecl
156    (
157        XMLSymbol &                     element
158        , unsigned int &                uriId
159        , const bool                    isRoot       
160        , const bool                    doPSVI       
161        , bool &                        hasIdentityConstraint
162        , bool &                        error
163        , XMLDocumentAccumulator &      parser
164    );
165
166    IDISA_ALWAYS_INLINE
167    bool validateAttribute
168    (
169          XMLElementDecl &              elemDecl       
170        , const XMLSize_t               elementCount
171        , const XMLSymbol &             attribute
172        , const unsigned int            uriId
173        , const XMLCh *                 value
174        , XMLSize_t                     length
175        , const MarkupType              type
176        , const Grammar::GrammarType    grammarType
177        , const bool                    doPSVI
178        , bool &                        error
179        , XMLDocumentAccumulator &      parser
180        , const bool                    write = false
181    );
182
183    IDISA_ALWAYS_INLINE
184    XMLSize_t postAttributeValidation
185    (
186        XMLElementDecl &                elemDecl
187        , const QName *                 elemName
188        , const XMLSize_t               elementCount
189        , XMLSize_t                     attributeCount
190        , const unsigned int            uriId
191        , const bool                    isRoot
192        , const bool                    isEmpty
193        , const Grammar::GrammarType    grammarType
194        , const bool                    doPSVI       
195        , bool &                        error       
196        , XMLDocumentAccumulator &      parser
197    );
198
199
200    IDISA_ALWAYS_INLINE
201    void validateEndTag
202        (
203        XMLElementDecl &                    element
204        , const QName *                     elemName
205        , const unsigned int                uriId
206        , const bool                        isRoot
207        , XMLElementDecl **                 children
208        , const XMLSize_t                   childCount
209        , const bool                        doPSVI
210        , bool &                            error
211        , XMLDocumentAccumulator &          parser
212        );
213
214    IDISA_ALWAYS_INLINE
215    void loadExternalGrammars();
216
217    IDISA_ALWAYS_INLINE
218        void setXsiType
219        (
220        const XMLCh *                           prefix
221        , const XMLCh *             localPart
222        , const unsigned int        uriId
223        );
224
225    IDISA_ALWAYS_INLINE
226    void setXsiNil
227        (
228                const XMLCh *                           value
229                , const XMLSize_t                       length
230        );
231
232    inline bool preValidateDefaultAttribute(const QName & element, const QName & attribute, const bool isExternal) const;
233
234    virtual bool expandEntityReference
235    (
236        const XMLCh *                   entityRef
237        , const XMLSize_t               length
238        , const bool                    inAttributeValue
239        , XMLBuffer &                   toFill
240        , XMLReplacementText &          replacementText
241    );
242
243        virtual const DTDGrammar * getDTDGrammar() const
244        {
245                return fDTDGrammar;
246        }
247
248    IDISA_ALWAYS_INLINE
249    Grammar::GrammarType getGrammarType() const
250    {
251        return fGrammarType;
252    }
253
254protected:
255
256        virtual void scanFirst();
257
258private :
259        // -----------------------------------------------------------------------
260        //  Unimplemented constructors and operators
261        // -----------------------------------------------------------------------
262        IGXMLScanner();
263        IGXMLScanner(const IGXMLScanner&);
264        IGXMLScanner& operator=(const IGXMLScanner&);
265
266        // -----------------------------------------------------------------------
267        //  XMLScanner virtual methods
268        // -----------------------------------------------------------------------
269        virtual void scanCDSection();
270        virtual void scanCharData(XMLBuffer& toToUse);
271        virtual EntityExpRes scanEntityRef
272        (
273                const   bool    inAttVal
274                ,       XMLCh&  firstCh
275                ,       XMLCh&  secondCh
276                ,       bool&   escaped
277        );
278        virtual void scanDocTypeDecl();
279        virtual void scanReset(const InputSource& src);
280        virtual void sendCharData(XMLBuffer& toSend);
281        virtual InputSource* resolveSystemId(const XMLCh* const sysId
282                                                                                ,const XMLCh* const pubId);
283
284        // -----------------------------------------------------------------------
285        //  Private helper methods
286        // -----------------------------------------------------------------------
287    void commonInit();
288    void setLocator(Locator * locator);
289        void cleanUp();
290
291    bool checkNamespaceAttribute(const bool isXMLNS, const XMLSymbol & attribute, const XMLCh * value, const bool declared, DatatypeValidator * & attrValidator);
292
293    bool tokenizeAttributeValue(const XMLCh * const value, const XMLSize_t length, XMLBuffer & toFill);
294
295    IDISA_ALWAYS_INLINE
296    bool doSchemaWhitespaceNormalization(const XMLCh *& content, XMLSize_t & length);
297
298    IDISA_ALWAYS_INLINE
299    XMLElementDecl * findElementDecl(XMLSymbol & element, unsigned int uriId, unsigned int scope, Grammar * grammar);
300
301        inline bool switchGrammar(const unsigned int uriId);
302
303        inline bool switchGrammar(const unsigned int uriId, const XMLCh* const newGrammarNameSpace);
304
305        void parseSchemaLocation(const XMLCh* const schemaLocationStr, const XMLSize_t schemaLocationStrLen, bool ignoreLoadSchema = false);
306
307        void resolveSchemaGrammar(const XMLCh* const loc, const XMLCh* const uri, bool ignoreLoadSchema = false);
308
309        inline bool switchGrammar(const XMLCh* const newGrammarNameSpace);
310
311        inline bool setCurrentGrammar(Grammar * tempGrammar);
312
313    IDISA_ALWAYS_INLINE
314    bool laxElementValidation
315    (
316        const QName *                           element
317        , const unsigned int                    uriId
318        , const ContentLeafNameTypeVector *     cv
319        , const XMLContentModel* const          cm
320        , const XMLSize_t                       parentElemDepth
321    );
322
323        bool anyAttributeValidation(SchemaAttDef* attWildCard,
324                                                                unsigned int uriId,
325                                                                bool& skipThisOne,
326                                                                bool& laxThisOne);
327
328        void resizeElemState();
329
330
331    IDISA_ALWAYS_INLINE
332    DatatypeValidator * getAnySimpleTypeValidator();
333
334    // -----------------------------------------------------------------------
335    //  Private error reporting methods
336    // -----------------------------------------------------------------------
337
338    void reportRequiredAttribute(const DTDAttDef & attDef);
339
340    void reportRequiredAttribute(const SchemaAttDef & attDef);
341
342    void reportAttributeNotDefinedForElement(const DTDElementDecl & elemDecl, const XMLCh * attributeName);
343
344        // -----------------------------------------------------------------------
345        //  Private scanning methods
346        // -----------------------------------------------------------------------
347
348        bool scanContent();
349        void scanEndTag(bool& gotData);
350        bool scanStartTag(bool& gotData);
351        bool scanStartTagNS(bool& gotData);
352
353        // -----------------------------------------------------------------------
354        //  IdentityConstraints Activation methods
355        // -----------------------------------------------------------------------
356    inline bool toCheckIdentityConstraint() const;
357
358    virtual IdentityConstraintHandler * getIdentityConstraintHandler();
359
360        // -----------------------------------------------------------------------
361        //  Grammar preparsing methods
362        // -----------------------------------------------------------------------
363        Grammar* loadXMLSchemaGrammar(const InputSource& src, const bool toCache = false);
364        Grammar* loadDTDGrammar(const InputSource& src, const bool toCache = false);
365    void switchToSchemaGrammar();
366
367        // -----------------------------------------------------------------------
368        //  PSVI handling methods
369        // -----------------------------------------------------------------------
370
371    inline XSModel * getPSVIModel() { return fModel; }
372
373    inline void endElementPSVI(SchemaElementDecl & elemDecl, XMLDocumentAccumulator & parser);
374
375        void resetPSVIElemContext();
376
377        // -----------------------------------------------------------------------
378        //  DEPRECATED PRIVATE METHODS; KEPT FOR DLL COMPATIBILITY
379        // -----------------------------------------------------------------------
380    bool basicAttrValueScan(const XMLCh* const, XMLBuffer&);
381
382    XMLSize_t rawAttrScan(const XMLCh* const, RefVectorOf<KVStringPair>&, bool&);
383
384    bool scanAttValue(const XMLAttDef* const, const XMLCh* const, XMLBuffer&);
385
386    XMLSize_t buildAttList(const RefVectorOf<KVStringPair>&, const XMLSize_t, XMLElementDecl*, RefVectorOf<XMLAttr>&);
387
388    void updateNSMap(const XMLCh* const, const XMLCh* const);
389
390    bool normalizeAttValue(const XMLAttDef* const, const XMLCh* const, const XMLCh* const, XMLBuffer&);
391
392    bool normalizeAttRawValue(const XMLCh* const, const XMLCh* const, XMLBuffer&);
393
394    void parseSchemaLocation(const XMLCh* const, bool);
395
396    void processSchemaLocation(XMLCh* const);
397
398        void resizeRawAttrColonList();
399
400    void scanRawAttrListforNameSpaces(XMLSize_t);
401
402//    inline
403//    XMLAttDefList & getAttDefList( bool              isSchemaGrammar
404//                                 , ComplexTypeInfo*  currType
405//                                 , XMLElementDecl*   elemDecl );
406
407    void updateNSMap(const XMLCh* const, const XMLCh* const, const int);
408
409    void updateNSMap(const QName* const, const XMLCh* const);
410
411    bool laxElementValidation(QName*, ContentLeafNameTypeVector*, const XMLContentModel* const, const XMLSize_t);
412
413    void endElementPSVI(SchemaElementDecl* const, DatatypeValidator* const);
414
415        // -----------------------------------------------------------------------
416        //  Data members
417        //
418        //  fRawAttrList
419        //      During the initial scan of the attributes we can only do a raw
420        //      scan for key/value pairs. So this vector is used to store them
421        //      until they can be processed (and put into fAttrList.)
422        //
423        //  fDTDValidator
424        //      The DTD validator instance.
425        //
426        //  fSchemaValidator
427        //      The Schema validator instance.
428        //
429        //  fSeeXsi
430        //      This flag indicates a schema has been seen.
431        //
432        //  fElemState
433        //  fElemLoopState
434        //  fElemStateSize
435        //      Stores an element next state from DFA content model - used for
436        //      wildcard validation
437        //
438        // fDTDElemNonDeclPool
439        //      registry of "faulted-in" DTD element decls
440        // fSchemaElemNonDeclPool
441        //      registry for elements without decls in the grammar
442        // fElemCount
443        //      count of the number of start tags seen so far (starts at 1).
444        //      Used for duplicate attribute detection/processing of required/defaulted attributes
445        // fPSVIAttrList
446        //      PSVI attribute list implementation that needs to be
447        //      filled when a PSVIHandler is registered
448        // fSchemaInfoList
449        //      Transient schema info list that is passed to TraverseSchema instances.
450        // fCachedSchemaInfoList
451        //      Cached Schema info list that is passed to TraverseSchema instances.
452        //
453        // -----------------------------------------------------------------------
454
455        Grammar::GrammarType                    fGrammarType;
456        unsigned int                            fElemStateSize;
457        unsigned int*                           fElemState;
458        unsigned int*                           fElemLoopState;
459        XMLBuffer                               fWSNormalizeBuf;
460        DTDValidator*                           fDTDValidator;
461        SchemaValidator*                        fSchemaValidator;
462        DTDGrammar*                             fDTDGrammar;
463        IdentityConstraintHandler*              fICHandler;
464        NameIdPool<DTDElementDecl>*             fDTDElemNonDeclPool;
465        RefHash3KeysIdPool<SchemaElementDecl>*  fSchemaElemNonDeclPool;
466        PSVIAttributeList *                     fPSVIAttrList;
467        XSModel*                                fModel;
468        PSVIElement*                            fPSVIElement;   
469        PSVIElemContext                         fPSVIElemContext;
470        RefHash2KeysTableOf<SchemaInfo>*        fSchemaInfoList;
471        RefHash2KeysTableOf<SchemaInfo>*        fCachedSchemaInfoList;
472    XMLGrammarResolver                      fGrammarList;
473    DatatypeValidator *                     fAnySimpleTypeValidator;
474};
475
476inline const XMLCh* IGXMLScanner::getName() const
477{
478        return XMLUni::fgIGXMLScanner;
479}
480
481inline bool IGXMLScanner::toCheckIdentityConstraint()  const
482{
483    return (getValidationScheme() != ValSchemes::Val_Never) && fIdentityConstraintChecking;
484}
485
486inline IdentityConstraintHandler * IGXMLScanner::getIdentityConstraintHandler()
487{
488    return toCheckIdentityConstraint() ? fICHandler : 0;
489}
490
491inline Grammar::GrammarType IGXMLScanner::getCurrentGrammarType() const
492{
493        return fGrammarType;
494}
495
496inline DatatypeValidator * IGXMLScanner::getAnySimpleTypeValidator()
497{
498    if (unlikely(fAnySimpleTypeValidator == 0))
499    {
500        fAnySimpleTypeValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYSIMPLETYPE);
501    }
502    return fAnySimpleTypeValidator;
503}
504
505// ---------------------------------------------------------------------------
506//  IGXMLScanner: Private helper methods
507// ---------------------------------------------------------------------------
508
509bool IGXMLScanner::switchGrammar(const unsigned int uriId)
510{
511    Grammar * grammar = fGrammarList.getGrammar(uriId);
512    const XMLCh * grammarNameSpace = NULL;
513        if (unlikely(grammar == NULL))
514        {
515        grammarNameSpace = fNamespaceResolver->getUriForId(uriId);
516                grammar = fGrammarResolver->getGrammar(grammarNameSpace);
517                if (!grammar && !fSkipDTDValidation)
518                {
519                        // This is a case where namespaces is on with a DTD grammar.
520                        grammar = fDTDGrammar;
521                }
522                fGrammarList.setGrammar(uriId, grammar);
523        }
524    assert (grammar);
525    DEBUG_GRAMMAR_MESSAGE("switchGrammar(" << uriId << ")={" << grammarNameSpace << ',' << (grammar ? grammar->getTargetNamespace() : (XMLCh*)(0)) << '}')
526        return setCurrentGrammar(grammar);
527}
528
529bool IGXMLScanner::switchGrammar(const unsigned int uriId, const XMLCh* const newGrammarNameSpace)
530{
531        Grammar * grammar = fGrammarList.getGrammar(uriId);
532        if (unlikely(grammar == NULL))
533        {
534                grammar = fGrammarResolver->getGrammar(newGrammarNameSpace);
535                if (!grammar && !fSkipDTDValidation)
536                {
537                        // This is a case where namespaces is on with a DTD grammar.
538                        grammar = fDTDGrammar;
539                }
540                fGrammarList.setGrammar(uriId, grammar);
541        }
542    assert (grammar);
543    DEBUG_GRAMMAR_MESSAGE("switchGrammar(" << uriId << ',' << newGrammarNameSpace << ")=" << (grammar ? grammar->getTargetNamespace() : (XMLCh*)(0)))
544        return setCurrentGrammar(grammar);
545}
546
547bool IGXMLScanner::switchGrammar(const XMLCh* const newGrammarNameSpace)
548{
549    return switchGrammar(fNamespaceResolver->resolveUriId(newGrammarNameSpace), newGrammarNameSpace);
550}
551
552bool IGXMLScanner::setCurrentGrammar(Grammar * grammar)
553{
554        if (unlikely(grammar == 0))
555        {
556                return false;
557        }
558        else if (grammar != fGrammar)
559        {
560        DEBUG_GRAMMAR_MESSAGE(" *** setCurrentGrammar(" << grammar << ") " << (grammar->getGrammarType() == Grammar::SchemaGrammarType ? "Schema" : "DTD"))
561
562        fGrammarType = grammar->getGrammarType();
563
564        if (fGrammarType == Grammar::SchemaGrammarType)
565                {
566                        fValidator = fSchemaValidator;
567
568                        if (unlikely(!fValidator->handlesSchema()))
569                        {
570                                if (fValidatorFromUser)
571                                {
572                                        ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoSchemaValidator, fMemoryManager);
573                                }
574                        }
575
576            fSchemaValidator->setGrammar(grammar);
577                }
578        else if (fGrammarType == Grammar::DTDGrammarType)
579                {
580                        if (fSkipDTDValidation)
581                        {
582                                return false;
583                        }
584
585                        fValidator = fDTDValidator;
586
587                        if (unlikely(!fValidator->handlesDTD()))
588                        {
589                                if (fValidatorFromUser)
590                                {
591                                        ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoDTDValidator, fMemoryManager);
592                                }
593                        }
594
595            fDTDValidator->setGrammar(grammar);
596                }
597
598                fGrammar = grammar;
599
600        }
601        return true;
602}
603
604// ---------------------------------------------------------------------------
605//  IGXMLScanner: XMLParser Callback Methods
606// ---------------------------------------------------------------------------
607
608void IGXMLScanner::loadExternalGrammars()
609{
610    //  Check if there is any external schema location specified, and if we are at root,
611    //  go through them first before scanning those specified in the instance document
612    if (unlikely(fExternalSchemaLocation != 0))
613        parseSchemaLocation(fExternalSchemaLocation, XMLString::stringLen(fExternalSchemaLocation), true);
614
615    if (unlikely(fExternalNoNamespaceSchemaLocation != 0))
616        resolveSchemaGrammar(fExternalNoNamespaceSchemaLocation, XMLUni::fgZeroLenString, true);
617}
618
619#ifdef __GNUC__
620#warning "TO CONSIDER: could it be possible to split the tag validation routines into get and validate functions?"
621/// Could perform resolution in the WF and NS layers and validation in the GV.
622/// Difficulty would be to maintain state--but the grammar may not need it as long as the proper elemDecl and attDef were obtained.
623/// Would be possible to create a stream of
624#endif
625
626// --------------------------------------------------------------------------------------------------------
627// HANDLE START / EMPTY TAG FUNCTIONS
628// --------------------------------------------------------------------------------------------------------
629
630XMLElementDecl & IGXMLScanner::getElementDecl
631(
632      XMLSymbol &                   element
633    , unsigned int &                uriId
634    , const bool                                        isRoot   
635    , const bool                    doPSVI
636    , bool &                        hasIdentityConstraint
637    , bool &                        error
638    , XMLDocumentAccumulator &      parser   
639)
640{
641    /// ----------------------------- DETERMINE THE ELEMENT DECLARATION -----------------------------------
642
643    XMLElementDecl * elemDecl = 0;   
644
645    if (unlikely(!fDoNamespaces))
646    {
647        //  Lets try to look up the element in the validator's element decl pool
648        //  We can pass bogus values for the URI id and the base name. We know that
649        //  this can only be called if we are doing a DTD style validator and that
650        //  he will only look at the QName.
651        //
652        //  We tell him to fault in a decl if he does not find one.
653        //  Actually, we *don't* tell him to fault in a decl if he does not find one- NG
654
655        elemDecl = findElementDecl(element, XMLNamespaceResolver::fEmptyUriId, Grammar::TOP_LEVEL_SCOPE, fDTDGrammar);
656
657        if (unlikely(elemDecl == 0))
658        {           
659            elemDecl = fDTDElemNonDeclPool->getByKey(element.getName());
660            if (!elemDecl)
661            {
662                // we're assuming this must be a DTD element.  DTD's can be
663                // used with or without namespaces, but schemas cannot be used without
664                // namespaces.
665                elemDecl = new (fMemoryManager) DTDElementDecl(element.getQName(), DTDElementDecl::Any, fMemoryManager);
666                elemDecl->setId(fDTDElemNonDeclPool->put((DTDElementDecl*)elemDecl));
667                elemDecl->setCreateReason(XMLElementDecl::JustFaultIn);
668            }
669            element.setElemDecl(XMLNamespaceResolver::fEmptyUriId, Grammar::TOP_LEVEL_SCOPE, elemDecl);
670        }
671
672        // If its not marked declared and validating, then emit an error
673        if (unlikely(!elemDecl->isDeclared() && fValidate))
674        {
675            fDTDValidator->emitError(XMLValid::ElementNotDefined, element.getName());
676            fValidate = false;
677        }
678
679        // Expand the element stack and add the new element
680        fElemStack.addLevel(elemDecl, 0);
681
682        fValidate &= !fSkipDTDValidation;
683
684        //  Validate the element
685        if (fValidate)
686        {
687            fDTDValidator->validateElement(elemDecl);
688        }
689    }
690    else  // if (fDoNamespaces)
691    {
692        // save the contentleafname and currentscope before addlevel, for later use
693        ContentLeafNameTypeVector* cv = 0;
694        XMLContentModel* cm = 0;
695        unsigned int currentScope = Grammar::TOP_LEVEL_SCOPE;
696        bool laxValidation = false;
697        bool hasXsiType = false;
698        bool wasAdded = false;
699
700        if (fGrammarType == Grammar::SchemaGrammarType)
701        {
702            hasXsiType = fSchemaValidator->getIsXsiTypeSet();
703
704            if (likely(!isRoot))
705            {
706                SchemaElementDecl::ModelTypes modelType;
707                ComplexTypeInfo *currType;
708
709                if (fValidate)
710                {
711                    // schema validator will have correct type if validating
712                    currType = fSchemaValidator->getCurrentTypeInfo();                   
713                    modelType = currType ? (SchemaElementDecl::ModelTypes)currType->getContentType() : SchemaElementDecl::Any;
714                }
715                else
716                {
717                    SchemaElementDecl & parent = *((SchemaElementDecl*)fElemStack.topElement()->fThisElement);
718                    currType = parent.getComplexTypeInfo();
719                    modelType = parent.getModelType();
720                }
721
722                switch (modelType)
723                {
724                    case SchemaElementDecl::Mixed_Simple:
725                    case SchemaElementDecl::Mixed_Complex:
726                    case SchemaElementDecl::Children:
727                        cm = currType->getContentModel();
728                        cv = cm->getContentLeafNameTypeVector();
729                        currentScope = fElemStack.getCurrentScope();
730                        //if schema, check if we should lax or skip the validation of this element
731                        laxValidation = laxElementValidation(element.getQName(), uriId, cv, cm, fElemStack.getLevel());
732                        break;
733                    case SchemaElementDecl::Any:
734                        laxValidation = true;
735                }
736            }
737
738            elemDecl = findElementDecl(element, uriId, currentScope, fGrammar);
739            if (unlikely(!elemDecl))
740            {               
741                if (likely(fDoSchema))
742                {
743                    const unsigned int grammarUriId = fGrammar->getTargetNamespaceId(fNamespaceResolver);
744
745                    Grammar * const originalGrammar = fGrammar;
746                    if (unlikely(grammarUriId != uriId))
747                    {
748                        if (likely(switchGrammar(uriId)))
749                        {
750                            elemDecl = findElementDecl(element, uriId, currentScope, fGrammar);
751                        }
752                        else if (unlikely(!laxValidation && fValidate))
753                        {
754                            // the laxElementValidation routine (called above) will
755                            // set fValidate to false for a "skipped" element
756                            fSchemaValidator->emitError(XMLValid::GrammarNotFound, fNamespaceResolver->getUriForId(uriId));
757                        }
758                    }
759
760                    if (unlikely(!elemDecl && (currentScope != Grammar::TOP_LEVEL_SCOPE)))
761                    {
762                        // try the top level
763                        elemDecl = findElementDecl(element, uriId, Grammar::TOP_LEVEL_SCOPE, fGrammar);
764                        if (unlikely(elemDecl == 0 && fValidate))
765                        {
766                            if (grammarUriId == uriId)
767                            {
768                                // still not found in specified uri; try emptyNamespace see if the element should be un-qualified.
769                                if (uriId != XMLNamespaceResolver::fEmptyUriId)
770                                {
771                                    XMLElementDecl * temp = findElementDecl(element, XMLNamespaceResolver::fEmptyUriId, currentScope, fGrammar);
772                                    if (temp && temp->getCreateReason() != XMLElementDecl::JustFaultIn && fValidate)
773                                    {
774                                        fSchemaValidator->emitError(XMLValid::ElementNotUnQualified, element.getName());
775                                        elemDecl = temp;
776                                        uriId = XMLNamespaceResolver::fEmptyUriId;
777                                    }
778                                }
779                            }
780                            else if (uriId == XMLNamespaceResolver::fEmptyUriId)
781                            {
782                                // still not found in specified uri; try the original grammar to see if the element needs to be fully qualified.
783                                if (originalGrammar)
784                                {
785                                    XMLElementDecl * temp = findElementDecl(element, grammarUriId, currentScope, originalGrammar);
786                                    if (temp && temp->getCreateReason() != XMLElementDecl::JustFaultIn)
787                                    {
788                                        fSchemaValidator->emitError(XMLValid::ElementNotQualified, element.getName());
789                                        fGrammar = originalGrammar;
790                                        fGrammarType = Grammar::SchemaGrammarType;
791                                        fValidator = fSchemaValidator;
792                                        uriId = grammarUriId;
793                                        elemDecl = temp;
794                                    }
795                                }
796                                else if (!laxValidation)
797                                {
798                                    fSchemaValidator->emitError(XMLValid::GrammarNotFound, originalGrammar->getTargetNamespace());
799                                }
800                            }
801                        }
802                    }
803
804                    if (unlikely(elemDecl == 0))
805                    {
806                        fGrammar = originalGrammar;
807                        fGrammarType = Grammar::SchemaGrammarType;
808                        fValidator = fSchemaValidator;
809                        // look in the list of undeclared elements, as would have been
810                        // done before we made grammars stateless:
811                        elemDecl = fSchemaElemNonDeclPool->getByKey(element.getQName()->getLocalPart(), uriId, (int)Grammar::TOP_LEVEL_SCOPE);
812                    }
813                }
814
815                if (unlikely(!elemDecl))
816                {
817                    //  Could not find the element declaration; fault one in.
818                    elemDecl = new (fMemoryManager) SchemaElementDecl(element.getQName(), SchemaElementDecl::Any, Grammar::TOP_LEVEL_SCOPE, fMemoryManager);
819                    fSchemaElemNonDeclPool->put((void*)element.getQName()->getLocalPart(), uriId, (int)Grammar::TOP_LEVEL_SCOPE, (SchemaElementDecl*)elemDecl);
820                    elemDecl->setCreateReason(XMLElementDecl::JustFaultIn);
821                    element.setElemDecl(uriId, currentScope, elemDecl);
822                    wasAdded = true;
823                }
824
825                element.setElemDecl(uriId, currentScope, elemDecl);
826
827                if (unlikely((static_cast<const SchemaElementDecl*>(elemDecl)->getIdentityConstraintCount() > 0)))
828                {
829                    hasIdentityConstraint = fIdentityConstraintChecking;
830                    DEBUG_GRAMMAR_MESSAGE(" *** hasIdentityConstraint *** ")
831                }
832            }
833
834            if (doPSVI)
835            {
836                fPSVIElemContext.fElemDepth++;
837                if (elemDecl->isDeclared())
838                {
839                    fPSVIElemContext.fNoneValidationDepth = fPSVIElemContext.fElemDepth;
840                }
841                else
842                {
843                    fPSVIElemContext.fFullValidationDepth = fPSVIElemContext.fElemDepth;
844                }
845            }
846        }
847        else // if (fGrammarType == Grammar::DTDGrammarType)
848        {
849            elemDecl = findElementDecl(element, uriId, Grammar::TOP_LEVEL_SCOPE, fDTDGrammar);
850            if (unlikely(elemDecl == 0))
851            {
852                elemDecl = fDTDElemNonDeclPool->getByKey(element.getName());
853                if (fDoSchema)
854                {
855                    if (unlikely(!switchGrammar(uriId)))
856                    {
857                        fDTDValidator->emitError(XMLValid::GrammarNotFound, fNamespaceResolver->getUriForId(uriId));
858                    }
859                }
860                if (unlikely(elemDecl == 0))
861                {
862                    //  Could not find the element declaration; fault one in.
863                    elemDecl = new (fMemoryManager) DTDElementDecl(element.getQName(), DTDElementDecl::Any, fMemoryManager);
864                    elemDecl->setId(fDTDElemNonDeclPool->put((DTDElementDecl*)elemDecl));
865                    elemDecl->setCreateReason(XMLElementDecl::JustFaultIn);
866                    wasAdded = true;
867                }
868
869                element.setElemDecl(uriId, Grammar::TOP_LEVEL_SCOPE, elemDecl);
870            }
871            fValidate &= !fSkipDTDValidation;
872        }
873
874
875        if (unlikely(!elemDecl->isDeclared()))
876        {
877            DEBUG_GRAMMAR_MESSAGE(" --- faulting element in! laxValidation=" << laxValidation << ", hasXsiType=" << hasXsiType)
878
879            if (laxValidation && !hasXsiType)
880            {
881                fValidate = false;
882            }
883            else if (fValidate)
884            {
885                // if xsi:type was specified, don't complain about missing definition
886                if (!hasXsiType)
887                {
888                    fValidator->emitError(XMLValid::ElementNotDefined, elemDecl->getFullName());
889                    error = true;
890                }
891            }
892        }
893
894        //  Now we can update the element stack to set the current element decl.
895        const XMLSize_t elemDepth = fElemStack.addLevel(elemDecl, 0);
896
897        //  Validate the element       
898        if (fGrammarType == Grammar::SchemaGrammarType)
899        {
900            ComplexTypeInfo * typeInfo;
901            if (fValidate)
902            {
903                fSchemaValidator->validateElement(elemDecl);
904                error |= fSchemaValidator->getErrorOccurred();
905                typeInfo = fSchemaValidator->getCurrentTypeInfo();
906            }
907            else
908            {
909                typeInfo = ((SchemaElementDecl*)elemDecl)->getComplexTypeInfo();
910            }
911
912            DEBUG_MESSAGE(" -- typeInfo=" << typeInfo << ", validate=" << fValidate)
913
914            if (typeInfo)
915            {
916                currentScope = typeInfo->getScopeDefined();
917                // switch grammar if the typeinfo has a different grammar (happens when there is xsi:type)
918                XMLCh* typeName = typeInfo->getTypeName();
919                const int comma = XMLString::indexOf(typeName, chComma);
920                if (comma > 0)
921                {
922                    XMLBuffer prefixBuf(comma + 1, fMemoryManager);
923                    prefixBuf.set(typeName, comma);
924                    const XMLCh* uri = prefixBuf.getRawBuffer();
925                    bool switched = switchGrammar(uri);
926                    if (!switched && !laxValidation && fValidate)
927                    {
928                        fSchemaValidator->emitError(XMLValid::GrammarNotFound, uri);
929                    }
930                }
931                else if (comma == 0)
932                {
933                    bool switched = switchGrammar(XMLNamespaceResolver::fEmptyUriId);
934                    if (!switched && !laxValidation && fValidate)
935                    {
936                        fSchemaValidator->emitError(XMLValid::GrammarNotFound, XMLUni::fgZeroLenString);
937                    }
938                }
939            }
940
941            fElemStack.setCurrentScope(currentScope);
942
943            // Set element next state
944            if (unlikely(elemDepth >= fElemStateSize))
945            {
946                resizeElemState();
947            }
948
949            fElemState[elemDepth] = 0;
950            fElemLoopState[elemDepth] = 0;
951        }
952        else if (fValidate) // && fGrammarType == Grammar::DTDGrammarType
953        {
954            fDTDValidator->validateElement(elemDecl);
955        }
956
957        fElemStack.setCurrentGrammar(fGrammar);       
958    }
959
960    fElemStack.setValidationFlag(fValidate);
961
962    //  If this is the first element and we are validating, check the root element.
963    if (unlikely(isRoot))
964    {
965        fRootGrammar = fGrammar;
966        if (fRootElemName)
967        {
968            bool validRootName = (!fValidate || XMLString::equals(element.getName(), fRootElemName));
969            if (unlikely(!validRootName))
970            {
971                fValidator->emitError(XMLValid::RootElemNotLikeDocType);
972            }
973        }
974        else
975        {
976            setRootElemName(const_cast<XMLCh*>(element.getName()));
977        }
978    }
979
980    return *elemDecl;
981}
982
983XMLElementDecl * IGXMLScanner::findElementDecl(XMLSymbol & element, unsigned int uriId, unsigned int scope, Grammar * grammar)
984{   
985    size_t index;
986    XMLElementDecl * elemDecl = element.getElemDecl(uriId, scope, index);
987    if (unlikely(!elemDecl))
988    {
989        QName * const qName = element.getQName();
990        elemDecl = grammar->getElemDecl(uriId, qName->getLocalPart(), qName->getRawName(), scope);
991        if (likely(elemDecl != NULL))
992        {
993            element.setElemDecl(index, uriId, scope, elemDecl);
994        }
995    }
996    return elemDecl;
997}
998
999static inline const XMLCh * subsituteEmptyStringWithNull(const XMLCh * string)
1000{
1001    if (unlikely(string && *string == 0))
1002        string = 0;
1003    return string;
1004}
1005
1006bool IGXMLScanner::validateAttribute
1007(
1008      XMLElementDecl &              elemDecl
1009    , const XMLSize_t               elementCount
1010    , const XMLSymbol &             attribute
1011    , const unsigned int            uriId
1012    , const XMLCh *                 value
1013    , XMLSize_t                     length
1014    , const MarkupType              type
1015    , const Grammar::GrammarType    grammarType
1016    , const bool                    doPSVI
1017    , bool &                        error
1018    , XMLDocumentAccumulator &      parser
1019    , const bool                    write
1020)
1021{
1022    XMLAttDef::AttTypes attType = XMLAttDef::CData;
1023
1024    if (unlikely(grammarType == Grammar::DTDGrammarType))
1025    {
1026        //  See if this attribute is declared for this element. If we are
1027        //  not validating of course it will not be at first, but we will
1028        //  fault it into the pool (to avoid lots of redundant errors.)
1029        DTDElementDecl & dtdElemDecl = reinterpret_cast<DTDElementDecl&>(elemDecl);
1030
1031        DTDAttDef * attDef = dtdElemDecl.getAttDef(attribute.getName());
1032
1033        //  Add this attribute to the attribute list that we use to
1034        //  pass them to the handler. We reuse its existing elements
1035        //  but expand it as required.
1036
1037        // Note that we want to this first since this will
1038        // make a copy of the namePtr; we can then make use of
1039        // that copy in the hashtable lookup that checks
1040        // for duplicates.  This will mean we may have to update
1041        // the type of the XMLAttr later.
1042
1043        bool tokenized = false;
1044
1045        if (unlikely(attDef == 0))
1046        {
1047            //  If there is a validation handler, then we are validating so emit an error.
1048            if (fValidate)
1049            {
1050                reportAttributeNotDefinedForElement(dtdElemDecl, attribute.getName());
1051                error = true;
1052            }
1053        }
1054        else
1055        {
1056            // prepare for duplicate detection
1057            attDef->setLastOccurrence(elementCount);
1058            attType = attDef->getType();
1059
1060            // check to see if we need to tokenize the value
1061            if (unlikely(attType != XMLAttDef::CData && attType <= XMLAttDef::Enumeration))
1062            {
1063                tokenized = tokenizeAttributeValue(value, length, fWSNormalizeBuf);
1064                if (unlikely(tokenized))
1065                {
1066                    if (unlikely(fStandalone && fValidate && attDef->isExternal()))
1067                    {
1068                        // Can't have a standalone document declaration of "yes" if  attribute
1069                        // values are subject to normalisation
1070                        fValidator->emitError(XMLValid::NoAttNormForStandalone, attDef->getFullName());
1071                    }
1072                    value = fWSNormalizeBuf.getRawBuffer();
1073                    length = fWSNormalizeBuf.getLen();
1074                }
1075            }
1076
1077            if (fValidate)
1078            {
1079                if (unlikely(attDef->getDefaultType() == XMLAttDef::Prohibited))
1080                {
1081                    // (schema) report error for PROHIBITED attrs that are present (V_TAGc)
1082                    fDTDValidator->emitError(XMLValid::ProhibitedAttributePresent, attDef->getFullName());
1083                }
1084
1085                // Let the validator pass judgement on the attribute value
1086                fDTDValidator->validateAttrValue(attDef, value, false, &dtdElemDecl);
1087            }
1088        }
1089
1090        parser.writeAttribute(attribute.getQName(), attType, uriId, value, length, type, write | tokenized);
1091    }
1092    else // if (fDoNamespaces)
1093    {
1094        SchemaElementDecl & schemaElemDecl = ((SchemaElementDecl&)elemDecl);
1095        SchemaAttDef * attDef = 0;
1096        const QName * attName = attribute.getQName();
1097        DatatypeValidator * attrValidator = 0;       
1098        bool normalized = false;
1099        bool laxValidation = false;
1100        bool skipValidation = false;
1101        PSVIItem::VALIDITY_STATE attrValid = PSVIItem::VALIDITY_VALID;
1102        PSVIItem::ASSESSMENT_TYPE attrAssessed = PSVIItem::VALIDATION_FULL;
1103
1104        //  If the uri comes back as the xmlns or xml URI or its just a name
1105        //  and that name is 'xmlns', then we handle it specially. So set a
1106        //  boolean flag that lets us quickly below know which we are dealing
1107        //  with.
1108
1109        const bool isXSI = (uriId == XMLNamespaceResolver::fSchemaInstanceUriId);
1110        const bool isXMLNS = (uriId == XMLNamespaceResolver::fXMLNSUriId);
1111
1112        if (unlikely(isXSI | isXMLNS))
1113        {
1114            skipValidation = checkNamespaceAttribute(isXMLNS, attribute, value, elemDecl.isDeclared(), attrValidator);
1115        }
1116
1117        if (likely(!skipValidation))
1118        {
1119            // Some checking for attribute wild card first (for schema)
1120            SchemaAttDef* attWildCard = 0;
1121
1122            const XMLCh* const localPart = attName->getLocalPart();
1123
1124            ComplexTypeInfo * const currType = fSchemaValidator->getCurrentTypeInfo();
1125            //retrieve the att def and wildcard
1126            if (currType)
1127            {
1128                attDef = currType->getAttDef(localPart, uriId);
1129                attWildCard = currType->getAttWildCard();
1130            }
1131            else if (!fSchemaValidator->getCurrentDatatypeValidator())
1132            {
1133                // check explicitly-set wildcard
1134                attDef = schemaElemDecl.getAttDef(localPart, uriId);
1135                attWildCard = schemaElemDecl.getAttWildCard();
1136            }
1137
1138            // if not found or faulted in - check for a matching wildcard attribute
1139            // if no matching wildcard attribute, check (un)qualifed cases and flag
1140            // appropriate errors
1141            if (unlikely(!attDef || (attDef->getCreateReason() == XMLAttDef::JustFaultIn)))
1142            {
1143                if (attWildCard)
1144                {
1145                    //if schema, see if we should lax or skip the validation of this attribute
1146                    if (anyAttributeValidation(attWildCard, uriId, skipValidation, laxValidation))
1147                    {
1148                        if (!skipValidation)
1149                        {
1150                            Grammar* sGrammar = fGrammarList.getGrammar(uriId);
1151                            if (unlikely(sGrammar == NULL))
1152                            {
1153                                sGrammar = fGrammarResolver->getGrammar((*fNamespaceResolver)[uriId]);
1154                                fGrammarList.setGrammar(uriId, sGrammar);
1155                            }
1156
1157                            if (sGrammar && sGrammar->getGrammarType() == Grammar::SchemaGrammarType)
1158                            {
1159                                RefHashTableOf<XMLAttDef>* attRegistry = ((SchemaGrammar*)sGrammar)->getAttributeDeclRegistry();
1160                                if (attRegistry)
1161                                {
1162                                    attDef = reinterpret_cast<SchemaAttDef *>(attRegistry->get(localPart));
1163                                }
1164                            }
1165                        }
1166                    }
1167                }
1168                else if (currType)
1169                {
1170                    const unsigned int tempUriId =
1171                        (uriId == XMLNamespaceResolver::fEmptyUriId) ? fGrammar->getTargetNamespaceId(fNamespaceResolver) : XMLNamespaceResolver::fEmptyUriId;
1172
1173                    // not found, see if the attDef should be qualified or not
1174                    attDef = currType->getAttDef(localPart, tempUriId);
1175
1176                    if (unlikely(attDef && attDef->getCreateReason() != XMLAttDef::JustFaultIn) && fValidate)
1177                    {
1178                        XMLValid::Codes errCode =
1179                            (uriId == XMLNamespaceResolver::fEmptyUriId)
1180                            ? XMLValid::AttributeNotQualified
1181                            : XMLValid::AttributeNotUnQualified;
1182                        fSchemaValidator->emitError(errCode, attDef->getFullName());                       
1183                        attrValid = PSVIItem::VALIDITY_INVALID;
1184                    }
1185                }
1186            } // if (!attDef || (attDef->getCreateReason() == XMLAttDef::JustFaultIn))
1187
1188            if (likely(!!attDef))
1189            {
1190                attDef->setLastOccurrence(elementCount);
1191                attType = attDef->getType();
1192
1193                if (unlikely(attDef->getDefaultType() == XMLAttDef::Prohibited))
1194                {
1195                    // (schema) report error for PROHIBITED attrs that are present (V_TAGc)
1196                    fSchemaValidator->emitError(XMLValid::ProhibitedAttributePresent, attDef->getFullName());
1197                    attrValid = PSVIItem::VALIDITY_INVALID;
1198                }
1199                else
1200                {
1201                    //  Normalize the raw value since we have the attribute type. We
1202                    //  don't care about the return status here. If it failed, an error
1203                    //  will be issued, which is all we care about.
1204
1205                    const XMLCh * normalizedValue = value;
1206                    XMLSize_t normalizedLength = length;
1207
1208                    DatatypeValidator* tempDV = attDef->getDatatypeValidator();
1209                    if (tempDV && tempDV->getWSFacet() != DatatypeValidator::PRESERVE)
1210                    {
1211                        fSchemaValidator->normalizeWhiteSpace(tempDV->getWSFacet(), value, fWSNormalizeBuf, length, true);
1212                        normalizedValue = fWSNormalizeBuf.getRawBuffer();
1213                        normalizedLength = fWSNormalizeBuf.getLen();
1214                    }
1215
1216                    if (fValidate && !skipValidation)
1217                    {
1218                        fSchemaValidator->validateAttrValue(attDef, normalizedValue, false, &schemaElemDecl);
1219                        attrValidator = fSchemaValidator->getMostRecentAttrValidator();
1220                        if (unlikely(fSchemaValidator->getErrorOccurred()))
1221                        {
1222                            attrValid = PSVIItem::VALIDITY_INVALID;
1223                        }
1224                    }
1225
1226                    if (fNormalizeData)
1227                    {
1228                        value = normalizedValue;
1229                        length = normalizedLength;
1230                        normalized = true;
1231                    }
1232                }
1233            }
1234            else if (unlikely(!laxValidation && !skipValidation && fValidate))
1235            {
1236                reportUndefinedAttribute(uriId, attribute.getQName(), schemaElemDecl);
1237                attrValid = PSVIItem::VALIDITY_INVALID;
1238            }
1239            else
1240            {
1241                attrValid = PSVIItem::VALIDITY_NOTKNOWN;
1242                attrAssessed = laxValidation ? PSVIItem::VALIDATION_PARTIAL : PSVIItem::VALIDATION_NONE;
1243            }
1244        }
1245        else
1246        {
1247            attrValid = PSVIItem::VALIDITY_NOTKNOWN;
1248            attrAssessed = PSVIItem::VALIDATION_NONE;
1249        }
1250
1251        parser.writeAttribute(attName, attType, uriId, value, length, type, normalized | write);
1252
1253        if (doPSVI)
1254        {
1255            XSAttributeDeclaration * attrDecl = 0;
1256            XSSimpleTypeDefinition * memberType = 0;
1257            XSSimpleTypeDefinition * validatingType = 0;
1258            const XMLCh * defaultValue = 0;           
1259
1260            if (likely(!!attDef))
1261            {
1262                attrDecl = (XSAttributeDeclaration *)fModel->getXSObject(attDef);
1263                DatatypeValidator * attrDataType = attDef->getDatatypeValidator();
1264                validatingType = (XSSimpleTypeDefinition *)fModel->getXSObject(attrDataType);
1265                defaultValue = attDef->getValue();
1266                if (unlikely(attrValidator == 0))
1267                {
1268                    attrValidator = getAnySimpleTypeValidator();
1269                }
1270                if (likely(attrValid == PSVIItem::VALIDITY_VALID))
1271                {
1272                    if (unlikely(validatingType->getVariety() == XSSimpleTypeDefinition::VARIETY_UNION))
1273                    {
1274                        memberType = (XSSimpleTypeDefinition *)fModel->getXSObject(attrValidator);
1275                    }
1276                    attrValidator = (memberType) ? attrValidator : attrDataType;
1277                }
1278            }
1279            else if (attrValidator)
1280            {
1281                validatingType = (XSSimpleTypeDefinition *)fModel->getXSObject(attrValidator);
1282            }
1283
1284            parser.writeAttributePSVI(attrDecl, validatingType, memberType, defaultValue, attrValid, attrAssessed, attrValidator, false);
1285        }
1286
1287        if (unlikely(attrValid == PSVIItem::VALIDITY_INVALID))
1288        {
1289            error = true;
1290        }
1291    }
1292
1293    return 1;
1294}
1295
1296XMLSize_t IGXMLScanner::postAttributeValidation
1297(
1298      XMLElementDecl &              elemDecl
1299    , const QName *                 elemName
1300    , const XMLSize_t               elementCount
1301    , XMLSize_t                     attributeCount
1302    , const unsigned int            uriId
1303    , const bool                                        isRoot
1304    , const bool                                        isEmpty
1305    , const Grammar::GrammarType    grammarType
1306    , const bool                    doPSVI   
1307    , bool &                        error   
1308    , XMLDocumentAccumulator &      parser
1309)
1310{
1311    /// ------------------------------ POST ATTRIBUTE VALIDATION ---------------------------------
1312
1313    if (fValidate)
1314    {
1315        if (grammarType == Grammar::DTDGrammarType)
1316        {
1317            DTDElementDecl & dtdElemDecl = reinterpret_cast<DTDElementDecl&>(elemDecl);
1318
1319            //  Ok, so lets get an enumerator for the attributes of this element
1320            //  and run through them for well formedness and validity checks. But
1321            //  make sure that we had any attributes before we do it, since the list
1322            //  would have have gotten faulted in anyway.
1323            if (unlikely(dtdElemDecl.hasAttDefs()))
1324            {
1325                const XMLAttDefList & attDefList = dtdElemDecl.getAttDefList();
1326                size_t attDefCount = attDefList.getAttDefCount();
1327
1328                for (XMLSize_t i = 0; attDefCount--; i++)
1329                {
1330                    // Get the current att def, for convenience and its def type
1331                    const DTDAttDef & attDef = (DTDAttDef &)attDefList.getAttDef(i);
1332                    const XMLAttDef::DefAttTypes defType = attDef.getDefaultType();
1333
1334                    if (unlikely(attDef.getLastOccurrence() != elementCount))
1335                    {
1336                        // If we are validating and its required, then an error
1337                        if (defType == XMLAttDef::Required)
1338                        {
1339                            reportRequiredAttribute(attDef);
1340                        }
1341                    }
1342                }
1343            }
1344        }
1345        else // if (fDoNamespaces && (grammarType == Grammar::SchemaGrammarType))
1346        {
1347            ComplexTypeInfo * currType = 0;
1348            SchemaElementDecl & schemaElemDecl = reinterpret_cast<SchemaElementDecl&>(elemDecl);
1349
1350            currType = fSchemaValidator->getCurrentTypeInfo();
1351
1352            const bool hasDefs = (currType) ? currType->hasAttDefs() : schemaElemDecl.hasAttDefs();
1353
1354            //  Now, if there are any attributes declared by this element, let's
1355            //  go through them and make sure that any required ones are provided,
1356            //  and fault in any fixed ones and defaulted ones that are not provided
1357            //  literally.
1358            if (unlikely(hasDefs))
1359            {
1360                // Check after all specified attrs are scanned
1361                // (1) report error for REQUIRED attrs that are missing (V_TAGc)
1362                // (2) add default attrs if missing (FIXED and NOT_FIXED)
1363
1364                const XMLAttDefList & attDefList = (currType) ? currType->getAttDefList() : schemaElemDecl.getAttDefList();
1365                size_t attDefCount = attDefList.getAttDefCount();
1366
1367                for (XMLSize_t i = 0; attDefCount--; i++)
1368                {
1369                    // Get the current att def, for convenience and its def type
1370                    const SchemaAttDef & attDef = (SchemaAttDef &)attDefList.getAttDef(i);
1371                    const XMLAttDef::DefAttTypes defType = attDef.getDefaultType();
1372
1373                    // if this attribute is not present within the element
1374                    if (unlikely(attDef.getLastOccurrence() != elementCount))
1375                    {
1376                        //the attribute is not provided
1377                        if ((defType == XMLAttDef::Required) || (defType == XMLAttDef::Required_And_Fixed))
1378                        {
1379                            reportRequiredAttribute(attDef);
1380                            error = true;
1381                        }
1382                        else if ((defType == XMLAttDef::Default) || (defType == XMLAttDef::Fixed))
1383                        {
1384                            if (fStandalone && attDef.isExternal())
1385                            {
1386                                // XML 1.0 Section 2.9
1387                                // Document is standalone, so attributes must not be defaulted.
1388                                fSchemaValidator->emitError(XMLValid::NoDefAttForStandalone, attDef.getFullName(), schemaElemDecl.getFullName());
1389                                error = true;
1390                            }
1391
1392                            // Let the validator pass judgement on the attribute value
1393                            fSchemaValidator->validateAttrValue(&attDef, attDef.getValue(), false, &schemaElemDecl);
1394
1395                            parser.writeAttribute(attDef.getAttName(), attDef.getType(), attDef.getAttName()->getURI(), attDef.getValue(), XMLString::stringLen(attDef.getValue()), SchemaDefaultAttribute, false);
1396
1397                            if (doPSVI)
1398                            {
1399                                XSAttributeDeclaration * attrDecl = (XSAttributeDeclaration *)fModel->getXSObject((void*)&attDef);
1400                                DatatypeValidator * attrValidator = attDef.getDatatypeValidator();
1401                                XSSimpleTypeDefinition *validatingType = (XSSimpleTypeDefinition*)fModel->getXSObject(attrValidator);
1402                                PSVIItem::VALIDITY_STATE attrValid = PSVIItem::VALIDITY_VALID;
1403                                XSSimpleTypeDefinition * memberType = 0;
1404                                // check if any error occurred during the validation of default value
1405                                if (unlikely(fSchemaValidator->getErrorOccurred()))
1406                                {
1407                                    attrValidator = 0;
1408                                    attrValid = PSVIItem::VALIDITY_INVALID;
1409                                }
1410                                else if (validatingType->getVariety() == XSSimpleTypeDefinition::VARIETY_UNION)
1411                                {
1412                                    DatatypeValidator * mostRecentAttrValidator = fSchemaValidator->getMostRecentAttrValidator();
1413                                    memberType = (XSSimpleTypeDefinition*)fModel->getXSObject(mostRecentAttrValidator);
1414                                    if (memberType)
1415                                    {
1416                                        attrValidator = mostRecentAttrValidator;
1417                                    }
1418                                }
1419                                parser.writeAttributePSVI(attrDecl, validatingType, memberType, attDef.getValue(), attrValid, PSVIItem::VALIDATION_FULL, attrValidator, true);
1420                            }
1421                            // increase the attributeCount
1422                            attributeCount++;
1423                        }
1424                    }
1425                }
1426            }
1427        }
1428    }
1429
1430    /// ------------------------------ END OF TAG HANDLING ---------------------------------
1431
1432    parser.writeStartTag(elemDecl, elemName, uriId, attributeCount, isEmpty);
1433
1434    //  If empty, validate content right now if we are validating and then
1435    //  pop the element stack top. Else, we have to update the current stack
1436    //  top's namespace mapping elements.
1437    if (isEmpty)
1438    {
1439        // Pop the element stack back off since it'll never be used now
1440        fElemStack.popTop();
1441
1442        if (grammarType == Grammar::DTDGrammarType)
1443        {                       
1444            // If validating, then insure that its legal to have no content
1445            if (fValidate)
1446            {
1447                XMLSize_t failure;
1448                if (unlikely(!fDTDValidator->checkContent(&elemDecl, ((XMLElementDecl**)0), 0, &failure)))
1449                {
1450                    fDTDValidator->emitError(XMLValid::ElementNotValidForContent, elemDecl.getFullName(), elemDecl.getFormattedContentModel());
1451                    error = true;
1452                }
1453            }               
1454        }
1455        else // if (grammarType == Grammar::SchemaGrammarType)
1456        {
1457            const Grammar::GrammarType grammarType = fGrammarType;
1458
1459            if (likely(grammarType == Grammar::SchemaGrammarType))
1460            {
1461                // reset error occurred
1462                if (fValidate && elemDecl.isDeclared())
1463                {
1464                    fPSVIElemContext.fCurrentTypeInfo = fSchemaValidator->getCurrentTypeInfo();
1465                    fPSVIElemContext.fCurrentDV = fPSVIElemContext.fCurrentTypeInfo ? 0 : fSchemaValidator->getCurrentDatatypeValidator();
1466                    fPSVIElemContext.fNormalizedValue = doPSVI ? subsituteEmptyStringWithNull(fSchemaValidator->getNormalizedValue()) : 0;
1467                }
1468                else
1469                {
1470                    fPSVIElemContext.fCurrentDV = 0;
1471                    fPSVIElemContext.fCurrentTypeInfo = 0;
1472                    fPSVIElemContext.fNormalizedValue = 0;
1473                }
1474            }
1475
1476            if (fValidate)
1477            {               
1478                bool hasSpecifiedValue = false;
1479                XMLSize_t failure;
1480
1481                // reset current type info
1482                if (likely(elemDecl.isDeclared()))
1483                {
1484                    fPSVIElemContext.fCurrentTypeInfo = fSchemaValidator->getCurrentTypeInfo();
1485                    fPSVIElemContext.fCurrentDV = fPSVIElemContext.fCurrentTypeInfo ? 0 : fSchemaValidator->getCurrentDatatypeValidator();
1486                    fPSVIElemContext.fNormalizedValue = doPSVI ? subsituteEmptyStringWithNull(fSchemaValidator->getNormalizedValue()) : 0;
1487                }
1488                else
1489                {
1490                    fPSVIElemContext.fCurrentTypeInfo = 0;
1491                    fPSVIElemContext.fCurrentDV = 0;
1492                    fPSVIElemContext.fNormalizedValue = 0;
1493                }
1494                fPSVIElemContext.fIsSpecified = false;
1495
1496
1497                // If validating, then ensure that it's legal to have no content
1498                if (unlikely(!fSchemaValidator->checkContent(&elemDecl, ((XMLElementDecl**)0), 0, &failure)))
1499                {
1500                    fSchemaValidator->emitError(XMLValid::ElementNotValidForContent, elemDecl.getFullName(), elemDecl.getFormattedContentModel());
1501                    error = true;
1502                }
1503                else if (unlikely(fSchemaValidator->getErrorOccurred()))
1504                {
1505                    error = true;
1506                }
1507                else if (unlikely(fSchemaValidator->getIsElemSpecified()))
1508                {                   
1509                    fPSVIElemContext.fNormalizedValue = ((SchemaElementDecl &)elemDecl).getDefaultValue();
1510
1511                    // even though this element is empty, if it has a specified content value then it must be transformed into
1512                    // a start and end tag pair. Ergo, this element is only marked as empty if and only if it has no specified value.
1513
1514                    parser.invertEmptyTag();
1515                    if (doPSVI)
1516                    {
1517                        parser.writePartialElementPSVI(NULL, NULL, true);
1518                    }
1519                    parser.writeContent(fPSVIElemContext.fNormalizedValue, XMLString::stringLen(fPSVIElemContext.fNormalizedValue), false, true);
1520                    parser.writeEndTag(elemDecl, elemName, uriId);
1521                }
1522
1523
1524                if (doPSVI)
1525                {
1526                    // note that if we're empty, won't be a current DV                   
1527                    fPSVIElemContext.fIsSpecified = hasSpecifiedValue;
1528                    fPSVIElemContext.fErrorOccurred = error;
1529                    endElementPSVI((SchemaElementDecl &)elemDecl, parser);
1530                }
1531            }
1532            else
1533            {
1534                fSchemaValidator->resetNillable();
1535            }
1536        }
1537
1538        // If the elem stack is empty, then it was an empty root
1539        if (likely(!isRoot))
1540        {
1541            // if namespaces exist, then its possible we have multiple grammars. check to see what the previous grammar was.
1542            if (fDoNamespaces)
1543            {
1544                // Restore the grammar
1545                setCurrentGrammar(fElemStack.getCurrentGrammar());
1546            }
1547            // Restore the validation flag
1548            fValidate = fElemStack.getValidationFlag();
1549        }
1550    }
1551    else // if (!isEmpty)
1552    {
1553        if (doPSVI)
1554        {
1555            // send a partial element psvi
1556            XSElementDeclaration * xsElemDecl = 0;
1557            XSTypeDefinition * typeDef = 0;
1558            if (likely(elemDecl.isDeclared()))
1559            {
1560                xsElemDecl = (XSElementDeclaration*) fModel->getXSObject(&elemDecl);
1561                if (likely(fValidate))
1562                {
1563                    ComplexTypeInfo * const curTypeInfo = fSchemaValidator->getCurrentTypeInfo();
1564                    if (curTypeInfo)
1565                    {
1566                        typeDef = (XSTypeDefinition*) fModel->getXSObject(curTypeInfo);
1567                    }
1568                    else
1569                    {
1570                        DatatypeValidator * const curDV = fSchemaValidator->getCurrentDatatypeValidator();
1571                        if (curDV)
1572                        {
1573                            typeDef = (XSTypeDefinition*) fModel->getXSObject(curDV);
1574                        }
1575                    }
1576                }
1577            }
1578
1579            // fSchemaValidator->getIsElemSpecified() will always return false until SchemaValidator::checkContent(...) is called.
1580            parser.writePartialElementPSVI(xsElemDecl, typeDef, false);
1581        }
1582    }
1583
1584    return attributeCount;
1585}
1586
1587// --------------------------------------------------------------------------------------------------------
1588// HANDLE END TAG
1589// --------------------------------------------------------------------------------------------------------
1590
1591void IGXMLScanner::validateEndTag
1592(
1593    XMLElementDecl &                        elemDecl
1594    , const QName *                         elemName
1595    , const unsigned int                    uriId
1596    , const bool                            isRoot
1597    , XMLElementDecl **                     children
1598    , const XMLSize_t                       childCount
1599    , const bool                            doPSVI
1600    , bool &                                error
1601    , XMLDocumentAccumulator &              parser
1602)
1603{
1604    DEBUG_GRAMMAR_MESSAGE("validateEndTag(" << elemDecl << ',' << elemName << ',' << uriId << ',' << isRoot << ',' << childCount << ',' << doPSVI << ')');
1605
1606    const Grammar::GrammarType grammarType = fGrammarType;
1607
1608    if (likely(grammarType == Grammar::SchemaGrammarType))
1609    {
1610        // reset error occurred
1611        if (fValidate && elemDecl.isDeclared())
1612        {
1613            fPSVIElemContext.fCurrentTypeInfo = fSchemaValidator->getCurrentTypeInfo();
1614            fPSVIElemContext.fCurrentDV = fPSVIElemContext.fCurrentTypeInfo ? 0 : fSchemaValidator->getCurrentDatatypeValidator();
1615            fPSVIElemContext.fNormalizedValue = doPSVI ? subsituteEmptyStringWithNull(fSchemaValidator->getNormalizedValue()) : 0;
1616        }
1617        else
1618        {
1619            fPSVIElemContext.fCurrentDV = 0;
1620            fPSVIElemContext.fCurrentTypeInfo = 0;
1621            fPSVIElemContext.fNormalizedValue = 0;
1622        }
1623    }
1624
1625    bool isSpecified = false;
1626
1627    //  If validation is enabled, then lets pass him the list of children and
1628    //  this element and let him validate it.
1629    if (fValidate)
1630    {       
1631        XMLSize_t failure;
1632        if (unlikely(!fValidator->checkContent(&elemDecl, children, childCount, &failure)))
1633        {
1634            //  One of the elements is not valid for the content. NOTE that
1635            //  if no children were provided but the content model requires
1636            //  them, it comes back with a zero value. But we cannot use that
1637            //  to index the child array in this case, and have to put out a
1638            //  special message.
1639            if (!childCount)
1640            {
1641                fValidator->emitError(XMLValid::EmptyNotValidForContent, elemDecl.getFormattedContentModel());
1642            }
1643            else if (failure >= childCount)
1644            {
1645                fValidator->emitError(XMLValid::NotEnoughElemsForCM, elemDecl.getFormattedContentModel());               
1646            }
1647            else
1648            {
1649                fValidator->emitError(XMLValid::ElementNotValidForContent, children[failure]->getFullName(), elemDecl.getFormattedContentModel());
1650            }
1651            error = true;
1652        }
1653
1654        if (likely(grammarType == Grammar::SchemaGrammarType))
1655        {           
1656            if (fSchemaValidator->getErrorOccurred())
1657            {
1658                error = true;
1659            }
1660            else
1661            {
1662                if (unlikely(fSchemaValidator->getIsElemSpecified()))
1663                {
1664                    const XMLCh * defaultValue = ((SchemaElementDecl&)elemDecl).getDefaultValue();
1665                    fPSVIElemContext.fNormalizedValue = ((SchemaElementDecl &)elemDecl).getDefaultValue();
1666                    parser.writeContent(defaultValue, XMLString::stringLen(defaultValue));
1667                    isSpecified = true;
1668                }
1669            }
1670        }
1671    }
1672    else if (grammarType == Grammar::SchemaGrammarType)
1673    {
1674        fSchemaValidator->resetNillable();
1675    }
1676
1677    parser.writeEndTag(elemDecl, elemName, uriId);
1678
1679    // QName dv needed topElem to resolve URIs on the checkContent
1680    fElemStack.popTop();
1681
1682    if (grammarType == Grammar::SchemaGrammarType)
1683    {
1684        if (doPSVI)
1685        {
1686            fPSVIElemContext.fIsSpecified = isSpecified;
1687            fPSVIElemContext.fErrorOccurred = error;
1688            endElementPSVI((SchemaElementDecl&)elemDecl, parser);
1689        }
1690        fSchemaValidator->clearDatatypeBuffer();
1691    }
1692
1693
1694    // If this was the root, then done with content
1695    if (likely(!isRoot))
1696    {
1697        if (fDoNamespaces)
1698        {
1699            // Restore the grammar
1700            fGrammar = fElemStack.getCurrentGrammar();
1701            fGrammarType = fGrammar->getGrammarType();
1702
1703            if (fGrammarType == Grammar::SchemaGrammarType && !fValidator->handlesSchema())
1704            {
1705                if (fValidatorFromUser)
1706                {
1707                    ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoSchemaValidator, fMemoryManager);
1708                }
1709                else
1710                {
1711                    fValidator = fSchemaValidator;
1712                }
1713            }
1714            else if (fGrammarType == Grammar::DTDGrammarType && !fValidator->handlesDTD())
1715            {
1716                if (fValidatorFromUser)
1717                {
1718                    ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoDTDValidator, fMemoryManager);
1719                }
1720                else
1721                {
1722                    fValidator = fDTDValidator;
1723                }
1724            }
1725            fValidator->setGrammar(fGrammar);
1726        }
1727
1728        // Restore the validation flag
1729        fValidate = fElemStack.getValidationFlag();
1730    }
1731}
1732
1733// --------------------------------------------------------------------------------------------------------
1734// HANDLE SCHEMA WHITESPACE NORMALIZATION
1735// --------------------------------------------------------------------------------------------------------
1736
1737bool IGXMLScanner::doSchemaWhitespaceNormalization
1738(
1739    const XMLCh     * &             content
1740    , XMLSize_t &                   length
1741)
1742{
1743    DatatypeValidator * dv = fSchemaValidator->getCurrentDatatypeValidator();
1744    bool normalized = false;
1745    const XMLCh * normalizedContent = content;
1746    XMLSize_t normalizedLength = length;
1747    if (dv && dv->getWSFacet() != DatatypeValidator::PRESERVE)
1748    {
1749        // normalize the character according to schema whitespace facet
1750        fSchemaValidator->normalizeWhiteSpace(dv->getWSFacet(), content, fWSNormalizeBuf, length, false);
1751        normalizedContent = fWSNormalizeBuf.getRawBuffer();
1752        normalizedLength = fWSNormalizeBuf.getLen();
1753        normalized = fNormalizeData;
1754    }
1755
1756    // tell the schema validation about the character data for checkContent later
1757    fSchemaValidator->setDatatypeBuffer(normalizedContent);
1758
1759    if (normalized)
1760    {
1761        content = normalizedContent;
1762        length = normalizedLength;
1763    }
1764    return normalized;
1765}
1766
1767// --------------------------------------------------------------------------------------------------------
1768// HANDLE CONTENT
1769// --------------------------------------------------------------------------------------------------------
1770
1771void IGXMLScanner::validateContent
1772(
1773    const XMLCh     *               content
1774    , XMLSize_t                     length
1775    , const XMLContentFlag          flags
1776    , const bool                    doPSVI
1777    , XMLDocumentAccumulator &      parser
1778    , const bool                    write
1779)
1780{
1781    //  We do different things according to whether we are validating or
1782    //  not. If not, its always just characters; else, it depends on the
1783    //  current element's content model.
1784    if (fValidate)
1785    {
1786        // bool hasContentCommenPItOrRef = (length) || (flags & (HasCommentOrProcessingInstruction | ContainsEntityReference));
1787
1788        // Get the character data opts for the current element
1789        XMLElementDecl::CharDataOpts charOpts = XMLElementDecl::AllCharData;
1790        const XMLElementDecl * elemDecl = 0;
1791        if (fGrammarType == Grammar::SchemaGrammarType)
1792        {           
1793            // And see if the current element is a 'Children' style content model
1794            ComplexTypeInfo * currType = fSchemaValidator->getCurrentTypeInfo();
1795            DEBUG_MESSAGE("currType=" << currType)
1796            if (currType)
1797            {
1798                switch ((SchemaElementDecl::ModelTypes)currType->getContentType())
1799                {
1800                    case SchemaElementDecl::Empty:
1801                        charOpts = XMLElementDecl::NoCharData;
1802                        break;
1803                    case SchemaElementDecl::Children:
1804                    case SchemaElementDecl::ElementOnlyEmpty:
1805                        charOpts = XMLElementDecl::SpacesOk;
1806                }
1807            }
1808        }
1809        else // if (fGrammarType == Grammar::DTDGrammarType)
1810        {
1811            // And see if the current element is a 'Children' style content model
1812            elemDecl = fElemStack.topElement()->fThisElement;
1813            charOpts = ((const DTDElementDecl*)elemDecl)->getCharDataOpts();
1814        }
1815
1816        bool contentModelError = 0;
1817
1818        if (charOpts == XMLElementDecl::AllCharData)
1819        {
1820            if (length)
1821            {
1822                bool normalized = false;
1823                if (fGrammarType == Grammar::SchemaGrammarType)
1824                {
1825                    normalized = doSchemaWhitespaceNormalization(content, length);
1826                }
1827                parser.writeContent(content, length, write | normalized, doPSVI);
1828            }
1829        }
1830        else if (charOpts == XMLElementDecl::SpacesOk)
1831        {
1832            if (length == 0)
1833            {
1834                // do nothing
1835            }
1836            else if (XMLStringU::isWhitespace(content, length))
1837            {
1838                // XML 1.0 Section 2.9
1839
1840                // The standalone document declaration MUST have the value "no" if any external markup declarations contain declarations of
1841                // element types with element content, if white space occurs directly within any instance of those types.
1842
1843                if (unlikely(fStandalone && fValidate))
1844                {
1845                    elemDecl = fElemStack.topElement()->fThisElement;
1846                    if (unlikely(elemDecl->isExternal()))
1847                    {
1848                        fValidator->emitError(XMLValid::NoWSForStandalone);
1849                    }
1850                }
1851                parser.writeIgnorableWhitespace(content, length, write);
1852            }
1853            else
1854            {
1855                contentModelError = 1;
1856            }
1857        }
1858        else // if (charOpts == XMLElementDecl::NoCharData)
1859        {
1860            contentModelError = (length) || (flags & (HasCommentOrProcessingInstruction | ContainsEntityReference));
1861        }
1862
1863        if (unlikely(contentModelError))
1864        {
1865            XMLValid::Codes errorCode = XMLValid::NoCharDataInCM;
1866            if (unlikely(fGrammarType == Grammar::DTDGrammarType))
1867            {
1868                const DTDElementDecl::ModelTypes modelType = ((const DTDElementDecl*)elemDecl)->getModelType();
1869
1870                // XML1.0-3rd
1871                // Validity Constraint:
1872
1873                // The declaration matches EMPTY and the element has no content (not even entity references, comments, PIs or white space).
1874                if (unlikely(((flags & HasCommentOrProcessingInstruction) || length) && modelType == DTDElementDecl::Empty))
1875                {
1876                    errorCode = XMLValid::EmptyElemHasContent;
1877                }
1878
1879                //
1880                // XML1.0-3rd
1881                // Validity Constraint:
1882                //
1883                // The declaration matches children and the sequence of child elements
1884                // belongs to the language generated by the regular expression in the
1885                // content model, with optional white space, comments and PIs
1886                // (i.e. markup matching production [27] Misc) between the start-tag and
1887                // the first child element, between child elements, or between the last
1888                // child element and the end-tag.
1889                //
1890                // Note that
1891                //    a CDATA section containing only white space or
1892                //    a reference to an entity whose replacement text is character references
1893                //       expanding to white space do not match the nonterminal S, and hence
1894                //       cannot appear in these positions; however,
1895                //    a reference to an internal entity with a literal value consisting
1896                //       of character references expanding to white space does match S,
1897                //       since its replacement text is the white space resulting from expansion
1898                //       of the character references.
1899                //
1900                if (unlikely((flags & ContainsEntityReference) && modelType == DTDElementDecl::Children))
1901                {
1902                    errorCode = XMLValid::ElemChildrenHasInvalidWS;
1903                }
1904            }
1905
1906            if (errorCode == XMLValid::NoCharDataInCM)
1907            {
1908                // either there is an error or no char data is allowed
1909                fValidator->emitError(XMLValid::NoCharDataInCM);
1910            }
1911            else
1912            {
1913                fValidator->emitError(errorCode, elemDecl->getFullName());
1914                // even though an error occured, write out the content anyway
1915                if (errorCode == XMLValid::ElemChildrenHasInvalidWS)
1916                {
1917                    parser.writeContent(content, length, write);
1918                }
1919            }
1920        }
1921    }
1922    else if (length)
1923    {
1924        parser.writeContent(content, length, write);
1925    }
1926}
1927
1928// --------------------------------------------------------------------------------------------------------
1929
1930void IGXMLScanner::validateCDATA
1931(
1932    const XMLCh       *             cdata
1933    , XMLSize_t                     length
1934    , const bool                    doPSVI
1935    , XMLDocumentAccumulator &      parser
1936)
1937{
1938    bool normalized = false;
1939
1940    if (fValidate)
1941    {
1942
1943        const ElemStack::StackElem* topElem = fElemStack.topElement();
1944
1945        // Get the character data opts for the current element
1946        XMLElementDecl::CharDataOpts charOpts = XMLElementDecl::AllCharData;
1947
1948        if (fGrammarType == Grammar::SchemaGrammarType)
1949        {
1950            ComplexTypeInfo * currType = fSchemaValidator->getCurrentTypeInfo();
1951            if (currType)
1952            {
1953                switch ((SchemaElementDecl::ModelTypes)currType->getContentType())
1954                {
1955                    case SchemaElementDecl::Empty:
1956                        charOpts = XMLElementDecl::NoCharData;
1957                        break;
1958                    case SchemaElementDecl::Children:
1959                    case SchemaElementDecl::ElementOnlyEmpty:
1960                        charOpts = XMLElementDecl::SpacesOk;
1961                }
1962            }
1963
1964            normalized = doSchemaWhitespaceNormalization(cdata, length);
1965        }
1966        else // if (fGrammarType == Grammar::DTDGrammarType)
1967        {
1968            charOpts = topElem->fThisElement->getCharDataOpts();
1969        }
1970
1971        if (charOpts != XMLElementDecl::AllCharData)
1972        {
1973            if (unlikely((charOpts == XMLElementDecl::SpacesOk) && fStandalone && XMLStringU::isWhitespace(cdata, length)))
1974            {
1975                // XML 1.0 Section 2.9
1976
1977                // The standalone document declaration MUST have the value "no" if any external markup declarations contain declarations of
1978                // element types with element content, if white space occurs directly within any instance of those types.
1979
1980                XMLElementDecl * const elemDecl = topElem->fThisElement;
1981                if (unlikely(elemDecl->isExternal()))
1982                {
1983                    fValidator->emitError(XMLValid::NoWSForStandalone);
1984                }
1985            }
1986            else
1987            {
1988                // They definitely cannot handle any type of char data
1989                fValidator->emitError(XMLValid::NoCharDataInCM);
1990            }
1991        }
1992
1993
1994
1995    }
1996
1997    parser.writeCDATA(cdata, length, normalized, doPSVI);
1998}
1999
2000// ----------------------------------------------------------------------------------------------
2001
2002void IGXMLScanner::setXsiType
2003(
2004    const XMLCh *                               prefix
2005    , const XMLCh *             localPart
2006    , const unsigned int        uriId
2007)
2008{
2009        if (fSchemaValidator)
2010        {
2011        if (unlikely(!fValidator->handlesSchema()))
2012        {
2013            switchToSchemaGrammar();
2014        }
2015
2016        fSchemaValidator->setXsiType(prefix, localPart, uriId);
2017        }
2018
2019}
2020
2021void IGXMLScanner::setXsiNil
2022(
2023        const XMLCh *                           value
2024        , const XMLSize_t                       length
2025)
2026{
2027        if (fSchemaValidator)
2028        {
2029        if (unlikely(!fValidator->handlesSchema()))
2030        {
2031            switchToSchemaGrammar();
2032        }
2033
2034        if (length == 4 && XMLString::equals(value, SchemaSymbols::fgATTVAL_TRUE))
2035                {
2036                        fSchemaValidator->setNillable(true);
2037                }
2038        else if (length == 5 && XMLString::equals(value, SchemaSymbols::fgATTVAL_FALSE))
2039                {
2040                        fSchemaValidator->setNillable(false);
2041                }
2042                else
2043                {
2044                        emitError(XMLErrs::InvalidAttValue, value, value);
2045                }
2046        }
2047}
2048
2049bool IGXMLScanner::preValidateDefaultAttribute(const QName & element, const QName & attribute, const bool isExternal) const
2050{
2051    if (unlikely(getStandalone() && isExternal))
2052    {
2053        fDTDValidator->emitError(XMLValid::NoDefAttForStandalone, attribute.getRawName(), element.getRawName());
2054    }
2055    return true;
2056}
2057
2058// ----------------------------------------------------------------------------------------------
2059
2060void IGXMLScanner::endElementPSVI(SchemaElementDecl & element, XMLDocumentAccumulator & parser)
2061{
2062    XSTypeDefinition* typeDef = 0;
2063    PSVIElement::ASSESSMENT_TYPE assessmentType;
2064    PSVIElement::VALIDITY_STATE validity = PSVIElement::VALIDITY_NOTKNOWN;
2065    bool isMixed = false;   
2066    DatatypeValidator * const currentDV = fPSVIElemContext.fCurrentDV;
2067    DatatypeValidator * memberDV = 0;
2068    XSSimpleTypeDefinition * memberType = 0;
2069
2070    DEBUG_MESSAGE(" -- currentDV=" << currentDV)
2071
2072    // note that if we're empty, won't be a current DV
2073    if (currentDV && currentDV->getType() == DatatypeValidator::Union)
2074    {
2075        memberDV = fValidationContext->getValidatingMemberType();
2076    }
2077
2078    DEBUG_MESSAGE(" -- memberDV=" << memberDV)
2079
2080    if (memberDV)
2081    {
2082        memberType = (XSSimpleTypeDefinition*)fModel->getXSObject(memberDV);
2083    }
2084    else
2085    {
2086        memberDV = currentDV;
2087    }
2088
2089    DEBUG_MESSAGE(" -- memberType=" << memberType)
2090
2091    if (fPSVIElemContext.fElemDepth > fPSVIElemContext.fFullValidationDepth)
2092    {
2093        assessmentType = PSVIElement::VALIDATION_FULL;
2094    }
2095    else if (fPSVIElemContext.fElemDepth > fPSVIElemContext.fNoneValidationDepth)
2096    {
2097        assessmentType = PSVIElement::VALIDATION_NONE;
2098    }
2099    else
2100    {
2101        assessmentType  = PSVIElement::VALIDATION_PARTIAL;
2102        fPSVIElemContext.fFullValidationDepth = fPSVIElemContext.fElemDepth - 1;
2103        fPSVIElemContext.fNoneValidationDepth = fPSVIElemContext.fElemDepth - 1;
2104    }
2105
2106    fPSVIElemContext.fElemDepth--;
2107
2108    XSElementDeclaration * elemDecl = 0;
2109    if (likely(element.isDeclared()))
2110    {
2111        elemDecl = (XSElementDeclaration*) fModel->getXSObject(&element);
2112        validity = (fPSVIElemContext.fErrorOccurred && fValidate) ? PSVIElement::VALIDITY_INVALID : PSVIElement::VALIDITY_VALID;
2113    }
2114
2115    if (fPSVIElemContext.fCurrentTypeInfo)
2116    {
2117        typeDef = (XSTypeDefinition*) fModel->getXSObject(fPSVIElemContext.fCurrentTypeInfo);
2118        SchemaElementDecl::ModelTypes modelType = (SchemaElementDecl::ModelTypes)(fPSVIElemContext.fCurrentTypeInfo->getContentType());
2119        isMixed = (modelType == SchemaElementDecl::Mixed_Simple || modelType == SchemaElementDecl::Mixed_Complex);
2120    }
2121    else if (currentDV)
2122    {
2123        typeDef = (XSTypeDefinition*) fModel->getXSObject(currentDV);
2124    }
2125
2126    DEBUG_MESSAGE(" -- typeDef=" << typeDef)
2127
2128    // TODO: modify all the getCanonicalRepresentation functions so that most of them aren't simply validating and returning a duplicate of the string.
2129    // NOTE: I ought to insert the appropriate canonical value into the psvi string pool directly if and only if it differs from the normalized value.
2130    XMLCh* canonicalValue = 0;
2131    if (fPSVIElemContext.fNormalizedValue && !isMixed && memberDV && validity == PSVIElement::VALIDITY_VALID)
2132    {
2133        canonicalValue = (XMLCh*)memberDV->getCanonicalRepresentation(fPSVIElemContext.fNormalizedValue, fMemoryManager);
2134    }
2135
2136    parser.writeElementPSVI(elemDecl, typeDef, memberType, fPSVIElemContext.fNormalizedValue, canonicalValue, validity, assessmentType, fPSVIElemContext.fIsSpecified);
2137
2138    if (canonicalValue)
2139    {
2140        XMLString::release(&canonicalValue, fMemoryManager);
2141    }
2142}
2143
2144// ----------------------------------------------------------------------------------------------
2145
2146bool IGXMLScanner::laxElementValidation
2147(
2148    const QName *                           element
2149    , const unsigned int                    elementUriId
2150    , const ContentLeafNameTypeVector *     cv
2151    , const XMLContentModel* const          cm
2152    , const XMLSize_t                       parentElemDepth
2153)
2154{
2155    if (cv == 0)
2156    {
2157        return false;
2158    }
2159
2160    unsigned int currState = fElemState[parentElemDepth];
2161
2162    if (currState == XMLContentModel::gInvalidTrans)
2163    {
2164        return false;
2165    }
2166
2167    unsigned int currLoop = fElemLoopState[parentElemDepth];
2168
2169    SubstitutionGroupComparator comparator(fGrammarResolver, fNamespaceResolver);
2170
2171    XMLSize_t i = 0;
2172    XMLSize_t leafCount = cv->getLeafCount();
2173    unsigned int nextState = 0;
2174
2175    for (; i < leafCount; i++)
2176    {
2177        QName* fElemMap = cv->getLeafNameAt(i);
2178        unsigned int mappedUriId = fElemMap->getURI();
2179        ContentSpecNode::NodeTypes type = cv->getLeafTypeAt(i);
2180
2181        if (type == ContentSpecNode::Leaf)
2182        {
2183            if (((mappedUriId == elementUriId) && (fElemMap->getLocalPart() == element->getLocalPart())) || comparator.isEquivalentTo(element, fElemMap))
2184            {
2185                nextState = cm->getNextState(currState, i);
2186                if (nextState != XMLContentModel::gInvalidTrans)
2187                    break;
2188            }
2189        }
2190        else if ((type & 0x0f) == ContentSpecNode::Any)
2191        {
2192            nextState = cm->getNextState(currState, i);
2193            if (nextState != XMLContentModel::gInvalidTrans)
2194                break;
2195        }
2196        else if ((type & 0x0f) == ContentSpecNode::Any_Other)
2197        {
2198            if (mappedUriId != elementUriId && elementUriId != XMLNamespaceResolver::fEmptyUriId)
2199            {
2200                nextState = cm->getNextState(currState, i);
2201                if (nextState != XMLContentModel::gInvalidTrans)
2202                    break;
2203            }
2204        }
2205        else if ((type & 0x0f) == ContentSpecNode::Any_NS)
2206        {
2207            if (mappedUriId == elementUriId)
2208            {
2209                nextState = cm->getNextState(currState, i);
2210                if (nextState != XMLContentModel::gInvalidTrans)
2211                    break;
2212            }
2213        }
2214    } // for
2215
2216    if (i == leafCount) // no match
2217    {
2218        fElemState[parentElemDepth] = XMLContentModel::gInvalidTrans;
2219        fElemLoopState[parentElemDepth] = 0;
2220        return false;
2221    }
2222
2223    unsigned int nextLoop = 0;
2224    if (!cm->handleRepetitions(element, currState, currLoop, nextState, nextLoop, i, &comparator))
2225    {
2226        fElemState[parentElemDepth] = XMLContentModel::gInvalidTrans;
2227        fElemLoopState[parentElemDepth] = 0;
2228        return false;
2229    }
2230
2231
2232    bool skipThisOne = false;
2233    bool laxThisOne = false;
2234
2235    const ContentSpecNode::NodeTypes type = cv->getLeafTypeAt(i);
2236    switch (type & 0xF)
2237    {
2238        case ContentSpecNode::Any:
2239        case ContentSpecNode::Any_Other:
2240        case ContentSpecNode::Any_NS:
2241            laxThisOne = (type >> 4) & 1;   // 16
2242            skipThisOne = (type >> 5) & 1;  // 32
2243            break;
2244    }
2245
2246    fElemState[parentElemDepth] = nextState;
2247    fElemLoopState[parentElemDepth] = nextLoop;
2248
2249    fValidate &= !skipThisOne;
2250
2251    return laxThisOne;
2252}
2253
2254XERCES_CPP_NAMESPACE_END
2255
2256#endif
Note: See TracBrowser for help on using the repository browser.