msxml3: Implement IEnumVARIANT::Next() for IXMLDOMSelection.
[wine/multimedia.git] / dlls / msxml3 / selection.c
blob31137f34ff49629b8f9786eb03bf268352fa8e35
1 /*
2 * XPath/XSLPattern query result node list implementation
4 * Copyright 2005 Mike McCormack
5 * Copyright 2007 Mikolaj Zalewski
6 * Copyright 2010 Adam Martinson for CodeWeavers
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #define COBJMACROS
25 #include "config.h"
27 #include <stdarg.h>
28 #ifdef HAVE_LIBXML2
29 # include <libxml/parser.h>
30 # include <libxml/xmlerror.h>
31 # include <libxml/xpath.h>
32 # include <libxml/xpathInternals.h>
33 #endif
35 #include "windef.h"
36 #include "winbase.h"
37 #include "winuser.h"
38 #include "ole2.h"
39 #include "msxml6.h"
41 #include "msxml_private.h"
43 #include "wine/debug.h"
45 /* This file implements the object returned by a XPath query. Note that this is
46 * not the IXMLDOMNodeList returned by childNodes - it's implemented in nodelist.c.
47 * They are different because the list returned by XPath queries:
48 * - is static - gives the results for the XML tree as it existed during the
49 * execution of the query
50 * - supports IXMLDOMSelection
54 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
56 #ifdef HAVE_LIBXML2
58 int registerNamespaces(xmlXPathContextPtr ctxt);
59 xmlChar* XSLPattern_to_XPath(xmlXPathContextPtr ctxt, xmlChar const* xslpat_str);
61 typedef struct _enumvariant
63 IEnumVARIANT IEnumVARIANT_iface;
64 LONG ref;
66 IXMLDOMSelection *selection;
67 BOOL own;
69 LONG pos;
70 } enumvariant;
72 typedef struct _domselection
74 DispatchEx dispex;
75 IXMLDOMSelection IXMLDOMSelection_iface;
76 LONG ref;
77 xmlNodePtr node;
78 xmlXPathObjectPtr result;
79 int resultPos;
80 IEnumVARIANT *enumvariant;
81 } domselection;
83 static inline domselection *impl_from_IXMLDOMSelection( IXMLDOMSelection *iface )
85 return CONTAINING_RECORD(iface, domselection, IXMLDOMSelection_iface);
88 static inline enumvariant *impl_from_IEnumVARIANT( IEnumVARIANT *iface )
90 return CONTAINING_RECORD(iface, enumvariant, IEnumVARIANT_iface);
93 static HRESULT create_enumvariant(IXMLDOMSelection*, BOOL, IUnknown**);
95 static HRESULT WINAPI domselection_QueryInterface(
96 IXMLDOMSelection *iface,
97 REFIID riid,
98 void** ppvObject )
100 domselection *This = impl_from_IXMLDOMSelection( iface );
102 TRACE("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppvObject);
104 if(!ppvObject)
105 return E_INVALIDARG;
107 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
108 IsEqualGUID( riid, &IID_IXMLDOMNodeList ) ||
109 IsEqualGUID( riid, &IID_IXMLDOMSelection ))
111 *ppvObject = &This->IXMLDOMSelection_iface;
113 else if (IsEqualGUID( riid, &IID_IEnumVARIANT ))
115 if (!This->enumvariant)
117 HRESULT hr = create_enumvariant(iface, FALSE, (IUnknown**)&This->enumvariant);
118 if (FAILED(hr)) return hr;
121 return IEnumVARIANT_QueryInterface(This->enumvariant, &IID_IEnumVARIANT, ppvObject);
123 else if (dispex_query_interface(&This->dispex, riid, ppvObject))
125 return *ppvObject ? S_OK : E_NOINTERFACE;
127 else
129 TRACE("interface %s not implemented\n", debugstr_guid(riid));
130 *ppvObject = NULL;
131 return E_NOINTERFACE;
134 IXMLDOMSelection_AddRef( iface );
136 return S_OK;
139 static ULONG WINAPI domselection_AddRef(
140 IXMLDOMSelection *iface )
142 domselection *This = impl_from_IXMLDOMSelection( iface );
143 ULONG ref = InterlockedIncrement( &This->ref );
144 TRACE("(%p)->(%d)\n", This, ref);
145 return ref;
148 static ULONG WINAPI domselection_Release(
149 IXMLDOMSelection *iface )
151 domselection *This = impl_from_IXMLDOMSelection( iface );
152 ULONG ref = InterlockedDecrement(&This->ref);
154 TRACE("(%p)->(%d)\n", This, ref);
155 if ( ref == 0 )
157 xmlXPathFreeObject(This->result);
158 xmldoc_release(This->node->doc);
159 if (This->enumvariant) IEnumVARIANT_Release(This->enumvariant);
160 release_dispex(&This->dispex);
161 heap_free(This);
164 return ref;
167 static HRESULT WINAPI domselection_GetTypeInfoCount(
168 IXMLDOMSelection *iface,
169 UINT* pctinfo )
171 domselection *This = impl_from_IXMLDOMSelection( iface );
173 TRACE("(%p)->(%p)\n", This, pctinfo);
175 *pctinfo = 1;
177 return S_OK;
180 static HRESULT WINAPI domselection_GetTypeInfo(
181 IXMLDOMSelection *iface,
182 UINT iTInfo,
183 LCID lcid,
184 ITypeInfo** ppTInfo )
186 domselection *This = impl_from_IXMLDOMSelection( iface );
187 HRESULT hr;
189 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
191 hr = get_typeinfo(IXMLDOMSelection_tid, ppTInfo);
193 return hr;
196 static HRESULT WINAPI domselection_GetIDsOfNames(
197 IXMLDOMSelection *iface,
198 REFIID riid,
199 LPOLESTR* rgszNames,
200 UINT cNames,
201 LCID lcid,
202 DISPID* rgDispId )
204 domselection *This = impl_from_IXMLDOMSelection( iface );
205 ITypeInfo *typeinfo;
206 HRESULT hr;
208 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
209 lcid, rgDispId);
211 if(!rgszNames || cNames == 0 || !rgDispId)
212 return E_INVALIDARG;
214 hr = get_typeinfo(IXMLDOMSelection_tid, &typeinfo);
215 if(SUCCEEDED(hr))
217 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
218 ITypeInfo_Release(typeinfo);
221 return hr;
224 static HRESULT WINAPI domselection_Invoke(
225 IXMLDOMSelection *iface,
226 DISPID dispIdMember,
227 REFIID riid,
228 LCID lcid,
229 WORD wFlags,
230 DISPPARAMS* pDispParams,
231 VARIANT* pVarResult,
232 EXCEPINFO* pExcepInfo,
233 UINT* puArgErr )
235 domselection *This = impl_from_IXMLDOMSelection( iface );
236 ITypeInfo *typeinfo;
237 HRESULT hr;
239 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
240 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
242 hr = get_typeinfo(IXMLDOMSelection_tid, &typeinfo);
243 if(SUCCEEDED(hr))
245 hr = ITypeInfo_Invoke(typeinfo, &This->IXMLDOMSelection_iface, dispIdMember, wFlags, pDispParams,
246 pVarResult, pExcepInfo, puArgErr);
247 ITypeInfo_Release(typeinfo);
250 return hr;
253 static HRESULT WINAPI domselection_get_item(
254 IXMLDOMSelection* iface,
255 LONG index,
256 IXMLDOMNode** listItem)
258 domselection *This = impl_from_IXMLDOMSelection( iface );
260 TRACE("(%p)->(%d %p)\n", This, index, listItem);
262 if(!listItem)
263 return E_INVALIDARG;
265 *listItem = NULL;
267 if (index < 0 || index >= xmlXPathNodeSetGetLength(This->result->nodesetval))
268 return S_FALSE;
270 *listItem = create_node(xmlXPathNodeSetItem(This->result->nodesetval, index));
271 This->resultPos = index + 1;
273 return S_OK;
276 static HRESULT WINAPI domselection_get_length(
277 IXMLDOMSelection* iface,
278 LONG* listLength)
280 domselection *This = impl_from_IXMLDOMSelection( iface );
282 TRACE("(%p)->(%p)\n", This, listLength);
284 if(!listLength)
285 return E_INVALIDARG;
287 *listLength = xmlXPathNodeSetGetLength(This->result->nodesetval);
288 return S_OK;
291 static HRESULT WINAPI domselection_nextNode(
292 IXMLDOMSelection* iface,
293 IXMLDOMNode** nextItem)
295 domselection *This = impl_from_IXMLDOMSelection( iface );
297 TRACE("(%p)->(%p)\n", This, nextItem );
299 if(!nextItem)
300 return E_INVALIDARG;
302 *nextItem = NULL;
304 if (This->resultPos >= xmlXPathNodeSetGetLength(This->result->nodesetval))
305 return S_FALSE;
307 *nextItem = create_node(xmlXPathNodeSetItem(This->result->nodesetval, This->resultPos));
308 This->resultPos++;
309 return S_OK;
312 static HRESULT WINAPI domselection_reset(
313 IXMLDOMSelection* iface)
315 domselection *This = impl_from_IXMLDOMSelection( iface );
317 TRACE("%p\n", This);
318 This->resultPos = 0;
319 return S_OK;
322 static HRESULT WINAPI domselection_get__newEnum(
323 IXMLDOMSelection* iface,
324 IUnknown** ppUnk)
326 domselection *This = impl_from_IXMLDOMSelection( iface );
328 TRACE("(%p)->(%p)\n", This, ppUnk);
330 return create_enumvariant(iface, TRUE, ppUnk);
333 static HRESULT WINAPI domselection_get_expr(
334 IXMLDOMSelection* iface,
335 BSTR *p)
337 domselection *This = impl_from_IXMLDOMSelection( iface );
338 FIXME("(%p)->(%p)\n", This, p);
339 return E_NOTIMPL;
342 static HRESULT WINAPI domselection_put_expr(
343 IXMLDOMSelection* iface,
344 BSTR p)
346 domselection *This = impl_from_IXMLDOMSelection( iface );
347 FIXME("(%p)->(%s)\n", This, debugstr_w(p));
348 return E_NOTIMPL;
351 static HRESULT WINAPI domselection_get_context(
352 IXMLDOMSelection* iface,
353 IXMLDOMNode **node)
355 domselection *This = impl_from_IXMLDOMSelection( iface );
356 FIXME("(%p)->(%p)\n", This, node);
357 return E_NOTIMPL;
360 static HRESULT WINAPI domselection_putref_context(
361 IXMLDOMSelection* iface,
362 IXMLDOMNode *node)
364 domselection *This = impl_from_IXMLDOMSelection( iface );
365 FIXME("(%p)->(%p)\n", This, node);
366 return E_NOTIMPL;
369 static HRESULT WINAPI domselection_peekNode(
370 IXMLDOMSelection* iface,
371 IXMLDOMNode **node)
373 domselection *This = impl_from_IXMLDOMSelection( iface );
374 FIXME("(%p)->(%p)\n", This, node);
375 return E_NOTIMPL;
378 static HRESULT WINAPI domselection_matches(
379 IXMLDOMSelection* iface,
380 IXMLDOMNode *node,
381 IXMLDOMNode **out_node)
383 domselection *This = impl_from_IXMLDOMSelection( iface );
384 FIXME("(%p)->(%p %p)\n", This, node, out_node);
385 return E_NOTIMPL;
388 static HRESULT WINAPI domselection_removeNext(
389 IXMLDOMSelection* iface,
390 IXMLDOMNode **node)
392 domselection *This = impl_from_IXMLDOMSelection( iface );
393 FIXME("(%p)->(%p)\n", This, node);
394 return E_NOTIMPL;
397 static HRESULT WINAPI domselection_removeAll(
398 IXMLDOMSelection* iface)
400 domselection *This = impl_from_IXMLDOMSelection( iface );
401 FIXME("(%p)\n", This);
402 return E_NOTIMPL;
405 static HRESULT WINAPI domselection_clone(
406 IXMLDOMSelection* iface,
407 IXMLDOMSelection **node)
409 domselection *This = impl_from_IXMLDOMSelection( iface );
410 FIXME("(%p)->(%p)\n", This, node);
411 return E_NOTIMPL;
414 static HRESULT WINAPI domselection_getProperty(
415 IXMLDOMSelection* iface,
416 BSTR p,
417 VARIANT *var)
419 domselection *This = impl_from_IXMLDOMSelection( iface );
420 FIXME("(%p)->(%s %p)\n", This, debugstr_w(p), var);
421 return E_NOTIMPL;
424 static HRESULT WINAPI domselection_setProperty(
425 IXMLDOMSelection* iface,
426 BSTR p,
427 VARIANT var)
429 domselection *This = impl_from_IXMLDOMSelection( iface );
430 FIXME("(%p)->(%s %s)\n", This, debugstr_w(p), debugstr_variant(&var));
431 return E_NOTIMPL;
434 static const struct IXMLDOMSelectionVtbl domselection_vtbl =
436 domselection_QueryInterface,
437 domselection_AddRef,
438 domselection_Release,
439 domselection_GetTypeInfoCount,
440 domselection_GetTypeInfo,
441 domselection_GetIDsOfNames,
442 domselection_Invoke,
443 domselection_get_item,
444 domselection_get_length,
445 domselection_nextNode,
446 domselection_reset,
447 domselection_get__newEnum,
448 domselection_get_expr,
449 domselection_put_expr,
450 domselection_get_context,
451 domselection_putref_context,
452 domselection_peekNode,
453 domselection_matches,
454 domselection_removeNext,
455 domselection_removeAll,
456 domselection_clone,
457 domselection_getProperty,
458 domselection_setProperty
461 /* IEnumVARIANT support */
462 static HRESULT WINAPI enumvariant_QueryInterface(
463 IEnumVARIANT *iface,
464 REFIID riid,
465 void** ppvObject )
467 enumvariant *This = impl_from_IEnumVARIANT( iface );
469 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
471 *ppvObject = NULL;
473 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
474 IsEqualGUID( riid, &IID_IEnumVARIANT ))
476 *ppvObject = &This->IEnumVARIANT_iface;
478 else
479 return IXMLDOMSelection_QueryInterface(This->selection, riid, ppvObject);
481 IEnumVARIANT_AddRef( iface );
483 return S_OK;
486 static ULONG WINAPI enumvariant_AddRef(IEnumVARIANT *iface )
488 enumvariant *This = impl_from_IEnumVARIANT( iface );
489 ULONG ref = InterlockedIncrement( &This->ref );
490 TRACE("(%p)->(%d)\n", This, ref);
491 return ref;
494 static ULONG WINAPI enumvariant_Release(IEnumVARIANT *iface )
496 enumvariant *This = impl_from_IEnumVARIANT( iface );
497 ULONG ref = InterlockedDecrement(&This->ref);
499 TRACE("(%p)->(%d)\n", This, ref);
500 if ( ref == 0 )
502 if (This->own) IXMLDOMSelection_Release(This->selection);
503 heap_free(This);
506 return ref;
509 static HRESULT WINAPI enumvariant_Next(
510 IEnumVARIANT *iface,
511 ULONG celt,
512 VARIANT *var,
513 ULONG *fetched)
515 enumvariant *This = impl_from_IEnumVARIANT( iface );
516 IXMLDOMNode *node;
517 ULONG ret_count = 0;
519 TRACE("(%p)->(%u %p %p)\n", This, celt, var, fetched);
521 if (fetched) *fetched = 0;
523 if (celt && !var) return E_INVALIDARG;
525 for (; celt > 0; celt--, var++, This->pos++)
527 IDispatch *disp = NULL;
528 HRESULT hr;
530 node = NULL;
531 hr = IXMLDOMSelection_get_item(This->selection, This->pos, &node);
532 if (hr != S_OK) break;
534 IXMLDOMNode_QueryInterface(node, &IID_IDispatch, (void**)&disp);
535 IXMLDOMNode_Release(node);
537 V_VT(var) = VT_DISPATCH;
538 V_DISPATCH(var) = disp;
540 ret_count++;
543 if (fetched) (*fetched)++;
545 /* we need to advance one step more for some reason */
546 if (ret_count)
547 IXMLDOMSelection_nextNode(This->selection, &node);
549 return celt == 0 ? S_OK : S_FALSE;
552 static HRESULT WINAPI enumvariant_Skip(
553 IEnumVARIANT *iface,
554 ULONG celt)
556 enumvariant *This = impl_from_IEnumVARIANT( iface );
557 FIXME("(%p)->(%u): stub\n", This, celt);
558 return E_NOTIMPL;
561 static HRESULT WINAPI enumvariant_Reset(IEnumVARIANT *iface)
563 enumvariant *This = impl_from_IEnumVARIANT( iface );
564 FIXME("(%p): stub\n", This);
565 return E_NOTIMPL;
568 static HRESULT WINAPI enumvariant_Clone(
569 IEnumVARIANT *iface, IEnumVARIANT **ppenum)
571 enumvariant *This = impl_from_IEnumVARIANT( iface );
572 FIXME("(%p)->(%p): stub\n", This, ppenum);
573 return E_NOTIMPL;
576 static const struct IEnumVARIANTVtbl EnumVARIANTVtbl =
578 enumvariant_QueryInterface,
579 enumvariant_AddRef,
580 enumvariant_Release,
581 enumvariant_Next,
582 enumvariant_Skip,
583 enumvariant_Reset,
584 enumvariant_Clone
587 static HRESULT create_enumvariant(IXMLDOMSelection *selection, BOOL own, IUnknown **penum)
589 enumvariant *This;
591 This = heap_alloc(sizeof(enumvariant));
592 if (!This) return E_OUTOFMEMORY;
594 This->IEnumVARIANT_iface.lpVtbl = &EnumVARIANTVtbl;
595 This->ref = 0;
596 This->selection = selection;
597 This->own = own;
598 This->pos = 0;
600 if (This->own)
601 IXMLDOMSelection_AddRef(selection);
603 return IEnumVARIANT_QueryInterface(&This->IEnumVARIANT_iface, &IID_IUnknown, (void**)penum);
606 static HRESULT domselection_get_dispid(IUnknown *iface, BSTR name, DWORD flags, DISPID *dispid)
608 domselection *This = impl_from_IXMLDOMSelection( (IXMLDOMSelection*)iface );
609 WCHAR *ptr;
610 int idx = 0;
612 for(ptr = name; *ptr && isdigitW(*ptr); ptr++)
613 idx = idx*10 + (*ptr-'0');
614 if(*ptr)
615 return DISP_E_UNKNOWNNAME;
617 if(idx >= xmlXPathNodeSetGetLength(This->result->nodesetval))
618 return DISP_E_UNKNOWNNAME;
620 *dispid = MSXML_DISPID_CUSTOM_MIN + idx;
621 TRACE("ret %x\n", *dispid);
622 return S_OK;
625 static HRESULT domselection_invoke(IUnknown *iface, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params,
626 VARIANT *res, EXCEPINFO *ei)
628 domselection *This = impl_from_IXMLDOMSelection( (IXMLDOMSelection*)iface );
630 TRACE("(%p)->(%x %x %x %p %p %p)\n", This, id, lcid, flags, params, res, ei);
632 V_VT(res) = VT_DISPATCH;
633 V_DISPATCH(res) = NULL;
635 switch(flags)
637 case INVOKE_PROPERTYGET:
639 IXMLDOMNode *disp = NULL;
641 domselection_get_item(&This->IXMLDOMSelection_iface, id - MSXML_DISPID_CUSTOM_MIN, &disp);
642 V_DISPATCH(res) = (IDispatch*)disp;
643 break;
645 default:
647 FIXME("unimplemented flags %x\n", flags);
648 break;
652 TRACE("ret %p\n", V_DISPATCH(res));
654 return S_OK;
657 static const dispex_static_data_vtbl_t domselection_dispex_vtbl = {
658 domselection_get_dispid,
659 domselection_invoke
662 static const tid_t domselection_iface_tids[] = {
663 IXMLDOMSelection_tid,
666 static dispex_static_data_t domselection_dispex = {
667 &domselection_dispex_vtbl,
668 IXMLDOMSelection_tid,
669 NULL,
670 domselection_iface_tids
673 #define XSLPATTERN_CHECK_ARGS(n) \
674 if (nargs != n) { \
675 FIXME("XSLPattern syntax error: Expected %i arguments, got %i\n", n, nargs); \
676 xmlXPathSetArityError(pctx); \
677 return; \
681 static void XSLPattern_index(xmlXPathParserContextPtr pctx, int nargs)
683 XSLPATTERN_CHECK_ARGS(0);
685 xmlXPathPositionFunction(pctx, 0);
686 xmlXPathReturnNumber(pctx, xmlXPathPopNumber(pctx) - 1.0);
689 static void XSLPattern_end(xmlXPathParserContextPtr pctx, int nargs)
691 double pos, last;
692 XSLPATTERN_CHECK_ARGS(0);
694 xmlXPathPositionFunction(pctx, 0);
695 pos = xmlXPathPopNumber(pctx);
696 xmlXPathLastFunction(pctx, 0);
697 last = xmlXPathPopNumber(pctx);
698 xmlXPathReturnBoolean(pctx, pos == last);
701 static void XSLPattern_nodeType(xmlXPathParserContextPtr pctx, int nargs)
703 XSLPATTERN_CHECK_ARGS(0);
704 xmlXPathReturnNumber(pctx, pctx->context->node->type);
707 static void XSLPattern_OP_IEq(xmlXPathParserContextPtr pctx, int nargs)
709 xmlChar *arg1, *arg2;
710 XSLPATTERN_CHECK_ARGS(2);
712 arg2 = xmlXPathPopString(pctx);
713 arg1 = xmlXPathPopString(pctx);
714 xmlXPathReturnBoolean(pctx, xmlStrcasecmp(arg1, arg2) == 0);
715 xmlFree(arg1);
716 xmlFree(arg2);
719 static void XSLPattern_OP_INEq(xmlXPathParserContextPtr pctx, int nargs)
721 xmlChar *arg1, *arg2;
722 XSLPATTERN_CHECK_ARGS(2);
724 arg2 = xmlXPathPopString(pctx);
725 arg1 = xmlXPathPopString(pctx);
726 xmlXPathReturnBoolean(pctx, xmlStrcasecmp(arg1, arg2) != 0);
727 xmlFree(arg1);
728 xmlFree(arg2);
731 static void XSLPattern_OP_ILt(xmlXPathParserContextPtr pctx, int nargs)
733 xmlChar *arg1, *arg2;
734 XSLPATTERN_CHECK_ARGS(2);
736 arg2 = xmlXPathPopString(pctx);
737 arg1 = xmlXPathPopString(pctx);
738 xmlXPathReturnBoolean(pctx, xmlStrcasecmp(arg1, arg2) < 0);
739 xmlFree(arg1);
740 xmlFree(arg2);
743 static void XSLPattern_OP_ILEq(xmlXPathParserContextPtr pctx, int nargs)
745 xmlChar *arg1, *arg2;
746 XSLPATTERN_CHECK_ARGS(2);
748 arg2 = xmlXPathPopString(pctx);
749 arg1 = xmlXPathPopString(pctx);
750 xmlXPathReturnBoolean(pctx, xmlStrcasecmp(arg1, arg2) <= 0);
751 xmlFree(arg1);
752 xmlFree(arg2);
755 static void XSLPattern_OP_IGt(xmlXPathParserContextPtr pctx, int nargs)
757 xmlChar *arg1, *arg2;
758 XSLPATTERN_CHECK_ARGS(2);
760 arg2 = xmlXPathPopString(pctx);
761 arg1 = xmlXPathPopString(pctx);
762 xmlXPathReturnBoolean(pctx, xmlStrcasecmp(arg1, arg2) > 0);
763 xmlFree(arg1);
764 xmlFree(arg2);
767 static void XSLPattern_OP_IGEq(xmlXPathParserContextPtr pctx, int nargs)
769 xmlChar *arg1, *arg2;
770 XSLPATTERN_CHECK_ARGS(2);
772 arg2 = xmlXPathPopString(pctx);
773 arg1 = xmlXPathPopString(pctx);
774 xmlXPathReturnBoolean(pctx, xmlStrcasecmp(arg1, arg2) >= 0);
775 xmlFree(arg1);
776 xmlFree(arg2);
779 static void query_serror(void* ctx, xmlErrorPtr err)
781 LIBXML2_CALLBACK_SERROR(domselection_create, err);
784 HRESULT create_selection(xmlNodePtr node, xmlChar* query, IXMLDOMNodeList **out)
786 domselection *This = heap_alloc(sizeof(domselection));
787 xmlXPathContextPtr ctxt = xmlXPathNewContext(node->doc);
788 HRESULT hr;
790 TRACE("(%p, %s, %p)\n", node, wine_dbgstr_a((char const*)query), out);
792 *out = NULL;
793 if (!This || !ctxt || !query)
795 xmlXPathFreeContext(ctxt);
796 heap_free(This);
797 return E_OUTOFMEMORY;
800 This->IXMLDOMSelection_iface.lpVtbl = &domselection_vtbl;
801 This->ref = 1;
802 This->resultPos = 0;
803 This->node = node;
804 This->enumvariant = NULL;
805 init_dispex(&This->dispex, (IUnknown*)&This->IXMLDOMSelection_iface, &domselection_dispex);
806 xmldoc_add_ref(This->node->doc);
808 ctxt->error = query_serror;
809 ctxt->node = node;
810 registerNamespaces(ctxt);
812 if (is_xpathmode(This->node->doc))
814 xmlXPathRegisterAllFunctions(ctxt);
815 This->result = xmlXPathEvalExpression(query, ctxt);
817 else
819 xmlChar* pattern_query = XSLPattern_to_XPath(ctxt, query);
821 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"not", xmlXPathNotFunction);
822 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"boolean", xmlXPathBooleanFunction);
824 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"index", XSLPattern_index);
825 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"end", XSLPattern_end);
826 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"nodeType", XSLPattern_nodeType);
828 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"OP_IEq", XSLPattern_OP_IEq);
829 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"OP_INEq", XSLPattern_OP_INEq);
830 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"OP_ILt", XSLPattern_OP_ILt);
831 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"OP_ILEq", XSLPattern_OP_ILEq);
832 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"OP_IGt", XSLPattern_OP_IGt);
833 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"OP_IGEq", XSLPattern_OP_IGEq);
835 This->result = xmlXPathEvalExpression(pattern_query, ctxt);
836 xmlFree(pattern_query);
839 if (!This->result || This->result->type != XPATH_NODESET)
841 hr = E_FAIL;
842 goto cleanup;
845 *out = (IXMLDOMNodeList*)&This->IXMLDOMSelection_iface;
846 hr = S_OK;
847 TRACE("found %d matches\n", xmlXPathNodeSetGetLength(This->result->nodesetval));
849 cleanup:
850 if (This && FAILED(hr))
851 IXMLDOMSelection_Release( &This->IXMLDOMSelection_iface );
852 xmlXPathFreeContext(ctxt);
853 return hr;
856 #endif