Skip to content
Snippets Groups Projects
AbstractDOMParser.cpp 50.9 KiB
Newer Older
Khaled Noaman's avatar
Khaled Noaman committed
/*
 * The Apache Software License, Version 1.1
 *
Neil Graham's avatar
Neil Graham committed
 * Copyright (c) 2002,2003 The Apache Software Foundation.  All rights
Khaled Noaman's avatar
Khaled Noaman committed
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 2001, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/**
*  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$
*
*/



// ---------------------------------------------------------------------------
//  Includes
// ---------------------------------------------------------------------------
Khaled Noaman's avatar
Khaled Noaman committed
#include <xercesc/parsers/AbstractDOMParser.hpp>
#include <xercesc/internal/XMLScannerResolver.hpp>
#include <xercesc/internal/ElemStack.hpp>
Khaled Noaman's avatar
Khaled Noaman committed
#include <xercesc/sax/EntityResolver.hpp>
#include <xercesc/util/XMLUniDefs.hpp>
#include <xercesc/framework/XMLNotationDecl.hpp>
Khaled Noaman's avatar
Khaled Noaman committed
#include <xercesc/framework/XMLValidator.hpp>
Khaled Noaman's avatar
Khaled Noaman committed
#include <xercesc/util/IOException.hpp>
#include <xercesc/dom/DOMImplementation.hpp>
#include <xercesc/dom/DOMElement.hpp>
#include <xercesc/dom/impl/DOMAttrImpl.hpp>
#include <xercesc/dom/DOMCDATASection.hpp>
#include <xercesc/dom/DOMComment.hpp>
#include <xercesc/dom/impl/DOMTextImpl.hpp>
#include <xercesc/dom/impl/DOMDocumentImpl.hpp>
#include <xercesc/dom/impl/DOMDocumentTypeImpl.hpp>
#include <xercesc/dom/DOMDocumentType.hpp>
#include <xercesc/dom/impl/DOMElementImpl.hpp>
#include <xercesc/dom/impl/DOMEntityImpl.hpp>
#include <xercesc/dom/impl/DOMEntityReferenceImpl.hpp>
#include <xercesc/dom/impl/DOMNotationImpl.hpp>
#include <xercesc/dom/DOMNamedNodeMap.hpp>
#include <xercesc/dom/DOMProcessingInstruction.hpp>
Tinny Ng's avatar
Tinny Ng committed
#include <xercesc/dom/impl/DOMProcessingInstructionImpl.hpp>
Khaled Noaman's avatar
Khaled Noaman committed
#include <xercesc/dom/impl/DOMNodeIDMap.hpp>
#include <xercesc/validators/common/ContentSpecNode.hpp>
Khaled Noaman's avatar
Khaled Noaman committed
#include <xercesc/validators/common/GrammarResolver.hpp>
#include <xercesc/validators/schema/SchemaSymbols.hpp>
Tinny Ng's avatar
Tinny Ng committed
XERCES_CPP_NAMESPACE_BEGIN


Khaled Noaman's avatar
Khaled Noaman committed
// ---------------------------------------------------------------------------
//  AbstractDOMParser: Constructors and Destructor
// ---------------------------------------------------------------------------
AbstractDOMParser::AbstractDOMParser( XMLValidator* const valToAdopt
                                    , MemoryManager* const manager) :
Khaled Noaman's avatar
Khaled Noaman committed

  fCreateEntityReferenceNodes(true)
, fIncludeIgnorableWhitespace(true)
, fWithinElement(false)
, fParseInProgress(false)
Khaled Noaman's avatar
Khaled Noaman committed
, fCreateCommentNodes(true)
, fDocumentAdoptedByUser(false)
Khaled Noaman's avatar
Khaled Noaman committed
, fScanner(0)
, fCurrentParent(0)
, fCurrentNode(0)
Tinny Ng's avatar
Tinny Ng committed
, fCurrentEntity(0)
Khaled Noaman's avatar
Khaled Noaman committed
, fDocument(0)
, fNodeStack(0)
, fDocumentType(0)
, fDocumentVector(0)
Khaled Noaman's avatar
Khaled Noaman committed
, fGrammarResolver(0)
, fURIStringPool(0)
, fValidator(valToAdopt)
, fMemoryManager(manager)
, fBufMgr(manager)
, fInternalSubset(fBufMgr.bidOnBuffer())
Khaled Noaman's avatar
Khaled Noaman committed
{
Khaled Noaman's avatar
Khaled Noaman committed
    try
    {
        initialize();
    }
    catch(...)
    {
       cleanUp();
       throw;
    }
}


