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
24 #include <libxml/parser.h>
25 #include <libxml/xmlerror.h>
34 #include "wine/debug.h"
36 #include "msxml_private.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(msxml
);
40 static HRESULT
XMLElementCollection_create( xmlNodePtr node
, LPVOID
*ppObj
);
42 /**********************************************************************
45 typedef struct _xmlelem
47 IXMLElement IXMLElement_iface
;
53 static inline xmlelem
*impl_from_IXMLElement(IXMLElement
*iface
)
55 return CONTAINING_RECORD(iface
, xmlelem
, IXMLElement_iface
);
58 static HRESULT WINAPI
xmlelem_QueryInterface(IXMLElement
*iface
, REFIID riid
, void** ppvObject
)
60 xmlelem
*This
= impl_from_IXMLElement(iface
);
62 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppvObject
);
64 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
65 IsEqualGUID(riid
, &IID_IDispatch
) ||
66 IsEqualGUID(riid
, &IID_IXMLElement
))
72 FIXME("interface %s not implemented\n", debugstr_guid(riid
));
77 IXMLElement_AddRef(iface
);
82 static ULONG WINAPI
xmlelem_AddRef(IXMLElement
*iface
)
84 xmlelem
*This
= impl_from_IXMLElement(iface
);
86 return InterlockedIncrement(&This
->ref
);
89 static ULONG WINAPI
xmlelem_Release(IXMLElement
*iface
)
91 xmlelem
*This
= impl_from_IXMLElement(iface
);
96 ref
= InterlockedDecrement(&This
->ref
);
99 if (This
->own
) xmlFreeNode(This
->node
);
106 static HRESULT WINAPI
xmlelem_GetTypeInfoCount(IXMLElement
*iface
, UINT
* pctinfo
)
108 xmlelem
*This
= impl_from_IXMLElement(iface
);
110 TRACE("(%p)->(%p)\n", This
, pctinfo
);
117 static HRESULT WINAPI
xmlelem_GetTypeInfo(IXMLElement
*iface
, UINT iTInfo
,
118 LCID lcid
, ITypeInfo
** ppTInfo
)
120 TRACE("%p, %u, %lx, %p.\n", iface
, iTInfo
, lcid
, ppTInfo
);
122 return get_typeinfo(IXMLElement_tid
, ppTInfo
);
125 static HRESULT WINAPI
xmlelem_GetIDsOfNames(IXMLElement
*iface
, REFIID riid
,
126 LPOLESTR
* rgszNames
, UINT cNames
,
127 LCID lcid
, DISPID
* rgDispId
)
132 TRACE("%p, %s, %p, %u, %lx, %p.\n", iface
, debugstr_guid(riid
), rgszNames
, cNames
,
135 if(!rgszNames
|| cNames
== 0 || !rgDispId
)
138 hr
= get_typeinfo(IXMLElement_tid
, &typeinfo
);
141 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
142 ITypeInfo_Release(typeinfo
);
148 static HRESULT WINAPI
xmlelem_Invoke(IXMLElement
*iface
, DISPID dispIdMember
,
149 REFIID riid
, LCID lcid
, WORD wFlags
,
150 DISPPARAMS
* pDispParams
, VARIANT
* pVarResult
,
151 EXCEPINFO
* pExcepInfo
, UINT
* puArgErr
)
156 TRACE("%p, %ld, %s, %lx, %d, %p, %p, %p, %p.\n", iface
, dispIdMember
, debugstr_guid(riid
),
157 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
159 hr
= get_typeinfo(IXMLElement_tid
, &typeinfo
);
162 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
163 ITypeInfo_Release(typeinfo
);
169 static HRESULT WINAPI
xmlelem_get_tagName(IXMLElement
*iface
, BSTR
*p
)
171 xmlelem
*This
= impl_from_IXMLElement(iface
);
173 TRACE("(%p)->(%p)\n", This
, p
);
178 if (*This
->node
->name
) {
179 *p
= bstr_from_xmlChar(This
->node
->name
);
180 CharUpperBuffW(*p
, SysStringLen(*p
));
185 TRACE("returning %s\n", debugstr_w(*p
));
190 static HRESULT WINAPI
xmlelem_put_tagName(IXMLElement
*iface
, BSTR p
)
192 xmlelem
*This
= impl_from_IXMLElement(iface
);
194 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(p
));
202 static HRESULT WINAPI
xmlelem_get_parent(IXMLElement
*iface
, IXMLElement
**parent
)
204 xmlelem
*This
= impl_from_IXMLElement(iface
);
206 TRACE("(%p)->(%p)\n", This
, parent
);
213 if (!This
->node
->parent
)
216 return XMLElement_create(This
->node
->parent
, (LPVOID
*)parent
, FALSE
);
219 static HRESULT WINAPI
xmlelem_setAttribute(IXMLElement
*iface
, BSTR strPropertyName
,
220 VARIANT PropertyValue
)
222 xmlelem
*This
= impl_from_IXMLElement(iface
);
223 xmlChar
*name
, *value
;
226 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(strPropertyName
), debugstr_variant(&PropertyValue
));
228 if (!strPropertyName
|| V_VT(&PropertyValue
) != VT_BSTR
)
231 name
= xmlchar_from_wchar(strPropertyName
);
232 value
= xmlchar_from_wchar(V_BSTR(&PropertyValue
));
233 attr
= xmlSetProp(This
->node
, name
, value
);
237 return (attr
) ? S_OK
: S_FALSE
;
240 static HRESULT WINAPI
xmlelem_getAttribute(IXMLElement
*iface
, BSTR name
,
243 static const WCHAR xmllangW
[] = { 'x','m','l',':','l','a','n','g',0 };
244 xmlelem
*This
= impl_from_IXMLElement(iface
);
247 TRACE("(%p)->(%s, %p)\n", This
, debugstr_w(name
), value
);
253 V_BSTR(value
) = NULL
;
258 /* case for xml:lang attribute */
259 if (!lstrcmpiW(name
, xmllangW
))
262 ns
= xmlSearchNs(This
->node
->doc
, This
->node
, (xmlChar
*)"xml");
263 val
= xmlGetNsProp(This
->node
, (xmlChar
*)"lang", ns
->href
);
270 xml_name
= xmlchar_from_wchar(name
);
271 attr
= This
->node
->properties
;
276 attr_name
= bstr_from_xmlChar(attr
->name
);
277 if (!lstrcmpiW(name
, attr_name
))
279 val
= xmlNodeListGetString(attr
->doc
, attr
->children
, 1);
280 SysFreeString(attr_name
);
285 SysFreeString(attr_name
);
293 V_VT(value
) = VT_BSTR
;
294 V_BSTR(value
) = bstr_from_xmlChar(val
);
298 TRACE("returning %s\n", debugstr_w(V_BSTR(value
)));
299 return (val
) ? S_OK
: S_FALSE
;
302 static HRESULT WINAPI
xmlelem_removeAttribute(IXMLElement
*iface
, BSTR strPropertyName
)
304 xmlelem
*This
= impl_from_IXMLElement(iface
);
308 HRESULT hr
= S_FALSE
;
310 TRACE("(%p)->(%s)\n", This
, debugstr_w(strPropertyName
));
312 if (!strPropertyName
)
315 name
= xmlchar_from_wchar(strPropertyName
);
316 attr
= xmlHasProp(This
->node
, name
);
320 res
= xmlRemoveProp(attr
);
330 static HRESULT WINAPI
xmlelem_get_children(IXMLElement
*iface
, IXMLElementCollection
**p
)
332 xmlelem
*This
= impl_from_IXMLElement(iface
);
334 TRACE("(%p)->(%p)\n", This
, p
);
339 return XMLElementCollection_create(This
->node
, (LPVOID
*)p
);
342 static LONG
type_libxml_to_msxml(xmlElementType type
)
346 case XML_ELEMENT_NODE
:
347 return XMLELEMTYPE_ELEMENT
;
349 return XMLELEMTYPE_TEXT
;
350 case XML_COMMENT_NODE
:
351 return XMLELEMTYPE_COMMENT
;
352 case XML_DOCUMENT_NODE
:
353 return XMLELEMTYPE_DOCUMENT
;
355 return XMLELEMTYPE_DTD
;
357 return XMLELEMTYPE_PI
;
362 return XMLELEMTYPE_OTHER
;
365 static HRESULT WINAPI
xmlelem_get_type(IXMLElement
*iface
, LONG
*p
)
367 xmlelem
*This
= impl_from_IXMLElement(iface
);
369 TRACE("(%p)->(%p)\n", This
, p
);
374 *p
= type_libxml_to_msxml(This
->node
->type
);
375 TRACE("returning %ld\n", *p
);
379 static HRESULT WINAPI
xmlelem_get_text(IXMLElement
*iface
, BSTR
*p
)
381 xmlelem
*This
= impl_from_IXMLElement(iface
);
384 TRACE("(%p)->(%p)\n", This
, p
);
389 content
= xmlNodeGetContent(This
->node
);
390 *p
= bstr_from_xmlChar(content
);
391 TRACE("returning %s\n", debugstr_w(*p
));
397 static HRESULT WINAPI
xmlelem_put_text(IXMLElement
*iface
, BSTR p
)
399 xmlelem
*This
= impl_from_IXMLElement(iface
);
402 TRACE("(%p)->(%s)\n", This
, debugstr_w(p
));
404 /* FIXME: test which types can be used */
405 if (This
->node
->type
== XML_ELEMENT_NODE
)
408 content
= xmlchar_from_wchar(p
);
409 xmlNodeSetContent(This
->node
, content
);
416 static HRESULT WINAPI
xmlelem_addChild(IXMLElement
*iface
, IXMLElement
*pChildElem
,
417 LONG lIndex
, LONG lreserved
)
419 xmlelem
*This
= impl_from_IXMLElement(iface
);
420 xmlelem
*childElem
= impl_from_IXMLElement(pChildElem
);
423 TRACE("%p, %p, %ld, %ld.\n", iface
, pChildElem
, lIndex
, lreserved
);
426 child
= xmlAddChild(This
->node
, childElem
->node
);
428 child
= xmlAddNextSibling(This
->node
, childElem
->node
->last
);
430 /* parent is responsible for child data */
431 if (child
) childElem
->own
= FALSE
;
433 return (child
) ? S_OK
: S_FALSE
;
436 static HRESULT WINAPI
xmlelem_removeChild(IXMLElement
*iface
, IXMLElement
*pChildElem
)
438 xmlelem
*This
= impl_from_IXMLElement(iface
);
439 xmlelem
*childElem
= impl_from_IXMLElement(pChildElem
);
441 TRACE("(%p)->(%p)\n", This
, childElem
);
446 /* only supported for This is childElem parent case */
447 if (This
->node
!= childElem
->node
->parent
)
450 xmlUnlinkNode(childElem
->node
);
451 /* standalone element now */
452 childElem
->own
= TRUE
;
457 static const struct IXMLElementVtbl xmlelem_vtbl
=
459 xmlelem_QueryInterface
,
462 xmlelem_GetTypeInfoCount
,
464 xmlelem_GetIDsOfNames
,
469 xmlelem_setAttribute
,
470 xmlelem_getAttribute
,
471 xmlelem_removeAttribute
,
472 xmlelem_get_children
,
480 HRESULT
XMLElement_create(xmlNodePtr node
, LPVOID
*ppObj
, BOOL own
)
484 TRACE("(%p)\n", ppObj
);
491 elem
= malloc(sizeof(*elem
));
493 return E_OUTOFMEMORY
;
495 elem
->IXMLElement_iface
.lpVtbl
= &xmlelem_vtbl
;
500 *ppObj
= &elem
->IXMLElement_iface
;
502 TRACE("returning iface %p\n", *ppObj
);
506 /************************************************************************
507 * IXMLElementCollection
509 typedef struct _xmlelem_collection
511 IXMLElementCollection IXMLElementCollection_iface
;
512 IEnumVARIANT IEnumVARIANT_iface
;
517 /* IEnumVARIANT members */
519 } xmlelem_collection
;
521 static inline LONG
xmlelem_collection_updatelength(xmlelem_collection
*collection
)
523 xmlNodePtr ptr
= collection
->node
->children
;
525 collection
->length
= 0;
528 collection
->length
++;
531 return collection
->length
;
534 static inline xmlelem_collection
*impl_from_IXMLElementCollection(IXMLElementCollection
*iface
)
536 return CONTAINING_RECORD(iface
, xmlelem_collection
, IXMLElementCollection_iface
);
539 static inline xmlelem_collection
*impl_from_IEnumVARIANT(IEnumVARIANT
*iface
)
541 return CONTAINING_RECORD(iface
, xmlelem_collection
, IEnumVARIANT_iface
);
544 static HRESULT WINAPI
xmlelem_collection_QueryInterface(IXMLElementCollection
*iface
, REFIID riid
, void** ppvObject
)
546 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
548 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppvObject
);
550 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
551 IsEqualGUID(riid
, &IID_IXMLElementCollection
))
555 else if (IsEqualGUID(riid
, &IID_IEnumVARIANT
))
557 *ppvObject
= &This
->IEnumVARIANT_iface
;
561 FIXME("interface %s not implemented\n", debugstr_guid(riid
));
563 return E_NOINTERFACE
;
566 IXMLElementCollection_AddRef(iface
);
571 static ULONG WINAPI
xmlelem_collection_AddRef(IXMLElementCollection
*iface
)
573 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
574 TRACE("(%p)\n", This
);
575 return InterlockedIncrement(&This
->ref
);
578 static ULONG WINAPI
xmlelem_collection_Release(IXMLElementCollection
*iface
)
580 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
583 TRACE("(%p)\n", This
);
585 ref
= InterlockedDecrement(&This
->ref
);
594 static HRESULT WINAPI
xmlelem_collection_GetTypeInfoCount(IXMLElementCollection
*iface
, UINT
* pctinfo
)
600 static HRESULT WINAPI
xmlelem_collection_GetTypeInfo(IXMLElementCollection
*iface
, UINT iTInfo
,
601 LCID lcid
, ITypeInfo
** ppTInfo
)
607 static HRESULT WINAPI
xmlelem_collection_GetIDsOfNames(IXMLElementCollection
*iface
, REFIID riid
,
608 LPOLESTR
* rgszNames
, UINT cNames
,
609 LCID lcid
, DISPID
* rgDispId
)
615 static HRESULT WINAPI
xmlelem_collection_Invoke(IXMLElementCollection
*iface
, DISPID dispIdMember
,
616 REFIID riid
, LCID lcid
, WORD wFlags
,
617 DISPPARAMS
* pDispParams
, VARIANT
* pVarResult
,
618 EXCEPINFO
* pExcepInfo
, UINT
* puArgErr
)
624 static HRESULT WINAPI
xmlelem_collection_put_length(IXMLElementCollection
*iface
, LONG v
)
626 TRACE("%p, %ld.\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", This
, 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", This
, ppUnk
);
653 IXMLElementCollection_AddRef(iface
);
654 *ppUnk
= (IUnknown
*)&This
->IEnumVARIANT_iface
;
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)->(%s %s %p)\n", This
, debugstr_variant(&var1
), debugstr_variant(&var2
), ppDisp
);
676 xmlelem_collection_updatelength(This
);
677 if (index
>= This
->length
)
680 for (i
= 0; i
< index
; i
++)
683 return XMLElement_create(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
);
709 TRACE("(%p)->(%s %p)\n", this, debugstr_guid(riid
), ppvObj
);
711 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
712 IsEqualGUID(riid
, &IID_IEnumVARIANT
))
715 IEnumVARIANT_AddRef(iface
);
719 FIXME("interface %s not implemented\n", debugstr_guid(riid
));
721 return E_NOINTERFACE
;
724 static ULONG WINAPI
xmlelem_collection_IEnumVARIANT_AddRef(
727 xmlelem_collection
*this = impl_from_IEnumVARIANT(iface
);
728 return IXMLElementCollection_AddRef(&this->IXMLElementCollection_iface
);
731 static ULONG WINAPI
xmlelem_collection_IEnumVARIANT_Release(
734 xmlelem_collection
*this = impl_from_IEnumVARIANT(iface
);
735 return IXMLElementCollection_Release(&this->IXMLElementCollection_iface
);
738 static HRESULT WINAPI
xmlelem_collection_IEnumVARIANT_Next(
739 IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*rgVar
, ULONG
*fetched
)
741 xmlelem_collection
*This
= impl_from_IEnumVARIANT(iface
);
744 TRACE("%p, %lu, %p, %p.\n", iface
, celt
, rgVar
, fetched
);
749 if (fetched
) *fetched
= 0;
753 V_VT(rgVar
) = VT_EMPTY
;
757 while (celt
> 0 && This
->current
)
759 V_VT(rgVar
) = VT_DISPATCH
;
760 hr
= XMLElement_create(This
->current
, (void **)&V_DISPATCH(rgVar
), FALSE
);
761 if (FAILED(hr
)) return hr
;
762 This
->current
= This
->current
->next
;
763 if (fetched
) ++*fetched
;
767 if (!celt
) return S_OK
;
768 V_VT(rgVar
) = VT_EMPTY
;
772 static HRESULT WINAPI
xmlelem_collection_IEnumVARIANT_Skip(
773 IEnumVARIANT
*iface
, ULONG celt
)
775 FIXME("%p, %lu: stub\n", iface
, celt
);
779 static HRESULT WINAPI
xmlelem_collection_IEnumVARIANT_Reset(
782 xmlelem_collection
*This
= impl_from_IEnumVARIANT(iface
);
783 TRACE("(%p)\n", This
);
784 This
->current
= This
->node
->children
;
788 static HRESULT WINAPI
xmlelem_collection_IEnumVARIANT_Clone(
789 IEnumVARIANT
*iface
, IEnumVARIANT
**ppEnum
)
791 xmlelem_collection
*This
= impl_from_IEnumVARIANT(iface
);
792 FIXME("(%p)->(%p): stub\n", This
, ppEnum
);
796 static const struct IEnumVARIANTVtbl xmlelem_collection_IEnumVARIANTvtbl
=
798 xmlelem_collection_IEnumVARIANT_QueryInterface
,
799 xmlelem_collection_IEnumVARIANT_AddRef
,
800 xmlelem_collection_IEnumVARIANT_Release
,
801 xmlelem_collection_IEnumVARIANT_Next
,
802 xmlelem_collection_IEnumVARIANT_Skip
,
803 xmlelem_collection_IEnumVARIANT_Reset
,
804 xmlelem_collection_IEnumVARIANT_Clone
807 static HRESULT
XMLElementCollection_create(xmlNodePtr node
, LPVOID
*ppObj
)
809 xmlelem_collection
*collection
;
811 TRACE("(%p)\n", ppObj
);
818 collection
= malloc(sizeof(*collection
));
820 return E_OUTOFMEMORY
;
822 collection
->IXMLElementCollection_iface
.lpVtbl
= &xmlelem_collection_vtbl
;
823 collection
->IEnumVARIANT_iface
.lpVtbl
= &xmlelem_collection_IEnumVARIANTvtbl
;
825 collection
->length
= 0;
826 collection
->node
= node
;
827 collection
->current
= node
->children
;
828 xmlelem_collection_updatelength(collection
);
830 *ppObj
= &collection
->IXMLElementCollection_iface
;
832 TRACE("returning iface %p\n", *ppObj
);