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
;
53 static inline xmlelem
*impl_from_IXMLElement(IXMLElement
*iface
)
55 return (xmlelem
*)((char*)iface
- FIELD_OFFSET(xmlelem
, lpVtbl
));
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_IXMLElement
))
71 FIXME("interface %s not implemented\n", debugstr_guid(riid
));
75 IXMLElement_AddRef(iface
);
80 static ULONG WINAPI
xmlelem_AddRef(IXMLElement
*iface
)
82 xmlelem
*This
= impl_from_IXMLElement(iface
);
84 return InterlockedIncrement(&This
->ref
);
87 static ULONG WINAPI
xmlelem_Release(IXMLElement
*iface
)
89 xmlelem
*This
= impl_from_IXMLElement(iface
);
94 ref
= InterlockedDecrement(&This
->ref
);
97 HeapFree(GetProcessHeap(), 0, This
);
103 static HRESULT WINAPI
xmlelem_GetTypeInfoCount(IXMLElement
*iface
, UINT
* pctinfo
)
105 xmlelem
*This
= impl_from_IXMLElement(iface
);
107 TRACE("(%p)->(%p)\n", This
, pctinfo
);
114 static HRESULT WINAPI
xmlelem_GetTypeInfo(IXMLElement
*iface
, UINT iTInfo
,
115 LCID lcid
, ITypeInfo
** ppTInfo
)
117 xmlelem
*This
= impl_from_IXMLElement(iface
);
120 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
122 hr
= get_typeinfo(IXMLElement_tid
, ppTInfo
);
127 static HRESULT WINAPI
xmlelem_GetIDsOfNames(IXMLElement
*iface
, REFIID riid
,
128 LPOLESTR
* rgszNames
, UINT cNames
,
129 LCID lcid
, DISPID
* rgDispId
)
131 xmlelem
*This
= impl_from_IXMLElement(iface
);
135 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
,
138 if(!rgszNames
|| cNames
== 0 || !rgDispId
)
141 hr
= get_typeinfo(IXMLElement_tid
, &typeinfo
);
144 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
145 ITypeInfo_Release(typeinfo
);
151 static HRESULT WINAPI
xmlelem_Invoke(IXMLElement
*iface
, DISPID dispIdMember
,
152 REFIID riid
, LCID lcid
, WORD wFlags
,
153 DISPPARAMS
* pDispParams
, VARIANT
* pVarResult
,
154 EXCEPINFO
* pExcepInfo
, UINT
* puArgErr
)
156 xmlelem
*This
= impl_from_IXMLElement(iface
);
160 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
161 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
163 hr
= get_typeinfo(IXMLElement_tid
, &typeinfo
);
166 hr
= ITypeInfo_Invoke(typeinfo
, &(This
->lpVtbl
), dispIdMember
, wFlags
, pDispParams
,
167 pVarResult
, pExcepInfo
, puArgErr
);
168 ITypeInfo_Release(typeinfo
);
174 static inline BSTR
str_dup_upper(BSTR str
)
176 INT len
= (lstrlenW(str
) + 1) * sizeof(WCHAR
);
177 BSTR p
= SysAllocStringLen(NULL
, len
);
186 static HRESULT WINAPI
xmlelem_get_tagName(IXMLElement
*iface
, BSTR
*p
)
188 xmlelem
*This
= impl_from_IXMLElement(iface
);
191 TRACE("(%p, %p)\n", iface
, p
);
196 temp
= bstr_from_xmlChar(This
->node
->name
);
197 *p
= str_dup_upper(temp
);
200 TRACE("returning %s\n", debugstr_w(*p
));
205 static HRESULT WINAPI
xmlelem_put_tagName(IXMLElement
*iface
, BSTR p
)
207 FIXME("(%p, %p): stub\n", iface
, p
);
215 static HRESULT WINAPI
xmlelem_get_parent(IXMLElement
*iface
, IXMLElement
**parent
)
217 xmlelem
*This
= impl_from_IXMLElement(iface
);
219 TRACE("(%p, %p)\n", iface
, parent
);
226 if (!This
->node
->parent
)
229 return XMLElement_create((IUnknown
*)iface
, This
->node
->parent
, (LPVOID
*)parent
);
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)\n", iface
, debugstr_w(strPropertyName
));
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
);
248 HeapFree(GetProcessHeap(), 0, name
);
249 HeapFree(GetProcessHeap(), 0, value
);
250 return (attr
) ? S_OK
: S_FALSE
;
253 static HRESULT WINAPI
xmlelem_getAttribute(IXMLElement
*iface
, BSTR strPropertyName
,
254 VARIANT
*PropertyValue
)
256 xmlelem
*This
= impl_from_IXMLElement(iface
);
257 xmlChar
*val
= NULL
, *name
;
260 TRACE("(%p, %s, %p)\n", iface
, debugstr_w(strPropertyName
), PropertyValue
);
265 VariantInit(PropertyValue
);
266 V_BSTR(PropertyValue
) = NULL
;
268 if (!strPropertyName
)
271 name
= xmlChar_from_wchar(strPropertyName
);
272 ptr
= This
->node
->properties
;
275 if (!lstrcmpiA((LPSTR
)name
, (LPCSTR
)ptr
->name
))
277 val
= xmlNodeListGetString(ptr
->doc
, ptr
->children
, 1);
286 V_VT(PropertyValue
) = VT_BSTR
;
287 V_BSTR(PropertyValue
) = bstr_from_xmlChar(val
);
290 HeapFree(GetProcessHeap(), 0, name
);
292 TRACE("returning %s\n", debugstr_w(V_BSTR(PropertyValue
)));
293 return (val
) ? S_OK
: S_FALSE
;
296 static HRESULT WINAPI
xmlelem_removeAttribute(IXMLElement
*iface
, BSTR strPropertyName
)
298 xmlelem
*This
= impl_from_IXMLElement(iface
);
302 HRESULT hr
= S_FALSE
;
304 TRACE("(%p, %s)\n", iface
, debugstr_w(strPropertyName
));
306 if (!strPropertyName
)
309 name
= xmlChar_from_wchar(strPropertyName
);
310 attr
= xmlHasProp(This
->node
, name
);
314 res
= xmlRemoveProp(attr
);
320 HeapFree(GetProcessHeap(), 0, name
);
324 static HRESULT WINAPI
xmlelem_get_children(IXMLElement
*iface
, IXMLElementCollection
**p
)
326 xmlelem
*This
= impl_from_IXMLElement(iface
);
328 TRACE("(%p, %p)\n", iface
, p
);
333 return XMLElementCollection_create((IUnknown
*)iface
, This
->node
->children
, (LPVOID
*)p
);
336 static LONG
type_libxml_to_msxml(xmlElementType type
)
340 case XML_ELEMENT_NODE
:
341 return XMLELEMTYPE_ELEMENT
;
343 return XMLELEMTYPE_TEXT
;
344 case XML_COMMENT_NODE
:
345 return XMLELEMTYPE_COMMENT
;
346 case XML_DOCUMENT_NODE
:
347 return XMLELEMTYPE_DOCUMENT
;
349 return XMLELEMTYPE_DTD
;
351 return XMLELEMTYPE_PI
;
356 return XMLELEMTYPE_OTHER
;
359 static HRESULT WINAPI
xmlelem_get_type(IXMLElement
*iface
, LONG
*p
)
361 xmlelem
*This
= impl_from_IXMLElement(iface
);
363 TRACE("(%p, %p)\n", This
, p
);
368 *p
= type_libxml_to_msxml(This
->node
->type
);
369 TRACE("returning %d\n", *p
);
373 static HRESULT WINAPI
xmlelem_get_text(IXMLElement
*iface
, BSTR
*p
)
375 xmlelem
*This
= impl_from_IXMLElement(iface
);
378 TRACE("(%p, %p)\n", iface
, p
);
383 content
= xmlNodeGetContent(This
->node
);
384 *p
= bstr_from_xmlChar(content
);
385 TRACE("returning %s\n", debugstr_w(*p
));
391 static HRESULT WINAPI
xmlelem_put_text(IXMLElement
*iface
, BSTR p
)
393 xmlelem
*This
= impl_from_IXMLElement(iface
);
396 TRACE("(%p, %s)\n", iface
, debugstr_w(p
));
398 /* FIXME: test which types can be used */
399 if (This
->node
->type
== XML_ELEMENT_NODE
)
402 content
= xmlChar_from_wchar(p
);
403 xmlNodeSetContent(This
->node
, content
);
405 HeapFree( GetProcessHeap(), 0, content
);
410 static HRESULT WINAPI
xmlelem_addChild(IXMLElement
*iface
, IXMLElement
*pChildElem
,
411 LONG lIndex
, LONG lreserved
)
413 xmlelem
*This
= impl_from_IXMLElement(iface
);
414 xmlelem
*childElem
= impl_from_IXMLElement(pChildElem
);
417 TRACE("(%p, %p, %d, %d)\n", iface
, pChildElem
, lIndex
, lreserved
);
420 child
= xmlAddChild(This
->node
, childElem
->node
);
422 child
= xmlAddNextSibling(This
->node
, childElem
->node
->last
);
424 return (child
) ? S_OK
: S_FALSE
;
427 static HRESULT WINAPI
xmlelem_removeChild(IXMLElement
*iface
, IXMLElement
*pChildElem
)
429 FIXME("(%p, %p): stub\n", iface
, pChildElem
);
433 static const struct IXMLElementVtbl xmlelem_vtbl
=
435 xmlelem_QueryInterface
,
438 xmlelem_GetTypeInfoCount
,
440 xmlelem_GetIDsOfNames
,
445 xmlelem_setAttribute
,
446 xmlelem_getAttribute
,
447 xmlelem_removeAttribute
,
448 xmlelem_get_children
,
456 HRESULT
XMLElement_create(IUnknown
*pUnkOuter
, xmlNodePtr node
, LPVOID
*ppObj
)
460 TRACE("(%p,%p)\n", pUnkOuter
, ppObj
);
467 elem
= HeapAlloc(GetProcessHeap(), 0, sizeof (*elem
));
469 return E_OUTOFMEMORY
;
471 elem
->lpVtbl
= &xmlelem_vtbl
;
475 *ppObj
= &elem
->lpVtbl
;
477 TRACE("returning iface %p\n", *ppObj
);
481 /************************************************************************
482 * IXMLElementCollection
484 typedef struct _xmlelem_collection
486 const IXMLElementCollectionVtbl
*lpVtbl
;
487 const IEnumVARIANTVtbl
*lpvtblIEnumVARIANT
;
492 /* IEnumVARIANT members */
494 } xmlelem_collection
;
496 static inline xmlelem_collection
*impl_from_IXMLElementCollection(IXMLElementCollection
*iface
)
498 return (xmlelem_collection
*)((char*)iface
- FIELD_OFFSET(xmlelem_collection
, lpVtbl
));
501 static inline xmlelem_collection
*impl_from_IEnumVARIANT(IEnumVARIANT
*iface
)
503 return (xmlelem_collection
*)((char*)iface
- FIELD_OFFSET(xmlelem_collection
, lpvtblIEnumVARIANT
));
506 static HRESULT WINAPI
xmlelem_collection_QueryInterface(IXMLElementCollection
*iface
, REFIID riid
, void** ppvObject
)
508 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
510 TRACE("%p %s %p\n", This
, debugstr_guid(riid
), ppvObject
);
512 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
513 IsEqualGUID(riid
, &IID_IXMLElementCollection
))
517 else if (IsEqualGUID(riid
, &IID_IEnumVARIANT
))
519 *ppvObject
= &(This
->lpvtblIEnumVARIANT
);
523 FIXME("interface %s not implemented\n", debugstr_guid(riid
));
524 return E_NOINTERFACE
;
527 IXMLElementCollection_AddRef(iface
);
532 static ULONG WINAPI
xmlelem_collection_AddRef(IXMLElementCollection
*iface
)
534 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
536 return InterlockedIncrement(&This
->ref
);
539 static ULONG WINAPI
xmlelem_collection_Release(IXMLElementCollection
*iface
)
541 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
546 ref
= InterlockedDecrement(&This
->ref
);
549 HeapFree(GetProcessHeap(), 0, This
);
555 static HRESULT WINAPI
xmlelem_collection_GetTypeInfoCount(IXMLElementCollection
*iface
, UINT
* pctinfo
)
561 static HRESULT WINAPI
xmlelem_collection_GetTypeInfo(IXMLElementCollection
*iface
, UINT iTInfo
,
562 LCID lcid
, ITypeInfo
** ppTInfo
)
568 static HRESULT WINAPI
xmlelem_collection_GetIDsOfNames(IXMLElementCollection
*iface
, REFIID riid
,
569 LPOLESTR
* rgszNames
, UINT cNames
,
570 LCID lcid
, DISPID
* rgDispId
)
576 static HRESULT WINAPI
xmlelem_collection_Invoke(IXMLElementCollection
*iface
, DISPID dispIdMember
,
577 REFIID riid
, LCID lcid
, WORD wFlags
,
578 DISPPARAMS
* pDispParams
, VARIANT
* pVarResult
,
579 EXCEPINFO
* pExcepInfo
, UINT
* puArgErr
)
585 static HRESULT WINAPI
xmlelem_collection_put_length(IXMLElementCollection
*iface
, LONG v
)
587 TRACE("(%p, %d)\n", iface
, v
);
591 static HRESULT WINAPI
xmlelem_collection_get_length(IXMLElementCollection
*iface
, LONG
*p
)
593 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
595 TRACE("(%p, %p)\n", iface
, p
);
604 static HRESULT WINAPI
xmlelem_collection_get__newEnum(IXMLElementCollection
*iface
, IUnknown
**ppUnk
)
606 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
608 TRACE("(%p, %p)\n", iface
, ppUnk
);
613 *ppUnk
= (IUnknown
*)This
;
614 IUnknown_AddRef(*ppUnk
);
618 static HRESULT WINAPI
xmlelem_collection_item(IXMLElementCollection
*iface
, VARIANT var1
,
619 VARIANT var2
, IDispatch
**ppDisp
)
621 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
622 xmlNodePtr ptr
= This
->node
;
625 TRACE("(%p, %p)\n", iface
, ppDisp
);
635 if (index
>= This
->length
)
638 for (i
= 0; i
< index
; i
++)
641 return XMLElement_create((IUnknown
*)iface
, ptr
, (LPVOID
*)ppDisp
);
644 static const struct IXMLElementCollectionVtbl xmlelem_collection_vtbl
=
646 xmlelem_collection_QueryInterface
,
647 xmlelem_collection_AddRef
,
648 xmlelem_collection_Release
,
649 xmlelem_collection_GetTypeInfoCount
,
650 xmlelem_collection_GetTypeInfo
,
651 xmlelem_collection_GetIDsOfNames
,
652 xmlelem_collection_Invoke
,
653 xmlelem_collection_put_length
,
654 xmlelem_collection_get_length
,
655 xmlelem_collection_get__newEnum
,
656 xmlelem_collection_item
659 /************************************************************************
660 * xmlelem_collection implementation of IEnumVARIANT.
662 static HRESULT WINAPI
xmlelem_collection_IEnumVARIANT_QueryInterface(
663 IEnumVARIANT
*iface
, REFIID riid
, LPVOID
*ppvObj
)
665 xmlelem_collection
*this = impl_from_IEnumVARIANT(iface
);
666 return IXMLDocument_QueryInterface((IXMLDocument
*)this, riid
, ppvObj
);
669 static ULONG WINAPI
xmlelem_collection_IEnumVARIANT_AddRef(
672 xmlelem_collection
*this = impl_from_IEnumVARIANT(iface
);
673 return IXMLDocument_AddRef((IXMLDocument
*)this);
676 static ULONG WINAPI
xmlelem_collection_IEnumVARIANT_Release(
679 xmlelem_collection
*this = impl_from_IEnumVARIANT(iface
);
680 return IXMLDocument_Release((IXMLDocument
*)this);
683 static HRESULT WINAPI
xmlelem_collection_IEnumVARIANT_Next(
684 IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*rgVar
, ULONG
*pCeltFetched
)
686 xmlelem_collection
*This
= impl_from_IEnumVARIANT(iface
);
687 xmlNodePtr ptr
= This
->current
;
689 TRACE("(%p, %d, %p, %p)\n", iface
, celt
, rgVar
, pCeltFetched
);
694 /* FIXME: handle celt */
698 This
->current
= This
->current
->next
;
700 V_VT(rgVar
) = VT_DISPATCH
;
701 return XMLElement_create((IUnknown
*)iface
, ptr
, (LPVOID
*)&V_DISPATCH(rgVar
));
704 static HRESULT WINAPI
xmlelem_collection_IEnumVARIANT_Skip(
705 IEnumVARIANT
*iface
, ULONG celt
)
707 FIXME("(%p, %d): stub\n", iface
, celt
);
711 static HRESULT WINAPI
xmlelem_collection_IEnumVARIANT_Reset(
714 xmlelem_collection
*This
= impl_from_IEnumVARIANT(iface
);
715 This
->current
= This
->node
;
719 static HRESULT WINAPI
xmlelem_collection_IEnumVARIANT_Clone(
720 IEnumVARIANT
*iface
, IEnumVARIANT
**ppEnum
)
722 FIXME("(%p, %p): stub\n", iface
, ppEnum
);
726 static const struct IEnumVARIANTVtbl xmlelem_collection_IEnumVARIANTvtbl
=
728 xmlelem_collection_IEnumVARIANT_QueryInterface
,
729 xmlelem_collection_IEnumVARIANT_AddRef
,
730 xmlelem_collection_IEnumVARIANT_Release
,
731 xmlelem_collection_IEnumVARIANT_Next
,
732 xmlelem_collection_IEnumVARIANT_Skip
,
733 xmlelem_collection_IEnumVARIANT_Reset
,
734 xmlelem_collection_IEnumVARIANT_Clone
737 static HRESULT
XMLElementCollection_create(IUnknown
*pUnkOuter
, xmlNodePtr node
, LPVOID
*ppObj
)
739 xmlelem_collection
*collection
;
742 TRACE("(%p,%p)\n", pUnkOuter
, ppObj
);
749 collection
= HeapAlloc(GetProcessHeap(), 0, sizeof (*collection
));
751 return E_OUTOFMEMORY
;
753 collection
->lpVtbl
= &xmlelem_collection_vtbl
;
754 collection
->lpvtblIEnumVARIANT
= &xmlelem_collection_IEnumVARIANTvtbl
;
756 collection
->length
= 0;
757 collection
->node
= node
;
758 collection
->current
= node
;
763 collection
->length
++;
767 *ppObj
= &collection
->lpVtbl
;
769 TRACE("returning iface %p\n", *ppObj
);