in src/xercesc/validators/schema/TraverseSchema.cpp [2259:2631]
void TraverseSchema::traverseAttributeDecl(const DOMElement* const elem,
ComplexTypeInfo* const typeInfo,
const bool topLevel) {
NamespaceScopeManager nsMgr(elem, fSchemaInfo, this);
const XMLCh* name = getElementAttValue(elem, SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName);
const XMLCh* ref = getElementAttValue(elem, SchemaSymbols::fgATT_REF, DatatypeValidator::QName);
bool nameEmpty = (!name || !*name);
bool refEmpty = (!ref || !*ref);
if (nameEmpty && refEmpty) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::NoNameRefAttribute);
return;
}
if (topLevel && nameEmpty) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::TopLevelNoNameAttribute);
return;
}
// ------------------------------------------------------------------
// Check attributes
// ------------------------------------------------------------------
unsigned short scope = (topLevel)
? GeneralAttributeCheck::E_AttributeGlobal
: (refEmpty) ? GeneralAttributeCheck::E_AttributeLocal
: GeneralAttributeCheck::E_AttributeRef;
fAttributeCheck.checkAttributes(elem, scope, this, topLevel, fNonXSAttList);
const XMLCh* defaultVal = getElementAttValue(elem, SchemaSymbols::fgATT_DEFAULT);
const XMLCh* fixedVal = getElementAttValue(elem, SchemaSymbols::fgATT_FIXED);
const XMLCh* useVal = getElementAttValue(elem, SchemaSymbols::fgATT_USE);
const XMLCh* attForm = getElementAttValue(elem, SchemaSymbols::fgATT_FORM);
const XMLCh* dvType = getElementAttValue(elem, SchemaSymbols::fgATT_TYPE, DatatypeValidator::QName);
DOMElement* simpleType = checkContent(elem, XUtil::getFirstChildElement(elem), true);
Janitor<XSAnnotation> janAnnot(fAnnotation);
bool badContent = false;
while (simpleType != 0) {
const XMLCh* contentName = simpleType->getLocalName();
if (XMLString::equals(SchemaSymbols::fgELT_SIMPLETYPE, contentName)) {
if (XUtil::getNextSiblingElement(simpleType) != 0) {
badContent = true;
}
break;
}
badContent = true;
simpleType = XUtil::getNextSiblingElement(simpleType);
}
if (badContent) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidAttributeContent,
(name) ? name : ref);
}
if (defaultVal) {
if (fixedVal) {
fixedVal = 0;
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AttributeDefaultFixedValue,
(name) ? name : ref);
}
if ((useVal && *useVal)
&& !XMLString::equals(useVal, SchemaSymbols::fgATTVAL_OPTIONAL)) {
useVal = 0;
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::NotOptionalDefaultAttValue,
(name) ? name : ref);
}
}
// processing ref
if (!refEmpty && !topLevel) {
// Check ref representation OK - 3.2.3::3.2
if (attForm || dvType || (simpleType != 0)) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AttributeRefContentError,
(name) ? name : ref);
}
processAttributeDeclRef(elem, typeInfo, ref, useVal, defaultVal, fixedVal);
return;
}
if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size())
{
fAnnotation = generateSyntheticAnnotation(elem, fNonXSAttList);
janAnnot.reset(fAnnotation);
}
// processing 'name'
if (!XMLChar1_0::isValidNCName(name, XMLString::stringLen(name))
|| XMLString::equals(name, XMLUni::fgXMLNSString)) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidDeclarationName, SchemaSymbols::fgELT_ATTRIBUTE, name);
return;
}
// Check for duplicate declaration
const XMLCh* qualified = SchemaSymbols::fgATTVAL_QUALIFIED;
int uriIndex = fEmptyNamespaceURI;
if ((fTargetNSURIString && *fTargetNSURIString)
&& (topLevel || XMLString::equals(attForm, qualified)
|| ((fSchemaInfo->getElemAttrDefaultQualified() & Attr_Def_Qualified)
&& (!attForm || !*attForm)))) {
uriIndex = fTargetNSURI;
}
// make sure that attribute namespace is not xsi uri
if (XMLString::equals(fTargetNSURIString, SchemaSymbols::fgURI_XSI)) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidAttTNS, name);
return;
}
if (typeInfo && typeInfo->getAttDef(name, uriIndex) != 0) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateAttribute, name);
return;
}
else if (fCurrentAttGroupInfo && fCurrentAttGroupInfo->containsAttribute(name, uriIndex)) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateAttribute, name);
return;
}
DatatypeValidator* dv = 0;
XMLAttDef::AttTypes attType = XMLAttDef::Simple;
SchemaInfo* saveInfo = fSchemaInfo;
if (simpleType != 0) {
if (dvType && *dvType) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AttributeWithTypeAndSimpleType, name);
}
dv = traverseSimpleTypeDecl(simpleType, false);
}
else if (!dvType || !*dvType) {
dv = fDatatypeRegistry->getDatatypeValidator(SchemaSymbols::fgDT_ANYSIMPLETYPE);
}
else {
checkEnumerationRequiredNotation(elem, name, dvType);
const XMLCh* localPart = getLocalPart(dvType);
const XMLCh* prefix = getPrefix(dvType);
const XMLCh* typeURI = resolvePrefixToURI(elem, prefix);
DatatypeValidator* dvBack = 0;
if (XMLString::equals(typeURI, SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) {
dv = fDatatypeRegistry->getDatatypeValidator(localPart);
dvBack = dv;
}
else { //isn't of the schema for schemas namespace...
dv = getAttrDatatypeValidatorNS(elem, localPart, typeURI);
dvBack = dv;
while(dv != 0 && !XMLString::equals(dv->getTypeUri(), SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) {
dv = dv->getBaseValidator();
}
if(dv)
localPart = dv->getTypeLocalName();
}
if(dv) {
if (XMLString::equals(localPart,XMLUni::fgIDString)) {
attType = XMLAttDef::ID;
}
else if (XMLString::equals(localPart,XMLUni::fgIDRefString)) {
attType = XMLAttDef::IDRef;
}
else if (XMLString::equals(localPart,XMLUni::fgIDRefsString)) {
attType = XMLAttDef::IDRefs;
}
else if (XMLString::equals(localPart,XMLUni::fgEntityString)) {
attType = XMLAttDef::Entity;
}
else if (XMLString::equals(localPart,XMLUni::fgEntitiesString)) {
attType = XMLAttDef::Entities;
}
else if (XMLString::equals(localPart,XMLUni::fgNmTokenString)) {
attType = XMLAttDef::NmToken;
}
else if (XMLString::equals(localPart,XMLUni::fgNmTokensString)) {
attType = XMLAttDef::NmTokens;
}
else if (XMLString::equals(localPart,XMLUni::fgNotationString)) {
attType = XMLAttDef::Notation;
}
else {
attType = XMLAttDef::Simple;
}
}
else
attType = XMLAttDef::Simple;
dv = dvBack;
if (!dv) {
reportSchemaError
(
elem
, XMLUni::fgXMLErrDomain
, XMLErrs::AttributeSimpleTypeNotFound
, typeURI
, localPart
, name
);
}
}
// restore schema information, if necessary
fSchemaInfo = saveInfo;
bool required = false;
bool prohibited = false;
if (useVal && *useVal) {
if (XMLString::equals(useVal, SchemaSymbols::fgATTVAL_REQUIRED)) {
required = true;
}
else if (XMLString::equals(useVal, SchemaSymbols::fgATTVAL_PROHIBITED)) {
prohibited = true;
}
}
// validate fixed/default values
const XMLCh* valueToCheck = defaultVal ? defaultVal : fixedVal;
bool ofTypeID = (dv && dv->getType() == DatatypeValidator::ID);
if (attType == XMLAttDef::Simple && dv && valueToCheck) {
short wsFacet = dv->getWSFacet();
if((wsFacet == DatatypeValidator::REPLACE && !XMLString::isWSReplaced(valueToCheck)) ||
(wsFacet == DatatypeValidator::COLLAPSE && !XMLString::isWSCollapsed(valueToCheck)))
{
XMLCh* normalizedValue=XMLString::replicate(valueToCheck, fMemoryManager);
ArrayJanitor<XMLCh> tempURIName(normalizedValue, fMemoryManager);
if(wsFacet == DatatypeValidator::REPLACE)
XMLString::replaceWS(normalizedValue, fMemoryManager);
else if(wsFacet == DatatypeValidator::COLLAPSE)
XMLString::collapseWS(normalizedValue, fMemoryManager);
valueToCheck=fStringPool->getValueForId(fStringPool->addOrFind(normalizedValue));
}
try {
dv->validate(valueToCheck
, fSchemaInfo->getValidationContext()
, fMemoryManager);
}
catch (const XMLException& excep) {
reportSchemaError(elem, excep);
}
catch(const OutOfMemoryException&)
{
throw;
}
catch(...) {
reportSchemaError(elem, XMLUni::fgValidityDomain, XMLValid::DatatypeValidationFailure, valueToCheck);
}
}
else if((attType == XMLAttDef::NmTokens || attType==XMLAttDef::IDRefs || attType==XMLAttDef::Entities) &&
valueToCheck && !XMLString::isWSCollapsed(valueToCheck))
{
XMLCh* normalizedValue=XMLString::replicate(valueToCheck, fMemoryManager);
ArrayJanitor<XMLCh> tempURIName(normalizedValue, fMemoryManager);
XMLString::collapseWS(normalizedValue, fMemoryManager);
valueToCheck=fStringPool->getValueForId(fStringPool->addOrFind(normalizedValue));
}
if (ofTypeID && valueToCheck) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AttDeclPropCorrect3, name);
}
// check for multiple attributes with type derived from ID
if (!topLevel && ofTypeID) {
if (fCurrentAttGroupInfo) {
if (fCurrentAttGroupInfo->containsTypeWithId()) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AttGrpPropCorrect3, name);
return;
}
fCurrentAttGroupInfo->setTypeWithId(true);
}
else {
if (typeInfo->containsAttWithTypeId()) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AttDeclPropCorrect5, name);
return;
}
typeInfo->setAttWithTypeId(true);
}
}
// create SchemaAttDef
SchemaAttDef* attDef = new (fGrammarPoolMemoryManager) SchemaAttDef
(
XMLUni::fgZeroLenString
, name
, uriIndex
, attType
, XMLAttDef::Implied
, fGrammarPoolMemoryManager
);
attDef->setDatatypeValidator(dv);
if (prohibited) {
attDef->setDefaultType(XMLAttDef::Prohibited);
}
else if (required) {
if (fixedVal) {
attDef->setDefaultType(XMLAttDef::Required_And_Fixed);
}
else {
attDef->setDefaultType(XMLAttDef::Required);
}
}
else {
if (fixedVal) {
attDef->setDefaultType(XMLAttDef::Fixed);
}
else if (defaultVal) {
attDef->setDefaultType(XMLAttDef::Default);
}
}
if (valueToCheck) {
attDef->setValue(valueToCheck);
}
if (!janAnnot.isDataNull())
fSchemaGrammar->putAnnotation(attDef, janAnnot.release());
if (topLevel)
{
fAttributeDeclRegistry->put((void*) fStringPool->getValueForId(fStringPool->addOrFind(name)), attDef);
attDef->setPSVIScope(PSVIDefs::SCP_GLOBAL);
}
else
{
if (typeInfo)
{
typeInfo->addAttDef(attDef);
if (!fCurrentAttGroupInfo)
attDef->setPSVIScope(PSVIDefs::SCP_LOCAL);
}
if (fCurrentAttGroupInfo) {
fCurrentAttGroupInfo->addAttDef(attDef, (typeInfo != 0));
}
}
}