in src/xercesc/validators/schema/SchemaValidator.cpp [86:315]
bool SchemaValidator::checkContent (XMLElementDecl* const elemDecl
, QName** const children
, XMLSize_t childCount
, XMLSize_t* indexFailingChild)
{
fErrorOccurred = false;
fElemIsSpecified = false;
//
// Look up the element id in our element decl pool. This will get us
// the element decl in our own way of looking at them.
//
if (!elemDecl)
ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Val_InvalidElemId, fMemoryManager);
//
// Get the content spec type of this element. This will tell us what
// to do to validate it.
//
// the top of the type stack always knows best...
ComplexTypeInfo* currType = fTypeStack->pop();
const SchemaElementDecl::ModelTypes modelType = (currType)
? (SchemaElementDecl::ModelTypes)(currType->getContentType())
: ((SchemaElementDecl*)elemDecl)->getModelType();
if (modelType == SchemaElementDecl::Empty ||
modelType == SchemaElementDecl::ElementOnlyEmpty)
{
//
// We can do this one here. It cannot have any children. If it does
// we return 0 as the index of the first bad child.
//
if (childCount) {
fErrorOccurred = true;
*indexFailingChild=0;
return false;
}
}
else if ((modelType == SchemaElementDecl::Mixed_Simple)
|| (modelType == SchemaElementDecl::Mixed_Complex)
|| (modelType == SchemaElementDecl::Children))
{
// if nillable, it's an error to have value
// XML Schema REC: Validation Rule: Element Locally Valid (Element)
// 3.2.1 The element information item must have no
// character or element information item [children].
//
if (fNil) {
if (childCount > 0 || !XMLString::equals(fDatatypeBuffer.getRawBuffer(), XMLUni::fgZeroLenString)) {
emitError(XMLValid::NilAttrNotEmpty, elemDecl->getFullName());
fErrorOccurred = true;
}
}
else {
// Get the element's content model or fault it in
XMLContentModel* elemCM = (currType)
? currType->getContentModel()
: ((SchemaElementDecl*)elemDecl)->getContentModel();
// Ask it to validate and return its return
unsigned int emptyNS = getScanner()->getEmptyNamespaceId();
bool result = elemCM->validateContent(children, childCount, emptyNS, indexFailingChild, getScanner()->getMemoryManager());
if (!result) {
result = elemCM->validateContentSpecial(children
, childCount
, emptyNS
, fGrammarResolver
, fGrammarResolver->getStringPool()
, indexFailingChild
, getScanner()->getMemoryManager());
}
if(!result) {
fErrorOccurred = true;
}
return result;
}
}
else if (modelType == SchemaElementDecl::Simple || modelType == SchemaElementDecl::Any)
{
// Normally for SchemaElementDecl::Any, We pass no judgement on it and anything goes
// but if there is a fXsiTypeValidator, we need to use it for validation
if (modelType == SchemaElementDecl::Simple && childCount > 0) {
emitError(XMLValid::SimpleTypeHasChild, elemDecl->getFullName());
fErrorOccurred = true;
}
else
{
XMLCh* value = fDatatypeBuffer.getRawBuffer();
XMLCh* elemDefaultValue = ((SchemaElementDecl*) elemDecl)->getDefaultValue();
if (fNil)
{
if ((!XMLString::equals(value, XMLUni::fgZeroLenString))
|| elemDefaultValue)
{
emitError(XMLValid::NilAttrNotEmpty, elemDecl->getFullName());
fErrorOccurred = true;
}
}
else if (fCurrentDatatypeValidator)
{
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 (elemDefaultValue)
{
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;
}
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)
{
if (fCurrentDatatypeValidator->compare(value, elemDefaultValue, fMemoryManager) != 0 )
{
emitError(XMLValid::FixedDifferentFromActual, elemDecl->getFullName());
fErrorOccurred = true;
}
}
}
}
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)
{
emitError (XMLValid::DatatypeError, idve.getCode(), idve.getMessage());
fErrorOccurred = true;
}
catch(const OutOfMemoryException&) {
throw;
}
catch (...)
{
emitError(XMLValid::GenericError);
throw;
}
}
}
else if (modelType == SchemaElementDecl::Simple)
{
emitError(XMLValid::NoDatatypeValidatorForSimpleType, elemDecl->getFullName());
fErrorOccurred = true;
}
// modelType is any
else if (elemDefaultValue)
{
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);
}
}
}
}
}
else
{
ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::CM_UnknownCMType, fMemoryManager);
}
// 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;
// Went ok, so return success
return true;
}