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 name
,
244 static const WCHAR xmllangW
[] = { 'x','m','l',':','l','a','n','g',0 };
245 xmlelem
*This
= impl_from_IXMLElement(iface
);
248 TRACE("(%p, %s, %p)\n", iface
, debugstr_w(name
), value
);
254 V_BSTR(value
) = NULL
;
259 /* case for xml:lang attribute */
260 if (!lstrcmpiW(name
, xmllangW
))
263 ns
= xmlSearchNs(This
->node
->doc
, This
->node
, (xmlChar
*)"xml");
264 val
= xmlGetNsProp(This
->node
, (xmlChar
*)"lang", ns
->href
);
272 xml_name
= xmlChar_from_wchar(name
);
273 attr
= This
->node
->properties
;
278 attr_name
= bstr_from_xmlChar(attr
->name
);
279 if (!lstrcmpiW(name
, attr_name
))
281 val
= xmlNodeListGetString(attr
->doc
, attr
->children
, 1);
282 SysFreeString(attr_name
);
287 SysFreeString(attr_name
);
295 V_VT(value
) = VT_BSTR
;
296 V_BSTR(value
) = bstr_from_xmlChar(val
);
300 TRACE("returning %s\n", debugstr_w(V_BSTR(value
)));
301 return (val
) ? S_OK
: S_FALSE
;
304 static HRESULT WINAPI
xmlelem_removeAttribute(IXMLElement
*iface
, BSTR strPropertyName
)
306 xmlelem
*This
= impl_from_IXMLElement(iface
);
310 HRESULT hr
= S_FALSE
;
312 TRACE("(%p, %s)\n", iface
, debugstr_w(strPropertyName
));
314 if (!strPropertyName
)
317 name
= xmlChar_from_wchar(strPropertyName
);
318 attr
= xmlHasProp(This
->node
, name
);
322 res
= xmlRemoveProp(attr
);
332 static HRESULT WINAPI
xmlelem_get_children(IXMLElement
*iface
, IXMLElementCollection
**p
)
334 xmlelem
*This
= impl_from_IXMLElement(iface
);
336 TRACE("(%p, %p)\n", iface
, p
);
341 return XMLElementCollection_create((IUnknown
*)iface
, This
->node
, (LPVOID
*)p
);
344 static LONG
type_libxml_to_msxml(xmlElementType type
)
348 case XML_ELEMENT_NODE
:
349 return XMLELEMTYPE_ELEMENT
;
351 return XMLELEMTYPE_TEXT
;
352 case XML_COMMENT_NODE
:
353 return XMLELEMTYPE_COMMENT
;
354 case XML_DOCUMENT_NODE
:
355 return XMLELEMTYPE_DOCUMENT
;
357 return XMLELEMTYPE_DTD
;
359 return XMLELEMTYPE_PI
;
364 return XMLELEMTYPE_OTHER
;
367 static HRESULT WINAPI
xmlelem_get_type(IXMLElement
*iface
, LONG
*p
)
369 xmlelem
*This
= impl_from_IXMLElement(iface
);
371 TRACE("(%p, %p)\n", This
, p
);
376 *p
= type_libxml_to_msxml(This
->node
->type
);
377 TRACE("returning %d\n", *p
);
381 static HRESULT WINAPI
xmlelem_get_text(IXMLElement
*iface
, BSTR
*p
)
383 xmlelem
*This
= impl_from_IXMLElement(iface
);
386 TRACE("(%p, %p)\n", iface
, p
);
391 content
= xmlNodeGetContent(This
->node
);
392 *p
= bstr_from_xmlChar(content
);
393 TRACE("returning %s\n", debugstr_w(*p
));
399 static HRESULT WINAPI
xmlelem_put_text(IXMLElement
*iface
, BSTR p
)
401 xmlelem
*This
= impl_from_IXMLElement(iface
);
404 TRACE("(%p, %s)\n", iface
, debugstr_w(p
));
406 /* FIXME: test which types can be used */
407 if (This
->node
->type
== XML_ELEMENT_NODE
)
410 content
= xmlChar_from_wchar(p
);
411 xmlNodeSetContent(This
->node
, content
);
418 static HRESULT WINAPI
xmlelem_addChild(IXMLElement
*iface
, IXMLElement
*pChildElem
,
419 LONG lIndex
, LONG lreserved
)
421 xmlelem
*This
= impl_from_IXMLElement(iface
);
422 xmlelem
*childElem
= impl_from_IXMLElement(pChildElem
);
425 TRACE("(%p, %p, %d, %d)\n", iface
, pChildElem
, lIndex
, lreserved
);
428 child
= xmlAddChild(This
->node
, childElem
->node
);
430 child
= xmlAddNextSibling(This
->node
, childElem
->node
->last
);
432 /* parent is responsible for child data */
433 if (child
) childElem
->own
= FALSE
;
435 return (child
) ? S_OK
: S_FALSE
;
438 static HRESULT WINAPI
xmlelem_removeChild(IXMLElement
*iface
, IXMLElement
*pChildElem
)
440 xmlelem
*This
= impl_from_IXMLElement(iface
);
441 xmlelem
*childElem
= impl_from_IXMLElement(pChildElem
);
443 TRACE("(%p, %p)\n", This
, childElem
);
448 /* only supported for This is childElem parent case */
449 if (This
->node
!= childElem
->node
->parent
)
452 xmlUnlinkNode(childElem
->node
);
453 /* standalone element now */
454 childElem
->own
= TRUE
;
459 static const struct IXMLElementVtbl xmlelem_vtbl
=
461 xmlelem_QueryInterface
,
464 xmlelem_GetTypeInfoCount
,
466 xmlelem_GetIDsOfNames
,
471 xmlelem_setAttribute
,
472 xmlelem_getAttribute
,
473 xmlelem_removeAttribute
,
474 xmlelem_get_children
,
482 HRESULT
XMLElement_create(IUnknown
*pUnkOuter
, xmlNodePtr node
, LPVOID
*ppObj
, BOOL own
)
486 TRACE("(%p,%p)\n", pUnkOuter
, ppObj
);
493 elem
= heap_alloc(sizeof (*elem
));
495 return E_OUTOFMEMORY
;
497 elem
->lpVtbl
= &xmlelem_vtbl
;
502 *ppObj
= &elem
->lpVtbl
;
504 TRACE("returning iface %p\n", *ppObj
);
508 /************************************************************************
509 * IXMLElementCollection
511 typedef struct _xmlelem_collection
513 const IXMLElementCollectionVtbl
*lpVtbl
;
514 const IEnumVARIANTVtbl
*lpvtblIEnumVARIANT
;
519 /* IEnumVARIANT members */
521 } xmlelem_collection
;
523 static inline LONG
xmlelem_collection_updatelength(xmlelem_collection
*collection
)
525 xmlNodePtr ptr
= collection
->node
->children
;
527 collection
->length
= 0;
530 collection
->length
++;
533 return collection
->length
;
536 static inline xmlelem_collection
*impl_from_IXMLElementCollection(IXMLElementCollection
*iface
)
538 return (xmlelem_collection
*)((char*)iface
- FIELD_OFFSET(xmlelem_collection
, lpVtbl
));
541 static inline xmlelem_collection
*impl_from_IEnumVARIANT(IEnumVARIANT
*iface
)
543 return (xmlelem_collection
*)((char*)iface
- FIELD_OFFSET(xmlelem_collection
, lpvtblIEnumVARIANT
));
546 static HRESULT WINAPI
xmlelem_collection_QueryInterface(IXMLElementCollection
*iface
, REFIID riid
, void** ppvObject
)
548 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
550 TRACE("%p %s %p\n", This
, debugstr_guid(riid
), ppvObject
);
552 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
553 IsEqualGUID(riid
, &IID_IXMLElementCollection
))
557 else if (IsEqualGUID(riid
, &IID_IEnumVARIANT
))
559 *ppvObject
= &(This
->lpvtblIEnumVARIANT
);
563 FIXME("interface %s not implemented\n", debugstr_guid(riid
));
564 return E_NOINTERFACE
;
567 IXMLElementCollection_AddRef(iface
);
572 static ULONG WINAPI
xmlelem_collection_AddRef(IXMLElementCollection
*iface
)
574 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
576 return InterlockedIncrement(&This
->ref
);
579 static ULONG WINAPI
xmlelem_collection_Release(IXMLElementCollection
*iface
)
581 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
586 ref
= InterlockedDecrement(&This
->ref
);
595 static HRESULT WINAPI
xmlelem_collection_GetTypeInfoCount(IXMLElementCollection
*iface
, UINT
* pctinfo
)
601 static HRESULT WINAPI
xmlelem_collection_GetTypeInfo(IXMLElementCollection
*iface
, UINT iTInfo
,
602 LCID lcid
, ITypeInfo
** ppTInfo
)
608 static HRESULT WINAPI
xmlelem_collection_GetIDsOfNames(IXMLElementCollection
*iface
, REFIID riid
,
609 LPOLESTR
* rgszNames
, UINT cNames
,
610 LCID lcid
, DISPID
* rgDispId
)
616 static HRESULT WINAPI
xmlelem_collection_Invoke(IXMLElementCollection
*iface
, DISPID dispIdMember
,
617 REFIID riid
, LCID lcid
, WORD wFlags
,
618 DISPPARAMS
* pDispParams
, VARIANT
* pVarResult
,
619 EXCEPINFO
* pExcepInfo
, UINT
* puArgErr
)
625 static HRESULT WINAPI
xmlelem_collection_put_length(IXMLElementCollection
*iface
, LONG v
)
627 TRACE("(%p, %d)\n", iface
, v
);
631 static HRESULT WINAPI
xmlelem_collection_get_length(IXMLElementCollection
*iface
, LONG
*p
)
633 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
635 TRACE("(%p, %p)\n", iface
, p
);
640 *p
= xmlelem_collection_updatelength(This
);
644 static HRESULT WINAPI
xmlelem_collection_get__newEnum(IXMLElementCollection
*iface
, IUnknown
**ppUnk
)
646 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
648 TRACE("(%p, %p)\n", iface
, ppUnk
);
653 *ppUnk
= (IUnknown
*)This
;
654 IUnknown_AddRef(*ppUnk
);
658 static HRESULT WINAPI
xmlelem_collection_item(IXMLElementCollection
*iface
, VARIANT var1
,
659 VARIANT var2
, IDispatch
**ppDisp
)
661 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
662 xmlNodePtr ptr
= This
->node
->children
;
665 TRACE("(%p, %p)\n", iface
, ppDisp
);
676 xmlelem_collection_updatelength(This
);
677 if (index
>= This
->length
)
680 for (i
= 0; i
< index
; i
++)
683 return XMLElement_create((IUnknown
*)iface
, ptr
, (LPVOID
*)ppDisp
, FALSE
);
686 static const struct IXMLElementCollectionVtbl xmlelem_collection_vtbl
=
688 xmlelem_collection_QueryInterface
,
689 xmlelem_collection_AddRef
,
690 xmlelem_collection_Release
,
691 xmlelem_collection_GetTypeInfoCount
,
692 xmlelem_collection_GetTypeInfo
,
693 xmlelem_collection_GetIDsOfNames
,
694 xmlelem_collection_Invoke
,
695 xmlelem_collection_put_length
,
696 xmlelem_collection_get_length
,
697 xmlelem_collection_get__newEnum
,
698 xmlelem_collection_item
701 /************************************************************************
702 * xmlelem_collection implementation of IEnumVARIANT.
704 static HRESULT WINAPI
xmlelem_collection_IEnumVARIANT_QueryInterface(
705 IEnumVARIANT
*iface
, REFIID riid
, LPVOID
*ppvObj
)
707 xmlelem_collection
*this = impl_from_IEnumVARIANT(iface
);
708 return IXMLDocument_QueryInterface((IXMLDocument
*)this, riid
, ppvObj
);
711 static ULONG WINAPI
xmlelem_collection_IEnumVARIANT_AddRef(
714 xmlelem_collection
*this = impl_from_IEnumVARIANT(iface
);
715 return IXMLDocument_AddRef((IXMLDocument
*)this);
718 static ULONG WINAPI
xmlelem_collection_IEnumVARIANT_Release(
721 xmlelem_collection
*this = impl_from_IEnumVARIANT(iface
);
722 return IXMLDocument_Release((IXMLDocument
*)this);
725 static HRESULT WINAPI
xmlelem_collection_IEnumVARIANT_Next(
726 IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*rgVar
, ULONG
*fetched
)
728 xmlelem_collection
*This
= impl_from_IEnumVARIANT(iface
);
729 xmlNodePtr ptr
= This
->current
;
731 TRACE("(%p, %d, %p, %p)\n", iface
, celt
, rgVar
, fetched
);
736 /* FIXME: handle celt */
741 This
->current
= This
->current
->next
;
744 V_VT(rgVar
) = VT_EMPTY
;
745 if (fetched
) *fetched
= 0;
749 V_VT(rgVar
) = VT_DISPATCH
;
750 return XMLElement_create((IUnknown
*)iface
, ptr
, (LPVOID
*)&V_DISPATCH(rgVar
), FALSE
);
753 static HRESULT WINAPI
xmlelem_collection_IEnumVARIANT_Skip(
754 IEnumVARIANT
*iface
, ULONG celt
)
756 FIXME("(%p, %d): stub\n", iface
, celt
);
760 static HRESULT WINAPI
xmlelem_collection_IEnumVARIANT_Reset(
763 xmlelem_collection
*This
= impl_from_IEnumVARIANT(iface
);
764 This
->current
= This
->node
->children
;
768 static HRESULT WINAPI
xmlelem_collection_IEnumVARIANT_Clone(
769 IEnumVARIANT
*iface
, IEnumVARIANT
**ppEnum
)
771 FIXME("(%p, %p): stub\n", iface
, ppEnum
);
775 static const struct IEnumVARIANTVtbl xmlelem_collection_IEnumVARIANTvtbl
=
777 xmlelem_collection_IEnumVARIANT_QueryInterface
,
778 xmlelem_collection_IEnumVARIANT_AddRef
,
779 xmlelem_collection_IEnumVARIANT_Release
,
780 xmlelem_collection_IEnumVARIANT_Next
,
781 xmlelem_collection_IEnumVARIANT_Skip
,
782 xmlelem_collection_IEnumVARIANT_Reset
,
783 xmlelem_collection_IEnumVARIANT_Clone
786 static HRESULT
XMLElementCollection_create(IUnknown
*pUnkOuter
, xmlNodePtr node
, LPVOID
*ppObj
)
788 xmlelem_collection
*collection
;
790 TRACE("(%p,%p)\n", pUnkOuter
, ppObj
);
797 collection
= heap_alloc(sizeof (*collection
));
799 return E_OUTOFMEMORY
;
801 collection
->lpVtbl
= &xmlelem_collection_vtbl
;
802 collection
->lpvtblIEnumVARIANT
= &xmlelem_collection_IEnumVARIANTvtbl
;
804 collection
->length
= 0;
805 collection
->node
= node
;
806 collection
->current
= node
->children
;
807 xmlelem_collection_updatelength(collection
);
809 *ppObj
= &collection
->lpVtbl
;
811 TRACE("returning iface %p\n", *ppObj
);