GME
13
|
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