| /* |
| * The Apache Software License, Version 1.1 |
| * |
| * Copyright (c) 1999-2001 The Apache Software Foundation. All rights |
| * reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * |
| * 3. The end-user documentation included with the redistribution, |
| * if any, must include the following acknowledgment: |
| * "This product includes software developed by the |
| * Apache Software Foundation (http://www.apache.org/)." |
| * Alternately, this acknowledgment may appear in the software itself, |
| * if and wherever such third-party acknowledgments normally appear. |
| * |
| * 4. The names "Xerces" and "Apache Software Foundation" must |
| * not be used to endorse or promote products derived from this |
| * software without prior written permission. For written |
| * permission, please contact apache\@apache.org. |
| * |
| * 5. Products derived from this software may not be called "Apache", |
| * nor may "Apache" appear in their name, without prior written |
| * permission of the Apache Software Foundation. |
| * |
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR |
| * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
| * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| * SUCH DAMAGE. |
| * ==================================================================== |
| * |
| * This software consists of voluntary contributions made by many |
| * individuals on behalf of the Apache Software Foundation, and was |
| * originally based on software copyright (c) 1999, International |
| * Business Machines, Inc., http://www.ibm.com . For more information |
| * on the Apache Software Foundation, please see |
| * <http://www.apache.org/>. |
| */ |
| |
| /* |
| * $Id$ |
| */ |
| |
| #include "stdafx.h" |
| #include "xml4com.h" |
| #include "XMLDOMElement.h" |
| #include "XMLDOMAttribute.h" |
| #include "XMLDOMText.h" |
| #include "XMLDOMCDATASection.h" |
| #include "XMLDOMEntityReference.h" |
| #include "XMLDOMEntity.h" |
| #include "XMLDOMProcessingInstruction.h" |
| #include "XMLDOMComment.h" |
| #include "XMLDOMDocument.h" |
| #include "XMLDOMDocumentType.h" |
| #include "XMLDOMDocumentFragment.h" |
| #include "XMLDOMNotation.h" |
| #include "XMLDOMXMLDecl.h" |
| #include "XMLDOMUtil.h" |
| #include <util/PlatformUtils.hpp> |
| #include <util/XMLUniDefs.hpp> |
| |
| |
| const OLECHAR* g_DomNodeName[] = |
| { |
| OLESTR("invalid"), |
| OLESTR("element"), |
| OLESTR("attribute"), |
| OLESTR("text"), |
| OLESTR("cdatasection"), |
| OLESTR("entityreference"), |
| OLESTR("entity"), |
| OLESTR("processinginstruction"), |
| OLESTR("comment"), |
| OLESTR("document"), |
| OLESTR("documenttype"), |
| OLESTR("documentfragment"), |
| OLESTR("notation") |
| }; |
| |
| const int g_DomNodeNameSize = sizeof(g_DomNodeName) / sizeof(OLECHAR*); |
| |
| DOMString GetText(const DOM_Node& node) |
| { |
| DOM_Node::NodeType type = static_cast<DOM_Node::NodeType> (node.getNodeType()); |
| DOMString val; |
| |
| if (DOM_Node::DOCUMENT_TYPE_NODE == type || |
| DOM_Node::NOTATION_NODE == type) |
| return val; |
| |
| if (DOM_Node::CDATA_SECTION_NODE == type || |
| DOM_Node::COMMENT_NODE == type || |
| DOM_Node::PROCESSING_INSTRUCTION_NODE == type || |
| DOM_Node::TEXT_NODE == type) { |
| val = node.getNodeValue(); |
| return val; |
| } |
| |
| DOM_NodeList l = node.getChildNodes(); |
| int length = l.getLength(); |
| if (length > 0) { |
| for (int i = 0; i < length; ++i) |
| val.appendData(GetText(l.item(i))); |
| } |
| else { |
| val = node.getNodeValue(); |
| } |
| return val; |
| } |
| |
| |
| |
| template <class Base> |
| class CComObjectPool |
| { |
| public: |
| CComObjectPool(unsigned long poolSize); |
| |
| virtual ~CComObjectPool(); |
| |
| HRESULT WINAPI CreateInstance(Base** pp); |
| |
| HRESULT Deactivate(Base* obj); |
| |
| private: |
| Base** m_pool; |
| unsigned long m_size; |
| unsigned long m_hit; |
| unsigned long m_attempt; |
| HRESULT Activate(Base* obj); |
| }; |
| |
| |
| |
| |
| template <class Base> |
| class CPooledComObject : public Base |
| { |
| public: |
| typedef Base _BaseClass; |
| CPooledComObject(void* = NULL) |
| { |
| _Module.Lock(); |
| } |
| // Set refcount to 1 to protect destruction |
| ~CPooledComObject() |
| { |
| m_dwRef = 1L; |
| FinalRelease(); |
| #ifdef _ATL_DEBUG_INTERFACES |
| _Module.DeleteNonAddRefThunk(_GetRawUnknown()); |
| #endif |
| _Module.Unlock(); |
| } |
| //If InternalAddRef or InternalRelease is undefined then your class |
| //doesn't derive from CComObjectRoot |
| STDMETHOD_(ULONG, AddRef)() {return InternalAddRef();} |
| STDMETHOD_(ULONG, Release)() |
| { |
| ULONG l = InternalRelease(); |
| if (l == 0) { |
| if(SUCCEEDED(m_pool.Deactivate(this))) { |
| FinalRelease(); |
| } |
| else |
| delete this; |
| } |
| return l; |
| } |
| //if _InternalQueryInterface is undefined then you forgot BEGIN_COM_MAP |
| STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject) |
| {return _InternalQueryInterface(iid, ppvObject);} |
| template <class Q> |
| HRESULT STDMETHODCALLTYPE QueryInterface(Q** pp) |
| { |
| return QueryInterface(__uuidof(Q), (void**)pp); |
| } |
| |
| static HRESULT WINAPI CreateInstance(Base** pp) { |
| return m_pool.CreateInstance(pp); |
| } |
| |
| private: |
| static CComObjectPool<Base> m_pool; |
| }; |
| |
| |
| |
| |
| template <class Base> |
| CComObjectPool<Base>::CComObjectPool<Base>(unsigned long poolSize) { |
| m_pool = NULL; |
| m_size = poolSize; |
| m_pool = new Base*[m_size]; |
| for(unsigned long i = 0; i < m_size; i++) |
| m_pool[i] = NULL; |
| m_hit= 0; |
| m_attempt = 0; |
| } |
| |
| template <class Base> |
| CComObjectPool<Base>::~CComObjectPool<Base>() { |
| for(unsigned long i = 0; i < m_size; i++) { |
| if(m_pool[i]) delete m_pool[i]; |
| } |
| delete [] m_pool; |
| } |
| |
| template <class Base> |
| HRESULT CComObjectPool<Base>::Deactivate(Base* obj) { |
| for(unsigned long i = 0; i < m_size; i++) { |
| if(m_pool[i] == NULL) { |
| m_pool[i] = obj; |
| return S_OK; |
| } |
| } |
| return E_FAIL; |
| } |
| |
| template <class Base> |
| HRESULT CComObjectPool<Base>::Activate(Base* p) |
| { |
| p->SetVoid(NULL); |
| p->InternalFinalConstructAddRef(); |
| HRESULT hRes = p->FinalConstruct(); |
| p->InternalFinalConstructRelease(); |
| return hRes; |
| } |
| |
| |
| template <class Base> |
| HRESULT WINAPI CComObjectPool<Base>::CreateInstance(Base** pp) { |
| ATLASSERT(pp != NULL); |
| HRESULT hRes = E_OUTOFMEMORY; |
| Base* p = NULL; |
| |
| m_attempt++; |
| |
| for(unsigned long i = 0; i < m_size; i++) { |
| if(m_pool[i]) { |
| p = m_pool[i]; |
| m_pool[i] = NULL; |
| hRes = Activate(p); |
| if (SUCCEEDED(hRes)) { |
| m_hit++; |
| break; |
| } |
| else { |
| delete p; |
| p = NULL; |
| } |
| } |
| } |
| |
| if(FAILED(hRes)) { |
| ATLTRY(p = new CPooledComObject<Base>()) |
| if (p != NULL) { |
| hRes = Activate(p); |
| if (hRes != S_OK) { |
| delete p; |
| p = NULL; |
| } |
| } |
| } |
| *pp = p; |
| return hRes; |
| } |
| |
| |
| CComObjectPool<CXMLDOMElement> CPooledComObject<CXMLDOMElement>::m_pool(6); |
| typedef CPooledComObject<CXMLDOMElement> CPooledXMLDOMElementObj; |
| |
| CComObjectPool<CXMLDOMAttribute> CPooledComObject<CXMLDOMAttribute>::m_pool(6); |
| typedef CPooledComObject<CXMLDOMAttribute> CPooledXMLDOMAttributeObj; |
| |
| CComObjectPool<CXMLDOMText> CPooledComObject<CXMLDOMText>::m_pool(6); |
| typedef CPooledComObject<CXMLDOMText> CPooledXMLDOMTextObj; |
| |
| CComObjectPool<CXMLDOMCDATASection> CPooledComObject<CXMLDOMCDATASection>::m_pool(6); |
| typedef CPooledComObject<CXMLDOMCDATASection> CPooledXMLDOMCDATASectionObj; |
| |
| CComObjectPool<CXMLDOMEntityReference> CPooledComObject<CXMLDOMEntityReference>::m_pool(6); |
| typedef CPooledComObject<CXMLDOMEntityReference> CPooledXMLDOMEntityReferenceObj; |
| |
| CComObjectPool<CXMLDOMEntity> CPooledComObject<CXMLDOMEntity>::m_pool(6); |
| typedef CPooledComObject<CXMLDOMEntity> CPooledXMLDOMEntityObj; |
| |
| CComObjectPool<CXMLDOMProcessingInstruction> CPooledComObject<CXMLDOMProcessingInstruction>::m_pool(6); |
| typedef CPooledComObject<CXMLDOMProcessingInstruction> CPooledXMLDOMProcessingInstructionObj; |
| |
| CComObjectPool<CXMLDOMComment> CPooledComObject<CXMLDOMComment>::m_pool(6); |
| typedef CPooledComObject<CXMLDOMComment> CPooledXMLDOMCommentObj; |
| |
| |
| HRESULT wrapNode(IXMLDOMDocument *pDoc, DOM_Node& node, REFIID iid, LPVOID *pVal) |
| { |
| HRESULT hr = S_OK; |
| if (NULL == pVal) |
| return E_POINTER; |
| |
| *pVal = NULL; |
| short type = node.getNodeType(); |
| |
| // the way we are constructing the wrappers is kind of fishy but oh well... |
| // the various IBM DOM wrapper classes don't ever add any members or have |
| // any v-tables so what we are doing should be safe. There isn't any other |
| // way as far as I can tell to do this.... |
| |
| switch(type) |
| { |
| case DOM_Node::ELEMENT_NODE: |
| { |
| CXMLDOMElement *pObj = NULL; |
| hr = CPooledXMLDOMElementObj::CreateInstance(&pObj); |
| if (S_OK != hr) |
| return hr; |
| |
| pObj->AddRef(); |
| pObj->SetOwnerDoc(pDoc); |
| |
| try |
| { |
| pObj->element = *(static_cast<DOM_Element*> (&node)); |
| } |
| catch(DOM_DOMException& ex) |
| { |
| pObj->Release(); |
| return MakeHRESULT(ex); |
| } |
| catch(...) |
| { |
| pObj->Release(); |
| return E_FAIL; |
| } |
| |
| hr = pObj->QueryInterface(iid, pVal); |
| if (S_OK != hr) |
| *pVal = NULL; |
| |
| pObj->Release(); |
| break; |
| } |
| case DOM_Node::ATTRIBUTE_NODE: |
| { |
| CXMLDOMAttribute *pObj = NULL; |
| hr = CPooledXMLDOMAttributeObj::CreateInstance(&pObj); |
| if (S_OK != hr) |
| return hr; |
| |
| pObj->AddRef(); |
| pObj->SetOwnerDoc(pDoc); |
| |
| try |
| { |
| pObj->attr = *(static_cast<DOM_Attr*> (&node)); |
| } |
| catch(DOM_DOMException& ex) |
| { |
| pObj->Release(); |
| return MakeHRESULT(ex); |
| } |
| catch(...) |
| { |
| pObj->Release(); |
| return E_FAIL; |
| } |
| |
| hr = pObj->QueryInterface(iid, pVal); |
| if (S_OK != hr) |
| *pVal = NULL; |
| |
| pObj->Release(); |
| break; |
| } |
| case DOM_Node::TEXT_NODE: |
| { |
| CXMLDOMText *pObj = NULL; |
| hr = CPooledXMLDOMTextObj::CreateInstance(&pObj); |
| if (S_OK != hr) |
| return hr; |
| |
| pObj->AddRef(); |
| pObj->SetOwnerDoc(pDoc); |
| |
| try |
| { |
| pObj->text = *(static_cast<DOM_Text*> (&node)); |
| } |
| catch(DOM_DOMException& ex) |
| { |
| pObj->Release(); |
| return MakeHRESULT(ex); |
| } |
| catch(...) |
| { |
| pObj->Release(); |
| return E_FAIL; |
| } |
| |
| hr = pObj->QueryInterface(iid, pVal); |
| if (S_OK != hr) |
| *pVal = NULL; |
| |
| pObj->Release(); |
| break; |
| } |
| case DOM_Node::CDATA_SECTION_NODE: |
| { |
| CXMLDOMCDATASection *pObj = NULL; |
| hr = CPooledXMLDOMCDATASectionObj::CreateInstance(&pObj); |
| if (S_OK != hr) |
| return hr; |
| |
| pObj->AddRef(); |
| pObj->SetOwnerDoc(pDoc); |
| |
| try |
| { |
| pObj->cdataSection = *(static_cast<DOM_CDATASection*> (&node)); |
| } |
| catch(DOM_DOMException& ex) |
| { |
| pObj->Release(); |
| return MakeHRESULT(ex); |
| } |
| catch(...) |
| { |
| pObj->Release(); |
| return E_FAIL; |
| } |
| |
| hr = pObj->QueryInterface(iid, pVal); |
| if (S_OK != hr) |
| *pVal = NULL; |
| |
| pObj->Release(); |
| break; |
| } |
| case DOM_Node::ENTITY_REFERENCE_NODE: |
| { |
| CXMLDOMEntityReference *pObj = NULL; |
| hr = CPooledXMLDOMEntityReferenceObj::CreateInstance(&pObj); |
| if (S_OK != hr) |
| return hr; |
| |
| pObj->AddRef(); |
| pObj->SetOwnerDoc(pDoc); |
| |
| try |
| { |
| pObj->entityReference = *(static_cast<DOM_EntityReference*> (&node)); |
| } |
| catch(DOM_DOMException& ex) |
| { |
| pObj->Release(); |
| return MakeHRESULT(ex); |
| } |
| catch(...) |
| { |
| pObj->Release(); |
| return E_FAIL; |
| } |
| |
| hr = pObj->QueryInterface(iid, pVal); |
| if (S_OK != hr) |
| *pVal = NULL; |
| |
| pObj->Release(); |
| break; |
| } |
| case DOM_Node::ENTITY_NODE: |
| { |
| CXMLDOMEntity *pObj = NULL; |
| hr = CPooledXMLDOMEntityObj::CreateInstance(&pObj); |
| if (S_OK != hr) |
| return hr; |
| |
| pObj->AddRef(); |
| pObj->SetOwnerDoc(pDoc); |
| |
| try |
| { |
| pObj->entity = *(static_cast<DOM_Entity*> (&node)); |
| } |
| catch(DOM_DOMException& ex) |
| { |
| pObj->Release(); |
| return MakeHRESULT(ex); |
| } |
| catch(...) |
| { |
| pObj->Release(); |
| return E_FAIL; |
| } |
| |
| hr = pObj->QueryInterface(iid, pVal); |
| if (S_OK != hr) |
| *pVal = NULL; |
| |
| pObj->Release(); |
| break; |
| } |
| case DOM_Node::PROCESSING_INSTRUCTION_NODE: |
| { |
| CXMLDOMProcessingInstruction *pObj = NULL; |
| hr = CPooledXMLDOMProcessingInstructionObj::CreateInstance(&pObj); |
| if (S_OK != hr) |
| return hr; |
| |
| pObj->AddRef(); |
| pObj->SetOwnerDoc(pDoc); |
| |
| try |
| { |
| pObj->processingInstruction = *(static_cast<DOM_ProcessingInstruction*> (&node)); |
| } |
| catch(DOM_DOMException& ex) |
| { |
| pObj->Release(); |
| return MakeHRESULT(ex); |
| } |
| catch(...) |
| { |
| pObj->Release(); |
| return E_FAIL; |
| } |
| |
| hr = pObj->QueryInterface(iid, pVal); |
| if (S_OK != hr) |
| *pVal = NULL; |
| |
| pObj->Release(); |
| break; |
| } |
| case DOM_Node::COMMENT_NODE: |
| { |
| CXMLDOMComment *pObj = NULL; |
| hr = CPooledXMLDOMCommentObj::CreateInstance(&pObj); |
| if (S_OK != hr) |
| return hr; |
| |
| pObj->AddRef(); |
| pObj->SetOwnerDoc(pDoc); |
| |
| try |
| { |
| pObj->comment = *(static_cast<DOM_Comment*> (&node)); |
| } |
| catch(DOM_DOMException& ex) |
| { |
| pObj->Release(); |
| return MakeHRESULT(ex); |
| } |
| catch(...) |
| { |
| pObj->Release(); |
| return E_FAIL; |
| } |
| |
| hr = pObj->QueryInterface(iid, pVal); |
| if (S_OK != hr) |
| *pVal = NULL; |
| |
| pObj->Release(); |
| break; |
| } |
| case DOM_Node::DOCUMENT_NODE: |
| { |
| CXMLDOMDocumentObj *pObj = NULL; |
| hr = CXMLDOMDocumentObj::CreateInstance(&pObj); |
| if (S_OK != hr) |
| return hr; |
| |
| pObj->AddRef(); |
| pObj->SetOwnerDoc(pDoc); |
| |
| try |
| { |
| pObj->m_Document = *(static_cast<DOM_Document*> (&node)); |
| } |
| catch(DOM_DOMException& ex) |
| { |
| pObj->Release(); |
| return MakeHRESULT(ex); |
| } |
| catch(...) |
| { |
| pObj->Release(); |
| return E_FAIL; |
| } |
| |
| hr = pObj->QueryInterface(iid, pVal); |
| if (S_OK != hr) |
| *pVal = NULL; |
| |
| pObj->Release(); |
| break; |
| } |
| case DOM_Node::DOCUMENT_TYPE_NODE: |
| { |
| CXMLDOMDocumentTypeObj *pObj = NULL; |
| hr = CXMLDOMDocumentTypeObj::CreateInstance(&pObj); |
| if (S_OK != hr) |
| return hr; |
| |
| pObj->AddRef(); |
| pObj->SetOwnerDoc(pDoc); |
| |
| try |
| { |
| pObj->documentType = *(static_cast<DOM_DocumentType*> (&node)); |
| } |
| catch(DOM_DOMException& ex) |
| { |
| pObj->Release(); |
| return MakeHRESULT(ex); |
| } |
| catch(...) |
| { |
| pObj->Release(); |
| return E_FAIL; |
| } |
| |
| hr = pObj->QueryInterface(iid, pVal); |
| if (S_OK != hr) |
| *pVal = NULL; |
| |
| pObj->Release(); |
| break; |
| } |
| case DOM_Node::DOCUMENT_FRAGMENT_NODE: |
| { |
| CXMLDOMDocumentFragmentObj *pObj = NULL; |
| hr = CXMLDOMDocumentFragmentObj::CreateInstance(&pObj); |
| if (S_OK != hr) |
| return hr; |
| |
| pObj->AddRef(); |
| pObj->SetOwnerDoc(pDoc); |
| |
| try |
| { |
| pObj->documentFragment = *(static_cast<DOM_DocumentFragment*> (&node)); |
| } |
| catch(DOM_DOMException& ex) |
| { |
| pObj->Release(); |
| return MakeHRESULT(ex); |
| } |
| catch(...) |
| { |
| pObj->Release(); |
| return E_FAIL; |
| } |
| |
| hr = pObj->QueryInterface(iid, pVal); |
| if (S_OK != hr) |
| *pVal = NULL; |
| |
| pObj->Release(); |
| break; |
| } |
| case DOM_Node::NOTATION_NODE: |
| { |
| CXMLDOMNotationObj *pObj = NULL; |
| hr = CXMLDOMNotationObj::CreateInstance(&pObj); |
| if (S_OK != hr) |
| return hr; |
| |
| pObj->AddRef(); |
| pObj->SetOwnerDoc(pDoc); |
| |
| try |
| { |
| pObj->notation = *(static_cast<DOM_Notation*> (&node)); |
| } |
| catch(DOM_DOMException& ex) |
| { |
| pObj->Release(); |
| return MakeHRESULT(ex); |
| } |
| catch(...) |
| { |
| pObj->Release(); |
| return E_FAIL; |
| } |
| |
| hr = pObj->QueryInterface(iid, pVal); |
| if (S_OK != hr) |
| *pVal = NULL; |
| |
| pObj->Release(); |
| break; |
| } |
| |
| case DOM_Node::XML_DECL_NODE: |
| { |
| CXMLDOMXMLDeclObj *pObj = NULL; |
| hr = CXMLDOMXMLDeclObj::CreateInstance(&pObj); |
| if (S_OK != hr) |
| return hr; |
| |
| pObj->AddRef(); |
| pObj->SetOwnerDoc(pDoc); |
| |
| try |
| { |
| pObj->xmlDecl = *(static_cast<DOM_XMLDecl*> (&node)); |
| } |
| catch(DOM_DOMException& ex) |
| { |
| pObj->Release(); |
| return MakeHRESULT(ex); |
| } |
| catch(...) |
| { |
| pObj->Release(); |
| return E_FAIL; |
| } |
| |
| hr = pObj->QueryInterface(iid, pVal); |
| if (S_OK != hr) |
| *pVal = NULL; |
| |
| pObj->Release(); |
| break; |
| } |
| default: |
| hr = E_NOTIMPL; |
| break; |
| } |
| |
| return hr; |
| } |
| |
| |
| class xmlstream { |
| public: |
| xmlstream() { |
| m_length = 0; |
| m_alloc = 0; |
| m_buffer = 0; |
| m_next = 0; |
| } |
| |
| ~xmlstream() { |
| delete [] m_buffer; |
| } |
| |
| xmlstream& operator<<(const XMLCh* other) { |
| // |
| // get length of string |
| // |
| unsigned long len = 0; |
| for(const XMLCh* source = other; *source; source++,len++); |
| |
| // |
| // append to stream |
| // |
| append(other,len); |
| return *this; |
| } |
| |
| xmlstream& operator<<(const DOMString& other) { |
| append(other.rawBuffer(),other.length()); |
| return *this; |
| } |
| |
| xmlstream& operator<<(const XMLCh other) { |
| append(&other,1); |
| return *this; |
| } |
| |
| BSTR SysAllocString() { |
| if(m_length > 0) |
| return SysAllocStringLen(m_buffer,m_length); |
| return 0; |
| } |
| |
| private: |
| void append(const XMLCh* other,unsigned long length) { |
| const XMLCh* source = NULL; |
| |
| if(m_length + length > m_alloc) { |
| unsigned long chunk = 4096; |
| if(length > chunk) chunk += length; |
| XMLCh* newbuf = new XMLCh[m_alloc+ chunk]; |
| m_alloc += chunk; |
| m_next = newbuf + m_length; |
| |
| // |
| // copy old content into new buffer |
| // |
| XMLCh* dest = newbuf; |
| source = m_buffer; |
| for(unsigned long i = 0; i < m_length; i++,dest++,source++) { |
| *dest = *source; |
| } |
| delete [] m_buffer; |
| m_buffer = newbuf; |
| } |
| |
| source = other; |
| for(unsigned long i = 0; i < length; i++,source++,m_next++) { |
| *m_next = *source; |
| } |
| m_length += length; |
| } |
| |
| unsigned long m_length; |
| unsigned long m_alloc; |
| XMLCh* m_buffer; |
| XMLCh* m_next; |
| }; |
| |
| |
| |
| |
| // --------------------------------------------------------------------------- |
| // outputContent |
| // |
| // Write document content from a DOMString to a C++ ostream. Escape the |
| // XML special characters (<, &, etc.) unless this is suppressed by the |
| // command line option. |
| // --------------------------------------------------------------------------- |
| void outputContent(xmlstream& target, const DOMString &toWrite) |
| { |
| |
| int length = toWrite.length(); |
| const XMLCh* chars = toWrite.rawBuffer(); |
| |
| int index; |
| for (index = 0; index < length; index++) |
| { |
| switch (chars[index]) |
| { |
| case chAmpersand : |
| target << XMLStrL("&"); |
| break; |
| |
| case chOpenAngle : |
| target << XMLStrL("<"); |
| break; |
| |
| case chCloseAngle: |
| target << XMLStrL(">"); |
| break; |
| |
| case chDoubleQuote : |
| target << XMLStrL("""); |
| break; |
| |
| default: |
| // If it is none of the special characters, print it as such |
| target << toWrite.substringData(index, 1); |
| break; |
| } |
| } |
| |
| return; |
| } |
| |
| xmlstream& operator<<(xmlstream& target, const DOM_Node& toWrite) |
| { |
| // Get the name and value out for convenience |
| DOMString nodeName = toWrite.getNodeName(); |
| DOMString nodeValue = toWrite.getNodeValue(); |
| |
| |
| switch (toWrite.getNodeType()) |
| { |
| case DOM_Node::TEXT_NODE: |
| { |
| outputContent(target, nodeValue); |
| break; |
| } |
| |
| case DOM_Node::PROCESSING_INSTRUCTION_NODE : |
| { |
| target << XMLStrL("<?") |
| << nodeName |
| << XMLStrL(' ') |
| << nodeValue |
| << XMLStrL("?>"); |
| break; |
| } |
| |
| case DOM_Node::DOCUMENT_NODE : |
| { |
| // |
| // Bug here: we need to find a way to get the encoding name |
| // for the default code page on the system where the program |
| // is running, and plug that in for the encoding name. |
| // |
| //target << "<?xml version='1.0' encoding='ISO-8859-1' ?>\n"; |
| DOM_Node child = toWrite.getFirstChild(); |
| while( child != 0) |
| { |
| target << child; |
| child = child.getNextSibling(); |
| } |
| break; |
| } |
| |
| case DOM_Node::ELEMENT_NODE : |
| { |
| // Output the element start tag. |
| target << XMLStrL('<') << nodeName; |
| |
| // Output any attributes on this element |
| DOM_NamedNodeMap attributes = toWrite.getAttributes(); |
| int attrCount = attributes.getLength(); |
| for (int i = 0; i < attrCount; i++) |
| { |
| DOM_Node attribute = attributes.item(i); |
| |
| target << XMLStrL(' ') << attribute.getNodeName() |
| << XMLStrL(" = \""); |
| // Note that "<" must be escaped in attribute values. |
| outputContent(target, attribute.getNodeValue()); |
| target << XMLStrL('"'); |
| } |
| |
| // |
| // Test for the presence of children, which includes both |
| // text content and nested elements. |
| // |
| DOM_Node child = toWrite.getFirstChild(); |
| if (child != 0) |
| { |
| // There are children. Close start-tag, and output children. |
| target << XMLStrL(">"); |
| while( child != 0) |
| { |
| target << child; |
| child = child.getNextSibling(); |
| } |
| |
| // Done with children. Output the end tag. |
| target << XMLStrL("</") << nodeName << XMLStrL(">"); |
| } |
| else |
| { |
| // |
| // There were no children. Output the short form close of |
| // the element start tag, making it an empty-element tag. |
| // |
| target << XMLStrL("/>"); |
| } |
| break; |
| } |
| |
| case DOM_Node::ENTITY_REFERENCE_NODE: |
| { |
| DOM_Node child; |
| for (child = toWrite.getFirstChild(); child != 0; child = child.getNextSibling()) |
| target << child; |
| break; |
| } |
| |
| case DOM_Node::CDATA_SECTION_NODE: |
| { |
| target << XMLStrL("<![CDATA[") << nodeValue << XMLStrL("]]>"); |
| break; |
| } |
| |
| case DOM_Node::COMMENT_NODE: |
| { |
| target << XMLStrL("<!--") << nodeValue << XMLStrL("-->"); |
| break; |
| } |
| |
| case DOM_Node::DOCUMENT_TYPE_NODE: |
| { |
| DOM_DocumentType doctype = (DOM_DocumentType &)toWrite;; |
| |
| target << XMLStrL("<!DOCTYPE ") << nodeName ; |
| DOMString id = doctype.getPublicId(); |
| if (id != 0) |
| target << XMLStrL(" PUBLIC \"") << id << XMLStrL("\""); |
| id = doctype.getSystemId(); |
| if (id != 0) |
| target << XMLStrL(" SYSTEM \"") << id << XMLStrL("\""); |
| id = doctype.getInternalSubset(); |
| if (id !=0) |
| target << XMLStrL(" [ ") << id << XMLStrL("]"); |
| target << XMLStrL(">"); |
| break; |
| } |
| case DOM_Node::ENTITY_NODE: |
| { |
| target << XMLStrL("<!ENTITY ") << nodeName; |
| DOMString id = ((DOM_Entity &)toWrite).getPublicId(); |
| if (id != 0) |
| target << XMLStrL("PUBLIC \"") << id << XMLStrL("\""); |
| id = ((DOM_Entity &)toWrite).getSystemId(); |
| if (id != 0) |
| target << XMLStrL("SYSTEM \"") << id << XMLStrL("\""); |
| id = ((DOM_Entity &)toWrite).getNotationName(); |
| if (id != 0) |
| target << XMLStrL("NDATA \"") << id << XMLStrL("\""); |
| |
| break; |
| } |
| case DOM_Node::XML_DECL_NODE: |
| { |
| target << XMLStrL("<?xml version=") << ((DOM_XMLDecl &)toWrite).getVersion(); |
| DOMString str = ((DOM_XMLDecl &)toWrite).getEncoding(); |
| if (str != 0) |
| target << XMLStrL(" encoding=") << str; |
| str = ((DOM_XMLDecl &)toWrite).getStandalone(); |
| if (str != 0) |
| target << XMLStrL(" standalone=") << str; |
| target << XMLStrL("?>"); |
| break; |
| } |
| default: |
| target << XMLStrL("<!-- Unrecognized node type -->"); |
| } |
| return target; |
| } |
| |
| void GetXML(const DOM_Node &node, _bstr_t &text) |
| { |
| xmlstream stream; |
| stream << node; |
| text.Assign(stream.SysAllocString()); |
| } |
| |