schemavalidator.cpp

来自「IBM的解析xml的工具Xerces的源代码」· C++ 代码 · 共 1,621 行 · 第 1/5 页

CPP
1,621
字号
}SchemaValidator::~SchemaValidator(){    delete fXsiType;    delete fTypeStack;    if (fNotationBuf)        delete fNotationBuf;}// ---------------------------------------------------------------------------//  SchemaValidator: Implementation of the XMLValidator interface// ---------------------------------------------------------------------------int SchemaValidator::checkContent (XMLElementDecl* const elemDecl                                 , QName** const         children                                 , const unsigned int    childCount){    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)    {        //        //  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;            return 0;        }    }    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->getContentModel();            // Ask it to validate and return its return            unsigned int emptyNS = getScanner()->getEmptyNamespaceId();            int result = elemCM->validateContent(children, childCount, emptyNS);            if (result != -1) {                result = elemCM->validateContentSpecial(children                                                      , childCount                                                      , emptyNS                                                      , fGrammarResolver                                                      , fGrammarResolver->getStringPool());            }            if(result != -1) {                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 if (fCurrentDatatypeValidator)        {            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            {                DatatypeValidator::ValidatorType eleDefDVType = fCurrentDatatypeValidator->getType();                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);                    fNotationBuf->set(getScanner()->getURIText(uriId));                    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;                        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;                            }                        }                    }                }                else                {                    // no default value, then check nillable                    if (XMLString::equals(value, XMLUni::fgZeroLenString)                        && (((SchemaElementDecl*)elemDecl)->getMiscFlags() & SchemaSymbols::XSD_NILLABLE) != 0)                            value = 0;                }                if ((!fErrorOccurred) && value)                {                    try                    {                        fCurrentDatatypeValidator->validate(value, getScanner()->getValidationContext(), fMemoryManager);                    }                    catch (XMLException& idve)                    {                        emitError (XMLValid::DatatypeError, idve.getType(), 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;        }    }    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;    fTrailing=false;    fCurrentDatatypeValidator = 0;    // Went ok, so return success    return -1;}void SchemaValidator::faultInAttr (XMLAttr&    toFill, const XMLAttDef&  attDef)   const{    //    //  At this level, we cannot set the URI id. So we just set it to zero    //  and leave it at that. The scanner, who called us, will look at the    //  prefix we stored (if any), resolve it, and store the URL id if any.    //    SchemaAttDef* schemaAttDef = (SchemaAttDef*) &attDef;    QName* attName = schemaAttDef->getAttName();    toFill.set    (          attName->getURI()        , attName->getLocalPart()        , attName->getPrefix()        , schemaAttDef->getValue()        , schemaAttDef->getType()    );}void SchemaValidator::reset(){    fTrailing = false;    fSeenId = false;	fTypeStack->removeAllElements();    delete fXsiType;    fXsiType = 0;    fCurrentDatatypeValidator = 0;    fNil = false;    fDatatypeBuffer.reset();    fErrorOccurred = false;}bool SchemaValidator::requiresNamespaces() const{    return true;}void SchemaValidator::validateAttrValue (const XMLAttDef*      attDef                                       , const XMLCh* const    attrValue                                       , bool                  preValidation                                       , const XMLElementDecl* elemDecl){    fErrorOccurred = false;    //turn on IdRefList checking    getScanner()->getValidationContext()->toCheckIdRefList(true);    //    //  Get quick refs to lot of the stuff in the passed objects in    //  order to simplify the code below, which will reference them very    //  often.    //    XMLAttDef::AttTypes            type      = attDef->getType();    const XMLAttDef::DefAttTypes   defType   = attDef->getDefaultType();    //    //  If the default type is fixed, then make sure the passed value maps    //  to the fixed value.    //    //  If during preContentValidation, the value we are validating is the fixed value itself    //  so no need to compare.    //  Only need to do this for regular attribute value validation    //    if ((defType == XMLAttDef::Fixed || defType == XMLAttDef::Required_And_Fixed) && !preValidation)    {        const XMLCh* const valueText = attDef->getValue();        if (!XMLString::equals(attrValue, valueText)) {            emitError(XMLValid::NotSameAsFixedValue, attDef->getFullName(), attrValue, valueText);            fErrorOccurred = true;        }    }    // An empty string cannot be valid for non_CDATA any of the other types    if (!attrValue[0] && type != XMLAttDef::Simple)    {        emitError(XMLValid::InvalidEmptyAttValue, attDef->getFullName());        // accords with original DOMTypeInfo implementation, but this does not feel right.        fMostRecentAttrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYSIMPLETYPE);        fErrorOccurred = true;        return;    }    DatatypeValidator* attDefDV = ((SchemaAttDef*) attDef)->getDatatypeValidator();    if (!attDefDV) {        emitError(XMLValid::NoDatatypeValidatorForAttribute, attDef->getFullName());        fErrorOccurred = true;    }    else {        DatatypeValidator::ValidatorType attDefDVType = attDefDV->getType();        ValidationContext *context = getScanner()->getValidationContext();        try {            // first, if notation, need to bind URI to notation first            if (attDefDVType == DatatypeValidator::NOTATION)            {                //                //  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.                //                XMLBuffer notationBuf(1023, fMemoryManager);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?