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

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

Updates for build

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