AbstractDOMParser::~AbstractDOMParser()
{
    cleanUp();
}

// ---------------------------------------------------------------------------
//  AbstractDOMParser: Initialize/CleanUp methods
// ---------------------------------------------------------------------------
void AbstractDOMParser::initialize()
{
    //  Create grammar resolver and string pool to pass to the scanner
    fGrammarResolver = new (fMemoryManager) GrammarResolver(fMemoryManager);
    fURIStringPool = new (fMemoryManager) XMLStringPool(109, fMemoryManager);
Khaled Noaman's avatar
Khaled Noaman committed
    //  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, fMemoryManager);
Khaled Noaman's avatar
Khaled Noaman committed
    fScanner->setDocHandler(this);
    fScanner->setDocTypeHandler(this);
Khaled Noaman's avatar
Khaled Noaman committed
    fScanner->setGrammarResolver(fGrammarResolver);
    fScanner->setURIStringPool(fURIStringPool);
    fNodeStack = new (fMemoryManager) ValueStackOf<DOMNode*>(64, fMemoryManager);
Khaled Noaman's avatar
Khaled Noaman committed
void AbstractDOMParser::cleanUp()
Khaled Noaman's avatar
Khaled Noaman committed
{
    if (fDocumentVector)
        delete fDocumentVector;

PeiYong Zhang's avatar
PeiYong Zhang committed
    if (!fDocumentAdoptedByUser && fDocument)
        fDocument->release();
Khaled Noaman's avatar
Khaled Noaman committed
    delete fNodeStack;
    delete fScanner;
Khaled Noaman's avatar
Khaled Noaman committed
    delete fGrammarResolver;
    delete fURIStringPool;
Khaled Noaman's avatar
Khaled Noaman committed
    if (fValidator)
        delete fValidator;
}
Tinny Ng's avatar
Tinny Ng committed
// ---------------------------------------------------------------------------
//  AbstractDOMParser: Utilities
Tinny Ng's avatar
Tinny Ng committed
// ---------------------------------------------------------------------------
Khaled Noaman's avatar
Khaled Noaman committed
void AbstractDOMParser::reset()
{
    // if fDocument exists already, store the old pointer in the vector for deletion later
Tinny Ng's avatar
Tinny Ng committed
    if (fDocument && !fDocumentAdoptedByUser) {
Khaled Noaman's avatar
Khaled Noaman committed
        if (!fDocumentVector) {
            // allocate the vector if not exists yet
            fDocumentVector  = new (fMemoryManager) RefVectorOf<DOMDocumentImpl>(10, true, fMemoryManager) ;
Khaled Noaman's avatar
Khaled Noaman committed
        }
        fDocumentVector->addElement(fDocument);
    }

    fDocument = 0;
    resetDocType();

    fCurrentParent   = 0;
    fCurrentNode     = 0;
Tinny Ng's avatar
Tinny Ng committed
    fCurrentEntity   = 0;
Khaled Noaman's avatar
Khaled Noaman committed
    fParseInProgress = false;
    fWithinElement   = false;
Tinny Ng's avatar
Tinny Ng committed
    fDocumentAdoptedByUser = false;
Khaled Noaman's avatar
Khaled Noaman committed
    fNodeStack->removeAllElements();
    fInternalSubset.reset();
Tinny Ng's avatar
Tinny Ng committed
void AbstractDOMParser::resetPool()
{
    //  We cannot enter here while a regular parse is in progress.
    if (fParseInProgress)
        ThrowXML(IOException, XMLExcepts::Gen_ParseInProgress);

    if (fDocumentVector)
        fDocumentVector->removeAllElements();

     if (!fDocumentAdoptedByUser)
       delete fDocument;

Tinny Ng's avatar
Tinny Ng committed
    fDocument = 0;
}

bool AbstractDOMParser::isDocumentAdopted() const
{
    return fDocumentAdoptedByUser;
}
Tinny Ng's avatar
Tinny Ng committed

DOMDocument* AbstractDOMParser::adoptDocument()
{
    fDocumentAdoptedByUser = true;
    return fDocument;
}

Khaled Noaman's avatar
Khaled Noaman committed

// ---------------------------------------------------------------------------
//  AbstractDOMParser: Getter methods
// ---------------------------------------------------------------------------
DOMDocument* AbstractDOMParser::getDocument()
{
    return fDocument;
}

const XMLValidator& AbstractDOMParser::getValidator() const
{
    return *fScanner->getValidator();
}

bool AbstractDOMParser::getDoNamespaces() const
{
    return fScanner->getDoNamespaces();
}

bool AbstractDOMParser::getExitOnFirstFatalError() const
{
    return fScanner->getExitOnFirstFatal();
}

bool AbstractDOMParser::getValidationConstraintFatal() const
{
    return fScanner->getValidationConstraintFatal();
}

AbstractDOMParser::ValSchemes AbstractDOMParser::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 AbstractDOMParser::getDoSchema() const
{
    return fScanner->getDoSchema();
}

bool AbstractDOMParser::getValidationSchemaFullChecking() const
{
    return fScanner->getValidationSchemaFullChecking();
}

int AbstractDOMParser::getErrorCount() const
{
    return fScanner->getErrorCount();
}

XMLCh* AbstractDOMParser::getExternalSchemaLocation() const
{
    return fScanner->getExternalSchemaLocation();
}

XMLCh* AbstractDOMParser::getExternalNoNamespaceSchemaLocation() const
{
    return fScanner->getExternalNoNamespaceSchemaLocation();
}

Neil Graham's avatar
Neil Graham committed
SecurityManager* AbstractDOMParser::getSecurityManager() const
{
    return fScanner->getSecurityManager();
}

bool AbstractDOMParser::getLoadExternalDTD() const
{
    return fScanner->getLoadExternalDTD();
}

Khaled Noaman's avatar
Khaled Noaman committed
bool AbstractDOMParser::getCalculateSrcOfs() const
{
    return fScanner->getCalculateSrcOfs();
}

bool AbstractDOMParser::getStandardUriConformant() const
{
    return fScanner->getStandardUriConformant();
}

Khaled Noaman's avatar
Khaled Noaman committed
// ---------------------------------------------------------------------------
//  AbstractDOMParser: Setter methods
// ---------------------------------------------------------------------------
void AbstractDOMParser::setDoNamespaces(const bool newState)
{
    fScanner->setDoNamespaces(newState);
}

void AbstractDOMParser::setExitOnFirstFatalError(const bool newState)
{
    fScanner->setExitOnFirstFatal(newState);
}

void AbstractDOMParser::setValidationConstraintFatal(const bool newState)
{
    fScanner->setValidationConstraintFatal(newState);
}

void AbstractDOMParser::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 AbstractDOMParser::setDoSchema(const bool newState)
{
    fScanner->setDoSchema(newState);
}

void AbstractDOMParser::setValidationSchemaFullChecking(const bool schemaFullChecking)
{
    fScanner->setValidationSchemaFullChecking(schemaFullChecking);
}

void AbstractDOMParser::setExternalSchemaLocation(const XMLCh* const schemaLocation)
{
    fScanner->setExternalSchemaLocation(schemaLocation);
}
void AbstractDOMParser::setExternalNoNamespaceSchemaLocation(const XMLCh* const noNamespaceSchemaLocation)
{
    fScanner->setExternalNoNamespaceSchemaLocation(noNamespaceSchemaLocation);
}

void AbstractDOMParser::setExternalSchemaLocation(const char* const schemaLocation)
{
    fScanner->setExternalSchemaLocation(schemaLocation);
}
void AbstractDOMParser::setExternalNoNamespaceSchemaLocation(const char* const noNamespaceSchemaLocation)
{
    fScanner->setExternalNoNamespaceSchemaLocation(noNamespaceSchemaLocation);
}

Neil Graham's avatar
Neil Graham committed
void AbstractDOMParser::setSecurityManager(SecurityManager* const securityManager)
{
    // since this could impact various components, don't permit it to change
    // during a parse
    if (fParseInProgress)
        ThrowXML(IOException, XMLExcepts::Gen_ParseInProgress);

    fScanner->setSecurityManager(securityManager);
}

void AbstractDOMParser::setLoadExternalDTD(const bool newState)
{
    fScanner->setLoadExternalDTD(newState);
}

Khaled Noaman's avatar
Khaled Noaman committed
void AbstractDOMParser::setCalculateSrcOfs(const bool newState)
{
    fScanner->setCalculateSrcOfs(newState);
}

void AbstractDOMParser::setStandardUriConformant(const bool newState)
{
    fScanner->setStandardUriConformant(newState);
}

Khaled Noaman's avatar
Khaled Noaman committed
void AbstractDOMParser::useScanner(const XMLCh* const scannerName)
{
    XMLScanner* tempScanner = XMLScannerResolver::resolveScanner
    (
        scannerName
        , fValidator
        , fMemoryManager
    );
Khaled Noaman's avatar
Khaled Noaman committed

    if (tempScanner) {

        tempScanner->setParseSettings(fScanner);
        tempScanner->setGrammarResolver(fGrammarResolver);
        tempScanner->setURIStringPool(fURIStringPool);
Khaled Noaman's avatar
Khaled Noaman committed
        delete fScanner;
        fScanner = tempScanner;
    }
}
Khaled Noaman's avatar
Khaled Noaman committed

// ---------------------------------------------------------------------------
//  AbstractDOMParser: Parsing methods
// ---------------------------------------------------------------------------
void AbstractDOMParser::parse(const InputSource& source)
Khaled Noaman's avatar
Khaled Noaman committed
{
    // Avoid multiple entrance
    if (fParseInProgress)
        ThrowXML(IOException, XMLExcepts::Gen_ParseInProgress);

    try
    {
        fParseInProgress = true;
        fScanner->scanDocument(source);
Khaled Noaman's avatar
Khaled Noaman committed
        fParseInProgress = false;
    }

    catch(...)
    {
        fParseInProgress = false;
        throw;
    }
}

void AbstractDOMParser::parse(const XMLCh* const systemId)
Khaled Noaman's avatar
Khaled Noaman committed
{
    // Avoid multiple entrance
    if (fParseInProgress)
        ThrowXML(IOException, XMLExcepts::Gen_ParseInProgress);

    try
    {
        fParseInProgress = true;
        fScanner->scanDocument(systemId);
Khaled Noaman's avatar
Khaled Noaman committed
        fParseInProgress = false;
    }

    catch(...)
    {
        fParseInProgress = false;
        throw;
    }
}

void AbstractDOMParser::parse(const char* const systemId)
Khaled Noaman's avatar
Khaled Noaman committed
{
    // Avoid multiple entrance
    if (fParseInProgress)
        ThrowXML(IOException, XMLExcepts::Gen_ParseInProgress);

    try
    {
        fParseInProgress = true;
        fScanner->scanDocument(systemId);
Khaled Noaman's avatar
Khaled Noaman committed
        fParseInProgress = false;
    }

    catch(...)
    {
        fParseInProgress = false;
        throw;
    }
}



// ---------------------------------------------------------------------------
//  AbstractDOMParser: Progressive parse methods
// ---------------------------------------------------------------------------
bool AbstractDOMParser::parseFirst( const XMLCh* const    systemId
                                   ,       XMLPScanToken&  toFill)
Khaled Noaman's avatar
Khaled Noaman committed
{
    //
    //  Avoid multiple entrance. We cannot enter here while a regular parse
    //  is in progress.
    //
    if (fParseInProgress)
        ThrowXML(IOException, XMLExcepts::Gen_ParseInProgress);

    return fScanner->scanFirst(systemId, toFill);
Khaled Noaman's avatar
Khaled Noaman committed
}

bool AbstractDOMParser::parseFirst( const char* const         systemId
                                   ,       XMLPScanToken&      toFill)
Khaled Noaman's avatar
Khaled Noaman committed
{
    //
    //  Avoid multiple entrance. We cannot enter here while a regular parse
    //  is in progress.
    //
    if (fParseInProgress)
        ThrowXML(IOException, XMLExcepts::Gen_ParseInProgress);

    return fScanner->scanFirst(systemId, toFill);
Khaled Noaman's avatar
Khaled Noaman committed
}

bool AbstractDOMParser::parseFirst( const InputSource& source
                                   ,       XMLPScanToken&  toFill)
Khaled Noaman's avatar
Khaled Noaman committed
{
    //
    //  Avoid multiple entrance. We cannot enter here while a regular parse
    //  is in progress.
    //
    if (fParseInProgress)
        ThrowXML(IOException, XMLExcepts::Gen_ParseInProgress);

    return fScanner->scanFirst(source, toFill);
Khaled Noaman's avatar
Khaled Noaman committed
}

bool AbstractDOMParser::parseNext(XMLPScanToken& token)
{
    return fScanner->scanNext(token);
}

void AbstractDOMParser::parseReset(XMLPScanToken& token)
{
    // Reset the scanner, and then reset the parser
    fScanner->scanReset(token);
    reset();
}



// ---------------------------------------------------------------------------
//  AbstractDOMParser: Implementation of XMLDocumentHandler interface
// ---------------------------------------------------------------------------
void AbstractDOMParser::docCharacters(  const   XMLCh* const    chars
                              , const unsigned int    length
                              , const bool            cdataSection)
{
    // Ignore chars outside of content
    if (!fWithinElement)
        return;

    // revisit.  Is it really safe to null-terminate here?
    //                Does the scanner do it already?
    //                If scanner goes up to the very end of an unterminated
    //                buffer, we may be stepping on something bad here.
    //           Probably best to modify the scanner to null terminate.
    XMLCh savedChar = chars[length];
    XMLCh *ncChars  = (XMLCh *)chars;   // cast off const
    ncChars[length] = 0;
    if (cdataSection == true)
    {
        DOMCDATASection *node = fDocument->createCDATASection(chars);
        fCurrentParent->appendChild(node);
        fCurrentNode = node;
    }
    else
    {
        if (fCurrentNode->getNodeType() == DOMNode::TEXT_NODE)
        {
            DOMText *node = (DOMText *)fCurrentNode;
            node->appendData(chars);
        }
        else
        {
            DOMText *node = fDocument->createTextNode(chars);
            fCurrentParent->appendChild(node);
            fCurrentNode = node;
        }
    }
    ncChars[length] = savedChar;
    return;
}


void AbstractDOMParser::docComment(const XMLCh* const comment)
{
    if (fCreateCommentNodes) {
        DOMComment *dcom = fDocument->createComment(comment);
        fCurrentParent->appendChild(dcom);
        fCurrentNode = dcom;
    }
Khaled Noaman's avatar
Khaled Noaman committed
}


void AbstractDOMParser::docPI(  const   XMLCh* const    target
                      , const XMLCh* const    data)
{
    DOMProcessingInstruction *pi = fDocument->createProcessingInstruction
        (
        target
        , data
        );
    fCurrentParent->appendChild(pi);
    fCurrentNode = pi;
}


void AbstractDOMParser::endEntityReference(const XMLEntityDecl& entDecl)
{
    DOMEntityReferenceImpl *erImpl = 0;
    DOMNode* firstChild = 0;

    if (fCurrentParent->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE) {
        erImpl = (DOMEntityReferenceImpl *) fCurrentParent;
        firstChild = erImpl->getFirstChild();
    }

    fCurrentParent = fNodeStack->pop();

    if (!fCreateEntityReferenceNodes && erImpl && firstChild) {
        DOMNode *kid, *next;
        fCurrentNode   = fCurrentParent->getLastChild();

        for (kid = firstChild; kid != 0; kid = next)
        {
            // If kid and fCurrentNode are both Text nodes (but _not_ CDATASection,
            // which is a subclass of Text), they can be merged.
            if (kid->getNodeType() == DOMNode::TEXT_NODE   &&
                fCurrentNode &&
                fCurrentNode->getNodeType() == DOMNode::TEXT_NODE )
            {
                ((DOMTextImpl *) fCurrentNode)->appendData(((DOMTextImpl *) kid)->getData());
            }
            else {
                // append the child of erImpl to currentParent
                fCurrentNode = kid->cloneNode(true);
                fCurrentParent->appendChild(fCurrentNode);
Tinny Ng's avatar
Tinny Ng committed

                if (erImpl->getBaseURI()) {
                    /**
                     * Record baseURI information for the Element (by adding xml:base attribute)
                     * or for the ProcessingInstruction (by setting a baseURI field)
                     */
                    if (fCurrentNode->getNodeType() == DOMNode::ELEMENT_NODE) {
                        // if an element already has xml:base attribute
                        // do nothing
                        const XMLCh baseString[] =
                        {
                            chLatin_b, chLatin_a, chLatin_s, chLatin_e, chNull
                        };
                        const XMLCh xmlBaseString[] =
                        {
                            chLatin_x, chLatin_m, chLatin_l, chColon, chLatin_b, chLatin_a, chLatin_s, chLatin_e, chNull
                        };

                        if (fScanner -> getDoNamespaces() && (((DOMElement*)fCurrentNode)->getAttributeNodeNS(DOMNodeImpl::getXmlURIString(), baseString) != 0)) {
                            return;
                        } else if (((DOMElement*)fCurrentNode)->getAttributeNode(xmlBaseString) != 0) {
                            return;
                        }

                        // retrive the baseURI from the entity decl
                        const XMLCh* baseURI = erImpl->getBaseURI();
                        if (baseURI != 0 && !XMLString::equals(baseURI,fDocument->getDocumentURI())) {
Tinny Ng's avatar
Tinny Ng committed
                            if (fScanner -> getDoNamespaces()) {
                                ((DOMElement*)fCurrentNode)->setAttributeNS(DOMNodeImpl::getXmlURIString(), baseString, baseURI);
                            } else {
                                ((DOMElement*)fCurrentNode)->setAttribute(xmlBaseString, baseURI);
                            }
                        }
                    }
                    else if (fCurrentNode->getNodeType() == DOMNode::PROCESSING_INSTRUCTION_NODE) {
                        ((DOMProcessingInstructionImpl*)fCurrentNode)->setBaseURI(erImpl->getBaseURI());
                    }
                }
    else
        fCurrentNode   = fCurrentParent;

    if (erImpl)
        erImpl->setReadOnly(true, true);
Khaled Noaman's avatar
Khaled Noaman committed
}


void AbstractDOMParser::endElement( const   XMLElementDecl&     elemDecl
                           , const unsigned int        urlId
                           , const bool                isRoot
                           , const XMLCh* const        elemPrefix)
Khaled Noaman's avatar
Khaled Noaman committed
{
    fCurrentNode   = fCurrentParent;
    fCurrentParent = fNodeStack->pop();

    //validation is performed after the startElement event so we have to associate the info here
    ((DOMElementImpl *)(fCurrentNode))->setTypeInfo(elemDecl.getDOMTypeInfoName(), elemDecl.getDOMTypeInfoUri());


Khaled Noaman's avatar
Khaled Noaman committed
    // If we've hit the end of content, clear the flag
    if (fNodeStack->empty())
        fWithinElement = false;
}


void AbstractDOMParser::ignorableWhitespace(const   XMLCh* const    chars
                                    , const unsigned int    length
                                    , const bool            cdataSection)
{
    // Ignore chars before the root element
    if (!fWithinElement || !fIncludeIgnorableWhitespace)
        return;

    // revisit.  Not safe to slam in a null like this.
    XMLCh savedChar = chars[length];
    XMLCh *ncChars  = (XMLCh *)chars;   // cast off const
    ncChars[length] = chNull;

    if (fCurrentNode->getNodeType() == DOMNode::TEXT_NODE)
    {
        DOMText *node = (DOMText *)fCurrentNode;
        node->appendData(chars);
    }
    else
    {
        DOMTextImpl *node = (DOMTextImpl *)fDocument->createTextNode(chars);
        node->setIgnorableWhitespace(true);
        fCurrentParent->appendChild(node);

        fCurrentNode = node;
    }
    ncChars[length] = savedChar;
}


void AbstractDOMParser::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 AbstractDOMParser::startDocument()
{
    fDocument = (DOMDocumentImpl *)DOMImplementation::getImplementation()->createDocument();
Khaled Noaman's avatar
Khaled Noaman committed
    // Just set the document as the current parent and current node
    fCurrentParent = fDocument;
    fCurrentNode   = fDocument;
    // set DOM error checking off
    fDocument->setErrorChecking(false);
    fDocument->setDocumentURI(fScanner->getLocator()->getSystemId());
Tinny Ng's avatar
Tinny Ng committed
    fDocument->setActualEncoding(fScanner->getReaderMgr()->getCurrentEncodingStr());
Khaled Noaman's avatar
Khaled Noaman committed
}


void AbstractDOMParser::endDocument()
{
    // set DOM error checking back on
    fDocument->setErrorChecking(true);

    // DOM L2 does not support editing DocumentType nodes
    if (fDocumentType && fScanner -> getDoNamespaces())
        fDocumentType->setReadOnly(true, true);
Khaled Noaman's avatar
Khaled Noaman committed
}


void AbstractDOMParser::startElement(const  XMLElementDecl&         elemDecl
                             , const unsigned int            urlId
                             , const XMLCh* const            elemPrefix
                             , const RefVectorOf<XMLAttr>&   attrList
                             , const unsigned int            attrCount
                             , const bool                    isEmpty
                             , const bool                    isRoot)
{
    DOMElement     *elem;
    static const XMLCh XMLNS[] = {
    chLatin_x, chLatin_m, chLatin_l, chLatin_n, chLatin_s, chNull
    };
    static const XMLCh XSI[] = {
    chLatin_x, chLatin_s, chLatin_i, chNull
    };
    //get the list for use in the loop
    XMLAttDefList* defAttrs = 0;
    if(elemDecl.hasAttDefs()) {
        defAttrs = &elemDecl.getAttDefList();
    }

    if (fScanner -> getDoNamespaces()) {    //DOM Level 2, doNamespaces on
        const XMLCh* namespaceURI = 0;
Khaled Noaman's avatar
Khaled Noaman committed
        if (urlId != fScanner->getEmptyNamespaceId()) {  //TagName has a prefix

            namespaceURI = fScanner->getURIText(urlId); //get namespaceURI

            if (elemPrefix && *elemPrefix) {

                XMLBufBid elemQName(&fBufMgr);

                elemQName.set(elemPrefix);
                elemQName.append(chColon);
                elemQName.append(elemDecl.getBaseName());
                elem = createElementNSNode(namespaceURI, elemQName.getRawBuffer());
            }
            else { 
                elem = createElementNSNode(namespaceURI, elemDecl.getBaseName());
        } 
        else {
            elem = createElementNSNode(namespaceURI, elemDecl.getBaseName());
Khaled Noaman's avatar
Khaled Noaman committed
        }
        elemImpl = (DOMElementImpl *) elem;
Khaled Noaman's avatar
Khaled Noaman committed
        for (unsigned int index = 0; index < attrCount; ++index) {
            const XMLAttr* oneAttrib = attrList.elementAt(index);
            unsigned int attrURIId = oneAttrib -> getURIId();
            namespaceURI = 0;
            if (XMLString::equals(oneAttrib -> getName(), XMLNS))    //for xmlns=...
Khaled Noaman's avatar
Khaled Noaman committed
                attrURIId = fScanner->getXMLNSNamespaceId();
            if (attrURIId != fScanner->getEmptyNamespaceId()) {  //TagName has a prefix
                namespaceURI = fScanner->getURIText(attrURIId);   //get namespaceURI
Khaled Noaman's avatar
Khaled Noaman committed
            }
            //  revisit.  Optimize to init the named node map to the
            //            right size up front.
            DOMAttrImpl *attr = (DOMAttrImpl *)
                fDocument->createAttributeNS(namespaceURI, oneAttrib->getQName());
            attr->setValue(oneAttrib -> getValue());
            DOMNode* remAttr = elemImpl->setAttributeNodeNS(attr);
Tinny Ng's avatar
Tinny Ng committed
            if (remAttr)
                remAttr->release();
Khaled Noaman's avatar
Khaled Noaman committed

            //DOMAttrImpl *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 (fDocument->fNodeIDMap == 0)
                    fDocument->fNodeIDMap = new (fDocument) DOMNodeIDMap(500, fDocument);
                fDocument->fNodeIDMap->add(attr);
                attr->fNode.isIdAttr(true);
            }

            attr->setSpecified(oneAttrib->getSpecified());

            XMLAttDef *attDef = 0;
            if(defAttrs != 0)
                attDef = defAttrs->findAttDef(attrURIId, oneAttrib->getQName());

            if(attDef != 0) {
                attr->setTypeInfo(attDef->getDOMTypeInfoName(), attDef->getDOMTypeInfoUri());
                attDef->reset();
            }
            else {
                const XMLCh *name = oneAttrib->getName();
                if (XMLString::equals(oneAttrib->getPrefix(), XSI)) {
                    if(XMLString::equals(name, SchemaSymbols::fgXSI_TYPE)) {
                        attr->setTypeInfo(SchemaSymbols::fgDT_QNAME, SchemaSymbols::fgURI_SCHEMAFORSCHEMA);
                    }
                    else if(XMLString::equals(name, SchemaSymbols::fgATT_NILL)) {
                        attr->setTypeInfo(SchemaSymbols::fgDT_BOOLEAN, SchemaSymbols::fgURI_SCHEMAFORSCHEMA);
                    }
                    else if(XMLString::equals(name, SchemaSymbols::fgXSI_NONAMESPACESCHEMALOCACTION)) {
                        attr->setTypeInfo(SchemaSymbols::fgDT_ANYURI, SchemaSymbols::fgURI_SCHEMAFORSCHEMA);
                    }
                }
                else {
                    //for normal ns attrs
                    attr->setTypeInfo(SchemaSymbols::fgDT_ANYURI, SchemaSymbols::fgURI_SCHEMAFORSCHEMA);
                }
            }
Khaled Noaman's avatar
Khaled Noaman committed
        }
    }
    else {    //DOM Level 1
        elem = fDocument->createElement(elemDecl.getFullName());
        elemImpl = (DOMElementImpl *) elem;
Khaled Noaman's avatar
Khaled Noaman committed
			for (unsigned int index = 0; index < attrCount; ++index) {
				const XMLAttr* oneAttrib = attrList.elementAt(index);
            //AttrImpl *attr = elemImpl->setAttribute(oneAttrib->getName(), oneAttrib->getValue());
            DOMAttrImpl *attr = (DOMAttrImpl *)
                fDocument->createAttribute(oneAttrib->getName());
            attr->setValue(oneAttrib -> getValue());
Tinny Ng's avatar
Tinny Ng committed
            DOMNode* rem = elemImpl->setAttributeNode(attr);
            if (rem)
                rem->release();
Khaled Noaman's avatar
Khaled Noaman committed
				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 (fDocument->fNodeIDMap == 0)
                    fDocument->fNodeIDMap = new (fDocument) DOMNodeIDMap(500, fDocument);
                fDocument->fNodeIDMap->add(attr);
                attr->fNode.isIdAttr(true);
            }

            XMLAttDef *attDef = 0;
            if(defAttrs != 0)
                attDef = defAttrs->findAttDef(oneAttrib -> getURIId(), oneAttrib->getQName());

            if(attDef != 0) {
                attr->setTypeInfo(attDef->getDOMTypeInfoName(), attDef->getDOMTypeInfoUri());
                attDef->reset();
            }

	if (defAttrs != 0)
	{		
        XMLAttDef* attr = 0;

        DOMAttrImpl * insertAttr = 0;

        while (defAttrs->hasMoreElements())
        {
            attr = &defAttrs->nextElement();

            const XMLAttDef::DefAttTypes defType = attr->getDefaultType();
            if ((defType == XMLAttDef::Default)
            ||  (defType == XMLAttDef::Fixed))
            {

                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.
                    const XMLCh* qualifiedName = attr->getFullName();
                    XMLBufBid bbPrefixQName(&fBufMgr);
                    XMLBuffer& prefixBuf = bbPrefixQName.getBuffer();
                    int colonPos = -1;
                    unsigned int uriId = fScanner->resolveQName(qualifiedName, prefixBuf, ElemStack::Mode_Attribute, colonPos);

                    const XMLCh* namespaceURI = 0;
                    if (XMLString::equals(qualifiedName, XMLNS))    //for xmlns=...
                        uriId = fScanner->getXMLNSNamespaceId();
                    if (uriId != fScanner->getEmptyNamespaceId()) {  //TagName has a prefix
                        namespaceURI = fScanner->getURIText(uriId);
                    }
                    insertAttr = (DOMAttrImpl *) fDocument->createAttributeNS(
                                                                              namespaceURI,     // NameSpaceURI
                                                                              qualifiedName);   // qualified name
                    DOMAttr* remAttr = elemImpl->setDefaultAttributeNodeNS(insertAttr);
                    if (remAttr)
                        remAttr->release();
                    if (attr->getValue() != 0)
                    {
                        insertAttr->setValue(attr->getValue());
                        insertAttr->setSpecified(false);
                {
                    // Namespaces is turned off...
                    insertAttr = (DOMAttrImpl *) fDocument->createAttribute(attr->getFullName());
                    DOMNode* remAttr = elemImpl->setDefaultAttributeNode(insertAttr);
                    if (remAttr)
                        remAttr->release();
                    //need to do this before the get as otherwise we overwrite any value in the attr
                    if (attr->getValue() != 0)
                    {
                        insertAttr->setValue(attr->getValue());
                        insertAttr->setSpecified(false);

                insertAttr->setTypeInfo(attr->getDOMTypeInfoName(), attr->getDOMTypeInfoUri());


            insertAttr = 0;
            attr->reset();