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
21 #define WIN32_NO_STATUS
30 # include <libxml/parser.h>
31 //# include <libxml/xmlerror.h>
36 //#include "winuser.h"
41 #include <wine/debug.h>
43 #include "msxml_private.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(msxml
);
49 static HRESULT
XMLElementCollection_create( IUnknown
*pUnkOuter
, xmlNodePtr node
, LPVOID
*ppObj
);
51 /**********************************************************************
54 typedef struct _xmlelem
56 IXMLElement IXMLElement_iface
;
62 static inline xmlelem
*impl_from_IXMLElement(IXMLElement
*iface
)
64 return CONTAINING_RECORD(iface
, xmlelem
, IXMLElement_iface
);
67 static HRESULT WINAPI
xmlelem_QueryInterface(IXMLElement
*iface
, REFIID riid
, void** ppvObject
)
69 xmlelem
*This
= impl_from_IXMLElement(iface
);
71 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppvObject
);
73 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
74 IsEqualGUID(riid
, &IID_IDispatch
) ||
75 IsEqualGUID(riid
, &IID_IXMLElement
))
81 FIXME("interface %s not implemented\n", debugstr_guid(riid
));
86 IXMLElement_AddRef(iface
);
91 static ULONG WINAPI
xmlelem_AddRef(IXMLElement
*iface
)
93 xmlelem
*This
= impl_from_IXMLElement(iface
);
95 return InterlockedIncrement(&This
->ref
);
98 static ULONG WINAPI
xmlelem_Release(IXMLElement
*iface
)
100 xmlelem
*This
= impl_from_IXMLElement(iface
);
105 ref
= InterlockedDecrement(&This
->ref
);
108 if (This
->own
) xmlFreeNode(This
->node
);
115 static HRESULT WINAPI
xmlelem_GetTypeInfoCount(IXMLElement
*iface
, UINT
* pctinfo
)
117 xmlelem
*This
= impl_from_IXMLElement(iface
);
119 TRACE("(%p)->(%p)\n", This
, pctinfo
);
126 static HRESULT WINAPI
xmlelem_GetTypeInfo(IXMLElement
*iface
, UINT iTInfo
,
127 LCID lcid
, ITypeInfo
** ppTInfo
)
129 xmlelem
*This
= impl_from_IXMLElement(iface
);
132 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
134 hr
= get_typeinfo(IXMLElement_tid
, ppTInfo
);
139 static HRESULT WINAPI
xmlelem_GetIDsOfNames(IXMLElement
*iface
, REFIID riid
,
140 LPOLESTR
* rgszNames
, UINT cNames
,
141 LCID lcid
, DISPID
* rgDispId
)
143 xmlelem
*This
= impl_from_IXMLElement(iface
);
147 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
,
150 if(!rgszNames
|| cNames
== 0 || !rgDispId
)
153 hr
= get_typeinfo(IXMLElement_tid
, &typeinfo
);
156 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
157 ITypeInfo_Release(typeinfo
);
163 static HRESULT WINAPI
xmlelem_Invoke(IXMLElement
*iface
, DISPID dispIdMember
,
164 REFIID riid
, LCID lcid
, WORD wFlags
,
165 DISPPARAMS
* pDispParams
, VARIANT
* pVarResult
,
166 EXCEPINFO
* pExcepInfo
, UINT
* puArgErr
)
168 xmlelem
*This
= impl_from_IXMLElement(iface
);
172 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
173 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
175 hr
= get_typeinfo(IXMLElement_tid
, &typeinfo
);
178 hr
= ITypeInfo_Invoke(typeinfo
, &This
->IXMLElement_iface
, dispIdMember
, wFlags
, pDispParams
,
179 pVarResult
, pExcepInfo
, puArgErr
);
180 ITypeInfo_Release(typeinfo
);
186 static HRESULT WINAPI
xmlelem_get_tagName(IXMLElement
*iface
, BSTR
*p
)
188 xmlelem
*This
= impl_from_IXMLElement(iface
);
190 TRACE("(%p)->(%p)\n", This
, p
);
195 *p
= bstr_from_xmlChar(This
->node
->name
);
196 CharUpperBuffW(*p
, SysStringLen(*p
));
198 TRACE("returning %s\n", debugstr_w(*p
));
203 static HRESULT WINAPI
xmlelem_put_tagName(IXMLElement
*iface
, BSTR p
)
205 xmlelem
*This
= impl_from_IXMLElement(iface
);
207 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(p
));
215 static HRESULT WINAPI
xmlelem_get_parent(IXMLElement
*iface
, IXMLElement
**parent
)
217 xmlelem
*This
= impl_from_IXMLElement(iface
);
219 TRACE("(%p)->(%p)\n", This
, parent
);
226 if (!This
->node
->parent
)
229 return XMLElement_create((IUnknown
*)iface
, This
->node
->parent
, (LPVOID
*)parent
, FALSE
);
232 static HRESULT WINAPI
xmlelem_setAttribute(IXMLElement
*iface
, BSTR strPropertyName
,
233 VARIANT PropertyValue
)
235 xmlelem
*This
= impl_from_IXMLElement(iface
);
236 xmlChar
*name
, *value
;
239 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(strPropertyName
), debugstr_variant(&PropertyValue
));
241 if (!strPropertyName
|| V_VT(&PropertyValue
) != VT_BSTR
)
244 name
= xmlchar_from_wchar(strPropertyName
);
245 value
= xmlchar_from_wchar(V_BSTR(&PropertyValue
));
246 attr
= xmlSetProp(This
->node
, name
, value
);
250 return (attr
) ? S_OK
: S_FALSE
;
253 static HRESULT WINAPI
xmlelem_getAttribute(IXMLElement
*iface
, BSTR name
,
256 static const WCHAR xmllangW
[] = { 'x','m','l',':','l','a','n','g',0 };
257 xmlelem
*This
= impl_from_IXMLElement(iface
);
260 TRACE("(%p)->(%s, %p)\n", This
, debugstr_w(name
), value
);
266 V_BSTR(value
) = NULL
;
271 /* case for xml:lang attribute */
272 if (!lstrcmpiW(name
, xmllangW
))
275 ns
= xmlSearchNs(This
->node
->doc
, This
->node
, (xmlChar
*)"xml");
276 val
= xmlGetNsProp(This
->node
, (xmlChar
*)"lang", ns
->href
);
283 xml_name
= xmlchar_from_wchar(name
);
284 attr
= This
->node
->properties
;
289 attr_name
= bstr_from_xmlChar(attr
->name
);
290 if (!lstrcmpiW(name
, attr_name
))
292 val
= xmlNodeListGetString(attr
->doc
, attr
->children
, 1);
293 SysFreeString(attr_name
);
298 SysFreeString(attr_name
);
306 V_VT(value
) = VT_BSTR
;
307 V_BSTR(value
) = bstr_from_xmlChar(val
);
311 TRACE("returning %s\n", debugstr_w(V_BSTR(value
)));
312 return (val
) ? S_OK
: S_FALSE
;
315 static HRESULT WINAPI
xmlelem_removeAttribute(IXMLElement
*iface
, BSTR strPropertyName
)
317 xmlelem
*This
= impl_from_IXMLElement(iface
);
321 HRESULT hr
= S_FALSE
;
323 TRACE("(%p)->(%s)\n", This
, debugstr_w(strPropertyName
));
325 if (!strPropertyName
)
328 name
= xmlchar_from_wchar(strPropertyName
);
329 attr
= xmlHasProp(This
->node
, name
);
333 res
= xmlRemoveProp(attr
);
343 static HRESULT WINAPI
xmlelem_get_children(IXMLElement
*iface
, IXMLElementCollection
**p
)
345 xmlelem
*This
= impl_from_IXMLElement(iface
);
347 TRACE("(%p)->(%p)\n", This
, p
);
352 return XMLElementCollection_create((IUnknown
*)iface
, This
->node
, (LPVOID
*)p
);
355 static LONG
type_libxml_to_msxml(xmlElementType type
)
359 case XML_ELEMENT_NODE
:
360 return XMLELEMTYPE_ELEMENT
;
362 return XMLELEMTYPE_TEXT
;
363 case XML_COMMENT_NODE
:
364 return XMLELEMTYPE_COMMENT
;
365 case XML_DOCUMENT_NODE
:
366 return XMLELEMTYPE_DOCUMENT
;
368 return XMLELEMTYPE_DTD
;
370 return XMLELEMTYPE_PI
;
375 return XMLELEMTYPE_OTHER
;
378 static HRESULT WINAPI
xmlelem_get_type(IXMLElement
*iface
, LONG
*p
)
380 xmlelem
*This
= impl_from_IXMLElement(iface
);
382 TRACE("(%p)->(%p)\n", This
, p
);
387 *p
= type_libxml_to_msxml(This
->node
->type
);
388 TRACE("returning %d\n", *p
);
392 static HRESULT WINAPI
xmlelem_get_text(IXMLElement
*iface
, BSTR
*p
)
394 xmlelem
*This
= impl_from_IXMLElement(iface
);
397 TRACE("(%p)->(%p)\n", This
, p
);
402 content
= xmlNodeGetContent(This
->node
);
403 *p
= bstr_from_xmlChar(content
);
404 TRACE("returning %s\n", debugstr_w(*p
));
410 static HRESULT WINAPI
xmlelem_put_text(IXMLElement
*iface
, BSTR p
)
412 xmlelem
*This
= impl_from_IXMLElement(iface
);
415 TRACE("(%p)->(%s)\n", This
, debugstr_w(p
));
417 /* FIXME: test which types can be used */
418 if (This
->node
->type
== XML_ELEMENT_NODE
)
421 content
= xmlchar_from_wchar(p
);
422 xmlNodeSetContent(This
->node
, content
);
429 static HRESULT WINAPI
xmlelem_addChild(IXMLElement
*iface
, IXMLElement
*pChildElem
,
430 LONG lIndex
, LONG lreserved
)
432 xmlelem
*This
= impl_from_IXMLElement(iface
);
433 xmlelem
*childElem
= impl_from_IXMLElement(pChildElem
);
436 TRACE("(%p)->(%p %d %d)\n", This
, pChildElem
, lIndex
, lreserved
);
439 child
= xmlAddChild(This
->node
, childElem
->node
);
441 child
= xmlAddNextSibling(This
->node
, childElem
->node
->last
);
443 /* parent is responsible for child data */
444 if (child
) childElem
->own
= FALSE
;
446 return (child
) ? S_OK
: S_FALSE
;
449 static HRESULT WINAPI
xmlelem_removeChild(IXMLElement
*iface
, IXMLElement
*pChildElem
)
451 xmlelem
*This
= impl_from_IXMLElement(iface
);
452 xmlelem
*childElem
= impl_from_IXMLElement(pChildElem
);
454 TRACE("(%p)->(%p)\n", This
, childElem
);
459 /* only supported for This is childElem parent case */
460 if (This
->node
!= childElem
->node
->parent
)
463 xmlUnlinkNode(childElem
->node
);
464 /* standalone element now */
465 childElem
->own
= TRUE
;
470 static const struct IXMLElementVtbl xmlelem_vtbl
=
472 xmlelem_QueryInterface
,
475 xmlelem_GetTypeInfoCount
,
477 xmlelem_GetIDsOfNames
,
482 xmlelem_setAttribute
,
483 xmlelem_getAttribute
,
484 xmlelem_removeAttribute
,
485 xmlelem_get_children
,
493 HRESULT
XMLElement_create(IUnknown
*pUnkOuter
, xmlNodePtr node
, LPVOID
*ppObj
, BOOL own
)
497 TRACE("(%p,%p)\n", pUnkOuter
, ppObj
);
504 elem
= heap_alloc(sizeof (*elem
));
506 return E_OUTOFMEMORY
;
508 elem
->IXMLElement_iface
.lpVtbl
= &xmlelem_vtbl
;
513 *ppObj
= &elem
->IXMLElement_iface
;
515 TRACE("returning iface %p\n", *ppObj
);
519 /************************************************************************
520 * IXMLElementCollection
522 typedef struct _xmlelem_collection
524 IXMLElementCollection IXMLElementCollection_iface
;
525 IEnumVARIANT IEnumVARIANT_iface
;
530 /* IEnumVARIANT members */
532 } xmlelem_collection
;
534 static inline LONG
xmlelem_collection_updatelength(xmlelem_collection
*collection
)
536 xmlNodePtr ptr
= collection
->node
->children
;
538 collection
->length
= 0;
541 collection
->length
++;
544 return collection
->length
;
547 static inline xmlelem_collection
*impl_from_IXMLElementCollection(IXMLElementCollection
*iface
)
549 return CONTAINING_RECORD(iface
, xmlelem_collection
, IXMLElementCollection_iface
);
552 static inline xmlelem_collection
*impl_from_IEnumVARIANT(IEnumVARIANT
*iface
)
554 return CONTAINING_RECORD(iface
, xmlelem_collection
, IEnumVARIANT_iface
);
557 static HRESULT WINAPI
xmlelem_collection_QueryInterface(IXMLElementCollection
*iface
, REFIID riid
, void** ppvObject
)
559 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
561 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppvObject
);
563 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
564 IsEqualGUID(riid
, &IID_IXMLElementCollection
))
568 else if (IsEqualGUID(riid
, &IID_IEnumVARIANT
))
570 *ppvObject
= &This
->IEnumVARIANT_iface
;
574 FIXME("interface %s not implemented\n", debugstr_guid(riid
));
575 return E_NOINTERFACE
;
578 IXMLElementCollection_AddRef(iface
);
583 static ULONG WINAPI
xmlelem_collection_AddRef(IXMLElementCollection
*iface
)
585 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
586 TRACE("(%p)\n", This
);
587 return InterlockedIncrement(&This
->ref
);
590 static ULONG WINAPI
xmlelem_collection_Release(IXMLElementCollection
*iface
)
592 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
595 TRACE("(%p)\n", This
);
597 ref
= InterlockedDecrement(&This
->ref
);
606 static HRESULT WINAPI
xmlelem_collection_GetTypeInfoCount(IXMLElementCollection
*iface
, UINT
* pctinfo
)
612 static HRESULT WINAPI
xmlelem_collection_GetTypeInfo(IXMLElementCollection
*iface
, UINT iTInfo
,
613 LCID lcid
, ITypeInfo
** ppTInfo
)
619 static HRESULT WINAPI
xmlelem_collection_GetIDsOfNames(IXMLElementCollection
*iface
, REFIID riid
,
620 LPOLESTR
* rgszNames
, UINT cNames
,
621 LCID lcid
, DISPID
* rgDispId
)
627 static HRESULT WINAPI
xmlelem_collection_Invoke(IXMLElementCollection
*iface
, DISPID dispIdMember
,
628 REFIID riid
, LCID lcid
, WORD wFlags
,
629 DISPPARAMS
* pDispParams
, VARIANT
* pVarResult
,
630 EXCEPINFO
* pExcepInfo
, UINT
* puArgErr
)
636 static HRESULT WINAPI
xmlelem_collection_put_length(IXMLElementCollection
*iface
, LONG v
)
638 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
639 TRACE("(%p)->(%d)\n", This
, v
);
643 static HRESULT WINAPI
xmlelem_collection_get_length(IXMLElementCollection
*iface
, LONG
*p
)
645 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
647 TRACE("(%p)->(%p)\n", This
, p
);
652 *p
= xmlelem_collection_updatelength(This
);
656 static HRESULT WINAPI
xmlelem_collection_get__newEnum(IXMLElementCollection
*iface
, IUnknown
**ppUnk
)
658 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
660 TRACE("(%p)->(%p)\n", This
, ppUnk
);
665 *ppUnk
= (IUnknown
*)This
;
666 IUnknown_AddRef(*ppUnk
);
670 static HRESULT WINAPI
xmlelem_collection_item(IXMLElementCollection
*iface
, VARIANT var1
,
671 VARIANT var2
, IDispatch
**ppDisp
)
673 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
674 xmlNodePtr ptr
= This
->node
->children
;
677 TRACE("(%p)->(%s %s %p)\n", This
, debugstr_variant(&var1
), debugstr_variant(&var2
), ppDisp
);
688 xmlelem_collection_updatelength(This
);
689 if (index
>= This
->length
)
692 for (i
= 0; i
< index
; i
++)
695 return XMLElement_create((IUnknown
*)iface
, ptr
, (LPVOID
*)ppDisp
, FALSE
);
698 static const struct IXMLElementCollectionVtbl xmlelem_collection_vtbl
=
700 xmlelem_collection_QueryInterface
,
701 xmlelem_collection_AddRef
,
702 xmlelem_collection_Release
,
703 xmlelem_collection_GetTypeInfoCount
,
704 xmlelem_collection_GetTypeInfo
,
705 xmlelem_collection_GetIDsOfNames
,
706 xmlelem_collection_Invoke
,
707 xmlelem_collection_put_length
,
708 xmlelem_collection_get_length
,
709 xmlelem_collection_get__newEnum
,
710 xmlelem_collection_item
713 /************************************************************************
714 * xmlelem_collection implementation of IEnumVARIANT.
716 static HRESULT WINAPI
xmlelem_collection_IEnumVARIANT_QueryInterface(
717 IEnumVARIANT
*iface
, REFIID riid
, LPVOID
*ppvObj
)
719 xmlelem_collection
*this = impl_from_IEnumVARIANT(iface
);
720 return IXMLDocument_QueryInterface((IXMLDocument
*)this, riid
, ppvObj
);
723 static ULONG WINAPI
xmlelem_collection_IEnumVARIANT_AddRef(
726 xmlelem_collection
*this = impl_from_IEnumVARIANT(iface
);
727 return IXMLDocument_AddRef((IXMLDocument
*)this);
730 static ULONG WINAPI
xmlelem_collection_IEnumVARIANT_Release(
733 xmlelem_collection
*this = impl_from_IEnumVARIANT(iface
);
734 return IXMLDocument_Release((IXMLDocument
*)this);
737 static HRESULT WINAPI
xmlelem_collection_IEnumVARIANT_Next(
738 IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*rgVar
, ULONG
*fetched
)
740 xmlelem_collection
*This
= impl_from_IEnumVARIANT(iface
);
741 xmlNodePtr ptr
= This
->current
;
743 TRACE("(%p)->(%d %p %p)\n", This
, celt
, rgVar
, fetched
);
748 /* FIXME: handle celt */
753 This
->current
= This
->current
->next
;
756 V_VT(rgVar
) = VT_EMPTY
;
757 if (fetched
) *fetched
= 0;
761 V_VT(rgVar
) = VT_DISPATCH
;
762 return XMLElement_create((IUnknown
*)iface
, ptr
, (LPVOID
*)&V_DISPATCH(rgVar
), FALSE
);
765 static HRESULT WINAPI
xmlelem_collection_IEnumVARIANT_Skip(
766 IEnumVARIANT
*iface
, ULONG celt
)
768 xmlelem_collection
*This
= impl_from_IEnumVARIANT(iface
);
769 FIXME("(%p)->(%d): stub\n", This
, celt
);
773 static HRESULT WINAPI
xmlelem_collection_IEnumVARIANT_Reset(
776 xmlelem_collection
*This
= impl_from_IEnumVARIANT(iface
);
777 TRACE("(%p)\n", This
);
778 This
->current
= This
->node
->children
;
782 static HRESULT WINAPI
xmlelem_collection_IEnumVARIANT_Clone(
783 IEnumVARIANT
*iface
, IEnumVARIANT
**ppEnum
)
785 xmlelem_collection
*This
= impl_from_IEnumVARIANT(iface
);
786 FIXME("(%p)->(%p): stub\n", This
, ppEnum
);
790 static const struct IEnumVARIANTVtbl xmlelem_collection_IEnumVARIANTvtbl
=
792 xmlelem_collection_IEnumVARIANT_QueryInterface
,
793 xmlelem_collection_IEnumVARIANT_AddRef
,
794 xmlelem_collection_IEnumVARIANT_Release
,
795 xmlelem_collection_IEnumVARIANT_Next
,
796 xmlelem_collection_IEnumVARIANT_Skip
,
797 xmlelem_collection_IEnumVARIANT_Reset
,
798 xmlelem_collection_IEnumVARIANT_Clone
801 static HRESULT
XMLElementCollection_create(IUnknown
*pUnkOuter
, xmlNodePtr node
, LPVOID
*ppObj
)
803 xmlelem_collection
*collection
;
805 TRACE("(%p,%p)\n", pUnkOuter
, ppObj
);
812 collection
= heap_alloc(sizeof (*collection
));
814 return E_OUTOFMEMORY
;
816 collection
->IXMLElementCollection_iface
.lpVtbl
= &xmlelem_collection_vtbl
;
817 collection
->IEnumVARIANT_iface
.lpVtbl
= &xmlelem_collection_IEnumVARIANTvtbl
;
819 collection
->length
= 0;
820 collection
->node
= node
;
821 collection
->current
= node
->children
;
822 xmlelem_collection_updatelength(collection
);
824 *ppObj
= &collection
->IXMLElementCollection_iface
;
826 TRACE("returning iface %p\n", *ppObj
);