hidclass.sys: Support parsing of explicit usage page.
[wine.git] / dlls / msxml3 / selection.c
blobd05a1d6ffcb8680d7b947bdb606ef06fef9e4738
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"
40 #include "msxml2did.h"
42 #include "msxml_private.h"
44 #include "wine/debug.h"
46 /* This file implements the object returned by a XPath query. Note that this is
47 * not the IXMLDOMNodeList returned by childNodes - it's implemented in nodelist.c.
48 * They are different because the list returned by XPath queries:
49 * - is static - gives the results for the XML tree as it existed during the
50 * execution of the query
51 * - supports IXMLDOMSelection
55 #ifdef HAVE_LIBXML2
57 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
59 int registerNamespaces(xmlXPathContextPtr ctxt);
60 xmlChar* XSLPattern_to_XPath(xmlXPathContextPtr ctxt, xmlChar const* xslpat_str);
62 typedef struct
64 IEnumVARIANT IEnumVARIANT_iface;
65 LONG ref;
67 IUnknown *outer;
68 BOOL own;
70 LONG pos;
72 const struct enumvariant_funcs *funcs;
73 } enumvariant;
75 typedef struct
77 DispatchEx dispex;
78 IXMLDOMSelection IXMLDOMSelection_iface;
79 LONG ref;
80 xmlNodePtr node;
81 xmlXPathObjectPtr result;
82 int resultPos;
83 IEnumVARIANT *enumvariant;
84 } domselection;
86 static HRESULT selection_get_item(IUnknown *iface, LONG index, VARIANT* item)
88 V_VT(item) = VT_DISPATCH;
89 return IXMLDOMSelection_get_item((IXMLDOMSelection*)iface, index, (IXMLDOMNode**)&V_DISPATCH(item));
92 static HRESULT selection_next(IUnknown *iface)
94 IXMLDOMNode *node;
95 HRESULT hr = IXMLDOMSelection_nextNode((IXMLDOMSelection*)iface, &node);
96 if (hr == S_OK) IXMLDOMNode_Release(node);
97 return hr;
100 static const struct enumvariant_funcs selection_enumvariant = {
101 selection_get_item,
102 selection_next
105 static inline domselection *impl_from_IXMLDOMSelection( IXMLDOMSelection *iface )
107 return CONTAINING_RECORD(iface, domselection, IXMLDOMSelection_iface);
110 static inline enumvariant *impl_from_IEnumVARIANT( IEnumVARIANT *iface )
112 return CONTAINING_RECORD(iface, enumvariant, IEnumVARIANT_iface);
115 static HRESULT WINAPI domselection_QueryInterface(
116 IXMLDOMSelection *iface,
117 REFIID riid,
118 void** ppvObject )
120 domselection *This = impl_from_IXMLDOMSelection( iface );
122 TRACE("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppvObject);
124 if(!ppvObject)
125 return E_INVALIDARG;
127 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
128 IsEqualGUID( riid, &IID_IXMLDOMNodeList ) ||
129 IsEqualGUID( riid, &IID_IXMLDOMSelection ))
131 *ppvObject = &This->IXMLDOMSelection_iface;
133 else if (IsEqualGUID( riid, &IID_IEnumVARIANT ))
135 if (!This->enumvariant)
137 HRESULT hr = create_enumvariant((IUnknown*)iface, FALSE, &selection_enumvariant, &This->enumvariant);
138 if (FAILED(hr)) return hr;
141 return IEnumVARIANT_QueryInterface(This->enumvariant, &IID_IEnumVARIANT, ppvObject);
143 else if (dispex_query_interface(&This->dispex, riid, ppvObject))
145 return *ppvObject ? S_OK : E_NOINTERFACE;
147 else
149 TRACE("interface %s not implemented\n", debugstr_guid(riid));
150 *ppvObject = NULL;
151 return E_NOINTERFACE;
154 IXMLDOMSelection_AddRef( iface );
156 return S_OK;
159 static ULONG WINAPI domselection_AddRef(
160 IXMLDOMSelection *iface )
162 domselection *This = impl_from_IXMLDOMSelection( iface );
163 ULONG ref = InterlockedIncrement( &This->ref );
164 TRACE("(%p)->(%d)\n", This, ref);
165 return ref;
168 static ULONG WINAPI domselection_Release(
169 IXMLDOMSelection *iface )
171 domselection *This = impl_from_IXMLDOMSelection( iface );
172 ULONG ref = InterlockedDecrement(&This->ref);
174 TRACE("(%p)->(%d)\n", This, ref);
175 if ( ref == 0 )
177 xmlXPathFreeObject(This->result);
178 xmldoc_release(This->node->doc);
179 if (This->enumvariant) IEnumVARIANT_Release(This->enumvariant);
180 heap_free(This);
183 return ref;
186 static HRESULT WINAPI domselection_GetTypeInfoCount(
187 IXMLDOMSelection *iface,
188 UINT* pctinfo )
190 domselection *This = impl_from_IXMLDOMSelection( iface );
191 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
194 static HRESULT WINAPI domselection_GetTypeInfo(
195 IXMLDOMSelection *iface,
196 UINT iTInfo,
197 LCID lcid,
198 ITypeInfo** ppTInfo )
200 domselection *This = impl_from_IXMLDOMSelection( iface );
201 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface,
202 iTInfo, lcid, ppTInfo);
205 static HRESULT WINAPI domselection_GetIDsOfNames(
206 IXMLDOMSelection *iface,
207 REFIID riid,
208 LPOLESTR* rgszNames,
209 UINT cNames,
210 LCID lcid,
211 DISPID* rgDispId )
213 domselection *This = impl_from_IXMLDOMSelection( iface );
214 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface,
215 riid, rgszNames, cNames, lcid, rgDispId);
218 static HRESULT WINAPI domselection_Invoke(
219 IXMLDOMSelection *iface,
220 DISPID dispIdMember,
221 REFIID riid,
222 LCID lcid,
223 WORD wFlags,
224 DISPPARAMS* pDispParams,
225 VARIANT* pVarResult,
226 EXCEPINFO* pExcepInfo,
227 UINT* puArgErr )
229 domselection *This = impl_from_IXMLDOMSelection( iface );
230 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface,
231 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
234 static HRESULT WINAPI domselection_get_item(
235 IXMLDOMSelection* iface,
236 LONG index,
237 IXMLDOMNode** listItem)
239 domselection *This = impl_from_IXMLDOMSelection( iface );
241 TRACE("(%p)->(%d %p)\n", This, index, listItem);
243 if(!listItem)
244 return E_INVALIDARG;
246 *listItem = NULL;
248 if (index < 0 || index >= xmlXPathNodeSetGetLength(This->result->nodesetval))
249 return S_FALSE;
251 *listItem = create_node(xmlXPathNodeSetItem(This->result->nodesetval, index));
252 This->resultPos = index + 1;
254 return S_OK;
257 static HRESULT WINAPI domselection_get_length(
258 IXMLDOMSelection* iface,
259 LONG* listLength)
261 domselection *This = impl_from_IXMLDOMSelection( iface );
263 TRACE("(%p)->(%p)\n", This, listLength);
265 if(!listLength)
266 return E_INVALIDARG;
268 *listLength = xmlXPathNodeSetGetLength(This->result->nodesetval);
269 return S_OK;
272 static HRESULT WINAPI domselection_nextNode(
273 IXMLDOMSelection* iface,
274 IXMLDOMNode** nextItem)
276 domselection *This = impl_from_IXMLDOMSelection( iface );
278 TRACE("(%p)->(%p)\n", This, nextItem );
280 if(!nextItem)
281 return E_INVALIDARG;
283 *nextItem = NULL;
285 if (This->resultPos >= xmlXPathNodeSetGetLength(This->result->nodesetval))
286 return S_FALSE;
288 *nextItem = create_node(xmlXPathNodeSetItem(This->result->nodesetval, This->resultPos));
289 This->resultPos++;
290 return S_OK;
293 static HRESULT WINAPI domselection_reset(
294 IXMLDOMSelection* iface)
296 domselection *This = impl_from_IXMLDOMSelection( iface );
298 TRACE("%p\n", This);
299 This->resultPos = 0;
300 return S_OK;
303 static HRESULT WINAPI domselection_get__newEnum(
304 IXMLDOMSelection* iface,
305 IUnknown** enumv)
307 domselection *This = impl_from_IXMLDOMSelection( iface );
309 TRACE("(%p)->(%p)\n", This, enumv);
311 return create_enumvariant((IUnknown*)iface, TRUE, &selection_enumvariant, (IEnumVARIANT**)enumv);
314 static HRESULT WINAPI domselection_get_expr(
315 IXMLDOMSelection* iface,
316 BSTR *p)
318 domselection *This = impl_from_IXMLDOMSelection( iface );
319 FIXME("(%p)->(%p)\n", This, p);
320 return E_NOTIMPL;
323 static HRESULT WINAPI domselection_put_expr(
324 IXMLDOMSelection* iface,
325 BSTR p)
327 domselection *This = impl_from_IXMLDOMSelection( iface );
328 FIXME("(%p)->(%s)\n", This, debugstr_w(p));
329 return E_NOTIMPL;
332 static HRESULT WINAPI domselection_get_context(
333 IXMLDOMSelection* iface,
334 IXMLDOMNode **node)
336 domselection *This = impl_from_IXMLDOMSelection( iface );
337 FIXME("(%p)->(%p)\n", This, node);
338 return E_NOTIMPL;
341 static HRESULT WINAPI domselection_putref_context(
342 IXMLDOMSelection* iface,
343 IXMLDOMNode *node)
345 domselection *This = impl_from_IXMLDOMSelection( iface );
346 FIXME("(%p)->(%p)\n", This, node);
347 return E_NOTIMPL;
350 static HRESULT WINAPI domselection_peekNode(
351 IXMLDOMSelection* iface,
352 IXMLDOMNode **node)
354 domselection *This = impl_from_IXMLDOMSelection( iface );
355 FIXME("(%p)->(%p)\n", This, node);
356 return E_NOTIMPL;
359 static HRESULT WINAPI domselection_matches(
360 IXMLDOMSelection* iface,
361 IXMLDOMNode *node,
362 IXMLDOMNode **out_node)
364 domselection *This = impl_from_IXMLDOMSelection( iface );
365 FIXME("(%p)->(%p %p)\n", This, node, out_node);
366 return E_NOTIMPL;
369 static HRESULT WINAPI domselection_removeNext(
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_removeAll(
379 IXMLDOMSelection* iface)
381 domselection *This = impl_from_IXMLDOMSelection( iface );
382 FIXME("(%p)\n", This);
383 return E_NOTIMPL;
386 static HRESULT WINAPI domselection_clone(
387 IXMLDOMSelection* iface,
388 IXMLDOMSelection **node)
390 domselection *This = impl_from_IXMLDOMSelection( iface );
391 FIXME("(%p)->(%p)\n", This, node);
392 return E_NOTIMPL;
395 static HRESULT WINAPI domselection_getProperty(
396 IXMLDOMSelection* iface,
397 BSTR p,
398 VARIANT *var)
400 domselection *This = impl_from_IXMLDOMSelection( iface );
401 FIXME("(%p)->(%s %p)\n", This, debugstr_w(p), var);
402 return E_NOTIMPL;
405 static HRESULT WINAPI domselection_setProperty(
406 IXMLDOMSelection* iface,
407 BSTR p,
408 VARIANT var)
410 domselection *This = impl_from_IXMLDOMSelection( iface );
411 FIXME("(%p)->(%s %s)\n", This, debugstr_w(p), debugstr_variant(&var));
412 return E_NOTIMPL;
415 static const struct IXMLDOMSelectionVtbl domselection_vtbl =
417 domselection_QueryInterface,
418 domselection_AddRef,
419 domselection_Release,
420 domselection_GetTypeInfoCount,
421 domselection_GetTypeInfo,
422 domselection_GetIDsOfNames,
423 domselection_Invoke,
424 domselection_get_item,
425 domselection_get_length,
426 domselection_nextNode,
427 domselection_reset,
428 domselection_get__newEnum,
429 domselection_get_expr,
430 domselection_put_expr,
431 domselection_get_context,
432 domselection_putref_context,
433 domselection_peekNode,
434 domselection_matches,
435 domselection_removeNext,
436 domselection_removeAll,
437 domselection_clone,
438 domselection_getProperty,
439 domselection_setProperty
442 /* IEnumVARIANT support */
443 static HRESULT WINAPI enumvariant_QueryInterface(
444 IEnumVARIANT *iface,
445 REFIID riid,
446 void** ppvObject )
448 enumvariant *This = impl_from_IEnumVARIANT( iface );
450 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
452 *ppvObject = NULL;
454 if (IsEqualGUID( riid, &IID_IUnknown ))
456 if (This->own)
457 *ppvObject = &This->IEnumVARIANT_iface;
458 else
459 return IUnknown_QueryInterface(This->outer, riid, ppvObject);
461 else if (IsEqualGUID( riid, &IID_IEnumVARIANT ))
463 *ppvObject = &This->IEnumVARIANT_iface;
465 else
466 return IUnknown_QueryInterface(This->outer, riid, ppvObject);
468 IEnumVARIANT_AddRef( iface );
470 return S_OK;
473 static ULONG WINAPI enumvariant_AddRef(IEnumVARIANT *iface )
475 enumvariant *This = impl_from_IEnumVARIANT( iface );
476 ULONG ref = InterlockedIncrement( &This->ref );
477 TRACE("(%p)->(%d)\n", This, ref);
478 return ref;
481 static ULONG WINAPI enumvariant_Release(IEnumVARIANT *iface )
483 enumvariant *This = impl_from_IEnumVARIANT( iface );
484 ULONG ref = InterlockedDecrement(&This->ref);
486 TRACE("(%p)->(%d)\n", This, ref);
487 if ( ref == 0 )
489 if (This->own) IUnknown_Release(This->outer);
490 heap_free(This);
493 return ref;
496 static HRESULT WINAPI enumvariant_Next(
497 IEnumVARIANT *iface,
498 ULONG celt,
499 VARIANT *var,
500 ULONG *fetched)
502 enumvariant *This = impl_from_IEnumVARIANT( iface );
503 ULONG ret_count = 0;
505 TRACE("(%p)->(%u %p %p)\n", This, celt, var, fetched);
507 if (fetched) *fetched = 0;
509 if (celt && !var) return E_INVALIDARG;
511 for (; celt > 0; celt--, var++, This->pos++)
513 HRESULT hr = This->funcs->get_item(This->outer, This->pos, var);
514 if (hr != S_OK)
516 V_VT(var) = VT_EMPTY;
517 break;
519 ret_count++;
522 if (fetched) *fetched = ret_count;
524 /* we need to advance one step more for some reason */
525 if (ret_count)
527 if (This->funcs->next)
528 This->funcs->next(This->outer);
531 return celt == 0 ? S_OK : S_FALSE;
534 static HRESULT WINAPI enumvariant_Skip(
535 IEnumVARIANT *iface,
536 ULONG celt)
538 enumvariant *This = impl_from_IEnumVARIANT( iface );
539 FIXME("(%p)->(%u): stub\n", This, celt);
540 return E_NOTIMPL;
543 static HRESULT WINAPI enumvariant_Reset(IEnumVARIANT *iface)
545 enumvariant *This = impl_from_IEnumVARIANT( iface );
547 TRACE("%p\n", This);
548 This->pos = 0;
549 return S_OK;
552 static HRESULT WINAPI enumvariant_Clone(
553 IEnumVARIANT *iface, IEnumVARIANT **ppenum)
555 enumvariant *This = impl_from_IEnumVARIANT( iface );
556 FIXME("(%p)->(%p): stub\n", This, ppenum);
557 return E_NOTIMPL;
560 static const struct IEnumVARIANTVtbl EnumVARIANTVtbl =
562 enumvariant_QueryInterface,
563 enumvariant_AddRef,
564 enumvariant_Release,
565 enumvariant_Next,
566 enumvariant_Skip,
567 enumvariant_Reset,
568 enumvariant_Clone
571 HRESULT create_enumvariant(IUnknown *outer, BOOL own, const struct enumvariant_funcs *funcs, IEnumVARIANT **penum)
573 enumvariant *This;
575 This = heap_alloc(sizeof(enumvariant));
576 if (!This) return E_OUTOFMEMORY;
578 This->IEnumVARIANT_iface.lpVtbl = &EnumVARIANTVtbl;
579 This->ref = 0;
580 This->outer = outer;
581 This->own = own;
582 This->pos = 0;
583 This->funcs = funcs;
585 if (This->own)
586 IUnknown_AddRef(This->outer);
588 *penum = &This->IEnumVARIANT_iface;
589 IEnumVARIANT_AddRef(*penum);
590 return S_OK;
593 static HRESULT domselection_get_dispid(IUnknown *iface, BSTR name, DWORD flags, DISPID *dispid)
595 WCHAR *ptr;
596 int idx = 0;
598 for(ptr = name; *ptr >= '0' && *ptr <= '9'; ptr++)
599 idx = idx*10 + (*ptr-'0');
600 if(*ptr)
601 return DISP_E_UNKNOWNNAME;
603 *dispid = DISPID_DOM_COLLECTION_BASE + idx;
604 TRACE("ret %x\n", *dispid);
605 return S_OK;
608 static HRESULT domselection_invoke(IUnknown *iface, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params,
609 VARIANT *res, EXCEPINFO *ei)
611 domselection *This = impl_from_IXMLDOMSelection( (IXMLDOMSelection*)iface );
613 TRACE("(%p)->(%x %x %x %p %p %p)\n", This, id, lcid, flags, params, res, ei);
615 V_VT(res) = VT_DISPATCH;
616 V_DISPATCH(res) = NULL;
618 if (id < DISPID_DOM_COLLECTION_BASE || id > DISPID_DOM_COLLECTION_MAX)
619 return DISP_E_UNKNOWNNAME;
621 switch(flags)
623 case INVOKE_PROPERTYGET:
625 IXMLDOMNode *disp = NULL;
627 IXMLDOMSelection_get_item(&This->IXMLDOMSelection_iface, id - DISPID_DOM_COLLECTION_BASE, &disp);
628 V_DISPATCH(res) = (IDispatch*)disp;
629 break;
631 default:
633 FIXME("unimplemented flags %x\n", flags);
634 break;
638 TRACE("ret %p\n", V_DISPATCH(res));
640 return S_OK;
643 static const dispex_static_data_vtbl_t domselection_dispex_vtbl = {
644 domselection_get_dispid,
645 domselection_invoke
648 static const tid_t domselection_iface_tids[] = {
649 IXMLDOMSelection_tid,
652 static dispex_static_data_t domselection_dispex = {
653 &domselection_dispex_vtbl,
654 IXMLDOMSelection_tid,
655 NULL,
656 domselection_iface_tids
659 #define XSLPATTERN_CHECK_ARGS(n) \
660 if (nargs != n) { \
661 FIXME("XSLPattern syntax error: Expected %i arguments, got %i\n", n, nargs); \
662 xmlXPathSetArityError(pctx); \
663 return; \
667 static void XSLPattern_index(xmlXPathParserContextPtr pctx, int nargs)
669 XSLPATTERN_CHECK_ARGS(0);
671 xmlXPathPositionFunction(pctx, 0);
672 xmlXPathReturnNumber(pctx, xmlXPathPopNumber(pctx) - 1.0);
675 static void XSLPattern_end(xmlXPathParserContextPtr pctx, int nargs)
677 double pos, last;
678 XSLPATTERN_CHECK_ARGS(0);
680 xmlXPathPositionFunction(pctx, 0);
681 pos = xmlXPathPopNumber(pctx);
682 xmlXPathLastFunction(pctx, 0);
683 last = xmlXPathPopNumber(pctx);
684 xmlXPathReturnBoolean(pctx, pos == last);
687 static void XSLPattern_nodeType(xmlXPathParserContextPtr pctx, int nargs)
689 XSLPATTERN_CHECK_ARGS(0);
690 xmlXPathReturnNumber(pctx, pctx->context->node->type);
693 static void XSLPattern_OP_IEq(xmlXPathParserContextPtr pctx, int nargs)
695 xmlChar *arg1, *arg2;
696 XSLPATTERN_CHECK_ARGS(2);
698 arg2 = xmlXPathPopString(pctx);
699 arg1 = xmlXPathPopString(pctx);
700 xmlXPathReturnBoolean(pctx, xmlStrcasecmp(arg1, arg2) == 0);
701 xmlFree(arg1);
702 xmlFree(arg2);
705 static void XSLPattern_OP_INEq(xmlXPathParserContextPtr pctx, int nargs)
707 xmlChar *arg1, *arg2;
708 XSLPATTERN_CHECK_ARGS(2);
710 arg2 = xmlXPathPopString(pctx);
711 arg1 = xmlXPathPopString(pctx);
712 xmlXPathReturnBoolean(pctx, xmlStrcasecmp(arg1, arg2) != 0);
713 xmlFree(arg1);
714 xmlFree(arg2);
717 static void XSLPattern_OP_ILt(xmlXPathParserContextPtr pctx, int nargs)
719 xmlChar *arg1, *arg2;
720 XSLPATTERN_CHECK_ARGS(2);
722 arg2 = xmlXPathPopString(pctx);
723 arg1 = xmlXPathPopString(pctx);
724 xmlXPathReturnBoolean(pctx, xmlStrcasecmp(arg1, arg2) < 0);
725 xmlFree(arg1);
726 xmlFree(arg2);
729 static void XSLPattern_OP_ILEq(xmlXPathParserContextPtr pctx, int nargs)
731 xmlChar *arg1, *arg2;
732 XSLPATTERN_CHECK_ARGS(2);
734 arg2 = xmlXPathPopString(pctx);
735 arg1 = xmlXPathPopString(pctx);
736 xmlXPathReturnBoolean(pctx, xmlStrcasecmp(arg1, arg2) <= 0);
737 xmlFree(arg1);
738 xmlFree(arg2);
741 static void XSLPattern_OP_IGt(xmlXPathParserContextPtr pctx, int nargs)
743 xmlChar *arg1, *arg2;
744 XSLPATTERN_CHECK_ARGS(2);
746 arg2 = xmlXPathPopString(pctx);
747 arg1 = xmlXPathPopString(pctx);
748 xmlXPathReturnBoolean(pctx, xmlStrcasecmp(arg1, arg2) > 0);
749 xmlFree(arg1);
750 xmlFree(arg2);
753 static void XSLPattern_OP_IGEq(xmlXPathParserContextPtr pctx, int nargs)
755 xmlChar *arg1, *arg2;
756 XSLPATTERN_CHECK_ARGS(2);
758 arg2 = xmlXPathPopString(pctx);
759 arg1 = xmlXPathPopString(pctx);
760 xmlXPathReturnBoolean(pctx, xmlStrcasecmp(arg1, arg2) >= 0);
761 xmlFree(arg1);
762 xmlFree(arg2);
765 static void query_serror(void* ctx, xmlErrorPtr err)
767 LIBXML2_CALLBACK_SERROR(domselection_create, err);
770 HRESULT create_selection(xmlNodePtr node, xmlChar* query, IXMLDOMNodeList **out)
772 domselection *This = heap_alloc(sizeof(domselection));
773 xmlXPathContextPtr ctxt = xmlXPathNewContext(node->doc);
774 HRESULT hr;
776 TRACE("(%p, %s, %p)\n", node, debugstr_a((char const*)query), out);
778 *out = NULL;
779 if (!This || !ctxt || !query)
781 xmlXPathFreeContext(ctxt);
782 heap_free(This);
783 return E_OUTOFMEMORY;
786 This->IXMLDOMSelection_iface.lpVtbl = &domselection_vtbl;
787 This->ref = 1;
788 This->resultPos = 0;
789 This->node = node;
790 This->enumvariant = NULL;
791 init_dispex(&This->dispex, (IUnknown*)&This->IXMLDOMSelection_iface, &domselection_dispex);
792 xmldoc_add_ref(This->node->doc);
794 ctxt->error = query_serror;
795 ctxt->node = node;
796 registerNamespaces(ctxt);
798 if (is_xpathmode(This->node->doc))
800 xmlXPathRegisterAllFunctions(ctxt);
801 This->result = xmlXPathEvalExpression(query, ctxt);
803 else
805 xmlChar* pattern_query = XSLPattern_to_XPath(ctxt, query);
807 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"not", xmlXPathNotFunction);
808 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"boolean", xmlXPathBooleanFunction);
810 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"index", XSLPattern_index);
811 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"end", XSLPattern_end);
812 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"nodeType", XSLPattern_nodeType);
814 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"OP_IEq", XSLPattern_OP_IEq);
815 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"OP_INEq", XSLPattern_OP_INEq);
816 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"OP_ILt", XSLPattern_OP_ILt);
817 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"OP_ILEq", XSLPattern_OP_ILEq);
818 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"OP_IGt", XSLPattern_OP_IGt);
819 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"OP_IGEq", XSLPattern_OP_IGEq);
821 This->result = xmlXPathEvalExpression(pattern_query, ctxt);
822 xmlFree(pattern_query);
825 if (!This->result || This->result->type != XPATH_NODESET)
827 hr = E_FAIL;
828 goto cleanup;
831 *out = (IXMLDOMNodeList*)&This->IXMLDOMSelection_iface;
832 hr = S_OK;
833 TRACE("found %d matches\n", xmlXPathNodeSetGetLength(This->result->nodesetval));
835 cleanup:
836 if (FAILED(hr))
837 IXMLDOMSelection_Release( &This->IXMLDOMSelection_iface );
838 xmlXPathFreeContext(ctxt);
839 return hr;
842 #endif