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 static HRESULT XMLElementCollection_create( IUnknown *pUnkOuter, xmlNodePtr node, LPVOID *ppObj );
43 /**********************************************************************
46 typedef struct _xmlelem
48 const IXMLElementVtbl *lpVtbl;
54 static inline xmlelem *impl_from_IXMLElement(IXMLElement *iface)
56 return (xmlelem *)((char*)iface - FIELD_OFFSET(xmlelem, lpVtbl));
59 static HRESULT WINAPI xmlelem_QueryInterface(IXMLElement *iface, REFIID riid, void** ppvObject)
61 xmlelem *This = impl_from_IXMLElement(iface);
63 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
65 if (IsEqualGUID(riid, &IID_IUnknown) ||
66 IsEqualGUID(riid, &IID_IXMLElement))
72 FIXME("interface %s not implemented\n", debugstr_guid(riid));
76 IXMLElement_AddRef(iface);
81 static ULONG WINAPI xmlelem_AddRef(IXMLElement *iface)
83 xmlelem *This = impl_from_IXMLElement(iface);
85 return InterlockedIncrement(&This->ref);
88 static ULONG WINAPI xmlelem_Release(IXMLElement *iface)
90 xmlelem *This = impl_from_IXMLElement(iface);
95 ref = InterlockedDecrement(&This->ref);
98 if (This->own) xmlFreeNode(This->node);
105 static HRESULT WINAPI xmlelem_GetTypeInfoCount(IXMLElement *iface, UINT* pctinfo)
107 xmlelem *This = impl_from_IXMLElement(iface);
109 TRACE("(%p)->(%p)\n", This, pctinfo);
116 static HRESULT WINAPI xmlelem_GetTypeInfo(IXMLElement *iface, UINT iTInfo,
117 LCID lcid, ITypeInfo** ppTInfo)
119 xmlelem *This = impl_from_IXMLElement(iface);
122 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
124 hr = get_typeinfo(IXMLElement_tid, ppTInfo);
129 static HRESULT WINAPI xmlelem_GetIDsOfNames(IXMLElement *iface, REFIID riid,
130 LPOLESTR* rgszNames, UINT cNames,
131 LCID lcid, DISPID* rgDispId)
133 xmlelem *This = impl_from_IXMLElement(iface);
137 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
140 if(!rgszNames || cNames == 0 || !rgDispId)
143 hr = get_typeinfo(IXMLElement_tid, &typeinfo);
146 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
147 ITypeInfo_Release(typeinfo);
153 static HRESULT WINAPI xmlelem_Invoke(IXMLElement *iface, DISPID dispIdMember,
154 REFIID riid, LCID lcid, WORD wFlags,
155 DISPPARAMS* pDispParams, VARIANT* pVarResult,
156 EXCEPINFO* pExcepInfo, UINT* puArgErr)
158 xmlelem *This = impl_from_IXMLElement(iface);
162 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
163 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
165 hr = get_typeinfo(IXMLElement_tid, &typeinfo);
168 hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
169 pVarResult, pExcepInfo, puArgErr);
170 ITypeInfo_Release(typeinfo);
176 static HRESULT WINAPI xmlelem_get_tagName(IXMLElement *iface, BSTR *p)
178 xmlelem *This = impl_from_IXMLElement(iface);
180 TRACE("(%p, %p)\n", iface, p);
185 *p = bstr_from_xmlChar(This->node->name);
186 CharUpperBuffW(*p, SysStringLen(*p));
188 TRACE("returning %s\n", debugstr_w(*p));
193 static HRESULT WINAPI xmlelem_put_tagName(IXMLElement *iface, BSTR p)
195 FIXME("(%p, %p): stub\n", iface, p);
203 static HRESULT WINAPI xmlelem_get_parent(IXMLElement *iface, IXMLElement **parent)
205 xmlelem *This = impl_from_IXMLElement(iface);
207 TRACE("(%p, %p)\n", iface, parent);
214 if (!This->node->parent)
217 return XMLElement_create((IUnknown *)iface, This->node->parent, (LPVOID *)parent, FALSE);
220 static HRESULT WINAPI xmlelem_setAttribute(IXMLElement *iface, BSTR strPropertyName,
221 VARIANT PropertyValue)
223 xmlelem *This = impl_from_IXMLElement(iface);
224 xmlChar *name, *value;
227 TRACE("(%p, %s)\n", iface, debugstr_w(strPropertyName));
229 if (!strPropertyName || V_VT(&PropertyValue) != VT_BSTR)
232 name = xmlChar_from_wchar(strPropertyName);
233 value = xmlChar_from_wchar(V_BSTR(&PropertyValue));
234 attr = xmlSetProp(This->node, name, value);
238 return (attr) ? S_OK : S_FALSE;
241 static HRESULT WINAPI xmlelem_getAttribute(IXMLElement *iface, BSTR strPropertyName,
242 VARIANT *PropertyValue)
244 xmlelem *This = impl_from_IXMLElement(iface);
245 xmlChar *val = NULL, *name;
248 TRACE("(%p, %s, %p)\n", iface, debugstr_w(strPropertyName), PropertyValue);
253 VariantInit(PropertyValue);
254 V_BSTR(PropertyValue) = NULL;
256 if (!strPropertyName)
259 name = xmlChar_from_wchar(strPropertyName);
260 ptr = This->node->properties;
263 if (!lstrcmpiA((LPSTR)name, (LPCSTR)ptr->name))
265 val = xmlNodeListGetString(ptr->doc, ptr->children, 1);
274 V_VT(PropertyValue) = VT_BSTR;
275 V_BSTR(PropertyValue) = bstr_from_xmlChar(val);
280 TRACE("returning %s\n", debugstr_w(V_BSTR(PropertyValue)));
281 return (val) ? S_OK : S_FALSE;
284 static HRESULT WINAPI xmlelem_removeAttribute(IXMLElement *iface, BSTR strPropertyName)
286 xmlelem *This = impl_from_IXMLElement(iface);
290 HRESULT hr = S_FALSE;
292 TRACE("(%p, %s)\n", iface, debugstr_w(strPropertyName));
294 if (!strPropertyName)
297 name = xmlChar_from_wchar(strPropertyName);
298 attr = xmlHasProp(This->node, name);
302 res = xmlRemoveProp(attr);
312 static HRESULT WINAPI xmlelem_get_children(IXMLElement *iface, IXMLElementCollection **p)
314 xmlelem *This = impl_from_IXMLElement(iface);
316 TRACE("(%p, %p)\n", iface, p);
321 return XMLElementCollection_create((IUnknown *)iface, This->node, (LPVOID *)p);
324 static LONG type_libxml_to_msxml(xmlElementType type)
328 case XML_ELEMENT_NODE:
329 return XMLELEMTYPE_ELEMENT;
331 return XMLELEMTYPE_TEXT;
332 case XML_COMMENT_NODE:
333 return XMLELEMTYPE_COMMENT;
334 case XML_DOCUMENT_NODE:
335 return XMLELEMTYPE_DOCUMENT;
337 return XMLELEMTYPE_DTD;
339 return XMLELEMTYPE_PI;
344 return XMLELEMTYPE_OTHER;
347 static HRESULT WINAPI xmlelem_get_type(IXMLElement *iface, LONG *p)
349 xmlelem *This = impl_from_IXMLElement(iface);
351 TRACE("(%p, %p)\n", This, p);
356 *p = type_libxml_to_msxml(This->node->type);
357 TRACE("returning %d\n", *p);
361 static HRESULT WINAPI xmlelem_get_text(IXMLElement *iface, BSTR *p)
363 xmlelem *This = impl_from_IXMLElement(iface);
366 TRACE("(%p, %p)\n", iface, p);
371 content = xmlNodeGetContent(This->node);
372 *p = bstr_from_xmlChar(content);
373 TRACE("returning %s\n", debugstr_w(*p));
379 static HRESULT WINAPI xmlelem_put_text(IXMLElement *iface, BSTR p)
381 xmlelem *This = impl_from_IXMLElement(iface);
384 TRACE("(%p, %s)\n", iface, debugstr_w(p));
386 /* FIXME: test which types can be used */
387 if (This->node->type == XML_ELEMENT_NODE)
390 content = xmlChar_from_wchar(p);
391 xmlNodeSetContent(This->node, content);
398 static HRESULT WINAPI xmlelem_addChild(IXMLElement *iface, IXMLElement *pChildElem,
399 LONG lIndex, LONG lreserved)
401 xmlelem *This = impl_from_IXMLElement(iface);
402 xmlelem *childElem = impl_from_IXMLElement(pChildElem);
405 TRACE("(%p, %p, %d, %d)\n", iface, pChildElem, lIndex, lreserved);
408 child = xmlAddChild(This->node, childElem->node);
410 child = xmlAddNextSibling(This->node, childElem->node->last);
412 /* parent is responsible for child data */
413 if (child) childElem->own = FALSE;
415 return (child) ? S_OK : S_FALSE;
418 static HRESULT WINAPI xmlelem_removeChild(IXMLElement *iface, IXMLElement *pChildElem)
420 xmlelem *This = impl_from_IXMLElement(iface);
421 xmlelem *childElem = impl_from_IXMLElement(pChildElem);
423 TRACE("(%p, %p)\n", This, childElem);
428 /* only supported for This is childElem parent case */
429 if (This->node != childElem->node->parent)
432 xmlUnlinkNode(childElem->node);
433 /* standalone element now */
434 childElem->own = TRUE;
439 static const struct IXMLElementVtbl xmlelem_vtbl =
441 xmlelem_QueryInterface,
444 xmlelem_GetTypeInfoCount,
446 xmlelem_GetIDsOfNames,
451 xmlelem_setAttribute,
452 xmlelem_getAttribute,
453 xmlelem_removeAttribute,
454 xmlelem_get_children,
462 HRESULT XMLElement_create(IUnknown *pUnkOuter, xmlNodePtr node, LPVOID *ppObj, BOOL own)
466 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
473 elem = heap_alloc(sizeof (*elem));
475 return E_OUTOFMEMORY;
477 elem->lpVtbl = &xmlelem_vtbl;
482 *ppObj = &elem->lpVtbl;
484 TRACE("returning iface %p\n", *ppObj);
488 /************************************************************************
489 * IXMLElementCollection
491 typedef struct _xmlelem_collection
493 const IXMLElementCollectionVtbl *lpVtbl;
494 const IEnumVARIANTVtbl *lpvtblIEnumVARIANT;
499 /* IEnumVARIANT members */
501 } xmlelem_collection;
503 static inline LONG xmlelem_collection_updatelength(xmlelem_collection *collection)
505 xmlNodePtr ptr = collection->node->children;
507 collection->length = 0;
510 collection->length++;
513 return collection->length;
516 static inline xmlelem_collection *impl_from_IXMLElementCollection(IXMLElementCollection *iface)
518 return (xmlelem_collection *)((char*)iface - FIELD_OFFSET(xmlelem_collection, lpVtbl));
521 static inline xmlelem_collection *impl_from_IEnumVARIANT(IEnumVARIANT *iface)
523 return (xmlelem_collection *)((char*)iface - FIELD_OFFSET(xmlelem_collection, lpvtblIEnumVARIANT));
526 static HRESULT WINAPI xmlelem_collection_QueryInterface(IXMLElementCollection *iface, REFIID riid, void** ppvObject)
528 xmlelem_collection *This = impl_from_IXMLElementCollection(iface);
530 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
532 if (IsEqualGUID(riid, &IID_IUnknown) ||
533 IsEqualGUID(riid, &IID_IXMLElementCollection))
537 else if (IsEqualGUID(riid, &IID_IEnumVARIANT))
539 *ppvObject = &(This->lpvtblIEnumVARIANT);
543 FIXME("interface %s not implemented\n", debugstr_guid(riid));
544 return E_NOINTERFACE;
547 IXMLElementCollection_AddRef(iface);
552 static ULONG WINAPI xmlelem_collection_AddRef(IXMLElementCollection *iface)
554 xmlelem_collection *This = impl_from_IXMLElementCollection(iface);
556 return InterlockedIncrement(&This->ref);
559 static ULONG WINAPI xmlelem_collection_Release(IXMLElementCollection *iface)
561 xmlelem_collection *This = impl_from_IXMLElementCollection(iface);
566 ref = InterlockedDecrement(&This->ref);
575 static HRESULT WINAPI xmlelem_collection_GetTypeInfoCount(IXMLElementCollection *iface, UINT* pctinfo)
581 static HRESULT WINAPI xmlelem_collection_GetTypeInfo(IXMLElementCollection *iface, UINT iTInfo,
582 LCID lcid, ITypeInfo** ppTInfo)
588 static HRESULT WINAPI xmlelem_collection_GetIDsOfNames(IXMLElementCollection *iface, REFIID riid,
589 LPOLESTR* rgszNames, UINT cNames,
590 LCID lcid, DISPID* rgDispId)
596 static HRESULT WINAPI xmlelem_collection_Invoke(IXMLElementCollection *iface, DISPID dispIdMember,
597 REFIID riid, LCID lcid, WORD wFlags,
598 DISPPARAMS* pDispParams, VARIANT* pVarResult,
599 EXCEPINFO* pExcepInfo, UINT* puArgErr)
605 static HRESULT WINAPI xmlelem_collection_put_length(IXMLElementCollection *iface, LONG v)
607 TRACE("(%p, %d)\n", iface, v);
611 static HRESULT WINAPI xmlelem_collection_get_length(IXMLElementCollection *iface, LONG *p)
613 xmlelem_collection *This = impl_from_IXMLElementCollection(iface);
615 TRACE("(%p, %p)\n", iface, p);
620 *p = xmlelem_collection_updatelength(This);
624 static HRESULT WINAPI xmlelem_collection_get__newEnum(IXMLElementCollection *iface, IUnknown **ppUnk)
626 xmlelem_collection *This = impl_from_IXMLElementCollection(iface);
628 TRACE("(%p, %p)\n", iface, ppUnk);
633 *ppUnk = (IUnknown *)This;
634 IUnknown_AddRef(*ppUnk);
638 static HRESULT WINAPI xmlelem_collection_item(IXMLElementCollection *iface, VARIANT var1,
639 VARIANT var2, IDispatch **ppDisp)
641 xmlelem_collection *This = impl_from_IXMLElementCollection(iface);
642 xmlNodePtr ptr = This->node->children;
645 TRACE("(%p, %p)\n", iface, ppDisp);
656 xmlelem_collection_updatelength(This);
657 if (index >= This->length)
660 for (i = 0; i < index; i++)
663 return XMLElement_create((IUnknown *)iface, ptr, (LPVOID *)ppDisp, FALSE);
666 static const struct IXMLElementCollectionVtbl xmlelem_collection_vtbl =
668 xmlelem_collection_QueryInterface,
669 xmlelem_collection_AddRef,
670 xmlelem_collection_Release,
671 xmlelem_collection_GetTypeInfoCount,
672 xmlelem_collection_GetTypeInfo,
673 xmlelem_collection_GetIDsOfNames,
674 xmlelem_collection_Invoke,
675 xmlelem_collection_put_length,
676 xmlelem_collection_get_length,
677 xmlelem_collection_get__newEnum,
678 xmlelem_collection_item
681 /************************************************************************
682 * xmlelem_collection implementation of IEnumVARIANT.
684 static HRESULT WINAPI xmlelem_collection_IEnumVARIANT_QueryInterface(
685 IEnumVARIANT *iface, REFIID riid, LPVOID *ppvObj)
687 xmlelem_collection *this = impl_from_IEnumVARIANT(iface);
688 return IXMLDocument_QueryInterface((IXMLDocument *)this, riid, ppvObj);
691 static ULONG WINAPI xmlelem_collection_IEnumVARIANT_AddRef(
694 xmlelem_collection *this = impl_from_IEnumVARIANT(iface);
695 return IXMLDocument_AddRef((IXMLDocument *)this);
698 static ULONG WINAPI xmlelem_collection_IEnumVARIANT_Release(
701 xmlelem_collection *this = impl_from_IEnumVARIANT(iface);
702 return IXMLDocument_Release((IXMLDocument *)this);
705 static HRESULT WINAPI xmlelem_collection_IEnumVARIANT_Next(
706 IEnumVARIANT *iface, ULONG celt, VARIANT *rgVar, ULONG *pCeltFetched)
708 xmlelem_collection *This = impl_from_IEnumVARIANT(iface);
709 xmlNodePtr ptr = This->current;
711 TRACE("(%p, %d, %p, %p)\n", iface, celt, rgVar, pCeltFetched);
716 /* FIXME: handle celt */
720 This->current = This->current->next;
722 V_VT(rgVar) = VT_DISPATCH;
723 return XMLElement_create((IUnknown *)iface, ptr, (LPVOID *)&V_DISPATCH(rgVar), FALSE);
726 static HRESULT WINAPI xmlelem_collection_IEnumVARIANT_Skip(
727 IEnumVARIANT *iface, ULONG celt)
729 FIXME("(%p, %d): stub\n", iface, celt);
733 static HRESULT WINAPI xmlelem_collection_IEnumVARIANT_Reset(
736 xmlelem_collection *This = impl_from_IEnumVARIANT(iface);
737 This->current = This->node->children;
741 static HRESULT WINAPI xmlelem_collection_IEnumVARIANT_Clone(
742 IEnumVARIANT *iface, IEnumVARIANT **ppEnum)
744 FIXME("(%p, %p): stub\n", iface, ppEnum);
748 static const struct IEnumVARIANTVtbl xmlelem_collection_IEnumVARIANTvtbl =
750 xmlelem_collection_IEnumVARIANT_QueryInterface,
751 xmlelem_collection_IEnumVARIANT_AddRef,
752 xmlelem_collection_IEnumVARIANT_Release,
753 xmlelem_collection_IEnumVARIANT_Next,
754 xmlelem_collection_IEnumVARIANT_Skip,
755 xmlelem_collection_IEnumVARIANT_Reset,
756 xmlelem_collection_IEnumVARIANT_Clone
759 static HRESULT XMLElementCollection_create(IUnknown *pUnkOuter, xmlNodePtr node, LPVOID *ppObj)
761 xmlelem_collection *collection;
763 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
770 collection = heap_alloc(sizeof (*collection));
772 return E_OUTOFMEMORY;
774 collection->lpVtbl = &xmlelem_collection_vtbl;
775 collection->lpvtblIEnumVARIANT = &xmlelem_collection_IEnumVARIANTvtbl;
777 collection->length = 0;
778 collection->node = node;
779 collection->current = node->children;
780 xmlelem_collection_updatelength(collection);
782 *ppObj = &collection->lpVtbl;
784 TRACE("returning iface %p\n", *ppObj);