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
29 # include <libxml/parser.h>
30 # include <libxml/xmlerror.h>
31 # include <libxml/xpath.h>
32 # include <libxml/xpathInternals.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
);
58 int registerNamespaces(xmlXPathContextPtr ctxt
);
59 xmlChar
* XSLPattern_to_XPath(xmlXPathContextPtr ctxt
, xmlChar
const* xslpat_str
);
61 typedef struct _enumvariant
63 IEnumVARIANT IEnumVARIANT_iface
;
66 IXMLDOMSelection
*selection
;
72 typedef struct _domselection
75 IXMLDOMSelection IXMLDOMSelection_iface
;
78 xmlXPathObjectPtr result
;
80 IEnumVARIANT
*enumvariant
;
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
,
100 domselection
*This
= impl_from_IXMLDOMSelection( iface
);
102 TRACE("(%p)->(%s %p)\n", iface
, debugstr_guid(riid
), ppvObject
);
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
;
129 TRACE("interface %s not implemented\n", debugstr_guid(riid
));
131 return E_NOINTERFACE
;
134 IXMLDOMSelection_AddRef( iface
);
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
);
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
);
157 xmlXPathFreeObject(This
->result
);
158 xmldoc_release(This
->node
->doc
);
159 if (This
->enumvariant
) IEnumVARIANT_Release(This
->enumvariant
);
160 release_dispex(&This
->dispex
);
167 static HRESULT WINAPI
domselection_GetTypeInfoCount(
168 IXMLDOMSelection
*iface
,
171 domselection
*This
= impl_from_IXMLDOMSelection( iface
);
173 TRACE("(%p)->(%p)\n", This
, pctinfo
);
180 static HRESULT WINAPI
domselection_GetTypeInfo(
181 IXMLDOMSelection
*iface
,
184 ITypeInfo
** ppTInfo
)
186 domselection
*This
= impl_from_IXMLDOMSelection( iface
);
189 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
191 hr
= get_typeinfo(IXMLDOMSelection_tid
, ppTInfo
);
196 static HRESULT WINAPI
domselection_GetIDsOfNames(
197 IXMLDOMSelection
*iface
,
204 domselection
*This
= impl_from_IXMLDOMSelection( iface
);
208 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
,
211 if(!rgszNames
|| cNames
== 0 || !rgDispId
)
214 hr
= get_typeinfo(IXMLDOMSelection_tid
, &typeinfo
);
217 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
218 ITypeInfo_Release(typeinfo
);
224 static HRESULT WINAPI
domselection_Invoke(
225 IXMLDOMSelection
*iface
,
230 DISPPARAMS
* pDispParams
,
232 EXCEPINFO
* pExcepInfo
,
235 domselection
*This
= impl_from_IXMLDOMSelection( iface
);
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
);
245 hr
= ITypeInfo_Invoke(typeinfo
, &This
->IXMLDOMSelection_iface
, dispIdMember
, wFlags
, pDispParams
,
246 pVarResult
, pExcepInfo
, puArgErr
);
247 ITypeInfo_Release(typeinfo
);
253 static HRESULT WINAPI
domselection_get_item(
254 IXMLDOMSelection
* iface
,
256 IXMLDOMNode
** listItem
)
258 domselection
*This
= impl_from_IXMLDOMSelection( iface
);
260 TRACE("(%p)->(%d %p)\n", This
, index
, listItem
);
267 if (index
< 0 || index
>= xmlXPathNodeSetGetLength(This
->result
->nodesetval
))
270 *listItem
= create_node(xmlXPathNodeSetItem(This
->result
->nodesetval
, index
));
271 This
->resultPos
= index
+ 1;
276 static HRESULT WINAPI
domselection_get_length(
277 IXMLDOMSelection
* iface
,
280 domselection
*This
= impl_from_IXMLDOMSelection( iface
);
282 TRACE("(%p)->(%p)\n", This
, listLength
);
287 *listLength
= xmlXPathNodeSetGetLength(This
->result
->nodesetval
);
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
);
304 if (This
->resultPos
>= xmlXPathNodeSetGetLength(This
->result
->nodesetval
))
307 *nextItem
= create_node(xmlXPathNodeSetItem(This
->result
->nodesetval
, This
->resultPos
));
312 static HRESULT WINAPI
domselection_reset(
313 IXMLDOMSelection
* iface
)
315 domselection
*This
= impl_from_IXMLDOMSelection( iface
);
322 static HRESULT WINAPI
domselection_get__newEnum(
323 IXMLDOMSelection
* iface
,
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
,
337 domselection
*This
= impl_from_IXMLDOMSelection( iface
);
338 FIXME("(%p)->(%p)\n", This
, p
);
342 static HRESULT WINAPI
domselection_put_expr(
343 IXMLDOMSelection
* iface
,
346 domselection
*This
= impl_from_IXMLDOMSelection( iface
);
347 FIXME("(%p)->(%s)\n", This
, debugstr_w(p
));
351 static HRESULT WINAPI
domselection_get_context(
352 IXMLDOMSelection
* iface
,
355 domselection
*This
= impl_from_IXMLDOMSelection( iface
);
356 FIXME("(%p)->(%p)\n", This
, node
);
360 static HRESULT WINAPI
domselection_putref_context(
361 IXMLDOMSelection
* iface
,
364 domselection
*This
= impl_from_IXMLDOMSelection( iface
);
365 FIXME("(%p)->(%p)\n", This
, node
);
369 static HRESULT WINAPI
domselection_peekNode(
370 IXMLDOMSelection
* iface
,
373 domselection
*This
= impl_from_IXMLDOMSelection( iface
);
374 FIXME("(%p)->(%p)\n", This
, node
);
378 static HRESULT WINAPI
domselection_matches(
379 IXMLDOMSelection
* iface
,
381 IXMLDOMNode
**out_node
)
383 domselection
*This
= impl_from_IXMLDOMSelection( iface
);
384 FIXME("(%p)->(%p %p)\n", This
, node
, out_node
);
388 static HRESULT WINAPI
domselection_removeNext(
389 IXMLDOMSelection
* iface
,
392 domselection
*This
= impl_from_IXMLDOMSelection( iface
);
393 FIXME("(%p)->(%p)\n", This
, node
);
397 static HRESULT WINAPI
domselection_removeAll(
398 IXMLDOMSelection
* iface
)
400 domselection
*This
= impl_from_IXMLDOMSelection( iface
);
401 FIXME("(%p)\n", This
);
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
);
414 static HRESULT WINAPI
domselection_getProperty(
415 IXMLDOMSelection
* iface
,
419 domselection
*This
= impl_from_IXMLDOMSelection( iface
);
420 FIXME("(%p)->(%s %p)\n", This
, debugstr_w(p
), var
);
424 static HRESULT WINAPI
domselection_setProperty(
425 IXMLDOMSelection
* iface
,
429 domselection
*This
= impl_from_IXMLDOMSelection( iface
);
430 FIXME("(%p)->(%s %s)\n", This
, debugstr_w(p
), debugstr_variant(&var
));
434 static const struct IXMLDOMSelectionVtbl domselection_vtbl
=
436 domselection_QueryInterface
,
438 domselection_Release
,
439 domselection_GetTypeInfoCount
,
440 domselection_GetTypeInfo
,
441 domselection_GetIDsOfNames
,
443 domselection_get_item
,
444 domselection_get_length
,
445 domselection_nextNode
,
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
,
457 domselection_getProperty
,
458 domselection_setProperty
461 /* IEnumVARIANT support */
462 static HRESULT WINAPI
enumvariant_QueryInterface(
467 enumvariant
*This
= impl_from_IEnumVARIANT( iface
);
469 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppvObject
);
473 if ( IsEqualGUID( riid
, &IID_IUnknown
) ||
474 IsEqualGUID( riid
, &IID_IEnumVARIANT
))
476 *ppvObject
= &This
->IEnumVARIANT_iface
;
479 return IXMLDOMSelection_QueryInterface(This
->selection
, riid
, ppvObject
);
481 IEnumVARIANT_AddRef( iface
);
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
);
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
);
502 if (This
->own
) IXMLDOMSelection_Release(This
->selection
);
509 static HRESULT WINAPI
enumvariant_Next(
515 enumvariant
*This
= impl_from_IEnumVARIANT( iface
);
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
;
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
;
543 if (fetched
) (*fetched
)++;
545 /* we need to advance one step more for some reason */
547 IXMLDOMSelection_nextNode(This
->selection
, &node
);
549 return celt
== 0 ? S_OK
: S_FALSE
;
552 static HRESULT WINAPI
enumvariant_Skip(
556 enumvariant
*This
= impl_from_IEnumVARIANT( iface
);
557 FIXME("(%p)->(%u): stub\n", This
, celt
);
561 static HRESULT WINAPI
enumvariant_Reset(IEnumVARIANT
*iface
)
563 enumvariant
*This
= impl_from_IEnumVARIANT( iface
);
564 FIXME("(%p): stub\n", This
);
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
);
576 static const struct IEnumVARIANTVtbl EnumVARIANTVtbl
=
578 enumvariant_QueryInterface
,
587 static HRESULT
create_enumvariant(IXMLDOMSelection
*selection
, BOOL own
, IUnknown
**penum
)
591 This
= heap_alloc(sizeof(enumvariant
));
592 if (!This
) return E_OUTOFMEMORY
;
594 This
->IEnumVARIANT_iface
.lpVtbl
= &EnumVARIANTVtbl
;
596 This
->selection
= selection
;
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
);
612 for(ptr
= name
; *ptr
&& isdigitW(*ptr
); ptr
++)
613 idx
= idx
*10 + (*ptr
-'0');
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
);
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
;
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
;
647 FIXME("unimplemented flags %x\n", flags
);
652 TRACE("ret %p\n", V_DISPATCH(res
));
657 static const dispex_static_data_vtbl_t domselection_dispex_vtbl
= {
658 domselection_get_dispid
,
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
,
670 domselection_iface_tids
673 #define XSLPATTERN_CHECK_ARGS(n) \
675 FIXME("XSLPattern syntax error: Expected %i arguments, got %i\n", n, nargs); \
676 xmlXPathSetArityError(pctx); \
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
)
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);
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);
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);
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);
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);
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);
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
);
790 TRACE("(%p, %s, %p)\n", node
, wine_dbgstr_a((char const*)query
), out
);
793 if (!This
|| !ctxt
|| !query
)
795 xmlXPathFreeContext(ctxt
);
797 return E_OUTOFMEMORY
;
800 This
->IXMLDOMSelection_iface
.lpVtbl
= &domselection_vtbl
;
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
;
810 registerNamespaces(ctxt
);
812 if (is_xpathmode(This
->node
->doc
))
814 xmlXPathRegisterAllFunctions(ctxt
);
815 This
->result
= xmlXPathEvalExpression(query
, ctxt
);
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
)
845 *out
= (IXMLDOMNodeList
*)&This
->IXMLDOMSelection_iface
;
847 TRACE("found %d matches\n", xmlXPathNodeSetGetLength(This
->result
->nodesetval
));
850 if (This
&& FAILED(hr
))
851 IXMLDOMSelection_Release( &This
->IXMLDOMSelection_iface
);
852 xmlXPathFreeContext(ctxt
);