| /* |
| * 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()); |
| } |
| |
| |
| |
| } |