2 * Node list implementation
4 * Copyright 2005 Mike McCormack
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>
32 #include "msxml2did.h"
34 #include "msxml_private.h"
36 #include "wine/debug.h"
38 /* This file implements the object returned by childNodes property. Note that this is
39 * not the IXMLDOMNodeList returned by XPath queries - it's implemented in selection.c.
40 * They are different because the list returned by childNodes:
41 * - is "live" - changes to the XML tree are automatically reflected in the list
42 * - doesn't supports IXMLDOMSelection
43 * - note that an attribute node have a text child in DOM but not in the XPath data model
44 * thus the child is inaccessible by an XPath query
47 WINE_DEFAULT_DEBUG_CHANNEL(msxml
);
52 IXMLDOMNodeList IXMLDOMNodeList_iface
;
56 IEnumVARIANT
*enumvariant
;
59 static HRESULT
nodelist_get_item(IUnknown
*iface
, LONG index
, VARIANT
*item
)
61 V_VT(item
) = VT_DISPATCH
;
62 return IXMLDOMNodeList_get_item((IXMLDOMNodeList
*)iface
, index
, (IXMLDOMNode
**)&V_DISPATCH(item
));
65 static const struct enumvariant_funcs nodelist_enumvariant
= {
70 static inline xmlnodelist
*impl_from_IXMLDOMNodeList( IXMLDOMNodeList
*iface
)
72 return CONTAINING_RECORD(iface
, xmlnodelist
, IXMLDOMNodeList_iface
);
75 static HRESULT WINAPI
xmlnodelist_QueryInterface(
76 IXMLDOMNodeList
*iface
,
80 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
82 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppvObject
);
84 if ( IsEqualGUID( riid
, &IID_IUnknown
) ||
85 IsEqualGUID( riid
, &IID_IDispatch
) ||
86 IsEqualGUID( riid
, &IID_IXMLDOMNodeList
) )
90 else if (IsEqualGUID( riid
, &IID_IEnumVARIANT
))
92 if (!This
->enumvariant
)
94 HRESULT hr
= create_enumvariant((IUnknown
*)iface
, FALSE
, &nodelist_enumvariant
, &This
->enumvariant
);
95 if (FAILED(hr
)) return hr
;
98 return IEnumVARIANT_QueryInterface(This
->enumvariant
, &IID_IEnumVARIANT
, ppvObject
);
100 else if (dispex_query_interface(&This
->dispex
, riid
, ppvObject
))
102 return *ppvObject
? S_OK
: E_NOINTERFACE
;
106 TRACE("interface %s not implemented\n", debugstr_guid(riid
));
108 return E_NOINTERFACE
;
111 IXMLDOMNodeList_AddRef( iface
);
116 static ULONG WINAPI
xmlnodelist_AddRef(
117 IXMLDOMNodeList
*iface
)
119 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
120 ULONG ref
= InterlockedIncrement( &This
->ref
);
121 TRACE("%p, refcount %lu.\n", iface
, ref
);
125 static ULONG WINAPI
xmlnodelist_Release(
126 IXMLDOMNodeList
*iface
)
128 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
129 ULONG ref
= InterlockedDecrement( &This
->ref
);
131 TRACE("%p, refcount %lu.\n", iface
, ref
);
135 xmldoc_release( This
->parent
->doc
);
136 if (This
->enumvariant
) IEnumVARIANT_Release(This
->enumvariant
);
143 static HRESULT WINAPI
xmlnodelist_GetTypeInfoCount(
144 IXMLDOMNodeList
*iface
,
147 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
148 return IDispatchEx_GetTypeInfoCount(&This
->dispex
.IDispatchEx_iface
, pctinfo
);
151 static HRESULT WINAPI
xmlnodelist_GetTypeInfo(
152 IXMLDOMNodeList
*iface
,
155 ITypeInfo
** ppTInfo
)
157 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
158 return IDispatchEx_GetTypeInfo(&This
->dispex
.IDispatchEx_iface
,
159 iTInfo
, lcid
, ppTInfo
);
162 static HRESULT WINAPI
xmlnodelist_GetIDsOfNames(
163 IXMLDOMNodeList
*iface
,
170 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
171 return IDispatchEx_GetIDsOfNames(&This
->dispex
.IDispatchEx_iface
,
172 riid
, rgszNames
, cNames
, lcid
, rgDispId
);
175 static HRESULT WINAPI
xmlnodelist_Invoke(
176 IXMLDOMNodeList
*iface
,
181 DISPPARAMS
* pDispParams
,
183 EXCEPINFO
* pExcepInfo
,
186 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
187 return IDispatchEx_Invoke(&This
->dispex
.IDispatchEx_iface
,
188 dispIdMember
, riid
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
191 static HRESULT WINAPI
xmlnodelist_get_item(
192 IXMLDOMNodeList
* iface
,
194 IXMLDOMNode
** listItem
)
196 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
200 TRACE("%p, %ld, %p.\n", iface
, index
, listItem
);
210 curr
= This
->parent
->children
;
213 if(nodeIndex
++ == index
) break;
216 if(!curr
) return S_FALSE
;
218 *listItem
= create_node( curr
);
223 static HRESULT WINAPI
xmlnodelist_get_length(
224 IXMLDOMNodeList
* iface
,
231 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
233 TRACE("(%p)->(%p)\n", This
, listLength
);
238 curr
= This
->parent
->children
;
245 *listLength
= nodeCount
;
249 static HRESULT WINAPI
xmlnodelist_nextNode(
250 IXMLDOMNodeList
* iface
,
251 IXMLDOMNode
** nextItem
)
253 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
255 TRACE("(%p)->(%p)\n", This
, nextItem
);
265 *nextItem
= create_node( This
->current
);
266 This
->current
= This
->current
->next
;
270 static HRESULT WINAPI
xmlnodelist_reset(
271 IXMLDOMNodeList
* iface
)
273 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
276 This
->current
= This
->parent
->children
;
280 static HRESULT WINAPI
xmlnodelist__newEnum(
281 IXMLDOMNodeList
* iface
,
284 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
285 TRACE("(%p)->(%p)\n", This
, enumv
);
286 return create_enumvariant((IUnknown
*)iface
, TRUE
, &nodelist_enumvariant
, (IEnumVARIANT
**)enumv
);
289 static const struct IXMLDOMNodeListVtbl xmlnodelist_vtbl
=
291 xmlnodelist_QueryInterface
,
294 xmlnodelist_GetTypeInfoCount
,
295 xmlnodelist_GetTypeInfo
,
296 xmlnodelist_GetIDsOfNames
,
298 xmlnodelist_get_item
,
299 xmlnodelist_get_length
,
300 xmlnodelist_nextNode
,
302 xmlnodelist__newEnum
,
305 static HRESULT
xmlnodelist_get_dispid(IUnknown
*iface
, BSTR name
, DWORD flags
, DISPID
*dispid
)
310 for(ptr
= name
; *ptr
>= '0' && *ptr
<= '9'; ptr
++)
311 idx
= idx
*10 + (*ptr
-'0');
313 return DISP_E_UNKNOWNNAME
;
315 *dispid
= DISPID_DOM_COLLECTION_BASE
+ idx
;
316 TRACE("ret %lx\n", *dispid
);
320 static HRESULT
xmlnodelist_invoke(IUnknown
*iface
, DISPID id
, LCID lcid
, WORD flags
, DISPPARAMS
*params
,
321 VARIANT
*res
, EXCEPINFO
*ei
)
323 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( (IXMLDOMNodeList
*)iface
);
325 TRACE("%p, %ld, %lx, %x, %p, %p, %p.\n", iface
, id
, lcid
, flags
, params
, res
, ei
);
327 if (id
>= DISPID_DOM_COLLECTION_BASE
&& id
<= DISPID_DOM_COLLECTION_MAX
)
331 case DISPATCH_PROPERTYGET
:
333 IXMLDOMNode
*disp
= NULL
;
335 V_VT(res
) = VT_DISPATCH
;
336 IXMLDOMNodeList_get_item(&This
->IXMLDOMNodeList_iface
, id
- DISPID_DOM_COLLECTION_BASE
, &disp
);
337 V_DISPATCH(res
) = (IDispatch
*)disp
;
342 FIXME("unimplemented flags %x\n", flags
);
347 else if (id
== DISPID_VALUE
)
351 case DISPATCH_METHOD
|DISPATCH_PROPERTYGET
:
352 case DISPATCH_PROPERTYGET
:
353 case DISPATCH_METHOD
:
359 if (params
->cArgs
- params
->cNamedArgs
!= 1) return DISP_E_BADPARAMCOUNT
;
362 hr
= VariantChangeType(&index
, params
->rgvarg
, 0, VT_I4
);
365 FIXME("failed to convert arg, %s\n", debugstr_variant(params
->rgvarg
));
369 IXMLDOMNodeList_get_item(&This
->IXMLDOMNodeList_iface
, V_I4(&index
), &item
);
370 V_VT(res
) = VT_DISPATCH
;
371 V_DISPATCH(res
) = (IDispatch
*)item
;
376 FIXME("DISPID_VALUE: unimplemented flags %x\n", flags
);
382 return DISP_E_UNKNOWNNAME
;
384 TRACE("ret %p\n", V_DISPATCH(res
));
389 static const dispex_static_data_vtbl_t xmlnodelist_dispex_vtbl
= {
390 xmlnodelist_get_dispid
,
394 static const tid_t xmlnodelist_iface_tids
[] = {
398 static dispex_static_data_t xmlnodelist_dispex
= {
399 &xmlnodelist_dispex_vtbl
,
402 xmlnodelist_iface_tids
405 IXMLDOMNodeList
* create_children_nodelist( xmlNodePtr node
)
409 This
= heap_alloc( sizeof *This
);
413 This
->IXMLDOMNodeList_iface
.lpVtbl
= &xmlnodelist_vtbl
;
416 This
->current
= node
->children
;
417 This
->enumvariant
= NULL
;
418 xmldoc_add_ref( node
->doc
);
420 init_dispex(&This
->dispex
, (IUnknown
*)&This
->IXMLDOMNodeList_iface
, &xmlnodelist_dispex
);
422 return &This
->IXMLDOMNodeList_iface
;