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
27 # include <libxml/parser.h>
28 # include <libxml/xmlerror.h>
38 #include "wine/debug.h"
40 #include "msxml_private.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(msxml
);
46 static HRESULT
XMLElementCollection_create( IUnknown
*pUnkOuter
, xmlNodePtr node
, LPVOID
*ppObj
);
48 /**********************************************************************
51 typedef struct _xmlelem
53 IXMLElement IXMLElement_iface
;
59 static inline xmlelem
*impl_from_IXMLElement(IXMLElement
*iface
)
61 return CONTAINING_RECORD(iface
, xmlelem
, IXMLElement_iface
);
64 static HRESULT WINAPI
xmlelem_QueryInterface(IXMLElement
*iface
, REFIID riid
, void** ppvObject
)
66 xmlelem
*This
= impl_from_IXMLElement(iface
);
68 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppvObject
);
70 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
71 IsEqualGUID(riid
, &IID_IXMLElement
))
77 FIXME("interface %s not implemented\n", debugstr_guid(riid
));
82 IXMLElement_AddRef(iface
);
87 static ULONG WINAPI
xmlelem_AddRef(IXMLElement
*iface
)
89 xmlelem
*This
= impl_from_IXMLElement(iface
);
91 return InterlockedIncrement(&This
->ref
);
94 static ULONG WINAPI
xmlelem_Release(IXMLElement
*iface
)
96 xmlelem
*This
= impl_from_IXMLElement(iface
);
101 ref
= InterlockedDecrement(&This
->ref
);
104 if (This
->own
) xmlFreeNode(This
->node
);
111 static HRESULT WINAPI
xmlelem_GetTypeInfoCount(IXMLElement
*iface
, UINT
* pctinfo
)
113 xmlelem
*This
= impl_from_IXMLElement(iface
);
115 TRACE("(%p)->(%p)\n", This
, pctinfo
);
122 static HRESULT WINAPI
xmlelem_GetTypeInfo(IXMLElement
*iface
, UINT iTInfo
,
123 LCID lcid
, ITypeInfo
** ppTInfo
)
125 xmlelem
*This
= impl_from_IXMLElement(iface
);
128 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
130 hr
= get_typeinfo(IXMLElement_tid
, ppTInfo
);
135 static HRESULT WINAPI
xmlelem_GetIDsOfNames(IXMLElement
*iface
, REFIID riid
,
136 LPOLESTR
* rgszNames
, UINT cNames
,
137 LCID lcid
, DISPID
* rgDispId
)
139 xmlelem
*This
= impl_from_IXMLElement(iface
);
143 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
,
146 if(!rgszNames
|| cNames
== 0 || !rgDispId
)
149 hr
= get_typeinfo(IXMLElement_tid
, &typeinfo
);
152 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
153 ITypeInfo_Release(typeinfo
);
159 static HRESULT WINAPI
xmlelem_Invoke(IXMLElement
*iface
, DISPID dispIdMember
,
160 REFIID riid
, LCID lcid
, WORD wFlags
,
161 DISPPARAMS
* pDispParams
, VARIANT
* pVarResult
,
162 EXCEPINFO
* pExcepInfo
, UINT
* puArgErr
)
164 xmlelem
*This
= impl_from_IXMLElement(iface
);
168 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
169 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
171 hr
= get_typeinfo(IXMLElement_tid
, &typeinfo
);
174 hr
= ITypeInfo_Invoke(typeinfo
, &This
->IXMLElement_iface
, dispIdMember
, wFlags
, pDispParams
,
175 pVarResult
, pExcepInfo
, puArgErr
);
176 ITypeInfo_Release(typeinfo
);
182 static HRESULT WINAPI
xmlelem_get_tagName(IXMLElement
*iface
, BSTR
*p
)
184 xmlelem
*This
= impl_from_IXMLElement(iface
);
186 TRACE("(%p)->(%p)\n", This
, p
);
191 *p
= bstr_from_xmlChar(This
->node
->name
);
192 CharUpperBuffW(*p
, SysStringLen(*p
));
194 TRACE("returning %s\n", debugstr_w(*p
));
199 static HRESULT WINAPI
xmlelem_put_tagName(IXMLElement
*iface
, BSTR p
)
201 xmlelem
*This
= impl_from_IXMLElement(iface
);
203 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(p
));
211 static HRESULT WINAPI
xmlelem_get_parent(IXMLElement
*iface
, IXMLElement
**parent
)
213 xmlelem
*This
= impl_from_IXMLElement(iface
);
215 TRACE("(%p)->(%p)\n", This
, parent
);
222 if (!This
->node
->parent
)
225 return XMLElement_create((IUnknown
*)iface
, This
->node
->parent
, (LPVOID
*)parent
, FALSE
);
228 static HRESULT WINAPI
xmlelem_setAttribute(IXMLElement
*iface
, BSTR strPropertyName
,
229 VARIANT PropertyValue
)
231 xmlelem
*This
= impl_from_IXMLElement(iface
);
232 xmlChar
*name
, *value
;
235 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(strPropertyName
), debugstr_variant(&PropertyValue
));
237 if (!strPropertyName
|| V_VT(&PropertyValue
) != VT_BSTR
)
240 name
= xmlchar_from_wchar(strPropertyName
);
241 value
= xmlchar_from_wchar(V_BSTR(&PropertyValue
));
242 attr
= xmlSetProp(This
->node
, name
, value
);
246 return (attr
) ? S_OK
: S_FALSE
;
249 static HRESULT WINAPI
xmlelem_getAttribute(IXMLElement
*iface
, BSTR name
,
252 static const WCHAR xmllangW
[] = { 'x','m','l',':','l','a','n','g',0 };
253 xmlelem
*This
= impl_from_IXMLElement(iface
);
256 TRACE("(%p)->(%s, %p)\n", This
, debugstr_w(name
), value
);
262 V_BSTR(value
) = NULL
;
267 /* case for xml:lang attribute */
268 if (!lstrcmpiW(name
, xmllangW
))
271 ns
= xmlSearchNs(This
->node
->doc
, This
->node
, (xmlChar
*)"xml");
272 val
= xmlGetNsProp(This
->node
, (xmlChar
*)"lang", ns
->href
);
279 xml_name
= xmlchar_from_wchar(name
);
280 attr
= This
->node
->properties
;
285 attr_name
= bstr_from_xmlChar(attr
->name
);
286 if (!lstrcmpiW(name
, attr_name
))
288 val
= xmlNodeListGetString(attr
->doc
, attr
->children
, 1);
289 SysFreeString(attr_name
);
294 SysFreeString(attr_name
);
302 V_VT(value
) = VT_BSTR
;
303 V_BSTR(value
) = bstr_from_xmlChar(val
);
307 TRACE("returning %s\n", debugstr_w(V_BSTR(value
)));
308 return (val
) ? S_OK
: S_FALSE
;
311 static HRESULT WINAPI
xmlelem_removeAttribute(IXMLElement
*iface
, BSTR strPropertyName
)
313 xmlelem
*This
= impl_from_IXMLElement(iface
);
317 HRESULT hr
= S_FALSE
;
319 TRACE("(%p)->(%s)\n", This
, debugstr_w(strPropertyName
));
321 if (!strPropertyName
)
324 name
= xmlchar_from_wchar(strPropertyName
);
325 attr
= xmlHasProp(This
->node
, name
);
329 res
= xmlRemoveProp(attr
);
339 static HRESULT WINAPI
xmlelem_get_children(IXMLElement
*iface
, IXMLElementCollection
**p
)
341 xmlelem
*This
= impl_from_IXMLElement(iface
);
343 TRACE("(%p)->(%p)\n", This
, p
);
348 return XMLElementCollection_create((IUnknown
*)iface
, This
->node
, (LPVOID
*)p
);
351 static LONG
type_libxml_to_msxml(xmlElementType type
)
355 case XML_ELEMENT_NODE
:
356 return XMLELEMTYPE_ELEMENT
;
358 return XMLELEMTYPE_TEXT
;
359 case XML_COMMENT_NODE
:
360 return XMLELEMTYPE_COMMENT
;
361 case XML_DOCUMENT_NODE
:
362 return XMLELEMTYPE_DOCUMENT
;
364 return XMLELEMTYPE_DTD
;
366 return XMLELEMTYPE_PI
;
371 return XMLELEMTYPE_OTHER
;
374 static HRESULT WINAPI
xmlelem_get_type(IXMLElement
*iface
, LONG
*p
)
376 xmlelem
*This
= impl_from_IXMLElement(iface
);
378 TRACE("(%p)->(%p)\n", This
, p
);
383 *p
= type_libxml_to_msxml(This
->node
->type
);
384 TRACE("returning %d\n", *p
);
388 static HRESULT WINAPI
xmlelem_get_text(IXMLElement
*iface
, BSTR
*p
)
390 xmlelem
*This
= impl_from_IXMLElement(iface
);
393 TRACE("(%p)->(%p)\n", This
, p
);
398 content
= xmlNodeGetContent(This
->node
);
399 *p
= bstr_from_xmlChar(content
);
400 TRACE("returning %s\n", debugstr_w(*p
));
406 static HRESULT WINAPI
xmlelem_put_text(IXMLElement
*iface
, BSTR p
)
408 xmlelem
*This
= impl_from_IXMLElement(iface
);
411 TRACE("(%p)->(%s)\n", This
, debugstr_w(p
));
413 /* FIXME: test which types can be used */
414 if (This
->node
->type
== XML_ELEMENT_NODE
)
417 content
= xmlchar_from_wchar(p
);
418 xmlNodeSetContent(This
->node
, content
);
425 static HRESULT WINAPI
xmlelem_addChild(IXMLElement
*iface
, IXMLElement
*pChildElem
,
426 LONG lIndex
, LONG lreserved
)
428 xmlelem
*This
= impl_from_IXMLElement(iface
);
429 xmlelem
*childElem
= impl_from_IXMLElement(pChildElem
);
432 TRACE("(%p)->(%p %d %d)\n", This
, pChildElem
, lIndex
, lreserved
);
435 child
= xmlAddChild(This
->node
, childElem
->node
);
437 child
= xmlAddNextSibling(This
->node
, childElem
->node
->last
);
439 /* parent is responsible for child data */
440 if (child
) childElem
->own
= FALSE
;
442 return (child
) ? S_OK
: S_FALSE
;
445 static HRESULT WINAPI
xmlelem_removeChild(IXMLElement
*iface
, IXMLElement
*pChildElem
)
447 xmlelem
*This
= impl_from_IXMLElement(iface
);
448 xmlelem
*childElem
= impl_from_IXMLElement(pChildElem
);
450 TRACE("(%p)->(%p)\n", This
, childElem
);
455 /* only supported for This is childElem parent case */
456 if (This
->node
!= childElem
->node
->parent
)
459 xmlUnlinkNode(childElem
->node
);
460 /* standalone element now */
461 childElem
->own
= TRUE
;
466 static const struct IXMLElementVtbl xmlelem_vtbl
=
468 xmlelem_QueryInterface
,
471 xmlelem_GetTypeInfoCount
,
473 xmlelem_GetIDsOfNames
,
478 xmlelem_setAttribute
,
479 xmlelem_getAttribute
,
480 xmlelem_removeAttribute
,
481 xmlelem_get_children
,
489 HRESULT
XMLElement_create(IUnknown
*pUnkOuter
, xmlNodePtr node
, LPVOID
*ppObj
, BOOL own
)
493 TRACE("(%p,%p)\n", pUnkOuter
, ppObj
);
500 elem
= heap_alloc(sizeof (*elem
));
502 return E_OUTOFMEMORY
;
504 elem
->IXMLElement_iface
.lpVtbl
= &xmlelem_vtbl
;
509 *ppObj
= &elem
->IXMLElement_iface
;
511 TRACE("returning iface %p\n", *ppObj
);
515 /************************************************************************
516 * IXMLElementCollection
518 typedef struct _xmlelem_collection
520 IXMLElementCollection IXMLElementCollection_iface
;
521 IEnumVARIANT IEnumVARIANT_iface
;
526 /* IEnumVARIANT members */
528 } xmlelem_collection
;
530 static inline LONG
xmlelem_collection_updatelength(xmlelem_collection
*collection
)
532 xmlNodePtr ptr
= collection
->node
->children
;
534 collection
->length
= 0;
537 collection
->length
++;
540 return collection
->length
;
543 static inline xmlelem_collection
*impl_from_IXMLElementCollection(IXMLElementCollection
*iface
)
545 return CONTAINING_RECORD(iface
, xmlelem_collection
, IXMLElementCollection_iface
);
548 static inline xmlelem_collection
*impl_from_IEnumVARIANT(IEnumVARIANT
*iface
)
550 return CONTAINING_RECORD(iface
, xmlelem_collection
, IEnumVARIANT_iface
);
553 static HRESULT WINAPI
xmlelem_collection_QueryInterface(IXMLElementCollection
*iface
, REFIID riid
, void** ppvObject
)
555 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
557 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppvObject
);
559 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
560 IsEqualGUID(riid
, &IID_IXMLElementCollection
))
564 else if (IsEqualGUID(riid
, &IID_IEnumVARIANT
))
566 *ppvObject
= &This
->IEnumVARIANT_iface
;
570 FIXME("interface %s not implemented\n", debugstr_guid(riid
));
571 return E_NOINTERFACE
;
574 IXMLElementCollection_AddRef(iface
);
579 static ULONG WINAPI
xmlelem_collection_AddRef(IXMLElementCollection
*iface
)
581 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
582 TRACE("(%p)\n", This
);
583 return InterlockedIncrement(&This
->ref
);
586 static ULONG WINAPI
xmlelem_collection_Release(IXMLElementCollection
*iface
)
588 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
591 TRACE("(%p)\n", This
);
593 ref
= InterlockedDecrement(&This
->ref
);
602 static HRESULT WINAPI
xmlelem_collection_GetTypeInfoCount(IXMLElementCollection
*iface
, UINT
* pctinfo
)
608 static HRESULT WINAPI
xmlelem_collection_GetTypeInfo(IXMLElementCollection
*iface
, UINT iTInfo
,
609 LCID lcid
, ITypeInfo
** ppTInfo
)
615 static HRESULT WINAPI
xmlelem_collection_GetIDsOfNames(IXMLElementCollection
*iface
, REFIID riid
,
616 LPOLESTR
* rgszNames
, UINT cNames
,
617 LCID lcid
, DISPID
* rgDispId
)
623 static HRESULT WINAPI
xmlelem_collection_Invoke(IXMLElementCollection
*iface
, DISPID dispIdMember
,
624 REFIID riid
, LCID lcid
, WORD wFlags
,
625 DISPPARAMS
* pDispParams
, VARIANT
* pVarResult
,
626 EXCEPINFO
* pExcepInfo
, UINT
* puArgErr
)
632 static HRESULT WINAPI
xmlelem_collection_put_length(IXMLElementCollection
*iface
, LONG v
)
634 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
635 TRACE("(%p)->(%d)\n", This
, v
);
639 static HRESULT WINAPI
xmlelem_collection_get_length(IXMLElementCollection
*iface
, LONG
*p
)
641 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
643 TRACE("(%p)->(%p)\n", This
, p
);
648 *p
= xmlelem_collection_updatelength(This
);
652 static HRESULT WINAPI
xmlelem_collection_get__newEnum(IXMLElementCollection
*iface
, IUnknown
**ppUnk
)
654 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
656 TRACE("(%p)->(%p)\n", This
, ppUnk
);
661 *ppUnk
= (IUnknown
*)This
;
662 IUnknown_AddRef(*ppUnk
);
666 static HRESULT WINAPI
xmlelem_collection_item(IXMLElementCollection
*iface
, VARIANT var1
,
667 VARIANT var2
, IDispatch
**ppDisp
)
669 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
670 xmlNodePtr ptr
= This
->node
->children
;
673 TRACE("(%p)->(%s %s %p)\n", This
, debugstr_variant(&var1
), debugstr_variant(&var2
), ppDisp
);
684 xmlelem_collection_updatelength(This
);
685 if (index
>= This
->length
)
688 for (i
= 0; i
< index
; i
++)
691 return XMLElement_create((IUnknown
*)iface
, ptr
, (LPVOID
*)ppDisp
, FALSE
);
694 static const struct IXMLElementCollectionVtbl xmlelem_collection_vtbl
=
696 xmlelem_collection_QueryInterface
,
697 xmlelem_collection_AddRef
,
698 xmlelem_collection_Release
,
699 xmlelem_collection_GetTypeInfoCount
,
700 xmlelem_collection_GetTypeInfo
,
701 xmlelem_collection_GetIDsOfNames
,
702 xmlelem_collection_Invoke
,
703 xmlelem_collection_put_length
,
704 xmlelem_collection_get_length
,
705 xmlelem_collection_get__newEnum
,
706 xmlelem_collection_item
709 /************************************************************************
710 * xmlelem_collection implementation of IEnumVARIANT.
712 static HRESULT WINAPI
xmlelem_collection_IEnumVARIANT_QueryInterface(
713 IEnumVARIANT
*iface
, REFIID riid
, LPVOID
*ppvObj
)
715 xmlelem_collection
*this = impl_from_IEnumVARIANT(iface
);
716 return IXMLDocument_QueryInterface((IXMLDocument
*)this, riid
, ppvObj
);
719 static ULONG WINAPI
xmlelem_collection_IEnumVARIANT_AddRef(
722 xmlelem_collection
*this = impl_from_IEnumVARIANT(iface
);
723 return IXMLDocument_AddRef((IXMLDocument
*)this);
726 static ULONG WINAPI
xmlelem_collection_IEnumVARIANT_Release(
729 xmlelem_collection
*this = impl_from_IEnumVARIANT(iface
);
730 return IXMLDocument_Release((IXMLDocument
*)this);
733 static HRESULT WINAPI
xmlelem_collection_IEnumVARIANT_Next(
734 IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*rgVar
, ULONG
*fetched
)
736 xmlelem_collection
*This
= impl_from_IEnumVARIANT(iface
);
737 xmlNodePtr ptr
= This
->current
;
739 TRACE("(%p)->(%d %p %p)\n", This
, celt
, rgVar
, fetched
);
744 /* FIXME: handle celt */
749 This
->current
= This
->current
->next
;
752 V_VT(rgVar
) = VT_EMPTY
;
753 if (fetched
) *fetched
= 0;
757 V_VT(rgVar
) = VT_DISPATCH
;
758 return XMLElement_create((IUnknown
*)iface
, ptr
, (LPVOID
*)&V_DISPATCH(rgVar
), FALSE
);
761 static HRESULT WINAPI
xmlelem_collection_IEnumVARIANT_Skip(
762 IEnumVARIANT
*iface
, ULONG celt
)
764 xmlelem_collection
*This
= impl_from_IEnumVARIANT(iface
);
765 FIXME("(%p)->(%d): stub\n", This
, celt
);
769 static HRESULT WINAPI
xmlelem_collection_IEnumVARIANT_Reset(
772 xmlelem_collection
*This
= impl_from_IEnumVARIANT(iface
);
773 TRACE("(%p)\n", This
);
774 This
->current
= This
->node
->children
;
778 static HRESULT WINAPI
xmlelem_collection_IEnumVARIANT_Clone(
779 IEnumVARIANT
*iface
, IEnumVARIANT
**ppEnum
)
781 xmlelem_collection
*This
= impl_from_IEnumVARIANT(iface
);
782 FIXME("(%p)->(%p): stub\n", This
, ppEnum
);
786 static const struct IEnumVARIANTVtbl xmlelem_collection_IEnumVARIANTvtbl
=
788 xmlelem_collection_IEnumVARIANT_QueryInterface
,
789 xmlelem_collection_IEnumVARIANT_AddRef
,
790 xmlelem_collection_IEnumVARIANT_Release
,
791 xmlelem_collection_IEnumVARIANT_Next
,
792 xmlelem_collection_IEnumVARIANT_Skip
,
793 xmlelem_collection_IEnumVARIANT_Reset
,
794 xmlelem_collection_IEnumVARIANT_Clone
797 static HRESULT
XMLElementCollection_create(IUnknown
*pUnkOuter
, xmlNodePtr node
, LPVOID
*ppObj
)
799 xmlelem_collection
*collection
;
801 TRACE("(%p,%p)\n", pUnkOuter
, ppObj
);
808 collection
= heap_alloc(sizeof (*collection
));
810 return E_OUTOFMEMORY
;
812 collection
->IXMLElementCollection_iface
.lpVtbl
= &xmlelem_collection_vtbl
;
813 collection
->IEnumVARIANT_iface
.lpVtbl
= &xmlelem_collection_IEnumVARIANTvtbl
;
815 collection
->length
= 0;
816 collection
->node
= node
;
817 collection
->current
= node
->children
;
818 xmlelem_collection_updatelength(collection
);
820 *ppObj
= &collection
->IXMLElementCollection_iface
;
822 TRACE("returning iface %p\n", *ppObj
);