GME  13
XSAXMLScanner.cpp
Go to the documentation of this file.
00001 /*
00002  * Licensed to the Apache Software Foundation (ASF) under one or more
00003  * contributor license agreements.  See the NOTICE file distributed with
00004  * this work for additional information regarding copyright ownership.
00005  * The ASF licenses this file to You under the Apache License, Version 2.0
00006  * (the "License"); you may not use this file except in compliance with
00007  * the License.  You may obtain a copy of the License at
00008  *
00009  *      http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 /*
00019  * $Id: XSAXMLScanner.cpp 833045 2009-11-05 13:21:27Z borisk $
00020  */
00021 
00022 
00023 // ---------------------------------------------------------------------------
00024 //  Includes
00025 // ---------------------------------------------------------------------------
00026 #include <xercesc/internal/XSAXMLScanner.hpp>
00027 
00028 #include <xercesc/sax/InputSource.hpp>
00029 #include <xercesc/framework/XMLEntityHandler.hpp>
00030 #include <xercesc/framework/XMLDocumentHandler.hpp>
00031 #include <xercesc/framework/psvi/XSAnnotation.hpp>
00032 #include <xercesc/validators/schema/SchemaValidator.hpp>
00033 
00034 
00035 XERCES_CPP_NAMESPACE_BEGIN
00036 
00037 // ---------------------------------------------------------------------------
00038 //  XSAXMLScanner: Constructors and Destructor
00039 // ---------------------------------------------------------------------------
00040 XSAXMLScanner::XSAXMLScanner( GrammarResolver* const grammarResolver
00041                             , XMLStringPool* const   uriStringPool
00042                             , SchemaGrammar* const   xsaGrammar
00043                             , MemoryManager* const manager) :
00044 
00045     SGXMLScanner(0, grammarResolver, manager)
00046 {
00047     fSchemaGrammar = xsaGrammar;
00048     setURIStringPool(uriStringPool);
00049 }
00050 
00051 XSAXMLScanner::~XSAXMLScanner()
00052 {
00053 }
00054 
00055 // ---------------------------------------------------------------------------
00056 //  XSAXMLScanner: SGXMLScanner virtual methods
00057 // ---------------------------------------------------------------------------
00058 //  This method will kick off the scanning of the primary content of the
00059 void XSAXMLScanner::scanEndTag(bool& gotData)
00060 {
00061     //  Assume we will still have data until proven otherwise. It will only
00062     //  ever be false if this is the end of the root element.
00063     gotData = true;
00064 
00065     //  Check if the element stack is empty. If so, then this is an unbalanced
00066     //  element (i.e. more ends than starts, perhaps because of bad text
00067     //  causing one to be skipped.)
00068     if (fElemStack.isEmpty())
00069     {
00070         emitError(XMLErrs::MoreEndThanStartTags);
00071         fReaderMgr.skipPastChar(chCloseAngle);
00072         ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Scan_UnbalancedStartEnd, fMemoryManager);
00073     }
00074 
00075     //  Pop the stack of the element we are supposed to be ending. Remember
00076     //  that we don't own this. The stack just keeps them and reuses them.
00077     unsigned int uriId = fElemStack.getCurrentURI();
00078 
00079     // Make sure that its the end of the element that we expect
00080     const XMLCh *elemName = fElemStack.getCurrentSchemaElemName();
00081     const ElemStack::StackElem* topElem = fElemStack.popTop();
00082     if (!fReaderMgr.skippedStringLong(elemName))
00083     {
00084         emitError
00085         (
00086             XMLErrs::ExpectedEndOfTagX, elemName
00087         );
00088         fReaderMgr.skipPastChar(chCloseAngle);
00089         return;
00090     }
00091 
00092     // See if it was the root element, to avoid multiple calls below
00093     const bool isRoot = fElemStack.isEmpty();
00094 
00095     // Make sure we are back on the same reader as where we started
00096     if (topElem->fReaderNum != fReaderMgr.getCurrentReaderNum())
00097         emitError(XMLErrs::PartialTagMarkupError);
00098 
00099     // Skip optional whitespace
00100     fReaderMgr.skipPastSpaces();
00101 
00102     // Make sure we find the closing bracket
00103     if (!fReaderMgr.skippedChar(chCloseAngle))
00104     {
00105         emitError
00106         (
00107             XMLErrs::UnterminatedEndTag, topElem->fThisElement->getFullName()
00108         );
00109     }
00110 
00111     //  If validation is enabled, then lets pass him the list of children and
00112     //  this element and let him validate it.
00113     if (fValidate)
00114     {
00115         XMLSize_t failure;
00116         bool res = fValidator->checkContent
00117         (
00118             topElem->fThisElement
00119             , topElem->fChildren
00120             , topElem->fChildCount
00121             , &failure
00122         );
00123 
00124         if (!res)
00125         {
00126             //  One of the elements is not valid for the content. NOTE that
00127             //  if no children were provided but the content model requires
00128             //  them, it comes back with a zero value. But we cannot use that
00129             //  to index the child array in this case, and have to put out a
00130             //  special message.
00131             if (!topElem->fChildCount)
00132             {
00133                 fValidator->emitError
00134                 (
00135                     XMLValid::EmptyNotValidForContent
00136                     , topElem->fThisElement->getFormattedContentModel()
00137                 );
00138             }
00139             else if (failure >= topElem->fChildCount)
00140             {
00141                 fValidator->emitError
00142                 (
00143                     XMLValid::NotEnoughElemsForCM
00144                     , topElem->fThisElement->getFormattedContentModel()
00145                 );
00146             }
00147             else
00148             {
00149                 fValidator->emitError
00150                 (
00151                     XMLValid::ElementNotValidForContent
00152                     , topElem->fChildren[failure]->getRawName()
00153                     , topElem->fThisElement->getFormattedContentModel()
00154                 );
00155             }
00156         }
00157     }
00158 
00159     // now we can reset the datatype buffer, since the
00160     // application has had a chance to copy the characters somewhere else
00161     ((SchemaValidator *)fValidator)->clearDatatypeBuffer();
00162 
00163     // If we have a doc handler, tell it about the end tag
00164     if (fDocHandler)
00165     {
00166         if (topElem->fPrefixColonPos != -1)
00167             fPrefixBuf.set(elemName, topElem->fPrefixColonPos);
00168         else
00169             fPrefixBuf.reset();
00170         fDocHandler->endElement
00171         (
00172             *topElem->fThisElement
00173             , uriId
00174             , isRoot
00175             , fPrefixBuf.getRawBuffer()
00176         );
00177     }
00178 
00179     // If this was the root, then done with content
00180     gotData = !isRoot;
00181 
00182     if (gotData) {
00183 
00184         // Restore the grammar
00185         fGrammar = fElemStack.getCurrentGrammar();
00186         fGrammarType = fGrammar->getGrammarType();
00187         fValidator->setGrammar(fGrammar);
00188 
00189         // Restore the validation flag
00190         fValidate = fElemStack.getValidationFlag();
00191     }
00192 }
00193 
00194 bool XSAXMLScanner::scanStartTag(bool& gotData)
00195 {
00196     //  Assume we will still have data until proven otherwise. It will only
00197     //  ever be false if this is the root and its empty.
00198     gotData = true;
00199 
00200     // Reset element content
00201     fContent.reset();
00202 
00203     //  The current position is after the open bracket, so we need to read in
00204     //  in the element name.
00205     int prefixColonPos;
00206     if (!fReaderMgr.getQName(fQNameBuf, &prefixColonPos))
00207     {
00208         if (fQNameBuf.isEmpty())
00209             emitError(XMLErrs::ExpectedElementName);
00210         else
00211             emitError(XMLErrs::InvalidElementName, fQNameBuf.getRawBuffer());
00212         fReaderMgr.skipToChar(chOpenAngle);
00213         return false;
00214     }
00215 
00216     // See if its the root element
00217     const bool isRoot = fElemStack.isEmpty();
00218 
00219     // Skip any whitespace after the name
00220     fReaderMgr.skipPastSpaces();
00221 
00222     //  First we have to do the rawest attribute scan. We don't do any
00223     //  normalization of them at all, since we don't know yet what type they
00224     //  might be (since we need the element decl in order to do that.)
00225     const XMLCh* qnameRawBuf = fQNameBuf.getRawBuffer();
00226     bool isEmpty;
00227     XMLSize_t attCount = rawAttrScan(qnameRawBuf, *fRawAttrList, isEmpty);
00228 
00229     // save the contentleafname and currentscope before addlevel, for later use
00230     ContentLeafNameTypeVector* cv = 0;
00231     XMLContentModel* cm = 0;
00232     unsigned int currentScope = Grammar::TOP_LEVEL_SCOPE;
00233     bool laxThisOne = false;
00234     if (!isRoot)
00235     {
00236         // schema validator will have correct type if validating
00237         SchemaElementDecl* tempElement = (SchemaElementDecl*)
00238             fElemStack.topElement()->fThisElement;
00239         SchemaElementDecl::ModelTypes modelType = tempElement->getModelType();
00240         ComplexTypeInfo *currType = 0;
00241 
00242         if (fValidate)
00243         {
00244             currType = ((SchemaValidator*)fValidator)->getCurrentTypeInfo();
00245             if (currType)
00246                 modelType = (SchemaElementDecl::ModelTypes)currType->getContentType();
00247             else // something must have gone wrong
00248                 modelType = SchemaElementDecl::Any;
00249         }
00250         else {
00251             currType = tempElement->getComplexTypeInfo();
00252         }
00253 
00254         if ((modelType == SchemaElementDecl::Mixed_Simple)
00255           ||  (modelType == SchemaElementDecl::Mixed_Complex)
00256           ||  (modelType == SchemaElementDecl::Children))
00257         {
00258             cm = currType->getContentModel();
00259             cv = cm->getContentLeafNameTypeVector();
00260             currentScope = fElemStack.getCurrentScope();
00261         }
00262         else if (modelType == SchemaElementDecl::Any) {
00263             laxThisOne = true;
00264         }
00265     }
00266 
00267     //  Now, since we might have to update the namespace map for this element,
00268     //  but we don't have the element decl yet, we just tell the element stack
00269     //  to expand up to get ready.
00270     XMLSize_t elemDepth = fElemStack.addLevel();
00271     fElemStack.setValidationFlag(fValidate);
00272     fElemStack.setPrefixColonPos(prefixColonPos);
00273 
00274     //  Make an initial pass through the list and find any xmlns attributes or
00275     //  schema attributes.
00276     if (attCount)
00277         scanRawAttrListforNameSpaces(attCount);
00278 
00279     //  Resolve the qualified name to a URI and name so that we can look up
00280     //  the element decl for this element. We have now update the prefix to
00281     //  namespace map so we should get the correct element now.
00282     unsigned int uriId = resolveQNameWithColon
00283     (
00284         qnameRawBuf, fPrefixBuf, ElemStack::Mode_Element, prefixColonPos
00285     );
00286 
00287     //if schema, check if we should lax or skip the validation of this element
00288     bool parentValidation = fValidate;
00289     if (cv) {
00290         QName element(fPrefixBuf.getRawBuffer(), &qnameRawBuf[prefixColonPos + 1], uriId, fMemoryManager);
00291         // elementDepth will be > 0, as cv is only constructed if element is not
00292         // root.
00293         laxThisOne = laxElementValidation(&element, cv, cm, elemDepth - 1);
00294     }
00295 
00296     //  Look up the element now in the grammar. This will get us back a
00297     //  generic element decl object. We tell him to fault one in if he does
00298     //  not find it.
00299     bool wasAdded = false;
00300     const XMLCh* nameRawBuf = &qnameRawBuf[prefixColonPos + 1];
00301     XMLElementDecl* elemDecl = fGrammar->getElemDecl
00302     (
00303         uriId, nameRawBuf, qnameRawBuf, currentScope
00304     );
00305 
00306     if (!elemDecl)
00307     {
00308         // URI is different, so we try to switch grammar
00309         if (uriId != fURIStringPool->getId(fGrammar->getTargetNamespace())) {
00310             switchGrammar(getURIText(uriId), laxThisOne);
00311         }
00312 
00313         // look for a global element declaration
00314         elemDecl = fGrammar->getElemDecl(
00315             uriId, nameRawBuf, qnameRawBuf, Grammar::TOP_LEVEL_SCOPE
00316         );
00317 
00318         if (!elemDecl)
00319         {
00320             // if still not found, look in list of undeclared elements
00321             elemDecl = fElemNonDeclPool->getByKey(
00322                 nameRawBuf, uriId, (int)Grammar::TOP_LEVEL_SCOPE);
00323 
00324             if (!elemDecl)
00325             {
00326                 elemDecl = new (fMemoryManager) SchemaElementDecl
00327                 (
00328                     fPrefixBuf.getRawBuffer(), nameRawBuf, uriId
00329                     , SchemaElementDecl::Any, Grammar::TOP_LEVEL_SCOPE
00330                     , fMemoryManager
00331                 );
00332 
00333                 elemDecl->setId (fElemNonDeclPool->put(
00334                       (void*)elemDecl->getBaseName(),
00335                       uriId,
00336                       (int)Grammar::TOP_LEVEL_SCOPE,
00337                       (SchemaElementDecl*)elemDecl));
00338 
00339                 wasAdded = true;
00340             }
00341                 }
00342     }
00343 
00344     //  We do something different here according to whether we found the
00345     //  element or not.
00346     bool bXsiTypeSet= (fValidator)?((SchemaValidator*)fValidator)->getIsXsiTypeSet():false;
00347     if (wasAdded || !elemDecl->isDeclared())
00348     {
00349         if (laxThisOne && !bXsiTypeSet) {
00350             fValidate = false;
00351             fElemStack.setValidationFlag(fValidate);
00352         }
00353 
00354         // If validating then emit an error
00355         if (fValidate)
00356         {
00357             // This is to tell the reuse Validator that this element was
00358             // faulted-in, was not an element in the grammar pool originally
00359             elemDecl->setCreateReason(XMLElementDecl::JustFaultIn);
00360 
00361             if(!bXsiTypeSet)
00362                 fValidator->emitError
00363                 (
00364                     XMLValid::ElementNotDefined, elemDecl->getFullName()
00365                 );
00366         }
00367     }
00368 
00369     //  Now we can update the element stack to set the current element
00370     //  decl. We expanded the stack above, but couldn't store the element
00371     //  decl because we didn't know it yet.
00372     fElemStack.setElement(elemDecl, fReaderMgr.getCurrentReaderNum());
00373     fElemStack.setCurrentURI(uriId);
00374 
00375     if (isRoot) {
00376         fRootElemName = XMLString::replicate(qnameRawBuf, fMemoryManager);
00377     }
00378 
00379     //  Validate the element
00380     if (fValidate) {
00381         fValidator->validateElement(elemDecl);
00382     }
00383 
00384     // squirrel away the element's QName, so that we can do an efficient
00385     // end-tag match
00386     fElemStack.setCurrentSchemaElemName(fQNameBuf.getRawBuffer());
00387 
00388     ComplexTypeInfo* typeinfo = (fValidate)
00389         ? ((SchemaValidator*)fValidator)->getCurrentTypeInfo()
00390         : ((SchemaElementDecl*) elemDecl)->getComplexTypeInfo();
00391 
00392     if (typeinfo)
00393     {
00394         currentScope = typeinfo->getScopeDefined();
00395 
00396         // switch grammar if the typeinfo has a different grammar
00397         XMLCh* typeName = typeinfo->getTypeName();
00398         int comma = XMLString::indexOf(typeName, chComma);
00399         if (comma > 0)
00400         {
00401             XMLBufBid bbPrefix(&fBufMgr);
00402             XMLBuffer& prefixBuf = bbPrefix.getBuffer();
00403 
00404             prefixBuf.append(typeName, comma);
00405             switchGrammar(prefixBuf.getRawBuffer(), laxThisOne);
00406         }
00407     }
00408     fElemStack.setCurrentScope(currentScope);
00409 
00410     // Set element next state
00411     if (elemDepth >= fElemStateSize) {
00412         resizeElemState();
00413     }
00414 
00415     fElemState[elemDepth] = 0;
00416     fElemLoopState[elemDepth] = 0;
00417     fElemStack.setCurrentGrammar(fGrammar);
00418 
00419     //  If this is the first element and we are validating, check the root
00420     //  element.
00421     if (!isRoot && parentValidation) {
00422         fElemStack.addChild(elemDecl->getElementName(), true);
00423     }
00424 
00425     //  Now lets get the fAttrList filled in. This involves faulting in any
00426     //  defaulted and fixed attributes and normalizing the values of any that
00427     //  we got explicitly.
00428     //
00429     //  We update the attCount value with the total number of attributes, but
00430     //  it goes in with the number of values we got during the raw scan of
00431     //  explictly provided attrs above.
00432     attCount = buildAttList(*fRawAttrList, attCount, elemDecl, *fAttrList);
00433 
00434     if(attCount)
00435     {
00436         // clean up after ourselves:
00437         // clear the map used to detect duplicate attributes
00438         fUndeclaredAttrRegistry->removeAll();
00439     }
00440 
00441     // Since the element may have default values, call start tag now regardless if it is empty or not
00442     // If we have a document handler, then tell it about this start tag
00443     if (fDocHandler)
00444     {
00445         fDocHandler->startElement
00446         (
00447             *elemDecl, uriId, fPrefixBuf.getRawBuffer(), *fAttrList
00448             , attCount, false, isRoot
00449         );
00450     } // may be where we output something...
00451 
00452     //  If empty, validate content right now if we are validating and then
00453     //  pop the element stack top. Else, we have to update the current stack
00454     //  top's namespace mapping elements.
00455     if (isEmpty)
00456     {
00457         // Pop the element stack back off since it'll never be used now
00458         fElemStack.popTop();
00459 
00460         // If validating, then insure that its legal to have no content
00461         if (fValidate)
00462         {
00463             XMLSize_t failure;
00464             bool res = fValidator->checkContent(elemDecl, 0, 0, &failure);
00465             if (!res)
00466             {
00467                 // REVISIT:  in the case of xsi:type, this may
00468                 // return the wrong string...
00469                 fValidator->emitError
00470                 (
00471                     XMLValid::ElementNotValidForContent
00472                     , elemDecl->getFullName()
00473                     , elemDecl->getFormattedContentModel()
00474                 );
00475             }
00476         }
00477 
00478         // If we have a doc handler, tell it about the end tag
00479         if (fDocHandler)
00480         {
00481             fDocHandler->endElement
00482             (
00483                 *elemDecl, uriId, isRoot, fPrefixBuf.getRawBuffer()
00484             );
00485         }
00486 
00487         // If the elem stack is empty, then it was an empty root
00488         if (isRoot) {
00489             gotData = false;
00490         }
00491         else
00492         {
00493             // Restore the grammar
00494             fGrammar = fElemStack.getCurrentGrammar();
00495             fGrammarType = fGrammar->getGrammarType();
00496             fValidator->setGrammar(fGrammar);
00497 
00498             // Restore the validation flag
00499             fValidate = fElemStack.getValidationFlag();
00500         }
00501     }
00502 
00503     return true;
00504 }
00505 
00506 // ---------------------------------------------------------------------------
00507 //  XSAXMLScanner: XMLScanner virtual methods
00508 // ---------------------------------------------------------------------------
00509 //  This method will reset the scanner data structures, and related plugged
00510 //  in stuff, for a new scan session. We get the input source for the primary
00511 //  XML entity, create the reader for it, and push it on the stack so that
00512 //  upon successful return from here we are ready to go.
00513 void XSAXMLScanner::scanReset(const InputSource& src)
00514 {
00515     fGrammar = fSchemaGrammar;
00516     fGrammarType = Grammar::SchemaGrammarType;
00517     fRootGrammar = fSchemaGrammar;
00518 
00519     fValidator->setGrammar(fGrammar);
00520 
00521     // Reset validation
00522     fValidate = true;
00523 
00524     //  And for all installed handlers, send reset events. This gives them
00525     //  a chance to flush any cached data.
00526     if (fDocHandler)
00527         fDocHandler->resetDocument();
00528     if (fEntityHandler)
00529         fEntityHandler->resetEntities();
00530     if (fErrorReporter)
00531         fErrorReporter->resetErrors();
00532 
00533     // Clear out the id reference list
00534     resetValidationContext();
00535 
00536     // Reset the Root Element Name
00537     if (fRootElemName) {
00538         fMemoryManager->deallocate(fRootElemName);//delete [] fRootElemName;
00539     }
00540 
00541     fRootElemName = 0;
00542 
00543     //  Reset the element stack, and give it the latest ids for the special
00544     //  URIs it has to know about.
00545     fElemStack.reset
00546     (
00547         fEmptyNamespaceId, fUnknownNamespaceId, fXMLNamespaceId, fXMLNSNamespaceId
00548     );
00549 
00550     if (!fSchemaNamespaceId)
00551         fSchemaNamespaceId  = fURIStringPool->addOrFind(SchemaSymbols::fgURI_XSI);
00552 
00553     // Reset some status flags
00554     fInException = false;
00555     fStandalone = false;
00556     fErrorCount = 0;
00557     fHasNoDTD = true;
00558     fSeeXsi = false;
00559     fDoNamespaces = true;
00560     fDoSchema = true;
00561 
00562     // Reset the validators
00563     fSchemaValidator->reset();
00564     fSchemaValidator->setErrorReporter(fErrorReporter);
00565     fSchemaValidator->setExitOnFirstFatal(fExitOnFirstFatal);
00566     fSchemaValidator->setGrammarResolver(fGrammarResolver);
00567 
00568     //  Handle the creation of the XML reader object for this input source.
00569     //  This will provide us with transcoding and basic lexing services.
00570     XMLReader* newReader = fReaderMgr.createReader
00571     (
00572         src
00573         , true
00574         , XMLReader::RefFrom_NonLiteral
00575         , XMLReader::Type_General
00576         , XMLReader::Source_External
00577         , fCalculateSrcOfs
00578         , fLowWaterMark
00579     );
00580 
00581     if (!newReader) {
00582         if (src.getIssueFatalErrorIfNotFound())
00583             ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource, src.getSystemId(), fMemoryManager);
00584         else
00585             ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource_Warning, src.getSystemId(), fMemoryManager);
00586     }
00587 
00588     // Push this read onto the reader manager
00589     fReaderMgr.pushReader(newReader, 0);
00590 
00591     // and reset security-related things if necessary:
00592     if(fSecurityManager != 0)
00593     {
00594         fEntityExpansionLimit = fSecurityManager->getEntityExpansionLimit();
00595         fEntityExpansionCount = 0;
00596     }
00597     fElemCount = 0;
00598     if (fUIntPoolRowTotal >= 32)
00599     { // 8 KB tied up with validating attributes...
00600         fAttDefRegistry->removeAll();
00601         recreateUIntPool();
00602     }
00603     else
00604     {
00605         // note that this will implicitly reset the values of the hashtables,
00606         // though their buckets will still be tied up
00607         resetUIntPool();
00608     }
00609     fUndeclaredAttrRegistry->removeAll();
00610 }
00611 
00612 
00613 void XSAXMLScanner::scanRawAttrListforNameSpaces(XMLSize_t attCount)
00614 {
00615     //  Make an initial pass through the list and find any xmlns attributes or
00616     //  schema attributes.
00617     //  When we find one, send it off to be used to update the element stack's
00618     //  namespace mappings.
00619     XMLSize_t index = 0;
00620     for (index = 0; index < attCount; index++)
00621     {
00622         // each attribute has the prefix:suffix="value"
00623         const KVStringPair* curPair = fRawAttrList->elementAt(index);
00624         const XMLCh* rawPtr = curPair->getKey();
00625 
00626         //  If either the key begins with "xmlns:" or its just plain
00627         //  "xmlns", then use it to update the map.
00628         if (!XMLString::compareNString(rawPtr, XMLUni::fgXMLNSColonString, 6)
00629         ||  XMLString::equals(rawPtr, XMLUni::fgXMLNSString))
00630         {
00631             const XMLCh* valuePtr = curPair->getValue();
00632 
00633             updateNSMap(rawPtr, valuePtr, fRawAttrColonList[index]);
00634 
00635             // if the schema URI is seen in the the valuePtr, set the boolean seeXsi
00636             if (XMLString::equals(valuePtr, SchemaSymbols::fgURI_XSI)) {
00637                 fSeeXsi = true;
00638             }
00639         }
00640     }
00641 
00642     // walk through the list again to deal with "xsi:...."
00643     if (fSeeXsi)
00644     {
00645         //  Schema Xsi Type yyyy (e.g. xsi:type="yyyyy")
00646         XMLBufBid bbXsi(&fBufMgr);
00647         XMLBuffer& fXsiType = bbXsi.getBuffer();
00648 
00649         QName attName(fMemoryManager);
00650 
00651         for (index = 0; index < attCount; index++)
00652         {
00653             // each attribute has the prefix:suffix="value"
00654             const KVStringPair* curPair = fRawAttrList->elementAt(index);
00655             const XMLCh* rawPtr = curPair->getKey();
00656 
00657             attName.setName(rawPtr, fEmptyNamespaceId);
00658             const XMLCh* prefPtr = attName.getPrefix();
00659 
00660             // if schema URI has been seen, scan for the schema location and uri
00661             // and resolve the schema grammar; or scan for schema type
00662             if (resolvePrefix(prefPtr, ElemStack::Mode_Attribute) == fSchemaNamespaceId) {
00663 
00664                 const XMLCh* valuePtr = curPair->getValue();
00665                 const XMLCh* suffPtr = attName.getLocalPart();
00666 
00667                 if (XMLString::equals(suffPtr, SchemaSymbols::fgXSI_TYPE)) 
00668                 {
00669                     // normalize the attribute according to schema whitespace facet
00670                     DatatypeValidator* tempDV = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_QNAME);
00671                     ((SchemaValidator*) fValidator)->normalizeWhiteSpace(tempDV, valuePtr, fXsiType, true);
00672                 }
00673                 else if (XMLString::equals(suffPtr, SchemaSymbols::fgATT_NILL))
00674                 {
00675                     // normalize the attribute according to schema whitespace facet
00676                     XMLBuffer& fXsiNil = fBufMgr.bidOnBuffer();
00677                     DatatypeValidator* tempDV = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_BOOLEAN);
00678                     ((SchemaValidator*) fValidator)->normalizeWhiteSpace(tempDV, valuePtr, fXsiNil, true);
00679                     if(XMLString::equals(fXsiNil.getRawBuffer(), SchemaSymbols::fgATTVAL_TRUE))
00680                         ((SchemaValidator*)fValidator)->setNillable(true);
00681                     else if(XMLString::equals(fXsiNil.getRawBuffer(), SchemaSymbols::fgATTVAL_FALSE))
00682                         ((SchemaValidator*)fValidator)->setNillable(false);
00683                     else
00684                         emitError(XMLErrs::InvalidAttValue, fXsiNil.getRawBuffer(), valuePtr);
00685                     fBufMgr.releaseBuffer(fXsiNil);
00686                 }
00687             }
00688         }
00689 
00690         if (!fXsiType.isEmpty())
00691         {
00692             int colonPos = -1;
00693             unsigned int uriId = resolveQName
00694             (
00695                 fXsiType.getRawBuffer(), fPrefixBuf, ElemStack::Mode_Element, colonPos
00696             );
00697             ((SchemaValidator*)fValidator)->setXsiType(fPrefixBuf.getRawBuffer(), fXsiType.getRawBuffer() + colonPos + 1, uriId);
00698         }
00699     }
00700 }
00701 
00702 void XSAXMLScanner::switchGrammar( const XMLCh* const uriStr
00703                                  , bool laxValidate)
00704 {
00705     Grammar* tempGrammar = 0;
00706 
00707     if (XMLString::equals(uriStr, SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) {
00708         tempGrammar = fSchemaGrammar;
00709     }
00710     else {
00711         tempGrammar = fGrammarResolver->getGrammar(uriStr);
00712     }
00713 
00714     if (tempGrammar && tempGrammar->getGrammarType() == Grammar::SchemaGrammarType)
00715     {
00716         fGrammar = tempGrammar;
00717         fGrammarType = Grammar::SchemaGrammarType;
00718         fValidator->setGrammar(fGrammar);
00719     }
00720     else if(!laxValidate) {
00721         fValidator->emitError(XMLValid::GrammarNotFound, uriStr);
00722     }
00723 }
00724 
00725 XERCES_CPP_NAMESPACE_END