dgxmlscanner.cpp
来自「IBM的解析xml的工具Xerces的源代码」· C++ 代码 · 共 1,902 行 · 第 1/5 页
CPP
1,902 行
fValidator->validateElement(elemDecl); } // Expand the element stack and add the new element fElemStack.addLevel(elemDecl, fReaderMgr.getCurrentReaderNum()); // If this is the first element and we are validating, check the root // element. if (isRoot) { fRootGrammar = fGrammar; 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); // Some validators may also want to check the root, call the // XMLValidator::checkRootElement if (fValidatorFromUser && !fValidator->checkRootElement(elemDecl->getId())) fValidator->emitError(XMLValid::RootElemNotLikeDocType); } } else if (fValidate) { // 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); } // Skip any whitespace after the name fReaderMgr.skipPastSpaces(); // We loop until we either see a /> or >, handling attribute/value // pairs until we get there. unsigned int attCount = 0; unsigned int curAttListSize = fAttrList->size(); wasAdded = false; fElemCount++; while (true) { // And get the next non-space character XMLCh nextCh = fReaderMgr.peekNextChar(); // If the next character is not a slash or closed angle bracket, // then it must be whitespace, since whitespace is required // between the end of the last attribute and the name of the next // one. if (attCount) { if ((nextCh != chForwardSlash) && (nextCh != chCloseAngle)) { if (fReaderMgr.getCurrentReader()->isWhitespace(nextCh)) { // Ok, skip by them and peek another char fReaderMgr.skipPastSpaces(); nextCh = fReaderMgr.peekNextChar(); } else { // Emit the error but keep on going emitError(XMLErrs::ExpectedWhitespace); } } } // Ok, here we first check for any of the special case characters. // If its not one, then we do the normal case processing, which // assumes that we've hit an attribute value, Otherwise, we do all // the special case checks. if (!fReaderMgr.getCurrentReader()->isSpecialStartTagChar(nextCh)) { // Assume its going to be an attribute, so get a name from // the input. if (!fReaderMgr.getName(fAttNameBuf)) { emitError(XMLErrs::ExpectedAttrName); fReaderMgr.skipPastChar(chCloseAngle); return false; } // And next must be an equal sign if (!scanEq()) { static const XMLCh tmpList[] = { chSingleQuote, chDoubleQuote, chCloseAngle , chOpenAngle, chForwardSlash, chNull }; emitError(XMLErrs::ExpectedEqSign); // Try to sync back up by skipping forward until we either // hit something meaningful. const XMLCh chFound = fReaderMgr.skipUntilInOrWS(tmpList); if ((chFound == chCloseAngle) || (chFound == chForwardSlash)) { // Jump back to top for normal processing of these continue; } else if ((chFound == chSingleQuote) || (chFound == chDoubleQuote) || fReaderMgr.getCurrentReader()->isWhitespace(chFound)) { // Just fall through assuming that the value is to follow } else if (chFound == chOpenAngle) { // Assume a malformed tag and that new one is starting emitError(XMLErrs::UnterminatedStartTag, elemDecl->getFullName()); return false; } else { // Something went really wrong return false; } } // See if this attribute is declared for this element. If we are // not validating of course it will not be at first, but we will // fault it into the pool (to avoid lots of redundant errors.) XMLAttDef* attDef = ((DTDElementDecl *)elemDecl)->getAttDef ( fAttNameBuf.getRawBuffer()); XMLCh * namePtr = fAttNameBuf.getRawBuffer(); // Add this attribute to the attribute list that we use to // pass them to the handler. We reuse its existing elements // but expand it as required. // Note that we want to this first since this will // make a copy of the namePtr; we can then make use of // that copy in the hashtable lookup that checks // for duplicates. This will mean we may have to update // the type of the XMLAttr later. XMLAttr* curAtt; if (attCount >= curAttListSize) { if (fDoNamespaces) { curAtt = new (fMemoryManager) XMLAttr ( fEmptyNamespaceId , fAttNameBuf.getRawBuffer() , XMLUni::fgZeroLenString , (attDef)?attDef->getType():XMLAttDef::CData , true , fMemoryManager ); } else { curAtt = new (fMemoryManager) XMLAttr ( -1 , fAttNameBuf.getRawBuffer() , XMLUni::fgZeroLenString , XMLUni::fgZeroLenString , (attDef)?attDef->getType():XMLAttDef::CData , true , fMemoryManager ); } fAttrList->addElement(curAtt); } else { curAtt = fAttrList->elementAt(attCount); if (fDoNamespaces) { curAtt->set ( fEmptyNamespaceId , fAttNameBuf.getRawBuffer() , XMLUni::fgZeroLenString , (attDef)?attDef->getType():XMLAttDef::CData ); } else { curAtt->set ( -1 , fAttNameBuf.getRawBuffer() , XMLUni::fgZeroLenString , XMLUni::fgZeroLenString , (attDef)?attDef->getType():XMLAttDef::CData ); } curAtt->setSpecified(true); } // reset namePtr so it refers to newly-allocated memory namePtr = (XMLCh *)curAtt->getName(); // now need to prepare for duplicate detection if(attDef) { unsigned int *curCountPtr = fAttDefRegistry->get(attDef); if(!curCountPtr) { curCountPtr = getNewUIntPtr(); *curCountPtr = fElemCount; fAttDefRegistry->put(attDef, curCountPtr); } else if(*curCountPtr < fElemCount) *curCountPtr = fElemCount; else { emitError ( XMLErrs::AttrAlreadyUsedInSTag , attDef->getFullName() , elemDecl->getFullName() ); } } else { unsigned int *curCountPtr = fUndeclaredAttrRegistry->get(namePtr); if(!curCountPtr) { curCountPtr = getNewUIntPtr(); *curCountPtr = fElemCount; fUndeclaredAttrRegistry->put((void *)namePtr, curCountPtr); } else if(*curCountPtr < fElemCount) *curCountPtr = fElemCount; else { emitError ( XMLErrs::AttrAlreadyUsedInSTag , namePtr , elemDecl->getFullName() ); } } if (fValidate) { if (!attDef) { fValidator->emitError ( XMLValid::AttNotDefinedForElement , fAttNameBuf.getRawBuffer() , qnameRawBuf ); } } // Skip any whitespace before the value and then scan the att // value. This will come back normalized with entity refs and // char refs expanded. fReaderMgr.skipPastSpaces(); if (!scanAttValue(attDef, fAttNameBuf.getRawBuffer(), fAttValueBuf)) { static const XMLCh tmpList[] = { chCloseAngle, chOpenAngle, chForwardSlash, chNull }; emitError(XMLErrs::ExpectedAttrValue); // It failed, so lets try to get synced back up. We skip // forward until we find some whitespace or one of the // chars in our list. const XMLCh chFound = fReaderMgr.skipUntilInOrWS(tmpList); if ((chFound == chCloseAngle) || (chFound == chForwardSlash) || fReaderMgr.getCurrentReader()->isWhitespace(chFound)) { // Just fall through and process this attribute, though // the value will be "". } else if (chFound == chOpenAngle) { // Assume a malformed tag and that new one is starting emitError(XMLErrs::UnterminatedStartTag, elemDecl->getFullName()); return false; } else { // Something went really wrong return false; } } // must set the newly-minted value on the XMLAttr: curAtt->setValue(fAttValueBuf.getRawBuffer()); // Now that its all stretched out, lets look at its type and // determine if it has a valid value. It will output any needed // errors, but we just keep going. We only need to do this if // we are validating. if (attDef) { // Let the validator pass judgement on the attribute value if (fValidate) { fValidator->validateAttrValue ( attDef , fAttValueBuf.getRawBuffer() , false , elemDecl ); } } if (fDoNamespaces) { // Make sure that the name is basically well formed for namespace // enabled rules. It either has no colons, or it has one which // is neither the first or last char. const int colonFirst = XMLString::indexOf(fAttNameBuf.getRawBuffer(), chColon); if (colonFirst != -1) { const int colonLast = XMLString::lastIndexOf(fAttNameBuf.getRawBuffer(), chColon); if (colonFirst != colonLast) { emitError(XMLErrs::TooManyColonsInName); continue; } else if ((colonFirst == 0) || (colonLast == (int)fAttNameBuf.getLen() - 1)) { emitError(XMLErrs::InvalidColonPos); continue; } } } attCount++; // And jump back to the top of the loop continue; } // It was some special case character so do all of the checks and // deal with it. if (!nextCh) ThrowXMLwithMemMgr(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF, fMemoryManager); if (nextCh == chForwardSlash) { fReaderMgr.getNextChar(); isEmpty = true; if (!fReaderMgr.skippedChar(chCloseAngle)) emitError(XMLErrs::UnterminatedStartTag, elemDecl->getFullName()); break; } else if (nextCh == chCloseAngle) { fReaderMgr.getNextChar(); break; } else if (nextCh == chOpenAngle) { // Check for this one specially, since its going to be common // and it is kind of auto-recovering since we've already hit the // next open bracket, which is what we would have seeked to (and // skipped this whole tag.) emitError(XMLErrs::UnterminatedStartTag, elemDecl->getFullName()); break; } else if ((nextCh == chSingleQuote) || (nextCh == chDoubleQuote)) { // Check for this one specially, which is probably a missing // attribute name, e.g. ="value". Just issue expected name // error and eat the quoted string, then jump back to the // top again. emitError(XMLErrs::ExpectedAttrName); fReaderMgr.getNextChar(); fReaderMgr.skipQuotedString(nextCh); fReaderMgr.skipPastSpaces();
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?