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 WIN32_NO_STATUS
32 //# include <libxml/parser.h>
33 //# include <libxml/xmlerror.h>
34 //# include <libxml/xpath.h>
35 # include <libxml/xpathInternals.h>
40 //#include "winuser.h"
43 #include <msxml2did.h>
45 #include "msxml_private.h"
47 #include <wine/debug.h>
49 /* This file implements the object returned by a XPath query. Note that this is
50 * not the IXMLDOMNodeList returned by childNodes - it's implemented in nodelist.c.
51 * They are different because the list returned by XPath queries:
52 * - is static - gives the results for the XML tree as it existed during the
53 * execution of the query
54 * - supports IXMLDOMSelection
58 WINE_DEFAULT_DEBUG_CHANNEL(msxml
);
62 int registerNamespaces(xmlXPathContextPtr ctxt
);
63 xmlChar
* XSLPattern_to_XPath(xmlXPathContextPtr ctxt
, xmlChar
const* xslpat_str
);
67 IEnumVARIANT IEnumVARIANT_iface
;
75 const struct enumvariant_funcs
*funcs
;
81 IXMLDOMSelection IXMLDOMSelection_iface
;
84 xmlXPathObjectPtr result
;
86 IEnumVARIANT
*enumvariant
;
89 static HRESULT
selection_get_item(IUnknown
*iface
, LONG index
, VARIANT
* item
)
91 V_VT(item
) = VT_DISPATCH
;
92 return IXMLDOMSelection_get_item((IXMLDOMSelection
*)iface
, index
, (IXMLDOMNode
**)&V_DISPATCH(item
));
95 static HRESULT
selection_next(IUnknown
*iface
)
98 HRESULT hr
= IXMLDOMSelection_nextNode((IXMLDOMSelection
*)iface
, &node
);
99 if (hr
== S_OK
) IXMLDOMNode_Release(node
);
103 static const struct enumvariant_funcs selection_enumvariant
= {
108 static inline domselection
*impl_from_IXMLDOMSelection( IXMLDOMSelection
*iface
)
110 return CONTAINING_RECORD(iface
, domselection
, IXMLDOMSelection_iface
);
113 static inline enumvariant
*impl_from_IEnumVARIANT( IEnumVARIANT
*iface
)
115 return CONTAINING_RECORD(iface
, enumvariant
, IEnumVARIANT_iface
);
118 static HRESULT WINAPI
domselection_QueryInterface(
119 IXMLDOMSelection
*iface
,
123 domselection
*This
= impl_from_IXMLDOMSelection( iface
);
125 TRACE("(%p)->(%s %p)\n", iface
, debugstr_guid(riid
), ppvObject
);
130 if ( IsEqualGUID( riid
, &IID_IUnknown
) ||
131 IsEqualGUID( riid
, &IID_IXMLDOMNodeList
) ||
132 IsEqualGUID( riid
, &IID_IXMLDOMSelection
))
134 *ppvObject
= &This
->IXMLDOMSelection_iface
;
136 else if (IsEqualGUID( riid
, &IID_IEnumVARIANT
))
138 if (!This
->enumvariant
)
140 HRESULT hr
= create_enumvariant((IUnknown
*)iface
, FALSE
, &selection_enumvariant
, &This
->enumvariant
);
141 if (FAILED(hr
)) return hr
;
144 return IEnumVARIANT_QueryInterface(This
->enumvariant
, &IID_IEnumVARIANT
, ppvObject
);
146 else if (dispex_query_interface(&This
->dispex
, riid
, ppvObject
))
148 return *ppvObject
? S_OK
: E_NOINTERFACE
;
152 TRACE("interface %s not implemented\n", debugstr_guid(riid
));
154 return E_NOINTERFACE
;
157 IXMLDOMSelection_AddRef( iface
);
162 static ULONG WINAPI
domselection_AddRef(
163 IXMLDOMSelection
*iface
)
165 domselection
*This
= impl_from_IXMLDOMSelection( iface
);
166 ULONG ref
= InterlockedIncrement( &This
->ref
);
167 TRACE("(%p)->(%d)\n", This
, ref
);
171 static ULONG WINAPI
domselection_Release(
172 IXMLDOMSelection
*iface
)
174 domselection
*This
= impl_from_IXMLDOMSelection( iface
);
175 ULONG ref
= InterlockedDecrement(&This
->ref
);
177 TRACE("(%p)->(%d)\n", This
, ref
);
180 xmlXPathFreeObject(This
->result
);
181 xmldoc_release(This
->node
->doc
);
182 if (This
->enumvariant
) IEnumVARIANT_Release(This
->enumvariant
);
183 release_dispex(&This
->dispex
);
190 static HRESULT WINAPI
domselection_GetTypeInfoCount(
191 IXMLDOMSelection
*iface
,
194 domselection
*This
= impl_from_IXMLDOMSelection( iface
);
195 return IDispatchEx_GetTypeInfoCount(&This
->dispex
.IDispatchEx_iface
, pctinfo
);
198 static HRESULT WINAPI
domselection_GetTypeInfo(
199 IXMLDOMSelection
*iface
,
202 ITypeInfo
** ppTInfo
)
204 domselection
*This
= impl_from_IXMLDOMSelection( iface
);
205 return IDispatchEx_GetTypeInfo(&This
->dispex
.IDispatchEx_iface
,
206 iTInfo
, lcid
, ppTInfo
);
209 static HRESULT WINAPI
domselection_GetIDsOfNames(
210 IXMLDOMSelection
*iface
,
217 domselection
*This
= impl_from_IXMLDOMSelection( iface
);
218 return IDispatchEx_GetIDsOfNames(&This
->dispex
.IDispatchEx_iface
,
219 riid
, rgszNames
, cNames
, lcid
, rgDispId
);
222 static HRESULT WINAPI
domselection_Invoke(
223 IXMLDOMSelection
*iface
,
228 DISPPARAMS
* pDispParams
,
230 EXCEPINFO
* pExcepInfo
,
233 domselection
*This
= impl_from_IXMLDOMSelection( iface
);
234 return IDispatchEx_Invoke(&This
->dispex
.IDispatchEx_iface
,
235 dispIdMember
, riid
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
238 static HRESULT WINAPI
domselection_get_item(
239 IXMLDOMSelection
* iface
,
241 IXMLDOMNode
** listItem
)
243 domselection
*This
= impl_from_IXMLDOMSelection( iface
);
245 TRACE("(%p)->(%d %p)\n", This
, index
, listItem
);
252 if (index
< 0 || index
>= xmlXPathNodeSetGetLength(This
->result
->nodesetval
))
255 *listItem
= create_node(xmlXPathNodeSetItem(This
->result
->nodesetval
, index
));
256 This
->resultPos
= index
+ 1;
261 static HRESULT WINAPI
domselection_get_length(
262 IXMLDOMSelection
* iface
,
265 domselection
*This
= impl_from_IXMLDOMSelection( iface
);
267 TRACE("(%p)->(%p)\n", This
, listLength
);
272 *listLength
= xmlXPathNodeSetGetLength(This
->result
->nodesetval
);
276 static HRESULT WINAPI
domselection_nextNode(
277 IXMLDOMSelection
* iface
,
278 IXMLDOMNode
** nextItem
)
280 domselection
*This
= impl_from_IXMLDOMSelection( iface
);
282 TRACE("(%p)->(%p)\n", This
, nextItem
);
289 if (This
->resultPos
>= xmlXPathNodeSetGetLength(This
->result
->nodesetval
))
292 *nextItem
= create_node(xmlXPathNodeSetItem(This
->result
->nodesetval
, This
->resultPos
));
297 static HRESULT WINAPI
domselection_reset(
298 IXMLDOMSelection
* iface
)
300 domselection
*This
= impl_from_IXMLDOMSelection( iface
);
307 static HRESULT WINAPI
domselection_get__newEnum(
308 IXMLDOMSelection
* iface
,
311 domselection
*This
= impl_from_IXMLDOMSelection( iface
);
313 TRACE("(%p)->(%p)\n", This
, enumv
);
315 return create_enumvariant((IUnknown
*)iface
, TRUE
, &selection_enumvariant
, (IEnumVARIANT
**)enumv
);
318 static HRESULT WINAPI
domselection_get_expr(
319 IXMLDOMSelection
* iface
,
322 domselection
*This
= impl_from_IXMLDOMSelection( iface
);
323 FIXME("(%p)->(%p)\n", This
, p
);
327 static HRESULT WINAPI
domselection_put_expr(
328 IXMLDOMSelection
* iface
,
331 domselection
*This
= impl_from_IXMLDOMSelection( iface
);
332 FIXME("(%p)->(%s)\n", This
, debugstr_w(p
));
336 static HRESULT WINAPI
domselection_get_context(
337 IXMLDOMSelection
* iface
,
340 domselection
*This
= impl_from_IXMLDOMSelection( iface
);
341 FIXME("(%p)->(%p)\n", This
, node
);
345 static HRESULT WINAPI
domselection_putref_context(
346 IXMLDOMSelection
* iface
,
349 domselection
*This
= impl_from_IXMLDOMSelection( iface
);
350 FIXME("(%p)->(%p)\n", This
, node
);
354 static HRESULT WINAPI
domselection_peekNode(
355 IXMLDOMSelection
* iface
,
358 domselection
*This
= impl_from_IXMLDOMSelection( iface
);
359 FIXME("(%p)->(%p)\n", This
, node
);
363 static HRESULT WINAPI
domselection_matches(
364 IXMLDOMSelection
* iface
,
366 IXMLDOMNode
**out_node
)
368 domselection
*This
= impl_from_IXMLDOMSelection( iface
);
369 FIXME("(%p)->(%p %p)\n", This
, node
, out_node
);
373 static HRESULT WINAPI
domselection_removeNext(
374 IXMLDOMSelection
* iface
,
377 domselection
*This
= impl_from_IXMLDOMSelection( iface
);
378 FIXME("(%p)->(%p)\n", This
, node
);
382 static HRESULT WINAPI
domselection_removeAll(
383 IXMLDOMSelection
* iface
)
385 domselection
*This
= impl_from_IXMLDOMSelection( iface
);
386 FIXME("(%p)\n", This
);
390 static HRESULT WINAPI
domselection_clone(
391 IXMLDOMSelection
* iface
,
392 IXMLDOMSelection
**node
)
394 domselection
*This
= impl_from_IXMLDOMSelection( iface
);
395 FIXME("(%p)->(%p)\n", This
, node
);
399 static HRESULT WINAPI
domselection_getProperty(
400 IXMLDOMSelection
* iface
,
404 domselection
*This
= impl_from_IXMLDOMSelection( iface
);
405 FIXME("(%p)->(%s %p)\n", This
, debugstr_w(p
), var
);
409 static HRESULT WINAPI
domselection_setProperty(
410 IXMLDOMSelection
* iface
,
414 domselection
*This
= impl_from_IXMLDOMSelection( iface
);
415 FIXME("(%p)->(%s %s)\n", This
, debugstr_w(p
), debugstr_variant(&var
));
419 static const struct IXMLDOMSelectionVtbl domselection_vtbl
=
421 domselection_QueryInterface
,
423 domselection_Release
,
424 domselection_GetTypeInfoCount
,
425 domselection_GetTypeInfo
,
426 domselection_GetIDsOfNames
,
428 domselection_get_item
,
429 domselection_get_length
,
430 domselection_nextNode
,
432 domselection_get__newEnum
,
433 domselection_get_expr
,
434 domselection_put_expr
,
435 domselection_get_context
,
436 domselection_putref_context
,
437 domselection_peekNode
,
438 domselection_matches
,
439 domselection_removeNext
,
440 domselection_removeAll
,
442 domselection_getProperty
,
443 domselection_setProperty
446 /* IEnumVARIANT support */
447 static HRESULT WINAPI
enumvariant_QueryInterface(
452 enumvariant
*This
= impl_from_IEnumVARIANT( iface
);
454 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppvObject
);
458 if (IsEqualGUID( riid
, &IID_IUnknown
))
461 *ppvObject
= &This
->IEnumVARIANT_iface
;
463 return IUnknown_QueryInterface(This
->outer
, riid
, ppvObject
);
465 else if (IsEqualGUID( riid
, &IID_IEnumVARIANT
))
467 *ppvObject
= &This
->IEnumVARIANT_iface
;
470 return IUnknown_QueryInterface(This
->outer
, riid
, ppvObject
);
472 IEnumVARIANT_AddRef( iface
);
477 static ULONG WINAPI
enumvariant_AddRef(IEnumVARIANT
*iface
)
479 enumvariant
*This
= impl_from_IEnumVARIANT( iface
);
480 ULONG ref
= InterlockedIncrement( &This
->ref
);
481 TRACE("(%p)->(%d)\n", This
, ref
);
485 static ULONG WINAPI
enumvariant_Release(IEnumVARIANT
*iface
)
487 enumvariant
*This
= impl_from_IEnumVARIANT( iface
);
488 ULONG ref
= InterlockedDecrement(&This
->ref
);
490 TRACE("(%p)->(%d)\n", This
, ref
);
493 if (This
->own
) IUnknown_Release(This
->outer
);
500 static HRESULT WINAPI
enumvariant_Next(
506 enumvariant
*This
= impl_from_IEnumVARIANT( iface
);
509 TRACE("(%p)->(%u %p %p)\n", This
, celt
, var
, fetched
);
511 if (fetched
) *fetched
= 0;
513 if (celt
&& !var
) return E_INVALIDARG
;
515 for (; celt
> 0; celt
--, var
++, This
->pos
++)
517 HRESULT hr
= This
->funcs
->get_item(This
->outer
, This
->pos
, var
);
520 V_VT(var
) = VT_EMPTY
;
526 if (fetched
) (*fetched
)++;
528 /* we need to advance one step more for some reason */
531 if (This
->funcs
->next
)
532 This
->funcs
->next(This
->outer
);
535 return celt
== 0 ? S_OK
: S_FALSE
;
538 static HRESULT WINAPI
enumvariant_Skip(
542 enumvariant
*This
= impl_from_IEnumVARIANT( iface
);
543 FIXME("(%p)->(%u): stub\n", This
, celt
);
547 static HRESULT WINAPI
enumvariant_Reset(IEnumVARIANT
*iface
)
549 enumvariant
*This
= impl_from_IEnumVARIANT( iface
);
550 FIXME("(%p): stub\n", This
);
554 static HRESULT WINAPI
enumvariant_Clone(
555 IEnumVARIANT
*iface
, IEnumVARIANT
**ppenum
)
557 enumvariant
*This
= impl_from_IEnumVARIANT( iface
);
558 FIXME("(%p)->(%p): stub\n", This
, ppenum
);
562 static const struct IEnumVARIANTVtbl EnumVARIANTVtbl
=
564 enumvariant_QueryInterface
,
573 HRESULT
create_enumvariant(IUnknown
*outer
, BOOL own
, const struct enumvariant_funcs
*funcs
, IEnumVARIANT
**penum
)
577 This
= heap_alloc(sizeof(enumvariant
));
578 if (!This
) return E_OUTOFMEMORY
;
580 This
->IEnumVARIANT_iface
.lpVtbl
= &EnumVARIANTVtbl
;
588 IUnknown_AddRef(This
->outer
);
590 *penum
= &This
->IEnumVARIANT_iface
;
591 IEnumVARIANT_AddRef(*penum
);
595 static HRESULT
domselection_get_dispid(IUnknown
*iface
, BSTR name
, DWORD flags
, DISPID
*dispid
)
600 for(ptr
= name
; *ptr
&& isdigitW(*ptr
); ptr
++)
601 idx
= idx
*10 + (*ptr
-'0');
603 return DISP_E_UNKNOWNNAME
;
605 *dispid
= DISPID_DOM_COLLECTION_BASE
+ idx
;
606 TRACE("ret %x\n", *dispid
);
610 static HRESULT
domselection_invoke(IUnknown
*iface
, DISPID id
, LCID lcid
, WORD flags
, DISPPARAMS
*params
,
611 VARIANT
*res
, EXCEPINFO
*ei
)
613 domselection
*This
= impl_from_IXMLDOMSelection( (IXMLDOMSelection
*)iface
);
615 TRACE("(%p)->(%x %x %x %p %p %p)\n", This
, id
, lcid
, flags
, params
, res
, ei
);
617 V_VT(res
) = VT_DISPATCH
;
618 V_DISPATCH(res
) = NULL
;
620 if (id
< DISPID_DOM_COLLECTION_BASE
|| id
> DISPID_DOM_COLLECTION_MAX
)
621 return DISP_E_UNKNOWNNAME
;
625 case INVOKE_PROPERTYGET
:
627 IXMLDOMNode
*disp
= NULL
;
629 IXMLDOMSelection_get_item(&This
->IXMLDOMSelection_iface
, id
- DISPID_DOM_COLLECTION_BASE
, &disp
);
630 V_DISPATCH(res
) = (IDispatch
*)disp
;
635 FIXME("unimplemented flags %x\n", flags
);
640 TRACE("ret %p\n", V_DISPATCH(res
));
645 static const dispex_static_data_vtbl_t domselection_dispex_vtbl
= {
646 domselection_get_dispid
,
650 static const tid_t domselection_iface_tids
[] = {
651 IXMLDOMSelection_tid
,
654 static dispex_static_data_t domselection_dispex
= {
655 &domselection_dispex_vtbl
,
656 IXMLDOMSelection_tid
,
658 domselection_iface_tids
661 #define XSLPATTERN_CHECK_ARGS(n) \
663 FIXME("XSLPattern syntax error: Expected %i arguments, got %i\n", n, nargs); \
664 xmlXPathSetArityError(pctx); \
669 static void XSLPattern_index(xmlXPathParserContextPtr pctx
, int nargs
)
671 XSLPATTERN_CHECK_ARGS(0);
673 xmlXPathPositionFunction(pctx
, 0);
674 xmlXPathReturnNumber(pctx
, xmlXPathPopNumber(pctx
) - 1.0);
677 static void XSLPattern_end(xmlXPathParserContextPtr pctx
, int nargs
)
680 XSLPATTERN_CHECK_ARGS(0);
682 xmlXPathPositionFunction(pctx
, 0);
683 pos
= xmlXPathPopNumber(pctx
);
684 xmlXPathLastFunction(pctx
, 0);
685 last
= xmlXPathPopNumber(pctx
);
686 xmlXPathReturnBoolean(pctx
, pos
== last
);
689 static void XSLPattern_nodeType(xmlXPathParserContextPtr pctx
, int nargs
)
691 XSLPATTERN_CHECK_ARGS(0);
692 xmlXPathReturnNumber(pctx
, pctx
->context
->node
->type
);
695 static void XSLPattern_OP_IEq(xmlXPathParserContextPtr pctx
, int nargs
)
697 xmlChar
*arg1
, *arg2
;
698 XSLPATTERN_CHECK_ARGS(2);
700 arg2
= xmlXPathPopString(pctx
);
701 arg1
= xmlXPathPopString(pctx
);
702 xmlXPathReturnBoolean(pctx
, xmlStrcasecmp(arg1
, arg2
) == 0);
707 static void XSLPattern_OP_INEq(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_ILt(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_ILEq(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_IGt(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_IGEq(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 query_serror(void* ctx
, xmlErrorPtr err
)
769 LIBXML2_CALLBACK_SERROR(domselection_create
, err
);
772 HRESULT
create_selection(xmlNodePtr node
, xmlChar
* query
, IXMLDOMNodeList
**out
)
774 domselection
*This
= heap_alloc(sizeof(domselection
));
775 xmlXPathContextPtr ctxt
= xmlXPathNewContext(node
->doc
);
778 TRACE("(%p, %s, %p)\n", node
, debugstr_a((char const*)query
), out
);
781 if (!This
|| !ctxt
|| !query
)
783 xmlXPathFreeContext(ctxt
);
785 return E_OUTOFMEMORY
;
788 This
->IXMLDOMSelection_iface
.lpVtbl
= &domselection_vtbl
;
792 This
->enumvariant
= NULL
;
793 init_dispex(&This
->dispex
, (IUnknown
*)&This
->IXMLDOMSelection_iface
, &domselection_dispex
);
794 xmldoc_add_ref(This
->node
->doc
);
796 ctxt
->error
= query_serror
;
798 registerNamespaces(ctxt
);
800 if (is_xpathmode(This
->node
->doc
))
802 xmlXPathRegisterAllFunctions(ctxt
);
803 This
->result
= xmlXPathEvalExpression(query
, ctxt
);
807 xmlChar
* pattern_query
= XSLPattern_to_XPath(ctxt
, query
);
809 xmlXPathRegisterFunc(ctxt
, (xmlChar
const*)"not", xmlXPathNotFunction
);
810 xmlXPathRegisterFunc(ctxt
, (xmlChar
const*)"boolean", xmlXPathBooleanFunction
);
812 xmlXPathRegisterFunc(ctxt
, (xmlChar
const*)"index", XSLPattern_index
);
813 xmlXPathRegisterFunc(ctxt
, (xmlChar
const*)"end", XSLPattern_end
);
814 xmlXPathRegisterFunc(ctxt
, (xmlChar
const*)"nodeType", XSLPattern_nodeType
);
816 xmlXPathRegisterFunc(ctxt
, (xmlChar
const*)"OP_IEq", XSLPattern_OP_IEq
);
817 xmlXPathRegisterFunc(ctxt
, (xmlChar
const*)"OP_INEq", XSLPattern_OP_INEq
);
818 xmlXPathRegisterFunc(ctxt
, (xmlChar
const*)"OP_ILt", XSLPattern_OP_ILt
);
819 xmlXPathRegisterFunc(ctxt
, (xmlChar
const*)"OP_ILEq", XSLPattern_OP_ILEq
);
820 xmlXPathRegisterFunc(ctxt
, (xmlChar
const*)"OP_IGt", XSLPattern_OP_IGt
);
821 xmlXPathRegisterFunc(ctxt
, (xmlChar
const*)"OP_IGEq", XSLPattern_OP_IGEq
);
823 This
->result
= xmlXPathEvalExpression(pattern_query
, ctxt
);
824 xmlFree(pattern_query
);
827 if (!This
->result
|| This
->result
->type
!= XPATH_NODESET
)
833 *out
= (IXMLDOMNodeList
*)&This
->IXMLDOMSelection_iface
;
835 TRACE("found %d matches\n", xmlXPathNodeSetGetLength(This
->result
->nodesetval
));
838 if (This
&& FAILED(hr
))
839 IXMLDOMSelection_Release( &This
->IXMLDOMSelection_iface
);
840 xmlXPathFreeContext(ctxt
);