/* * Copyright 1999-2002,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. */ /** * This file contains code to build the DOM tree. It registers a document * handler with the scanner. In these handler methods, appropriate DOM nodes * are created and added to the DOM tree. * * $Id: DOMParser.cpp 176291 2005-01-14 10:37:42Z amassari $ * */ // --------------------------------------------------------------------------- // Includes // --------------------------------------------------------------------------- #include #include #include #include #include #include #include #include #include #include #include #include #include "DOMParser.hpp" #include "ElementImpl.hpp" #include "AttrImpl.hpp" #include "AttrNSImpl.hpp" #include "TextImpl.hpp" #include "DocumentImpl.hpp" #include "DocumentTypeImpl.hpp" #include "EntityImpl.hpp" #include "NotationImpl.hpp" #include "NamedNodeMapImpl.hpp" #include "NodeIDMap.hpp" #include #include #include #include XERCES_CPP_NAMESPACE_BEGIN // --------------------------------------------------------------------------- // DOMParser: Constructors and Destructor // --------------------------------------------------------------------------- DOMParser::DOMParser( XMLValidator* const valToAdopt , MemoryManager* const manager , XMLGrammarPool* const gramPool) : fToCreateXMLDeclTypeNode(false) , fCreateEntityReferenceNodes(true) , fIncludeIgnorableWhitespace(true) , fParseInProgress(false) , fWithinElement(false) , fEntityResolver(0) , fXMLEntityResolver(0) , fErrorHandler(0) , fPSVIHandler(0) , fNodeStack(0) , fScanner(0) , fDocumentType(0) , fGrammarResolver(0) , fURIStringPool(0) , fValidator(valToAdopt) , fMemoryManager(manager) , fGrammarPool(gramPool) { try { initialize(); } catch(const OutOfMemoryException&) { throw; } catch(...) { cleanUp(); throw; } } DOMParser::~DOMParser() { cleanUp(); } // --------------------------------------------------------------------------- // DOMParser: Initialize/CleanUp methods // --------------------------------------------------------------------------- void DOMParser::initialize() { // Create grammar resolver and URI string pool to pass to the scanner fGrammarResolver = new (fMemoryManager) GrammarResolver(fGrammarPool, fMemoryManager); fURIStringPool = fGrammarResolver->getStringPool(); // Create a scanner and tell it what validator to use. Then set us // as the document event handler so we can fill the DOM document. fScanner = XMLScannerResolver::getDefaultScanner(fValidator, fGrammarResolver, fMemoryManager); fScanner->setDocHandler(this); fScanner->setDocTypeHandler(this); fScanner->setURIStringPool(fURIStringPool); fNodeStack = new (fMemoryManager) ValueStackOf(64, fMemoryManager, true); this->reset(); } void DOMParser::cleanUp() { delete fNodeStack; delete fScanner; delete fGrammarResolver; // grammar pool must do this //delete fURIStringPool; if (fValidator) delete fValidator; } void DOMParser::reset() { // // Note: DOM Documents are reference counted. Doing this assignment // will cause the old one to go away unless application code is also // holding a reference to it. // fDocument = DOM_Document::createDocument(fMemoryManager); resetDocType(); fCurrentParent = 0; fCurrentNode = 0; fParseInProgress = false; fWithinElement = false; fNodeStack->removeAllElements(); }; // --------------------------------------------------------------------------- // DOMParser: Getter methods // --------------------------------------------------------------------------- const XMLValidator& DOMParser::getValidator() const { return *fScanner->getValidator(); } bool DOMParser::getDoNamespaces() const { return fScanner->getDoNamespaces(); } bool DOMParser::getExitOnFirstFatalError() const { return fScanner->getExitOnFirstFatal(); } bool DOMParser::getValidationConstraintFatal() const { return fScanner->getValidationConstraintFatal(); } DOMParser::ValSchemes DOMParser::getValidationScheme() const { const XMLScanner::ValSchemes scheme = fScanner->getValidationScheme(); if (scheme == XMLScanner::Val_Always) return Val_Always; else if (scheme == XMLScanner::Val_Never) return Val_Never; return Val_Auto; } bool DOMParser::getDoSchema() const { return fScanner->getDoSchema(); } bool DOMParser::getValidationSchemaFullChecking() const { return fScanner->getValidationSchemaFullChecking(); } bool DOMParser::getIdentityConstraintChecking() const { return fScanner->getIdentityConstraintChecking(); } int DOMParser::getErrorCount() const { return fScanner->getErrorCount(); } XMLCh* DOMParser::getExternalSchemaLocation() const { return fScanner->getExternalSchemaLocation(); } XMLCh* DOMParser::getExternalNoNamespaceSchemaLocation() const { return fScanner->getExternalNoNamespaceSchemaLocation(); } bool DOMParser::isCachingGrammarFromParse() const { return fScanner->isCachingGrammarFromParse(); } bool DOMParser::isUsingCachedGrammarInParse() const { return fScanner->isUsingCachedGrammarInParse(); } Grammar* DOMParser::getGrammar(const XMLCh* const nameSpaceKey) { return fGrammarResolver->getGrammar(nameSpaceKey); } Grammar* DOMParser::getRootGrammar() { return fScanner->getRootGrammar(); } const XMLCh* DOMParser::getURIText(unsigned int uriId) const { return fScanner->getURIText(uriId); } bool DOMParser::getCalculateSrcOfs() const { return fScanner->getCalculateSrcOfs(); } bool DOMParser::getStandardUriConformant() const { return fScanner->getStandardUriConformant(); } unsigned int DOMParser::getSrcOffset() const { return fScanner->getSrcOffset(); } // --------------------------------------------------------------------------- // DOMParser: Setter methods // --------------------------------------------------------------------------- void DOMParser::setDoNamespaces(const bool newState) { fScanner->setDoNamespaces(newState); } void DOMParser::setErrorHandler(ErrorHandler* const handler) { fErrorHandler = handler; if (fErrorHandler) { fScanner->setErrorReporter(this); fScanner->setErrorHandler(fErrorHandler); } else { fScanner->setErrorReporter(0); fScanner->setErrorHandler(0); } } void DOMParser::setPSVIHandler(PSVIHandler* const handler) { fPSVIHandler = handler; if (fPSVIHandler) { fScanner->setPSVIHandler(fPSVIHandler); } else { fScanner->setPSVIHandler(0); } } void DOMParser::setEntityResolver(EntityResolver* const handler) { fEntityResolver = handler; if (fEntityResolver) { fScanner->setEntityHandler(this); fXMLEntityResolver = 0; } else { fScanner->setEntityHandler(0); } } void DOMParser::setXMLEntityResolver(XMLEntityResolver* const handler) { fXMLEntityResolver = handler; if (fXMLEntityResolver) { fEntityResolver = 0; fScanner->setEntityHandler(this); } else { fScanner->setEntityHandler(0); } } void DOMParser::setExitOnFirstFatalError(const bool newState) { fScanner->setExitOnFirstFatal(newState); } void DOMParser::setValidationConstraintFatal(const bool newState) { fScanner->setValidationConstraintFatal(newState); } void DOMParser::setValidationScheme(const ValSchemes newScheme) { if (newScheme == Val_Never) fScanner->setValidationScheme(XMLScanner::Val_Never); else if (newScheme == Val_Always) fScanner->setValidationScheme(XMLScanner::Val_Always); else fScanner->setValidationScheme(XMLScanner::Val_Auto); } void DOMParser::setDoSchema(const bool newState) { fScanner->setDoSchema(newState); } void DOMParser::setValidationSchemaFullChecking(const bool schemaFullChecking) { fScanner->setValidationSchemaFullChecking(schemaFullChecking); } void DOMParser::setIdentityConstraintChecking(const bool identityConstraintChecking) { fScanner->setIdentityConstraintChecking(identityConstraintChecking); } void DOMParser::setExternalSchemaLocation(const XMLCh* const schemaLocation) { fScanner->setExternalSchemaLocation(schemaLocation); } void DOMParser::setExternalNoNamespaceSchemaLocation(const XMLCh* const noNamespaceSchemaLocation) { fScanner->setExternalNoNamespaceSchemaLocation(noNamespaceSchemaLocation); } void DOMParser::setExternalSchemaLocation(const char* const schemaLocation) { fScanner->setExternalSchemaLocation(schemaLocation); } void DOMParser::setExternalNoNamespaceSchemaLocation(const char* const noNamespaceSchemaLocation) { fScanner->setExternalNoNamespaceSchemaLocation(noNamespaceSchemaLocation); } void DOMParser::cacheGrammarFromParse(const bool newState) { fScanner->cacheGrammarFromParse(newState); if (newState) fScanner->useCachedGrammarInParse(newState); } void DOMParser::useCachedGrammarInParse(const bool newState) { if (newState || !fScanner->isCachingGrammarFromParse()) fScanner->useCachedGrammarInParse(newState); } void DOMParser::setCalculateSrcOfs(const bool newState) { fScanner->setCalculateSrcOfs(newState); } void DOMParser::setStandardUriConformant(const bool newState) { fScanner->setStandardUriConformant(newState); } void DOMParser::useScanner(const XMLCh* const scannerName) { XMLScanner* tempScanner = XMLScannerResolver::resolveScanner ( scannerName , fValidator , fGrammarResolver , fMemoryManager ); if (tempScanner) { tempScanner->setParseSettings(fScanner); tempScanner->setURIStringPool(fURIStringPool); delete fScanner; fScanner = tempScanner; } } // --------------------------------------------------------------------------- // DOMParser: Parsing methods // --------------------------------------------------------------------------- void DOMParser::parse(const InputSource& source) { // Avoid multiple entrance if (fParseInProgress) ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager); try { fParseInProgress = true; fScanner->scanDocument(source); fParseInProgress = false; } catch(const OutOfMemoryException&) { throw; } catch(...) { fParseInProgress = false; throw; } } void DOMParser::parse(const XMLCh* const systemId) { // Avoid multiple entrance if (fParseInProgress) ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager); try { fParseInProgress = true; fScanner->scanDocument(systemId); fParseInProgress = false; } catch(const OutOfMemoryException&) { throw; } catch(...) { fParseInProgress = false; throw; } } void DOMParser::parse(const char* const systemId) { // Avoid multiple entrance if (fParseInProgress) ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager); try { fParseInProgress = true; fScanner->scanDocument(systemId); fParseInProgress = false; } catch(const OutOfMemoryException&) { throw; } catch(...) { fParseInProgress = false; throw; } } // --------------------------------------------------------------------------- // DOMParser: Progressive parse methods // --------------------------------------------------------------------------- bool DOMParser::parseFirst( const XMLCh* const systemId , XMLPScanToken& toFill) { // // Avoid multiple entrance. We cannot enter here while a regular parse // is in progress. // if (fParseInProgress) ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager); return fScanner->scanFirst(systemId, toFill); } bool DOMParser::parseFirst( const char* const systemId , XMLPScanToken& toFill) { // // Avoid multiple entrance. We cannot enter here while a regular parse // is in progress. // if (fParseInProgress) ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager); return fScanner->scanFirst(systemId, toFill); } bool DOMParser::parseFirst( const InputSource& source , XMLPScanToken& toFill) { // // Avoid multiple entrance. We cannot enter here while a regular parse // is in progress. // if (fParseInProgress) ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager); return fScanner->scanFirst(source, toFill); } bool DOMParser::parseNext(XMLPScanToken& token) { return fScanner->scanNext(token); } void DOMParser::parseReset(XMLPScanToken& token) { // Reset the scanner, and then reset the parser fScanner->scanReset(token); reset(); } // --------------------------------------------------------------------------- // DOMParser: Implementation of the XMLErrorReporter interface // --------------------------------------------------------------------------- void DOMParser::error( const unsigned int /*code*/ , const XMLCh* const /*msgDomain*/ , const XMLErrorReporter::ErrTypes errType , const XMLCh* const errorText , const XMLCh* const systemId , const XMLCh* const publicId , const XMLSSize_t lineNum , const XMLSSize_t colNum) { SAXParseException toThrow = SAXParseException ( errorText , publicId , systemId , lineNum , colNum , fMemoryManager ); // // If there is an error handler registered, call it, otherwise ignore // all but the fatal errors. // if (!fErrorHandler) { if (errType == XMLErrorReporter::ErrType_Fatal) throw toThrow; return; } if (errType == XMLErrorReporter::ErrType_Warning) fErrorHandler->warning(toThrow); else if (errType >= XMLErrorReporter::ErrType_Fatal) fErrorHandler->fatalError(toThrow); else fErrorHandler->error(toThrow); } void DOMParser::resetErrors() { } // --------------------------------------------------------------------------- // DOMParser: Implementation of XMLEntityHandler interface // --------------------------------------------------------------------------- InputSource* DOMParser::resolveEntity(const XMLCh* const publicId, const XMLCh* const systemId, const XMLCh* const /*baseURI*/) { // // Just map it to the SAX entity resolver. If there is not one installed, // return a null pointer to cause the default resolution. // if (fEntityResolver) return fEntityResolver->resolveEntity(publicId, systemId); return 0; } InputSource* DOMParser::resolveEntity(XMLResourceIdentifier* resourceIdentifier) { // // Just map it to the SAX entity resolver. If there is not one installed, // return a null pointer to cause the default resolution. // if (fEntityResolver) return fEntityResolver->resolveEntity(resourceIdentifier->getPublicId(), resourceIdentifier->getSystemId()); if (fXMLEntityResolver) return fXMLEntityResolver->resolveEntity(resourceIdentifier); return 0; } // --------------------------------------------------------------------------- // DOMParser: Implementation of XMLDocumentHandler interface // --------------------------------------------------------------------------- void DOMParser::docCharacters( const XMLCh* const chars , const unsigned int length , const bool cdataSection) { // Ignore chars outside of content if (!fWithinElement) return; if (cdataSection == true) { DOM_CDATASection node = fDocument.createCDATASection ( DOMString(chars, length) ); fCurrentParent.appendChild(node); fCurrentNode = node; } else { if (fCurrentNode.getNodeType() == DOM_Node::TEXT_NODE) { DOM_Text node = (DOM_Text&)fCurrentNode; node.appendData(DOMString(chars, length)); } else { DOM_Text node = fDocument.createTextNode(DOMString(chars, length)); fCurrentParent.appendChild(node); fCurrentNode = node; } } } void DOMParser::docComment(const XMLCh* const comment) { DOM_Comment dcom = fDocument.createComment(comment); fCurrentParent.appendChild(dcom); fCurrentNode = dcom; } void DOMParser::docPI( const XMLCh* const target , const XMLCh* const data) { DOM_ProcessingInstruction pi = fDocument.createProcessingInstruction ( target , data ); fCurrentParent.appendChild(pi); fCurrentNode = pi; } void DOMParser::endEntityReference(const XMLEntityDecl& entDecl) { if (fCreateEntityReferenceNodes == true) { if (fCurrentParent.getNodeType() == DOM_Node::ENTITY_REFERENCE_NODE) { // stick the parsed content of this entity reference into the entity definition node EntityImpl* entity = (EntityImpl*)fDocumentType->entities->getNamedItem(entDecl.getName()); entity->setEntityRef((EntityReferenceImpl*)fCurrentParent.fImpl); ((DOM_EntityReference&)fCurrentParent).fImpl->setReadOnly(true, true); } fCurrentParent = fNodeStack->pop(); fCurrentNode = fCurrentParent; } } void DOMParser::endElement( const XMLElementDecl& /*elemDecl*/ , const unsigned int /*urlId*/ , const bool /*isRoot*/ , const XMLCh* const /*elemPrefix*/) { fCurrentNode = fCurrentParent; fCurrentParent = fNodeStack->pop(); // If we've hit the end of content, clear the flag if (fNodeStack->empty()) fWithinElement = false; } void DOMParser::ignorableWhitespace(const XMLCh* const chars , const unsigned int length , const bool /*cdataSection*/) { // Ignore chars before the root element if (!fWithinElement || !fIncludeIgnorableWhitespace) return; if (fCurrentNode.getNodeType() == DOM_Node::TEXT_NODE) { DOM_Text node = (DOM_Text&)fCurrentNode; node.appendData(DOMString(chars, length)); } else { DOM_Text node = fDocument.createTextNode(DOMString(chars, length)); TextImpl *text = (TextImpl *) node.fImpl; text -> setIgnorableWhitespace(true); fCurrentParent.appendChild(node); fCurrentNode = node; } } void DOMParser::resetDocument() { // // The reset methods are called before a new parse event occurs. // Reset this parsers state to clear out anything that may be left // from a previous use, in particular the DOM document itself. // this->reset(); } void DOMParser::startDocument() { // Just set the document as the current parent and current node fCurrentParent = fDocument; fCurrentNode = fDocument; // set DOM error checking off fDocument.setErrorChecking(false); } void DOMParser::endDocument() { // set DOM error checking back on fDocument.setErrorChecking(true); } void DOMParser::startElement(const XMLElementDecl& elemDecl , const unsigned int urlId , const XMLCh* const elemPrefix , const RefVectorOf& attrList , const unsigned int attrCount , const bool isEmpty , const bool isRoot) { DOM_Element elem; DocumentImpl *docImpl = (DocumentImpl *)fDocument.fImpl; if (fScanner -> getDoNamespaces()) { //DOM Level 2, doNamespaces on XMLBuffer buf(1023, fMemoryManager); DOMString namespaceURI = 0; DOMString elemQName = 0; if (urlId != fScanner->getEmptyNamespaceId()) { //TagName has a prefix fScanner->getURIText(urlId, buf); //get namespaceURI namespaceURI = DOMString(buf.getRawBuffer()); if (elemPrefix && *elemPrefix) { elemQName.appendData(elemPrefix); elemQName.appendData(chColon); } } elemQName.appendData(elemDecl.getBaseName()); elem = fDocument.createElementNS(namespaceURI, elemQName); ElementImpl *elemImpl = (ElementImpl *) elem.fImpl; for (unsigned int index = 0; index < attrCount; ++index) { static const XMLCh XMLNS[] = { chLatin_x, chLatin_m, chLatin_l, chLatin_n, chLatin_s, chNull }; const XMLAttr* oneAttrib = attrList.elementAt(index); unsigned int attrURIId = oneAttrib -> getURIId(); namespaceURI = 0; if (!XMLString::compareString(oneAttrib -> getName(), XMLNS)) //for xmlns=... attrURIId = fScanner->getXMLNSNamespaceId(); if (attrURIId != fScanner->getEmptyNamespaceId()) { //TagName has a prefix fScanner->getURIText(attrURIId, buf); //get namespaceURI namespaceURI = DOMString(buf.getRawBuffer()); } AttrImpl *attr = elemImpl->setAttributeNS(namespaceURI, oneAttrib -> getQName(), oneAttrib -> getValue()); // Attributes of type ID. If this is one, add it to the hashtable of IDs // that is constructed for use by GetElementByID(). // if (oneAttrib->getType()==XMLAttDef::ID) { if (docImpl->fNodeIDMap == 0) docImpl->fNodeIDMap = new (fMemoryManager) NodeIDMap(500, fMemoryManager); docImpl->fNodeIDMap->add(attr); attr->isIdAttr(true); } attr->setSpecified(oneAttrib->getSpecified()); } } else { //DOM Level 1 elem = fDocument.createElement(elemDecl.getFullName()); ElementImpl *elemImpl = (ElementImpl *) elem.fImpl; for (unsigned int index = 0; index < attrCount; ++index) { const XMLAttr* oneAttrib = attrList.elementAt(index); AttrImpl *attr = elemImpl->setAttribute(oneAttrib->getName(), oneAttrib->getValue()); attr->setSpecified(oneAttrib->getSpecified()); // Attributes of type ID. If this is one, add it to the hashtable of IDs // that is constructed for use by GetElementByID(). // if (oneAttrib->getType()==XMLAttDef::ID) { if (docImpl->fNodeIDMap == 0) docImpl->fNodeIDMap = new (fMemoryManager) NodeIDMap(500, fMemoryManager); docImpl->fNodeIDMap->add(attr); attr->isIdAttr(true); } } } fCurrentParent.appendChild(elem); fNodeStack->push(fCurrentParent); fCurrentParent = elem; fCurrentNode = elem; fWithinElement = true; // If an empty element, do end right now (no endElement() will be called) if (isEmpty) endElement(elemDecl, urlId, isRoot, elemPrefix); } void DOMParser::startEntityReference(const XMLEntityDecl& entDecl) { if (fCreateEntityReferenceNodes == true) { DOMString entName(entDecl.getName()); DOM_EntityReference er = fDocument.createEntityReference(entName); //set the readOnly flag to false before appending node, will be reset in endEntityReference er.fImpl->setReadOnly(false, true); fCurrentParent.appendChild(er); fNodeStack->push(fCurrentParent); fCurrentParent = er; fCurrentNode = er; } } void DOMParser::XMLDecl(const XMLCh* const version , const XMLCh* const encoding , const XMLCh* const standalone , const XMLCh* const /*actualEncStr*/) { //This is a non-standard extension to creating XMLDecl type nodes and attching to DOM Tree // currently this flag it set to false unless user explicitly asks for it // Needs to be revisited after W3C specs are laid out on this issue. if (fToCreateXMLDeclTypeNode) { DOMString ver(version); DOMString enc(encoding); DOMString isStd(standalone); DOM_XMLDecl xmlDecl = fDocument.createXMLDecl(ver, enc, isStd); fCurrentParent.appendChild(xmlDecl); } } // --------------------------------------------------------------------------- // DOMParser: Deprecated methods // --------------------------------------------------------------------------- bool DOMParser::getDoValidation() const { // // We don't want to tie the public parser classes to the enum used // by the scanner, so we use a separate one and map. // // DON'T mix the new and old methods!! // const XMLScanner::ValSchemes scheme = fScanner->getValidationScheme(); if (scheme == XMLScanner::Val_Always) return true; return false; } void DOMParser::setDoValidation(const bool newState) { fScanner->setDoValidation ( newState ? XMLScanner::Val_Always : XMLScanner::Val_Never ); } //doctypehandler interfaces void DOMParser::attDef ( const DTDElementDecl& elemDecl , const DTDAttDef& attDef , const bool /*ignoring*/ ) { if (fDocumentType->isIntSubsetReading()) { DOMString attString; if (elemDecl.hasAttDefs()) { attString.appendData(chOpenAngle); attString.appendData(chBang); attString.appendData(XMLUni::fgAttListString); attString.appendData(chSpace); attString.appendData(elemDecl.getFullName()); attString.appendData(chSpace); attString.appendData(attDef.getFullName()); // Get the type and display it const XMLAttDef::AttTypes type = attDef.getType(); switch(type) { case XMLAttDef::CData : attString.appendData(chSpace); attString.appendData(XMLUni::fgCDATAString); break; case XMLAttDef::ID : attString.appendData(chSpace); attString.appendData(XMLUni::fgIDString); break; case XMLAttDef::IDRef : attString.appendData(chSpace); attString.appendData(XMLUni::fgIDRefString); break; case XMLAttDef::IDRefs : attString.appendData(chSpace); attString.appendData(XMLUni::fgIDRefsString); break; case XMLAttDef::Entity : attString.appendData(chSpace); attString.appendData(XMLUni::fgEntityString); break; case XMLAttDef::Entities : attString.appendData(chSpace); attString.appendData(XMLUni::fgEntitiesString); break; case XMLAttDef::NmToken : attString.appendData(chSpace); attString.appendData(XMLUni::fgNmTokenString); break; case XMLAttDef::NmTokens : attString.appendData(chSpace); attString.appendData(XMLUni::fgNmTokensString); break; case XMLAttDef::Notation : attString.appendData(chSpace); attString.appendData(XMLUni::fgNotationString); break; case XMLAttDef::Enumeration : { attString.appendData(chSpace); // attString.appendData(XMLUni::fgEnumerationString); const XMLCh* enumString = attDef.getEnumeration(); int length = XMLString::stringLen(enumString); if (length > 0) { DOMString anotherEnumString; anotherEnumString.appendData(chOpenParen ); for(int i=0; iinternalSubset.appendData(attString); } } } void DOMParser::doctypeComment ( const XMLCh* const comment ) { if (fDocumentType->isIntSubsetReading()) { if (comment != 0) { DOMString comString; comString.appendData(XMLUni::fgCommentString); comString.appendData(chSpace); comString.appendData(comment); comString.appendData(chSpace); comString.appendData(chDash); comString.appendData(chDash); comString.appendData(chCloseAngle); fDocumentType->internalSubset.appendData(comString); } } } void DOMParser::doctypeDecl ( const DTDElementDecl& elemDecl , const XMLCh* const publicId , const XMLCh* const systemId , const bool /*hasIntSubset*/ , const bool /*hasExtSubset*/ ) { DOM_DocumentType dt; dt = fDocument.getImplementation().createDocumentType(elemDecl.getFullName(), publicId, systemId); fDocumentType = (DocumentTypeImpl*)dt.fImpl; ((DocumentImpl*)fDocument.fImpl)->setDocumentType(fDocumentType); } void DOMParser::doctypePI ( const XMLCh* const target , const XMLCh* const data ) { if (fDocumentType->isIntSubsetReading()) { //add these chars to internalSubset variable DOMString pi; pi.appendData(chOpenAngle); pi.appendData(chQuestion); pi.appendData(target); pi.appendData(chSpace); pi.appendData(data); pi.appendData(chQuestion); pi.appendData(chCloseAngle); fDocumentType->internalSubset.appendData(pi); } } void DOMParser::doctypeWhitespace ( const XMLCh* const chars , const unsigned int /*length*/ ) { if (fDocumentType->isIntSubsetReading()) fDocumentType->internalSubset.appendData(chars); } void DOMParser::elementDecl ( const DTDElementDecl& decl , const bool /*isIgnored*/ ) { if (fDocumentType->isIntSubsetReading()) { DOMString elemDecl; elemDecl.appendData(chOpenAngle); elemDecl.appendData(chBang); elemDecl.appendData(XMLUni::fgElemString); elemDecl.appendData(chSpace); elemDecl.appendData(decl.getFullName()); //get the ContentSpec information const XMLCh* contentModel = decl.getFormattedContentModel(); if (contentModel != 0) { elemDecl.appendData(chSpace); elemDecl.appendData(contentModel); } elemDecl.appendData(chCloseAngle); fDocumentType->internalSubset.appendData(elemDecl); } } void DOMParser::endAttList ( const DTDElementDecl& elemDecl ) { // this section sets up default attributes. // default attribute nodes are stored in a NamedNodeMap DocumentTypeImpl::elements // default attribute data attached to the document is used to conform to the // DOM spec regarding creating element nodes & removing attributes with default values // see DocumentTypeImpl if (elemDecl.hasAttDefs()) { XMLAttDefList* defAttrs = &elemDecl.getAttDefList(); XMLAttDef* attr = 0; AttrImpl* insertAttr = 0; DOM_Element dom_elem = fDocument.createElement(elemDecl.getFullName()); ElementImpl* elem = (ElementImpl*)(dom_elem.fImpl); for(unsigned int i=0; igetAttDefCount(); i++) { attr = &defAttrs->getAttDef(i); if (attr->getValue() != null) { if (fScanner->getDoNamespaces()) { // DOM Level 2 wants all namespace declaration attributes // to be bound to "http://www.w3.org/2000/xmlns/" // So as long as the XML parser doesn't do it, it needs to // done here. DOMString qualifiedName = attr->getFullName(); int index = DocumentImpl::indexofQualifiedName(qualifiedName); XMLBuffer buf(1023, fMemoryManager); static const XMLCh XMLNS[] = { chLatin_x, chLatin_m, chLatin_l, chLatin_n, chLatin_s, chNull}; if (index > 0) { // there is prefix // map to XML URI for all cases except when prefix == "xmlns" DOMString prefix = qualifiedName.substringData(0, index); if (prefix.equals(XMLNS)) buf.append(XMLUni::fgXMLNSURIName); else buf.append(XMLUni::fgXMLURIName); } else { // No prefix if (qualifiedName.equals(XMLNS)) buf.append(XMLUni::fgXMLNSURIName); } insertAttr = new (fMemoryManager) AttrNSImpl((DocumentImpl*)fDocument.fImpl, DOMString(buf.getRawBuffer()), // NameSpaceURI qualifiedName); // qualified name } else { // Namespaces is turned off... insertAttr = new (fMemoryManager) AttrImpl((DocumentImpl*)fDocument.fImpl, attr->getFullName()); } insertAttr->setValue(attr->getValue()); // memory leak here AttrImpl * previousAttr = elem->setAttributeNode(insertAttr); if ( previousAttr != 0 && previousAttr->nodeRefCount ==0) NodeImpl::deleteIf(previousAttr); insertAttr->setSpecified(false); } } ElementImpl *previousElem = (ElementImpl *) fDocumentType->getElements()->setNamedItem( elem ); // // If this new element is replacing an element node that was already // in the element named node map, we need to delete the original // element node, assuming no-one else was referencing it. // if (previousElem != 0 && previousElem->nodeRefCount == 0) NodeImpl::deleteIf(previousElem); } } void DOMParser::endIntSubset() { fDocumentType->intSubsetReading = false; } void DOMParser::endExtSubset() { } void DOMParser::entityDecl ( const DTDEntityDecl& entityDecl , const bool /*isPEDecl*/ , const bool /*isIgnored*/ ) { EntityImpl* entity = ((DocumentImpl*)fDocument.fImpl)->createEntity(entityDecl.getName()); entity->setPublicId(entityDecl.getPublicId()); entity->setSystemId(entityDecl.getSystemId()); entity->setNotationName(entityDecl.getNotationName()); EntityImpl *previousDef = (EntityImpl *) fDocumentType->entities->setNamedItem( entity ); // // If this new entity node is replacing an entity node that was already // in the entities named node map (happens if documents redefine the // predefined entited such as lt), we need to delete the original // entitiy node, assuming no-one else was referencing it. // if (previousDef != 0 && previousDef->nodeRefCount == 0) NodeImpl::deleteIf(previousDef); if (fDocumentType->isIntSubsetReading()) { //add thes chars to internalSubset variable DOMString entityName; entityName.appendData(chOpenAngle); entityName.appendData(chBang); entityName.appendData(XMLUni::fgEntityString); entityName.appendData(chSpace); entityName.appendData(entityDecl.getName()); DOMString id = entity->getPublicId(); if (id != 0) { entityName.appendData(chSpace); entityName.appendData(XMLUni::fgPubIDString); entityName.appendData(chSpace); entityName.appendData(chDoubleQuote); entityName.appendData(id); entityName.appendData(chDoubleQuote); } id = entity->getSystemId(); if (id != 0) { entityName.appendData(chSpace); entityName.appendData(XMLUni::fgSysIDString); entityName.appendData(chSpace); entityName.appendData(chDoubleQuote); entityName.appendData(id); entityName.appendData(chDoubleQuote); } id = entity->getNotationName(); if (id != 0) { entityName.appendData(chSpace); entityName.appendData(XMLUni::fgNDATAString); entityName.appendData(chSpace); entityName.appendData(chDoubleQuote); entityName.appendData(id); entityName.appendData(chDoubleQuote); } id = entityDecl.getValue(); if (id !=0) { entityName.appendData(chSpace); entityName.appendData(chDoubleQuote); entityName.appendData(id); entityName.appendData(chDoubleQuote); } entityName.appendData(chCloseAngle); fDocumentType->internalSubset.appendData(entityName); } } void DOMParser::resetDocType() { fDocumentType = null; } void DOMParser::notationDecl ( const XMLNotationDecl& notDecl , const bool /*isIgnored*/ ) { NotationImpl* notation = ((DocumentImpl*)fDocument.fImpl)->createNotation(notDecl.getName()); notation->setPublicId(notDecl.getPublicId()); notation->setSystemId(notDecl.getSystemId()); NotationImpl *previousNot = (NotationImpl *) fDocumentType->notations->setNamedItem( notation ); // // If this new notation is replacing a notation node that was already // in the notation named node map, we need to delete the original // notation node, assuming no-one else was referencing it. // if (previousNot != 0 && previousNot->nodeRefCount == 0) NodeImpl::deleteIf(previousNot); } void DOMParser::startAttList ( const DTDElementDecl& /*elemDecl*/ ) { } void DOMParser::startIntSubset() { fDocumentType->intSubsetReading = true; } void DOMParser::startExtSubset() { } void DOMParser::TextDecl ( const XMLCh* const /*versionStr*/ , const XMLCh* const /*encodingStr*/ ) { } // --------------------------------------------------------------------------- // DOMParser: Grammar preparsing methods // --------------------------------------------------------------------------- Grammar* DOMParser::loadGrammar(const char* const systemId, const short grammarType, const bool toCache) { // Avoid multiple entrance if (fParseInProgress) ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager); Grammar* grammar = 0; try { fParseInProgress = true; grammar = fScanner->loadGrammar(systemId, grammarType, toCache); fParseInProgress = false; } catch(const OutOfMemoryException&) { throw; } catch(...) { fParseInProgress = false; throw; } return grammar; } Grammar* DOMParser::loadGrammar(const XMLCh* const systemId, const short grammarType, const bool toCache) { // Avoid multiple entrance if (fParseInProgress) ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager); Grammar* grammar = 0; try { fParseInProgress = true; grammar = fScanner->loadGrammar(systemId, grammarType, toCache); fParseInProgress = false; } catch(const OutOfMemoryException&) { throw; } catch(...) { fParseInProgress = false; throw; } return grammar; } Grammar* DOMParser::loadGrammar(const InputSource& source, const short grammarType, const bool toCache) { // Avoid multiple entrance if (fParseInProgress) ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager); Grammar* grammar = 0; try { fParseInProgress = true; grammar = fScanner->loadGrammar(source, grammarType, toCache); fParseInProgress = false; } catch(const OutOfMemoryException&) { throw; } catch(...) { fParseInProgress = false; throw; } return grammar; } void DOMParser::resetCachedGrammarPool() { fGrammarResolver->resetCachedGrammar(); } XERCES_CPP_NAMESPACE_END