Back to index

lightning-sunbird  0.9+nobinonly
XMLElementCollection.cpp
Go to the documentation of this file.
00001 // XMLElementCollection.cpp : Implementation of CXMLElementCollection
00002 #include "stdafx.h"
00003 //#include "Activexml.h"
00004 #include "XMLElementCollection.h"
00005 
00006 CXMLElementCollection::CXMLElementCollection()
00007 {
00008 }
00009 
00010 
00011 CXMLElementCollection::~CXMLElementCollection()
00012 {
00013 }
00014 
00015 
00016 HRESULT CXMLElementCollection::Add(IXMLElement *pElement)
00017 {
00018        if (pElement == NULL)
00019        {
00020               return E_INVALIDARG;
00021        }
00022 
00023        m_cElements.push_back( CComQIPtr<IXMLElement, &IID_IXMLElement>(pElement));
00024        return S_OK;
00025 }
00026 
00027 
00029 // CXMLElementCollection
00030 
00031 HRESULT STDMETHODCALLTYPE CXMLElementCollection::put_length(/* [in] */ long v)
00032 {
00033        // Why does MS define a method that has no purpose?
00034        return S_OK;
00035 }
00036 
00037 
00038 HRESULT STDMETHODCALLTYPE CXMLElementCollection::get_length(/* [out][retval] */ long __RPC_FAR *p)
00039 {
00040        if (p == NULL)
00041        {
00042               return E_INVALIDARG;
00043        }
00044        *p = m_cElements.size();
00045        return S_OK;
00046 }
00047 
00048 
00049 HRESULT STDMETHODCALLTYPE CXMLElementCollection::get__newEnum(/* [out][retval] */ IUnknown __RPC_FAR *__RPC_FAR *ppUnk)
00050 {
00051        return E_NOTIMPL;
00052 }
00053 
00054 
00055 // Perhaps the most overly complicated method ever...
00056 HRESULT STDMETHODCALLTYPE CXMLElementCollection::item(/* [in][optional] */ VARIANT var1, /* [in][optional] */ VARIANT var2, /* [out][retval] */ IDispatch __RPC_FAR *__RPC_FAR *ppDisp)
00057 {
00058        if (ppDisp == NULL)
00059        {
00060               return E_INVALIDARG;
00061        }
00062 
00063        *ppDisp;
00064 
00065        CComVariant vIndex;
00066 
00067        // If var1 is a number, the caller wants the element at the specified index
00068        
00069        if (vIndex.ChangeType(VT_I4, &var1) == S_OK)
00070        {
00071               long nIndex = vIndex.intVal;
00072               if (nIndex < 0 || nIndex >= m_cElements.size())
00073               {
00074                      return E_INVALIDARG;
00075               }
00076               // Get the element at the specified index
00077               m_cElements[nIndex]->QueryInterface(IID_IDispatch, (void **) ppDisp);
00078               return S_OK;
00079        }
00080 
00081        // If var1 is a string, the caller wants a collection of all elements with
00082        // the matching tagname, unless var2 contains an index or if there is only
00083        // one in which case just the element is returned.
00084        
00085        CComVariant vName;
00086        if (FAILED(vName.ChangeType(VT_BSTR, &var1)))
00087        {
00088               return E_INVALIDARG;
00089        }
00090 
00091        // Compile a list of elements matching the name
00092        ElementList cElements;
00093        ElementList::iterator i;
00094 
00095        for (i = m_cElements.begin(); i != m_cElements.end(); i++)
00096        {
00097               CComQIPtr<IXMLElement, &IID_IXMLElement> spElement;
00098               BSTR bstrTagName = NULL;
00099               (*i)->get_tagName(&bstrTagName);
00100               if (bstrTagName)
00101               {
00102                      if (wcscmp(bstrTagName, vName.bstrVal) == 0)
00103                      {
00104                             cElements.push_back(*i);
00105                      }
00106                      SysFreeString(bstrTagName);
00107               }
00108        }
00109 
00110        // Are there any matching elements?
00111        if (cElements.empty())
00112        {
00113               return S_OK;
00114        }
00115 
00116        // Does var2 contain an index?
00117        if (var2.vt == VT_I4)
00118        {
00119               long nIndex = var2.vt;
00120               if (nIndex < 0 || nIndex >= cElements.size())
00121               {
00122                      return E_INVALIDARG;
00123               }
00124 
00125               // Get the element at the specified index
00126               cElements[nIndex]->QueryInterface(IID_IDispatch, (void **) ppDisp);
00127               return S_OK;
00128        }
00129 
00130        // Is there more than one element?
00131        if (cElements.size() > 1)
00132        {
00133               // Create another collection
00134               CXMLElementCollectionInstance *pCollection = NULL;
00135               CXMLElementCollectionInstance::CreateInstance(&pCollection);
00136               if (pCollection == NULL)
00137               {
00138                      return E_OUTOFMEMORY;
00139               }
00140 
00141               if (FAILED(pCollection->QueryInterface(IID_IDispatch, (void **) ppDisp)))
00142               {
00143                      pCollection->Release();
00144                      return E_FAIL;
00145               }
00146 
00147               // Add elements to the collection
00148               for (i = cElements.begin(); i != cElements.end(); i++)
00149               {
00150                      pCollection->Add(*i);
00151               }
00152 
00153               return S_OK;
00154        }
00155 
00156        // Return the pointer to the element
00157        if (FAILED(cElements[0]->QueryInterface(IID_IDispatch, (void **) ppDisp)))
00158        {
00159               return E_FAIL;
00160        }
00161 
00162        return S_OK;
00163 }
00164