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
25 static HRESULT
XMLElementCollection_create( xmlNodePtr node
, LPVOID
*ppObj
);
27 /**********************************************************************
30 typedef struct _xmlelem
32 IXMLElement IXMLElement_iface
;
38 static inline xmlelem
*impl_from_IXMLElement(IXMLElement
*iface
)
40 return CONTAINING_RECORD(iface
, xmlelem
, IXMLElement_iface
);
43 static HRESULT WINAPI
xmlelem_QueryInterface(IXMLElement
*iface
, REFIID riid
, void** ppvObject
)
45 xmlelem
*This
= impl_from_IXMLElement(iface
);
47 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppvObject
);
49 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
50 IsEqualGUID(riid
, &IID_IDispatch
) ||
51 IsEqualGUID(riid
, &IID_IXMLElement
))
57 FIXME("interface %s not implemented\n", debugstr_guid(riid
));
62 IXMLElement_AddRef(iface
);
67 static ULONG WINAPI
xmlelem_AddRef(IXMLElement
*iface
)
69 xmlelem
*This
= impl_from_IXMLElement(iface
);
71 return InterlockedIncrement(&This
->ref
);
74 static ULONG WINAPI
xmlelem_Release(IXMLElement
*iface
)
76 xmlelem
*This
= impl_from_IXMLElement(iface
);
81 ref
= InterlockedDecrement(&This
->ref
);
84 if (This
->own
) xmlFreeNode(This
->node
);
91 static HRESULT WINAPI
xmlelem_GetTypeInfoCount(IXMLElement
*iface
, UINT
* pctinfo
)
93 xmlelem
*This
= impl_from_IXMLElement(iface
);
95 TRACE("(%p)->(%p)\n", This
, pctinfo
);
102 static HRESULT WINAPI
xmlelem_GetTypeInfo(IXMLElement
*iface
, UINT iTInfo
,
103 LCID lcid
, ITypeInfo
** ppTInfo
)
105 xmlelem
*This
= impl_from_IXMLElement(iface
);
108 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
110 hr
= get_typeinfo(IXMLElement_tid
, ppTInfo
);
115 static HRESULT WINAPI
xmlelem_GetIDsOfNames(IXMLElement
*iface
, REFIID riid
,
116 LPOLESTR
* rgszNames
, UINT cNames
,
117 LCID lcid
, DISPID
* rgDispId
)
119 xmlelem
*This
= impl_from_IXMLElement(iface
);
123 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
,
126 if(!rgszNames
|| cNames
== 0 || !rgDispId
)
129 hr
= get_typeinfo(IXMLElement_tid
, &typeinfo
);
132 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
133 ITypeInfo_Release(typeinfo
);
139 static HRESULT WINAPI
xmlelem_Invoke(IXMLElement
*iface
, DISPID dispIdMember
,
140 REFIID riid
, LCID lcid
, WORD wFlags
,
141 DISPPARAMS
* pDispParams
, VARIANT
* pVarResult
,
142 EXCEPINFO
* pExcepInfo
, UINT
* puArgErr
)
144 xmlelem
*This
= impl_from_IXMLElement(iface
);
148 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
149 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
151 hr
= get_typeinfo(IXMLElement_tid
, &typeinfo
);
154 hr
= ITypeInfo_Invoke(typeinfo
, &This
->IXMLElement_iface
, dispIdMember
, wFlags
, pDispParams
,
155 pVarResult
, pExcepInfo
, puArgErr
);
156 ITypeInfo_Release(typeinfo
);
162 static HRESULT WINAPI
xmlelem_get_tagName(IXMLElement
*iface
, BSTR
*p
)
164 xmlelem
*This
= impl_from_IXMLElement(iface
);
166 TRACE("(%p)->(%p)\n", This
, p
);
171 if (*This
->node
->name
) {
172 *p
= bstr_from_xmlChar(This
->node
->name
);
173 CharUpperBuffW(*p
, SysStringLen(*p
));
178 TRACE("returning %s\n", debugstr_w(*p
));
183 static HRESULT WINAPI
xmlelem_put_tagName(IXMLElement
*iface
, BSTR p
)
185 xmlelem
*This
= impl_from_IXMLElement(iface
);
187 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(p
));
195 static HRESULT WINAPI
xmlelem_get_parent(IXMLElement
*iface
, IXMLElement
**parent
)
197 xmlelem
*This
= impl_from_IXMLElement(iface
);
199 TRACE("(%p)->(%p)\n", This
, parent
);
206 if (!This
->node
->parent
)
209 return XMLElement_create(This
->node
->parent
, (LPVOID
*)parent
, FALSE
);
212 static HRESULT WINAPI
xmlelem_setAttribute(IXMLElement
*iface
, BSTR strPropertyName
,
213 VARIANT PropertyValue
)
215 xmlelem
*This
= impl_from_IXMLElement(iface
);
216 xmlChar
*name
, *value
;
219 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(strPropertyName
), debugstr_variant(&PropertyValue
));
221 if (!strPropertyName
|| V_VT(&PropertyValue
) != VT_BSTR
)
224 name
= xmlchar_from_wchar(strPropertyName
);
225 value
= xmlchar_from_wchar(V_BSTR(&PropertyValue
));
226 attr
= xmlSetProp(This
->node
, name
, value
);
230 return (attr
) ? S_OK
: S_FALSE
;
233 static HRESULT WINAPI
xmlelem_getAttribute(IXMLElement
*iface
, BSTR name
,
236 static const WCHAR xmllangW
[] = { 'x','m','l',':','l','a','n','g',0 };
237 xmlelem
*This
= impl_from_IXMLElement(iface
);
240 TRACE("(%p)->(%s, %p)\n", This
, debugstr_w(name
), value
);
246 V_BSTR(value
) = NULL
;
251 /* case for xml:lang attribute */
252 if (!lstrcmpiW(name
, xmllangW
))
255 ns
= xmlSearchNs(This
->node
->doc
, This
->node
, (xmlChar
*)"xml");
256 val
= xmlGetNsProp(This
->node
, (xmlChar
*)"lang", ns
->href
);
263 xml_name
= xmlchar_from_wchar(name
);
264 attr
= This
->node
->properties
;
269 attr_name
= bstr_from_xmlChar(attr
->name
);
270 if (!lstrcmpiW(name
, attr_name
))
272 val
= xmlNodeListGetString(attr
->doc
, attr
->children
, 1);
273 SysFreeString(attr_name
);
278 SysFreeString(attr_name
);
286 V_VT(value
) = VT_BSTR
;
287 V_BSTR(value
) = bstr_from_xmlChar(val
);
291 TRACE("returning %s\n", debugstr_w(V_BSTR(value
)));
292 return (val
) ? S_OK
: S_FALSE
;
295 static HRESULT WINAPI
xmlelem_removeAttribute(IXMLElement
*iface
, BSTR strPropertyName
)
297 xmlelem
*This
= impl_from_IXMLElement(iface
);
301 HRESULT hr
= S_FALSE
;
303 TRACE("(%p)->(%s)\n", This
, debugstr_w(strPropertyName
));
305 if (!strPropertyName
)
308 name
= xmlchar_from_wchar(strPropertyName
);
309 attr
= xmlHasProp(This
->node
, name
);
313 res
= xmlRemoveProp(attr
);
323 static HRESULT WINAPI
xmlelem_get_children(IXMLElement
*iface
, IXMLElementCollection
**p
)
325 xmlelem
*This
= impl_from_IXMLElement(iface
);
327 TRACE("(%p)->(%p)\n", This
, p
);
332 return XMLElementCollection_create(This
->node
, (LPVOID
*)p
);
335 static LONG
type_libxml_to_msxml(xmlElementType type
)
339 case XML_ELEMENT_NODE
:
340 return XMLELEMTYPE_ELEMENT
;
342 return XMLELEMTYPE_TEXT
;
343 case XML_COMMENT_NODE
:
344 return XMLELEMTYPE_COMMENT
;
345 case XML_DOCUMENT_NODE
:
346 return XMLELEMTYPE_DOCUMENT
;
348 return XMLELEMTYPE_DTD
;
350 return XMLELEMTYPE_PI
;
355 return XMLELEMTYPE_OTHER
;
358 static HRESULT WINAPI
xmlelem_get_type(IXMLElement
*iface
, LONG
*p
)
360 xmlelem
*This
= impl_from_IXMLElement(iface
);
362 TRACE("(%p)->(%p)\n", This
, p
);
367 *p
= type_libxml_to_msxml(This
->node
->type
);
368 TRACE("returning %d\n", *p
);
372 static HRESULT WINAPI
xmlelem_get_text(IXMLElement
*iface
, BSTR
*p
)
374 xmlelem
*This
= impl_from_IXMLElement(iface
);
377 TRACE("(%p)->(%p)\n", This
, p
);
382 content
= xmlNodeGetContent(This
->node
);
383 *p
= bstr_from_xmlChar(content
);
384 TRACE("returning %s\n", debugstr_w(*p
));
390 static HRESULT WINAPI
xmlelem_put_text(IXMLElement
*iface
, BSTR p
)
392 xmlelem
*This
= impl_from_IXMLElement(iface
);
395 TRACE("(%p)->(%s)\n", This
, debugstr_w(p
));
397 /* FIXME: test which types can be used */
398 if (This
->node
->type
== XML_ELEMENT_NODE
)
401 content
= xmlchar_from_wchar(p
);
402 xmlNodeSetContent(This
->node
, content
);
409 static HRESULT WINAPI
xmlelem_addChild(IXMLElement
*iface
, IXMLElement
*pChildElem
,
410 LONG lIndex
, LONG lreserved
)
412 xmlelem
*This
= impl_from_IXMLElement(iface
);
413 xmlelem
*childElem
= impl_from_IXMLElement(pChildElem
);
416 TRACE("(%p)->(%p %d %d)\n", This
, pChildElem
, lIndex
, lreserved
);
419 child
= xmlAddChild(This
->node
, childElem
->node
);
421 child
= xmlAddNextSibling(This
->node
, childElem
->node
->last
);
423 /* parent is responsible for child data */
424 if (child
) childElem
->own
= FALSE
;
426 return (child
) ? S_OK
: S_FALSE
;
429 static HRESULT WINAPI
xmlelem_removeChild(IXMLElement
*iface
, IXMLElement
*pChildElem
)
431 xmlelem
*This
= impl_from_IXMLElement(iface
);
432 xmlelem
*childElem
= impl_from_IXMLElement(pChildElem
);
434 TRACE("(%p)->(%p)\n", This
, childElem
);
439 /* only supported for This is childElem parent case */
440 if (This
->node
!= childElem
->node
->parent
)
443 xmlUnlinkNode(childElem
->node
);
444 /* standalone element now */
445 childElem
->own
= TRUE
;
450 static const struct IXMLElementVtbl xmlelem_vtbl
=
452 xmlelem_QueryInterface
,
455 xmlelem_GetTypeInfoCount
,
457 xmlelem_GetIDsOfNames
,
462 xmlelem_setAttribute
,
463 xmlelem_getAttribute
,
464 xmlelem_removeAttribute
,
465 xmlelem_get_children
,
473 HRESULT
XMLElement_create(xmlNodePtr node
, LPVOID
*ppObj
, BOOL own
)
477 TRACE("(%p)\n", ppObj
);
484 elem
= heap_alloc(sizeof (*elem
));
486 return E_OUTOFMEMORY
;
488 elem
->IXMLElement_iface
.lpVtbl
= &xmlelem_vtbl
;
493 *ppObj
= &elem
->IXMLElement_iface
;
495 TRACE("returning iface %p\n", *ppObj
);
499 /************************************************************************
500 * IXMLElementCollection
502 typedef struct _xmlelem_collection
504 IXMLElementCollection IXMLElementCollection_iface
;
505 IEnumVARIANT IEnumVARIANT_iface
;
510 /* IEnumVARIANT members */
512 } xmlelem_collection
;
514 static inline LONG
xmlelem_collection_updatelength(xmlelem_collection
*collection
)
516 xmlNodePtr ptr
= collection
->node
->children
;
518 collection
->length
= 0;
521 collection
->length
++;
524 return collection
->length
;
527 static inline xmlelem_collection
*impl_from_IXMLElementCollection(IXMLElementCollection
*iface
)
529 return CONTAINING_RECORD(iface
, xmlelem_collection
, IXMLElementCollection_iface
);
532 static inline xmlelem_collection
*impl_from_IEnumVARIANT(IEnumVARIANT
*iface
)
534 return CONTAINING_RECORD(iface
, xmlelem_collection
, IEnumVARIANT_iface
);
537 static HRESULT WINAPI
xmlelem_collection_QueryInterface(IXMLElementCollection
*iface
, REFIID riid
, void** ppvObject
)
539 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
541 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppvObject
);
543 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
544 IsEqualGUID(riid
, &IID_IXMLElementCollection
))
548 else if (IsEqualGUID(riid
, &IID_IEnumVARIANT
))
550 *ppvObject
= &This
->IEnumVARIANT_iface
;
554 FIXME("interface %s not implemented\n", debugstr_guid(riid
));
556 return E_NOINTERFACE
;
559 IXMLElementCollection_AddRef(iface
);
564 static ULONG WINAPI
xmlelem_collection_AddRef(IXMLElementCollection
*iface
)
566 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
567 TRACE("(%p)\n", This
);
568 return InterlockedIncrement(&This
->ref
);
571 static ULONG WINAPI
xmlelem_collection_Release(IXMLElementCollection
*iface
)
573 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
576 TRACE("(%p)\n", This
);
578 ref
= InterlockedDecrement(&This
->ref
);
587 static HRESULT WINAPI
xmlelem_collection_GetTypeInfoCount(IXMLElementCollection
*iface
, UINT
* pctinfo
)
593 static HRESULT WINAPI
xmlelem_collection_GetTypeInfo(IXMLElementCollection
*iface
, UINT iTInfo
,
594 LCID lcid
, ITypeInfo
** ppTInfo
)
600 static HRESULT WINAPI
xmlelem_collection_GetIDsOfNames(IXMLElementCollection
*iface
, REFIID riid
,
601 LPOLESTR
* rgszNames
, UINT cNames
,
602 LCID lcid
, DISPID
* rgDispId
)
608 static HRESULT WINAPI
xmlelem_collection_Invoke(IXMLElementCollection
*iface
, DISPID dispIdMember
,
609 REFIID riid
, LCID lcid
, WORD wFlags
,
610 DISPPARAMS
* pDispParams
, VARIANT
* pVarResult
,
611 EXCEPINFO
* pExcepInfo
, UINT
* puArgErr
)
617 static HRESULT WINAPI
xmlelem_collection_put_length(IXMLElementCollection
*iface
, LONG v
)
619 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
620 TRACE("(%p)->(%d)\n", This
, v
);
624 static HRESULT WINAPI
xmlelem_collection_get_length(IXMLElementCollection
*iface
, LONG
*p
)
626 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
628 TRACE("(%p)->(%p)\n", This
, p
);
633 *p
= xmlelem_collection_updatelength(This
);
637 static HRESULT WINAPI
xmlelem_collection_get__newEnum(IXMLElementCollection
*iface
, IUnknown
**ppUnk
)
639 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
641 TRACE("(%p)->(%p)\n", This
, ppUnk
);
646 IXMLElementCollection_AddRef(iface
);
647 *ppUnk
= (IUnknown
*)&This
->IEnumVARIANT_iface
;
651 static HRESULT WINAPI
xmlelem_collection_item(IXMLElementCollection
*iface
, VARIANT var1
,
652 VARIANT var2
, IDispatch
**ppDisp
)
654 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
655 xmlNodePtr ptr
= This
->node
->children
;
658 TRACE("(%p)->(%s %s %p)\n", This
, debugstr_variant(&var1
), debugstr_variant(&var2
), ppDisp
);
669 xmlelem_collection_updatelength(This
);
670 if (index
>= This
->length
)
673 for (i
= 0; i
< index
; i
++)
676 return XMLElement_create(ptr
, (LPVOID
*)ppDisp
, FALSE
);
679 static const struct IXMLElementCollectionVtbl xmlelem_collection_vtbl
=
681 xmlelem_collection_QueryInterface
,
682 xmlelem_collection_AddRef
,
683 xmlelem_collection_Release
,
684 xmlelem_collection_GetTypeInfoCount
,
685 xmlelem_collection_GetTypeInfo
,
686 xmlelem_collection_GetIDsOfNames
,
687 xmlelem_collection_Invoke
,
688 xmlelem_collection_put_length
,
689 xmlelem_collection_get_length
,
690 xmlelem_collection_get__newEnum
,
691 xmlelem_collection_item
694 /************************************************************************
695 * xmlelem_collection implementation of IEnumVARIANT.
697 static HRESULT WINAPI
xmlelem_collection_IEnumVARIANT_QueryInterface(
698 IEnumVARIANT
*iface
, REFIID riid
, LPVOID
*ppvObj
)
700 xmlelem_collection
*this = impl_from_IEnumVARIANT(iface
);
702 TRACE("(%p)->(%s %p)\n", this, debugstr_guid(riid
), ppvObj
);
704 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
705 IsEqualGUID(riid
, &IID_IEnumVARIANT
))
708 IEnumVARIANT_AddRef(iface
);
712 FIXME("interface %s not implemented\n", debugstr_guid(riid
));
714 return E_NOINTERFACE
;
717 static ULONG WINAPI
xmlelem_collection_IEnumVARIANT_AddRef(
720 xmlelem_collection
*this = impl_from_IEnumVARIANT(iface
);
721 return IXMLElementCollection_AddRef(&this->IXMLElementCollection_iface
);
724 static ULONG WINAPI
xmlelem_collection_IEnumVARIANT_Release(
727 xmlelem_collection
*this = impl_from_IEnumVARIANT(iface
);
728 return IXMLElementCollection_Release(&this->IXMLElementCollection_iface
);
731 static HRESULT WINAPI
xmlelem_collection_IEnumVARIANT_Next(
732 IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*rgVar
, ULONG
*fetched
)
734 xmlelem_collection
*This
= impl_from_IEnumVARIANT(iface
);
735 xmlNodePtr ptr
= This
->current
;
737 TRACE("(%p)->(%d %p %p)\n", This
, celt
, rgVar
, fetched
);
742 /* FIXME: handle celt */
747 This
->current
= This
->current
->next
;
750 V_VT(rgVar
) = VT_EMPTY
;
751 if (fetched
) *fetched
= 0;
755 V_VT(rgVar
) = VT_DISPATCH
;
756 return XMLElement_create(ptr
, (LPVOID
*)&V_DISPATCH(rgVar
), FALSE
);
759 static HRESULT WINAPI
xmlelem_collection_IEnumVARIANT_Skip(
760 IEnumVARIANT
*iface
, ULONG celt
)
762 xmlelem_collection
*This
= impl_from_IEnumVARIANT(iface
);
763 FIXME("(%p)->(%d): stub\n", This
, celt
);
767 static HRESULT WINAPI
xmlelem_collection_IEnumVARIANT_Reset(
770 xmlelem_collection
*This
= impl_from_IEnumVARIANT(iface
);
771 TRACE("(%p)\n", This
);
772 This
->current
= This
->node
->children
;
776 static HRESULT WINAPI
xmlelem_collection_IEnumVARIANT_Clone(
777 IEnumVARIANT
*iface
, IEnumVARIANT
**ppEnum
)
779 xmlelem_collection
*This
= impl_from_IEnumVARIANT(iface
);
780 FIXME("(%p)->(%p): stub\n", This
, ppEnum
);
784 static const struct IEnumVARIANTVtbl xmlelem_collection_IEnumVARIANTvtbl
=
786 xmlelem_collection_IEnumVARIANT_QueryInterface
,
787 xmlelem_collection_IEnumVARIANT_AddRef
,
788 xmlelem_collection_IEnumVARIANT_Release
,
789 xmlelem_collection_IEnumVARIANT_Next
,
790 xmlelem_collection_IEnumVARIANT_Skip
,
791 xmlelem_collection_IEnumVARIANT_Reset
,
792 xmlelem_collection_IEnumVARIANT_Clone
795 static HRESULT
XMLElementCollection_create(xmlNodePtr node
, LPVOID
*ppObj
)
797 xmlelem_collection
*collection
;
799 TRACE("(%p)\n", ppObj
);
806 collection
= heap_alloc(sizeof (*collection
));
808 return E_OUTOFMEMORY
;
810 collection
->IXMLElementCollection_iface
.lpVtbl
= &xmlelem_collection_vtbl
;
811 collection
->IEnumVARIANT_iface
.lpVtbl
= &xmlelem_collection_IEnumVARIANTvtbl
;
813 collection
->length
= 0;
814 collection
->node
= node
;
815 collection
->current
= node
->children
;
816 xmlelem_collection_updatelength(collection
);
818 *ppObj
= &collection
->IXMLElementCollection_iface
;
820 TRACE("returning iface %p\n", *ppObj
);