dtdvalidator.cpp

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

CPP
690
字号
/* * Copyright 1999-2001,2004 The Apache Software Foundation. *  * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at *  *      http://www.apache.org/licenses/LICENSE-2.0 *  * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *//* * $Id: DTDValidator.cpp,v 1.24 2004/09/08 13:56:50 peiyongz Exp $ */// ---------------------------------------------------------------------------//  Includes// ---------------------------------------------------------------------------#include <xercesc/util/Janitor.hpp>#include <xercesc/util/XMLUniDefs.hpp>#include <xercesc/util/XMLUni.hpp>#include <xercesc/internal/ReaderMgr.hpp>#include <xercesc/internal/XMLScanner.hpp>#include <xercesc/validators/DTD/DTDValidator.hpp>XERCES_CPP_NAMESPACE_BEGIN// ---------------------------------------------------------------------------//  DTDValidator: Constructors and Destructor// ---------------------------------------------------------------------------DTDValidator::DTDValidator(XMLErrorReporter* const errReporter) :    XMLValidator(errReporter)    , fDTDGrammar(0){    reset();}DTDValidator::~DTDValidator(){}// ---------------------------------------------------------------------------//  DTDValidator: Implementation of the XMLValidator interface// ---------------------------------------------------------------------------int DTDValidator::checkContent(XMLElementDecl* const elemDecl                              , QName** const        children                              , const unsigned int   childCount){    //    //  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, getScanner()->getMemoryManager());    //    //  Get the content spec type of this element. This will tell us what    //  to do to validate it.    //    const DTDElementDecl::ModelTypes modelType = ((DTDElementDecl*) elemDecl)->getModelType();    if (modelType == DTDElementDecl::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)            return 0;    }     else if (modelType == DTDElementDecl::Any)    {        // We pass no judgement on this one, anything goes    }     else if ((modelType == DTDElementDecl::Mixed_Simple)          ||  (modelType == DTDElementDecl::Children))    {        // Get the element's content model or fault it in        const XMLContentModel* elemCM = elemDecl->getContentModel();        // Ask it to validate and return its return        return elemCM->validateContent(children, childCount, getScanner()->getEmptyNamespaceId());    }     else    {        ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::CM_UnknownCMType, getScanner()->getMemoryManager());    }    // Went ok, so return success    return -1;}void DTDValidator::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.    //    const XMLCh* fullName = attDef.getFullName();    const int colonInd = XMLString::indexOf(fullName, chColon);    if (colonInd == -1)    {        // There is no prefix, so we just do a simple and quick setting        toFill.set        (            0            , fullName            , XMLUni::fgZeroLenString            , attDef.getValue()            , attDef.getType()        );    }     else    {        //        //  There is a colon, so we have to split apart the name and prefix        //  part.        //        XMLCh* tmpNameBuf = XMLString::replicate(fullName, getScanner()->getMemoryManager());        ArrayJanitor<XMLCh> janNameBuf(tmpNameBuf, getScanner()->getMemoryManager());        // Put a null where the colon is, to split it into two strings        tmpNameBuf[colonInd] = chNull;        //        //  And now we can set the attribute object with the prefix and name        //  parts.        //        toFill.set        (            0            , &tmpNameBuf[colonInd+1]            , tmpNameBuf            , attDef.getValue()            , attDef.getType()        );    }}void DTDValidator::reset(){}bool DTDValidator::requiresNamespaces() const{    // Namespaces are not supported for DTDs    return false;}voidDTDValidator::validateAttrValue(const   XMLAttDef*      attDef                                , const XMLCh* const    attrValue                                , bool                  preValidation                                , const XMLElementDecl*){    //    //  Get quick refs to lost of of the stuff in the passed objects in    //  order to simplify the code below, which will reference them very    //  often.    //    const XMLAttDef::AttTypes       type = attDef->getType();    const XMLAttDef::DefAttTypes    defType = attDef->getDefaultType();    const XMLCh* const              valueText = attDef->getValue();    const XMLCh* const              fullName = attDef->getFullName();    const XMLCh* const              enumList = attDef->getEnumeration();    //    //  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 && !preValidation)    {        if (!XMLString::equals(attrValue, valueText))            emitError(XMLValid::NotSameAsFixedValue, fullName, attrValue, valueText);    }    //    //  If its a CDATA attribute, then we are done with any DTD level    //  validation else do the rest.    //    if (type == XMLAttDef::CData)        return;    // An empty string cannot be valid for any of the other types    if (!attrValue[0])    {        emitError(XMLValid::InvalidEmptyAttValue, fullName);        return;    }    // See whether we are doing multiple values or not    const bool multipleValues =    (        (type == XMLAttDef::IDRefs)        || (type == XMLAttDef::Entities)        || (type == XMLAttDef::NmTokens)        || (type == XMLAttDef::Notation)        || (type == XMLAttDef::Enumeration)    );    // And whether we must check for a first name char    const bool firstNameChar =    (        (type == XMLAttDef::ID)        || (type == XMLAttDef::IDRef)        || (type == XMLAttDef::IDRefs)        || (type == XMLAttDef::Entity)        || (type == XMLAttDef::Entities)        || (type == XMLAttDef::Notation)    );    // Whether it requires ref checking stuff    const bool isARefType    (        (type == XMLAttDef::ID)        || (type == XMLAttDef::IDRef)        || (type == XMLAttDef::IDRefs)    );    // Some trigger flags to avoid issuing redundant errors and whatnot        bool alreadyCapped = false;    //    //  Make a copy of the text that we can mangle and get a pointer we can    //  move through the value    //    // Use a stack-based buffer, when possible...    XMLCh   tempBuffer[100];    XMLCh* pszTmpVal = 0;    ArrayJanitor<XMLCh> janTmpVal(0);    if (XMLString::stringLen(attrValue) < sizeof(tempBuffer) / sizeof(tempBuffer[0]))    {        XMLString::copyString(tempBuffer, attrValue);        pszTmpVal = tempBuffer;    }    else    {        janTmpVal.reset(XMLString::replicate(attrValue, getScanner()->getMemoryManager()), getScanner()->getMemoryManager());        pszTmpVal = janTmpVal.get();    }    XMLCh* valPtr = pszTmpVal;    bool doNamespace = getScanner()->getDoNamespaces();    while (true)    {        //        //  Make sure the first character is a valid first name char, i.e.        //  if its a Name value. For NmToken values we don't treat the first        //  char any differently.        //        if (firstNameChar)        {            // If its not, emit and error but try to keep going            if (!getReaderMgr()->getCurrentReader()->isFirstNameChar(*valPtr))                emitError(XMLValid::AttrValNotName, valPtr, fullName);            valPtr++;        }        // Make sure all the remaining chars are valid name chars        while (*valPtr)        {            //            //  If we hit a whitespace, its either a break between two            //  or more values, or an error if we have a single value.            //            //            //   XML1.0-3rd            //            //   [6]   Names   ::=   Name (#x20 Name)*            //   [8]   Nmtokens   ::=   Nmtoken (#x20 Nmtoken)*            //            //   only and only ONE #x20 is allowed to be the delimiter            //            if (*valPtr==chSpace)            {                if (!multipleValues)                {                    emitError(XMLValid::NoMultipleValues, fullName);                    return;                }                break;            }            // Now this attribute can be of type            //     ID, IDREF, IDREFS, ENTITY, ENTITIES, NOTATION, NMTOKEN, NMTOKENS, ENUMERATION            //  All these must be valid XMLName            // If namespace is enabled, colon is not allowed in the first 6            if (doNamespace && *valPtr == chColon && firstNameChar)                emitError(XMLValid::ColonNotValidWithNS);            if (!getReaderMgr()->getCurrentReader()->isNameChar(*valPtr))            {                emitError(XMLValid::AttrValNotName, valPtr, fullName);                return;            }            valPtr++;        }        //        //  Cap it off at the current non-name char. If already capped,        //  then remember this.        //        if (!(*valPtr))            alreadyCapped = true;        *valPtr = 0;        //        //  If this type of attribute requires that we track reference        //  stuff, then handle that.        //        if (isARefType)        {            if ((type == XMLAttDef::ID)            ||  (type == XMLAttDef::IDRef)            ||  (type == XMLAttDef::IDRefs))            {                XMLRefInfo* find = getScanner()->getIDRefList()->get(pszTmpVal);                if (find)                {                    if (find->getDeclared() && (type == XMLAttDef::ID))

⌨️ 快捷键说明

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