domimpl.cpp revision 4cb9ed4c3d183554e888e636844f8e3c2e666c40
/**
* Phoebe DOM Implementation.
*
* This is a C++ approximation of the W3C DOM model, which follows
* fairly closely the specifications in the various .idl files, copies of
* which are provided for reference. Most important is this one:
*
*
* Authors:
* Bob Jamison
*
* Copyright (C) 2005-2008 Bob Jamison
*
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <cstdio>
#include "domimpl.h"
namespace org
{
namespace w3c
{
namespace dom
{
/**
* Test if the given substring exists for the length of the string
* in a given buffer
*/
/*
static bool match(const DOMString &buf, char *str)
{
int pos = 0;
while (*str)
{
if (buf[pos++] != *str++)
return false;
}
return true;
}
*/
/*#########################################################################
## DOMImplementationSourceImpl
#########################################################################*/
/**
*
*/
{
domImpl = new DOMImplementationImpl();
}
/**
*
*/
{
delete domImpl;
}
/**
*
*/
const DOMString &/*features*/)
{
return domImpl;
}
/**
*
*/
const DOMString &/*features*/)
{
return domImplList;
}
/*#########################################################################
## DOMImplementationImpl
#########################################################################*/
/**
*
*/
{
}
/**
*
*/
{
}
/**
*
*/
const DOMString& /*version*/)
{
return false;
}
/**
*
*/
throw(DOMException)
{
return typeImpl;
}
/**
*
*/
const DOMString& namespaceURI,
const DOMString& qualifiedName,
throw(DOMException)
{
doctype);
return doc;
}
/**
*
*/
const DOMString& /*version*/)
{
return NULL;
}
/*#########################################################################
## NodeImpl
#########################################################################*/
/**
* Utility for finding the first Element above
* a given node. Used by several methods below
*/
{
return NULL;
//Either quit because I am an element, or because I am null
{
return node;
}
return node;
}
/**
*
*/
{
return nodeName;
}
/**
*
*/
{
return nodeValue;
}
/**
*
*/
{
}
/**
*
*/
unsigned short NodeImpl::getNodeType()
{
return nodeType;
}
/**
*
*/
{
return parent;
}
/**
*
*/
{
return list;
}
/**
*
*/
{
return firstChild;
}
/**
*
*/
{
return lastChild;
}
/**
*
*/
{
return prev;
}
/**
*
*/
{
return next;
}
/**
*
*/
{
return attrs;
}
/**
*
*/
{
return ownerDocument;
}
/**
*
*/
throw(DOMException)
{
if (!newChild)
return NULL;
//if no ref, then just append
if (!refChild)
return appendChild(newChild);
{
if (n == refChild)
{
//link to new
else
n->prev = newChildImpl;
//link from new
newChildImpl->next = n;
//reflect new location
newChildImpl->parent = this;
return n;
}
}
return NULL;
}
/**
*
*/
throw(DOMException)
{
if (!oldChild)
return NULL;
{
if (n == oldChild)
{
//link to new
else
else
//link from new
//reflect new location
newChildImpl->parent = this;
return n;
}
}
return NULL;
}
/**
*
*/
throw(DOMException)
{
if (!oldChild)
return NULL;
{
if (n == oldChild)
{
return n;
}
}
return NULL;
}
/**
*
*/
throw(DOMException)
{
if (!newChild)
return NULL;
newChildImpl->parent = this;
if (!firstChild || !lastChild)
{
//Set up our first member
}
else
{
//link at the last position
}
return newChild;
}
/**
*
*/
bool NodeImpl::hasChildNodes()
{
return (firstChild != (NodeImpl *)0);
}
/**
*
*/
{
if (deep)
{
{
}
}
else
{
}
return node;
}
/**
* Concatenate adjoining text subnodes, remove null-length nodes
*/
{
//First, concatenate adjoining text nodes
{
continue;
{
break;
//unlink and delete
//delete sibling;
}
}
//Next, we remove zero-length text subnodes
{
continue;
{
//unlink and delete
//delete child;
}
}
}
/**
*
*/
const DOMString& /*version*/)
{
//again, no idea
return false;
}
/**
*
*/
{
return namespaceURI;
}
/**
*
*/
{
return prefix;
}
/**
*
*/
{
else
}
/**
*
*/
{
return localName;
}
/**
*
*/
bool NodeImpl::hasAttributes()
{
return (attributes.getLength() > 0);
}
/**
*
*/
{
return baseURI;
}
/**
*
*/
{
return 0;//no flags
//Look above me
return DOCUMENT_POSITION_CONTAINED_BY;
//Look above the other guy. See me?
return DOCUMENT_POSITION_CONTAINS;
return DOCUMENT_POSITION_DISCONNECTED |
}
/**
*
*/
{
nodeType == CDATA_SECTION_NODE ||
nodeType == COMMENT_NODE ||
buf = getNodeValue();
else if (nodeType == ELEMENT_NODE ||
nodeType == ATTRIBUTE_NODE ||
nodeType == ENTITY_NODE ||
{
n=n->getNextSibling() )
{
if (n->getNodeType() != COMMENT_NODE &&
n->getNodeType() != COMMENT_NODE)
}
}
return buf;
}
/**
*
*/
{
//Delete children
/** Not necessary. Just let smart pointers to their work
for (NodePtr n = getFirstChild() ; n.get() ;
n=n->getNextSibling() )
delete n;
*/
//Replace with a single text node
}
/**
* From DOM3 Namespace algorithms
*/
{
if (theNamespaceURI.size()==0)
{
return DOMString("");
}
switch (nodeType)
{
case Node::ELEMENT_NODE:
{
}
case Node::DOCUMENT_NODE:
{
}
case Node::ENTITY_NODE :
case Node::NOTATION_NODE:
case Node::DOCUMENT_FRAGMENT_NODE:
case Node::DOCUMENT_TYPE_NODE:
case Node::ATTRIBUTE_NODE:
{
{
}
return DOMString("");
}
default:
{
//Get ancestor element, if any
{
}
return DOMString("");
}
}//switch
return DOMString("");
}
/**
*
*/
{
switch (nodeType)
{
case ELEMENT_NODE:
{
{
return (namespaceURI == theNamespaceURI);
}
{
}
{
}
else
{
return false;
}
}
case DOCUMENT_NODE:
{ //just use braces for local declaration
}
case ENTITY_NODE:
case NOTATION_NODE:
case DOCUMENT_TYPE_NODE:
case DOCUMENT_FRAGMENT_NODE:
return false;
case ATTRIBUTE_NODE:
{//braces only for scope
if ( ownerElement.get() )
{
}
else
{
return false;
}
}
default:
{
{
}
else
{
return false;
}
}
}//switch
return false;
}
/**
*
*/
{
switch (nodeType)
{
case ELEMENT_NODE:
{
{
return (nsURI);
}
if ( hasAttributes() )
{
for (int i=0 ; i<nrAttrs ; i++)
{
{ // non default namespace
{
return (attr->getNodeValue());
}
return DOMString("");
}
{ // default namespace
{
return (attr->getNodeValue());
}
return DOMString("");
}
}
}
{
}
return DOMString("");
}
case DOCUMENT_NODE:
{
}
case ENTITY_NODE:
case NOTATION_NODE:
case DOCUMENT_TYPE_NODE:
case DOCUMENT_FRAGMENT_NODE:
return DOMString("");
case ATTRIBUTE_NODE:
{
if ( ownerElement.get() )
{
}
else
{
return DOMString("");
}
}
default:
{
{
}
else
{
return DOMString("");
}
}
}//switch
}
/**
*
*/
{
if (!nodeArg)
return false;
return true;
return false;
return true;
}
/**
*
*/
const DOMString &/*version*/)
{
//dont know
return NULL;
}
/**
*
*/
const DOMUserData *data,
const UserDataHandler *handler)
{
while (entry)
{
{
return oldData;
}
}
//Make a new one
if (!prev)
else
return NULL;
}
/**
*
*/
{
while (entry)
{
}
return NULL;
}
//##################
//# Non-API methods
//##################
/**
*
*/
{
prefix = "";
localName = "";
for (unsigned int i=0 ; i<qualifiedName.size() ; i++)
{
int ch = qualifiedName[i];
if (ch == ':')
{
localName = "";
}
else
{
}
}
}
/**
*
*/
{
}
/**
* From DOM3 Namespace algorithms
*/
{
if (!originalElement)
return DOMString("");
{
return (prefix);
}
if ( hasAttributes() )
{
for (int i=0 ; i<nrAttrs ; i++)
{
== theNamespaceURI)
{
return (attrLocalName);
}
}
}
//Get ancestor element, if any
{
}
return DOMString("");
}
/**
*
*/
{
init();
}
/**
*
*/
{
init();
}
/**
*
*/
{
init();
return *this;
}
/**
*
*/
{
init();
}
/**
*
*/
: Node()
{
init();
}
/**
*
*/
{
init();
//if (owner)
// namespaceURI = owner->stringCache(theNamespaceURI);
}
/**
*
*/
{
nodeType = 0; //none yet
nodeValue = "";
setNodeName("");
namespaceURI = "";
firstChild = NULL;
}
/**
*
*/
{
}
/**
*
*/
{
if (userDataEntries)
delete userDataEntries;
//Delete children
/** Use smart pointers. do not delete explicitly
for (NodePtr n = getFirstChild() ; n.get() ;
n=n->getNextSibling() )
delete n;
*/
}
/*#########################################################################
## CharacterDataImpl
#########################################################################*/
/**
*
*/
{
}
/**
*
*/
{
}
/**
*
*/
{
}
/**
*
*/
{
return nodeValue;
}
/**
*
*/
{
}
/**
*
*/
unsigned long CharacterDataImpl::getLength()
{
}
/**
*
*/
unsigned long count)
throw(DOMException)
{
}
/**
*
*/
{
}
/**
*
*/
throw(DOMException)
{
}
/**
*
*/
unsigned long count)
throw(DOMException)
{
}
/**
*
*/
unsigned long count,
throw(DOMException)
{
}
/*#########################################################################
## AttrImpl
#########################################################################*/
/**
*
*/
{
return nodeName;
}
/**
*
*/
bool AttrImpl::getSpecified()
{
}
/**
*
*/
{
return nodeValue;
}
/**
*
*/
{
}
/**
*
*/
{
return ownerElement;
}
/**
*
*/
{
return typeInfo;
}
/**
*
*/
{
return (nodeName == "id");
}
//##################
//# Non-API methods
//##################
{
ownerElement = elem;
}
/**
*
*/
: NodeImpl()
{
}
/**
*
*/
const DOMString &/*theNamespaceURI*/,
const DOMString &theQualifiedName)
: NodeImpl()
{
//if (owner)
// namespaceURI = owner->stringCache(theNamespaceURI);
}
/**
*
*/
{
}
/*#########################################################################
## ElementImpl
#########################################################################*/
/**
*
*/
{
else
return nodeName;
}
/**
*
*/
{
return DOMString("");
}
/**
*
*/
throw(DOMException)
{
attr->setOwnerElement(this);
}
/**
*
*/
throw(DOMException)
{
}
/**
*
*/
{
return NULL;
return attr;
}
/**
*
*/
throw(DOMException)
{
return attr;
}
/**
*
*/
throw(DOMException)
{
return attr;
}
/**
*
*/
{
if (!elem)
return;
{
continue;
}
}
/**
*
*/
{
return list;
}
/**
*
*/
{
return DOMString("");
}
/**
*
*/
const DOMString& qualifiedName,
throw(DOMException)
{
attr->setOwnerElement(this);
}
/**
*
*/
throw(DOMException)
{
}
/**
*
*/
{
return (Attr *)0;
return attr;
}
/**
*
*/
throw(DOMException)
{
return attr;
}
/**
*
*/
const DOMString& namespaceURI,
{
if (!elem)
return;
{
continue;
}
}
/**
*
*/
{
return list;
}
/**
*
*/
{
return false;
return true;
}
/**
*
*/
{
return false;
return true;
}
/**
*
*/
{
return typeInfo;
}
/**
*
*/
bool /*isId*/) throw (DOMException)
{
//fixme
}
/**
*
*/
const DOMString &/*localName*/,
bool /*isId*/) throw (DOMException)
{
//fixme
}
/**
*
*/
bool /*isId*/) throw (DOMException)
{
//fixme
}
//##################
//# Non-API methods
//##################
/**
*
*/
{
}
/**
*
*/
: NodeImpl()
{
}
/**
*
*/
const DOMString &/*theNamespaceURI*/,
const DOMString &qualifiedName) :
NodeImpl()
{
}
/**
*
*/
{
}
/**
*
*/
void ElementImpl::normalizeNamespaces()
{
//printf("### NORMALIZE\n");
//#######################################
//# Pick up local namespace declarations
//#######################################
bindingsClear(); //Reset bindings on this node
for (int i=0; i<nrAttrs ; i++)
{
continue;
continue;
//is the namespace declaration is invalid?
{
// Note: The prefix xmlns is used only to declare namespace bindings and
// is by definition bound to the namespace name http://www.w3.org/2000/xmlns/.
// It must not be declared. No other prefix may be bound to this namespace name.
//==> Report an error.
printf("normalizeNamespaces() error: Namespace %s cannot be reassigned\n",
}
else
{
//==> Record the namespace declaration
if (attrPrefix.size() > 0)
else
}
}
//#######################################
//# Fixup element's namespace
//#######################################
if ( namespaceURI.size() > 0 )
{
key = "*";
// are within the scope of a binding
if ( binding == namespaceURI )
{
//==> do nothing, declaration in scope is inherited
// See section "B.1.1: Scope of a binding" for an example
}
else
{
/*
==> Create a local namespace declaration attr for this namespace,
with Element's current prefix (or a default namespace, if
no prefix). If there's a conflicting local declaration
already present, change its value to use this namespace.
See section "B.1.2: Conflicting namespace declaration" for an example
*/
{
}
// NOTE that this may break other nodes within this Element's
// subtree, if they're already using this prefix.
// They will be repaired when we reach them.
}
}
else // Element has no namespace URI:
{
//###############################################
//# Bob -- alter this from the specs a bit.
//# Since the XmlReader does not set namespaces,
//# do it here
//###############################################
{
// DOM Level 1 node
/*
==> if in process of validation against a namespace aware schema
(i.e XML Schema) report a fatal error: the processor can not recover
in this situation.
Otherwise, report an error: no namespace fixup will be performed on this node.
*/
printf("normalizeNamespaces() error: no localName\n");
}
else
{
// Element has no pseudo-prefix
//there's a conflicting local default namespace declaration already present
{
//==> change its value to use this empty namespace.
//setAttribute("xmlns", "");
}
else //#BOB . I added this.
{
}
// NOTE that this may break other nodes within this Element's
// subtree, if they're already using the default namespaces.
// They will be repaired when we reach them.
}
}
//#######################################
//# Examine and polish the attributes
//#######################################
for (int i=0; i<nrAttrs ; i++)// all non-namespace Attrs of Element
{
continue;
continue;
{
/*
if attribute has no prefix (default namespace decl does not apply to attributes)
OR
attribute prefix is not declared
OR
conflict: attribute has a prefix that conflicts with a binding
already active in scope
*/
{
//namespaceURI matches an in scope declaration of one or more prefixes)
if ( prefixForNS.size() > 0 )
{
// pick the most local binding available;
// if there is more than one pick one arbitrarily
//==> change attribute's prefix.
}
else
{
// the current prefix is not null and it has no in scope declaration)
{
//==> declare this prefix
}
else
{
// find a prefix following the pattern "NS" +index (starting at 1)
// make sure this prefix is not declared in the current scope.
// create a local namespace declaration attribute
//==> declare this prefix
char buf[16];
//==> change attribute's prefix.
}
}
}
}
else // Attr has no namespace URI
{
// Attr has no localName
{
// DOM Level 1 node
/*
==> if in process of validation against a namespace aware schema
(i.e XML Schema) report a fatal error: the processor can not recover
in this situation.
Otherwise, report an error: no namespace fixup will be performed on this node.
*/
printf("normalizeNamespaces: no local name for attribute\n");
}
else
{
// attr has no namespace URI and no prefix
// no action is required, since attrs don't use default
//==> do nothing
}
}
} // end for-all-Attrs
//#######################################
//# Recursively normalize children
//#######################################
{
continue;
}
}
/*#########################################################################
## TextImpl
#########################################################################*/
/**
*
*/
{
nodeName = "#text";
}
/**
*
*/
{
nodeName = "#text";
}
/**
*
*/
{
}
/**
*
*/
throw(DOMException)
{
return NULL;
}
/**
*
*/
{
return false;
}
/**
*
*/
{
return nodeValue;
}
/**
*
*/
throw(DOMException)
{
return NULL;
}
/*#########################################################################
## CommentImpl
#########################################################################*/
/**
*
*/
{
nodeName = "#comment";
}
/**
*
*/
{
nodeName = "#comment";
}
/**
*
*/
{
}
/*#########################################################################
## UserDataHandlerImpl
#########################################################################*/
/**
*
*/
{
}
/**
*
*/
{
}
/**
*
*/
const DOMString &/*key*/,
const DOMUserData */*data*/,
const NodePtr /*src*/,
const NodePtr /*dst*/)
{
//do nothing. do we need anything here?
}
/*#########################################################################
## DOMErrorImpl
#########################################################################*/
/**
*
*/
{
}
/**
*
*/
{
}
/**
*
*/
unsigned short DOMErrorImpl::getSeverity()
{
return severity;
}
/**
*
*/
{
return message;
}
/**
*
*/
{
return type;
}
/**
*
*/
{
return NULL;
}
/**
*
*/
{
return NULL;
}
/**
*
*/
{
//really should fill this in
return NULL;
}
/*#########################################################################
## DOMErrorHandlerImpl
#########################################################################*/
/**
*
*/
{
}
/**
*
*/
{
}
/**
*
*/
{
if (!error)
return false;
return true;
}
/*#########################################################################
## DOMLocatorImpl
#########################################################################*/
/**
*
*/
{
}
/**
*
*/
{
}
/**
*
*/
long DOMLocatorImpl::getLineNumber()
{
return lineNumber;
}
/**
*
*/
long DOMLocatorImpl::getColumnNumber()
{
return columnNumber;
}
/**
*
*/
long DOMLocatorImpl::getByteOffset()
{
return byteOffset;
}
/**
*
*/
long DOMLocatorImpl::getUtf16Offset()
{
return utf16Offset;
}
/**
*
*/
{
return relatedNode;
}
/**
*
*/
{
return uri;
}
/*#########################################################################
## DOMConfigurationImpl
#########################################################################*/
/**
*
*/
{
}
/**
*
*/
{
}
/**
*
*/
{
}
/**
*
*/
throw (DOMException)
{
return NULL;
}
/**
*
*/
const DOMUserData */*data*/)
{
return false;
}
/**
*
*/
{
return NULL;
}
/*#########################################################################
## CDATASectionImpl
#########################################################################*/
/**
*
*/
{
nodeName = "#cdata-section";
}
/**
*
*/
: TextImpl()
{
nodeName = "#cdata-section";
}
/**
*
*/
{
}
/*#########################################################################
## DocumentTypeImpl
#########################################################################*/
/**
*
*/
const DOMString& thePublicId,
const DOMString& theSystemId)
: NodeImpl()
{
}
/**
*
*/
{
}
/**
*
*/
{
return nodeName;
}
/**
*
*/
{
return entities;
}
/**
*
*/
{
return notations;
}
/**
*
*/
{
return publicId;
}
/**
*
*/
{
return systemId;
}
/**
*
*/
{
return DOMString("");
}
/*#########################################################################
## NotationImpl
#########################################################################*/
/**
*
*/
{
}
/**
*
*/
{
}
/**
*
*/
{
return publicId;
}
/**
*
*/
{
return systemId;
}
/*#########################################################################
## EntityImpl
#########################################################################*/
/**
*
*/
{
}
/**
*
*/
{
}
/**
*
*/
EntityImpl::~EntityImpl()
{
}
/**
*
*/
{
return publicId;
}
/**
*
*/
{
return systemId;
}
/**
*
*/
{
return notationName;
}
/**
*
*/
{
return inputEncoding;
}
/**
*
*/
{
return xmlEncoding;
}
/**
*
*/
{
return xmlVersion;
}
/*#########################################################################
## EntityReferenceImpl
#########################################################################*/
/**
*
*/
{
}
/**
*
*/
: NodeImpl()
{
}
/**
*
*/
{
}
/*#########################################################################
## ProcessingInstructionImpl
#########################################################################*/
/**
*
*/
{
}
/**
*
*/
: NodeImpl()
{
}
/**
*
*/
{
}
/**
*
*/
{
return nodeName;
}
/**
*
*/
{
return nodeValue;
}
/**
*
*/
{
//do something here
}
/*#########################################################################
## DocumentFragmentImpl
#########################################################################*/
/**
*
*/
{
nodeName = "#document-fragment";
}
/**
*
*/
{
nodeName = "#document-fragment";
}
/**
*
*/
{
}
/*#########################################################################
## DocumentImpl
#########################################################################*/
/**
*
*/
{
return doctype;
}
/**
*
*/
{
return parent;
}
/**
*
*/
{
return documentElement;
}
/**
*
*/
throw(DOMException)
{
return elem;
}
/**
*
*/
{
return frag;
}
/**
*
*/
{
return text;
}
/**
*
*/
{
return comment;
}
/**
*
*/
throw(DOMException)
{
return cdata;
}
/**
*
*/
throw(DOMException)
{
return pi;
}
/**
*
*/
throw(DOMException)
{
return attr;
}
/**
*
*/
throw(DOMException)
{
return ref;
}
/**
*
*/
{
return list;
}
/**
*
*/
bool /*deep*/)
throw(DOMException)
{
return NULL;
}
/**
*
*/
const DOMString& qualifiedName)
throw(DOMException)
{
return elem;
}
/**
*
*/
const DOMString& qualifiedName)
throw(DOMException)
{
return attr;
}
/**
*
*/
{
return list;
}
/**
*
*/
{
return NULL;
}
/**
*
*/
{
return inputEncoding;
}
/**
*
*/
{
return xmlEncoding;
}
/**
*
*/
bool DocumentImpl::getXmlStandalone()
{
return xmlStandalone;
}
/**
*
*/
{
xmlStandalone = val;
}
/**
*
*/
{
return xmlVersion;
}
/**
*
*/
{
}
/**
*
*/
bool DocumentImpl::getStrictErrorChecking()
{
return strictErrorChecking;
}
/**
*
*/
{
}
/**
*
*/
{
return documentURI;
}
/**
*
*/
{
//documentURI = stringCache(uri);
}
/**
*
*/
{
}
/**
*
*/
{
return domConfig;
}
/**
*
*/
void DocumentImpl::normalizeDocument()
{
//i assume that this means adjusting namespaces & prefixes
if (documentElement.get())
}
/**
*
*/
const DOMString &/*namespaceURI*/,
const DOMString &qualifiedName)
throw (DOMException)
{
return node;
}
//##################
//# Non-API methods
//##################
/**
*
*/
const DOMString &/*theNamespaceURI*/,
const DOMString &theQualifiedName,
{
nodeName = "#document";
//documentURI = stringCache(theNamespaceURI);
else
namespaceIndex = 0;
}
/**
*
*/
{
}
} //namespace dom
} //namespace w3c
} //namespace org
/*#########################################################################
## E N D O F F I L E
#########################################################################*/