blob: 9ae34d0ff8d1aa663dedc5f1e6a0b26ea49f0721 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "XalanSourceTreeDocument.hpp"
#include <xercesc/sax/AttributeList.hpp>
#include <xercesc/sax2/Attributes.hpp>
#include <xalanc/XalanDOM/XalanDOMException.hpp>
#include <xalanc/PlatformSupport/PrefixResolver.hpp>
#include <xalanc/PlatformSupport/XalanUnicode.hpp>
#include <xalanc/DOMSupport/DOMServices.hpp>
#include "XalanSourceTreeHelper.hpp"
namespace XALAN_CPP_NAMESPACE {
static const XalanDOMString s_emptyString(XalanMemMgrs::getDummyMemMgr());
bool XalanSourceTreeDocument::s_poolAllTextNodes = false;
XalanSourceTreeDocument::XalanSourceTreeDocument(
MemoryManager& theManager,
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(theManager, eDefaultAttributeAllocatorBlockSize),
m_attributeNSAllocator(theManager, eDefaultAttributeNSAllocatorBlockSize),
m_commentAllocator(theManager, eDefaultCommentAllocatorBlockSize),
m_elementAAllocator(theManager, eDefaultElementAllocatorBlockSize),
m_elementANSAllocator(theManager, eDefaultElementNSAllocatorBlockSize),
m_elementNAAllocator(theManager, eDefaultElementAllocatorBlockSize),
m_elementNANSAllocator(theManager, eDefaultElementNSAllocatorBlockSize),
m_piAllocator(theManager, eDefaultPIAllocatorBlockSize),
m_textAllocator(theManager, eDefaultTextAllocatorBlockSize),
m_textIWSAllocator(theManager, eDefaultTextIWSAllocatorBlockSize),
m_namesStringPool(theManager, theNamesStringPoolBlockSize, theNamesStringPoolBucketCount, theNamesStringPoolBucketSize),
m_valuesStringPool(theManager, theValuesStringPoolBlockSize, theValuesStringPoolBucketCount, theValuesStringPoolBucketSize),
m_attributesVector(theManager),
m_nextIndexValue(2),
m_poolAllText(fPoolAllText),
m_elementsByID(theManager),
m_unparsedEntityURIs(theManager),
m_nonPooledStrings(theManager, theValuesStringPoolBlockSize),
m_stringBuffer(theManager)
{
}
XalanSourceTreeDocument*
XalanSourceTreeDocument::create(
MemoryManager& theManager,
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)
{
typedef XalanSourceTreeDocument ThisType;
XalanAllocationGuard theGuard(theManager, theManager.allocate(sizeof(ThisType)));
ThisType* const theResult =
new (theGuard.get()) ThisType(
theManager,
fPoolAllText,
theNamesStringPoolBlockSize,
theNamesStringPoolBucketCount,
theNamesStringPoolBucketSize,
theValuesStringPoolBlockSize,
theValuesStringPoolBucketCount,
theValuesStringPoolBucketSize);
theGuard.release();
return theResult;
}
XalanSourceTreeDocument::XalanSourceTreeDocument(
MemoryManager& theManager,
allocator_size_type theAttributeBlockSize,
allocator_size_type theAttributeNSBlockSize,
allocator_size_type theCommentBlockSize,
allocator_size_type theElementBlockSize,
allocator_size_type theElementNSBlockSize,
allocator_size_type thePIBlockSize,
allocator_size_type theTextBlockSize,
allocator_size_type theTextIWSBlockSize,
bool fPoolAllText) :
XalanDocument(),
m_firstChild(0),
m_documentElement(0),
m_attributeAllocator(theManager, theAttributeBlockSize),
m_attributeNSAllocator(theManager, theAttributeNSBlockSize),
m_commentAllocator(theManager, theCommentBlockSize),
m_elementAAllocator(theManager, theElementBlockSize),
m_elementANSAllocator(theManager, theElementNSBlockSize),
m_elementNAAllocator(theManager, theElementBlockSize),
m_elementNANSAllocator(theManager, theElementNSBlockSize),
m_piAllocator(theManager, thePIBlockSize),
m_textAllocator(theManager, theTextBlockSize),
m_textIWSAllocator(theManager, theTextIWSBlockSize),
m_namesStringPool(theManager, eDefaultNamesStringPoolBlockSize, eDefaultNamesStringPoolBucketCount, eDefaultNamesStringPoolBucketSize),
m_valuesStringPool(theManager, eDefaultValuesStringPoolBlockSize, eDefaultValuesStringPoolBucketCount, eDefaultValuesStringPoolBucketSize),
m_attributesVector(theManager),
m_nextIndexValue(2),
m_poolAllText(fPoolAllText),
m_elementsByID(theManager),
m_unparsedEntityURIs(theManager),
m_nonPooledStrings(theManager, eDefaultValuesStringPoolBlockSize),
m_stringBuffer(theManager)
{
}
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;
}
const XalanDOMString&
XalanSourceTreeDocument::getNamespaceURI() const
{
return s_emptyString;
}
const XalanDOMString&
XalanSourceTreeDocument::getPrefix() const
{
return s_emptyString;
}
const XalanDOMString&
XalanSourceTreeDocument::getLocalName() const
{
return s_nameString;
}
bool
XalanSourceTreeDocument::isIndexed() const
{
return true;
}
XalanSourceTreeDocument::IndexType
XalanSourceTreeDocument::getIndex() const
{
return 1;
}
XalanElement*
XalanSourceTreeDocument::getDocumentElement() const
{
return m_documentElement;
}
XalanElement*
XalanSourceTreeDocument::getElementById(const XalanDOMString& elementId) const
{
const ElementByIDMapType::const_iterator i =
m_elementsByID.find(elementId.c_str());
if (i == m_elementsByID.end())
{
return 0;
}
else
{
return (*i).second;
}
}
static bool
hasXMLNamespaceAttribute(const AttributeListType& attrs)
{
const XalanSize_t theLength = attrs.getLength();
for (XalanSize_t 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 AttributesType& attrs)
{
const XalanSize_t theLength = attrs.getLength();
for (XalanSize_t 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;
}
size_t
XalanSourceTreeDocument::createAttributes(
XalanSourceTreeAttr** theAttributeVector,
const AttributeListType& attrs,
size_t theStartIndex,
XalanSourceTreeElement* theOwnerElement,
bool fCreateNamespaces,
const PrefixResolver* thePrefixResolver)
{
const XalanSize_t theSAXAttributeCount = attrs.getLength();
// Now, create the attributes...
for (XalanSize_t i = 0; i < theSAXAttributeCount; ++i)
{
const XalanDOMChar* const theName =
attrs.getName(i);
assert(theName != 0);
const bool isNamespaceNode = startsWith(theName, DOMServices::s_XMLNamespaceWithSeparator) == true ||
theName == DOMServices::s_XMLNamespace;
if ((isNamespaceNode == true && fCreateNamespaces == true) ||
(isNamespaceNode == false && fCreateNamespaces == false))
{
const XalanDOMChar* const theValue =
attrs.getValue(i);
assert(theValue != 0);
if (thePrefixResolver == 0)
{
theAttributeVector[theStartIndex] =
m_attributeAllocator.create(
m_namesStringPool.get(theName),
m_valuesStringPool.get(theValue),
theOwnerElement,
m_nextIndexValue++);
assert(theAttributeVector[theStartIndex] != 0);
}
else
{
const XalanDOMChar* theLocalName = 0;
const XalanDOMString* const theNamespace =
getNamespaceForPrefix(
theName,
*thePrefixResolver,
m_stringBuffer,
false,
&theLocalName);
if (theNamespace == 0 || theNamespace->empty() == true)
{
// the prefix was returned by getNamespaceForPrefix()...
assert(m_stringBuffer.empty() == true);
theAttributeVector[theStartIndex] =
m_attributeAllocator.create(
m_namesStringPool.get(theName),
m_valuesStringPool.get(theValue),
theOwnerElement,
m_nextIndexValue++);
assert(theAttributeVector[theStartIndex] != 0);
}
else
{
assert(theLocalName != 0);
theAttributeVector[theStartIndex] =
m_attributeNSAllocator.create(
m_namesStringPool.get(theName),
m_namesStringPool.get(theLocalName),
m_namesStringPool.get(*theNamespace),
// This is the prefix...
m_namesStringPool.get(m_stringBuffer),
m_valuesStringPool.get(theValue),
theOwnerElement,
m_nextIndexValue++);
}
}
++theStartIndex;
}
}
return theStartIndex;
}
XalanSourceTreeElement*
XalanSourceTreeDocument::createElementNode(
const XalanDOMChar* name,
const AttributeListType& attrs,
XalanNode* theParentNode,
XalanNode* thePreviousSibling,
XalanNode* theNextSibling,
bool fAddXMLNamespaceAttribute)
{
XalanSize_t theAttributeCount = attrs.getLength();
if (fAddXMLNamespaceAttribute == true)
{
if (hasXMLNamespaceAttribute(attrs) == true)
{
fAddXMLNamespaceAttribute = false;
}
else
{
++theAttributeCount;
}
}
XalanSourceTreeAttr** theAttributeVector = 0;
XalanSourceTreeElement* theNewElement = 0;
if (theAttributeCount == 0)
{
theNewElement = m_elementNAAllocator.create(
m_namesStringPool.get(name),
this,
theParentNode,
thePreviousSibling,
theNextSibling,
m_nextIndexValue++);
}
else
{
theAttributeVector = m_attributesVector.allocate(theAttributeCount);
theNewElement = m_elementAAllocator.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;
}
// Create the namespace "nodes" first...
theIndex = createAttributes(
theAttributeVector,
attrs,
theIndex,
theNewElement,
true);
// Now, create the attribute "nodes"...
theIndex = createAttributes(
theAttributeVector,
attrs,
theIndex,
theNewElement,
false);
return theNewElement;
}
XalanSourceTreeElement*
XalanSourceTreeDocument::createElementNode(
const XalanDOMChar* tagName,
const AttributeListType& attrs,
const PrefixResolver& thePrefixResolver,
XalanNode* theParentNode,
XalanNode* thePreviousSibling,
XalanNode* theNextSibling,
bool fAddXMLNamespaceAttribute)
{
XalanSize_t 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;
}
// Create the namespace "nodes" first...
theIndex = createAttributes(
theAttributeVector,
attrs,
theIndex,
theNewElement,
true,
&thePrefixResolver);
// Now, create the attribute "nodes"...
theIndex = createAttributes(
theAttributeVector,
attrs,
theIndex,
theNewElement,
false,
&thePrefixResolver);
return theNewElement;
}
inline const XalanDOMString&
getElementNodePrefix(
MemoryManager& theManager,
const XalanDOMChar* qname,
XalanDOMStringPool* theStringPool,
XalanDOMString::size_type theLength,
XalanDOMString::size_type theColonIndex)
{
if(theColonIndex == theLength)
{
return theStringPool->get(XalanDOMString( theManager));
}
else
{
return theStringPool->get(qname, theColonIndex);
}
}
XalanSourceTreeElement*
XalanSourceTreeDocument::createElementNode(
const XalanDOMChar* uri,
const XalanDOMChar* localname,
const XalanDOMChar* qname,
const AttributesType& attrs,
XalanNode* theParentNode,
XalanNode* thePreviousSibling,
XalanNode* theNextSibling,
bool fAddXMLNamespaceAttribute)
{
XalanSize_t theAttributeCount = attrs.getLength();
if (fAddXMLNamespaceAttribute == true)
{
if (hasXMLNamespaceAttribute(attrs) == true)
{
fAddXMLNamespaceAttribute = false;
}
else
{
++theAttributeCount;
}
}
XalanSourceTreeAttr** theAttributeVector = 0;
XalanSourceTreeElement* theNewElement = 0;
const XalanDOMString::size_type theColonIndex = indexOf(qname, XalanUnicode::charColon);
const XalanDOMString::size_type theLength = length(qname);
if (theAttributeCount == 0)
{
theNewElement = m_elementNANSAllocator.create(
m_namesStringPool.get(qname),
m_namesStringPool.get(localname),
m_namesStringPool.get(uri),
// This is the prefix...
getElementNodePrefix( getMemoryManager() , qname, &m_namesStringPool, theLength, theColonIndex),
this,
theParentNode,
thePreviousSibling,
theNextSibling,
m_nextIndexValue++);
}
else
{
theAttributeVector = m_attributesVector.allocate(theAttributeCount);
theNewElement = m_elementANSAllocator.create(
m_namesStringPool.get(qname),
m_namesStringPool.get(localname),
m_namesStringPool.get(uri),
// This is the prefix...
getElementNodePrefix( getMemoryManager() ,qname, &m_namesStringPool, theLength, theColonIndex),
this,
theAttributeVector,
theAttributeCount,
theParentNode,
thePreviousSibling,
theNextSibling,
m_nextIndexValue++);
createAttributes(attrs, theAttributeVector, theNewElement, fAddXMLNamespaceAttribute);
}
return theNewElement;
}
XalanSourceTreeElement*
XalanSourceTreeDocument::createElementNode(
const XalanDOMChar* name,
const AttributesType& attrs,
XalanNode* theParentNode,
XalanNode* thePreviousSibling,
XalanNode* theNextSibling,
bool fAddXMLNamespaceAttribute)
{
assert(indexOf(name, XalanUnicode::charColon) == length(name));
XalanSize_t theAttributeCount = attrs.getLength();
if (fAddXMLNamespaceAttribute == true)
{
if (hasXMLNamespaceAttribute(attrs) == true)
{
fAddXMLNamespaceAttribute = false;
}
else
{
++theAttributeCount;
}
}
XalanSourceTreeAttr** theAttributeVector = 0;
XalanSourceTreeElement* theNewElement = 0;
if (theAttributeCount == 0)
{
theNewElement = m_elementNAAllocator.create(
m_namesStringPool.get(name),
this,
theParentNode,
thePreviousSibling,
theNextSibling,
m_nextIndexValue++);
}
else
{
theAttributeVector = m_attributesVector.allocate(theAttributeCount);
theNewElement = m_elementAAllocator.create(
m_namesStringPool.get(name),
this,
theAttributeVector,
theAttributeCount,
theParentNode,
thePreviousSibling,
theNextSibling,
m_nextIndexValue++);
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
{
XalanDOMString* const theString =
m_nonPooledStrings.create(chars, length);
assert(theString != 0);
return *theString;
}
}
const XalanDOMString*
XalanSourceTreeDocument::getNamespaceForPrefix(
const XalanDOMChar* theName,
const PrefixResolver& thePrefixResolver,
XalanDOMString& thePrefix,
bool fUseDefault,
const XalanDOMChar** theLocalName)
{
const XalanDOMString::size_type theLength = length(theName);
const XalanDOMString::size_type theColonIndex = indexOf(theName, XalanUnicode::charColon);
if (theColonIndex != theLength)
{
// Get the prefix from theName...
thePrefix.assign(theName, theColonIndex);
assert(thePrefix.empty() == false);
if (theLocalName != 0)
{
*theLocalName = theName + theColonIndex + 1;
}
return thePrefixResolver.getNamespaceForPrefix(thePrefix);
}
else
{
thePrefix.clear();
if (theLocalName != 0)
{
*theLocalName = theName;
}
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, getMemoryManager())] = XalanDOMString(systemId, getMemoryManager());
}
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 && m_stringBuffer.empty() == true) ||
(theNamespace != 0 && m_stringBuffer.empty() == false));
if (theNamespace == 0 || theNamespace->empty() == true)
{
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 + m_stringBuffer.length() + 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,
XalanSize_t theAttributeCount,
XalanNode* theParentNode,
XalanNode* thePreviousSibling,
XalanNode* theNextSibling,
const PrefixResolver& thePrefixResolver)
{
const XalanDOMString* const theNamespace =
getNamespaceForPrefix(
theTagName,
thePrefixResolver,
m_stringBuffer,
true);
if (theNamespace == 0 || theNamespace->empty() == true)
{
// the prefix was returned by getNamespaceForPrefix()...
assert(m_stringBuffer.empty() == true);
if (theAttributeCount == 0)
{
return m_elementNAAllocator.create(
m_namesStringPool.get(theTagName),
this,
theParentNode,
thePreviousSibling,
theNextSibling,
m_nextIndexValue++);
}
else
{
return m_elementAAllocator.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 = m_stringBuffer.length();
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
//
if (theAttributeCount == 0)
{
return m_elementNANSAllocator.create(
m_namesStringPool.get(theTagName),
m_namesStringPool.get(theLocalName),
m_namesStringPool.get(*theNamespace),
m_namesStringPool.get(m_stringBuffer),
this,
theParentNode,
thePreviousSibling,
theNextSibling,
m_nextIndexValue++);
}
else
{
return m_elementANSAllocator.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++);
}
}
}
size_t
XalanSourceTreeDocument::createAttributes(
XalanSourceTreeAttr** theAttributeVector,
const AttributesType& theAttributes,
size_t theStartIndex,
XalanSourceTreeElement* theOwnerElement,
bool fCreateNamespaces)
{
const XalanSize_t theSAXAttributeCount = theAttributes.getLength();
// Now, create the attributes...
for (XalanSize_t i = 0; i < theSAXAttributeCount; ++i)
{
const XalanDOMChar* const theQName =
theAttributes.getQName(i);
assert(theQName != 0);
const bool isNamespaceNode = startsWith(theQName, DOMServices::s_XMLNamespaceWithSeparator) == true ||
theQName == DOMServices::s_XMLNamespace;
if ((isNamespaceNode == true && fCreateNamespaces == true) ||
(isNamespaceNode == false && fCreateNamespaces == false))
{
const XalanDOMChar* const theValue =
theAttributes.getValue(i);
assert(theValue != 0);
const XalanDOMChar* const theURI =
theAttributes.getURI(i);
assert(theURI != 0);
if (length(theURI) == 0)
{
theAttributeVector[theStartIndex] =
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[theStartIndex] =
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(
theAttributeVector[theStartIndex]->getValue().c_str(),
theOwnerElement));
}
++theStartIndex;
}
}
return theStartIndex;
}
void
XalanSourceTreeDocument::createAttributes(
const AttributesType& 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;
}
// Create the namespace "nodes" first...
theIndex = createAttributes(
theAttributeVector,
theAttributes,
theIndex,
theOwnerElement,
true);
// Now, create the attribute "nodes"...
theIndex = createAttributes(
theAttributeVector,
theAttributes,
theIndex,
theOwnerElement,
false);
}
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_staticNameString(XalanMemMgrs::getDummyMemMgr());
const XalanDOMString& XalanSourceTreeDocument::s_nameString = s_staticNameString;
static const XalanDOMChar s_document[] =
{
XalanUnicode::charNumberSign,
XalanUnicode::charLetter_d,
XalanUnicode::charLetter_o,
XalanUnicode::charLetter_c,
XalanUnicode::charLetter_u,
XalanUnicode::charLetter_m,
XalanUnicode::charLetter_e,
XalanUnicode::charLetter_n,
XalanUnicode::charLetter_t,
0
};
void
XalanSourceTreeDocument::initialize(MemoryManager& theManager)
{
XalanDOMString tmpString(s_document, theManager);
s_staticNameString.swap(tmpString);
}
void
XalanSourceTreeDocument::terminate()
{
releaseMemory(s_staticNameString, XalanMemMgrs::getDummyMemMgr());
}
}