Ignore:
Timestamp:
Jan 12, 2013, 12:21:29 PM (6 years ago)
Author:
cameron
Message:

Fixes default attribute+namespace resolution; hashing

File:
1 edited

Legend:

Unmodified
Added
Removed
  • icXML/icXML-devel/src/icxercesc/internal/IGXMLScanner.hpp

    r2734 r2807  
    4141#include <xercesc/framework/psvi/PSVIElement.hpp>
    4242
     43#include <xercesc/framework/psvi/PSVIHandler.hpp>
     44#include <xercesc/validators/schema/identity/IdentityConstraintHandler.hpp>
     45
    4346#include <xercesc/util/XMLStringTokenizer.hpp>
    4447
     
    5154class DTDValidator;
    5255class SchemaValidator;
    53 class IdentityConstraintHandler;
    5456class IdentityConstraint;
    5557class ContentLeafNameTypeVector;
     
    117119        //  XMLScanner parabix virtual methods
    118120        // -----------------------------------------------------------------------
    119         virtual void handleCDATA
    120         (
    121                 const XMLCh       * cdata
    122                 , const XMLSize_t   cdataLength
    123         );
    124 
    125         virtual void handleContent
     121
     122    IDISA_ALWAYS_INLINE
     123    void handleContent
    126124        (
    127125                  const XMLCh     *       content
    128                 , const XMLSize_t         contentLength
     126        , const XMLSize_t         length
    129127        );
    130128
    131         virtual XMLElementDecl * handleStartTag
     129    IDISA_ALWAYS_INLINE
     130    void handleCDATA
     131    (
     132        const XMLCh       * cdata
     133        , const XMLSize_t   length
     134    );
     135
     136    IDISA_ALWAYS_INLINE
     137    XMLElementDecl * handleStartTag
    132138        (
    133139                  const XMLSymbol * const               element
     
    139145        );
    140146
    141         virtual void handleEndTag
     147    IDISA_ALWAYS_INLINE
     148    void handleEndTag
    142149        (
    143150                  XMLElementDecl * const                element
     
    149156        );
    150157
     158    IDISA_ALWAYS_INLINE
     159    void loadExternalGrammars();
     160
     161    IDISA_ALWAYS_INLINE
    151162        void setXsiType
    152163        (
     
    155166        );
    156167
    157         void setXsiNil
     168    IDISA_ALWAYS_INLINE
     169    void setXsiNil
    158170        (
    159171                const XMLCh *                           value
     
    621633}
    622634
     635// ---------------------------------------------------------------------------
     636//  IGXMLScanner: XMLParser Callback Methods
     637// ---------------------------------------------------------------------------
     638
     639void IGXMLScanner::loadExternalGrammars()
     640{
     641    //  Check if there is any external schema location specified, and if we are at root,
     642    //  go through them first before scanning those specified in the instance document
     643    if (unlikely(fExternalSchemaLocation != 0))
     644        parseSchemaLocation(fExternalSchemaLocation, XMLString::stringLen(fExternalSchemaLocation), true);
     645
     646    if (unlikely(fExternalNoNamespaceSchemaLocation != 0))
     647        resolveSchemaGrammar(fExternalNoNamespaceSchemaLocation, XMLUni::fgZeroLenString, true);
     648}
     649
     650// --------------------------------------------------------------------------------------------------------
     651// HANDLE START / EMPTY TAG FUNCTIONS
     652// --------------------------------------------------------------------------------------------------------
     653
     654XMLElementDecl * IGXMLScanner::handleStartTag
     655(
     656      const XMLSymbol * const           element
     657    , const XMLAttributeList &          attributeList
     658    , XMLSize_t                                         attributeCount
     659    , const bool                                        isRoot
     660    , const bool                                        isEmpty
     661    , const XMLSize_t                           readerNum
     662)
     663{
     664    #ifdef __GNUC__
     665    #warning "optimize the fDoNamespaces branches? may or may not help depending on what the compiler is able to do"
     666    #endif
     667
     668    /// ----------------------------- DETERMINE THE ELEMENT DECLARATION -----------------------------------
     669
     670    fContent.reset();
     671    XMLElementDecl * elemDecl = 0;
     672
     673    if (!fDoNamespaces)
     674    {
     675        //  Lets try to look up the element in the validator's element decl pool
     676        //  We can pass bogus values for the URI id and the base name. We know that
     677        //  this can only be called if we are doing a DTD style validator and that
     678        //  he will only look at the QName.
     679        //
     680        //  We tell him to fault in a decl if he does not find one.
     681        //  Actually, we *don't* tell him to fault in a decl if he does not find one- NG
     682
     683        elemDecl = element->getElemDecl();
     684
     685        if (!elemDecl)
     686        {
     687            const XMLCh * qName = element->getName();
     688            elemDecl = element->getElemDecl(XMLNamespaceResolver::fEmptyUriId, Grammar::TOP_LEVEL_SCOPE, fGrammar);
     689
     690            // look for it in the undeclared pool:
     691            if (!elemDecl)
     692            {
     693                elemDecl = fDTDElemNonDeclPool->getByKey(qName);
     694                bool notDeclared = false;
     695
     696                if (!elemDecl)
     697                {
     698                    // we're assuming this must be a DTD element.  DTD's can be
     699                    // used with or without namespaces, but schemas cannot be used without
     700                    // namespaces.
     701                    elemDecl = new (fMemoryManager) DTDElementDecl
     702                    (
     703                        element->fQName
     704                        , DTDElementDecl::Any
     705                        , fMemoryManager
     706                    );
     707                    elemDecl->setId(fDTDElemNonDeclPool->put((DTDElementDecl*)elemDecl));
     708                    if (fValidate)
     709                    {
     710                        elemDecl->setCreateReason(XMLElementDecl::JustFaultIn);
     711                        notDeclared = true;
     712                    }
     713                }
     714                else
     715                {
     716                    notDeclared = !elemDecl->isDeclared();
     717                }
     718
     719                // If its not marked declared and validating, then emit an error
     720                if (notDeclared)
     721                {
     722                    fValidator->emitError(XMLValid::ElementNotDefined, qName);
     723                }
     724            }
     725
     726            element->setElemDecl(elemDecl);
     727        }
     728
     729        // Expand the element stack and add the new element
     730        fElemStack.addLevel(elemDecl, readerNum);
     731        fElemStack.setValidationFlag(fValidate);
     732
     733        //  Validate the element
     734        if (fValidate)
     735        {
     736            fValidator->validateElement(elemDecl);
     737        }
     738
     739        //  If this is the first element and we are validating, check the root
     740        //  element.
     741        if (unlikely(isRoot))
     742        {
     743            fRootGrammar = fGrammar;
     744            if (fValidate)
     745            {
     746                //  If a DocType exists, then check if it matches the root name there.
     747                if (unlikely(fRootElemName && !XMLString::equals(element->getName(), fRootElemName)))
     748                {
     749                    fValidator->emitError(XMLValid::RootElemNotLikeDocType);
     750                }
     751            }
     752        }
     753    }
     754    else
     755    {
     756        // save the contentleafname and currentscope before addlevel, for later use
     757        ContentLeafNameTypeVector* cv = 0;
     758        XMLContentModel* cm = 0;
     759        unsigned int currentScope = Grammar::TOP_LEVEL_SCOPE;
     760        bool laxThisOne = false;
     761        const unsigned int elementUriId = element->getQName()->getURI();
     762
     763        if ((!isRoot) && (fGrammarType == Grammar::SchemaGrammarType))
     764        {
     765            // schema validator will have correct type if validating
     766            SchemaElementDecl* tempElement = (SchemaElementDecl*)fElemStack.topElement()->fThisElement;
     767            SchemaElementDecl::ModelTypes modelType = tempElement->getModelType();
     768            ComplexTypeInfo *currType = 0;
     769
     770            if (fValidate)
     771            {
     772                currType = fSchemaValidator->getCurrentTypeInfo();
     773                if (likely(currType != 0))
     774                    modelType = (SchemaElementDecl::ModelTypes)currType->getContentType();
     775                else // something must have gone wrong
     776                    modelType = SchemaElementDecl::Any;
     777            }
     778            else
     779            {
     780                currType = tempElement->getComplexTypeInfo();
     781            }
     782
     783            switch (modelType)
     784            {
     785                case SchemaElementDecl::Mixed_Simple:
     786                case SchemaElementDecl::Mixed_Complex:
     787                case SchemaElementDecl::Children:
     788                    cm = currType->getContentModel();
     789                    cv = cm->getContentLeafNameTypeVector();
     790                    currentScope = fElemStack.getCurrentScope();
     791                    break;
     792                case SchemaElementDecl::Any:
     793                    laxThisOne = true;
     794            }
     795        }
     796
     797        //if schema, check if we should lax or skip the validation of this element
     798        if (cv)
     799        {
     800            // elementDepth will be > 0, as cv is only constructed if element is not root.
     801            laxThisOne = laxElementValidation(element->getQName(), cv, cm, fElemStack.getLevel());
     802        }
     803
     804        // this info needed for DOMTypeInfo
     805        fPSVIElemContext.fErrorOccurred = false;
     806
     807        if (fGrammarType == Grammar::DTDGrammarType)
     808        {
     809            if (!fSkipDTDValidation)
     810            {
     811                elemDecl = element->getElemDecl(XMLNamespaceResolver::fEmptyUriId, Grammar::TOP_LEVEL_SCOPE, fGrammar);
     812                if (elemDecl && elemDecl->hasAttDefs())
     813                {
     814                    XMLAttDefList & attDefList = elemDecl->getAttDefList();
     815                    for (XMLSize_t i = 0; i < attDefList.getAttDefCount(); i++)
     816                    {
     817                        // Get the current att def, for convenience and its def type
     818                        const XMLAttDef & curDef = attDefList.getAttDef(i);
     819                        const XMLAttDef::DefAttTypes defType = curDef.getDefaultType();
     820
     821                        // update the NSMap if there are any default/fixed xmlns attributes
     822                        if ((defType == XMLAttDef::Default) || (defType == XMLAttDef::Fixed))
     823                        {
     824                            const XMLCh * rawPtr = curDef.getFullName();
     825                            if (XMLStringU::isXMLNS(rawPtr))
     826                            {
     827                                #ifdef __GNUC__
     828                                #warning "IGXMLScanner::beginStartTag cannot handle default xmlns attributes in the DTD."
     829                                #endif
     830                            }
     831                        }
     832                    }
     833                }
     834            }
     835
     836            if (!elemDecl)
     837            {
     838                elemDecl = fDTDElemNonDeclPool->getByKey(element->getName());
     839                if (elemDecl)
     840                {
     841                    element->setElemDecl(XMLNamespaceResolver::fEmptyUriId, Grammar::TOP_LEVEL_SCOPE, elemDecl, fGrammar);
     842                }
     843            }
     844        }
     845
     846        if (fDoSchema)
     847        {
     848            if (fGrammarType == Grammar::DTDGrammarType)
     849            {
     850                if (!switchGrammar(elementUriId))
     851                {
     852                    fValidator->emitError
     853                    (
     854                        XMLValid::GrammarNotFound, fUriResolver->getUriForId(elementUriId)
     855                    );
     856                }
     857            }
     858            else if (fGrammarType == Grammar::SchemaGrammarType)
     859            {
     860                Grammar * grammar = fGrammar;
     861                elemDecl = element->getElemDecl(elementUriId, currentScope, grammar);
     862                if (likely(elemDecl != 0))
     863                {
     864                    if (unlikely(grammar != fGrammar))
     865                    {
     866                        fGrammar = grammar;
     867                        fGrammarType = grammar->getGrammarType();
     868                        fValidator->setGrammar(grammar);
     869                    }
     870                }
     871                else // if not found, then it may be a reference, try TOP_LEVEL_SCOPE
     872                {
     873                    bool checkTopLevel = (currentScope != Grammar::TOP_LEVEL_SCOPE);
     874
     875                    const unsigned int grammarUriId =
     876                        fUriResolver->resolveUriId(fGrammar->getTargetNamespace());
     877
     878                    if (grammarUriId != elementUriId)
     879                    {
     880                        checkTopLevel = switchGrammar(elementUriId);
     881
     882                        // the laxElementValidation routine (called above) will
     883                        // set fValidate to false for a "skipped" element
     884                        if (unlikely(!laxThisOne && fValidate && !checkTopLevel))
     885                        {
     886                            fValidator->emitError
     887                            (
     888                                XMLValid::GrammarNotFound, fUriResolver->getUriForId(elementUriId)
     889                            );
     890                        }
     891
     892                    }
     893
     894                    if (checkTopLevel)
     895                    {
     896                        elemDecl = element->getElemDecl(elementUriId, Grammar::TOP_LEVEL_SCOPE, fGrammar);
     897                    }
     898
     899                    if (!elemDecl && currentScope != Grammar::TOP_LEVEL_SCOPE)
     900                    {
     901                        if (grammarUriId == elementUriId)
     902                        {
     903                            // still not found in specified uri; try emptyNamespace see if element should be un-qualified.
     904                            if (elementUriId != XMLNamespaceResolver::fEmptyUriId)
     905                            {
     906                                XMLElementDecl* tempElemDecl =
     907                                    element->getElemDecl(XMLNamespaceResolver::fEmptyUriId, currentScope, fGrammar);
     908
     909                                if (tempElemDecl && tempElemDecl->getCreateReason() != XMLElementDecl::JustFaultIn && fValidate)
     910                                {
     911                                    fValidator->emitError(XMLValid::ElementNotUnQualified, element->getName());
     912                                    elemDecl = tempElemDecl;
     913                                }
     914                            }
     915                        }
     916                        else if (elementUriId == XMLNamespaceResolver::fEmptyUriId)
     917                        {
     918                            // still Not found in specified uri
     919                            // go to original Grammar again to see if element needs
     920                            // to be fully qualified.
     921                            // Use a temp variable until we decide this is the case
     922
     923                            if (setCurrentGrammar(grammar))
     924                            {
     925                                XMLElementDecl* tempElemDecl = element->getElemDecl(grammarUriId, currentScope, fGrammar);
     926                                if (tempElemDecl && tempElemDecl->getCreateReason() != XMLElementDecl::JustFaultIn && fValidate)
     927                                {
     928                                    fValidator->emitError(XMLValid::ElementNotQualified, element->getName());
     929                                    elemDecl = tempElemDecl;
     930                                }
     931                            }
     932                            else if (!laxThisOne && fValidate)
     933                            {
     934                                fValidator->emitError(XMLValid::GrammarNotFound, fGrammar->getTargetNamespace());
     935                            }
     936                        }
     937                    }
     938
     939                    if (!elemDecl)
     940                    {
     941                        // still not found
     942                        // switch back to original grammar first if necessary
     943                        if (grammarUriId != elementUriId)
     944                        {
     945                            setCurrentGrammar(grammar);
     946                        }
     947
     948                        // look in the list of undeclared elements, as would have been
     949                        // done before we made grammars stateless:
     950                        elemDecl = fSchemaElemNonDeclPool->getByKey(element->getQName()->getLocalPart(), elementUriId, (int)Grammar::TOP_LEVEL_SCOPE);
     951                    }
     952
     953                    if (elemDecl)
     954                    {
     955                        element->setElemDecl(elementUriId, currentScope, elemDecl, fGrammar);
     956                    }
     957                }
     958            }
     959        }
     960
     961        //  Look up the element now in the grammar. This will get us back a
     962        //  generic element decl object. We tell him to fault one in if he does
     963        //  not find it.
     964        bool wasAdded = false;
     965
     966        if (!elemDecl)
     967        {
     968            if (fGrammarType == Grammar::DTDGrammarType)
     969            {
     970                elemDecl = new (fMemoryManager) DTDElementDecl(element->getQName(), DTDElementDecl::Any, fMemoryManager);
     971                elemDecl->setId(fDTDElemNonDeclPool->put((DTDElementDecl*)elemDecl));
     972            }
     973            else if (fGrammarType == Grammar::SchemaGrammarType)
     974            {
     975                elemDecl = new (fMemoryManager) SchemaElementDecl
     976                (
     977                    element->getQName()
     978                    , SchemaElementDecl::Any
     979                    , Grammar::TOP_LEVEL_SCOPE
     980                    , fMemoryManager
     981                );
     982                elemDecl->setId
     983                (
     984                    fSchemaElemNonDeclPool->put
     985                    (
     986                        (void*)elemDecl->getBaseName()
     987                        , elementUriId
     988                        , (int)Grammar::TOP_LEVEL_SCOPE
     989                        , (SchemaElementDecl*)elemDecl
     990                    )
     991                );
     992            }
     993
     994            element->setElemDecl(elementUriId, Grammar::TOP_LEVEL_SCOPE, elemDecl, fGrammar);
     995
     996            wasAdded = true;
     997        }
     998
     999        //  We do something different here according to whether we found the element or not.
     1000        const bool bXsiTypeSet = (fGrammarType == Grammar::SchemaGrammarType) && fSchemaValidator->getIsXsiTypeSet();
     1001
     1002        if (wasAdded)
     1003        {
     1004            if (laxThisOne && !bXsiTypeSet)
     1005            {
     1006                fValidate = false;
     1007            }
     1008            else if (fValidate)
     1009            {
     1010                // If validating then emit an error
     1011
     1012                // This is to tell the reuse Validator that this element was
     1013                // faulted-in, was not an element in the grammar pool originally
     1014                elemDecl->setCreateReason(XMLElementDecl::JustFaultIn);
     1015
     1016                // xsi:type was specified, don't complain about missing definition
     1017                if (!bXsiTypeSet)
     1018                {
     1019                    fValidator->emitError(XMLValid::ElementNotDefined, elemDecl->getFullName());
     1020
     1021                    if (fGrammarType == Grammar::SchemaGrammarType)
     1022                    {
     1023                        fPSVIElemContext.fErrorOccurred = true;
     1024                    }
     1025                }
     1026            }
     1027        }
     1028        else if (!elemDecl->isDeclared())
     1029        {
     1030            // If its not marked declared and validating, then emit an error
     1031            if (elemDecl->getCreateReason() == XMLElementDecl::NoReason)
     1032            {
     1033                if (!bXsiTypeSet && fGrammarType == Grammar::SchemaGrammarType)
     1034                {
     1035                    fPSVIElemContext.fErrorOccurred = true;
     1036                }
     1037            }
     1038
     1039            if (laxThisOne)
     1040            {
     1041                fValidate = false;
     1042            }
     1043            else if (fValidate && !bXsiTypeSet)
     1044            {
     1045                fValidator->emitError(XMLValid::ElementNotDefined, elemDecl->getFullName());
     1046            }
     1047        }
     1048
     1049        //  Now we can update the element stack to set the current element decl.
     1050        const XMLSize_t elemDepth = fElemStack.addLevel(elemDecl, fReaderMgr.getCurrentReaderNum());
     1051
     1052        if (isRoot)
     1053        {
     1054            fRootGrammar = fGrammar;
     1055            if (fGrammarType == Grammar::SchemaGrammarType && !fRootElemName)
     1056            {
     1057                fRootElemName = XMLString::replicate(element->getName(), element->getLength());
     1058            }
     1059        }
     1060
     1061        if (fGrammarType == Grammar::SchemaGrammarType && fPSVIHandler)
     1062        {
     1063            fPSVIElemContext.fElemDepth++;
     1064            if (elemDecl->isDeclared())
     1065            {
     1066                fPSVIElemContext.fNoneValidationDepth = fPSVIElemContext.fElemDepth;
     1067            }
     1068            else
     1069            {
     1070                fPSVIElemContext.fFullValidationDepth = fPSVIElemContext.fElemDepth;
     1071            }
     1072        }
     1073
     1074        //  Validate the element
     1075        if (fValidate)
     1076        {
     1077            fValidator->validateElement(elemDecl);
     1078            if (fValidator->handlesSchema())
     1079            {
     1080                if (fSchemaValidator->getErrorOccurred())
     1081                {
     1082                    fPSVIElemContext.fErrorOccurred = true;
     1083                }
     1084            }
     1085        }
     1086
     1087        if (fGrammarType == Grammar::SchemaGrammarType)
     1088        {
     1089            ComplexTypeInfo* typeinfo = (fValidate)
     1090                ? fSchemaValidator->getCurrentTypeInfo()
     1091                : ((SchemaElementDecl*)elemDecl)->getComplexTypeInfo();
     1092
     1093            if (typeinfo)
     1094            {
     1095                currentScope = typeinfo->getScopeDefined();
     1096
     1097                // switch grammar if the typeinfo has a different grammar (happens when there is xsi:type)
     1098                XMLCh* typeName = typeinfo->getTypeName();
     1099                const int comma = XMLString::indexOf(typeName, chComma);
     1100                if (comma > 0)
     1101                {
     1102                    XMLBuffer prefixBuf(comma + 1, fMemoryManager);
     1103                    prefixBuf.append(typeName, comma);
     1104                    const XMLCh* uriStr = prefixBuf.getRawBuffer();
     1105
     1106                    bool errorCondition = !switchGrammar(uriStr) && fValidate;
     1107                    if (errorCondition && !laxThisOne)
     1108                    {
     1109                        fValidator->emitError
     1110                        (
     1111                            XMLValid::GrammarNotFound
     1112                            , prefixBuf.getRawBuffer()
     1113                        );
     1114                    }
     1115                }
     1116                else if (comma == 0)
     1117                {
     1118                    bool errorCondition = !switchGrammar(XMLNamespaceResolver::fEmptyUriId) && fValidate;
     1119                    if (errorCondition && !laxThisOne)
     1120                    {
     1121                        fValidator->emitError
     1122                        (
     1123                            XMLValid::GrammarNotFound
     1124                            , XMLUni::fgZeroLenString
     1125                        );
     1126                    }
     1127                }
     1128            }
     1129
     1130            fElemStack.setCurrentScope(currentScope);
     1131
     1132            // Set element next state
     1133            if (elemDepth >= fElemStateSize)
     1134            {
     1135                resizeElemState();
     1136            }
     1137
     1138            fElemState[elemDepth] = 0;
     1139            fElemLoopState[elemDepth] = 0;
     1140        }
     1141
     1142        fElemStack.setCurrentGrammar(fGrammar);
     1143        fElemStack.setValidationFlag(fValidate);
     1144
     1145        //  If this is the first element and we are validating, check the root
     1146        //  element.
     1147        if (unlikely(isRoot && fValidate && fRootElemName))
     1148        {
     1149            //  If a DocType exists, then check if it matches the root name there.
     1150            if (!XMLString::equals(element->getName(), fRootElemName))
     1151            {
     1152                fValidator->emitError(XMLValid::RootElemNotLikeDocType);
     1153            }
     1154        }
     1155
     1156        // PSVI handling:  even if it turns out there are
     1157        // no attributes, we need to reset this list...
     1158        if (getPSVIHandler() && fGrammarType == Grammar::SchemaGrammarType )
     1159        {
     1160            fPSVIAttrList->reset();
     1161        }
     1162    }
     1163
     1164    /// -------------------------------- HANDLE ATTRIBUTES -----------------------------------
     1165
     1166    for (XMLSize_t index = 0; index < attributeCount; index++)
     1167    {
     1168        const XMLAttribute & attributeItem = attributeList[index];
     1169
     1170        const XMLSymbol * const attribute = attributeItem.getAttribute();
     1171        const XMLCh * value = attributeItem.getValue();
     1172        // const XMLSize_t length = attributeList[index].getLength();
     1173
     1174        XMLAttDef::AttTypes attType = XMLAttDef::CData;
     1175
     1176        if (!fDoNamespaces)
     1177        {
     1178            //  See if this attribute is declared for this element. If we are
     1179            //  not validating of course it will not be at first, but we will
     1180            //  fault it into the pool (to avoid lots of redundant errors.)
     1181            DTDElementDecl * const dtdElemDecl = reinterpret_cast<DTDElementDecl*>(elemDecl);
     1182
     1183            XMLAttDef * attDef = dtdElemDecl->getAttDef(attribute->getName());
     1184
     1185            //  Add this attribute to the attribute list that we use to
     1186            //  pass them to the handler. We reuse its existing elements
     1187            //  but expand it as required.
     1188
     1189            // Note that we want to this first since this will
     1190            // make a copy of the namePtr; we can then make use of
     1191            // that copy in the hashtable lookup that checks
     1192            // for duplicates.  This will mean we may have to update
     1193            // the type of the XMLAttr later.
     1194
     1195            if (unlikely(!attDef))
     1196            {
     1197                //  If there is a validation handler, then we are validating so emit an error.
     1198                if (fValidate)
     1199                {
     1200                    fValidator->emitError
     1201                    (
     1202                        XMLValid::AttNotDefinedForElement
     1203                        , attribute->getName()
     1204                        , element->getName()
     1205                    );
     1206                }
     1207            }
     1208            else
     1209            {
     1210                // prepare for duplicate detection
     1211                attDef->setLastOccurrence(attribute->fLastOccurence);
     1212
     1213                //  Now that its all stretched out, lets look at its type and
     1214                //  determine if it has a valid value. It will output any needed
     1215                //  errors, but we just keep going. We only need to do this if
     1216                //  we are validating.
     1217                if (fValidate)
     1218                {
     1219                    // Let the validator pass judgement on the attribute value
     1220                    fValidator->validateAttrValue
     1221                    (
     1222                        attDef
     1223                        , value
     1224                        , false
     1225                        , dtdElemDecl
     1226                    );
     1227                }
     1228            }
     1229        }
     1230        else // if (fDoNamespaces)
     1231        {
     1232            //  If its not a special case namespace attr of some sort, then we
     1233            //  do normal checking and processing.
     1234            DatatypeValidator * attrValidator = 0;
     1235            PSVIAttribute *psviAttr = 0;
     1236            bool otherXSI = false;
     1237            const unsigned int attributeUriId = attribute->getQName()->getURI();
     1238
     1239            // moving some of the processAttList code here....
     1240
     1241            PSVIItem::VALIDITY_STATE attrValid = PSVIItem::VALIDITY_VALID;
     1242            PSVIItem::ASSESSMENT_TYPE attrAssessed = PSVIItem::VALIDATION_FULL;
     1243
     1244            const QName* const qName = attribute->getQName();
     1245            // const XMLCh* const prefPtr = qName->getPrefix();
     1246            const XMLCh* const localPart = qName->getLocalPart();
     1247
     1248            //  If the uri comes back as the xmlns or xml URI or its just a name
     1249            //  and that name is 'xmlns', then we handle it specially. So set a
     1250            //  boolean flag that lets us quickly below know which we are dealing
     1251            //  with.
     1252
     1253            const bool isXSI = (attributeUriId == XMLNamespaceResolver::fSchemaInstanceUriId);
     1254            const bool isNamespaceAttribute = (isXSI | attribute->isXMLNS());
     1255
     1256            if (unlikely(isNamespaceAttribute && fGrammarType == Grammar::SchemaGrammarType))
     1257            {
     1258                bool ValueValidate = false;
     1259                bool tokenizeBuffer = false;
     1260
     1261                if (attributeUriId == XMLNamespaceResolver::fXMLNSUriId)
     1262                {
     1263                    attrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYURI);
     1264                }
     1265                else if (isXSI)
     1266                {
     1267                    if (XMLString::equals(localPart, SchemaSymbols::fgATT_NILL))
     1268                    {
     1269                        attrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_BOOLEAN);
     1270                        ValueValidate = true;
     1271                    }
     1272                    else if (XMLString::equals(localPart, SchemaSymbols::fgXSI_SCHEMALOCATION))
     1273                    {
     1274                        // use anyURI as the validator
     1275                        // tokenize the data and use the anyURI data for each piece
     1276                        attrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYURI);
     1277                        ValueValidate = false;
     1278                        tokenizeBuffer = true;
     1279                    }
     1280                    else if (XMLString::equals(localPart, SchemaSymbols::fgXSI_NONAMESPACESCHEMALOCATION))
     1281                    {
     1282                        attrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYURI);
     1283                        ValueValidate = false;
     1284                    }
     1285                    else if (XMLString::equals(localPart, SchemaSymbols::fgXSI_TYPE))
     1286                    {
     1287                        attrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_QNAME);
     1288                        ValueValidate = true;
     1289                    }
     1290                    else
     1291                    {
     1292                        otherXSI = true;
     1293                    }
     1294                }
     1295
     1296                if (!otherXSI)
     1297                {
     1298                    if (fValidate && attrValidator && ValueValidate)
     1299                    {
     1300                        ValidationContext* const theContext = getValidationContext();
     1301
     1302                        if (theContext)
     1303                        {
     1304                            try
     1305                            {
     1306                                if (tokenizeBuffer)
     1307                                {
     1308                                    XMLStringTokenizer tokenizer(value, fMemoryManager);
     1309                                    while (tokenizer.hasMoreTokens())
     1310                                    {
     1311                                        attrValidator->validate
     1312                                        (
     1313                                            tokenizer.nextToken(),
     1314                                            theContext,
     1315                                            fMemoryManager
     1316                                        );
     1317                                    }
     1318                                }
     1319                                else
     1320                                {
     1321                                    attrValidator->validate
     1322                                    (
     1323                                        value,
     1324                                        theContext,
     1325                                        fMemoryManager
     1326                                    );
     1327                                }
     1328                            }
     1329                            catch (const XMLException& idve)
     1330                            {
     1331                                fValidator->emitError(XMLValid::DatatypeError, idve.getCode(), idve.getMessage());
     1332                            }
     1333                        }
     1334                    }
     1335
     1336                    if (getPSVIHandler())
     1337                    {
     1338                        psviAttr = fPSVIAttrList->getPSVIAttributeToFill(localPart, fUriResolver->getUriForId(attributeUriId));
     1339
     1340                        XSSimpleTypeDefinition *validatingType = (attrValidator)
     1341                            ? (XSSimpleTypeDefinition *)fModel->getXSObject(attrValidator)
     1342                            : 0;
     1343                        // no attribute declarations for these...
     1344                        psviAttr->reset
     1345                        (
     1346                            fRootElemName
     1347                            , PSVIItem::VALIDITY_NOTKNOWN
     1348                            , PSVIItem::VALIDATION_NONE
     1349                            , validatingType
     1350                            , 0
     1351                            , 0
     1352                            , false
     1353                            , 0
     1354                            , attrValidator
     1355                        );
     1356                    }
     1357                }
     1358            } // if (isNamespaceAttribute && (fGrammarType == Grammar::SchemaGrammarType))
     1359
     1360            if (likely(!isNamespaceAttribute || fGrammarType == Grammar::DTDGrammarType || otherXSI))
     1361            {
     1362                // Some checking for attribute wild card first (for schema)
     1363                bool laxThisOne = false;
     1364                bool skipThisOne = false;
     1365
     1366                XMLAttDef * attDefForWildCard = 0;
     1367                XMLAttDef * attDef = 0;
     1368
     1369                if (fGrammarType == Grammar::SchemaGrammarType)
     1370                {
     1371                    ComplexTypeInfo *currType = 0;
     1372                    DatatypeValidator *currDV = 0;
     1373
     1374                    if (fValidate)
     1375                    {
     1376                        currType = fSchemaValidator->getCurrentTypeInfo();
     1377                        if (!currType)
     1378                        {
     1379                            currDV = fSchemaValidator->getCurrentDatatypeValidator();
     1380                        }
     1381                    }
     1382
     1383                    //retrieve the att def
     1384                    SchemaAttDef* attWildCard = 0;
     1385                    if (currType)
     1386                    {
     1387                        attDef = currType->getAttDef(localPart, attributeUriId);
     1388                        attWildCard = currType->getAttWildCard();
     1389                    }
     1390                    else if (!currDV)
     1391                    { // check explicitly-set wildcard
     1392                        attDef = ((SchemaElementDecl*)elemDecl)->getAttDef(localPart, attributeUriId);
     1393                        attWildCard = ((SchemaElementDecl*)elemDecl)->getAttWildCard();
     1394                    }
     1395
     1396                    // if not found or faulted in - check for a matching wildcard attribute
     1397                    // if no matching wildcard attribute, check (un)qualifed cases and flag
     1398                    // appropriate errors
     1399                    if (!attDef || (attDef->getCreateReason() == XMLAttDef::JustFaultIn))
     1400                    {
     1401                        if (attWildCard)
     1402                        {
     1403                            //if schema, see if we should lax or skip the validation of this attribute
     1404                            if (anyAttributeValidation(attWildCard, attributeUriId, skipThisOne, laxThisOne))
     1405                            {
     1406                                if (!skipThisOne)
     1407                                {
     1408                                    Grammar* sGrammar = fGrammarList.getGrammar(attributeUriId);
     1409                                    if (unlikely(sGrammar == NULL))
     1410                                    {
     1411                                        sGrammar = fGrammarResolver->getGrammar((*fUriResolver)[attributeUriId]);
     1412                                        fGrammarList.setGrammar(attributeUriId, sGrammar);
     1413                                    }
     1414
     1415                                    if (sGrammar && sGrammar->getGrammarType() == Grammar::SchemaGrammarType)
     1416                                    {
     1417                                        RefHashTableOf<XMLAttDef>* attRegistry = ((SchemaGrammar*)sGrammar)->getAttributeDeclRegistry();
     1418
     1419                                        if (attRegistry)
     1420                                        {
     1421                                            attDefForWildCard = attRegistry->get(localPart);
     1422                                        }
     1423                                    }
     1424                                }
     1425                            }
     1426                            #ifdef __GNUC__
     1427                            #warning "INVESTIGATE: can I set attDef to attWildCard to simplify the logic below?"
     1428                            #endif
     1429                        }
     1430                        else if (currType)
     1431                        {
     1432                            // not found, see if the attDef should be qualified or not
     1433                            attDef = currType->getAttDef
     1434                            (
     1435                                localPart
     1436                                , attributeUriId == XMLNamespaceResolver::fEmptyUriId
     1437                                ? fUriResolver->resolveUriId(fGrammar->getTargetNamespace())
     1438                                : XMLNamespaceResolver::fEmptyUriId
     1439                            );
     1440
     1441                            if (fValidate && attDef && attDef->getCreateReason() != XMLAttDef::JustFaultIn)
     1442                            {
     1443                                XMLValid::Codes errCode =
     1444                                    (attributeUriId == XMLNamespaceResolver::fEmptyUriId)
     1445                                    ? XMLValid::AttributeNotQualified
     1446                                    : XMLValid::AttributeNotUnQualified;
     1447
     1448                                fValidator->emitError(errCode, attDef->getFullName());
     1449
     1450                                fPSVIElemContext.fErrorOccurred = true;
     1451                                if (getPSVIHandler())
     1452                                {
     1453                                    attrValid = PSVIItem::VALIDITY_INVALID;
     1454                                }
     1455                            }
     1456                        }
     1457                    } // if (!attDef || (attDef->getCreateReason() == XMLAttDef::JustFaultIn))
     1458                }
     1459                else // if (fGrammarType == Grammar::DTDGrammarType)
     1460                {
     1461                    //  Find this attribute within the parent element. We pass both
     1462                    //  the uriID/name and the raw QName buffer, since we don't know
     1463                    //  how the derived validator and its elements store attributes.
     1464                    attDef = ((DTDElementDecl*)elemDecl)->getAttDef(qName->getRawName());
     1465                }
     1466
     1467                if (attDef)
     1468                {
     1469                    attDef->setLastOccurrence(element->fLastOccurence);
     1470
     1471                    if (unlikely(attDef->getDefaultType() == XMLAttDef::Prohibited && fValidate)) // attribute was provided for this definition
     1472                    {
     1473                        // TODO: is it safe to move the prohibited attribute validation into the attribute scan?
     1474
     1475                        // (schema) report error for PROHIBITED attrs that are present (V_TAGc)
     1476                        fValidator->emitError(XMLValid::ProhibitedAttributePresent, attDef->getFullName());
     1477
     1478                        if ((fGrammarType == Grammar::SchemaGrammarType))
     1479                        {
     1480                            fPSVIElemContext.fErrorOccurred = true;
     1481                            if (getPSVIHandler())
     1482                            {
     1483                                QName * attQName = ((SchemaAttDef *)attDef)->getAttName();
     1484                                // bad luck...
     1485                                PSVIAttribute *prohibitedAttr = fPSVIAttrList->getAttributePSVIByName
     1486                                (
     1487                                    attQName->getLocalPart(), fUriResolver->getUriForId(attributeUriId)
     1488                                );
     1489                                prohibitedAttr->updateValidity(PSVIItem::VALIDITY_INVALID);
     1490                            }
     1491                        }
     1492                    }
     1493                }
     1494                else // if (!attDef)
     1495                {
     1496                    if (fGrammarType == Grammar::SchemaGrammarType)
     1497                    {
     1498                        // if we've found either an attDef or an attDefForWildCard,
     1499                        // then we're doing full validation and it may still be valid.
     1500                        if (!attDefForWildCard)
     1501                        {
     1502                            fPSVIElemContext.fErrorOccurred |= !(laxThisOne & skipThisOne);
     1503
     1504                            if (getPSVIHandler())
     1505                            {
     1506                                if (!laxThisOne && !skipThisOne)
     1507                                {
     1508                                    attrValid = PSVIItem::VALIDITY_INVALID;
     1509                                }
     1510                                else
     1511                                {
     1512                                    attrValid = PSVIItem::VALIDITY_NOTKNOWN;
     1513                                    attrAssessed = (laxThisOne) ? PSVIItem::VALIDATION_PARTIAL : PSVIItem::VALIDATION_NONE;
     1514                                }
     1515                            }
     1516                        }
     1517                    }
     1518
     1519                    if (unlikely(fValidate && !attDefForWildCard && !skipThisOne && !laxThisOne))
     1520                    {
     1521                        //
     1522                        //  Its not valid for this element, so issue an error if we are
     1523                        //  validating.
     1524                        //
     1525                        XMLBuffer bufMsg;
     1526                        if (attributeUriId != XMLNamespaceResolver::fEmptyUriId)
     1527                        {
     1528                            bufMsg.append(chOpenCurly);
     1529                            bufMsg.append(fUriResolver->getUriForId(attributeUriId));
     1530                            bufMsg.append(chCloseCurly);
     1531                        }
     1532                        bufMsg.append(localPart);
     1533                        fValidator->emitError
     1534                        (
     1535                            XMLValid::AttNotDefinedForElement
     1536                            , bufMsg.getRawBuffer()
     1537                            , element->getQName()->getLocalPart()
     1538                        );
     1539                    }
     1540                }
     1541
     1542                /// VALIDATE THE ATTRIBUTE VALUE BASED ON THE DEFINITION
     1543
     1544                if (attDefForWildCard)
     1545                {
     1546                    validateAttValue(elemDecl, attDefForWildCard, value, attrValidator, attrValid, attType);
     1547                }
     1548                else if (attDef)
     1549                {
     1550                    validateAttValue(elemDecl, attDef, value, attrValidator, attrValid, attType);
     1551                }
     1552                else if (fGrammarType == Grammar::SchemaGrammarType)
     1553                {
     1554                    attrValidator = getAnySimpleTypeValidator();
     1555                }
     1556
     1557
     1558                // now fill in the PSVIAttributes entry for this attribute:
     1559                if (getPSVIHandler() && (fGrammarType == Grammar::SchemaGrammarType))
     1560                {
     1561                    psviAttr = fPSVIAttrList->getPSVIAttributeToFill(localPart, fUriResolver->getUriForId(attributeUriId));
     1562                    SchemaAttDef * actualAttDef = 0;
     1563                    if (attDef)
     1564                        actualAttDef = (SchemaAttDef*)attDef;
     1565                    else if (attDefForWildCard)
     1566                        actualAttDef = (SchemaAttDef*)attDefForWildCard;
     1567
     1568                    if (actualAttDef)
     1569                    {
     1570                        XSAttributeDeclaration *attrDecl = (XSAttributeDeclaration *)fModel->getXSObject(actualAttDef);
     1571                        DatatypeValidator * attrDataType = actualAttDef->getDatatypeValidator();
     1572                        XSSimpleTypeDefinition *validatingType = (XSSimpleTypeDefinition *)fModel->getXSObject(attrDataType);
     1573                        if (attrValid != PSVIItem::VALIDITY_VALID)
     1574                        {
     1575                            psviAttr->reset
     1576                            (
     1577                                fRootElemName
     1578                                , attrValid
     1579                                , attrAssessed
     1580                                , validatingType
     1581                                , 0
     1582                                , actualAttDef->getValue()
     1583                                , false
     1584                                , attrDecl
     1585                                , 0
     1586                            );
     1587                        }
     1588                        else
     1589                        {
     1590                            XSSimpleTypeDefinition *memberType = 0;
     1591                            if (validatingType->getVariety() == XSSimpleTypeDefinition::VARIETY_UNION)
     1592                                memberType = (XSSimpleTypeDefinition *)fModel->getXSObject(attrValidator);
     1593                            psviAttr->reset
     1594                            (
     1595                                fRootElemName
     1596                                , attrValid
     1597                                , attrAssessed
     1598                                , validatingType
     1599                                , memberType
     1600                                , actualAttDef->getValue()
     1601                                , false
     1602                                , attrDecl
     1603                                , (memberType) ? attrValidator : attrDataType
     1604                            );
     1605                        }
     1606                    }
     1607                    else
     1608                    {
     1609                        psviAttr->reset
     1610                        (
     1611                            fRootElemName
     1612                            , attrValid
     1613                            , attrAssessed
     1614                            , 0
     1615                            , 0
     1616                            , 0
     1617                            , false
     1618                            , 0
     1619                            , 0
     1620                        );
     1621                    }
     1622                }
     1623            }
     1624        } // end of if (fDoNamespaces) { ... } else { ... }
     1625
     1626        #ifdef __GNUC__
     1627        #warning "TODO: move the fAttrList into the XMLParserImpl and construct them directly there with all the non-derived values set"
     1628        #endif
     1629        XMLAttr * curAttr;
     1630
     1631        const XMLSize_t length = attributeItem.getLength();
     1632        const bool specified = attributeItem.getSpecified();
     1633
     1634        if (unlikely(index >= fAttrList.size()))
     1635        {
     1636            curAttr = new (fMemoryManager) XMLAttr
     1637            (
     1638                attribute->getQName()
     1639                , value
     1640                , length
     1641                , attType
     1642                , specified
     1643                , fMemoryManager
     1644            );
     1645
     1646            fAttrList.addElement(curAttr);
     1647        }
     1648        else
     1649        {
     1650            curAttr = fAttrList.elementAt(index);
     1651            curAttr->set
     1652            (
     1653                attribute->getQName()
     1654                , value
     1655                , length
     1656                , attType
     1657            );
     1658            curAttr->setSpecified(specified);
     1659        }
     1660
     1661    }
     1662
     1663    /// ------------------------------ POST ATTRIBUTE VALIDATION ---------------------------------
     1664
     1665    if (!fDoNamespaces)
     1666    {
     1667        //  Ok, so lets get an enumerator for the attributes of this element
     1668        //  and run through them for well formedness and validity checks. But
     1669        //  make sure that we had any attributes before we do it, since the list
     1670        //  would have have gotten faulted in anyway.
     1671        if (elemDecl->hasAttDefs())
     1672        {
     1673            // N.B.:  this assumes DTD validation.
     1674            XMLAttDefList & attDefList = elemDecl->getAttDefList();
     1675            for(XMLSize_t i = 0; i < attDefList.getAttDefCount(); i++)
     1676            {
     1677                // Get the current att def, for convenience and its def type
     1678                const XMLAttDef & curDef = attDefList.getAttDef(i);
     1679                const XMLAttDef::DefAttTypes defType = curDef.getDefaultType();
     1680
     1681                if (unlikely(curDef.getLastOccurrence() != element->fLastOccurence))
     1682                { // did not occur
     1683                    if (fValidate)
     1684                    {
     1685                        // If we are validating and its required, then an error
     1686                        if (defType == XMLAttDef::Required)
     1687                        {
     1688                            fValidator->emitError(XMLValid::RequiredAttrNotProvided, curDef.getFullName());
     1689                        }
     1690                        else if ((defType == XMLAttDef::Default) || (defType == XMLAttDef::Fixed))
     1691                        {
     1692                            if (fStandalone && curDef.isExternal())
     1693                            {
     1694                                // XML 1.0 Section 2.9
     1695                                // Document is standalone, so attributes must not be defaulted.
     1696                                fValidator->emitError(XMLValid::NoDefAttForStandalone, curDef.getFullName(), elemDecl->getFullName());
     1697                            }
     1698                        }
     1699                    }
     1700
     1701                    #ifdef IGNORE_DEFAULT_ATTRIBUTES
     1702                    // Fault in the value if needed, and bump the att count
     1703                    if ((defType == XMLAttDef::Default) || (defType == XMLAttDef::Fixed))
     1704                    {
     1705                        // Let the validator pass judgement on the attribute value
     1706                        if (fValidate)
     1707                        {
     1708                            fValidator->validateAttrValue
     1709                            (
     1710                                &curDef
     1711                                , curDef.getValue()
     1712                                , false
     1713                                , elemDecl
     1714                            );
     1715                        }
     1716
     1717                        XMLAttr * curAtt;
     1718                        if (attributeCount >= fAttrList.size())
     1719                        {
     1720                            curAtt = new (fMemoryManager) XMLAttr
     1721                            (
     1722                                curDef.getAttName()
     1723                                , curDef.getValue()
     1724                                , curDef.getType()
     1725                                , false
     1726                                , fMemoryManager
     1727                            );
     1728                            fAttrList.addElement(curAtt);
     1729                        }
     1730                        else
     1731                        {
     1732                            curAtt = fAttrList.elementAt(attributeCount);
     1733                            curAtt->set
     1734                            (
     1735                                curDef.getAttName()
     1736                                , curDef.getValue()
     1737                                , curDef.getType()
     1738                            );
     1739                            curAtt->setSpecified(false);
     1740                        }
     1741                        attributeCount++;
     1742                    }
     1743                    #endif
     1744                }
     1745            }
     1746        }
     1747
     1748        //  If empty, validate content right now if we are validating and then
     1749        //  pop the element stack top. Else, we have to update the current stack
     1750        //  top's namespace mapping elements.
     1751        if (isEmpty)
     1752        {
     1753            // If validating, then insure that its legal to have no content
     1754            if (fValidate)
     1755            {
     1756                XMLSize_t failure;
     1757                bool res = fValidator->checkContent(elemDecl, ((XMLElementDecl**)0), 0, &failure);
     1758                if (!res)
     1759                {
     1760                    fValidator->emitError
     1761                    (
     1762                        XMLValid::ElementNotValidForContent
     1763                        , elemDecl->getFullName()
     1764                        , elemDecl->getFormattedContentModel()
     1765                    );
     1766                }
     1767            }
     1768
     1769            // Pop the element stack back off since it'll never be used now
     1770            fElemStack.popTop();
     1771
     1772            // If the elem stack is empty, then it was an empty root
     1773            if (!isRoot)
     1774            {
     1775                // Restore the validation flag
     1776                fValidate = fElemStack.getValidationFlag();
     1777            }
     1778        }
     1779
     1780        //  If we have a document handler, then tell it about this start tag. We
     1781        //  don't have any URI id to send along, so send fEmptyNamespaceId. We also do not send
     1782        //  any prefix since its just one big name if we are not doing namespaces.
     1783        if (fDocHandler)
     1784        {
     1785            QName * origQName = elemDecl->getElementName();
     1786            elemDecl->setElementName(element->fQName);
     1787
     1788            fDocHandler->startElement
     1789            (
     1790                *elemDecl
     1791                , XMLNamespaceResolver::fEmptyUriId
     1792                , 0
     1793                , fAttrList
     1794                , attributeCount
     1795                , isEmpty
     1796                , isRoot
     1797            );
     1798
     1799            elemDecl->setElementName(origQName);
     1800        }
     1801    }
     1802    else // if (fDoNamespaces)
     1803    {
     1804        const QName * qName = element->getQName();
     1805
     1806        if (fValidate)
     1807        {
     1808            //  If doing DTD's, Ask the element to clear the 'provided' flag on all of the att defs
     1809            //  that it owns, and to return us a boolean indicating whether it has
     1810            //  any defs.  If schemas are being validated, the complexType
     1811            // at the top of the SchemaValidator's stack will
     1812            // know what's best.  REVISIT:  don't modify grammar at all; eliminate
     1813            // this step...
     1814
     1815            ComplexTypeInfo * currType = 0;
     1816            DatatypeValidator * currDV = 0;
     1817
     1818            if (fGrammarType == Grammar::SchemaGrammarType)
     1819            {
     1820                currType = fSchemaValidator->getCurrentTypeInfo();
     1821                if (!currType)
     1822                {
     1823                    currDV = fSchemaValidator->getCurrentDatatypeValidator();
     1824                }
     1825            }
     1826
     1827            const bool hasDefs = (currType) ? currType->hasAttDefs() : elemDecl->hasAttDefs();
     1828
     1829            //  Now, if there are any attributes declared by this element, let's
     1830            //  go through them and make sure that any required ones are provided,
     1831            //  and fault in any fixed ones and defaulted ones that are not provided
     1832            //  literally.
     1833            if (unlikely(hasDefs))
     1834            {
     1835                // Check after all specified attrs are scanned
     1836                // (1) report error for REQUIRED attrs that are missing (V_TAGc)
     1837                // (2) add default attrs if missing (FIXED and NOT_FIXED)
     1838
     1839                XMLAttDefList & attDefList = getAttDefList((fGrammarType == Grammar::SchemaGrammarType), currType, elemDecl);
     1840
     1841                for(XMLSize_t i = 0; i < attDefList.getAttDefCount(); i++)
     1842                {
     1843                    // Get the current att def, for convenience and its def type
     1844                    const XMLAttDef *curDef = &attDefList.getAttDef(i);
     1845                    const XMLAttDef::DefAttTypes defType = curDef->getDefaultType();
     1846
     1847                    // if this attribute is not present within the element
     1848                    if (unlikely(curDef->getLastOccurrence() != element->fLastOccurence))
     1849                    {
     1850                        // note that since there is no attribute information
     1851                        // item present, there is no PSVI infoset to augment here *except*
     1852                        // that the element is invalid
     1853
     1854                        //the attribute is not provided
     1855                        if ((defType == XMLAttDef::Required) || (defType == XMLAttDef::Required_And_Fixed))
     1856                        {
     1857                            fValidator->emitError(XMLValid::RequiredAttrNotProvided, curDef->getFullName());
     1858
     1859                            if (fGrammarType == Grammar::SchemaGrammarType)
     1860                            {
     1861                                fPSVIElemContext.fErrorOccurred = true;
     1862                            }
     1863                        }
     1864                        else if ((defType == XMLAttDef::Default) || (defType == XMLAttDef::Fixed))
     1865                        {
     1866                            if (fStandalone && curDef->isExternal())
     1867                            {
     1868                                // XML 1.0 Section 2.9
     1869                                // Document is standalone, so attributes must not be defaulted.
     1870                                fValidator->emitError(XMLValid::NoDefAttForStandalone, curDef->getFullName(), elemDecl->getFullName());
     1871                                if (fGrammarType == Grammar::SchemaGrammarType)
     1872                                {
     1873                                    fPSVIElemContext.fErrorOccurred = true;
     1874                                }
     1875                            }
     1876
     1877                            #ifndef IGNORE_DEFAULT_ATTRIBUTES
     1878                            if (fGrammarType == Grammar::SchemaGrammarType)
     1879                            {
     1880                            #endif
     1881                                // Let the validator pass judgement on the attribute value
     1882                                fValidator->validateAttrValue
     1883                                (
     1884                                    curDef
     1885                                    , curDef->getValue()
     1886                                    , false
     1887                                    , elemDecl
     1888                                );
     1889
     1890                                XMLAttr * curAttr;
     1891                                if (attributeCount >= fAttrList.size())
     1892                                {
     1893                                    curAttr = new (fMemoryManager) XMLAttr(fMemoryManager);
     1894                                    // fValidator->faultInAttr(*curAttr, *curDef);
     1895                                    fAttrList.addElement(curAttr);
     1896                                }
     1897                                else
     1898                                {
     1899                                    curAttr = fAttrList.elementAt(attributeCount);
     1900                                    // fValidator->faultInAttr(*curAttr, *curDef);
     1901                                }
     1902
     1903                                fValidator->faultInAttr(*curAttr, *curDef);
     1904
     1905                                if (fGrammarType == Grammar::DTDGrammarType)
     1906                                {
     1907                                    //  Map the new attribute's prefix to a URI id and store that in the attribute object.
     1908                                    curAttr->setURIId(fUriResolver->getUriIdForPrefix(curAttr->getPrefix(), fContextId));
     1909                                }
     1910
     1911                                // Indicate it was not explicitly specified and bump count
     1912                                curAttr->setSpecified(false);
     1913
     1914                                // increase the attributeCount
     1915                                attributeCount++;
     1916                            #ifndef IGNORE_DEFAULT_ATTRIBUTES
     1917                            }
     1918                            #endif
     1919
     1920                            if (getPSVIHandler() && (fGrammarType == Grammar::SchemaGrammarType))
     1921                            {
     1922                                QName * attName = ((SchemaAttDef *)curDef)->getAttName();
     1923                                PSVIAttribute *defAttrToFill = fPSVIAttrList->getPSVIAttributeToFill
     1924                                (
     1925                                    attName->getLocalPart()
     1926                                    , fUriResolver->getUriForId(attName->getURI())
     1927                                );
     1928                                XSAttributeDeclaration *defAttrDecl = (XSAttributeDeclaration *)fModel->getXSObject((void *)curDef);
     1929                                DatatypeValidator * attrDataType = ((SchemaAttDef *)curDef)->getDatatypeValidator();
     1930                                XSSimpleTypeDefinition *defAttrType =
     1931                                    (XSSimpleTypeDefinition*)fModel->getXSObject(attrDataType);
     1932                                // would have occurred during validation of default value
     1933                                if(fSchemaValidator->getErrorOccurred())
     1934                                {
     1935                                    defAttrToFill->reset
     1936                                    (
     1937                                        fRootElemName
     1938                                        , PSVIItem::VALIDITY_INVALID
     1939                                        , PSVIItem::VALIDATION_FULL
     1940                                        , defAttrType
     1941                                        , 0
     1942                                        , curDef->getValue()
     1943                                        , true
     1944                                        , defAttrDecl
     1945                                        , 0
     1946                                    );
     1947                                }
     1948                                else
     1949                                {
     1950                                    XSSimpleTypeDefinition *defAttrMemberType = 0;
     1951                                    if (defAttrType->getVariety() == XSSimpleTypeDefinition::VARIETY_UNION)
     1952                                    {
     1953                                        defAttrMemberType = (XSSimpleTypeDefinition *)fModel->getXSObject
     1954                                        (
     1955                                            fSchemaValidator->getMostRecentAttrValidator()
     1956                                        );
     1957                                    }
     1958                                    defAttrToFill->reset(
     1959                                        fRootElemName
     1960                                        , PSVIItem::VALIDITY_VALID
     1961                                        , PSVIItem::VALIDATION_FULL
     1962                                        , defAttrType
     1963                                        , defAttrMemberType
     1964                                        , curDef->getValue()
     1965                                        , true
     1966                                        , defAttrDecl
     1967                                        , (defAttrMemberType)?fSchemaValidator->getMostRecentAttrValidator():attrDataType
     1968                                    );
     1969                                }
     1970                                defAttrToFill->setValue(curDef->getValue());
     1971                            }
     1972                        }
     1973                    }
     1974                    /*else if (unlikely(defType == XMLAttDef::Prohibited)) // attribute was provided for this definition
     1975                    {
     1976                        // TODO: is it safe to move the prohibited attribute validation into the attribute scan?
     1977
     1978                        // (schema) report error for PROHIBITED attrs that are present (V_TAGc)
     1979                        fValidator->emitError(XMLValid::ProhibitedAttributePresent, curDef->getFullName());
     1980
     1981                        if ((fGrammarType == Grammar::SchemaGrammarType))
     1982                        {
     1983                            fPSVIElemContext.fErrorOccurred = true;
     1984                            if (getPSVIHandler())
     1985                            {
     1986                                QName * attQName = ((SchemaAttDef *)curDef)->getAttName();
     1987                                // bad luck...
     1988                                PSVIAttribute *prohibitedAttr = fPSVIAttrList->getAttributePSVIByName
     1989                                (
     1990                                    attQName->getLocalPart()
     1991                                    , fUriResolver->getUriForId(attQName->getURI())
     1992                                );
     1993                                prohibitedAttr->updateValidity(PSVIItem::VALIDITY_INVALID);
     1994                            }
     1995                        }
     1996                    }*/
     1997                }
     1998            }
     1999        }
     2000
     2001        const unsigned int uriId = element->getQName()->getURI();
     2002
     2003        if (fGrammarType == Grammar::SchemaGrammarType)
     2004        {
     2005            // activate identity constraints
     2006            if (fGrammar && toCheckIdentityConstraint())
     2007            {
     2008                fICHandler->activateIdentityConstraint
     2009                (
     2010                      (SchemaElementDecl*)elemDecl
     2011                    , (int)fElemStack.getLevel()
     2012                    , uriId
     2013                    , qName->getPrefix()
     2014                    , fAttrList
     2015                    , attributeCount
     2016                    , fValidationContext
     2017                );
     2018            }
     2019        }
     2020
     2021        // Since the element may have default values, call start tag now regardless if it is empty or not
     2022        // If we have a document handler, then tell it about this start tag
     2023        if (fDocHandler)
     2024        {
     2025            QName * origQName = elemDecl->getElementName();
     2026            elemDecl->setElementName(qName);
     2027
     2028            fDocHandler->startElement
     2029            (
     2030                *elemDecl
     2031                , uriId
     2032                , qName->getPrefix()
     2033                , fAttrList
     2034                , attributeCount
     2035                , false
     2036                , isRoot
     2037            );
     2038
     2039            elemDecl->setElementName(origQName);
     2040        }
     2041
     2042        // if we have a PSVIHandler, now's the time to call
     2043        // its handleAttributesPSVI method:
     2044        if (fPSVIHandler && fGrammarType == Grammar::SchemaGrammarType)
     2045        {
     2046            QName * eName = elemDecl->getElementName();
     2047
     2048            fPSVIHandler->handleAttributesPSVI
     2049            (
     2050                eName->getLocalPart()
     2051                , fUriResolver->getUriForId(eName->getURI())
     2052                , fPSVIAttrList
     2053            );
     2054        }
     2055
     2056        //  If empty, validate content right now if we are validating and then
     2057        //  pop the element stack top. Else, we have to update the current stack
     2058        //  top's namespace mapping elements.
     2059        if (isEmpty)
     2060        {
     2061            // Pop the element stack back off since it'll never be used now
     2062            fElemStack.popTop();
     2063
     2064            // reset current type info
     2065            DatatypeValidator* psviMemberType = 0;
     2066            if (fGrammarType == Grammar::SchemaGrammarType)
     2067            {
     2068                if (fValidate && elemDecl->isDeclared())
     2069                {
     2070                    fPSVIElemContext.fCurrentTypeInfo = fSchemaValidator->getCurrentTypeInfo();
     2071                    if (!fPSVIElemContext.fCurrentTypeInfo)
     2072                        fPSVIElemContext.fCurrentDV = fSchemaValidator->getCurrentDatatypeValidator();
     2073                    else
     2074                        fPSVIElemContext.fCurrentDV = 0;
     2075                    if (fPSVIHandler)
     2076                    {
     2077                        if (XMLString::stringLen(fPSVIElemContext.fNormalizedValue) == 0)
     2078                            fPSVIElemContext.fNormalizedValue = 0;
     2079                    }
     2080                }
     2081                else
     2082                {
     2083                    fPSVIElemContext.fCurrentDV = 0;
     2084                    fPSVIElemContext.fCurrentTypeInfo = 0;
     2085                    fPSVIElemContext.fNormalizedValue = 0;
     2086                }
     2087            }
     2088
     2089            // If validating, then insure that its legal to have no content
     2090            if (fValidate)
     2091            {
     2092                XMLSize_t failure;
     2093                bool res = fValidator->checkContent(elemDecl, ((XMLElementDecl**)0), 0, &failure);
     2094                if (!res)
     2095                {
     2096                    fValidator->emitError
     2097                    (
     2098                        XMLValid::ElementNotValidForContent
     2099                        , elemDecl->getFullName()
     2100                        , elemDecl->getFormattedContentModel()
     2101                    );
     2102                }
     2103
     2104                if (fGrammarType == Grammar::SchemaGrammarType)
     2105                {
     2106                    if (fSchemaValidator->getErrorOccurred())
     2107                    {
     2108                        fPSVIElemContext.fErrorOccurred = true;
     2109                    }
     2110                    else
     2111                    {
     2112                        if (fPSVIHandler)
     2113                        {
     2114                            fPSVIElemContext.fIsSpecified = fSchemaValidator->getIsElemSpecified();
     2115                            if(fPSVIElemContext.fIsSpecified)
     2116                                fPSVIElemContext.fNormalizedValue = ((SchemaElementDecl *)elemDecl)->getDefaultValue();
     2117                        }
     2118                        // note that if we're empty, won't be a current DV
     2119                        if (fPSVIElemContext.fCurrentDV && fPSVIElemContext.fCurrentDV->getType() == DatatypeValidator::Union)
     2120                            psviMemberType = fValidationContext->getValidatingMemberType();
     2121                    }
     2122
     2123                    // call matchers and de-activate context
     2124                    if (toCheckIdentityConstraint())
     2125                    {
     2126                        fICHandler->deactivateContext
     2127                        (
     2128                            (SchemaElementDecl *)elemDecl
     2129                            , fContent.getRawBuffer()
     2130                            , fValidationContext
     2131                            , fPSVIElemContext.fCurrentDV
     2132                        );
     2133                    }
     2134
     2135                }
     2136            }
     2137            else if (fGrammarType == Grammar::SchemaGrammarType)
     2138            {
     2139                fSchemaValidator->resetNillable();
     2140            }
     2141
     2142            if (fGrammarType == Grammar::SchemaGrammarType)
     2143            {
     2144                if (fPSVIHandler)
     2145                {
     2146                    endElementPSVI((SchemaElementDecl*)elemDecl, psviMemberType);
     2147                }
     2148            }
     2149
     2150            // If we have a doc handler, tell it about the end tag
     2151            if (fDocHandler)
     2152            {
     2153                QName * origQName = elemDecl->getElementName();
     2154                elemDecl->setElementName(qName);
     2155
     2156                fDocHandler->endElement
     2157                (
     2158                    *elemDecl
     2159                    , uriId
     2160                    , isRoot
     2161                    , qName->getPrefix()
     2162                );
     2163
     2164                elemDecl->setElementName(origQName);
     2165            }
     2166
     2167            // If the elem stack is empty, then it was an empty root
     2168            if (!isRoot)
     2169            {
     2170                // Restore the grammar
     2171                fGrammar = fElemStack.getCurrentGrammar();
     2172                fGrammarType = fGrammar->getGrammarType();
     2173
     2174                if (fGrammarType == Grammar::SchemaGrammarType && !fValidator->handlesSchema())
     2175                {
     2176                    if (fValidatorFromUser)
     2177                        ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoSchemaValidator, fMemoryManager);
     2178                    else
     2179                    {
     2180                        fValidator = fSchemaValidator;
     2181                    }
     2182                }
     2183                else if (fGrammarType == Grammar::DTDGrammarType && !fValidator->handlesDTD())
     2184                {
     2185                    if (fValidatorFromUser)
     2186                        ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoDTDValidator, fMemoryManager);
     2187                    else
     2188                    {
     2189                        fValidator = fDTDValidator;
     2190                    }
     2191                }
     2192
     2193                fValidator->setGrammar(fGrammar);
     2194
     2195                // Restore the validation flag
     2196                fValidate = fElemStack.getValidationFlag();
     2197            }
     2198        }
     2199
     2200        if (fGrammarType == Grammar::SchemaGrammarType)
     2201        {
     2202            // send a partial element psvi
     2203            if (fPSVIHandler)
     2204            {
     2205                ComplexTypeInfo   * curTypeInfo = 0;
     2206                DatatypeValidator * curDV = 0;
     2207                XSTypeDefinition  * typeDef = 0;
     2208
     2209                if (fValidate && elemDecl->isDeclared())
     2210                {
     2211                    curTypeInfo = fSchemaValidator->getCurrentTypeInfo();
     2212
     2213                    if (curTypeInfo)
     2214                    {
     2215                        typeDef = (XSTypeDefinition*) fModel->getXSObject(curTypeInfo);
     2216                    }
     2217                    else
     2218                    {
     2219                        curDV = fSchemaValidator->getCurrentDatatypeValidator();
     2220
     2221                        if (curDV)
     2222                        {
     2223                            typeDef = (XSTypeDefinition*) fModel->getXSObject(curDV);
     2224                        }
     2225                    }
     2226                }
     2227
     2228                fPSVIElement->reset
     2229                (
     2230                      PSVIElement::VALIDITY_NOTKNOWN
     2231                    , PSVIElement::VALIDATION_NONE
     2232                    , fRootElemName
     2233                    , fSchemaValidator->getIsElemSpecified()
     2234                    , (elemDecl->isDeclared()) ? (XSElementDeclaration*) fModel->getXSObject(elemDecl) : 0
     2235                    , typeDef
     2236                    , 0 //memberType
     2237                    , fModel
     2238                    , ((SchemaElementDecl*)elemDecl)->getDefaultValue()
     2239                    , 0
     2240                    , 0
     2241                    , 0
     2242                );
     2243
     2244
     2245                fPSVIHandler->handlePartialElementPSVI
     2246                (
     2247                    elemDecl->getBaseName()
     2248                    , fUriResolver->getUriForId(elemDecl->getURI())
     2249                    , fPSVIElement
     2250                );
     2251
     2252            }
     2253
     2254            // not empty
     2255            fErrorStack->push(fPSVIElemContext.fErrorOccurred);
     2256        }
     2257    }
     2258
     2259    return elemDecl;
     2260}
     2261
     2262// --------------------------------------------------------------------------------------------------------
     2263// HANDLE END TAG
     2264// --------------------------------------------------------------------------------------------------------
     2265
     2266void IGXMLScanner::handleEndTag
     2267(
     2268    XMLElementDecl * const                      elemDecl
     2269    , const unsigned int                        uriId
     2270    , const XMLSize_t                           readerNum
     2271    , const bool                                        isRoot
     2272    , XMLElementDecl **                         children
     2273    , const XMLSize_t                           childCount
     2274)
     2275{
     2276//      //  Pop the stack of the element we are supposed to be ending. Remember
     2277//      //  that we don't own this. The stack just keeps them and reuses them.
     2278
     2279    // these get initialized below
     2280    const ElemStack::StackElem * topElem = fElemStack.topElement();
     2281
     2282    // Make sure we are back on the same reader as where we started
     2283    if (unlikely(topElem->fReaderNum != readerNum))
     2284    {
     2285        emitError(XMLErrs::PartialTagMarkupError);
     2286    }
     2287
     2288    if (fGrammarType == Grammar::SchemaGrammarType)
     2289    {
     2290        // reset error occurred
     2291        fPSVIElemContext.fErrorOccurred = fErrorStack->pop();
     2292        if (fValidate && elemDecl->isDeclared())
     2293        {
     2294            fPSVIElemContext.fCurrentTypeInfo = fSchemaValidator->getCurrentTypeInfo();
     2295            if(!fPSVIElemContext.fCurrentTypeInfo)
     2296                fPSVIElemContext.fCurrentDV = fSchemaValidator->getCurrentDatatypeValidator();
     2297            else
     2298                fPSVIElemContext.fCurrentDV = 0;
     2299
     2300            if(fPSVIHandler)
     2301            {
     2302                //fPSVIElemContext.fNormalizedValue = fSchemaValidator->getNormalizedValue();
     2303                if (fPSVIElemContext.fNormalizedValue && *fPSVIElemContext.fNormalizedValue == 0)
     2304                    fPSVIElemContext.fNormalizedValue = 0;
     2305            }
     2306        }
     2307        else
     2308        {
     2309            fPSVIElemContext.fCurrentDV = 0;
     2310            fPSVIElemContext.fCurrentTypeInfo = 0;
     2311            fPSVIElemContext.fNormalizedValue = 0;
     2312        }
     2313    }
     2314
     2315    //  If validation is enabled, then lets pass him the list of children and
     2316    //  this element and let him validate it.
     2317    DatatypeValidator* psviMemberType = 0;
     2318
     2319    if (fValidate)
     2320    {
     2321        // XML1.0-3rd
     2322        // Validity Constraint:
     2323        // The declaration matches EMPTY and the element has no content (not even
     2324        // entity references, comments, PIs or white space).
     2325        //
     2326        if (fGrammarType == Grammar::DTDGrammarType && (topElem->fCommentOrPISeen) && ((DTDElementDecl*)elemDecl)->getModelType() == DTDElementDecl::Empty)
     2327        {
     2328            fValidator->emitError(XMLValid::EmptyElemHasContent, elemDecl->getFullName());
     2329        }
     2330
     2331        XMLSize_t failure;
     2332        bool res = fValidator->checkContent
     2333        (
     2334           elemDecl
     2335           , children
     2336           , childCount
     2337           , &failure
     2338        );
     2339
     2340        if (unlikely(!res))
     2341        {
     2342            //  One of the elements is not valid for the content. NOTE that
     2343            //  if no children were provided but the content model requires
     2344            //  them, it comes back with a zero value. But we cannot use that
     2345            //  to index the child array in this case, and have to put out a
     2346            //  special message.
     2347            if (!childCount)
     2348            {
     2349                fValidator->emitError
     2350                (
     2351                    XMLValid::EmptyNotValidForContent
     2352                    , elemDecl->getFormattedContentModel()
     2353                );
     2354            }
     2355            else if (failure >= childCount)
     2356            {
     2357                fValidator->emitError
     2358                (
     2359                    XMLValid::NotEnoughElemsForCM
     2360                    , elemDecl->getFormattedContentModel()
     2361                );
     2362            }
     2363            else
     2364            {
     2365                fValidator->emitError
     2366                (
     2367                    XMLValid::ElementNotValidForContent
     2368                    , children[failure]->getFullName()
     2369                    , elemDecl->getFormattedContentModel()
     2370                );
     2371            }
     2372        }
     2373
     2374        if (fGrammarType == Grammar::SchemaGrammarType)
     2375        {
     2376            if (fSchemaValidator->getErrorOccurred())
     2377                fPSVIElemContext.fErrorOccurred = true;
     2378            else if (fPSVIElemContext.fCurrentDV && fPSVIElemContext.fCurrentDV->getType() == DatatypeValidator::Union)
     2379                psviMemberType = fValidationContext->getValidatingMemberType();
     2380
     2381            if (fPSVIHandler)
     2382            {
     2383                fPSVIElemContext.fIsSpecified = fSchemaValidator->getIsElemSpecified();
     2384                if (fPSVIElemContext.fIsSpecified)
     2385                {
     2386                    fPSVIElemContext.fNormalizedValue = ((SchemaElementDecl *)elemDecl)->getDefaultValue();
     2387                }
     2388            }
     2389
     2390            // call matchers and de-activate context
     2391            if (toCheckIdentityConstraint())
     2392            {
     2393                fICHandler->deactivateContext
     2394                (
     2395                    (SchemaElementDecl *)elemDecl
     2396                    , fContent.getRawBuffer()
     2397                    , fValidationContext
     2398                    , fPSVIElemContext.fCurrentDV
     2399                );
     2400            }
     2401        }
     2402    }
     2403
     2404    // QName dv needed topElem to resolve URIs on the checkContent
     2405    fElemStack.popTop();
     2406
     2407    if (fGrammarType == Grammar::SchemaGrammarType)
     2408    {
     2409        if (fPSVIHandler)
     2410        {
     2411            endElementPSVI((SchemaElementDecl*)topElem->fThisElement, psviMemberType);
     2412        }
     2413        // now we can reset the datatype buffer, since the
     2414        // application has had a chance to copy the characters somewhere else
     2415        // fSchemaValidator->clearDatatypeBuffer();
     2416        fPSVIElemContext.fNormalizedValue = 0;
     2417    }
     2418
     2419    // If we have a doc handler, tell it about the end tag
     2420    if (fDocHandler)
     2421    {
     2422        fDocHandler->endElement
     2423        (
     2424            * elemDecl
     2425            , uriId
     2426            , isRoot
     2427            , elemDecl->getElementName()->getPrefix()
     2428        );
     2429    }
     2430
     2431    // If this was the root, then done with content
     2432    if (likely(!isRoot))
     2433    {
     2434        if (fGrammarType == Grammar::SchemaGrammarType)
     2435        {
     2436            // update error information
     2437            fErrorStack->push((fErrorStack->size() && fErrorStack->pop()) || fPSVIElemContext.fErrorOccurred);
     2438        }
     2439
     2440        if (fDoNamespaces)
     2441        {
     2442            // Restore the grammar
     2443            fGrammar = fElemStack.getCurrentGrammar();
     2444            fGrammarType = fGrammar->getGrammarType();
     2445
     2446            if (fGrammarType == Grammar::SchemaGrammarType && !fValidator->handlesSchema())
     2447            {
     2448                if (fValidatorFromUser)
     2449                {
     2450                    ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoSchemaValidator, fMemoryManager);
     2451                }
     2452                else
     2453                {
     2454                    fValidator = fSchemaValidator;
     2455                }
     2456            }
     2457            else if (fGrammarType == Grammar::DTDGrammarType && !fValidator->handlesDTD())
     2458            {
     2459                if (fValidatorFromUser)
     2460                {
     2461                    ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoDTDValidator, fMemoryManager);
     2462                }
     2463                else
     2464                {
     2465                    fValidator = fDTDValidator;
     2466                }
     2467            }
     2468            fValidator->setGrammar(fGrammar);
     2469        }
     2470
     2471        // Restore the validation flag
     2472        fValidate = fElemStack.getValidationFlag();
     2473    }
     2474}
     2475
     2476// --------------------------------------------------------------------------------------------------------
     2477// HANDLE CONTENT
     2478// --------------------------------------------------------------------------------------------------------
     2479
     2480void IGXMLScanner::handleContent
     2481(
     2482    const XMLCh       * content
     2483    , const XMLSize_t   length
     2484)
     2485{
     2486    //  We do different things according to whether we are validating or
     2487    //  not. If not, its always just characters; else, it depends on the
     2488    //  current element's content model.
     2489    if (fValidate)
     2490    {
     2491        // And see if the current element is a 'Children' style content model
     2492        const ElemStack::StackElem * topElem = fElemStack.topElement();
     2493
     2494        // Get the character data opts for the current element
     2495        XMLElementDecl::CharDataOpts charOpts = XMLElementDecl::AllCharData;
     2496        // fGrammar->getGrammarType()
     2497        if (fGrammarType == Grammar::SchemaGrammarType)
     2498        {
     2499            // And see if the current element is a 'Children' style content model
     2500            ComplexTypeInfo * currType = fSchemaValidator->getCurrentTypeInfo();
     2501            if (currType)
     2502            {
     2503                switch ((SchemaElementDecl::ModelTypes)currType->getContentType())
     2504                {
     2505                    case SchemaElementDecl::Empty:
     2506                        charOpts = XMLElementDecl::NoCharData;
     2507                        break;
     2508                    case SchemaElementDecl::Children:
     2509                    case SchemaElementDecl::ElementOnlyEmpty:
     2510                        charOpts = XMLElementDecl::SpacesOk;
     2511                }
     2512            }
     2513        }
     2514        else // DTD grammar
     2515        {
     2516            charOpts = topElem->fThisElement->getCharDataOpts();
     2517        }
     2518
     2519        if (charOpts == XMLElementDecl::AllCharData)
     2520        {
     2521            XMLSize_t normLength = length;
     2522            const XMLCh * normContent = content;
     2523
     2524            if (fGrammarType == Grammar::SchemaGrammarType)
     2525            {
     2526                DatatypeValidator * tempDV =
     2527                    fSchemaValidator->getCurrentDatatypeValidator();
     2528
     2529                if (tempDV)
     2530                {
     2531                    if (tempDV->getWSFacet() != DatatypeValidator::PRESERVE)
     2532                    {
     2533                        // normalize the character according to schema whitespace facet
     2534                        fSchemaValidator->normalizeWhiteSpace(tempDV, content, fWSNormalizeBuf);
     2535                        normContent = fWSNormalizeBuf.getRawBuffer();
     2536                        normLength = fWSNormalizeBuf.getLen();
     2537                    }
     2538                }
     2539                // tell the schema validation about the character data for checkContent later
     2540                fSchemaValidator->setDatatypeBuffer(normContent);
     2541
     2542                // call all active identity constraints
     2543                if (toCheckIdentityConstraint() && fICHandler->getMatcherCount())
     2544                {
     2545                    fContent.append(normContent, normLength);
     2546                }
     2547            }
     2548
     2549            if (fDocHandler)
     2550            {
     2551                if (fNormalizeData)
     2552                {
     2553                    fDocHandler->docCharacters(normContent, normLength, false);
     2554                }
     2555                else
     2556                {
     2557                    fDocHandler->docCharacters(content, length, false);
     2558                }
     2559            }
     2560            return;
     2561        }
     2562        else if (charOpts == XMLElementDecl::SpacesOk)
     2563        {
     2564            if (XMLString::isAllSpaces(content, length))
     2565            {
     2566                if (fDocHandler)
     2567                {
     2568                    fDocHandler->ignorableWhitespace(content, length, false);
     2569                }
     2570                return;
     2571            }
     2572        }
     2573        // either there is an error or no char data is allowed
     2574        fValidator->emitError(XMLValid::NoCharDataInCM);
     2575    }
     2576    else
     2577    {
     2578
     2579        // Always assume it's just char data if we're not validating
     2580        if (fDocHandler)
     2581        {
     2582            fDocHandler->docCharacters(content, length, false);
     2583        }
     2584    }
     2585}
     2586
     2587// --------------------------------------------------------------------------------------------------------
     2588
     2589void IGXMLScanner::handleCDATA
     2590(
     2591    const XMLCh       * cdata
     2592    , const XMLSize_t   length
     2593)
     2594{
     2595    if (fElemStack.isEmpty())
     2596    {
     2597        emitError(XMLErrs::CDATAOutsideOfContent);
     2598    }
     2599
     2600    const ElemStack::StackElem* topElem = fElemStack.topElement();
     2601
     2602    // Get the character data opts for the current element
     2603    XMLElementDecl::CharDataOpts charOpts = XMLElementDecl::AllCharData;
     2604
     2605    if (fGrammarType == Grammar::SchemaGrammarType)
     2606    {
     2607        // And see if the current element is a 'Children' style content model
     2608        ComplexTypeInfo *currType = fSchemaValidator->getCurrentTypeInfo();
     2609        if(currType)
     2610        {
     2611            SchemaElementDecl::ModelTypes modelType = (SchemaElementDecl::ModelTypes) currType->getContentType();
     2612            if (modelType == SchemaElementDecl::Children || modelType == SchemaElementDecl::ElementOnlyEmpty)
     2613                charOpts = XMLElementDecl::SpacesOk;
     2614            else if(modelType == SchemaElementDecl::Empty)
     2615                charOpts = XMLElementDecl::NoCharData;
     2616        }
     2617
     2618        const XMLCh* xsNormalized = cdata;
     2619        const XMLSize_t xsLen = length;
     2620
     2621        if (fValidate)
     2622        {
     2623            // tell the schema validation about the character data for checkContent later
     2624            fPSVIElemContext.fNormalizedValue = xsNormalized;
     2625
     2626            if (charOpts != XMLElementDecl::AllCharData)
     2627            {
     2628                // They definitely cannot handle any type of char data
     2629                fValidator->emitError(XMLValid::NoCharDataInCM);
     2630                if (getPSVIHandler())
     2631                {
     2632                    // REVISIT:
     2633                    // PSVIElement->setValidity(PSVIItem::VALIDITY_INVALID);
     2634                }
     2635            }
     2636        }
     2637
     2638        // call all active identity constraints
     2639        if (toCheckIdentityConstraint() && fICHandler->getMatcherCount())
     2640        {
     2641            fContent.append(xsNormalized, xsLen);
     2642        }
     2643    }
     2644    else // DTD grammar
     2645    {
     2646        if (fValidate)
     2647        {
     2648            charOpts = topElem->fThisElement->getCharDataOpts();
     2649            if (charOpts != XMLElementDecl::AllCharData)
     2650            {
     2651                // They definitely cannot handle any type of char data
     2652                fValidator->emitError(XMLValid::NoCharDataInCM);
     2653            }
     2654        }
     2655    }
     2656
     2657    if (fDocHandler)
     2658    {
     2659        fDocHandler->docCharacters(cdata, length, true);
     2660    }
     2661}
     2662
    6232663// ----------------------------------------------------------------------------------------------
    6242664
    625 inline void IGXMLScanner::setXsiType
     2665void IGXMLScanner::setXsiType
    6262666(
    6272667        const XMLCh *                           value
     
    6292669)
    6302670{
    631 
     2671    DEBUG_GRAMMAR_MESSAGE("IGXMLScanner::setXsiType(" << value << ',' << length << ')')
    6322672        if (fSchemaValidator)
    6332673        {
    634                 const int colonPos = XMLStringU::indexOf<chColon>(value, length);
     2674        const int colonPos = XMLStringU::indexOf<chColon>(value, length);
    6352675
    6362676                if (unlikely(colonPos == -1))
     
    6472687                        fSchemaValidator->setXsiType
    6482688                        (
    649                                 value, xsiTypeColon + 1, fUriResolver->getUriIdForPrefix(value, getContextId())
    650                         );
     2689                value, xsiTypeColon + 1, fUriResolver->getUriIdForPrefix(value, getContextId())
     2690            );
    6512691                        *xsiTypeColon = chColon;
    6522692                }
     
    6552695}
    6562696
    657 inline void IGXMLScanner::setXsiNil
     2697void IGXMLScanner::setXsiNil
    6582698(
    6592699        const XMLCh *                           value
     
    6612701)
    6622702{
    663 
     2703    DEBUG_GRAMMAR_MESSAGE("IGXMLScanner::setXsiNil(" << value << ',' << length << ')')
    6642704        if (fSchemaValidator)
    6652705        {
Note: See TracChangeset for help on using the changeset viewer.