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 static HRESULT WINAPI
queryresult_QueryInterface(
69 IXMLDOMNodeList
*iface
,
73 queryresult
*This
= impl_from_IXMLDOMNodeList( iface
);
75 TRACE("%p %s %p\n", iface
, debugstr_guid(riid
), ppvObject
);
80 if ( IsEqualGUID( riid
, &IID_IUnknown
) ||
81 IsEqualGUID( riid
, &IID_IXMLDOMNodeList
) )
85 else if(dispex_query_interface(&This
->dispex
, riid
, ppvObject
))
87 return *ppvObject
? S_OK
: E_NOINTERFACE
;
91 FIXME("interface %s not implemented\n", debugstr_guid(riid
));
96 IXMLDOMNodeList_AddRef( iface
);
101 static ULONG WINAPI
queryresult_AddRef(
102 IXMLDOMNodeList
*iface
)
104 queryresult
*This
= impl_from_IXMLDOMNodeList( iface
);
105 return InterlockedIncrement( &This
->ref
);
108 static ULONG WINAPI
queryresult_Release(
109 IXMLDOMNodeList
*iface
)
111 queryresult
*This
= impl_from_IXMLDOMNodeList( iface
);
114 ref
= InterlockedDecrement(&This
->ref
);
117 xmlXPathFreeObject(This
->result
);
118 xmldoc_release(This
->node
->doc
);
125 static HRESULT WINAPI
queryresult_GetTypeInfoCount(
126 IXMLDOMNodeList
*iface
,
129 queryresult
*This
= impl_from_IXMLDOMNodeList( iface
);
131 TRACE("(%p)->(%p)\n", This
, pctinfo
);
138 static HRESULT WINAPI
queryresult_GetTypeInfo(
139 IXMLDOMNodeList
*iface
,
142 ITypeInfo
** ppTInfo
)
144 queryresult
*This
= impl_from_IXMLDOMNodeList( iface
);
147 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
149 hr
= get_typeinfo(IXMLDOMNodeList_tid
, ppTInfo
);
154 static HRESULT WINAPI
queryresult_GetIDsOfNames(
155 IXMLDOMNodeList
*iface
,
162 queryresult
*This
= impl_from_IXMLDOMNodeList( iface
);
166 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
,
169 if(!rgszNames
|| cNames
== 0 || !rgDispId
)
172 hr
= get_typeinfo(IXMLDOMNodeList_tid
, &typeinfo
);
175 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
176 ITypeInfo_Release(typeinfo
);
182 static HRESULT WINAPI
queryresult_Invoke(
183 IXMLDOMNodeList
*iface
,
188 DISPPARAMS
* pDispParams
,
190 EXCEPINFO
* pExcepInfo
,
193 queryresult
*This
= impl_from_IXMLDOMNodeList( iface
);
197 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
198 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
200 hr
= get_typeinfo(IXMLDOMNodeList_tid
, &typeinfo
);
203 hr
= ITypeInfo_Invoke(typeinfo
, &(This
->lpVtbl
), dispIdMember
, wFlags
, pDispParams
,
204 pVarResult
, pExcepInfo
, puArgErr
);
205 ITypeInfo_Release(typeinfo
);
211 static HRESULT WINAPI
queryresult_get_item(
212 IXMLDOMNodeList
* iface
,
214 IXMLDOMNode
** listItem
)
216 queryresult
*This
= impl_from_IXMLDOMNodeList( iface
);
218 TRACE("%p %ld\n", This
, index
);
225 if (index
< 0 || index
>= xmlXPathNodeSetGetLength(This
->result
->nodesetval
))
228 *listItem
= create_node(This
->result
->nodesetval
->nodeTab
[index
]);
229 This
->resultPos
= index
+ 1;
234 static HRESULT WINAPI
queryresult_get_length(
235 IXMLDOMNodeList
* iface
,
238 queryresult
*This
= impl_from_IXMLDOMNodeList( iface
);
245 *listLength
= xmlXPathNodeSetGetLength(This
->result
->nodesetval
);
249 static HRESULT WINAPI
queryresult_nextNode(
250 IXMLDOMNodeList
* iface
,
251 IXMLDOMNode
** nextItem
)
253 queryresult
*This
= impl_from_IXMLDOMNodeList( iface
);
255 TRACE("%p %p\n", This
, nextItem
);
262 if (This
->resultPos
>= xmlXPathNodeSetGetLength(This
->result
->nodesetval
))
265 *nextItem
= create_node(This
->result
->nodesetval
->nodeTab
[This
->resultPos
]);
270 static HRESULT WINAPI
queryresult_reset(
271 IXMLDOMNodeList
* iface
)
273 queryresult
*This
= impl_from_IXMLDOMNodeList( iface
);
280 static HRESULT WINAPI
queryresult__newEnum(
281 IXMLDOMNodeList
* iface
,
289 static const struct IXMLDOMNodeListVtbl queryresult_vtbl
=
291 queryresult_QueryInterface
,
294 queryresult_GetTypeInfoCount
,
295 queryresult_GetTypeInfo
,
296 queryresult_GetIDsOfNames
,
298 queryresult_get_item
,
299 queryresult_get_length
,
300 queryresult_nextNode
,
302 queryresult__newEnum
,
305 static HRESULT
queryresult_get_dispid(IUnknown
*iface
, BSTR name
, DWORD flags
, DISPID
*dispid
)
307 queryresult
*This
= impl_from_IXMLDOMNodeList( (IXMLDOMNodeList
*)iface
);
311 for(ptr
= name
; *ptr
&& isdigitW(*ptr
); ptr
++)
312 idx
= idx
*10 + (*ptr
-'0');
314 return DISP_E_UNKNOWNNAME
;
316 if(idx
>= xmlXPathNodeSetGetLength(This
->result
->nodesetval
))
317 return DISP_E_UNKNOWNNAME
;
319 *dispid
= MSXML_DISPID_CUSTOM_MIN
+ idx
;
320 TRACE("ret %x\n", *dispid
);
324 static HRESULT
queryresult_invoke(IUnknown
*iface
, DISPID id
, LCID lcid
, WORD flags
, DISPPARAMS
*params
,
325 VARIANT
*res
, EXCEPINFO
*ei
)
327 queryresult
*This
= impl_from_IXMLDOMNodeList( (IXMLDOMNodeList
*)iface
);
329 if(flags
!= DISPATCH_PROPERTYGET
) {
330 FIXME("flags %x\n", flags
);
334 V_VT(res
) = VT_DISPATCH
;
335 V_DISPATCH(res
) = (IDispatch
*)create_node(This
->result
->nodesetval
->nodeTab
[This
->resultPos
]);
339 static const dispex_static_data_vtbl_t queryresult_dispex_vtbl
= {
340 queryresult_get_dispid
,
344 static const tid_t queryresult_iface_tids
[] = {
348 static dispex_static_data_t queryresult_dispex
= {
349 &queryresult_dispex_vtbl
,
352 queryresult_iface_tids
355 HRESULT
queryresult_create(xmlNodePtr node
, LPWSTR szQuery
, IXMLDOMNodeList
**out
)
357 queryresult
*This
= heap_alloc_zero(sizeof(queryresult
));
358 xmlXPathContextPtr ctxt
= xmlXPathNewContext(node
->doc
);
359 xmlChar
*str
= xmlChar_from_wchar(szQuery
);
363 TRACE("(%p, %s, %p)\n", node
, wine_dbgstr_w(szQuery
), out
);
366 if (This
== NULL
|| ctxt
== NULL
|| str
== NULL
)
372 This
->lpVtbl
= &queryresult_vtbl
;
376 xmldoc_add_ref(This
->node
->doc
);
379 This
->result
= xmlXPathEval(str
, ctxt
);
380 if (!This
->result
|| This
->result
->type
!= XPATH_NODESET
)
386 init_dispex(&This
->dispex
, (IUnknown
*)&This
->lpVtbl
, &queryresult_dispex
);
388 *out
= (IXMLDOMNodeList
*) &This
->lpVtbl
;
390 TRACE("found %d matches\n", xmlXPathNodeSetGetLength(This
->result
->nodesetval
));
393 if (This
!= NULL
&& FAILED(hr
))
394 IXMLDOMNodeList_Release( (IXMLDOMNodeList
*) &This
->lpVtbl
);
396 xmlXPathFreeContext(ctxt
);
397 HeapFree(GetProcessHeap(), 0, str
);