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
27 # include <libxml/parser.h>
28 # include <libxml/xmlerror.h>
36 #include "msxml2did.h"
38 #include "msxml_private.h"
40 #include "wine/debug.h"
42 /* This file implements the object returned by childNodes property. Note that this is
43 * not the IXMLDOMNodeList returned by XPath queries - it's implemented in selection.c.
44 * They are different because the list returned by childNodes:
45 * - is "live" - changes to the XML tree are automatically reflected in the list
46 * - doesn't supports IXMLDOMSelection
47 * - note that an attribute node have a text child in DOM but not in the XPath data model
48 * thus the child is inaccessible by an XPath query
51 WINE_DEFAULT_DEBUG_CHANNEL(msxml
);
58 IXMLDOMNodeList IXMLDOMNodeList_iface
;
62 IEnumVARIANT
*enumvariant
;
65 static HRESULT
nodelist_get_item(IUnknown
*iface
, LONG index
, VARIANT
*item
)
67 V_VT(item
) = VT_DISPATCH
;
68 return IXMLDOMNodeList_get_item((IXMLDOMNodeList
*)iface
, index
, (IXMLDOMNode
**)&V_DISPATCH(item
));
71 static const struct enumvariant_funcs nodelist_enumvariant
= {
76 static inline xmlnodelist
*impl_from_IXMLDOMNodeList( IXMLDOMNodeList
*iface
)
78 return CONTAINING_RECORD(iface
, xmlnodelist
, IXMLDOMNodeList_iface
);
81 static HRESULT WINAPI
xmlnodelist_QueryInterface(
82 IXMLDOMNodeList
*iface
,
86 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
88 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppvObject
);
90 if ( IsEqualGUID( riid
, &IID_IUnknown
) ||
91 IsEqualGUID( riid
, &IID_IDispatch
) ||
92 IsEqualGUID( riid
, &IID_IXMLDOMNodeList
) )
96 else if (IsEqualGUID( riid
, &IID_IEnumVARIANT
))
98 if (!This
->enumvariant
)
100 HRESULT hr
= create_enumvariant((IUnknown
*)iface
, FALSE
, &nodelist_enumvariant
, &This
->enumvariant
);
101 if (FAILED(hr
)) return hr
;
104 return IEnumVARIANT_QueryInterface(This
->enumvariant
, &IID_IEnumVARIANT
, ppvObject
);
106 else if (dispex_query_interface(&This
->dispex
, riid
, ppvObject
))
108 return *ppvObject
? S_OK
: E_NOINTERFACE
;
112 TRACE("interface %s not implemented\n", debugstr_guid(riid
));
114 return E_NOINTERFACE
;
117 IXMLDOMNodeList_AddRef( iface
);
122 static ULONG WINAPI
xmlnodelist_AddRef(
123 IXMLDOMNodeList
*iface
)
125 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
126 ULONG ref
= InterlockedIncrement( &This
->ref
);
127 TRACE("(%p)->(%d)\n", This
, ref
);
131 static ULONG WINAPI
xmlnodelist_Release(
132 IXMLDOMNodeList
*iface
)
134 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
135 ULONG ref
= InterlockedDecrement( &This
->ref
);
137 TRACE("(%p)->(%d)\n", This
, ref
);
140 xmldoc_release( This
->parent
->doc
);
141 if (This
->enumvariant
) IEnumVARIANT_Release(This
->enumvariant
);
148 static HRESULT WINAPI
xmlnodelist_GetTypeInfoCount(
149 IXMLDOMNodeList
*iface
,
152 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
153 return IDispatchEx_GetTypeInfoCount(&This
->dispex
.IDispatchEx_iface
, pctinfo
);
156 static HRESULT WINAPI
xmlnodelist_GetTypeInfo(
157 IXMLDOMNodeList
*iface
,
160 ITypeInfo
** ppTInfo
)
162 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
163 return IDispatchEx_GetTypeInfo(&This
->dispex
.IDispatchEx_iface
,
164 iTInfo
, lcid
, ppTInfo
);
167 static HRESULT WINAPI
xmlnodelist_GetIDsOfNames(
168 IXMLDOMNodeList
*iface
,
175 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
176 return IDispatchEx_GetIDsOfNames(&This
->dispex
.IDispatchEx_iface
,
177 riid
, rgszNames
, cNames
, lcid
, rgDispId
);
180 static HRESULT WINAPI
xmlnodelist_Invoke(
181 IXMLDOMNodeList
*iface
,
186 DISPPARAMS
* pDispParams
,
188 EXCEPINFO
* pExcepInfo
,
191 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
192 return IDispatchEx_Invoke(&This
->dispex
.IDispatchEx_iface
,
193 dispIdMember
, riid
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
196 static HRESULT WINAPI
xmlnodelist_get_item(
197 IXMLDOMNodeList
* iface
,
199 IXMLDOMNode
** listItem
)
201 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
205 TRACE("(%p)->(%d %p)\n", This
, index
, listItem
);
215 curr
= This
->parent
->children
;
218 if(nodeIndex
++ == index
) break;
221 if(!curr
) return S_FALSE
;
223 *listItem
= create_node( curr
);
228 static HRESULT WINAPI
xmlnodelist_get_length(
229 IXMLDOMNodeList
* iface
,
236 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
238 TRACE("(%p)->(%p)\n", This
, listLength
);
243 curr
= This
->parent
->children
;
250 *listLength
= nodeCount
;
254 static HRESULT WINAPI
xmlnodelist_nextNode(
255 IXMLDOMNodeList
* iface
,
256 IXMLDOMNode
** nextItem
)
258 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
260 TRACE("(%p)->(%p)\n", This
, nextItem
);
270 *nextItem
= create_node( This
->current
);
271 This
->current
= This
->current
->next
;
275 static HRESULT WINAPI
xmlnodelist_reset(
276 IXMLDOMNodeList
* iface
)
278 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
281 This
->current
= This
->parent
->children
;
285 static HRESULT WINAPI
xmlnodelist__newEnum(
286 IXMLDOMNodeList
* iface
,
289 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
290 TRACE("(%p)->(%p)\n", This
, enumv
);
291 return create_enumvariant((IUnknown
*)iface
, TRUE
, &nodelist_enumvariant
, (IEnumVARIANT
**)enumv
);
294 static const struct IXMLDOMNodeListVtbl xmlnodelist_vtbl
=
296 xmlnodelist_QueryInterface
,
299 xmlnodelist_GetTypeInfoCount
,
300 xmlnodelist_GetTypeInfo
,
301 xmlnodelist_GetIDsOfNames
,
303 xmlnodelist_get_item
,
304 xmlnodelist_get_length
,
305 xmlnodelist_nextNode
,
307 xmlnodelist__newEnum
,
310 static HRESULT
xmlnodelist_get_dispid(IUnknown
*iface
, BSTR name
, DWORD flags
, DISPID
*dispid
)
315 for(ptr
= name
; *ptr
&& isdigitW(*ptr
); ptr
++)
316 idx
= idx
*10 + (*ptr
-'0');
318 return DISP_E_UNKNOWNNAME
;
320 *dispid
= DISPID_DOM_COLLECTION_BASE
+ idx
;
321 TRACE("ret %x\n", *dispid
);
325 static HRESULT
xmlnodelist_invoke(IUnknown
*iface
, DISPID id
, LCID lcid
, WORD flags
, DISPPARAMS
*params
,
326 VARIANT
*res
, EXCEPINFO
*ei
)
328 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( (IXMLDOMNodeList
*)iface
);
330 TRACE("(%p)->(%x %x %x %p %p %p)\n", This
, id
, lcid
, flags
, params
, res
, ei
);
332 if (id
>= DISPID_DOM_COLLECTION_BASE
&& id
<= DISPID_DOM_COLLECTION_MAX
)
336 case DISPATCH_PROPERTYGET
:
338 IXMLDOMNode
*disp
= NULL
;
340 V_VT(res
) = VT_DISPATCH
;
341 IXMLDOMNodeList_get_item(&This
->IXMLDOMNodeList_iface
, id
- DISPID_DOM_COLLECTION_BASE
, &disp
);
342 V_DISPATCH(res
) = (IDispatch
*)disp
;
347 FIXME("unimplemented flags %x\n", flags
);
352 else if (id
== DISPID_VALUE
)
356 case DISPATCH_METHOD
|DISPATCH_PROPERTYGET
:
357 case DISPATCH_PROPERTYGET
:
358 case DISPATCH_METHOD
:
364 if (params
->cArgs
- params
->cNamedArgs
!= 1) return DISP_E_BADPARAMCOUNT
;
367 hr
= VariantChangeType(&index
, params
->rgvarg
, 0, VT_I4
);
370 FIXME("failed to convert arg, %s\n", debugstr_variant(params
->rgvarg
));
374 IXMLDOMNodeList_get_item(&This
->IXMLDOMNodeList_iface
, V_I4(&index
), &item
);
375 V_VT(res
) = VT_DISPATCH
;
376 V_DISPATCH(res
) = (IDispatch
*)item
;
381 FIXME("DISPID_VALUE: unimplemented flags %x\n", flags
);
387 return DISP_E_UNKNOWNNAME
;
389 TRACE("ret %p\n", V_DISPATCH(res
));
394 static const dispex_static_data_vtbl_t xmlnodelist_dispex_vtbl
= {
395 xmlnodelist_get_dispid
,
399 static const tid_t xmlnodelist_iface_tids
[] = {
403 static dispex_static_data_t xmlnodelist_dispex
= {
404 &xmlnodelist_dispex_vtbl
,
407 xmlnodelist_iface_tids
410 IXMLDOMNodeList
* create_children_nodelist( xmlNodePtr node
)
414 This
= heap_alloc( sizeof *This
);
418 This
->IXMLDOMNodeList_iface
.lpVtbl
= &xmlnodelist_vtbl
;
421 This
->current
= node
->children
;
422 This
->enumvariant
= NULL
;
423 xmldoc_add_ref( node
->doc
);
425 init_dispex(&This
->dispex
, (IUnknown
*)&This
->IXMLDOMNodeList_iface
, &xmlnodelist_dispex
);
427 return &This
->IXMLDOMNodeList_iface
;