in src/xercesc/validators/schema/TraverseSchema.cpp [5805:6038]
void TraverseSchema::processAttributeDeclRef(const DOMElement* const elem,
ComplexTypeInfo* const typeInfo,
const XMLCh* const refName,
const XMLCh* const useAttr,
const XMLCh* const defaultVal,
const XMLCh* const fixedVal) {
if (!typeInfo && !fCurrentAttGroupInfo) {
return;
}
const XMLCh* prefix = getPrefix(refName);
const XMLCh* localPart = getLocalPart(refName);
const XMLCh* uriStr = resolvePrefixToURI(elem, prefix);
unsigned int attURI = fURIStringPool->addOrFind(uriStr);
// Check for duplicate references
if (typeInfo && typeInfo->getAttDef(localPart, attURI)) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateRefAttribute, uriStr, localPart);
return;
}
else if (fCurrentAttGroupInfo && fCurrentAttGroupInfo->containsAttribute(localPart, attURI)) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateRefAttribute, uriStr, localPart);
return;
}
// check for different namespace
SchemaInfo* saveInfo = fSchemaInfo;
SchemaInfo::ListType infoType = SchemaInfo::INCLUDE;
SchemaAttDef* refAttDef = 0;
unsigned int saveScope = fCurrentScope;
if (!XMLString::equals(uriStr, fTargetNSURIString)) {
// Make sure that we have an explicit import statement.
// Clause 4 of Schema Representation Constraint:
// http://www.w3.org/TR/xmlschema-1/#src-resolve
unsigned int uriId = fURIStringPool->addOrFind(uriStr);
if (!isImportingNS(uriId)) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidNSReference, uriStr);
return;
}
Grammar* grammar = fGrammarResolver->getGrammar(uriStr);
if (grammar == 0 || grammar->getGrammarType() != Grammar::SchemaGrammarType) {
reportSchemaError(elem, XMLUni::fgValidityDomain, XMLValid::GrammarNotFound, uriStr);
return;
}
refAttDef = (SchemaAttDef*) ((SchemaGrammar*) grammar)->getAttributeDeclRegistry()->get(localPart);
if (!refAttDef) {
SchemaInfo* impInfo = fSchemaInfo->getImportInfo(attURI);
if (!impInfo || impInfo->getProcessed()) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::TopLevelAttributeNotFound, refName);
return;
}
infoType = SchemaInfo::IMPORT;
restoreSchemaInfo(impInfo, infoType);
}
}
// if Global attribute registry does not contain the ref attribute, get
// the referred attribute declaration and traverse it.
if (!refAttDef) {
if (fAttributeDeclRegistry->containsKey(localPart) == false) {
DOMElement* referredAttribute = fSchemaInfo->getTopLevelComponent(SchemaInfo::C_Attribute,
SchemaSymbols::fgELT_ATTRIBUTE, localPart, &fSchemaInfo);
if (referredAttribute != 0) {
traverseAttributeDecl(referredAttribute, 0, true);
}
}
refAttDef = (SchemaAttDef*) fAttributeDeclRegistry->get(localPart);
}
// restore schema information, if necessary
if (fSchemaInfo != saveInfo) {
restoreSchemaInfo(saveInfo, infoType, saveScope);
}
if (!refAttDef) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::TopLevelAttributeNotFound, refName);
return;
}
XMLAttDef::DefAttTypes refAttDefType = refAttDef->getDefaultType();
const XMLCh* refAttValue = refAttDef->getValue();
bool invalidAttUse = false;
if (refAttDefType == XMLAttDef::Fixed &&
(defaultVal || (fixedVal && !XMLString::equals(fixedVal, refAttValue)))) {
invalidAttUse = true;
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AttUseCorrect, refName);
}
DatatypeValidator* attDV = refAttDef->getDatatypeValidator();
//check for multiple attributes with type derived from ID
if (attDV && attDV->getType() == DatatypeValidator::ID) {
if (fCurrentAttGroupInfo) {
if (fCurrentAttGroupInfo->containsTypeWithId()) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AttGrpPropCorrect3, refName);
return;
}
fCurrentAttGroupInfo->setTypeWithId(true);
}
else {
if (typeInfo->containsAttWithTypeId()) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AttDeclPropCorrect5, refName);
return;
}
typeInfo->setAttWithTypeId(true);
}
}
bool required = XMLString::equals(useAttr,SchemaSymbols::fgATTVAL_REQUIRED);
bool prohibited = XMLString::equals(useAttr,SchemaSymbols::fgATTVAL_PROHIBITED);
QName* attQName = refAttDef->getAttName();
SchemaAttDef* attDef = new (fGrammarPoolMemoryManager) SchemaAttDef(attQName->getPrefix(),
attQName->getLocalPart(),
attQName->getURI(),
refAttValue,
refAttDef->getType(),
refAttDefType,
0, fGrammarPoolMemoryManager);
attDef->setBaseAttDecl(refAttDef);
attDef->setPSVIScope(PSVIDefs::SCP_GLOBAL);
if (refAttDefType == XMLAttDef::Fixed) {
if (required && !invalidAttUse) {
attDef->setDefaultType(XMLAttDef::Required_And_Fixed);
}
}
else {
if (prohibited) {
attDef->setDefaultType(XMLAttDef::Prohibited);
}
else {
const XMLCh* valueConstraint = defaultVal;
if (required){
if (fixedVal) {
attDef->setDefaultType(XMLAttDef::Required_And_Fixed);
valueConstraint = fixedVal;
}
else {
attDef->setDefaultType(XMLAttDef::Required);
}
}
else
{
if (fixedVal) {
attDef->setDefaultType(XMLAttDef::Fixed);
valueConstraint = fixedVal;
}
else if (defaultVal) {
attDef->setDefaultType(XMLAttDef::Default);
}
}
if (valueConstraint) {
// validate content of value constraint
if (attDV) {
if (attDV->getType() == DatatypeValidator::ID) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AttDeclPropCorrect3, refName);
}
else {
try {
attDV->validate(valueConstraint
, fSchemaInfo->getValidationContext()
, fMemoryManager);
}
catch(const XMLException& excep) {
reportSchemaError(elem, excep);
}
catch(const OutOfMemoryException&)
{
throw;
}
catch (...) {
reportSchemaError(elem, XMLUni::fgValidityDomain, XMLValid::DatatypeValidationFailure, valueConstraint);
}
}
}
attDef->setValue(valueConstraint);
}
}
}
attDef->setDatatypeValidator(attDV);
bool toClone = false;
if (typeInfo) {
toClone = true;
typeInfo->addAttDef(attDef);
}
if (fCurrentAttGroupInfo) {
fCurrentAttGroupInfo->addAttDef(attDef, toClone);
}
}