dgxmlscanner.cpp
来自「IBM的解析xml的工具Xerces的源代码」· C++ 代码 · 共 1,902 行 · 第 1/5 页
CPP
1,902 行
continue; } } // Make an initial pass through the list and find any xmlns attributes. if (fDoNamespaces && attCount) scanAttrListforNameSpaces(fAttrList, attCount, elemDecl); if(attCount) { // clean up after ourselves: // clear the map used to detect duplicate attributes fUndeclaredAttrRegistry->removeAll(); } // 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(attCount, elemDecl, *fAttrList); // If we have a document handler, then tell it about this start tag. We // don't have any URI id to send along, so send fEmptyNamespaceId. We also do not send // any prefix since its just one big name if we are not doing namespaces. unsigned int uriId = fEmptyNamespaceId; if (fDocHandler) { if (fDoNamespaces) { uriId = resolvePrefix ( elemDecl->getElementName()->getPrefix() , ElemStack::Mode_Element ); } fDocHandler->startElement ( *elemDecl , uriId , (fDoNamespaces) ? elemDecl->getElementName()->getPrefix() : 0 , *fAttrList , attCount , false , isRoot ); } // 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) { // If validating, then insure that its legal to have no content if (fValidate) { const int res = fValidator->checkContent(elemDecl, 0, 0); if (res >= 0) { fValidator->emitError ( XMLValid::ElementNotValidForContent , qnameRawBuf , elemDecl->getFormattedContentModel() ); } } // If we have a doc handler, tell it about the end tag if (fDocHandler) { fDocHandler->endElement ( *elemDecl , uriId , isRoot , (fDoNamespaces) ? elemDecl->getElementName()->getPrefix() : XMLUni::fgZeroLenString ); } // Pop the element stack back off since it'll never be used now fElemStack.popTop(); // If the elem stack is empty, then it was an empty root if (isRoot) gotData = false; } return true;}unsigned intDGXMLScanner::resolveQName(const XMLCh* const qName , XMLBuffer& prefixBuf , const short mode , int& prefixColonPos){ // Lets split out the qName into a URI and name buffer first. The URI // can be empty. prefixColonPos = XMLString::indexOf(qName, chColon); if (prefixColonPos == -1) { // Its all name with no prefix, so put the whole thing into the name // buffer. Then map the empty string to a URI, since the empty string // represents the default namespace. This will either return some // explicit URI which the default namespace is mapped to, or the // the default global namespace. bool unknown = false; prefixBuf.reset(); return fElemStack.mapPrefixToURI(XMLUni::fgZeroLenString, (ElemStack::MapModes) mode, unknown); } else { // Copy the chars up to but not including the colon into the prefix // buffer. prefixBuf.set(qName, prefixColonPos); // Watch for the special namespace prefixes. We always map these to // special URIs. 'xml' gets mapped to the official URI that its defined // to map to by the NS spec. xmlns gets mapped to a special place holder // URI that we define (so that it maps to something checkable.) const XMLCh* prefixRawBuf = prefixBuf.getRawBuffer(); if (XMLString::equals(prefixRawBuf, XMLUni::fgXMLNSString)) { // if this is an element, it is an error to have xmlns as prefix if (mode == ElemStack::Mode_Element) emitError(XMLErrs::NoXMLNSAsElementPrefix, qName); return fXMLNSNamespaceId; } else if (XMLString::equals(prefixRawBuf, XMLUni::fgXMLString)) { return fXMLNamespaceId; } else { bool unknown = false; unsigned int uriId = fElemStack.mapPrefixToURI(prefixRawBuf, (ElemStack::MapModes) mode, unknown); if (unknown) emitError(XMLErrs::UnknownPrefix, prefixRawBuf); return uriId; } }}// ---------------------------------------------------------------------------// DGXMLScanner: Grammar preparsing// ---------------------------------------------------------------------------Grammar* DGXMLScanner::loadGrammar(const InputSource& src , const short grammarType , const bool toCache){ Grammar* loadedGrammar = 0; try { fGrammarResolver->cacheGrammarFromParse(false); fGrammarResolver->useCachedGrammarInParse(false); fRootGrammar = 0; if (fValScheme == Val_Auto) { fValidate = true; } // Reset some status flags fInException = false; fStandalone = false; fErrorCount = 0; fHasNoDTD = true; if (grammarType == Grammar::DTDGrammarType) { loadedGrammar = loadDTDGrammar(src, toCache); } // Reset the reader manager to close all files, sockets, etc... fReaderMgr.reset(); } // NOTE: // // In all of the error processing below, the emitError() call MUST come // before the flush of the reader mgr, or it will fail because it tries // to find out the position in the XML source of the error. catch(const XMLErrs::Codes) { // This is a 'first fatal error' type exit, so reset and fall through fReaderMgr.reset(); } catch(const XMLValid::Codes) { // This is a 'first fatal error' type exit, so reset and fall through fReaderMgr.reset(); } catch(const XMLException& excToCatch) { // Emit the error and catch any user exception thrown from here. Make // sure in all cases we flush the reader manager. fInException = true; try { if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning) emitError ( XMLErrs::DisplayErrorMessage , excToCatch.getMessage() ); else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal) emitError ( XMLErrs::XMLException_Fatal , excToCatch.getType() , excToCatch.getMessage() ); else emitError ( XMLErrs::XMLException_Error , excToCatch.getType() , excToCatch.getMessage() ); } catch(const OutOfMemoryException&) { throw; } catch(...) { // Flush the reader manager and rethrow user's error fReaderMgr.reset(); throw; } // If it returned, then reset the reader manager and fall through fReaderMgr.reset(); } catch(const OutOfMemoryException&) { throw; } catch(...) { // Reset and rethrow fReaderMgr.reset(); throw; } return loadedGrammar;}Grammar* DGXMLScanner::loadDTDGrammar(const InputSource& src, const bool toCache){ // Reset the validators fDTDValidator->reset(); if (fValidatorFromUser) fValidator->reset(); fDTDGrammar = new (fGrammarPoolMemoryManager) DTDGrammar(fGrammarPoolMemoryManager); fGrammarResolver->putGrammar(fDTDGrammar); fGrammar = fDTDGrammar; fValidator->setGrammar(fGrammar); // And for all installed handlers, send reset events. This gives them // a chance to flush any cached data. if (fDocHandler) fDocHandler->resetDocument(); if (fEntityHandler) fEntityHandler->resetEntities(); if (fErrorReporter) fErrorReporter->resetErrors(); // Clear out the id reference list resetValidationContext(); if (toCache) { unsigned int sysId = fGrammarResolver->getStringPool()->addOrFind(src.getSystemId()); const XMLCh* sysIdStr = fGrammarResolver->getStringPool()->getValueForId(sysId); fGrammarResolver->orphanGrammar(XMLUni::fgDTDEntityString); ((XMLDTDDescription*) (fGrammar->getGrammarDescription()))->setSystemId(sysIdStr); fGrammarResolver->putGrammar(fGrammar); } // Handle the creation of the XML reader object for this input source. // This will provide us with transcoding and basic lexing services. XMLReader* newReader = fReaderMgr.createReader ( src , false , XMLReader::RefFrom_NonLiteral , XMLReader::Type_General , XMLReader::Source_External , fCalculateSrcOfs ); if (!newReader) { if (src.getIssueFatalErrorIfNotFound()) ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource, src.getSystemId(), fMemoryManager); else ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource_Warning, src.getSystemId(), fMemoryManager); } // In order to make the processing work consistently, we have to // make this look like an external entity. So create an entity // decl and fill it in and push it with the reader, as happens // with an external entity. Put a janitor on it to insure it gets // cleaned up. The reader manager does not adopt them. const XMLCh gDTDStr[] = { chLatin_D, chLatin_T, chLatin_D , chNull }; DTDEntityDecl* declDTD = new (fGrammarPoolMemoryManager) DTDEntityDecl(gDTDStr, false, fGrammarPoolMemoryManager); declDTD->setSystemId(src.getSystemId()); Janitor<DTDEntityDecl> janDecl(declDTD); // Mark this one as a throw at end newReader->setThrowAtEnd(true); // And push it onto the stack, with its pseudo name fReaderMgr.pushReader(newReader, declDTD); // If we have a doc type handler and advanced callbacks are enabled, // call the doctype event. if (fDocTypeHandler) { // Create a dummy root DTDElementDecl* rootDecl = new (fGrammarPoolMemoryManager) DTDElementDecl ( gDTDStr , fEmptyNamespaceId , DTDElementDecl::Any , fGrammarPoolMemoryManager ); rootDecl->setCreateReason(DTDElementDecl::AsRootElem); rootDecl->setExternalElemDeclaration(true); Janitor<DTDElementDecl> janSrc(rootDecl); fDocTypeHandler->doctypeDecl(*rootDecl, src.getPublicId(), src.getSystemId(), false, true); } // Create DTDScanner DTDScanner dtdScanner ( (DTDGrammar*)fGrammar , fDocTypeHandler , fGrammarPoolMemoryManager , fMemoryManager ); dtdScanner.setScannerInfo(this, &fReaderMgr, &fBufMgr); // Tell it its not in an include section dtdScanner.scanExtSubsetDecl(false, true); if (fValidate) { // validate the DTD scan so far fValidator->preContentValidation(false, true); } if (toCache) fGrammarResolver->cacheGrammars(); return fDTDGrammar;}// ---------------------------------------------------------------------------// DGXMLScanner: Private helper methods// ---------------------------------------------------------------------------// This method handles the common initialization, to avoid having to do// it redundantly in multiple constructors.void DGXMLScanner::commonInit(){ // And we need one for the raw attribute scan. This just stores key/
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?