2 * XPath query result node list implementation (TODO: XSLPattern support)
4 * Copyright 2005 Mike McCormack
5 * Copyright 2007 Mikolaj Zalewski
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
33 #include "msxml_private.h"
35 #include "wine/debug.h"
37 /* This file implements the object returned by a XPath query. Note that this is
38 * not the IXMLDOMNodeList returned by childNodes - it's implemented in nodelist.c.
39 * They are different because the list returned by XPath queries:
40 * - is static - gives the results for the XML tree as it existed during the
41 * execution of the query
42 * - supports IXMLDOMSelection (TODO)
44 * TODO: XSLPattern support
47 WINE_DEFAULT_DEBUG_CHANNEL(msxml
);
51 #include <libxml/xpath.h>
53 typedef struct _queryresult
56 const struct IXMLDOMNodeListVtbl
*lpVtbl
;
59 xmlXPathObjectPtr result
;
63 static inline queryresult
*impl_from_IXMLDOMNodeList( IXMLDOMNodeList
*iface
)
65 return (queryresult
*)((char*)iface
- FIELD_OFFSET(queryresult
, lpVtbl
));
68 #define XMLQUERYRES(x) ((IXMLDOMNodeList*)&(x)->lpVtbl)
70 static HRESULT WINAPI
queryresult_QueryInterface(
71 IXMLDOMNodeList
*iface
,
75 queryresult
*This
= impl_from_IXMLDOMNodeList( iface
);
77 TRACE("%p %s %p\n", iface
, debugstr_guid(riid
), ppvObject
);
82 if ( IsEqualGUID( riid
, &IID_IUnknown
) ||
83 IsEqualGUID( riid
, &IID_IXMLDOMNodeList
) )
87 else if(dispex_query_interface(&This
->dispex
, riid
, ppvObject
))
89 return *ppvObject
? S_OK
: E_NOINTERFACE
;
93 FIXME("interface %s not implemented\n", debugstr_guid(riid
));
98 IXMLDOMNodeList_AddRef( iface
);
103 static ULONG WINAPI
queryresult_AddRef(
104 IXMLDOMNodeList
*iface
)
106 queryresult
*This
= impl_from_IXMLDOMNodeList( iface
);
107 return InterlockedIncrement( &This
->ref
);
110 static ULONG WINAPI
queryresult_Release(
111 IXMLDOMNodeList
*iface
)
113 queryresult
*This
= impl_from_IXMLDOMNodeList( iface
);
116 ref
= InterlockedDecrement(&This
->ref
);
119 xmlXPathFreeObject(This
->result
);
120 xmldoc_release(This
->node
->doc
);
127 static HRESULT WINAPI
queryresult_GetTypeInfoCount(
128 IXMLDOMNodeList
*iface
,
131 queryresult
*This
= impl_from_IXMLDOMNodeList( iface
);
133 TRACE("(%p)->(%p)\n", This
, pctinfo
);
140 static HRESULT WINAPI
queryresult_GetTypeInfo(
141 IXMLDOMNodeList
*iface
,
144 ITypeInfo
** ppTInfo
)
146 queryresult
*This
= impl_from_IXMLDOMNodeList( iface
);
149 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
151 hr
= get_typeinfo(IXMLDOMNodeList_tid
, ppTInfo
);
156 static HRESULT WINAPI
queryresult_GetIDsOfNames(
157 IXMLDOMNodeList
*iface
,
164 queryresult
*This
= impl_from_IXMLDOMNodeList( iface
);
168 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
,
171 if(!rgszNames
|| cNames
== 0 || !rgDispId
)
174 hr
= get_typeinfo(IXMLDOMNodeList_tid
, &typeinfo
);
177 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
178 ITypeInfo_Release(typeinfo
);
184 static HRESULT WINAPI
queryresult_Invoke(
185 IXMLDOMNodeList
*iface
,
190 DISPPARAMS
* pDispParams
,
192 EXCEPINFO
* pExcepInfo
,
195 queryresult
*This
= impl_from_IXMLDOMNodeList( iface
);
199 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
200 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
202 hr
= get_typeinfo(IXMLDOMNodeList_tid
, &typeinfo
);
205 hr
= ITypeInfo_Invoke(typeinfo
, &(This
->lpVtbl
), dispIdMember
, wFlags
, pDispParams
,
206 pVarResult
, pExcepInfo
, puArgErr
);
207 ITypeInfo_Release(typeinfo
);
213 static HRESULT WINAPI
queryresult_get_item(
214 IXMLDOMNodeList
* iface
,
216 IXMLDOMNode
** listItem
)
218 queryresult
*This
= impl_from_IXMLDOMNodeList( iface
);
220 TRACE("%p %ld\n", This
, index
);
227 if (index
< 0 || index
>= xmlXPathNodeSetGetLength(This
->result
->nodesetval
))
230 *listItem
= create_node(This
->result
->nodesetval
->nodeTab
[index
]);
231 This
->resultPos
= index
+ 1;
236 static HRESULT WINAPI
queryresult_get_length(
237 IXMLDOMNodeList
* iface
,
240 queryresult
*This
= impl_from_IXMLDOMNodeList( iface
);
247 *listLength
= xmlXPathNodeSetGetLength(This
->result
->nodesetval
);
251 static HRESULT WINAPI
queryresult_nextNode(
252 IXMLDOMNodeList
* iface
,
253 IXMLDOMNode
** nextItem
)
255 queryresult
*This
= impl_from_IXMLDOMNodeList( iface
);
257 TRACE("%p %p\n", This
, nextItem
);
264 if (This
->resultPos
>= xmlXPathNodeSetGetLength(This
->result
->nodesetval
))
267 *nextItem
= create_node(This
->result
->nodesetval
->nodeTab
[This
->resultPos
]);
272 static HRESULT WINAPI
queryresult_reset(
273 IXMLDOMNodeList
* iface
)
275 queryresult
*This
= impl_from_IXMLDOMNodeList( iface
);
282 static HRESULT WINAPI
queryresult__newEnum(
283 IXMLDOMNodeList
* iface
,
291 static const struct IXMLDOMNodeListVtbl queryresult_vtbl
=
293 queryresult_QueryInterface
,
296 queryresult_GetTypeInfoCount
,
297 queryresult_GetTypeInfo
,
298 queryresult_GetIDsOfNames
,
300 queryresult_get_item
,
301 queryresult_get_length
,
302 queryresult_nextNode
,
304 queryresult__newEnum
,
307 static HRESULT
queryresult_get_dispid(IUnknown
*iface
, BSTR name
, DWORD flags
, DISPID
*dispid
)
309 queryresult
*This
= impl_from_IXMLDOMNodeList( (IXMLDOMNodeList
*)iface
);
313 for(ptr
= name
; *ptr
&& isdigitW(*ptr
); ptr
++)
314 idx
= idx
*10 + (*ptr
-'0');
316 return DISP_E_UNKNOWNNAME
;
318 if(idx
>= xmlXPathNodeSetGetLength(This
->result
->nodesetval
))
319 return DISP_E_UNKNOWNNAME
;
321 *dispid
= MSXML_DISPID_CUSTOM_MIN
+ idx
;
322 TRACE("ret %x\n", *dispid
);
326 static HRESULT
queryresult_invoke(IUnknown
*iface
, DISPID id
, LCID lcid
, WORD flags
, DISPPARAMS
*params
,
327 VARIANT
*res
, EXCEPINFO
*ei
)
329 queryresult
*This
= impl_from_IXMLDOMNodeList( (IXMLDOMNodeList
*)iface
);
331 TRACE("(%p)->(%x %x %x %p %p %p)\n", This
, id
, lcid
, flags
, params
, res
, ei
);
333 V_VT(res
) = VT_DISPATCH
;
334 V_DISPATCH(res
) = NULL
;
338 case INVOKE_PROPERTYGET
:
340 IXMLDOMNode
*disp
= NULL
;
342 queryresult_get_item(XMLQUERYRES(This
), id
- MSXML_DISPID_CUSTOM_MIN
, &disp
);
343 V_DISPATCH(res
) = (IDispatch
*)disp
;
348 FIXME("unimplemented flags %x\n", flags
);
353 TRACE("ret %p\n", V_DISPATCH(res
));
358 static const dispex_static_data_vtbl_t queryresult_dispex_vtbl
= {
359 queryresult_get_dispid
,
363 static const tid_t queryresult_iface_tids
[] = {
367 static dispex_static_data_t queryresult_dispex
= {
368 &queryresult_dispex_vtbl
,
371 queryresult_iface_tids
374 HRESULT
queryresult_create(xmlNodePtr node
, LPWSTR szQuery
, IXMLDOMNodeList
**out
)
376 queryresult
*This
= heap_alloc_zero(sizeof(queryresult
));
377 xmlXPathContextPtr ctxt
= xmlXPathNewContext(node
->doc
);
378 xmlChar
*str
= xmlChar_from_wchar(szQuery
);
382 TRACE("(%p, %s, %p)\n", node
, wine_dbgstr_w(szQuery
), out
);
385 if (This
== NULL
|| ctxt
== NULL
|| str
== NULL
)
391 This
->lpVtbl
= &queryresult_vtbl
;
395 xmldoc_add_ref(This
->node
->doc
);
398 This
->result
= xmlXPathEval(str
, ctxt
);
399 if (!This
->result
|| This
->result
->type
!= XPATH_NODESET
)
405 init_dispex(&This
->dispex
, (IUnknown
*)&This
->lpVtbl
, &queryresult_dispex
);
407 *out
= (IXMLDOMNodeList
*) &This
->lpVtbl
;
409 TRACE("found %d matches\n", xmlXPathNodeSetGetLength(This
->result
->nodesetval
));
412 if (This
!= NULL
&& FAILED(hr
))
413 IXMLDOMNodeList_Release( (IXMLDOMNodeList
*) &This
->lpVtbl
);
415 xmlXPathFreeContext(ctxt
);
416 HeapFree(GetProcessHeap(), 0, str
);