in src/xercesc/internal/IGXMLScanner.cpp [2115:2854]
bool IGXMLScanner::scanStartTagNS(bool& gotData)
{
// Assume we will still have data until proven otherwise. It will only
// ever be false if this is the root and its empty.
gotData = true;
// Reset element content buffer
fContent.reset();
// The current position is after the open bracket, so we need to read in
// in the element name.
int prefixColonPos;
if (!fReaderMgr.getQName(fQNameBuf, &prefixColonPos))
{
if (fQNameBuf.isEmpty())
emitError(XMLErrs::ExpectedElementName);
else
emitError(XMLErrs::InvalidElementName, fQNameBuf.getRawBuffer());
fReaderMgr.skipToChar(chOpenAngle);
return false;
}
// See if its the root element
const bool isRoot = fElemStack.isEmpty();
// Skip any whitespace after the name
fReaderMgr.skipPastSpaces();
// First we have to do the rawest attribute scan. We don't do any
// normalization of them at all, since we don't know yet what type they
// might be (since we need the element decl in order to do that.)
bool isEmpty;
XMLSize_t attCount = rawAttrScan
(
fQNameBuf.getRawBuffer()
, *fRawAttrList
, isEmpty
);
// save the contentleafname and currentscope before addlevel, for later use
ContentLeafNameTypeVector* cv = 0;
XMLContentModel* cm = 0;
unsigned int currentScope = Grammar::TOP_LEVEL_SCOPE;
bool laxThisOne = false;
if (!isRoot && fGrammarType == Grammar::SchemaGrammarType)
{
// schema validator will have correct type if validating
SchemaElementDecl* tempElement = (SchemaElementDecl*)
fElemStack.topElement()->fThisElement;
SchemaElementDecl::ModelTypes modelType = tempElement->getModelType();
ComplexTypeInfo *currType = 0;
if (fValidate)
{
currType = ((SchemaValidator*)fValidator)->getCurrentTypeInfo();
if (currType)
modelType = (SchemaElementDecl::ModelTypes)currType->getContentType();
else // something must have gone wrong
modelType = SchemaElementDecl::Any;
}
else
{
currType = tempElement->getComplexTypeInfo();
}
if ((modelType == SchemaElementDecl::Mixed_Simple)
|| (modelType == SchemaElementDecl::Mixed_Complex)
|| (modelType == SchemaElementDecl::Children))
{
cm = currType->getContentModel();
cv = cm->getContentLeafNameTypeVector();
currentScope = fElemStack.getCurrentScope();
}
else if (modelType == SchemaElementDecl::Any) {
laxThisOne = true;
}
}
// Now, since we might have to update the namespace map for this element,
// but we don't have the element decl yet, we just tell the element stack
// to expand up to get ready.
XMLSize_t elemDepth = fElemStack.addLevel();
fElemStack.setValidationFlag(fValidate);
fElemStack.setPrefixColonPos(prefixColonPos);
// Check if there is any external schema location specified, and if we are at root,
// go through them first before scanning those specified in the instance document
if (isRoot && fDoSchema
&& (fExternalSchemaLocation || fExternalNoNamespaceSchemaLocation)) {
if (fExternalSchemaLocation)
parseSchemaLocation(fExternalSchemaLocation, true);
if (fExternalNoNamespaceSchemaLocation)
resolveSchemaGrammar(fExternalNoNamespaceSchemaLocation, XMLUni::fgZeroLenString, true);
}
// Make an initial pass through the list and find any xmlns attributes or
// schema attributes.
if (attCount) {
scanRawAttrListforNameSpaces(attCount);
}
// Also find any default or fixed xmlns attributes in DTD defined for
// this element.
XMLElementDecl* elemDecl = 0;
const XMLCh* qnameRawBuf = fQNameBuf.getRawBuffer();
if (fGrammarType == Grammar::DTDGrammarType) {
if (!fSkipDTDValidation) {
elemDecl = fGrammar->getElemDecl(
fEmptyNamespaceId, 0, qnameRawBuf, Grammar::TOP_LEVEL_SCOPE
);
if (elemDecl) {
if (elemDecl->hasAttDefs()) {
XMLAttDefList& attDefList = elemDecl->getAttDefList();
for(XMLSize_t i=0; i<attDefList.getAttDefCount(); i++)
{
// Get the current att def, for convenience and its def type
const XMLAttDef& curDef = attDefList.getAttDef(i);
const XMLAttDef::DefAttTypes defType = curDef.getDefaultType();
// update the NSMap if there are any default/fixed xmlns attributes
if ((defType == XMLAttDef::Default)
|| (defType == XMLAttDef::Fixed))
{
const XMLCh* rawPtr = curDef.getFullName();
if (!XMLString::compareNString(rawPtr, XMLUni::fgXMLNSColonString, 6)
|| XMLString::equals(rawPtr, XMLUni::fgXMLNSString))
updateNSMap(rawPtr, curDef.getValue());
}
}
}
}
}
if (!elemDecl) {
elemDecl = fDTDElemNonDeclPool->getByKey(qnameRawBuf);
}
}
// Resolve the qualified name to a URI and name so that we can look up
// the element decl for this element. We have now update the prefix to
// namespace map so we should get the correct element now.
unsigned int uriId = resolveQNameWithColon(
qnameRawBuf, fPrefixBuf, ElemStack::Mode_Element, prefixColonPos
);
//if schema, check if we should lax or skip the validation of this element
bool parentValidation = fValidate;
if (cv) {
QName element(fPrefixBuf.getRawBuffer(), &qnameRawBuf[prefixColonPos + 1], uriId, fMemoryManager);
// elementDepth will be > 0, as cv is only constructed if element is not
// root.
laxThisOne = laxElementValidation(&element, cv, cm, elemDepth - 1);
}
// Look up the element now in the grammar. This will get us back a
// generic element decl object. We tell him to fault one in if he does
// not find it.
bool wasAdded = false;
const XMLCh* nameRawBuf = &qnameRawBuf[prefixColonPos + 1];
if (fDoSchema) {
if (fGrammarType == Grammar::DTDGrammarType) {
if (!switchGrammar(getURIText(uriId))) {
fValidator->emitError(
XMLValid::GrammarNotFound, getURIText(uriId)
);
}
}
if (fGrammarType == Grammar::SchemaGrammarType) {
elemDecl = fGrammar->getElemDecl(
uriId, nameRawBuf, qnameRawBuf, currentScope
);
// if not found, then it may be a reference, try TOP_LEVEL_SCOPE
if (!elemDecl) {
bool checkTopLevel = (currentScope != Grammar::TOP_LEVEL_SCOPE);
const XMLCh* original_uriStr = fGrammar->getTargetNamespace();
unsigned int orgGrammarUri = fURIStringPool->getId(original_uriStr);
if (orgGrammarUri != uriId) {
if (switchGrammar(getURIText(uriId))) {
checkTopLevel = true;
}
else {
// the laxElementValidation routine (called above) will
// set fValidate to false for a "skipped" element
if (!laxThisOne && fValidate) {
fValidator->emitError(
XMLValid::GrammarNotFound, getURIText(uriId)
);
}
checkTopLevel = false;
}
}
if (checkTopLevel) {
elemDecl = fGrammar->getElemDecl(
uriId, nameRawBuf, qnameRawBuf, Grammar::TOP_LEVEL_SCOPE
);
}
if (!elemDecl && currentScope != Grammar::TOP_LEVEL_SCOPE) {
if (orgGrammarUri == uriId) {
// still not found in specified uri
// try emptyNamespace see if element should be
// un-qualified.
// Use a temp variable until we decide this is the case
if (uriId != fEmptyNamespaceId) {
XMLElementDecl* tempElemDecl = fGrammar->getElemDecl(
fEmptyNamespaceId, nameRawBuf, qnameRawBuf, currentScope
);
if (tempElemDecl && tempElemDecl->getCreateReason() != XMLElementDecl::JustFaultIn && fValidate) {
fValidator->emitError(
XMLValid::ElementNotUnQualified, qnameRawBuf
);
elemDecl = tempElemDecl;
}
}
}
// still Not found in specified uri
// go to original Grammar again to see if element needs
// to be fully qualified.
// Use a temp variable until we decide this is the case
else if (uriId == fEmptyNamespaceId) {
if (switchGrammar(original_uriStr)) {
XMLElementDecl* tempElemDecl = fGrammar->getElemDecl(
orgGrammarUri, nameRawBuf, qnameRawBuf, currentScope
);
if (tempElemDecl && tempElemDecl->getCreateReason() != XMLElementDecl::JustFaultIn && fValidate) {
fValidator->emitError(
XMLValid::ElementNotQualified, qnameRawBuf
);
elemDecl = tempElemDecl;
}
}
else if (!laxThisOne && fValidate) {
fValidator->emitError(
XMLValid::GrammarNotFound,original_uriStr
);
}
}
}
if (!elemDecl) {
// still not found
// switch back to original grammar first if necessary
if (orgGrammarUri != uriId) {
switchGrammar(original_uriStr);
}
// look in the list of undeclared elements, as would have been
// done before we made grammars stateless:
elemDecl = fSchemaElemNonDeclPool->getByKey(
nameRawBuf, uriId, (int)Grammar::TOP_LEVEL_SCOPE
);
}
}
}
}
if (!elemDecl) {
if (fGrammarType == Grammar::DTDGrammarType) {
elemDecl = new (fMemoryManager) DTDElementDecl(
qnameRawBuf, uriId, DTDElementDecl::Any, fMemoryManager
);
elemDecl->setId(fDTDElemNonDeclPool->put((DTDElementDecl*)elemDecl));
}
else if (fGrammarType == Grammar::SchemaGrammarType) {
elemDecl = new (fMemoryManager) SchemaElementDecl(
fPrefixBuf.getRawBuffer(), nameRawBuf, uriId
, SchemaElementDecl::Any, Grammar::TOP_LEVEL_SCOPE
, fMemoryManager
);
elemDecl->setId(
fSchemaElemNonDeclPool->put((void*)elemDecl->getBaseName()
, uriId, (int)Grammar::TOP_LEVEL_SCOPE, (SchemaElementDecl*)elemDecl)
);
} else {
fValidator->emitError(
XMLValid::GrammarNotFound, getURIText(uriId)
);
}
wasAdded = true;
}
// this info needed for DOMTypeInfo
fPSVIElemContext.fErrorOccurred = false;
// We do something different here according to whether we found the
// element or not.
bool bXsiTypeSet= (fValidator && fGrammarType == Grammar::SchemaGrammarType)?((SchemaValidator*)fValidator)->getIsXsiTypeSet():false;
if (wasAdded)
{
if (laxThisOne && !bXsiTypeSet) {
fValidate = false;
fElemStack.setValidationFlag(fValidate);
}
else if (fValidate)
{
// If validating then emit an error
// This is to tell the reuse Validator that this element was
// faulted-in, was not an element in the grammar pool originally
elemDecl->setCreateReason(XMLElementDecl::JustFaultIn);
// xsi:type was specified, don't complain about missing definition
if(!bXsiTypeSet)
{
fValidator->emitError
(
XMLValid::ElementNotDefined
, elemDecl->getFullName()
);
if(fGrammarType == Grammar::SchemaGrammarType)
{
fPSVIElemContext.fErrorOccurred = true;
}
}
}
}
else
{
// If its not marked declared and validating, then emit an error
if (!elemDecl->isDeclared()) {
if(elemDecl->getCreateReason() == XMLElementDecl::NoReason) {
if(!bXsiTypeSet && fGrammarType == Grammar::SchemaGrammarType) {
fPSVIElemContext.fErrorOccurred = true;
}
}
if (laxThisOne) {
fValidate = false;
fElemStack.setValidationFlag(fValidate);
}
else if (fValidate && !bXsiTypeSet)
{
fValidator->emitError
(
XMLValid::ElementNotDefined
, elemDecl->getFullName()
);
}
}
}
// Now we can update the element stack to set the current element
// decl. We expanded the stack above, but couldn't store the element
// decl because we didn't know it yet.
fElemStack.setElement(elemDecl, fReaderMgr.getCurrentReaderNum());
fElemStack.setCurrentURI(uriId);
if (isRoot)
{
fRootGrammar = fGrammar;
if (fGrammarType == Grammar::SchemaGrammarType && !fRootElemName)
fRootElemName = XMLString::replicate(qnameRawBuf, fMemoryManager);
}
if (fGrammarType == Grammar::SchemaGrammarType && fPSVIHandler)
{
fPSVIElemContext.fElemDepth++;
if (elemDecl->isDeclared())
{
fPSVIElemContext.fNoneValidationDepth = fPSVIElemContext.fElemDepth;
}
else
{
fPSVIElemContext.fFullValidationDepth = fPSVIElemContext.fElemDepth;
/******
* While we report an error for historical reasons, this should
* actually result in lax assessment - NG.
if (isRoot && fValidate)
fPSVIElemContext.fErrorOccurred = true;
*****/
}
}
// Validate the element
if (fValidate)
{
fValidator->validateElement(elemDecl);
if (fValidator->handlesSchema())
{
if (((SchemaValidator*) fValidator)->getErrorOccurred())
fPSVIElemContext.fErrorOccurred = true;
}
}
if (fGrammarType == Grammar::SchemaGrammarType) {
// squirrel away the element's QName, so that we can do an efficient
// end-tag match
fElemStack.setCurrentSchemaElemName(fQNameBuf.getRawBuffer());
ComplexTypeInfo* typeinfo = (fValidate)
? ((SchemaValidator*)fValidator)->getCurrentTypeInfo()
: ((SchemaElementDecl*) elemDecl)->getComplexTypeInfo();
if (typeinfo) {
currentScope = typeinfo->getScopeDefined();
// switch grammar if the typeinfo has a different grammar (happens when there is xsi:type)
XMLCh* typeName = typeinfo->getTypeName();
const int comma = XMLString::indexOf(typeName, chComma);
if (comma > 0) {
XMLBuffer prefixBuf(comma+1, fMemoryManager);
prefixBuf.append(typeName, comma);
const XMLCh* uriStr = prefixBuf.getRawBuffer();
bool errorCondition = !switchGrammar(uriStr) && fValidate;
if (errorCondition && !laxThisOne)
{
fValidator->emitError
(
XMLValid::GrammarNotFound
, prefixBuf.getRawBuffer()
);
}
}
else if (comma == 0) {
bool errorCondition = !switchGrammar(XMLUni::fgZeroLenString) && fValidate;
if (errorCondition && !laxThisOne)
{
fValidator->emitError
(
XMLValid::GrammarNotFound
, XMLUni::fgZeroLenString
);
}
}
}
fElemStack.setCurrentScope(currentScope);
// Set element next state
if (elemDepth >= fElemStateSize) {
resizeElemState();
}
fElemState[elemDepth] = 0;
fElemLoopState[elemDepth] = 0;
}
fElemStack.setCurrentGrammar(fGrammar);
// If this is the first element and we are validating, check the root
// element.
if (isRoot)
{
if (fValidate)
{
// If a DocType exists, then check if it matches the root name there.
if (fRootElemName && !XMLString::equals(qnameRawBuf, fRootElemName))
fValidator->emitError(XMLValid::RootElemNotLikeDocType);
}
}
else if (parentValidation)
{
// If the element stack is not empty, then add this element as a
// child of the previous top element. If its empty, this is the root
// elem and is not the child of anything.
fElemStack.addChild(elemDecl->getElementName(), true);
}
// PSVI handling: even if it turns out there are
// no attributes, we need to reset this list...
if(getPSVIHandler() && fGrammarType == Grammar::SchemaGrammarType )
fPSVIAttrList->reset();
// Now lets get the fAttrList filled in. This involves faulting in any
// defaulted and fixed attributes and normalizing the values of any that
// we got explicitly.
//
// We update the attCount value with the total number of attributes, but
// it goes in with the number of values we got during the raw scan of
// explictly provided attrs above.
attCount = buildAttList(*fRawAttrList, attCount, elemDecl, *fAttrList);
if(attCount)
{
// clean up after ourselves:
// clear the map used to detect duplicate attributes
fUndeclaredAttrRegistry->removeAll();
}
// activate identity constraints
if (fGrammar &&
fGrammarType == Grammar::SchemaGrammarType &&
toCheckIdentityConstraint())
{
fICHandler->activateIdentityConstraint
(
(SchemaElementDecl*) elemDecl
, (int) elemDepth
, uriId
, fPrefixBuf.getRawBuffer()
, *fAttrList
, attCount
, fValidationContext
);
}
// Since the element may have default values, call start tag now regardless if it is empty or not
// If we have a document handler, then tell it about this start tag
if (fDocHandler)
{
fDocHandler->startElement
(
*elemDecl
, uriId
, fPrefixBuf.getRawBuffer()
, *fAttrList
, attCount
, false
, isRoot
);
}
// if we have a PSVIHandler, now's the time to call
// its handleAttributesPSVI method:
if(fPSVIHandler && fGrammarType == Grammar::SchemaGrammarType)
{
QName *eName = elemDecl->getElementName();
fPSVIHandler->handleAttributesPSVI
(
eName->getLocalPart()
, fURIStringPool->getValueForId(eName->getURI())
, fPSVIAttrList
);
}
// If empty, validate content right now if we are validating and then
// pop the element stack top. Else, we have to update the current stack
// top's namespace mapping elements.
if (isEmpty)
{
// Pop the element stack back off since it'll never be used now
fElemStack.popTop();
// reset current type info
DatatypeValidator* psviMemberType = 0;
if (fGrammarType == Grammar::SchemaGrammarType)
{
if (fValidate && elemDecl->isDeclared())
{
fPSVIElemContext.fCurrentTypeInfo = ((SchemaValidator*) fValidator)->getCurrentTypeInfo();
if(!fPSVIElemContext.fCurrentTypeInfo)
fPSVIElemContext.fCurrentDV = ((SchemaValidator*) fValidator)->getCurrentDatatypeValidator();
else
fPSVIElemContext.fCurrentDV = 0;
if(fPSVIHandler)
{
fPSVIElemContext.fNormalizedValue = ((SchemaValidator*) fValidator)->getNormalizedValue();
if (XMLString::equals(fPSVIElemContext.fNormalizedValue, XMLUni::fgZeroLenString))
fPSVIElemContext.fNormalizedValue = 0;
}
}
else
{
fPSVIElemContext.fCurrentDV = 0;
fPSVIElemContext.fCurrentTypeInfo = 0;
fPSVIElemContext.fNormalizedValue = 0;
}
}
// If validating, then insure that its legal to have no content
if (fValidate)
{
XMLSize_t failure;
bool res = fValidator->checkContent(elemDecl, 0, 0, &failure);
if (!res)
{
fValidator->emitError
(
XMLValid::ElementNotValidForContent
, elemDecl->getFullName()
, elemDecl->getFormattedContentModel()
);
}
if (fGrammarType == Grammar::SchemaGrammarType) {
if (((SchemaValidator*) fValidator)->getErrorOccurred())
{
fPSVIElemContext.fErrorOccurred = true;
}
else
{
if (fPSVIHandler)
{
fPSVIElemContext.fIsSpecified = ((SchemaValidator*) fValidator)->getIsElemSpecified();
if(fPSVIElemContext.fIsSpecified)
fPSVIElemContext.fNormalizedValue = ((SchemaElementDecl *)elemDecl)->getDefaultValue();
}
// note that if we're empty, won't be a current DV
if (fPSVIElemContext.fCurrentDV && fPSVIElemContext.fCurrentDV->getType() == DatatypeValidator::Union)
psviMemberType = fValidationContext->getValidatingMemberType();
}
// call matchers and de-activate context
if (toCheckIdentityConstraint())
{
fICHandler->deactivateContext
(
(SchemaElementDecl *) elemDecl
, fContent.getRawBuffer()
, fValidationContext
, fPSVIElemContext.fCurrentDV
);
}
}
}
else if (fGrammarType == Grammar::SchemaGrammarType) {
((SchemaValidator*)fValidator)->resetNillable();
}
if (fGrammarType == Grammar::SchemaGrammarType)
{
if (fPSVIHandler)
{
endElementPSVI((SchemaElementDecl*)elemDecl, psviMemberType);
}
}
// If we have a doc handler, tell it about the end tag
if (fDocHandler)
{
fDocHandler->endElement
(
*elemDecl
, uriId
, isRoot
, fPrefixBuf.getRawBuffer()
);
}
// If the elem stack is empty, then it was an empty root
if (isRoot)
gotData = false;
else
{
// Restore the grammar
fGrammar = fElemStack.getCurrentGrammar();
fGrammarType = fGrammar->getGrammarType();
if (fGrammarType == Grammar::SchemaGrammarType && !fValidator->handlesSchema()) {
if (fValidatorFromUser)
ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoSchemaValidator, fMemoryManager);
else {
fValidator = fSchemaValidator;
}
}
else if (fGrammarType == Grammar::DTDGrammarType && !fValidator->handlesDTD()) {
if (fValidatorFromUser)
ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoDTDValidator, fMemoryManager);
else {
fValidator = fDTDValidator;
}
}
fValidator->setGrammar(fGrammar);
// Restore the validation flag
fValidate = fElemStack.getValidationFlag();
}
}
else if (fGrammarType == Grammar::SchemaGrammarType)
{
// send a partial element psvi
if (fPSVIHandler)
{
ComplexTypeInfo* curTypeInfo = 0;
DatatypeValidator* curDV = 0;
XSTypeDefinition* typeDef = 0;
if (fValidate && elemDecl->isDeclared())
{
curTypeInfo = ((SchemaValidator*) fValidator)->getCurrentTypeInfo();
if (curTypeInfo)
{
typeDef = (XSTypeDefinition*) fModel->getXSObject(curTypeInfo);
}
else
{
curDV = ((SchemaValidator*) fValidator)->getCurrentDatatypeValidator();
if (curDV)
{
typeDef = (XSTypeDefinition*) fModel->getXSObject(curDV);
}
}
}
fPSVIElement->reset
(
PSVIElement::VALIDITY_NOTKNOWN
, PSVIElement::VALIDATION_NONE
, fRootElemName
, ((SchemaValidator*) fValidator)->getIsElemSpecified()
, (elemDecl->isDeclared()) ? (XSElementDeclaration*) fModel->getXSObject(elemDecl) : 0
, typeDef
, 0 //memberType
, fModel
, ((SchemaElementDecl*)elemDecl)->getDefaultValue()
, 0
, 0
, 0
);
fPSVIHandler->handlePartialElementPSVI
(
elemDecl->getBaseName()
, fURIStringPool->getValueForId(elemDecl->getURI())
, fPSVIElement
);
}
// not empty
fErrorStack->push(fPSVIElemContext.fErrorOccurred);
}
return true;
}