1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 /*
19 * $Id: XSAXMLScanner.cpp 833045 2009-11-05 13:21:27Z borisk $
20 */
21
22
23 // ---------------------------------------------------------------------------
24 // Includes
25 // ---------------------------------------------------------------------------
26 #include <xercesc/internal/XSAXMLScanner.hpp>
27
28 #include <xercesc/sax/InputSource.hpp>
29 #include <xercesc/framework/XMLEntityHandler.hpp>
30 #include <xercesc/framework/XMLDocumentHandler.hpp>
31 #include <xercesc/framework/psvi/XSAnnotation.hpp>
32 #include <xercesc/validators/schema/SchemaValidator.hpp>
33
34
35 XERCES_CPP_NAMESPACE_BEGIN
36
37 // ---------------------------------------------------------------------------
38 // XSAXMLScanner: Constructors and Destructor
39 // ---------------------------------------------------------------------------
XSAXMLScanner(GrammarResolver * const grammarResolver,XMLStringPool * const uriStringPool,SchemaGrammar * const xsaGrammar,MemoryManager * const manager)40 XSAXMLScanner::XSAXMLScanner( GrammarResolver* const grammarResolver
41 , XMLStringPool* const uriStringPool
42 , SchemaGrammar* const xsaGrammar
43 , MemoryManager* const manager) :
44
45 SGXMLScanner(0, grammarResolver, manager)
46 {
47 fSchemaGrammar = xsaGrammar;
48 setURIStringPool(uriStringPool);
49 }
50
~XSAXMLScanner()51 XSAXMLScanner::~XSAXMLScanner()
52 {
53 }
54
55 // ---------------------------------------------------------------------------
56 // XSAXMLScanner: SGXMLScanner virtual methods
57 // ---------------------------------------------------------------------------
58 // This method will kick off the scanning of the primary content of the
scanEndTag(bool & gotData)59 void XSAXMLScanner::scanEndTag(bool& gotData)
60 {
61 // Assume we will still have data until proven otherwise. It will only
62 // ever be false if this is the end of the root element.
63 gotData = true;
64
65 // Check if the element stack is empty. If so, then this is an unbalanced
66 // element (i.e. more ends than starts, perhaps because of bad text
67 // causing one to be skipped.)
68 if (fElemStack.isEmpty())
69 {
70 emitError(XMLErrs::MoreEndThanStartTags);
71 fReaderMgr.skipPastChar(chCloseAngle);
72 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Scan_UnbalancedStartEnd, fMemoryManager);
73 }
74
75 // Pop the stack of the element we are supposed to be ending. Remember
76 // that we don't own this. The stack just keeps them and reuses them.
77 unsigned int uriId = fElemStack.getCurrentURI();
78
79 // Make sure that its the end of the element that we expect
80 const XMLCh *elemName = fElemStack.getCurrentSchemaElemName();
81 const ElemStack::StackElem* topElem = fElemStack.popTop();
82 if (!fReaderMgr.skippedStringLong(elemName))
83 {
84 emitError
85 (
86 XMLErrs::ExpectedEndOfTagX, elemName
87 );
88 fReaderMgr.skipPastChar(chCloseAngle);
89 return;
90 }
91
92 // See if it was the root element, to avoid multiple calls below
93 const bool isRoot = fElemStack.isEmpty();
94
95 // Make sure we are back on the same reader as where we started
96 if (topElem->fReaderNum != fReaderMgr.getCurrentReaderNum())
97 emitError(XMLErrs::PartialTagMarkupError);
98
99 // Skip optional whitespace
100 fReaderMgr.skipPastSpaces();
101
102 // Make sure we find the closing bracket
103 if (!fReaderMgr.skippedChar(chCloseAngle))
104 {
105 emitError
106 (
107 XMLErrs::UnterminatedEndTag, topElem->fThisElement->getFullName()
108 );
109 }
110
111 // If validation is enabled, then lets pass him the list of children and
112 // this element and let him validate it.
113 if (fValidate)
114 {
115 XMLSize_t failure;
116 bool res = fValidator->checkContent
117 (
118 topElem->fThisElement
119 , topElem->fChildren
120 , topElem->fChildCount
121 , &failure
122 );
123
124 if (!res)
125 {
126 // One of the elements is not valid for the content. NOTE that
127 // if no children were provided but the content model requires
128 // them, it comes back with a zero value. But we cannot use that
129 // to index the child array in this case, and have to put out a
130 // special message.
131 if (!topElem->fChildCount)
132 {
133 fValidator->emitError
134 (
135 XMLValid::EmptyNotValidForContent
136 , topElem->fThisElement->getFormattedContentModel()
137 );
138 }
139 else if (failure >= topElem->fChildCount)
140 {
141 fValidator->emitError
142 (
143 XMLValid::NotEnoughElemsForCM
144 , topElem->fThisElement->getFormattedContentModel()
145 );
146 }
147 else
148 {
149 fValidator->emitError
150 (
151 XMLValid::ElementNotValidForContent
152 , topElem->fChildren[failure]->getRawName()
153 , topElem->fThisElement->getFormattedContentModel()
154 );
155 }
156 }
157 }
158
159 // now we can reset the datatype buffer, since the
160 // application has had a chance to copy the characters somewhere else
161 ((SchemaValidator *)fValidator)->clearDatatypeBuffer();
162
163 // If we have a doc handler, tell it about the end tag
164 if (fDocHandler)
165 {
166 if (topElem->fPrefixColonPos != -1)
167 fPrefixBuf.set(elemName, topElem->fPrefixColonPos);
168 else
169 fPrefixBuf.reset();
170 fDocHandler->endElement
171 (
172 *topElem->fThisElement
173 , uriId
174 , isRoot
175 , fPrefixBuf.getRawBuffer()
176 );
177 }
178
179 // If this was the root, then done with content
180 gotData = !isRoot;
181
182 if (gotData) {
183
184 // Restore the grammar
185 fGrammar = fElemStack.getCurrentGrammar();
186 fGrammarType = fGrammar->getGrammarType();
187 fValidator->setGrammar(fGrammar);
188
189 // Restore the validation flag
190 fValidate = fElemStack.getValidationFlag();
191 }
192 }
193
scanStartTag(bool & gotData)194 bool XSAXMLScanner::scanStartTag(bool& gotData)
195 {
196 // Assume we will still have data until proven otherwise. It will only
197 // ever be false if this is the root and its empty.
198 gotData = true;
199
200 // Reset element content
201 fContent.reset();
202
203 // The current position is after the open bracket, so we need to read in
204 // in the element name.
205 int prefixColonPos;
206 if (!fReaderMgr.getQName(fQNameBuf, &prefixColonPos))
207 {
208 if (fQNameBuf.isEmpty())
209 emitError(XMLErrs::ExpectedElementName);
210 else
211 emitError(XMLErrs::InvalidElementName, fQNameBuf.getRawBuffer());
212 fReaderMgr.skipToChar(chOpenAngle);
213 return false;
214 }
215
216 // See if its the root element
217 const bool isRoot = fElemStack.isEmpty();
218
219 // Skip any whitespace after the name
220 fReaderMgr.skipPastSpaces();
221
222 // First we have to do the rawest attribute scan. We don't do any
223 // normalization of them at all, since we don't know yet what type they
224 // might be (since we need the element decl in order to do that.)
225 const XMLCh* qnameRawBuf = fQNameBuf.getRawBuffer();
226 bool isEmpty;
227 XMLSize_t attCount = rawAttrScan(qnameRawBuf, *fRawAttrList, isEmpty);
228
229 // save the contentleafname and currentscope before addlevel, for later use
230 ContentLeafNameTypeVector* cv = 0;
231 XMLContentModel* cm = 0;
232 unsigned int currentScope = Grammar::TOP_LEVEL_SCOPE;
233 bool laxThisOne = false;
234 if (!isRoot)
235 {
236 // schema validator will have correct type if validating
237 SchemaElementDecl* tempElement = (SchemaElementDecl*)
238 fElemStack.topElement()->fThisElement;
239 SchemaElementDecl::ModelTypes modelType = tempElement->getModelType();
240 ComplexTypeInfo *currType = 0;
241
242 if (fValidate)
243 {
244 currType = ((SchemaValidator*)fValidator)->getCurrentTypeInfo();
245 if (currType)
246 modelType = (SchemaElementDecl::ModelTypes)currType->getContentType();
247 else // something must have gone wrong
248 modelType = SchemaElementDecl::Any;
249 }
250 else {
251 currType = tempElement->getComplexTypeInfo();
252 }
253
254 if ((modelType == SchemaElementDecl::Mixed_Simple)
255 || (modelType == SchemaElementDecl::Mixed_Complex)
256 || (modelType == SchemaElementDecl::Children))
257 {
258 cm = currType->getContentModel();
259 cv = cm->getContentLeafNameTypeVector();
260 currentScope = fElemStack.getCurrentScope();
261 }
262 else if (modelType == SchemaElementDecl::Any) {
263 laxThisOne = true;
264 }
265 }
266
267 // Now, since we might have to update the namespace map for this element,
268 // but we don't have the element decl yet, we just tell the element stack
269 // to expand up to get ready.
270 XMLSize_t elemDepth = fElemStack.addLevel();
271 fElemStack.setValidationFlag(fValidate);
272 fElemStack.setPrefixColonPos(prefixColonPos);
273
274 // Make an initial pass through the list and find any xmlns attributes or
275 // schema attributes.
276 if (attCount)
277 scanRawAttrListforNameSpaces(attCount);
278
279 // Resolve the qualified name to a URI and name so that we can look up
280 // the element decl for this element. We have now update the prefix to
281 // namespace map so we should get the correct element now.
282 unsigned int uriId = resolveQNameWithColon
283 (
284 qnameRawBuf, fPrefixBuf, ElemStack::Mode_Element, prefixColonPos
285 );
286
287 //if schema, check if we should lax or skip the validation of this element
288 bool parentValidation = fValidate;
289 if (cv) {
290 QName element(fPrefixBuf.getRawBuffer(), &qnameRawBuf[prefixColonPos + 1], uriId, fMemoryManager);
291 // elementDepth will be > 0, as cv is only constructed if element is not
292 // root.
293 laxThisOne = laxElementValidation(&element, cv, cm, elemDepth - 1);
294 }
295
296 // Look up the element now in the grammar. This will get us back a
297 // generic element decl object. We tell him to fault one in if he does
298 // not find it.
299 bool wasAdded = false;
300 const XMLCh* nameRawBuf = &qnameRawBuf[prefixColonPos + 1];
301 XMLElementDecl* elemDecl = fGrammar->getElemDecl
302 (
303 uriId, nameRawBuf, qnameRawBuf, currentScope
304 );
305
306 if (!elemDecl)
307 {
308 // URI is different, so we try to switch grammar
309 if (uriId != fURIStringPool->getId(fGrammar->getTargetNamespace())) {
310 switchGrammar(getURIText(uriId), laxThisOne);
311 }
312
313 // look for a global element declaration
314 elemDecl = fGrammar->getElemDecl(
315 uriId, nameRawBuf, qnameRawBuf, Grammar::TOP_LEVEL_SCOPE
316 );
317
318 if (!elemDecl)
319 {
320 // if still not found, look in list of undeclared elements
321 elemDecl = fElemNonDeclPool->getByKey(
322 nameRawBuf, uriId, (int)Grammar::TOP_LEVEL_SCOPE);
323
324 if (!elemDecl)
325 {
326 elemDecl = new (fMemoryManager) SchemaElementDecl
327 (
328 fPrefixBuf.getRawBuffer(), nameRawBuf, uriId
329 , SchemaElementDecl::Any, Grammar::TOP_LEVEL_SCOPE
330 , fMemoryManager
331 );
332
333 elemDecl->setId (fElemNonDeclPool->put(
334 (void*)elemDecl->getBaseName(),
335 uriId,
336 (int)Grammar::TOP_LEVEL_SCOPE,
337 (SchemaElementDecl*)elemDecl));
338
339 wasAdded = true;
340 }
341 }
342 }
343
344 // We do something different here according to whether we found the
345 // element or not.
346 bool bXsiTypeSet= (fValidator)?((SchemaValidator*)fValidator)->getIsXsiTypeSet():false;
347 if (wasAdded || !elemDecl->isDeclared())
348 {
349 if (laxThisOne && !bXsiTypeSet) {
350 fValidate = false;
351 fElemStack.setValidationFlag(fValidate);
352 }
353
354 // If validating then emit an error
355 if (fValidate)
356 {
357 // This is to tell the reuse Validator that this element was
358 // faulted-in, was not an element in the grammar pool originally
359 elemDecl->setCreateReason(XMLElementDecl::JustFaultIn);
360
361 if(!bXsiTypeSet)
362 fValidator->emitError
363 (
364 XMLValid::ElementNotDefined, elemDecl->getFullName()
365 );
366 }
367 }
368
369 // Now we can update the element stack to set the current element
370 // decl. We expanded the stack above, but couldn't store the element
371 // decl because we didn't know it yet.
372 fElemStack.setElement(elemDecl, fReaderMgr.getCurrentReaderNum());
373 fElemStack.setCurrentURI(uriId);
374
375 if (isRoot) {
376 fRootElemName = XMLString::replicate(qnameRawBuf, fMemoryManager);
377 }
378
379 // Validate the element
380 if (fValidate) {
381 fValidator->validateElement(elemDecl);
382 }
383
384 // squirrel away the element's QName, so that we can do an efficient
385 // end-tag match
386 fElemStack.setCurrentSchemaElemName(fQNameBuf.getRawBuffer());
387
388 ComplexTypeInfo* typeinfo = (fValidate)
389 ? ((SchemaValidator*)fValidator)->getCurrentTypeInfo()
390 : ((SchemaElementDecl*) elemDecl)->getComplexTypeInfo();
391
392 if (typeinfo)
393 {
394 currentScope = typeinfo->getScopeDefined();
395
396 // switch grammar if the typeinfo has a different grammar
397 XMLCh* typeName = typeinfo->getTypeName();
398 int comma = XMLString::indexOf(typeName, chComma);
399 if (comma > 0)
400 {
401 XMLBufBid bbPrefix(&fBufMgr);
402 XMLBuffer& prefixBuf = bbPrefix.getBuffer();
403
404 prefixBuf.append(typeName, comma);
405 switchGrammar(prefixBuf.getRawBuffer(), laxThisOne);
406 }
407 }
408 fElemStack.setCurrentScope(currentScope);
409
410 // Set element next state
411 if (elemDepth >= fElemStateSize) {
412 resizeElemState();
413 }
414
415 fElemState[elemDepth] = 0;
416 fElemLoopState[elemDepth] = 0;
417 fElemStack.setCurrentGrammar(fGrammar);
418
419 // If this is the first element and we are validating, check the root
420 // element.
421 if (!isRoot && parentValidation) {
422 fElemStack.addChild(elemDecl->getElementName(), true);
423 }
424
425 // Now lets get the fAttrList filled in. This involves faulting in any
426 // defaulted and fixed attributes and normalizing the values of any that
427 // we got explicitly.
428 //
429 // We update the attCount value with the total number of attributes, but
430 // it goes in with the number of values we got during the raw scan of
431 // explictly provided attrs above.
432 attCount = buildAttList(*fRawAttrList, attCount, elemDecl, *fAttrList);
433
434 if(attCount)
435 {
436 // clean up after ourselves:
437 // clear the map used to detect duplicate attributes
438 fUndeclaredAttrRegistry->removeAll();
439 }
440
441 // Since the element may have default values, call start tag now regardless if it is empty or not
442 // If we have a document handler, then tell it about this start tag
443 if (fDocHandler)
444 {
445 fDocHandler->startElement
446 (
447 *elemDecl, uriId, fPrefixBuf.getRawBuffer(), *fAttrList
448 , attCount, false, isRoot
449 );
450 } // may be where we output something...
451
452 // If empty, validate content right now if we are validating and then
453 // pop the element stack top. Else, we have to update the current stack
454 // top's namespace mapping elements.
455 if (isEmpty)
456 {
457 // Pop the element stack back off since it'll never be used now
458 fElemStack.popTop();
459
460 // If validating, then insure that its legal to have no content
461 if (fValidate)
462 {
463 XMLSize_t failure;
464 bool res = fValidator->checkContent(elemDecl, 0, 0, &failure);
465 if (!res)
466 {
467 // REVISIT: in the case of xsi:type, this may
468 // return the wrong string...
469 fValidator->emitError
470 (
471 XMLValid::ElementNotValidForContent
472 , elemDecl->getFullName()
473 , elemDecl->getFormattedContentModel()
474 );
475 }
476 }
477
478 // If we have a doc handler, tell it about the end tag
479 if (fDocHandler)
480 {
481 fDocHandler->endElement
482 (
483 *elemDecl, uriId, isRoot, fPrefixBuf.getRawBuffer()
484 );
485 }
486
487 // If the elem stack is empty, then it was an empty root
488 if (isRoot) {
489 gotData = false;
490 }
491 else
492 {
493 // Restore the grammar
494 fGrammar = fElemStack.getCurrentGrammar();
495 fGrammarType = fGrammar->getGrammarType();
496 fValidator->setGrammar(fGrammar);
497
498 // Restore the validation flag
499 fValidate = fElemStack.getValidationFlag();
500 }
501 }
502
503 return true;
504 }
505
506 // ---------------------------------------------------------------------------
507 // XSAXMLScanner: XMLScanner virtual methods
508 // ---------------------------------------------------------------------------
509 // This method will reset the scanner data structures, and related plugged
510 // in stuff, for a new scan session. We get the input source for the primary
511 // XML entity, create the reader for it, and push it on the stack so that
512 // upon successful return from here we are ready to go.
scanReset(const InputSource & src)513 void XSAXMLScanner::scanReset(const InputSource& src)
514 {
515 fGrammar = fSchemaGrammar;
516 fGrammarType = Grammar::SchemaGrammarType;
517 fRootGrammar = fSchemaGrammar;
518
519 fValidator->setGrammar(fGrammar);
520
521 // Reset validation
522 fValidate = true;
523
524 // And for all installed handlers, send reset events. This gives them
525 // a chance to flush any cached data.
526 if (fDocHandler)
527 fDocHandler->resetDocument();
528 if (fEntityHandler)
529 fEntityHandler->resetEntities();
530 if (fErrorReporter)
531 fErrorReporter->resetErrors();
532
533 // Clear out the id reference list
534 resetValidationContext();
535
536 // Reset the Root Element Name
537 if (fRootElemName) {
538 fMemoryManager->deallocate(fRootElemName);//delete [] fRootElemName;
539 }
540
541 fRootElemName = 0;
542
543 // Reset the element stack, and give it the latest ids for the special
544 // URIs it has to know about.
545 fElemStack.reset
546 (
547 fEmptyNamespaceId, fUnknownNamespaceId, fXMLNamespaceId, fXMLNSNamespaceId
548 );
549
550 if (!fSchemaNamespaceId)
551 fSchemaNamespaceId = fURIStringPool->addOrFind(SchemaSymbols::fgURI_XSI);
552
553 // Reset some status flags
554 fInException = false;
555 fStandalone = false;
556 fErrorCount = 0;
557 fHasNoDTD = true;
558 fSeeXsi = false;
559 fDoNamespaces = true;
560 fDoSchema = true;
561
562 // Reset the validators
563 fSchemaValidator->reset();
564 fSchemaValidator->setErrorReporter(fErrorReporter);
565 fSchemaValidator->setExitOnFirstFatal(fExitOnFirstFatal);
566 fSchemaValidator->setGrammarResolver(fGrammarResolver);
567
568 // Handle the creation of the XML reader object for this input source.
569 // This will provide us with transcoding and basic lexing services.
570 XMLReader* newReader = fReaderMgr.createReader
571 (
572 src
573 , true
574 , XMLReader::RefFrom_NonLiteral
575 , XMLReader::Type_General
576 , XMLReader::Source_External
577 , fCalculateSrcOfs
578 , fLowWaterMark
579 );
580
581 if (!newReader) {
582 if (src.getIssueFatalErrorIfNotFound())
583 ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource, src.getSystemId(), fMemoryManager);
584 else
585 ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource_Warning, src.getSystemId(), fMemoryManager);
586 }
587
588 // Push this read onto the reader manager
589 fReaderMgr.pushReader(newReader, 0);
590
591 // and reset security-related things if necessary:
592 if(fSecurityManager != 0)
593 {
594 fEntityExpansionLimit = fSecurityManager->getEntityExpansionLimit();
595 fEntityExpansionCount = 0;
596 }
597 fElemCount = 0;
598 if (fUIntPoolRowTotal >= 32)
599 { // 8 KB tied up with validating attributes...
600 fAttDefRegistry->removeAll();
601 recreateUIntPool();
602 }
603 else
604 {
605 // note that this will implicitly reset the values of the hashtables,
606 // though their buckets will still be tied up
607 resetUIntPool();
608 }
609 fUndeclaredAttrRegistry->removeAll();
610 }
611
612
scanRawAttrListforNameSpaces(XMLSize_t attCount)613 void XSAXMLScanner::scanRawAttrListforNameSpaces(XMLSize_t attCount)
614 {
615 // Make an initial pass through the list and find any xmlns attributes or
616 // schema attributes.
617 // When we find one, send it off to be used to update the element stack's
618 // namespace mappings.
619 XMLSize_t index = 0;
620 for (index = 0; index < attCount; index++)
621 {
622 // each attribute has the prefix:suffix="value"
623 const KVStringPair* curPair = fRawAttrList->elementAt(index);
624 const XMLCh* rawPtr = curPair->getKey();
625
626 // If either the key begins with "xmlns:" or its just plain
627 // "xmlns", then use it to update the map.
628 if (!XMLString::compareNString(rawPtr, XMLUni::fgXMLNSColonString, 6)
629 || XMLString::equals(rawPtr, XMLUni::fgXMLNSString))
630 {
631 const XMLCh* valuePtr = curPair->getValue();
632
633 updateNSMap(rawPtr, valuePtr, fRawAttrColonList[index]);
634
635 // if the schema URI is seen in the the valuePtr, set the boolean seeXsi
636 if (XMLString::equals(valuePtr, SchemaSymbols::fgURI_XSI)) {
637 fSeeXsi = true;
638 }
639 }
640 }
641
642 // walk through the list again to deal with "xsi:...."
643 if (fSeeXsi)
644 {
645 // Schema Xsi Type yyyy (e.g. xsi:type="yyyyy")
646 XMLBufBid bbXsi(&fBufMgr);
647 XMLBuffer& fXsiType = bbXsi.getBuffer();
648
649 QName attName(fMemoryManager);
650
651 for (index = 0; index < attCount; index++)
652 {
653 // each attribute has the prefix:suffix="value"
654 const KVStringPair* curPair = fRawAttrList->elementAt(index);
655 const XMLCh* rawPtr = curPair->getKey();
656
657 attName.setName(rawPtr, fEmptyNamespaceId);
658 const XMLCh* prefPtr = attName.getPrefix();
659
660 // if schema URI has been seen, scan for the schema location and uri
661 // and resolve the schema grammar; or scan for schema type
662 if (resolvePrefix(prefPtr, ElemStack::Mode_Attribute) == fSchemaNamespaceId) {
663
664 const XMLCh* valuePtr = curPair->getValue();
665 const XMLCh* suffPtr = attName.getLocalPart();
666
667 if (XMLString::equals(suffPtr, SchemaSymbols::fgXSI_TYPE))
668 {
669 // normalize the attribute according to schema whitespace facet
670 DatatypeValidator* tempDV = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_QNAME);
671 ((SchemaValidator*) fValidator)->normalizeWhiteSpace(tempDV, valuePtr, fXsiType, true);
672 }
673 else if (XMLString::equals(suffPtr, SchemaSymbols::fgATT_NILL))
674 {
675 // normalize the attribute according to schema whitespace facet
676 XMLBuffer& fXsiNil = fBufMgr.bidOnBuffer();
677 DatatypeValidator* tempDV = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_BOOLEAN);
678 ((SchemaValidator*) fValidator)->normalizeWhiteSpace(tempDV, valuePtr, fXsiNil, true);
679 if(XMLString::equals(fXsiNil.getRawBuffer(), SchemaSymbols::fgATTVAL_TRUE))
680 ((SchemaValidator*)fValidator)->setNillable(true);
681 else if(XMLString::equals(fXsiNil.getRawBuffer(), SchemaSymbols::fgATTVAL_FALSE))
682 ((SchemaValidator*)fValidator)->setNillable(false);
683 else
684 emitError(XMLErrs::InvalidAttValue, fXsiNil.getRawBuffer(), valuePtr);
685 fBufMgr.releaseBuffer(fXsiNil);
686 }
687 }
688 }
689
690 if (!fXsiType.isEmpty())
691 {
692 int colonPos = -1;
693 unsigned int uriId = resolveQName
694 (
695 fXsiType.getRawBuffer(), fPrefixBuf, ElemStack::Mode_Element, colonPos
696 );
697 ((SchemaValidator*)fValidator)->setXsiType(fPrefixBuf.getRawBuffer(), fXsiType.getRawBuffer() + colonPos + 1, uriId);
698 }
699 }
700 }
701
switchGrammar(const XMLCh * const uriStr,bool laxValidate)702 void XSAXMLScanner::switchGrammar( const XMLCh* const uriStr
703 , bool laxValidate)
704 {
705 Grammar* tempGrammar = 0;
706
707 if (XMLString::equals(uriStr, SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) {
708 tempGrammar = fSchemaGrammar;
709 }
710 else {
711 tempGrammar = fGrammarResolver->getGrammar(uriStr);
712 }
713
714 if (tempGrammar && tempGrammar->getGrammarType() == Grammar::SchemaGrammarType)
715 {
716 fGrammar = tempGrammar;
717 fGrammarType = Grammar::SchemaGrammarType;
718 fValidator->setGrammar(fGrammar);
719 }
720 else if(!laxValidate) {
721 fValidator->emitError(XMLValid::GrammarNotFound, uriStr);
722 }
723 }
724
725 XERCES_CPP_NAMESPACE_END
726