in src/xercesc/validators/schema/TraverseSchema.cpp [6649:6866]
void TraverseSchema::processAttributes(const DOMElement* const elem,
const DOMElement* const attElem,
ComplexTypeInfo* const typeInfo,
const bool isBaseAnyType) {
// If we do not have a complexTypeInfo, then what is the point of
// processing.
if (typeInfo == 0) {
return;
}
ComplexTypeInfo* baseTypeInfo = typeInfo->getBaseComplexTypeInfo();
if (baseTypeInfo && baseTypeInfo->getPreprocessed())
throw TraverseSchema::RecursingElement;
const DOMElement* child = attElem;
SchemaAttDef* attWildCard = 0;
Janitor<SchemaAttDef> janAttWildCard(0);
XercesAttGroupInfo* attGroupInfo = 0;
ValueVectorOf<XercesAttGroupInfo*> attGroupList(4, fGrammarPoolMemoryManager);
for (; child != 0; child = XUtil::getNextSiblingElement(child)) {
const XMLCh* childName = child->getLocalName();
if (XMLString::equals(childName, SchemaSymbols::fgELT_ATTRIBUTE)) {
if(attWildCard)
reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::AnyAttributeBeforeAttribute);
traverseAttributeDecl(child, typeInfo);
}
else if (XMLString::equals(childName, SchemaSymbols::fgELT_ATTRIBUTEGROUP)) {
if(attWildCard)
reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::AnyAttributeBeforeAttribute);
attGroupInfo = traverseAttributeGroupDecl(child, typeInfo);
if (attGroupInfo && !attGroupList.containsElement(attGroupInfo)) {
attGroupList.addElement(attGroupInfo);
}
}
else if (XMLString::equals(childName, SchemaSymbols::fgELT_ANYATTRIBUTE) ) {
if(attWildCard)
reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateAnyAttribute);
attWildCard = traverseAnyAttribute(child);
janAttWildCard.reset(attWildCard);
}
else {
reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::InvalidChildInComplexType, childName);
}
}
// -------------------------------------------------------------
// Handle wild card/any attribute
// -------------------------------------------------------------
int derivedBy = typeInfo->getDerivedBy();
XMLSize_t attGroupListSize = attGroupList.size();
if (attGroupListSize) {
SchemaAttDef* completeWildCard = 0;
Janitor<SchemaAttDef> janCompleteWildCard(0);
XMLAttDef::DefAttTypes defAttType = XMLAttDef::Default;
bool defAttTypeSet = false;
for (XMLSize_t i=0; i < attGroupListSize; i++) {
attGroupInfo = attGroupList.elementAt(i);
XMLSize_t anyAttCount = attGroupInfo->anyAttributeCount();
if (anyAttCount) {
if (!defAttTypeSet) {
defAttType = (attWildCard) ? attWildCard->getDefaultType()
: attGroupInfo->anyAttributeAt(0)->getDefaultType();
defAttTypeSet = true;
}
SchemaAttDef* attGroupWildCard = attGroupInfo->getCompleteWildCard();
if (completeWildCard) {
attWildCardIntersection(completeWildCard, attGroupWildCard);
}
else {
completeWildCard = new (fGrammarPoolMemoryManager) SchemaAttDef(attGroupWildCard);
janCompleteWildCard.reset(completeWildCard);
}
}
}
if (completeWildCard) {
if (attWildCard) {
attWildCardIntersection(attWildCard, completeWildCard);
}
else {
attWildCard = completeWildCard;
janCompleteWildCard.orphan();
janAttWildCard.reset(attWildCard);
}
attWildCard->setDefaultType(defAttType);
}
}
SchemaAttDef* baseAttWildCard = (baseTypeInfo) ? baseTypeInfo->getAttWildCard() : 0;
Janitor<SchemaAttDef> janBaseAttWildCard(0);
if (derivedBy == SchemaSymbols::XSD_EXTENSION) {
if (isBaseAnyType) {
baseAttWildCard = new (fGrammarPoolMemoryManager) SchemaAttDef(XMLUni::fgZeroLenString,
XMLUni::fgZeroLenString,
fEmptyNamespaceURI, XMLAttDef::Any_Any,
XMLAttDef::ProcessContents_Lax,
fGrammarPoolMemoryManager);
janBaseAttWildCard.reset(baseAttWildCard);
}
if (baseAttWildCard && attWildCard) {
XMLAttDef::DefAttTypes saveDefType = attWildCard->getDefaultType();
attWildCardUnion(attWildCard, baseAttWildCard);
attWildCard->setDefaultType(saveDefType);
}
}
// -------------------------------------------------------------
// insert wildcard attribute
// -------------------------------------------------------------
if (attWildCard) {
typeInfo->setAttWildCard(attWildCard);
janAttWildCard.orphan();
if (attWildCard->getType() == XMLAttDef::AttTypes_Unknown) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::NotExpressibleWildCardIntersection);
}
}
else if (baseAttWildCard && derivedBy == SchemaSymbols::XSD_EXTENSION) {
if (isBaseAnyType) {
typeInfo->setAttWildCard(baseAttWildCard);
janBaseAttWildCard.orphan();
}
else {
SchemaAttDef* newWildCard = new (fGrammarPoolMemoryManager) SchemaAttDef(baseAttWildCard);
typeInfo->setAttWildCard(newWildCard);
}
}
// -------------------------------------------------------------
// Check attributes derivation OK
// -------------------------------------------------------------
bool baseWithAttributes = (baseTypeInfo && baseTypeInfo->hasAttDefs());
bool childWithAttributes = (typeInfo->hasAttDefs() || typeInfo->getAttWildCard());
if (derivedBy == SchemaSymbols::XSD_RESTRICTION && childWithAttributes) {
if (!baseWithAttributes && !baseAttWildCard) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BadAttDerivation_1);
}
else {
checkAttDerivationOK(elem, baseTypeInfo, typeInfo);
}
}
// -------------------------------------------------------------
// merge in base type's attribute decls
// -------------------------------------------------------------
if (baseTypeInfo && baseTypeInfo->hasAttDefs()) {
SchemaAttDefList& baseAttList = (SchemaAttDefList&)
baseTypeInfo->getAttDefList();
for (XMLSize_t i=0; i<baseAttList.getAttDefCount(); i++) {
SchemaAttDef& attDef = (SchemaAttDef&) baseAttList.getAttDef(i);
QName* attName = attDef.getAttName();
const XMLCh* localPart = attName->getLocalPart();
// if found a duplicate, then skip the one from the base type
if (typeInfo->getAttDef(localPart, attName->getURI()) != 0) {
if (derivedBy == SchemaSymbols::XSD_EXTENSION) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateAttInDerivation, localPart);
}
continue;
}
if (attDef.getDefaultType() != XMLAttDef::Prohibited) {
SchemaAttDef* newAttDef = new (fGrammarPoolMemoryManager) SchemaAttDef(attName->getPrefix(),
attName->getLocalPart(),
attName->getURI(),
attDef.getValue(),
attDef.getType(),
attDef.getDefaultType(),
attDef.getEnumeration(),
fGrammarPoolMemoryManager);
newAttDef->setDatatypeValidator(attDef.getDatatypeValidator());
typeInfo->addAttDef(newAttDef);
if (attDef.getBaseAttDecl())
newAttDef->setBaseAttDecl(attDef.getBaseAttDecl());
else
newAttDef->setBaseAttDecl(&attDef);
}
}
}
}