diff --git a/src/xercesc/internal/IGXMLScanner.cpp b/src/xercesc/internal/IGXMLScanner.cpp index 651d7f0f84482a72095bcbc531061f27ccf05180..a46afbce187eedbeb3a7d122af48cd34019df89a 100644 --- a/src/xercesc/internal/IGXMLScanner.cpp +++ b/src/xercesc/internal/IGXMLScanner.cpp @@ -2729,7 +2729,7 @@ bool IGXMLScanner::scanStartTagNS(bool& gotData) } } else if (fGrammarType == Grammar::SchemaGrammarType) { - ((SchemaValidator*)fValidator)->setNillable(false); + ((SchemaValidator*)fValidator)->resetNillable(); } if (fGrammarType == Grammar::SchemaGrammarType) diff --git a/src/xercesc/internal/IGXMLScanner2.cpp b/src/xercesc/internal/IGXMLScanner2.cpp index 7d2133156923c55fafe4606552a53aac1d08ddf6..586b5e461b78a76af31059c36b9bd86c759522d6 100644 --- a/src/xercesc/internal/IGXMLScanner2.cpp +++ b/src/xercesc/internal/IGXMLScanner2.cpp @@ -1734,6 +1734,10 @@ void IGXMLScanner::scanRawAttrListforNameSpaces(XMLSize_t attCount) ((SchemaValidator*) fValidator)->normalizeWhiteSpace(tempDV, valuePtr, fXsiNil, true); if(XMLString::equals(fXsiNil.getRawBuffer(), SchemaSymbols::fgATTVAL_TRUE)) ((SchemaValidator*)fValidator)->setNillable(true); + else if(XMLString::equals(fXsiNil.getRawBuffer(), SchemaSymbols::fgATTVAL_FALSE)) + ((SchemaValidator*)fValidator)->setNillable(false); + else + emitError(XMLErrs::InvalidAttValue, fXsiNil.getRawBuffer(), valuePtr); fBufMgr.releaseBuffer(fXsiNil); } } diff --git a/src/xercesc/internal/SGXMLScanner.cpp b/src/xercesc/internal/SGXMLScanner.cpp index e904fe6342c1ff100e744d2004ff99612dfcff9d..e56e33d57bb6a35466eed4d5d3dd597fff8bd88b 100644 --- a/src/xercesc/internal/SGXMLScanner.cpp +++ b/src/xercesc/internal/SGXMLScanner.cpp @@ -1724,7 +1724,7 @@ bool SGXMLScanner::scanStartTag(bool& gotData) } else if (fGrammarType == Grammar::SchemaGrammarType) { - ((SchemaValidator*)fValidator)->setNillable(false); + ((SchemaValidator*)fValidator)->resetNillable(); } if (fPSVIHandler) @@ -3627,6 +3627,10 @@ void SGXMLScanner::scanRawAttrListforNameSpaces(XMLSize_t attCount) ((SchemaValidator*) fValidator)->normalizeWhiteSpace(tempDV, valuePtr, fXsiNil, true); if(XMLString::equals(fXsiNil.getRawBuffer(), SchemaSymbols::fgATTVAL_TRUE)) ((SchemaValidator*)fValidator)->setNillable(true); + else if(XMLString::equals(fXsiNil.getRawBuffer(), SchemaSymbols::fgATTVAL_FALSE)) + ((SchemaValidator*)fValidator)->setNillable(false); + else + emitError(XMLErrs::InvalidAttValue, fXsiNil.getRawBuffer(), valuePtr); fBufMgr.releaseBuffer(fXsiNil); } } diff --git a/src/xercesc/internal/XSAXMLScanner.cpp b/src/xercesc/internal/XSAXMLScanner.cpp index 88287dd4db8475e2bf8cb1d983ca8e39284291cf..dac164ec8ebff89105cf4541d9f6bb44e981b77a 100644 --- a/src/xercesc/internal/XSAXMLScanner.cpp +++ b/src/xercesc/internal/XSAXMLScanner.cpp @@ -677,6 +677,10 @@ void XSAXMLScanner::scanRawAttrListforNameSpaces(XMLSize_t attCount) ((SchemaValidator*) fValidator)->normalizeWhiteSpace(tempDV, valuePtr, fXsiNil, true); if(XMLString::equals(fXsiNil.getRawBuffer(), SchemaSymbols::fgATTVAL_TRUE)) ((SchemaValidator*)fValidator)->setNillable(true); + else if(XMLString::equals(fXsiNil.getRawBuffer(), SchemaSymbols::fgATTVAL_FALSE)) + ((SchemaValidator*)fValidator)->setNillable(false); + else + emitError(XMLErrs::InvalidAttValue, fXsiNil.getRawBuffer(), valuePtr); fBufMgr.releaseBuffer(fXsiNil); } } diff --git a/src/xercesc/validators/schema/SchemaValidator.cpp b/src/xercesc/validators/schema/SchemaValidator.cpp index 755168309a69b4f22508ba783a72f082ebad6190..c06000dd45b0002a627abeba84aec48d9b634810 100644 --- a/src/xercesc/validators/schema/SchemaValidator.cpp +++ b/src/xercesc/validators/schema/SchemaValidator.cpp @@ -52,6 +52,7 @@ SchemaValidator::SchemaValidator( XMLErrorReporter* const errReporter , fGrammarResolver(0) , fXsiType(0) , fNil(false) + , fNilFound(false) , fCurrentDatatypeValidator(0) , fNotationBuf(0) , fDatatypeBuffer(1023, manager) @@ -171,114 +172,104 @@ bool SchemaValidator::checkContent (XMLElementDecl* const elemDecl XMLCh* value = fDatatypeBuffer.getRawBuffer(); XMLCh* elemDefaultValue = ((SchemaElementDecl*) elemDecl)->getDefaultValue(); - if (fCurrentDatatypeValidator) + if (fNil) { - if (fNil) + if ((!XMLString::equals(value, XMLUni::fgZeroLenString)) + || elemDefaultValue) { - if ((!XMLString::equals(value, XMLUni::fgZeroLenString)) - || elemDefaultValue) - { - emitError(XMLValid::NilAttrNotEmpty, elemDecl->getFullName()); - fErrorOccurred = true; - } + emitError(XMLValid::NilAttrNotEmpty, elemDecl->getFullName()); + fErrorOccurred = true; } - else + } + else if (fCurrentDatatypeValidator) + { + DatatypeValidator::ValidatorType eleDefDVType = fCurrentDatatypeValidator->getType(); + bool validateCanonical = false; + if (eleDefDVType == DatatypeValidator::NOTATION) { - DatatypeValidator::ValidatorType eleDefDVType = fCurrentDatatypeValidator->getType(); - bool validateCanonical = false; - if (eleDefDVType == DatatypeValidator::NOTATION) - { - // if notation, need to bind URI to notation first - if (!fNotationBuf) - fNotationBuf = new (fMemoryManager) XMLBuffer(1023, fMemoryManager); - - // Make sure that this value maps to one of the - // notation values in the enumList parameter. We don't have to - // look it up in the notation pool (if a notation) because we - // will look up the enumerated values themselves. If they are in - // the notation pool (after the Grammar is parsed), then obviously - // this value will be legal since it matches one of them. - int colonPos = -1; - unsigned int uriId = getScanner()->resolveQName(value, *fNotationBuf, ElemStack::Mode_Element, colonPos); - - const XMLCh* uriText = getScanner()->getURIText(uriId); - if (uriText && *uriText) { - fNotationBuf->set(uriText); - fNotationBuf->append(chColon); - fNotationBuf->append(&value[colonPos + 1]); - value = fNotationBuf->getRawBuffer(); - } + // if notation, need to bind URI to notation first + if (!fNotationBuf) + fNotationBuf = new (fMemoryManager) XMLBuffer(1023, fMemoryManager); + + // Make sure that this value maps to one of the + // notation values in the enumList parameter. We don't have to + // look it up in the notation pool (if a notation) because we + // will look up the enumerated values themselves. If they are in + // the notation pool (after the Grammar is parsed), then obviously + // this value will be legal since it matches one of them. + int colonPos = -1; + unsigned int uriId = getScanner()->resolveQName(value, *fNotationBuf, ElemStack::Mode_Element, colonPos); + + const XMLCh* uriText = getScanner()->getURIText(uriId); + if (uriText && *uriText) { + fNotationBuf->set(uriText); + fNotationBuf->append(chColon); + fNotationBuf->append(&value[colonPos + 1]); + value = fNotationBuf->getRawBuffer(); } + } - if (elemDefaultValue) + if (elemDefaultValue) + { + if (XMLString::equals(value, XMLUni::fgZeroLenString)) { - if (XMLString::equals(value, XMLUni::fgZeroLenString)) - { - fElemIsSpecified = true; - // if this element didn't specified any value - // use default value - if (getScanner()->getDocHandler()) - getScanner()->getDocHandler()->docCharacters(elemDefaultValue, XMLString::stringLen(elemDefaultValue), false); - - // Normally for default value, it has been validated already during TraverseSchema - // But if there was a xsi:type and this validator is fXsiTypeValidator, - // need to validate again - // we determine this if the current content dataype validator - // is neither the one in the element nor the one in the current - // complex type (if any) - if ((fCurrentDatatypeValidator != ((SchemaElementDecl*)elemDecl)->getDatatypeValidator()) - && (!fTypeStack->peek() || (fCurrentDatatypeValidator != fTypeStack->peek()->getDatatypeValidator()))) { - value = elemDefaultValue; - validateCanonical = true; - } - else - value = 0; + fElemIsSpecified = true; + // if this element didn't specified any value + // use default value + if (getScanner()->getDocHandler()) + getScanner()->getDocHandler()->docCharacters(elemDefaultValue, XMLString::stringLen(elemDefaultValue), false); + + // Normally for default value, it has been validated already during TraverseSchema + // But if there was a xsi:type and this validator is fXsiTypeValidator, + // need to validate again + // we determine this if the current content dataype validator + // is neither the one in the element nor the one in the current + // complex type (if any) + if ((fCurrentDatatypeValidator != ((SchemaElementDecl*)elemDecl)->getDatatypeValidator()) + && (!fTypeStack->peek() || (fCurrentDatatypeValidator != fTypeStack->peek()->getDatatypeValidator()))) { + value = elemDefaultValue; + validateCanonical = true; } else + value = 0; + } + else + { + // this element has specified some value + // if the flag is FIXED, then this value must be same as default value + if ((((SchemaElementDecl*)elemDecl)->getMiscFlags() & SchemaSymbols::XSD_FIXED) != 0) { - // this element has specified some value - // if the flag is FIXED, then this value must be same as default value - if ((((SchemaElementDecl*)elemDecl)->getMiscFlags() & SchemaSymbols::XSD_FIXED) != 0) + if (fCurrentDatatypeValidator->compare(value, elemDefaultValue, fMemoryManager) != 0 ) { - if (fCurrentDatatypeValidator->compare(value, elemDefaultValue, fMemoryManager) != 0 ) - { - emitError(XMLValid::FixedDifferentFromActual, elemDecl->getFullName()); - fErrorOccurred = true; - } + emitError(XMLValid::FixedDifferentFromActual, elemDecl->getFullName()); + fErrorOccurred = true; } } } - else + } + + if ((!fErrorOccurred) && value) + { + try { + fCurrentDatatypeValidator->validate(value, getScanner()->getValidationContext(), fMemoryManager); + if (validateCanonical) { + XMLCh* canonical = (XMLCh*) fCurrentDatatypeValidator->getCanonicalRepresentation(value, fMemoryManager); + ArrayJanitor<XMLCh> tempCanonical(canonical, fMemoryManager); + fCurrentDatatypeValidator->validate(canonical, getScanner()->getValidationContext(), fMemoryManager); + } + } + catch (XMLException& idve) { - // no default value, then check nillable - if (XMLString::equals(value, XMLUni::fgZeroLenString) - && (((SchemaElementDecl*)elemDecl)->getMiscFlags() & SchemaSymbols::XSD_NILLABLE) != 0) - value = 0; + emitError (XMLValid::DatatypeError, idve.getCode(), idve.getMessage()); + fErrorOccurred = true; } - - if ((!fErrorOccurred) && value) + catch(const OutOfMemoryException&) { + throw; + } + catch (...) { - try { - fCurrentDatatypeValidator->validate(value, getScanner()->getValidationContext(), fMemoryManager); - if (validateCanonical) { - XMLCh* canonical = (XMLCh*) fCurrentDatatypeValidator->getCanonicalRepresentation(value, fMemoryManager); - ArrayJanitor<XMLCh> tempCanonical(canonical, fMemoryManager); - fCurrentDatatypeValidator->validate(canonical, getScanner()->getValidationContext(), fMemoryManager); - } - } - catch (XMLException& idve) - { - emitError (XMLValid::DatatypeError, idve.getCode(), idve.getMessage()); - fErrorOccurred = true; - } - catch(const OutOfMemoryException&) { - throw; - } - catch (...) - { - emitError(XMLValid::GenericError); - throw; - } + emitError(XMLValid::GenericError); + throw; } } } @@ -310,6 +301,7 @@ bool SchemaValidator::checkContent (XMLElementDecl* const elemDecl // must rely on scanner to clear fDatatypeBuffer // since it may need to query its contents after this method completes fNil = false; + fNilFound = false; fTrailing=false; fSeenNonWhiteSpace = false; fCurrentDatatypeValidator = 0; @@ -348,6 +340,7 @@ void SchemaValidator::reset() fXsiType = 0; fCurrentDatatypeValidator = 0; fNil = false; + fNilFound = false; fDatatypeBuffer.reset(); fErrorOccurred = false; } @@ -728,8 +721,9 @@ void SchemaValidator::validateElement(const XMLElementDecl* elemDef) // // Check whether this element allows Nillable // - if (fNil && (miscFlags & SchemaSymbols::XSD_NILLABLE) == 0 ) { + if (fNilFound && (miscFlags & SchemaSymbols::XSD_NILLABLE) == 0 ) { fNil = false; + fNilFound = false; emitError(XMLValid::NillNotAllowed, elemDef->getFullName()); fErrorOccurred = true; } diff --git a/src/xercesc/validators/schema/SchemaValidator.hpp b/src/xercesc/validators/schema/SchemaValidator.hpp index d209583f2c8d74666f6ae823af655d93d7cffb98..82d04943c85e43aafb05ba6bbdbb2da543ba6515 100644 --- a/src/xercesc/validators/schema/SchemaValidator.hpp +++ b/src/xercesc/validators/schema/SchemaValidator.hpp @@ -121,6 +121,7 @@ public: , const unsigned int uriId); void setNillable(bool isNil); + void resetNillable(); void setErrorReporter(XMLErrorReporter* const errorReporter); void setExitOnFirstFatal(const bool newValue); void setDatatypeBuffer(const XMLCh* const value); @@ -256,6 +257,8 @@ private: // Store the Schema Type Attribute Value if schema type is specified // // fNil + // Indicates if a nil value is acceptable + // fNilFound // Indicates if Nillable has been set // ----------------------------------------------------------------------- // The following used internally in the validator @@ -293,6 +296,7 @@ private: GrammarResolver* fGrammarResolver; QName* fXsiType; bool fNil; + bool fNilFound; DatatypeValidator* fCurrentDatatypeValidator; XMLBuffer* fNotationBuf; XMLBuffer fDatatypeBuffer; @@ -324,6 +328,12 @@ inline void SchemaValidator::setXsiType(const XMLCh* const prefix inline void SchemaValidator::setNillable(bool isNil) { fNil = isNil; + fNilFound = true; +} + +inline void SchemaValidator::resetNillable() { + fNil = false; + fNilFound = false; } inline void SchemaValidator::setExitOnFirstFatal(const bool newValue) {