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 querites - it's implemented in queryresult.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
);
55 typedef struct _xmlnodelist
58 IXMLDOMNodeList IXMLDOMNodeList_iface
;
64 static inline xmlnodelist
*impl_from_IXMLDOMNodeList( IXMLDOMNodeList
*iface
)
66 return CONTAINING_RECORD(iface
, xmlnodelist
, IXMLDOMNodeList_iface
);
69 static HRESULT WINAPI
xmlnodelist_QueryInterface(
70 IXMLDOMNodeList
*iface
,
74 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
76 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppvObject
);
78 if ( IsEqualGUID( riid
, &IID_IUnknown
) ||
79 IsEqualGUID( riid
, &IID_IDispatch
) ||
80 IsEqualGUID( riid
, &IID_IXMLDOMNodeList
) )
84 else if (dispex_query_interface(&This
->dispex
, riid
, ppvObject
))
86 return *ppvObject
? S_OK
: E_NOINTERFACE
;
90 TRACE("interface %s not implemented\n", debugstr_guid(riid
));
95 IXMLDOMNodeList_AddRef( iface
);
100 static ULONG WINAPI
xmlnodelist_AddRef(
101 IXMLDOMNodeList
*iface
)
103 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
104 ULONG ref
= InterlockedIncrement( &This
->ref
);
105 TRACE("(%p)->(%d)\n", This
, ref
);
109 static ULONG WINAPI
xmlnodelist_Release(
110 IXMLDOMNodeList
*iface
)
112 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
113 ULONG ref
= InterlockedDecrement( &This
->ref
);
115 TRACE("(%p)->(%d)\n", This
, ref
);
118 xmldoc_release( This
->parent
->doc
);
125 static HRESULT WINAPI
xmlnodelist_GetTypeInfoCount(
126 IXMLDOMNodeList
*iface
,
129 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
130 return IDispatchEx_GetTypeInfoCount(&This
->dispex
.IDispatchEx_iface
, pctinfo
);
133 static HRESULT WINAPI
xmlnodelist_GetTypeInfo(
134 IXMLDOMNodeList
*iface
,
137 ITypeInfo
** ppTInfo
)
139 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
140 return IDispatchEx_GetTypeInfo(&This
->dispex
.IDispatchEx_iface
,
141 iTInfo
, lcid
, ppTInfo
);
144 static HRESULT WINAPI
xmlnodelist_GetIDsOfNames(
145 IXMLDOMNodeList
*iface
,
152 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
153 return IDispatchEx_GetIDsOfNames(&This
->dispex
.IDispatchEx_iface
,
154 riid
, rgszNames
, cNames
, lcid
, rgDispId
);
157 static HRESULT WINAPI
xmlnodelist_Invoke(
158 IXMLDOMNodeList
*iface
,
163 DISPPARAMS
* pDispParams
,
165 EXCEPINFO
* pExcepInfo
,
168 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
169 return IDispatchEx_Invoke(&This
->dispex
.IDispatchEx_iface
,
170 dispIdMember
, riid
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
173 static HRESULT WINAPI
xmlnodelist_get_item(
174 IXMLDOMNodeList
* iface
,
176 IXMLDOMNode
** listItem
)
178 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
182 TRACE("(%p)->(%d %p)\n", This
, index
, listItem
);
192 curr
= This
->parent
->children
;
195 if(nodeIndex
++ == index
) break;
198 if(!curr
) return S_FALSE
;
200 *listItem
= create_node( curr
);
205 static HRESULT WINAPI
xmlnodelist_get_length(
206 IXMLDOMNodeList
* iface
,
213 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
215 TRACE("(%p)->(%p)\n", This
, listLength
);
220 curr
= This
->parent
->children
;
227 *listLength
= nodeCount
;
231 static HRESULT WINAPI
xmlnodelist_nextNode(
232 IXMLDOMNodeList
* iface
,
233 IXMLDOMNode
** nextItem
)
235 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
237 TRACE("(%p)->(%p)\n", This
, nextItem
);
247 *nextItem
= create_node( This
->current
);
248 This
->current
= This
->current
->next
;
252 static HRESULT WINAPI
xmlnodelist_reset(
253 IXMLDOMNodeList
* iface
)
255 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
258 This
->current
= This
->parent
->children
;
262 static HRESULT WINAPI
xmlnodelist__newEnum(
263 IXMLDOMNodeList
* iface
,
266 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
267 FIXME("(%p)->(%p)\n", This
, ppUnk
);
271 static const struct IXMLDOMNodeListVtbl xmlnodelist_vtbl
=
273 xmlnodelist_QueryInterface
,
276 xmlnodelist_GetTypeInfoCount
,
277 xmlnodelist_GetTypeInfo
,
278 xmlnodelist_GetIDsOfNames
,
280 xmlnodelist_get_item
,
281 xmlnodelist_get_length
,
282 xmlnodelist_nextNode
,
284 xmlnodelist__newEnum
,
287 static HRESULT
xmlnodelist_get_dispid(IUnknown
*iface
, BSTR name
, DWORD flags
, DISPID
*dispid
)
292 for(ptr
= name
; *ptr
&& isdigitW(*ptr
); ptr
++)
293 idx
= idx
*10 + (*ptr
-'0');
295 return DISP_E_UNKNOWNNAME
;
297 *dispid
= DISPID_DOM_COLLECTION_BASE
+ idx
;
298 TRACE("ret %x\n", *dispid
);
302 static HRESULT
xmlnodelist_invoke(IUnknown
*iface
, DISPID id
, LCID lcid
, WORD flags
, DISPPARAMS
*params
,
303 VARIANT
*res
, EXCEPINFO
*ei
)
305 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( (IXMLDOMNodeList
*)iface
);
307 TRACE("(%p)->(%x %x %x %p %p %p)\n", This
, id
, lcid
, flags
, params
, res
, ei
);
309 V_VT(res
) = VT_DISPATCH
;
310 V_DISPATCH(res
) = NULL
;
312 if (id
< DISPID_DOM_COLLECTION_BASE
|| id
> DISPID_DOM_COLLECTION_MAX
)
313 return DISP_E_UNKNOWNNAME
;
317 case INVOKE_PROPERTYGET
:
319 IXMLDOMNode
*disp
= NULL
;
321 IXMLDOMNodeList_get_item(&This
->IXMLDOMNodeList_iface
, id
- DISPID_DOM_COLLECTION_BASE
, &disp
);
322 V_DISPATCH(res
) = (IDispatch
*)disp
;
327 FIXME("unimplemented flags %x\n", flags
);
332 TRACE("ret %p\n", V_DISPATCH(res
));
337 static const dispex_static_data_vtbl_t xmlnodelist_dispex_vtbl
= {
338 xmlnodelist_get_dispid
,
342 static const tid_t xmlnodelist_iface_tids
[] = {
346 static dispex_static_data_t xmlnodelist_dispex
= {
347 &xmlnodelist_dispex_vtbl
,
350 xmlnodelist_iface_tids
353 IXMLDOMNodeList
* create_children_nodelist( xmlNodePtr node
)
357 This
= heap_alloc( sizeof *This
);
361 This
->IXMLDOMNodeList_iface
.lpVtbl
= &xmlnodelist_vtbl
;
364 This
->current
= node
->children
;
365 xmldoc_add_ref( node
->doc
);
367 init_dispex(&This
->dispex
, (IUnknown
*)&This
->IXMLDOMNodeList_iface
, &xmlnodelist_dispex
);
369 return &This
->IXMLDOMNodeList_iface
;