blob: 7046aa928a73510d9d2d43c43027dce518a879e6 [file] [log] [blame]
/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 2001 The Apache Software Foundation. All rights
* 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 IDOM nodes
* are created and added to the DOM tree.
*
* $Id$
*
*/
// ---------------------------------------------------------------------------
// Includes
// ---------------------------------------------------------------------------
#include <sax/EntityResolver.hpp>
#include <util/XMLUniDefs.hpp>
#include <sax/ErrorHandler.hpp>
#include <sax/SAXParseException.hpp>
#include <framework/XMLNotationDecl.hpp>
#include <util/IOException.hpp>
#include <internal/XMLScanner.hpp>
#include <validators/DTD/DTDValidator.hpp>
#include <parsers/IDOMParser.hpp>
#include <idom/IDOM_DOMImplementation.hpp>
#include <idom/IDOM_Element.hpp>
#include <idom/IDAttrImpl.hpp>
#include <idom/IDOM_CDATASection.hpp>
#include <idom/IDOM_Comment.hpp>
#include <idom/IDTextImpl.hpp>
#include <idom/IDDocumentImpl.hpp>
#include <idom/IDDocumentTypeImpl.hpp>
#include <idom/IDOM_DocumentType.hpp>
#include <idom/IDElementImpl.hpp>
#include <idom/IDEntityImpl.hpp>
#include <idom/IDEntityReferenceImpl.hpp>
#include <idom/IDNotationImpl.hpp>
#include <idom/IDOM_NamedNodeMap.hpp>
#include <idom/IDOM_ProcessingInstruction.hpp>
#include <idom/IDNodeIDMap.hpp>
#include <validators/common/ContentSpecNode.hpp>
#include <validators/DTD/DTDAttDefList.hpp>
// ---------------------------------------------------------------------------
// IDOMParser: Constructors and Destructor
// ---------------------------------------------------------------------------
IDOMParser::IDOMParser(XMLValidator* const valToAdopt) :
fErrorHandler(0)
, fEntityResolver(0)
, fCreateEntityReferenceNodes(false)
, fIncludeIgnorableWhitespace(true)
, fNodeStack(0)
, fScanner(0)
, fDocument(0)
, fDocumentVector(0)
{
//
// Create a scanner and tell it what validator to use. Then set us
// as the document event handler so we can fill the IDOM document.
//
fScanner = new XMLScanner(valToAdopt);
fScanner->setDocHandler(this);
fScanner->setDocTypeHandler(this);
fNodeStack = new ValueStackOf<IDOM_Node*>(64);
this->reset();
}
IDOMParser::~IDOMParser()
{
if (fDocumentVector)
delete fDocumentVector;
delete fDocument;
delete fNodeStack;
delete fScanner;
}
void IDOMParser::reset()
{
// if fDocument exists already, store the old pointer in the vector for deletion later
if (fDocument) {
if (!fDocumentVector) {
// allocate the vector if not exists yet
fDocumentVector = new RefVectorOf<IDDocumentImpl>(10, true) ;
}
fDocumentVector->addElement(fDocument);
}
fDocument = 0;
resetDocType();
fCurrentParent = 0;
fCurrentNode = 0;
fParseInProgress = false;
fWithinElement = false;
fNodeStack->removeAllElements();
};
// ---------------------------------------------------------------------------
// IDOMParser: Getter methods
// ---------------------------------------------------------------------------
IDOM_Document* IDOMParser::getDocument()
{
return fDocument;
}
const XMLValidator& IDOMParser::getValidator() const
{
return *fScanner->getValidator();
}
bool IDOMParser::getDoNamespaces() const
{
return fScanner->getDoNamespaces();
}
bool IDOMParser::getExitOnFirstFatalError() const
{
return fScanner->getExitOnFirstFatal();
}
bool IDOMParser::getValidationConstraintFatal() const
{
return fScanner->getValidationConstraintFatal();
}
IDOMParser::ValSchemes IDOMParser::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 IDOMParser::getDoSchema() const
{
return fScanner->getDoSchema();
}
bool IDOMParser::getValidationSchemaFullChecking() const
{
return fScanner->getValidationSchemaFullChecking();
}
int IDOMParser::getErrorCount() const
{
return fScanner->getErrorCount();
}
// ---------------------------------------------------------------------------
// IDOMParser: Setter methods
// ---------------------------------------------------------------------------
void IDOMParser::setDoNamespaces(const bool newState)
{
fScanner->setDoNamespaces(newState);
}
void IDOMParser::setErrorHandler(ErrorHandler* const handler)
{
fErrorHandler = handler;
if (fErrorHandler) {
fScanner->setErrorReporter(this);
fScanner->setErrorHandler(fErrorHandler);
}
else {
fScanner->setErrorReporter(0);
fScanner->setErrorHandler(0);
}
}
void IDOMParser::setEntityResolver(EntityResolver* const handler)
{
fEntityResolver = handler;
if (fEntityResolver) {
fScanner->setEntityHandler(this);
fScanner->setEntityResolver(fEntityResolver);
}
else {
fScanner->setEntityHandler(0);
fScanner->setEntityResolver(0);
}
}
void IDOMParser::setExitOnFirstFatalError(const bool newState)
{
fScanner->setExitOnFirstFatal(newState);
}
void IDOMParser::setValidationConstraintFatal(const bool newState)
{
fScanner->setValidationConstraintFatal(newState);
}
void IDOMParser::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 IDOMParser::setDoSchema(const bool newState)
{
fScanner->setDoSchema(newState);
}
void IDOMParser::setValidationSchemaFullChecking(const bool schemaFullChecking)
{
fScanner->setValidationSchemaFullChecking(schemaFullChecking);
}
// ---------------------------------------------------------------------------
// IDOMParser: Parsing methods
// ---------------------------------------------------------------------------
void IDOMParser::parse(const InputSource& source, const bool reuseGrammar)
{
// Avoid multiple entrance
if (fParseInProgress)
ThrowXML(IOException, XMLExcepts::Gen_ParseInProgress);
try
{
fParseInProgress = true;
fScanner->scanDocument(source, reuseGrammar);
fParseInProgress = false;
}
catch(...)
{
fParseInProgress = false;
throw;
}
}
void IDOMParser::parse(const XMLCh* const systemId, const bool reuseGrammar)
{
// Avoid multiple entrance
if (fParseInProgress)
ThrowXML(IOException, XMLExcepts::Gen_ParseInProgress);
try
{
fParseInProgress = true;
fScanner->scanDocument(systemId, reuseGrammar);
fParseInProgress = false;
}
catch(...)
{
fParseInProgress = false;
throw;
}
}
void IDOMParser::parse(const char* const systemId, const bool reuseGrammar)
{
// Avoid multiple entrance
if (fParseInProgress)
ThrowXML(IOException, XMLExcepts::Gen_ParseInProgress);
try
{
fParseInProgress = true;
fScanner->scanDocument(systemId, reuseGrammar);
fParseInProgress = false;
}
catch(...)
{
fParseInProgress = false;
throw;
}
}
// ---------------------------------------------------------------------------
// IDOMParser: Progressive parse methods
// ---------------------------------------------------------------------------
bool IDOMParser::parseFirst( const XMLCh* const systemId
, XMLPScanToken& toFill
, const bool reuseGrammar)
{
//
// 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, reuseGrammar);
}
bool IDOMParser::parseFirst( const char* const systemId
, XMLPScanToken& toFill
, const bool reuseGrammar)
{
//
// 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, reuseGrammar);
}
bool IDOMParser::parseFirst( const InputSource& source
, XMLPScanToken& toFill
, const bool reuseGrammar)
{
//
// 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, reuseGrammar);
}
bool IDOMParser::parseNext(XMLPScanToken& token)
{
return fScanner->scanNext(token);
}
void IDOMParser::parseReset(XMLPScanToken& token)
{
// Reset the scanner, and then reset the parser
fScanner->scanReset(token);
reset();
}
// ---------------------------------------------------------------------------
// IDOMParser: Utilities
// ---------------------------------------------------------------------------
void IDOMParser::resetDocumentPool()
{
// We cannot enter here while a regular parse is in progress.
if (fParseInProgress)
ThrowXML(IOException, XMLExcepts::Gen_ParseInProgress);
if (fDocumentVector)
fDocumentVector->removeAllElements();
delete fDocument;
fDocument = 0;
}
// ---------------------------------------------------------------------------
// IDOMParser: Implementation of the XMLErrorReporter interface
// ---------------------------------------------------------------------------
void IDOMParser::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 unsigned int lineNum
, const unsigned int colNum)
{
SAXParseException toThrow = SAXParseException
(
errorText
, publicId
, systemId
, lineNum
, colNum
);
//
// 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 IDOMParser::resetErrors()
{
}
// ---------------------------------------------------------------------------
// IDOMParser: Implementation of XMLEntityHandler interface
// ---------------------------------------------------------------------------
InputSource*
IDOMParser::resolveEntity(const XMLCh* const publicId, const XMLCh* const systemId)
{
//
// 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;
}
// ---------------------------------------------------------------------------
// IDOMParser: Implementation of XMLDocumentHandler interface
// ---------------------------------------------------------------------------
void IDOMParser::docCharacters( const XMLCh* const chars
, const unsigned int length
, const bool cdataSection)
{
// Ignore chars outside of content
if (!fWithinElement)
return;
// idom_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)
{
IDOM_CDATASection *node = fDocument->createCDATASection(chars);
fCurrentParent->appendChild(node);
fCurrentNode = node;
}
else
{
if (fCurrentNode->getNodeType() == IDOM_Node::TEXT_NODE)
{
IDOM_Text *node = (IDOM_Text *)fCurrentNode;
node->appendData(chars);
}
else
{
IDOM_Text *node = fDocument->createTextNode(chars);
//If the node type is entityRef then set the readOnly flag to false before appending node
if (fCurrentParent->getNodeType() == IDOM_Node::ENTITY_REFERENCE_NODE) {
IDEntityReferenceImpl *erImpl = (IDEntityReferenceImpl *) fCurrentParent;
bool oldReadFlag = erImpl->fNode.isReadOnly();
erImpl->fNode.isReadOnly(false);
fCurrentParent->appendChild(node);
erImpl->fNode.isReadOnly(oldReadFlag);
}
else
{
fCurrentParent->appendChild(node);
}
fCurrentNode = node;
}
}
ncChars[length] = savedChar;
return;
}
void IDOMParser::docComment(const XMLCh* const comment)
{
IDOM_Comment *dcom = fDocument->createComment(comment);
fCurrentParent->appendChild(dcom);
fCurrentNode = dcom;
}
void IDOMParser::docPI( const XMLCh* const target
, const XMLCh* const data)
{
IDOM_ProcessingInstruction *pi = fDocument->createProcessingInstruction
(
target
, data
);
fCurrentParent->appendChild(pi);
fCurrentNode = pi;
}
void IDOMParser::endEntityReference(const XMLEntityDecl& entDecl)
{
if (fCreateEntityReferenceNodes == true)
{
fCurrentParent = fNodeStack->pop();
fCurrentNode = fCurrentParent;
}
}
void IDOMParser::endElement( const XMLElementDecl& elemDecl
, const unsigned int urlId
, const bool isRoot)
{
fCurrentNode = fCurrentParent;
fCurrentParent = fNodeStack->pop();
// If we've hit the end of content, clear the flag
if (fNodeStack->empty())
fWithinElement = false;
}
void IDOMParser::ignorableWhitespace(const XMLCh* const chars
, const unsigned int length
, const bool cdataSection)
{
// Ignore chars before the root element
if (!fWithinElement || !fIncludeIgnorableWhitespace)
return;
// idom_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() == IDOM_Node::TEXT_NODE)
{
IDOM_Text *node = (IDOM_Text *)fCurrentNode;
node->appendData(chars);
}
else
{
IDTextImpl *node = (IDTextImpl *)fDocument->createTextNode(chars);
node->setIgnorableWhitespace(true);
//If the node type is entityRef then set the readOnly flag to false before appending node
if (fCurrentParent->getNodeType() == IDOM_Node::ENTITY_REFERENCE_NODE) {
IDEntityReferenceImpl *erImpl = (IDEntityReferenceImpl *) fCurrentParent;
bool oldReadFlag = erImpl->fNode.isReadOnly();
erImpl->fNode.isReadOnly(false);
fCurrentParent->appendChild(node);
erImpl->fNode.isReadOnly(oldReadFlag);
}
else
{
fCurrentParent->appendChild(node);
}
fCurrentNode = node;
}
ncChars[length] = savedChar;
}
void IDOMParser::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 IDOM document itself.
//
this->reset();
fDocument = (IDDocumentImpl *)IDOM_DOMImplementation::getImplementation()->createDocument();
}
void IDOMParser::startDocument()
{
// Just set the document as the current parent and current node
fCurrentParent = fDocument;
fCurrentNode = fDocument;
// set IDOM error checking off
fDocument->setErrorChecking(false);
}
void IDOMParser::endDocument()
{
// set IDOM error checking back on
fDocument->setErrorChecking(true);
}
void IDOMParser::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)
{
IDOM_Element *elem;
if (fScanner -> getDoNamespaces()) { //IDOM Level 2, doNamespaces on
XMLBuffer buf;
XMLCh* namespaceURI = 0;
if (urlId != fScanner->getEmptyNamespaceId()) { //TagName has a prefix
fScanner->getURIText(urlId, buf); //get namespaceURI
namespaceURI = buf.getRawBuffer();
}
elem = fDocument->createElementNS(namespaceURI, elemDecl.getFullName());
IDElementImpl *elemImpl = (IDElementImpl *) elem;
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 = buf.getRawBuffer();
}
// idom_revisit. Optimize to init the named node map to the
// right size up front.
IDAttrImpl *attr = (IDAttrImpl *)
fDocument->createAttributeNS(namespaceURI, oneAttrib->getQName());
attr->setValue(oneAttrib -> getValue());
elemImpl->setAttributeNode(attr);
//IDAttrImpl *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) IDNodeIDMap(500, fDocument);
fDocument->fNodeIDMap->add(attr);
attr->fNode.isIdAttr(true);
}
attr->setSpecified(oneAttrib->getSpecified());
}
}
else { //DOM Level 1
elem = fDocument->createElement(elemDecl.getFullName());
IDElementImpl *elemImpl = (IDElementImpl *) elem;
for (unsigned int index = 0; index < attrCount; ++index) {
const XMLAttr* oneAttrib = attrList.elementAt(index);
//AttrImpl *attr = elemImpl->setAttribute(oneAttrib->getName(), oneAttrib->getValue());
IDAttrImpl *attr = (IDAttrImpl *)
fDocument->createAttribute(oneAttrib->getName());
attr->setValue(oneAttrib -> getValue());
elemImpl->setAttributeNode(attr);
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) IDNodeIDMap(500, fDocument);
fDocument->fNodeIDMap->add(attr);
attr->fNode.isIdAttr(true);
}
}
}
//If the node type is entityRef then set the readOnly flag to false before appending node
bool oldReadFlag;
if (fCurrentParent->getNodeType() == IDOM_Node::ENTITY_REFERENCE_NODE) {
IDEntityReferenceImpl *erNode = (IDEntityReferenceImpl *)fCurrentParent;
oldReadFlag = erNode->fNode.isReadOnly();
erNode->fNode.isReadOnly(false);
fCurrentParent->appendChild(elem);
erNode->fNode.isReadOnly(oldReadFlag);
}
else
{
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);
}
void IDOMParser::startEntityReference(const XMLEntityDecl& entDecl)
{
if (fCreateEntityReferenceNodes == true)
{
const XMLCh * entName = entDecl.getName();
IDOM_EntityReference *er = fDocument->createEntityReference(entName);
fCurrentParent->appendChild(er);
fNodeStack->push(fCurrentParent);
fCurrentParent = er;
fCurrentNode = er;
// this entityRef needs to be stored in Entity map too.
// We'd decide later whether the entity nodes should be created by a
// separated method in parser or not. For now just stick it in if
// the ref nodes are created
IDOM_NamedNodeMap *entities = fDocumentType->getEntities();
IDEntityImpl* entity = (IDEntityImpl*)entities->getNamedItem(entName);
entity->setEntityRef(er);
}
}
void IDOMParser::XMLDecl(const XMLCh* const version
, const XMLCh* const encoding
, const XMLCh* const standalone
, const XMLCh* const actualEncStr)
{
// placehold for DOM Level 3
}
// ---------------------------------------------------------------------------
// IDOMParser: Deprecated methods
// ---------------------------------------------------------------------------
bool IDOMParser::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 IDOMParser::setDoValidation(const bool newState)
{
fScanner->setDoValidation
(
newState ? XMLScanner::Val_Always : XMLScanner::Val_Never
);
}
//doctypehandler interfaces
void IDOMParser::attDef
(
const DTDElementDecl& elemDecl
, const DTDAttDef& attDef
, const bool ignoring
)
{
if (fDocumentType->isIntSubsetReading())
{
XMLBuffer attString;
if (elemDecl.hasAttDefs())
{
attString.append(chOpenAngle);
attString.append(chBang);
attString.append(XMLUni::fgAttListString);
attString.append(chSpace);
attString.append(elemDecl.getFullName());
attString.append(chSpace);
attString.append(attDef.getFullName());
// Get the type and display it
const XMLAttDef::AttTypes type = attDef.getType();
switch(type)
{
case XMLAttDef::CData :
attString.append(chSpace);
attString.append(XMLUni::fgCDATAString);
break;
case XMLAttDef::ID :
attString.append(chSpace);
attString.append(XMLUni::fgIDString);
break;
case XMLAttDef::IDRef :
attString.append(chSpace);
attString.append(XMLUni::fgIDRefString);
break;
case XMLAttDef::IDRefs :
attString.append(chSpace);
attString.append(XMLUni::fgIDRefsString);
break;
case XMLAttDef::Entity :
attString.append(chSpace);
attString.append(XMLUni::fgEntityString);
break;
case XMLAttDef::Entities :
attString.append(chSpace);
attString.append(XMLUni::fgEntitiesString);
break;
case XMLAttDef::NmToken :
attString.append(chSpace);
attString.append(XMLUni::fgNmTokenString);
break;
case XMLAttDef::NmTokens :
attString.append(chSpace);
attString.append(XMLUni::fgNmTokensString);
break;
case XMLAttDef::Notation :
attString.append(chSpace);
attString.append(XMLUni::fgNotationString);
break;
case XMLAttDef::Enumeration :
attString.append(chSpace);
const XMLCh* enumString = attDef.getEnumeration();
int length = XMLString::stringLen(enumString);
if (length > 0) {
XMLBuffer anotherEnumString;
anotherEnumString.append(chOpenParen );
for(int i=0; i<length; i++) {
if (enumString[i] == chSpace)
anotherEnumString.append(chPipe);
else
anotherEnumString.append(enumString[i]);
}
anotherEnumString.append(chCloseParen);
attString.append(anotherEnumString.getRawBuffer());
}
break;
}
//get te default types of the attlist
const XMLAttDef::DefAttTypes def = attDef.getDefaultType();
switch(def)
{
case XMLAttDef::Required :
attString.append(chSpace);
attString.append(XMLUni::fgRequiredString);
break;
case XMLAttDef::Implied :
attString.append(chSpace);
attString.append(XMLUni::fgImpliedString);
break;
case XMLAttDef::Fixed :
attString.append(chSpace);
attString.append(XMLUni::fgFixedString);
break;
}
const XMLCh* defaultValue = attDef.getValue();
if (defaultValue != 0) {
attString.append(chSpace);
attString.append(chDoubleQuote);
attString.append(defaultValue);
attString.append(chDoubleQuote);
}
attString.append(chCloseAngle);
fDocumentType->setInternalSubset(attString.getRawBuffer());
}
}
}
void IDOMParser::doctypeComment
(
const XMLCh* const comment
)
{
if (fDocumentType->isIntSubsetReading())
{
if (comment != 0)
{
XMLBuffer comString;
comString.append(XMLUni::fgCommentString);
comString.append(chSpace);
comString.append(comment);
comString.append(chSpace);
comString.append(chDash);
comString.append(chDash);
comString.append(chCloseAngle);
fDocumentType->setInternalSubset(comString.getRawBuffer());
}
}
}
void IDOMParser::doctypeDecl
(
const DTDElementDecl& elemDecl
, const XMLCh* const publicId
, const XMLCh* const systemId
, const bool hasIntSubset
)
{
fDocumentType = (IDDocumentTypeImpl *) fDocument->createDocumentType(elemDecl.getFullName(), publicId, systemId);
fDocument->setDocumentType(fDocumentType);
}
void IDOMParser::doctypePI
(
const XMLCh* const target
, const XMLCh* const data
)
{
if (fDocumentType->isIntSubsetReading())
{
//add these chars to internalSubset variable
XMLBuffer pi;
pi.append(chOpenAngle);
pi.append(chQuestion);
pi.append(target);
pi.append(chSpace);
pi.append(data);
pi.append(chQuestion);
pi.append(chCloseAngle);
fDocumentType->setInternalSubset(pi.getRawBuffer());
}
}
void IDOMParser::doctypeWhitespace
(
const XMLCh* const chars
, const unsigned int length
)
{
if (fDocumentType->isIntSubsetReading())
fDocumentType->setInternalSubset(chars);
}
void IDOMParser::elementDecl
(
const DTDElementDecl& decl
, const bool isIgnored
)
{
if (fDocumentType->isIntSubsetReading())
{
XMLBuffer elemDecl;
elemDecl.append(chOpenAngle);
elemDecl.append(chBang);
elemDecl.append(XMLUni::fgElemString);
elemDecl.append(chSpace);
elemDecl.append(decl.getFullName());
//get the ContentSpec information
const XMLCh* contentModel = decl.getFormattedContentModel();
if (contentModel != 0) {
elemDecl.append(chSpace);
elemDecl.append(contentModel);
}
elemDecl.append(chCloseAngle);
fDocumentType->setInternalSubset(elemDecl.getRawBuffer());
}
}
void IDOMParser::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
// IDOM spec regarding creating element nodes & removing attributes with default values
// see DocumentTypeImpl
if (elemDecl.hasAttDefs())
{
XMLAttDefList* defAttrs = &elemDecl.getAttDefList();
XMLAttDef* attr = 0;
IDAttrImpl * insertAttr = 0;
IDOM_Element *elem = fDocument->createElement(elemDecl.getFullName());
IDElementImpl *elemImpl = (IDElementImpl *) elem;
while (defAttrs->hasMoreElements())
{
attr = &defAttrs->nextElement();
if (attr->getValue() != 0)
{
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();
int index = IDDocumentImpl::indexofQualifiedName(qualifiedName);
XMLBuffer buf;
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"
XMLCh* prefix;
XMLCh temp[1000];
if (index > 999)
prefix = new XMLCh[index+1];
else
prefix = temp;
XMLString::subString(prefix ,qualifiedName, 0, index);
if (!XMLString::compareString(prefix,XMLNS))
buf.append(XMLUni::fgXMLNSURIName);
else
buf.append(XMLUni::fgXMLURIName);
if (index > 999)
delete prefix;
}
else {
// No prefix
if (!XMLString::compareString(qualifiedName,XMLNS))
buf.append(XMLUni::fgXMLNSURIName);
}
insertAttr = (IDAttrImpl *) fDocument->createAttributeNS(
buf.getRawBuffer(), // NameSpaceURI
qualifiedName); // qualified name
}
else
{
// Namespaces is turned off...
insertAttr = (IDAttrImpl *) fDocument->createAttribute(attr->getFullName());
}
insertAttr->setValue(attr->getValue());
elemImpl->setAttributeNode(insertAttr);
insertAttr->setSpecified(false);
}
}
fDocumentType->getElements()->setNamedItem(elemImpl);
}
}
void IDOMParser::endIntSubset()
{
fDocumentType->intSubsetReading = false;
}
void IDOMParser::endExtSubset()
{
}
void IDOMParser::entityDecl
(
const DTDEntityDecl& entityDecl
, const bool isPEDecl
, const bool isIgnored
)
{
IDEntityImpl* entity = (IDEntityImpl *) fDocument->createEntity(entityDecl.getName());
entity->setPublicId(entityDecl.getPublicId());
entity->setSystemId(entityDecl.getSystemId());
entity->setNotationName(entityDecl.getNotationName());
IDEntityImpl *previousDef = (IDEntityImpl *)
fDocumentType->getEntities()->setNamedItem( entity );
#ifdef idom_revisit
//
// 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);
#endif
if (fDocumentType->isIntSubsetReading())
{
//add thes chars to internalSubset variable
XMLBuffer entityName;
entityName.append(chOpenAngle);
entityName.append(chBang);
entityName.append(XMLUni::fgEntityString);
entityName.append(chSpace);
entityName.append(entityDecl.getName());
const XMLCh* id = entity->getPublicId();
if (id != 0) {
entityName.append(chSpace);
entityName.append(XMLUni::fgPubIDString);
entityName.append(chSpace);
entityName.append(chDoubleQuote);
entityName.append(id);
entityName.append(chDoubleQuote);
}
id = entity->getSystemId();
if (id != 0) {
entityName.append(chSpace);
entityName.append(XMLUni::fgSysIDString);
entityName.append(chSpace);
entityName.append(chDoubleQuote);
entityName.append(id);
entityName.append(chDoubleQuote);
}
id = entity->getNotationName();
if (id != 0) {
entityName.append(chSpace);
entityName.append(XMLUni::fgNDATAString);
entityName.append(chSpace);
entityName.append(chDoubleQuote);
entityName.append(id);
entityName.append(chDoubleQuote);
}
id = entityDecl.getValue();
if (id !=0) {
entityName.append(chSpace);
entityName.append(chDoubleQuote);
entityName.append(id);
entityName.append(chDoubleQuote);
}
entityName.append(chCloseAngle);
fDocumentType->setInternalSubset(entityName.getRawBuffer());
}
}
void IDOMParser::resetDocType()
{
fDocumentType = 0;
}
void IDOMParser::notationDecl
(
const XMLNotationDecl& notDecl
, const bool isIgnored
)
{
IDNotationImpl* notation = (IDNotationImpl *)fDocument->createNotation(notDecl.getName());
notation->setPublicId(notDecl.getPublicId());
notation->setSystemId(notDecl.getSystemId());
fDocumentType->getNotations()->setNamedItem( notation );
}
void IDOMParser::startAttList
(
const DTDElementDecl& elemDecl
)
{
}
void IDOMParser::startIntSubset()
{
fDocumentType->intSubsetReading = true;
}
void IDOMParser::startExtSubset()
{
}
void IDOMParser::TextDecl
(
const XMLCh* const versionStr
, const XMLCh* const encodingStr
)
{
}