XMLDOMUtil.cpp
上传用户:huihehuasu
上传日期:2007-01-10
资源大小:6948k
文件大小:24k
源码类别:

xml/soap/webservice

开发平台:

C/C++

  1. /*
  2.  * The Apache Software License, Version 1.1
  3.  *
  4.  * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
  5.  * reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  *
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  *
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in
  16.  *    the documentation and/or other materials provided with the
  17.  *    distribution.
  18.  *
  19.  * 3. The end-user documentation included with the redistribution,
  20.  *    if any, must include the following acknowledgment:
  21.  *       "This product includes software developed by the
  22.  *        Apache Software Foundation (http://www.apache.org/)."
  23.  *    Alternately, this acknowledgment may appear in the software itself,
  24.  *    if and wherever such third-party acknowledgments normally appear.
  25.  *
  26.  * 4. The names "Xerces" and "Apache Software Foundation" must
  27.  *    not be used to endorse or promote products derived from this
  28.  *    software without prior written permission. For written
  29.  *    permission, please contact apache@apache.org.
  30.  *
  31.  * 5. Products derived from this software may not be called "Apache",
  32.  *    nor may "Apache" appear in their name, without prior written
  33.  *    permission of the Apache Software Foundation.
  34.  *
  35.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  36.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  37.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38.  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  39.  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41.  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  42.  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  43.  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  44.  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  45.  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46.  * SUCH DAMAGE.
  47.  * ====================================================================
  48.  *
  49.  * This software consists of voluntary contributions made by many
  50.  * individuals on behalf of the Apache Software Foundation, and was
  51.  * originally based on software copyright (c) 1999, International
  52.  * Business Machines, Inc., http://www.ibm.com .  For more information
  53.  * on the Apache Software Foundation, please see
  54.  * <http://www.apache.org/>.
  55.  */
  56. /*
  57.  * $Id: XMLDOMUtil.cpp,v 1.7 2001/05/11 13:25:08 tng Exp $
  58.  */
  59. #include "stdafx.h"
  60. #include "xml4com.h"
  61. #include "XMLDOMElement.h"
  62. #include "XMLDOMAttribute.h"
  63. #include "XMLDOMText.h"
  64. #include "XMLDOMCDATASection.h"
  65. #include "XMLDOMEntityReference.h"
  66. #include "XMLDOMEntity.h"
  67. #include "XMLDOMProcessingInstruction.h"
  68. #include "XMLDOMComment.h"
  69. #include "XMLDOMDocument.h"
  70. #include "XMLDOMDocumentType.h"
  71. #include "XMLDOMDocumentFragment.h"
  72. #include "XMLDOMNotation.h"
  73. #include "XMLDOMXMLDecl.h"
  74. #include "XMLDOMUtil.h"
  75. #include <util/PlatformUtils.hpp>
  76. #include <util/XMLUniDefs.hpp>
  77. const OLECHAR* g_DomNodeName[] =
  78. {
  79. OLESTR("invalid"),
  80. OLESTR("element"),
  81. OLESTR("attribute"),
  82. OLESTR("text"),
  83. OLESTR("cdatasection"),
  84. OLESTR("entityreference"),
  85. OLESTR("entity"),
  86. OLESTR("processinginstruction"),
  87. OLESTR("comment"),
  88. OLESTR("document"),
  89. OLESTR("documenttype"),
  90. OLESTR("documentfragment"),
  91. OLESTR("notation")
  92. };
  93. const int g_DomNodeNameSize = sizeof(g_DomNodeName) / sizeof(OLECHAR*);
  94. DOMString GetText(const DOM_Node& node)
  95. {
  96. DOM_Node::NodeType type = static_cast<DOM_Node::NodeType> (node.getNodeType());
  97. DOMString val;
  98. if (DOM_Node::DOCUMENT_TYPE_NODE   == type ||
  99. DOM_Node::NOTATION_NODE   == type)
  100. return val;
  101. if (DOM_Node::CDATA_SECTION_NODE   == type ||
  102. DOM_Node::COMMENT_NODE   == type ||
  103. DOM_Node::PROCESSING_INSTRUCTION_NODE == type ||
  104. DOM_Node::TEXT_NODE   == type) {
  105. val = node.getNodeValue();
  106. return val;
  107. }
  108. DOM_NodeList l =  node.getChildNodes();
  109. int length = l.getLength();
  110. if (length > 0) {
  111. for (int i = 0; i < length; ++i)
  112. val.appendData(GetText(l.item(i)));
  113. }
  114. else {
  115. val = node.getNodeValue();
  116. }
  117. return val;
  118. }
  119. template <class Base>
  120. class CComObjectPool
  121. {
  122. public:
  123. CComObjectPool(unsigned long poolSize);
  124. virtual ~CComObjectPool();
  125. HRESULT WINAPI CreateInstance(Base** pp);
  126. HRESULT Deactivate(Base* obj);
  127. private:
  128. Base** m_pool;
  129. unsigned long m_size;
  130. unsigned long m_hit;
  131. unsigned long m_attempt;
  132. HRESULT Activate(Base* obj);
  133. };
  134. template <class Base>
  135. class CPooledComObject : public Base
  136. {
  137. public:
  138. typedef Base _BaseClass;
  139. CPooledComObject(void* = NULL)
  140. {
  141. _Module.Lock();
  142. }
  143. // Set refcount to 1 to protect destruction
  144. ~CPooledComObject()
  145. {
  146. m_dwRef = 1L;
  147. FinalRelease();
  148. #ifdef _ATL_DEBUG_INTERFACES
  149. _Module.DeleteNonAddRefThunk(_GetRawUnknown());
  150. #endif
  151. _Module.Unlock();
  152. }
  153. //If InternalAddRef or InternalRelease is undefined then your class
  154. //doesn't derive from CComObjectRoot
  155. STDMETHOD_(ULONG, AddRef)() {return InternalAddRef();}
  156. STDMETHOD_(ULONG, Release)()
  157. {
  158. ULONG l = InternalRelease();
  159. if (l == 0) {
  160. if(SUCCEEDED(m_pool.Deactivate(this))) {
  161. FinalRelease();
  162. }
  163. else
  164. delete this;
  165. }
  166. return l;
  167. }
  168. //if _InternalQueryInterface is undefined then you forgot BEGIN_COM_MAP
  169. STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject)
  170. {return _InternalQueryInterface(iid, ppvObject);}
  171. template <class Q>
  172. HRESULT STDMETHODCALLTYPE QueryInterface(Q** pp)
  173. {
  174. return QueryInterface(__uuidof(Q), (void**)pp);
  175. }
  176. static HRESULT WINAPI CreateInstance(Base** pp) {
  177. return m_pool.CreateInstance(pp);
  178. }
  179. private:
  180. static CComObjectPool<Base> m_pool;
  181. };
  182. template <class Base>
  183. CComObjectPool<Base>::CComObjectPool<Base>(unsigned long poolSize) {
  184. m_pool = NULL;
  185. m_size = poolSize;
  186. m_pool = new Base*[m_size];
  187. for(unsigned long i = 0; i < m_size; i++)
  188. m_pool[i] = NULL;
  189. m_hit= 0;
  190. m_attempt = 0;
  191. }
  192. template <class Base>
  193. CComObjectPool<Base>::~CComObjectPool<Base>() {
  194. for(unsigned long i = 0; i < m_size; i++) {
  195. if(m_pool[i]) delete m_pool[i];
  196. }
  197. delete [] m_pool;
  198. }
  199. template <class Base>
  200. HRESULT CComObjectPool<Base>::Deactivate(Base* obj) {
  201. for(unsigned long i = 0; i < m_size; i++) {
  202. if(m_pool[i] == NULL) {
  203. m_pool[i] = obj;
  204. return S_OK;
  205. }
  206. }
  207. return E_FAIL;
  208. }
  209. template <class Base>
  210. HRESULT CComObjectPool<Base>::Activate(Base* p)
  211. {
  212. p->SetVoid(NULL);
  213. p->InternalFinalConstructAddRef();
  214. HRESULT hRes = p->FinalConstruct();
  215. p->InternalFinalConstructRelease();
  216. return hRes;
  217. }
  218. template <class Base>
  219. HRESULT WINAPI CComObjectPool<Base>::CreateInstance(Base** pp) {
  220. ATLASSERT(pp != NULL);
  221. HRESULT hRes = E_OUTOFMEMORY;
  222. Base* p = NULL;
  223. m_attempt++;
  224. for(unsigned long i = 0; i < m_size; i++) {
  225. if(m_pool[i]) {
  226. p = m_pool[i];
  227. m_pool[i] = NULL;
  228. hRes = Activate(p);
  229. if (SUCCEEDED(hRes)) {
  230. m_hit++;
  231. break;
  232. }
  233. else {
  234. delete p;
  235. p = NULL;
  236. }
  237. }
  238. }
  239. if(FAILED(hRes)) {
  240. ATLTRY(p = new CPooledComObject<Base>())
  241. if (p != NULL) {
  242. hRes = Activate(p);
  243. if (hRes != S_OK) {
  244. delete p;
  245. p = NULL;
  246. }
  247. }
  248. }
  249. *pp = p;
  250. return hRes;
  251. }
  252. CComObjectPool<CXMLDOMElement> CPooledComObject<CXMLDOMElement>::m_pool(6);
  253. typedef CPooledComObject<CXMLDOMElement> CPooledXMLDOMElementObj;
  254. CComObjectPool<CXMLDOMAttribute> CPooledComObject<CXMLDOMAttribute>::m_pool(6);
  255. typedef CPooledComObject<CXMLDOMAttribute> CPooledXMLDOMAttributeObj;
  256. CComObjectPool<CXMLDOMText> CPooledComObject<CXMLDOMText>::m_pool(6);
  257. typedef CPooledComObject<CXMLDOMText> CPooledXMLDOMTextObj;
  258. CComObjectPool<CXMLDOMCDATASection> CPooledComObject<CXMLDOMCDATASection>::m_pool(6);
  259. typedef CPooledComObject<CXMLDOMCDATASection> CPooledXMLDOMCDATASectionObj;
  260. CComObjectPool<CXMLDOMEntityReference> CPooledComObject<CXMLDOMEntityReference>::m_pool(6);
  261. typedef CPooledComObject<CXMLDOMEntityReference> CPooledXMLDOMEntityReferenceObj;
  262. CComObjectPool<CXMLDOMEntity> CPooledComObject<CXMLDOMEntity>::m_pool(6);
  263. typedef CPooledComObject<CXMLDOMEntity> CPooledXMLDOMEntityObj;
  264. CComObjectPool<CXMLDOMProcessingInstruction> CPooledComObject<CXMLDOMProcessingInstruction>::m_pool(6);
  265. typedef CPooledComObject<CXMLDOMProcessingInstruction> CPooledXMLDOMProcessingInstructionObj;
  266. CComObjectPool<CXMLDOMComment> CPooledComObject<CXMLDOMComment>::m_pool(6);
  267. typedef CPooledComObject<CXMLDOMComment> CPooledXMLDOMCommentObj;
  268. HRESULT wrapNode(IXMLDOMDocument *pDoc, DOM_Node& node, REFIID iid, LPVOID *pVal)
  269. {
  270. HRESULT hr = S_OK;
  271. if (NULL == pVal)
  272. return E_POINTER;
  273. *pVal = NULL;
  274. short type = node.getNodeType();
  275. // the way we are constructing the wrappers is kind of fishy but oh well...
  276. // the various IBM DOM wrapper classes don't ever add any members or have
  277. // any v-tables so what we are doing should be safe.  There isn't any other
  278. // way as far as I can tell to do this....
  279. switch(type)
  280. {
  281. case DOM_Node::ELEMENT_NODE:
  282. {
  283. CXMLDOMElement *pObj = NULL;
  284. hr = CPooledXMLDOMElementObj::CreateInstance(&pObj);
  285. if (S_OK != hr)
  286. return hr;
  287. pObj->AddRef();
  288. pObj->SetOwnerDoc(pDoc);
  289. try
  290. {
  291. pObj->element = *(static_cast<DOM_Element*> (&node));
  292. }
  293. catch(DOM_DOMException& ex)
  294. {
  295. pObj->Release();
  296. return MakeHRESULT(ex);
  297. }
  298. catch(...)
  299. {
  300. pObj->Release();
  301. return E_FAIL;
  302. }
  303. hr = pObj->QueryInterface(iid, pVal);
  304. if (S_OK != hr)
  305. *pVal = NULL;
  306. pObj->Release();
  307. break;
  308. }
  309. case DOM_Node::ATTRIBUTE_NODE:
  310. {
  311. CXMLDOMAttribute *pObj = NULL;
  312. hr = CPooledXMLDOMAttributeObj::CreateInstance(&pObj);
  313. if (S_OK != hr)
  314. return hr;
  315. pObj->AddRef();
  316. pObj->SetOwnerDoc(pDoc);
  317. try
  318. {
  319. pObj->attr = *(static_cast<DOM_Attr*> (&node));
  320. }
  321. catch(DOM_DOMException& ex)
  322. {
  323. pObj->Release();
  324. return MakeHRESULT(ex);
  325. }
  326. catch(...)
  327. {
  328. pObj->Release();
  329. return E_FAIL;
  330. }
  331. hr = pObj->QueryInterface(iid, pVal);
  332. if (S_OK != hr)
  333. *pVal = NULL;
  334. pObj->Release();
  335. break;
  336. }
  337. case DOM_Node::TEXT_NODE:
  338. {
  339. CXMLDOMText *pObj = NULL;
  340. hr = CPooledXMLDOMTextObj::CreateInstance(&pObj);
  341. if (S_OK != hr)
  342. return hr;
  343. pObj->AddRef();
  344. pObj->SetOwnerDoc(pDoc);
  345. try
  346. {
  347. pObj->text = *(static_cast<DOM_Text*> (&node));
  348. }
  349. catch(DOM_DOMException& ex)
  350. {
  351. pObj->Release();
  352. return MakeHRESULT(ex);
  353. }
  354. catch(...)
  355. {
  356. pObj->Release();
  357. return E_FAIL;
  358. }
  359. hr = pObj->QueryInterface(iid, pVal);
  360. if (S_OK != hr)
  361. *pVal = NULL;
  362. pObj->Release();
  363. break;
  364. }
  365. case DOM_Node::CDATA_SECTION_NODE:
  366. {
  367. CXMLDOMCDATASection *pObj = NULL;
  368. hr = CPooledXMLDOMCDATASectionObj::CreateInstance(&pObj);
  369. if (S_OK != hr)
  370. return hr;
  371. pObj->AddRef();
  372. pObj->SetOwnerDoc(pDoc);
  373. try
  374. {
  375. pObj->cdataSection = *(static_cast<DOM_CDATASection*> (&node));
  376. }
  377. catch(DOM_DOMException& ex)
  378. {
  379. pObj->Release();
  380. return MakeHRESULT(ex);
  381. }
  382. catch(...)
  383. {
  384. pObj->Release();
  385. return E_FAIL;
  386. }
  387. hr = pObj->QueryInterface(iid, pVal);
  388. if (S_OK != hr)
  389. *pVal = NULL;
  390. pObj->Release();
  391. break;
  392. }
  393. case DOM_Node::ENTITY_REFERENCE_NODE:
  394. {
  395. CXMLDOMEntityReference *pObj = NULL;
  396. hr = CPooledXMLDOMEntityReferenceObj::CreateInstance(&pObj);
  397. if (S_OK != hr)
  398. return hr;
  399. pObj->AddRef();
  400. pObj->SetOwnerDoc(pDoc);
  401. try
  402. {
  403. pObj->entityReference = *(static_cast<DOM_EntityReference*> (&node));
  404. }
  405. catch(DOM_DOMException& ex)
  406. {
  407. pObj->Release();
  408. return MakeHRESULT(ex);
  409. }
  410. catch(...)
  411. {
  412. pObj->Release();
  413. return E_FAIL;
  414. }
  415. hr = pObj->QueryInterface(iid, pVal);
  416. if (S_OK != hr)
  417. *pVal = NULL;
  418. pObj->Release();
  419. break;
  420. }
  421. case DOM_Node::ENTITY_NODE:
  422. {
  423. CXMLDOMEntity *pObj = NULL;
  424. hr = CPooledXMLDOMEntityObj::CreateInstance(&pObj);
  425. if (S_OK != hr)
  426. return hr;
  427. pObj->AddRef();
  428. pObj->SetOwnerDoc(pDoc);
  429. try
  430. {
  431. pObj->entity = *(static_cast<DOM_Entity*> (&node));
  432. }
  433. catch(DOM_DOMException& ex)
  434. {
  435. pObj->Release();
  436. return MakeHRESULT(ex);
  437. }
  438. catch(...)
  439. {
  440. pObj->Release();
  441. return E_FAIL;
  442. }
  443. hr = pObj->QueryInterface(iid, pVal);
  444. if (S_OK != hr)
  445. *pVal = NULL;
  446. pObj->Release();
  447. break;
  448. }
  449. case DOM_Node::PROCESSING_INSTRUCTION_NODE:
  450. {
  451. CXMLDOMProcessingInstruction *pObj = NULL;
  452. hr = CPooledXMLDOMProcessingInstructionObj::CreateInstance(&pObj);
  453. if (S_OK != hr)
  454. return hr;
  455. pObj->AddRef();
  456. pObj->SetOwnerDoc(pDoc);
  457. try
  458. {
  459. pObj->processingInstruction = *(static_cast<DOM_ProcessingInstruction*> (&node));
  460. }
  461. catch(DOM_DOMException& ex)
  462. {
  463. pObj->Release();
  464. return MakeHRESULT(ex);
  465. }
  466. catch(...)
  467. {
  468. pObj->Release();
  469. return E_FAIL;
  470. }
  471. hr = pObj->QueryInterface(iid, pVal);
  472. if (S_OK != hr)
  473. *pVal = NULL;
  474. pObj->Release();
  475. break;
  476. }
  477. case DOM_Node::COMMENT_NODE:
  478. {
  479. CXMLDOMComment *pObj = NULL;
  480. hr = CPooledXMLDOMCommentObj::CreateInstance(&pObj);
  481. if (S_OK != hr)
  482. return hr;
  483. pObj->AddRef();
  484. pObj->SetOwnerDoc(pDoc);
  485. try
  486. {
  487. pObj->comment = *(static_cast<DOM_Comment*> (&node));
  488. }
  489. catch(DOM_DOMException& ex)
  490. {
  491. pObj->Release();
  492. return MakeHRESULT(ex);
  493. }
  494. catch(...)
  495. {
  496. pObj->Release();
  497. return E_FAIL;
  498. }
  499. hr = pObj->QueryInterface(iid, pVal);
  500. if (S_OK != hr)
  501. *pVal = NULL;
  502. pObj->Release();
  503. break;
  504. }
  505. case DOM_Node::DOCUMENT_NODE:
  506. {
  507. CXMLDOMDocumentObj *pObj = NULL;
  508. hr = CXMLDOMDocumentObj::CreateInstance(&pObj);
  509. if (S_OK != hr)
  510. return hr;
  511. pObj->AddRef();
  512. pObj->SetOwnerDoc(pDoc);
  513. try
  514. {
  515. pObj->m_Document = *(static_cast<DOM_Document*> (&node));
  516. }
  517. catch(DOM_DOMException& ex)
  518. {
  519. pObj->Release();
  520. return MakeHRESULT(ex);
  521. }
  522. catch(...)
  523. {
  524. pObj->Release();
  525. return E_FAIL;
  526. }
  527. hr = pObj->QueryInterface(iid, pVal);
  528. if (S_OK != hr)
  529. *pVal = NULL;
  530. pObj->Release();
  531. break;
  532. }
  533. case DOM_Node::DOCUMENT_TYPE_NODE:
  534. {
  535. CXMLDOMDocumentTypeObj *pObj = NULL;
  536. hr = CXMLDOMDocumentTypeObj::CreateInstance(&pObj);
  537. if (S_OK != hr)
  538. return hr;
  539. pObj->AddRef();
  540. pObj->SetOwnerDoc(pDoc);
  541. try
  542. {
  543. pObj->documentType = *(static_cast<DOM_DocumentType*> (&node));
  544. }
  545. catch(DOM_DOMException& ex)
  546. {
  547. pObj->Release();
  548. return MakeHRESULT(ex);
  549. }
  550. catch(...)
  551. {
  552. pObj->Release();
  553. return E_FAIL;
  554. }
  555. hr = pObj->QueryInterface(iid, pVal);
  556. if (S_OK != hr)
  557. *pVal = NULL;
  558. pObj->Release();
  559. break;
  560. }
  561. case DOM_Node::DOCUMENT_FRAGMENT_NODE:
  562. {
  563. CXMLDOMDocumentFragmentObj *pObj = NULL;
  564. hr = CXMLDOMDocumentFragmentObj::CreateInstance(&pObj);
  565. if (S_OK != hr)
  566. return hr;
  567. pObj->AddRef();
  568. pObj->SetOwnerDoc(pDoc);
  569. try
  570. {
  571. pObj->documentFragment = *(static_cast<DOM_DocumentFragment*> (&node));
  572. }
  573. catch(DOM_DOMException& ex)
  574. {
  575. pObj->Release();
  576. return MakeHRESULT(ex);
  577. }
  578. catch(...)
  579. {
  580. pObj->Release();
  581. return E_FAIL;
  582. }
  583. hr = pObj->QueryInterface(iid, pVal);
  584. if (S_OK != hr)
  585. *pVal = NULL;
  586. pObj->Release();
  587. break;
  588. }
  589. case DOM_Node::NOTATION_NODE:
  590. {
  591. CXMLDOMNotationObj *pObj = NULL;
  592. hr = CXMLDOMNotationObj::CreateInstance(&pObj);
  593. if (S_OK != hr)
  594. return hr;
  595. pObj->AddRef();
  596. pObj->SetOwnerDoc(pDoc);
  597. try
  598. {
  599. pObj->notation = *(static_cast<DOM_Notation*> (&node));
  600. }
  601. catch(DOM_DOMException& ex)
  602. {
  603. pObj->Release();
  604. return MakeHRESULT(ex);
  605. }
  606. catch(...)
  607. {
  608. pObj->Release();
  609. return E_FAIL;
  610. }
  611. hr = pObj->QueryInterface(iid, pVal);
  612. if (S_OK != hr)
  613. *pVal = NULL;
  614. pObj->Release();
  615. break;
  616. }
  617. case DOM_Node::XML_DECL_NODE:
  618. {
  619. CXMLDOMXMLDeclObj *pObj = NULL;
  620. hr = CXMLDOMXMLDeclObj::CreateInstance(&pObj);
  621. if (S_OK != hr)
  622. return hr;
  623. pObj->AddRef();
  624. pObj->SetOwnerDoc(pDoc);
  625. try
  626. {
  627. pObj->xmlDecl = *(static_cast<DOM_XMLDecl*> (&node));
  628. }
  629. catch(DOM_DOMException& ex)
  630. {
  631. pObj->Release();
  632. return MakeHRESULT(ex);
  633. }
  634. catch(...)
  635. {
  636. pObj->Release();
  637. return E_FAIL;
  638. }
  639. hr = pObj->QueryInterface(iid, pVal);
  640. if (S_OK != hr)
  641. *pVal = NULL;
  642. pObj->Release();
  643. break;
  644. }
  645. default:
  646. hr = E_NOTIMPL;
  647. break;
  648. }
  649. return hr;
  650. }
  651. class xmlstream {
  652. public:
  653. xmlstream() {
  654. m_length = 0;
  655. m_alloc = 0;
  656. m_buffer = 0;
  657. m_next = 0;
  658. }
  659. ~xmlstream() {
  660. delete [] m_buffer;
  661. }
  662. xmlstream& operator<<(const XMLCh* other) {
  663. //
  664. //   get length of string
  665. //
  666. unsigned long len = 0;
  667. for(const XMLCh* source = other; *source; source++,len++);
  668. //
  669. //    append to stream
  670. //
  671. append(other,len);
  672. return *this;
  673. }
  674. xmlstream& operator<<(const DOMString& other) {
  675. append(other.rawBuffer(),other.length());
  676. return *this;
  677. }
  678. xmlstream& operator<<(const XMLCh other) {
  679. append(&other,1);
  680. return *this;
  681. }
  682. BSTR SysAllocString() {
  683. if(m_length > 0)
  684. return SysAllocStringLen(m_buffer,m_length);
  685. return 0;
  686. }
  687. private:
  688. void append(const XMLCh* other,unsigned long length) {
  689. const XMLCh* source = NULL;
  690. if(m_length + length > m_alloc) {
  691. unsigned long chunk = 4096;
  692. if(length > chunk) chunk += length;
  693. XMLCh* newbuf = new XMLCh[m_alloc+ chunk];
  694. m_alloc += chunk;
  695. m_next = newbuf + m_length;
  696. //
  697. //    copy old content into new buffer
  698. //
  699. XMLCh* dest = newbuf;
  700. source = m_buffer;
  701. for(unsigned long i = 0; i < m_length; i++,dest++,source++) {
  702. *dest = *source;
  703. }
  704. delete [] m_buffer;
  705. m_buffer = newbuf;
  706. }
  707. source = other;
  708. for(unsigned long i = 0; i < length; i++,source++,m_next++) {
  709. *m_next = *source;
  710. }
  711. m_length += length;
  712. }
  713. unsigned long m_length;
  714. unsigned long m_alloc;
  715. XMLCh* m_buffer;
  716. XMLCh* m_next;
  717. };
  718. // ---------------------------------------------------------------------------
  719. //  outputContent
  720. //
  721. //  Write document content from a DOMString to a C++ ostream. Escape the
  722. //  XML special characters (<, &, etc.) unless this is suppressed by the
  723. //  command line option.
  724. // ---------------------------------------------------------------------------
  725. void outputContent(xmlstream& target, const DOMString &toWrite)
  726. {
  727.         int            length = toWrite.length();
  728.         const XMLCh*   chars  = toWrite.rawBuffer();
  729.         int index;
  730.         for (index = 0; index < length; index++)
  731.         {
  732.             switch (chars[index])
  733.             {
  734.             case chAmpersand :
  735.                 target << XMLStrL("&amp;");
  736.                 break;
  737.             case chOpenAngle :
  738.                 target << XMLStrL("&lt;");
  739.                 break;
  740.             case chCloseAngle:
  741.                 target << XMLStrL("&gt;");
  742.                 break;
  743.             case chDoubleQuote :
  744.                 target << XMLStrL("&quot;");
  745.                 break;
  746.             default:
  747.                 // If it is none of the special characters, print it as such
  748.                 target << toWrite.substringData(index, 1);
  749.                 break;
  750.             }
  751.         }
  752.     return;
  753. }
  754. xmlstream& operator<<(xmlstream& target, const DOM_Node& toWrite)
  755. {
  756.     // Get the name and value out for convenience
  757.     DOMString   nodeName = toWrite.getNodeName();
  758.     DOMString   nodeValue = toWrite.getNodeValue();
  759. switch (toWrite.getNodeType())
  760.     {
  761. case DOM_Node::TEXT_NODE:
  762.         {
  763.             outputContent(target, nodeValue);
  764.             break;
  765.         }
  766.         case DOM_Node::PROCESSING_INSTRUCTION_NODE :
  767.         {
  768.             target  << XMLStrL("<?")
  769.                     << nodeName
  770.                     << XMLStrL(' ')
  771.                     << nodeValue
  772.                     << XMLStrL("?>");
  773.             break;
  774.         }
  775.         case DOM_Node::DOCUMENT_NODE :
  776.         {
  777.             //
  778.             //  Bug here:  we need to find a way to get the encoding name
  779.             //  for the default code page on the system where the program
  780.             //  is running, and plug that in for the encoding name.
  781.             //
  782.             //target << "<?xml version='1.0' encoding='ISO-8859-1' ?>n";
  783.             DOM_Node child = toWrite.getFirstChild();
  784.             while( child != 0)
  785.             {
  786.                 target << child;
  787.                 child = child.getNextSibling();
  788.             }
  789.             break;
  790.         }
  791.         case DOM_Node::ELEMENT_NODE :
  792.         {
  793.             // Output the element start tag.
  794.             target << XMLStrL('<') << nodeName;
  795.             // Output any attributes on this element
  796.             DOM_NamedNodeMap attributes = toWrite.getAttributes();
  797.             int attrCount = attributes.getLength();
  798.             for (int i = 0; i < attrCount; i++)
  799.             {
  800.                 DOM_Node  attribute = attributes.item(i);
  801.                 target  << XMLStrL(' ') << attribute.getNodeName()
  802.                         << XMLStrL(" = "");
  803.                         //  Note that "<" must be escaped in attribute values.
  804.                         outputContent(target, attribute.getNodeValue());
  805.                         target << XMLStrL('"');
  806.             }
  807.             //
  808.             //  Test for the presence of children, which includes both
  809.             //  text content and nested elements.
  810.             //
  811.             DOM_Node child = toWrite.getFirstChild();
  812.             if (child != 0)
  813.             {
  814.                 // There are children. Close start-tag, and output children.
  815.                 target << XMLStrL(">");
  816.                 while( child != 0)
  817.                 {
  818.                     target << child;
  819.                     child = child.getNextSibling();
  820.                 }
  821.                 // Done with children.  Output the end tag.
  822.                 target << XMLStrL("</") << nodeName << XMLStrL(">");
  823.             }
  824.             else
  825.             {
  826.                 //
  827.                 //  There were no children. Output the short form close of
  828.                 //  the element start tag, making it an empty-element tag.
  829.                 //
  830.                 target << XMLStrL("/>");
  831.             }
  832.             break;
  833.         }
  834.         case DOM_Node::ENTITY_REFERENCE_NODE:
  835.         {
  836.             DOM_Node child;
  837.             for (child = toWrite.getFirstChild(); child != 0; child = child.getNextSibling())
  838.                 target << child;
  839.             break;
  840.         }
  841.         case DOM_Node::CDATA_SECTION_NODE:
  842.         {
  843.             target << XMLStrL("<![CDATA[") << nodeValue << XMLStrL("]]>");
  844.             break;
  845.         }
  846.         case DOM_Node::COMMENT_NODE:
  847.         {
  848.             target << XMLStrL("<!--") << nodeValue << XMLStrL("-->");
  849.             break;
  850.         }
  851.         case DOM_Node::DOCUMENT_TYPE_NODE:
  852.         {
  853. DOM_DocumentType doctype = (DOM_DocumentType &)toWrite;;
  854. target << XMLStrL("<!DOCTYPE ") << nodeName ;
  855. DOMString id = doctype.getPublicId();
  856. if (id != 0)
  857. target << XMLStrL(" PUBLIC "") << id << XMLStrL(""");
  858. id = doctype.getSystemId();
  859. if (id != 0)
  860. target << XMLStrL(" SYSTEM "") << id << XMLStrL(""");
  861. id = doctype.getInternalSubset();
  862. if (id !=0)
  863. target << XMLStrL(" [ ") << id  << XMLStrL("]");
  864. target  << XMLStrL(">");
  865.             break;
  866.         }
  867. case DOM_Node::ENTITY_NODE:
  868.         {
  869. target << XMLStrL("<!ENTITY ") << nodeName;
  870. DOMString id = ((DOM_Entity &)toWrite).getPublicId();
  871. if (id != 0)
  872. target << XMLStrL("PUBLIC "") << id << XMLStrL(""");
  873. id = ((DOM_Entity &)toWrite).getSystemId();
  874. if (id != 0)
  875. target << XMLStrL("SYSTEM "") << id << XMLStrL(""");
  876. id = ((DOM_Entity &)toWrite).getNotationName();
  877. if (id != 0)
  878. target << XMLStrL("NDATA "") << id << XMLStrL(""");
  879.             break;
  880.         }
  881.         case DOM_Node::XML_DECL_NODE:
  882.         {
  883.             target << XMLStrL("<?xml version=") << ((DOM_XMLDecl &)toWrite).getVersion();
  884.             DOMString str = ((DOM_XMLDecl &)toWrite).getEncoding();
  885.             if (str != 0)
  886.                 target << XMLStrL(" encoding=") << str;
  887.             str = ((DOM_XMLDecl &)toWrite).getStandalone();
  888.             if (str != 0)
  889.                 target << XMLStrL(" standalone=") << str;
  890.             target << XMLStrL("?>");
  891.             break;
  892.         }
  893.         default:
  894.             target << XMLStrL("<!-- Unrecognized node type -->");
  895.     }
  896. return target;
  897. }
  898. void GetXML(const DOM_Node &node, _bstr_t &text)
  899. {
  900. xmlstream stream;
  901. stream << node;
  902. text.Assign(stream.SysAllocString());
  903. }