2 * XML Element implementation
4 * Copyright 2007 James Hawkins
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
33 #include "wine/debug.h"
35 #include "msxml_private.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
41 /**********************************************************************
44 typedef struct _xmlelem
46 const IXMLElementVtbl *lpVtbl;
51 static inline xmlelem *impl_from_IXMLElement(IXMLElement *iface)
53 return (xmlelem *)((char*)iface - FIELD_OFFSET(xmlelem, lpVtbl));
56 static HRESULT WINAPI xmlelem_QueryInterface(IXMLElement *iface, REFIID riid, void** ppvObject)
58 xmlelem *This = impl_from_IXMLElement(iface);
60 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
62 if (IsEqualGUID(riid, &IID_IUnknown) ||
63 IsEqualGUID(riid, &IID_IXMLElement))
69 FIXME("interface %s not implemented\n", debugstr_guid(riid));
73 IXMLElement_AddRef(iface);
78 static ULONG WINAPI xmlelem_AddRef(IXMLElement *iface)
80 xmlelem *This = impl_from_IXMLElement(iface);
82 return InterlockedIncrement(&This->ref);
85 static ULONG WINAPI xmlelem_Release(IXMLElement *iface)
87 xmlelem *This = impl_from_IXMLElement(iface);
92 ref = InterlockedDecrement(&This->ref);
95 HeapFree(GetProcessHeap(), 0, This);
101 static HRESULT WINAPI xmlelem_GetTypeInfoCount(IXMLElement *iface, UINT* pctinfo)
103 xmlelem *This = impl_from_IXMLElement(iface);
105 TRACE("(%p)->(%p)\n", This, pctinfo);
112 static HRESULT WINAPI xmlelem_GetTypeInfo(IXMLElement *iface, UINT iTInfo,
113 LCID lcid, ITypeInfo** ppTInfo)
115 xmlelem *This = impl_from_IXMLElement(iface);
118 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
120 hr = get_typeinfo(IXMLElement_tid, ppTInfo);
125 static HRESULT WINAPI xmlelem_GetIDsOfNames(IXMLElement *iface, REFIID riid,
126 LPOLESTR* rgszNames, UINT cNames,
127 LCID lcid, DISPID* rgDispId)
129 xmlelem *This = impl_from_IXMLElement(iface);
133 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
136 if(!rgszNames || cNames == 0 || !rgDispId)
139 hr = get_typeinfo(IXMLElement_tid, &typeinfo);
142 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
143 ITypeInfo_Release(typeinfo);
149 static HRESULT WINAPI xmlelem_Invoke(IXMLElement *iface, DISPID dispIdMember,
150 REFIID riid, LCID lcid, WORD wFlags,
151 DISPPARAMS* pDispParams, VARIANT* pVarResult,
152 EXCEPINFO* pExcepInfo, UINT* puArgErr)
154 xmlelem *This = impl_from_IXMLElement(iface);
158 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
159 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
161 hr = get_typeinfo(IXMLElement_tid, &typeinfo);
164 hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
165 pVarResult, pExcepInfo, puArgErr);
166 ITypeInfo_Release(typeinfo);
172 static inline BSTR str_dup_upper(BSTR str)
174 INT len = (lstrlenW(str) + 1) * sizeof(WCHAR);
175 BSTR p = SysAllocStringLen(NULL, len);
184 static HRESULT WINAPI xmlelem_get_tagName(IXMLElement *iface, BSTR *p)
186 xmlelem *This = impl_from_IXMLElement(iface);
189 TRACE("(%p, %p)\n", iface, p);
194 temp = bstr_from_xmlChar(This->node->name);
195 *p = str_dup_upper(temp);
198 TRACE("returning %s\n", debugstr_w(*p));
203 static HRESULT WINAPI xmlelem_put_tagName(IXMLElement *iface, BSTR p)
205 FIXME("(%p, %p): stub\n", iface, p);
213 static HRESULT WINAPI xmlelem_get_parent(IXMLElement *iface, IXMLElement **parent)
215 xmlelem *This = impl_from_IXMLElement(iface);
217 TRACE("(%p, %p)\n", iface, parent);
224 if (!This->node->parent)
227 return XMLElement_create((IUnknown *)iface, This->node->parent, (LPVOID *)parent);
230 static HRESULT WINAPI xmlelem_setAttribute(IXMLElement *iface, BSTR strPropertyName,
231 VARIANT PropertyValue)
233 xmlelem *This = impl_from_IXMLElement(iface);
234 xmlChar *name, *value;
237 TRACE("(%p, %s)\n", iface, debugstr_w(strPropertyName));
239 if (!strPropertyName || V_VT(&PropertyValue) != VT_BSTR)
242 name = xmlChar_from_wchar(strPropertyName);
243 value = xmlChar_from_wchar(V_BSTR(&PropertyValue));
244 attr = xmlSetProp(This->node, name, value);
246 HeapFree(GetProcessHeap(), 0, name);
247 HeapFree(GetProcessHeap(), 0, value);
248 return (attr) ? S_OK : S_FALSE;
251 static HRESULT WINAPI xmlelem_getAttribute(IXMLElement *iface, BSTR strPropertyName,
252 VARIANT *PropertyValue)
254 xmlelem *This = impl_from_IXMLElement(iface);
255 xmlChar *val = NULL, *name;
258 TRACE("(%p, %s, %p)\n", iface, debugstr_w(strPropertyName), PropertyValue);
263 VariantInit(PropertyValue);
264 V_BSTR(PropertyValue) = NULL;
266 if (!strPropertyName)
269 name = xmlChar_from_wchar(strPropertyName);
270 ptr = This->node->properties;
273 if (!lstrcmpiA((LPSTR)name, (LPCSTR)ptr->name))
275 val = xmlNodeListGetString(ptr->doc, ptr->children, 1);
284 V_VT(PropertyValue) = VT_BSTR;
285 V_BSTR(PropertyValue) = bstr_from_xmlChar(val);
288 HeapFree(GetProcessHeap(), 0, name);
290 TRACE("returning %s\n", debugstr_w(V_BSTR(PropertyValue)));
291 return (val) ? S_OK : S_FALSE;
294 static HRESULT WINAPI xmlelem_removeAttribute(IXMLElement *iface, BSTR strPropertyName)
296 xmlelem *This = impl_from_IXMLElement(iface);
300 HRESULT hr = S_FALSE;
302 TRACE("(%p, %s)\n", iface, debugstr_w(strPropertyName));
304 if (!strPropertyName)
307 name = xmlChar_from_wchar(strPropertyName);
308 attr = xmlHasProp(This->node, name);
312 res = xmlRemoveProp(attr);
318 HeapFree(GetProcessHeap(), 0, name);
322 static HRESULT WINAPI xmlelem_get_children(IXMLElement *iface, IXMLElementCollection **p)
324 xmlelem *This = impl_from_IXMLElement(iface);
326 TRACE("(%p, %p)\n", iface, p);
331 return XMLElementCollection_create((IUnknown *)iface, This->node->children, (LPVOID *)p);
334 static long type_libxml_to_msxml(xmlElementType type)
338 case XML_ELEMENT_NODE:
339 return XMLELEMTYPE_ELEMENT;
341 return XMLELEMTYPE_TEXT;
342 case XML_COMMENT_NODE:
343 return XMLELEMTYPE_COMMENT;
344 case XML_DOCUMENT_NODE:
345 return XMLELEMTYPE_DOCUMENT;
347 return XMLELEMTYPE_DTD;
349 return XMLELEMTYPE_PI;
354 return XMLELEMTYPE_OTHER;
357 static HRESULT WINAPI xmlelem_get_type(IXMLElement *iface, long *p)
359 xmlelem *This = impl_from_IXMLElement(iface);
361 TRACE("(%p, %p)\n", This, p);
366 *p = type_libxml_to_msxml(This->node->type);
367 TRACE("returning %ld\n", *p);
371 static HRESULT WINAPI xmlelem_get_text(IXMLElement *iface, BSTR *p)
373 xmlelem *This = impl_from_IXMLElement(iface);
376 TRACE("(%p, %p)\n", iface, p);
381 content = xmlNodeGetContent(This->node);
382 *p = bstr_from_xmlChar(content);
383 TRACE("returning %s\n", debugstr_w(*p));
389 static HRESULT WINAPI xmlelem_put_text(IXMLElement *iface, BSTR p)
391 xmlelem *This = impl_from_IXMLElement(iface);
394 TRACE("(%p, %s)\n", iface, debugstr_w(p));
396 /* FIXME: test which types can be used */
397 if (This->node->type == XML_ELEMENT_NODE)
400 content = xmlChar_from_wchar(p);
401 xmlNodeSetContent(This->node, content);
403 HeapFree( GetProcessHeap(), 0, content);
408 static HRESULT WINAPI xmlelem_addChild(IXMLElement *iface, IXMLElement *pChildElem,
409 long lIndex, long lreserved)
411 xmlelem *This = impl_from_IXMLElement(iface);
412 xmlelem *childElem = impl_from_IXMLElement(pChildElem);
415 TRACE("(%p, %p, %ld, %ld)\n", iface, pChildElem, lIndex, lreserved);
418 child = xmlAddChild(This->node, childElem->node);
420 child = xmlAddNextSibling(This->node, childElem->node->last);
422 return (child) ? S_OK : S_FALSE;
425 static HRESULT WINAPI xmlelem_removeChild(IXMLElement *iface, IXMLElement *pChildElem)
427 FIXME("(%p, %p): stub\n", iface, pChildElem);
431 static const struct IXMLElementVtbl xmlelem_vtbl =
433 xmlelem_QueryInterface,
436 xmlelem_GetTypeInfoCount,
438 xmlelem_GetIDsOfNames,
443 xmlelem_setAttribute,
444 xmlelem_getAttribute,
445 xmlelem_removeAttribute,
446 xmlelem_get_children,
454 HRESULT XMLElement_create(IUnknown *pUnkOuter, xmlNodePtr node, LPVOID *ppObj)
458 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
465 elem = HeapAlloc(GetProcessHeap(), 0, sizeof (*elem));
467 return E_OUTOFMEMORY;
469 elem->lpVtbl = &xmlelem_vtbl;
473 *ppObj = &elem->lpVtbl;
475 TRACE("returning iface %p\n", *ppObj);
479 /************************************************************************
480 * IXMLElementCollection
482 typedef struct _xmlelem_collection
484 const IXMLElementCollectionVtbl *lpVtbl;
485 const IEnumVARIANTVtbl *lpvtblIEnumVARIANT;
490 /* IEnumVARIANT members */
492 } xmlelem_collection;
494 static inline xmlelem_collection *impl_from_IXMLElementCollection(IXMLElementCollection *iface)
496 return (xmlelem_collection *)((char*)iface - FIELD_OFFSET(xmlelem_collection, lpVtbl));
499 static inline xmlelem_collection *impl_from_IEnumVARIANT(IEnumVARIANT *iface)
501 return (xmlelem_collection *)((char*)iface - FIELD_OFFSET(xmlelem_collection, lpvtblIEnumVARIANT));
504 static HRESULT WINAPI xmlelem_collection_QueryInterface(IXMLElementCollection *iface, REFIID riid, void** ppvObject)
506 xmlelem_collection *This = impl_from_IXMLElementCollection(iface);
508 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
510 if (IsEqualGUID(riid, &IID_IUnknown) ||
511 IsEqualGUID(riid, &IID_IXMLElementCollection))
515 else if (IsEqualGUID(riid, &IID_IEnumVARIANT))
517 *ppvObject = (IEnumVARIANT *)&(This->lpvtblIEnumVARIANT);
521 FIXME("interface %s not implemented\n", debugstr_guid(riid));
522 return E_NOINTERFACE;
525 IXMLElementCollection_AddRef(iface);
530 static ULONG WINAPI xmlelem_collection_AddRef(IXMLElementCollection *iface)
532 xmlelem_collection *This = impl_from_IXMLElementCollection(iface);
534 return InterlockedIncrement(&This->ref);
537 static ULONG WINAPI xmlelem_collection_Release(IXMLElementCollection *iface)
539 xmlelem_collection *This = impl_from_IXMLElementCollection(iface);
544 ref = InterlockedDecrement(&This->ref);
547 HeapFree(GetProcessHeap(), 0, This);
553 static HRESULT WINAPI xmlelem_collection_GetTypeInfoCount(IXMLElementCollection *iface, UINT* pctinfo)
559 static HRESULT WINAPI xmlelem_collection_GetTypeInfo(IXMLElementCollection *iface, UINT iTInfo,
560 LCID lcid, ITypeInfo** ppTInfo)
566 static HRESULT WINAPI xmlelem_collection_GetIDsOfNames(IXMLElementCollection *iface, REFIID riid,
567 LPOLESTR* rgszNames, UINT cNames,
568 LCID lcid, DISPID* rgDispId)
574 static HRESULT WINAPI xmlelem_collection_Invoke(IXMLElementCollection *iface, DISPID dispIdMember,
575 REFIID riid, LCID lcid, WORD wFlags,
576 DISPPARAMS* pDispParams, VARIANT* pVarResult,
577 EXCEPINFO* pExcepInfo, UINT* puArgErr)
583 static HRESULT WINAPI xmlelem_collection_put_length(IXMLElementCollection *iface, long v)
585 TRACE("(%p, %ld)\n", iface, v);
589 static HRESULT WINAPI xmlelem_collection_get_length(IXMLElementCollection *iface, long *p)
591 xmlelem_collection *This = impl_from_IXMLElementCollection(iface);
593 TRACE("(%p, %p)\n", iface, p);
602 static HRESULT WINAPI xmlelem_collection_get__newEnum(IXMLElementCollection *iface, IUnknown **ppUnk)
604 xmlelem_collection *This = impl_from_IXMLElementCollection(iface);
606 TRACE("(%p, %p)\n", iface, ppUnk);
611 *ppUnk = (IUnknown *)This;
612 IUnknown_AddRef(*ppUnk);
616 static HRESULT WINAPI xmlelem_collection_item(IXMLElementCollection *iface, VARIANT var1,
617 VARIANT var2, IDispatch **ppDisp)
619 xmlelem_collection *This = impl_from_IXMLElementCollection(iface);
620 xmlNodePtr ptr = This->node;
623 TRACE("(%p, %p)\n", iface, ppDisp);
633 if (index >= This->length)
636 for (i = 0; i < index; i++)
639 return XMLElement_create((IUnknown *)iface, ptr, (LPVOID *)ppDisp);
642 static const struct IXMLElementCollectionVtbl xmlelem_collection_vtbl =
644 xmlelem_collection_QueryInterface,
645 xmlelem_collection_AddRef,
646 xmlelem_collection_Release,
647 xmlelem_collection_GetTypeInfoCount,
648 xmlelem_collection_GetTypeInfo,
649 xmlelem_collection_GetIDsOfNames,
650 xmlelem_collection_Invoke,
651 xmlelem_collection_put_length,
652 xmlelem_collection_get_length,
653 xmlelem_collection_get__newEnum,
654 xmlelem_collection_item
657 /************************************************************************
658 * xmlelem_collection implementation of IEnumVARIANT.
660 static HRESULT WINAPI xmlelem_collection_IEnumVARIANT_QueryInterface(
661 IEnumVARIANT *iface, REFIID riid, LPVOID *ppvObj)
663 xmlelem_collection *this = impl_from_IEnumVARIANT(iface);
664 return IXMLDocument_QueryInterface((IXMLDocument *)this, riid, ppvObj);
667 static ULONG WINAPI xmlelem_collection_IEnumVARIANT_AddRef(
670 xmlelem_collection *this = impl_from_IEnumVARIANT(iface);
671 return IXMLDocument_AddRef((IXMLDocument *)this);
674 static ULONG WINAPI xmlelem_collection_IEnumVARIANT_Release(
677 xmlelem_collection *this = impl_from_IEnumVARIANT(iface);
678 return IXMLDocument_Release((IXMLDocument *)this);
681 static HRESULT WINAPI xmlelem_collection_IEnumVARIANT_Next(
682 IEnumVARIANT *iface, ULONG celt, VARIANT *rgVar, ULONG *pCeltFetched)
684 xmlelem_collection *This = impl_from_IEnumVARIANT(iface);
685 xmlNodePtr ptr = This->current;
687 TRACE("(%p, %d, %p, %p)\n", iface, celt, rgVar, pCeltFetched);
692 /* FIXME: handle celt */
696 This->current = This->current->next;
698 V_VT(rgVar) = VT_DISPATCH;
699 return XMLElement_create((IUnknown *)iface, ptr, (LPVOID *)&V_DISPATCH(rgVar));
702 static HRESULT WINAPI xmlelem_collection_IEnumVARIANT_Skip(
703 IEnumVARIANT *iface, ULONG celt)
705 FIXME("(%p, %d): stub\n", iface, celt);
709 static HRESULT WINAPI xmlelem_collection_IEnumVARIANT_Reset(
712 xmlelem_collection *This = impl_from_IEnumVARIANT(iface);
713 This->current = This->node;
717 static HRESULT WINAPI xmlelem_collection_IEnumVARIANT_Clone(
718 IEnumVARIANT *iface, IEnumVARIANT **ppEnum)
720 FIXME("(%p, %p): stub\n", iface, ppEnum);
724 static const struct IEnumVARIANTVtbl xmlelem_collection_IEnumVARIANTvtbl =
726 xmlelem_collection_IEnumVARIANT_QueryInterface,
727 xmlelem_collection_IEnumVARIANT_AddRef,
728 xmlelem_collection_IEnumVARIANT_Release,
729 xmlelem_collection_IEnumVARIANT_Next,
730 xmlelem_collection_IEnumVARIANT_Skip,
731 xmlelem_collection_IEnumVARIANT_Reset,
732 xmlelem_collection_IEnumVARIANT_Clone
735 HRESULT XMLElementCollection_create(IUnknown *pUnkOuter, xmlNodePtr node, LPVOID *ppObj)
737 xmlelem_collection *collection;
740 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
747 collection = HeapAlloc(GetProcessHeap(), 0, sizeof (*collection));
749 return E_OUTOFMEMORY;
751 collection->lpVtbl = &xmlelem_collection_vtbl;
752 collection->lpvtblIEnumVARIANT = &xmlelem_collection_IEnumVARIANTvtbl;
754 collection->length = 0;
755 collection->node = node;
756 collection->current = node;
761 collection->length++;
765 *ppObj = &collection->lpVtbl;
767 TRACE("returning iface %p\n", *ppObj);