blob: 9b784992152ad48ede0067a1d327d9af76c35f21 [file] [log] [blame]
/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 1999-2000 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 "Xalan" 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) 1999, International
* Business Machines, Inc., http://www.ibm.com. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
#include "XalanSourceTreeDocument.hpp"
#include <xercesc/sax/AttributeList.hpp>
#include <xercesc/sax2/Attributes.hpp>
#include <XalanDOM/XalanDOMException.hpp>
#include <PlatformSupport/PrefixResolver.hpp>
#include <PlatformSupport/XalanUnicode.hpp>
#include <DOMSupport/DOMServices.hpp>
#include "XalanSourceTreeHelper.hpp"
static const XalanDOMString s_emptyString;
XalanSourceTreeDocument::XalanSourceTreeDocument(
bool fPoolAllText,
block_size_type theNamesStringPoolBlockSize,
bucket_count_type theNamesStringPoolBucketCount,
bucket_size_type theNamesStringPoolBucketSize,
block_size_type theValuesStringPoolBlockSize,
bucket_count_type theValuesStringPoolBucketCount,
bucket_size_type theValuesStringPoolBucketSize) :
XalanDocument(),
m_firstChild(0),
m_documentElement(0),
m_attributeAllocator(200),
m_attributeNSAllocator(50),
m_commentAllocator(20),
m_elementAllocator(200),
m_elementNSAllocator(200),
m_piAllocator(25),
m_textAllocator(200),
m_textIWSAllocator(400),
m_namesStringPool(theNamesStringPoolBlockSize, theNamesStringPoolBucketCount, theNamesStringPoolBucketSize),
m_valuesStringPool(theValuesStringPoolBlockSize, theValuesStringPoolBucketCount, theValuesStringPoolBucketSize),
m_attributesVector(),
m_nextIndexValue(2),
m_poolAllText(fPoolAllText),
m_elementsByID(),
m_unparsedEntityURIs(),
m_nonPooledStrings(),
m_stringBuffer()
{
}
XalanSourceTreeDocument::~XalanSourceTreeDocument()
{
}
const XalanDOMString&
XalanSourceTreeDocument::getNodeName() const
{
return s_nameString;
}
const XalanDOMString&
XalanSourceTreeDocument::getNodeValue() const
{
return s_emptyString;
}
XalanSourceTreeDocument::NodeType
XalanSourceTreeDocument::getNodeType() const
{
return DOCUMENT_NODE;
}
XalanNode*
XalanSourceTreeDocument::getParentNode() const
{
return 0;
}
const XalanNodeList*
XalanSourceTreeDocument::getChildNodes() const
{
throw XalanDOMException(XalanDOMException::NOT_SUPPORTED_ERR);
// Dummy return value...
return 0;
}
XalanNode*
XalanSourceTreeDocument::getFirstChild() const
{
return m_firstChild;
}
XalanNode*
XalanSourceTreeDocument::getLastChild() const
{
return m_documentElement;
}
XalanNode*
XalanSourceTreeDocument::getPreviousSibling() const
{
return 0;
}
XalanNode*
XalanSourceTreeDocument::getNextSibling() const
{
return 0;
}
const XalanNamedNodeMap*
XalanSourceTreeDocument::getAttributes() const
{
return 0;
}
XalanDocument*
XalanSourceTreeDocument::getOwnerDocument() const
{
return 0;
}
#if defined(XALAN_NO_COVARIANT_RETURN_TYPE)
XalanNode*
#else
XalanSourceTreeDocument*
#endif
XalanSourceTreeDocument::cloneNode(bool /* deep */) const
{
return 0;
}
XalanNode*
XalanSourceTreeDocument::insertBefore(
XalanNode* /* newChild */,
XalanNode* /* refChild */)
{
throw XalanDOMException(XalanDOMException::NO_MODIFICATION_ALLOWED_ERR);
// Dummy return value...
return 0;
}
XalanNode*
XalanSourceTreeDocument::replaceChild(
XalanNode* /* newChild */,
XalanNode* /* oldChild */)
{
throw XalanDOMException(XalanDOMException::NO_MODIFICATION_ALLOWED_ERR);
// Dummy return value...
return 0;
}
XalanNode*
XalanSourceTreeDocument::removeChild(XalanNode* /* oldChild */)
{
throw XalanDOMException(XalanDOMException::NO_MODIFICATION_ALLOWED_ERR);
// Dummy return value...
return 0;
}
XalanNode*
XalanSourceTreeDocument::appendChild(XalanNode* /* newChild */)
{
throw XalanDOMException(XalanDOMException::NO_MODIFICATION_ALLOWED_ERR);
// Dummy return value...
return 0;
}
bool
XalanSourceTreeDocument::hasChildNodes() const
{
return m_documentElement != 0 ? true : false;
}
void
XalanSourceTreeDocument::setNodeValue(const XalanDOMString& /* nodeValue */)
{
throw XalanDOMException(XalanDOMException::NO_MODIFICATION_ALLOWED_ERR);
}
void
XalanSourceTreeDocument::normalize()
{
throw XalanDOMException(XalanDOMException::NO_MODIFICATION_ALLOWED_ERR);
}
bool
XalanSourceTreeDocument::isSupported(
const XalanDOMString& /* feature */,
const XalanDOMString& /* version */) const
{
return false;
}
const XalanDOMString&
XalanSourceTreeDocument::getNamespaceURI() const
{
return s_emptyString;
}
const XalanDOMString&
XalanSourceTreeDocument::getPrefix() const
{
return s_emptyString;
}
const XalanDOMString&
XalanSourceTreeDocument::getLocalName() const
{
return s_nameString;
}
void
XalanSourceTreeDocument::setPrefix(const XalanDOMString& /* prefix */)
{
throw XalanDOMException(XalanDOMException::NO_MODIFICATION_ALLOWED_ERR);
}
bool
XalanSourceTreeDocument::isIndexed() const
{
return true;
}
unsigned long
XalanSourceTreeDocument::getIndex() const
{
return 1;
}
XalanElement*
XalanSourceTreeDocument::createElement(const XalanDOMString& /* tagName */)
{
throw XalanDOMException(XalanDOMException::NOT_SUPPORTED_ERR);
// Dummy return value...
return 0;
}
XalanDocumentFragment*
XalanSourceTreeDocument::createDocumentFragment()
{
throw XalanDOMException(XalanDOMException::NOT_SUPPORTED_ERR);
// Dummy return value...
return 0;
}
XalanText*
XalanSourceTreeDocument::createTextNode(const XalanDOMString& /* data */)
{
throw XalanDOMException(XalanDOMException::NOT_SUPPORTED_ERR);
// Dummy return value...
return 0;
}
XalanComment*
XalanSourceTreeDocument::createComment(const XalanDOMString& /* data */)
{
throw XalanDOMException(XalanDOMException::NOT_SUPPORTED_ERR);
// Dummy return value...
return 0;
}
XalanCDATASection*
XalanSourceTreeDocument::createCDATASection(const XalanDOMString& /* data */)
{
throw XalanDOMException(XalanDOMException::NOT_SUPPORTED_ERR);
// Dummy return value...
return 0;
}
XalanProcessingInstruction*
XalanSourceTreeDocument::createProcessingInstruction(
const XalanDOMString& /* target */,
const XalanDOMString& /* data */)
{
throw XalanDOMException(XalanDOMException::NOT_SUPPORTED_ERR);
// Dummy return value...
return 0;
}
XalanAttr*
XalanSourceTreeDocument::createAttribute(const XalanDOMString& /* name */)
{
throw XalanDOMException(XalanDOMException::NOT_SUPPORTED_ERR);
// Dummy return value...
return 0;
}
XalanEntityReference*
XalanSourceTreeDocument::createEntityReference(const XalanDOMString& /* name */)
{
throw XalanDOMException(XalanDOMException::NOT_SUPPORTED_ERR);
// Dummy return value...
return 0;
}
XalanDocumentType*
XalanSourceTreeDocument::getDoctype() const
{
return 0;
}
XalanDOMImplementation*
XalanSourceTreeDocument::getImplementation() const
{
return 0;
}
XalanElement*
XalanSourceTreeDocument::getDocumentElement() const
{
return m_documentElement;
}
XalanNodeList*
XalanSourceTreeDocument::getElementsByTagName(const XalanDOMString& /* tagname */) const
{
throw XalanDOMException(XalanDOMException::NOT_SUPPORTED_ERR);
return 0;
}
XalanNode*
XalanSourceTreeDocument::importNode(
XalanNode* /* importedNode */,
bool /* deep */)
{
throw XalanDOMException(XalanDOMException::NO_MODIFICATION_ALLOWED_ERR);
return 0;
}
XalanElement*
XalanSourceTreeDocument::createElementNS(
const XalanDOMString& /* namespaceURI */,
const XalanDOMString& /* qualifiedName */)
{
throw XalanDOMException(XalanDOMException::NOT_SUPPORTED_ERR);
return 0;
}
XalanAttr*
XalanSourceTreeDocument::createAttributeNS(
const XalanDOMString& /* namespaceURI */,
const XalanDOMString& /* qualifiedName */)
{
throw XalanDOMException(XalanDOMException::NOT_SUPPORTED_ERR);
return 0;
}
XalanNodeList*
XalanSourceTreeDocument::getElementsByTagNameNS(
const XalanDOMString& /* namespaceURI */,
const XalanDOMString& /* localName */) const
{
// Not supported
return 0;
}
XalanElement*
XalanSourceTreeDocument::getElementById(const XalanDOMString& elementId) const
{
const ElementByIDMapType::const_iterator i =
m_elementsByID.find(c_wstr(elementId));
if (i == m_elementsByID.end())
{
return 0;
}
else
{
return (*i).second;
}
}
static bool
hasXMLNamespaceAttribute(const AttributeList& attrs)
{
const unsigned int theLength = attrs.getLength();
for (unsigned int i = 0; i < theLength; ++i)
{
const XalanDOMChar* const theName =
attrs.getName(i);
assert(theName != 0);
if(equals(theName, DOMServices::s_XMLNamespacePrefix) == true)
{
return true;
}
}
return false;
}
static bool
hasXMLNamespaceAttribute(const Attributes& attrs)
{
const unsigned int theLength = attrs.getLength();
for (unsigned int i = 0; i < theLength; ++i)
{
const XalanDOMChar* const theName =
attrs.getQName(i);
assert(theName != 0);
if(equals(theName, DOMServices::s_XMLNamespacePrefix) == true)
{
return true;
}
}
return false;
}
XalanSourceTreeElement*
XalanSourceTreeDocument::createElementNode(
const XalanDOMChar* name,
const AttributeList& attrs,
XalanNode* theParentNode,
XalanNode* thePreviousSibling,
XalanNode* theNextSibling,
bool fAddXMLNamespaceAttribute)
{
// We might have typedef'ed this to something smaller than unsigned int.
AttributesCountType theAttributeCount = AttributesCountType(attrs.getLength());
// assert that we didn't lose anything...
assert(theAttributeCount == attrs.getLength());
if (fAddXMLNamespaceAttribute == true)
{
if (hasXMLNamespaceAttribute(attrs) == true)
{
fAddXMLNamespaceAttribute = false;
}
else
{
++theAttributeCount;
}
}
XalanSourceTreeAttr** const theAttributeVector =
theAttributeCount == 0 ? 0 : m_attributesVector.allocate(theAttributeCount);
XalanSourceTreeElement* const theNewElement =
m_elementAllocator.create(
m_namesStringPool.get(name),
this,
theAttributeVector,
theAttributeCount,
theParentNode,
thePreviousSibling,
theNextSibling,
m_nextIndexValue++);
assert(theNewElement != 0);
size_t theIndex = 0;
if (fAddXMLNamespaceAttribute == true)
{
// The constructor parameters for AttrNS are:
//
// name
// local name
// namespace URI
// prefix
// value
// owner element
// index
//
theAttributeVector[theIndex] =
m_attributeNSAllocator.create(
m_namesStringPool.get(DOMServices::s_XMLNamespacePrefix),
m_namesStringPool.get(DOMServices::s_XMLString),
m_namesStringPool.get(DOMServices::s_XMLNamespacePrefixURI),
m_namesStringPool.get(DOMServices::s_XMLNamespace),
m_valuesStringPool.get(DOMServices::s_XMLNamespaceURI),
theNewElement,
m_nextIndexValue++);
assert(theAttributeVector[theIndex] != 0);
++theIndex;
}
const AttributesCountType theSAXAttributeCount = attrs.getLength();
// Now, create the attributes...
for(AttributesCountType i = 0; i < theSAXAttributeCount; ++i, ++theIndex)
{
const XalanDOMChar* const theName =
attrs.getName(i);
assert(theName != 0);
const XalanDOMChar* const theValue =
attrs.getValue(i);
assert(theValue != 0);
theAttributeVector[theIndex] =
m_attributeAllocator.create(
m_namesStringPool.get(theName),
m_valuesStringPool.get(theValue),
theNewElement,
m_nextIndexValue++);
assert(theAttributeVector[theIndex] != 0);
}
return theNewElement;
}
XalanSourceTreeElement*
XalanSourceTreeDocument::createElementNode(
const XalanDOMChar* tagName,
const AttributeList& attrs,
const PrefixResolver& thePrefixResolver,
XalanNode* theParentNode,
XalanNode* thePreviousSibling,
XalanNode* theNextSibling,
bool fAddXMLNamespaceAttribute)
{
// We might have typedef'ed this to something smaller than unsigned int.
AttributesCountType theAttributeCount = AttributesCountType(attrs.getLength());
// assert that we didn't lose anything...
assert(theAttributeCount == attrs.getLength());
if (fAddXMLNamespaceAttribute == true)
{
if (hasXMLNamespaceAttribute(attrs) == true)
{
fAddXMLNamespaceAttribute = false;
}
else
{
++theAttributeCount;
}
}
XalanSourceTreeAttr** const theAttributeVector =
theAttributeCount == 0 ? 0 : m_attributesVector.allocate(theAttributeCount);
XalanSourceTreeElement* const theNewElement =
createElementNode(
tagName,
theAttributeVector,
theAttributeCount,
theParentNode,
thePreviousSibling,
theNextSibling,
thePrefixResolver);
assert(theNewElement != 0);
size_t theIndex = 0;
if (fAddXMLNamespaceAttribute == true)
{
// The constructor parameters for AttrNS are:
//
// name
// local name
// namespace URI
// prefix
// value
// owner element
// index
//
theAttributeVector[theIndex] =
m_attributeNSAllocator.create(
m_namesStringPool.get(DOMServices::s_XMLNamespacePrefix),
m_namesStringPool.get(DOMServices::s_XMLString),
m_namesStringPool.get(DOMServices::s_XMLNamespacePrefixURI),
m_namesStringPool.get(DOMServices::s_XMLNamespace),
m_valuesStringPool.get(DOMServices::s_XMLNamespaceURI),
theNewElement,
m_nextIndexValue++);
assert(theAttributeVector[theIndex] != 0);
++theIndex;
}
const AttributesCountType theSAXAttributeCount = attrs.getLength();
// Now, create the attributes...
for(AttributesCountType i = 0; i < theSAXAttributeCount; ++i, ++theIndex)
{
const XalanDOMChar* const theName =
attrs.getName(i);
assert(theName != 0);
const XalanDOMChar* const theValue =
attrs.getValue(i);
assert(theValue != 0);
theAttributeVector[theIndex] =
createAttribute(
theName,
theValue,
theNewElement,
thePrefixResolver);
assert(theAttributeVector[theIndex] != 0);
}
return theNewElement;
}
inline const XalanDOMString&
getElementNodePrefix(
const XalanDOMChar* qname,
XalanDOMStringPool* theStringPool,
XalanDOMString::size_type theLength,
XalanDOMString::size_type theColonIndex)
{
if(theColonIndex == theLength)
{
return theStringPool->get(XalanDOMString());
}
else
{
return theStringPool->get(qname, theColonIndex);
}
}
XalanSourceTreeElement*
XalanSourceTreeDocument::createElementNode(
const XalanDOMChar* uri,
const XalanDOMChar* localname,
const XalanDOMChar* qname,
const Attributes& attrs,
XalanNode* theParentNode,
XalanNode* thePreviousSibling,
XalanNode* theNextSibling,
bool fAddXMLNamespaceAttribute)
{
// We might have typedef'ed this to something smaller than unsigned int.
AttributesCountType theAttributeCount = AttributesCountType(attrs.getLength());
// assert that we didn't lose anything...
assert(theAttributeCount == attrs.getLength());
if (fAddXMLNamespaceAttribute == true)
{
if (hasXMLNamespaceAttribute(attrs) == true)
{
fAddXMLNamespaceAttribute = false;
}
else
{
++theAttributeCount;
}
}
XalanSourceTreeAttr** const theAttributeVector =
theAttributeCount == 0 ? 0 : m_attributesVector.allocate(theAttributeCount);
const XalanDOMString::size_type theColonIndex = indexOf(qname, XalanUnicode::charColon);
const XalanDOMString::size_type theLength = length(qname);
XalanSourceTreeElement* const theNewElement =
m_elementNSAllocator.create(
m_namesStringPool.get(qname),
m_namesStringPool.get(localname),
m_namesStringPool.get(uri),
// This is the prefix...
getElementNodePrefix(qname, &m_namesStringPool, theLength, theColonIndex),
this,
theAttributeVector,
theAttributeCount,
theParentNode,
thePreviousSibling,
theNextSibling,
m_nextIndexValue++);
if (theAttributeCount != 0)
{
createAttributes(attrs, theAttributeVector, theNewElement, fAddXMLNamespaceAttribute);
}
return theNewElement;
}
XalanSourceTreeElement*
XalanSourceTreeDocument::createElementNode(
const XalanDOMChar* name,
const Attributes& attrs,
XalanNode* theParentNode,
XalanNode* thePreviousSibling,
XalanNode* theNextSibling,
bool fAddXMLNamespaceAttribute)
{
// We might have typedef'ed this to something smaller than unsigned int.
AttributesCountType theAttributeCount = AttributesCountType(attrs.getLength());
// assert that we didn't lose anything...
assert(theAttributeCount == attrs.getLength());
if (fAddXMLNamespaceAttribute == true)
{
if (hasXMLNamespaceAttribute(attrs) == true)
{
fAddXMLNamespaceAttribute = false;
}
else
{
++theAttributeCount;
}
}
XalanSourceTreeAttr** const theAttributeVector =
theAttributeCount == 0 ? 0 : m_attributesVector.allocate(theAttributeCount);
assert(indexOf(name, XalanUnicode::charColon) == length(name));
XalanSourceTreeElement* const theNewElement =
m_elementAllocator.create(
m_namesStringPool.get(name),
this,
theAttributeVector,
theAttributeCount,
theParentNode,
thePreviousSibling,
theNextSibling,
m_nextIndexValue++);
if (theAttributeCount != 0)
{
createAttributes(attrs, theAttributeVector, theNewElement, fAddXMLNamespaceAttribute);
}
return theNewElement;
}
XalanSourceTreeComment*
XalanSourceTreeDocument::createCommentNode(
const XalanDOMChar* data,
XalanDOMString::size_type length,
XalanNode* theParentNode,
XalanNode* thePreviousSibling,
XalanNode* theNextSibling)
{
return m_commentAllocator.create(
m_valuesStringPool.get(data, length),
this,
theParentNode,
thePreviousSibling,
theNextSibling,
m_nextIndexValue++);
}
XalanSourceTreeProcessingInstruction*
XalanSourceTreeDocument::createProcessingInstructionNode(
const XalanDOMChar* target,
const XalanDOMChar* data,
XalanNode* theParentNode,
XalanNode* thePreviousSibling,
XalanNode* theNextSibling)
{
assert(target != 0);
assert(data != 0);
return m_piAllocator.create(
m_namesStringPool.get(target),
m_valuesStringPool.get(data),
this,
theParentNode,
thePreviousSibling,
theNextSibling,
m_nextIndexValue++);
}
inline const XalanDOMString&
XalanSourceTreeDocument::getTextNodeString(
const XalanDOMChar* chars,
XalanDOMString::size_type length)
{
if (m_poolAllText == true)
{
return m_valuesStringPool.get(chars, length);
}
else
{
const StringCollectionType::iterator theIterator =
m_nonPooledStrings.insert(m_nonPooledStrings.end(), XalanDOMString());
XalanDOMString& theString = *theIterator;
assign(theString, chars, length);
assert(length == ::length(theString));
return theString;
}
}
const XalanDOMString*
XalanSourceTreeDocument::getNamespaceForPrefix(
const XalanDOMChar* theName,
const PrefixResolver& thePrefixResolver,
XalanDOMString& thePrefix,
bool fUseDefault)
{
const XalanDOMString::size_type theLength = length(theName);
const XalanDOMString::size_type theColonIndex = indexOf(theName, XalanUnicode::charColon);
if (theColonIndex != theLength)
{
// Get the prefix from theName...
assign(thePrefix, theName, theColonIndex);
assert(length(thePrefix) != 0);
return thePrefixResolver.getNamespaceForPrefix(thePrefix);
}
else
{
clear(thePrefix);
if (fUseDefault == false)
{
return 0;
}
else
{
return thePrefixResolver.getNamespaceForPrefix(s_emptyString);
}
}
}
XalanSourceTreeText*
XalanSourceTreeDocument::createTextNode(
const XalanDOMChar* chars,
XalanDOMString::size_type length,
XalanNode* theParentNode,
XalanNode* thePreviousSibling,
XalanNode* theNextSibling)
{
assert(chars != 0);
if (isXMLWhitespace(chars, 0, length) == true)
{
const XalanDOMString& theString = m_valuesStringPool.get(chars, length);
return m_textIWSAllocator.create(
theString,
theParentNode,
thePreviousSibling,
theNextSibling,
m_nextIndexValue++);
}
else
{
return m_textAllocator.create(
getTextNodeString(chars, length),
theParentNode,
thePreviousSibling,
theNextSibling,
m_nextIndexValue++);
}
}
XalanSourceTreeText*
XalanSourceTreeDocument::createTextIWSNode(
const XalanDOMChar* chars,
XalanDOMString::size_type length,
XalanNode* theParentNode,
XalanNode* thePreviousSibling,
XalanNode* theNextSibling)
{
assert(chars != 0);
return m_textIWSAllocator.create(
m_valuesStringPool.get(chars, length),
theParentNode,
thePreviousSibling,
theNextSibling,
m_nextIndexValue++);
}
void
XalanSourceTreeDocument::unparsedEntityDeclaration(
const XalanDOMChar* name,
const XalanDOMChar* publicId,
const XalanDOMChar* systemId,
const XalanDOMChar* notationName)
{
m_unparsedEntityURIs[XalanDOMString(name)] = XalanDOMString(systemId);
}
const XalanDOMString&
XalanSourceTreeDocument::getUnparsedEntityURI(const XalanDOMString& theName) const
{
const UnparsedEntityURIMapType::const_iterator i =
m_unparsedEntityURIs.find(theName);
if (i != m_unparsedEntityURIs.end())
{
return (*i).second;
}
else
{
return s_emptyString;
}
}
XalanSourceTreeAttr*
XalanSourceTreeDocument::createAttribute(
const XalanDOMChar* theName,
const XalanDOMChar* theValue,
XalanSourceTreeElement* theOwnerElement,
const PrefixResolver& thePrefixResolver)
{
// Get the namespace for the theName. Since attributes do not use
// the default namespace, make sure we don't get it...
const XalanDOMString* const theNamespace =
getNamespaceForPrefix(
theName,
thePrefixResolver,
m_stringBuffer,
false);
assert(theNamespace == 0 && length(m_stringBuffer) == 0 ||
theNamespace != 0 && length(m_stringBuffer) != 0);
if (theNamespace == 0 || length(*theNamespace) == 0)
{
return m_attributeAllocator.create(
m_namesStringPool.get(theName),
m_valuesStringPool.get(theValue),
theOwnerElement,
m_nextIndexValue++);
}
else
{
// There must be a prefix, so we don't have to check to see if
// we got one...
// The constructor parameters for AttrNS are:
//
// name
// local name
// namespace URI
// prefix
// value
// owner element
// index
//
return m_attributeNSAllocator.create(
m_namesStringPool.get(theName),
m_namesStringPool.get(theName + length(m_stringBuffer) + 1),
m_namesStringPool.get(*theNamespace),
// This is the prefix...
m_namesStringPool.get(m_stringBuffer),
m_valuesStringPool.get(theValue),
theOwnerElement,
m_nextIndexValue++);
}
}
XalanSourceTreeElement*
XalanSourceTreeDocument::createElementNode(
const XalanDOMChar* theTagName,
XalanSourceTreeAttr** theAttributeVector,
AttributesCountType theAttributeCount,
XalanNode* theParentNode,
XalanNode* thePreviousSibling,
XalanNode* theNextSibling,
const PrefixResolver& thePrefixResolver)
{
const XalanDOMString* const theNamespace =
getNamespaceForPrefix(
theTagName,
thePrefixResolver,
m_stringBuffer,
true);
if (theNamespace == 0 || length(*theNamespace) == 0)
{
// the prefix was returned by getNamespaceForPrefix()...
assert(length(m_stringBuffer) == 0);
return m_elementAllocator.create(
m_namesStringPool.get(theTagName),
this,
theAttributeVector,
theAttributeCount,
theParentNode,
thePreviousSibling,
theNextSibling,
m_nextIndexValue++);
}
else
{
// We need figure out if there's a prefix on theTagName. If not,
// the local name is the same as the tag name. Otherwise, we need
// to remove the prefix and the ':' that separates them. If
// m_stringBuffer is of length 0, there's no prefix.
const XalanDOMString::size_type thePrefixLength = length(m_stringBuffer);
const XalanDOMChar* const theLocalName =
thePrefixLength == 0 ? theTagName : theTagName + thePrefixLength + 1;
// The constructor parameters for ElementNS are:
//
// tag name
// local name
// namespace URI
// prefix
// owner document
// attributes
// attribute count
// parent element
// previous sibling
// next sibling
// index
//
return m_elementNSAllocator.create(
m_namesStringPool.get(theTagName),
m_namesStringPool.get(theLocalName),
m_namesStringPool.get(*theNamespace),
m_namesStringPool.get(m_stringBuffer),
this,
theAttributeVector,
theAttributeCount,
theParentNode,
thePreviousSibling,
theNextSibling,
m_nextIndexValue++);
}
}
void
XalanSourceTreeDocument::createAttributes(
const Attributes& theAttributes,
XalanSourceTreeAttr** theAttributeVector,
XalanSourceTreeElement* theOwnerElement,
bool fAddXMLNamespaceAttribute)
{
size_t theIndex = 0;
if (fAddXMLNamespaceAttribute == true)
{
// The constructor parameters for AttrNS are:
//
// name
// local name
// namespace URI
// prefix
// value
// owner element
// index
//
theAttributeVector[theIndex] =
m_attributeNSAllocator.create(
m_namesStringPool.get(DOMServices::s_XMLNamespacePrefix),
m_namesStringPool.get(DOMServices::s_XMLString),
m_namesStringPool.get(DOMServices::s_XMLNamespacePrefixURI),
m_namesStringPool.get(DOMServices::s_XMLNamespace),
m_valuesStringPool.get(DOMServices::s_XMLNamespaceURI),
theOwnerElement,
m_nextIndexValue++);
++theIndex;
}
const AttributesCountType theSAXAttributeCount = theAttributes.getLength();
// Now, create the attributes...
for(AttributesCountType i = 0; i < theSAXAttributeCount; ++i, ++theIndex)
{
const XalanDOMChar* const theQName =
theAttributes.getQName(i);
assert(theQName != 0);
const XalanDOMChar* const theValue =
theAttributes.getValue(i);
assert(theValue != 0);
const XalanDOMChar* const theURI =
theAttributes.getURI(i);
if (length(theURI) == 0)
{
theAttributeVector[theIndex] =
m_attributeAllocator.create(
m_namesStringPool.get(theQName),
m_valuesStringPool.get(theValue),
theOwnerElement,
m_nextIndexValue++);
}
else
{
const XalanDOMChar* const theLocalName =
theAttributes.getLocalName(i);
assert(theLocalName != 0);
const XalanDOMString::size_type theColonIndex = indexOf(theQName, XalanUnicode::charColon);
assert(theColonIndex != length(theQName));
// The constructor parameters for AttrNS are:
//
// name
// local name
// namespace URI
// prefix
// value
// owner element
// index
//
theAttributeVector[theIndex] =
m_attributeNSAllocator.create(
m_namesStringPool.get(theQName),
m_namesStringPool.get(theLocalName),
m_namesStringPool.get(theURI),
// This is the prefix...
m_namesStringPool.get(theQName, theColonIndex),
m_valuesStringPool.get(theValue),
theOwnerElement,
m_nextIndexValue++);
}
// OK, now let's see if we have an ID attribute...
const XalanDOMChar* theType =
theAttributes.getType(i);
// Look for an attribute that was declared as type ID in the DTD.
// Note that we can just save a pointer to the attribute's XalanDOMString
// data, since the attribute is guaranteed to exist for as long as the
// document does.
if (*theType == XalanUnicode::charLetter_I &&
*++theType == XalanUnicode::charLetter_D &&
*++theType == 0)
{
// The XPath says that if there are duplicate IDs, the first node is
// always returned, so use insert(), rather than []
m_elementsByID.insert(
ElementByIDMapType::value_type(
c_wstr(theAttributeVector[theIndex]->getValue()),
theOwnerElement));
}
}
}
void
XalanSourceTreeDocument::appendChildNode(XalanSourceTreeComment* theChild)
{
XalanSourceTreeHelper::appendSibling(this, m_firstChild, theChild);
}
void
XalanSourceTreeDocument::appendChildNode(XalanSourceTreeElement* theChild)
{
if (m_documentElement != 0)
{
throw XalanDOMException(XalanDOMException::HIERARCHY_REQUEST_ERR);
}
else
{
m_documentElement = theChild;
XalanSourceTreeHelper::appendSibling(this, m_firstChild, theChild);
}
}
void
XalanSourceTreeDocument::appendChildNode(XalanSourceTreeProcessingInstruction* theChild)
{
XalanSourceTreeHelper::appendSibling(this, m_firstChild, theChild);
}
static XalanDOMString s_nameString;
const XalanDOMString& XalanSourceTreeDocument::s_nameString = ::s_nameString;
void
XalanSourceTreeDocument::initialize()
{
::s_nameString = XALAN_STATIC_UCODE_STRING("#document");
}
void
XalanSourceTreeDocument::terminate()
{
releaseMemory(::s_nameString);
}