2007-12-30 10:49:17 +00:00
|
|
|
/*
|
|
|
|
* XPath query result node list implementation (TODO: XSLPattern support)
|
|
|
|
*
|
|
|
|
* Copyright 2005 Mike McCormack
|
|
|
|
* Copyright 2007 Mikolaj Zalewski
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define COBJMACROS
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include "windef.h"
|
|
|
|
#include "winbase.h"
|
|
|
|
#include "winuser.h"
|
|
|
|
#include "ole2.h"
|
|
|
|
#include "msxml2.h"
|
|
|
|
|
|
|
|
#include "msxml_private.h"
|
|
|
|
|
|
|
|
#include "wine/debug.h"
|
|
|
|
|
|
|
|
/* This file implements the object returned by a XPath query. Note that this is
|
|
|
|
* not the IXMLDOMNodeList returned by childNodes - it's implemented in nodelist.c.
|
|
|
|
* They are different because the list returned by XPath queries:
|
|
|
|
* - is static - gives the results for the XML tree as it existed during the
|
|
|
|
* execution of the query
|
|
|
|
* - supports IXMLDOMSelection (TODO)
|
|
|
|
*
|
|
|
|
* TODO: XSLPattern support
|
|
|
|
*/
|
|
|
|
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(msxml);
|
|
|
|
|
|
|
|
#ifdef HAVE_LIBXML2
|
|
|
|
|
|
|
|
#include <libxml/xpath.h>
|
|
|
|
|
|
|
|
typedef struct _queryresult
|
|
|
|
{
|
2008-09-08 16:51:03 +00:00
|
|
|
DispatchEx dispex;
|
2007-12-30 10:49:17 +00:00
|
|
|
const struct IXMLDOMNodeListVtbl *lpVtbl;
|
|
|
|
LONG ref;
|
|
|
|
xmlNodePtr node;
|
|
|
|
xmlXPathObjectPtr result;
|
|
|
|
int resultPos;
|
|
|
|
} queryresult;
|
|
|
|
|
|
|
|
static inline queryresult *impl_from_IXMLDOMNodeList( IXMLDOMNodeList *iface )
|
|
|
|
{
|
|
|
|
return (queryresult *)((char*)iface - FIELD_OFFSET(queryresult, lpVtbl));
|
|
|
|
}
|
|
|
|
|
2008-09-21 13:03:20 +00:00
|
|
|
#define XMLQUERYRES(x) ((IXMLDOMNodeList*)&(x)->lpVtbl)
|
|
|
|
|
2007-12-30 10:49:17 +00:00
|
|
|
static HRESULT WINAPI queryresult_QueryInterface(
|
|
|
|
IXMLDOMNodeList *iface,
|
|
|
|
REFIID riid,
|
|
|
|
void** ppvObject )
|
|
|
|
{
|
2008-09-08 16:51:03 +00:00
|
|
|
queryresult *This = impl_from_IXMLDOMNodeList( iface );
|
|
|
|
|
2010-03-01 11:10:15 +00:00
|
|
|
TRACE("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppvObject);
|
2007-12-30 10:49:17 +00:00
|
|
|
|
2008-09-08 16:51:03 +00:00
|
|
|
if(!ppvObject)
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
2007-12-30 10:49:17 +00:00
|
|
|
if ( IsEqualGUID( riid, &IID_IUnknown ) ||
|
|
|
|
IsEqualGUID( riid, &IID_IXMLDOMNodeList ) )
|
|
|
|
{
|
|
|
|
*ppvObject = iface;
|
|
|
|
}
|
2008-09-08 16:51:03 +00:00
|
|
|
else if(dispex_query_interface(&This->dispex, riid, ppvObject))
|
|
|
|
{
|
|
|
|
return *ppvObject ? S_OK : E_NOINTERFACE;
|
|
|
|
}
|
2007-12-30 10:49:17 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
FIXME("interface %s not implemented\n", debugstr_guid(riid));
|
|
|
|
*ppvObject = NULL;
|
|
|
|
return E_NOINTERFACE;
|
|
|
|
}
|
|
|
|
|
|
|
|
IXMLDOMNodeList_AddRef( iface );
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG WINAPI queryresult_AddRef(
|
|
|
|
IXMLDOMNodeList *iface )
|
|
|
|
{
|
|
|
|
queryresult *This = impl_from_IXMLDOMNodeList( iface );
|
|
|
|
return InterlockedIncrement( &This->ref );
|
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG WINAPI queryresult_Release(
|
|
|
|
IXMLDOMNodeList *iface )
|
|
|
|
{
|
|
|
|
queryresult *This = impl_from_IXMLDOMNodeList( iface );
|
|
|
|
ULONG ref;
|
|
|
|
|
|
|
|
ref = InterlockedDecrement(&This->ref);
|
|
|
|
if ( ref == 0 )
|
|
|
|
{
|
|
|
|
xmlXPathFreeObject(This->result);
|
|
|
|
xmldoc_release(This->node->doc);
|
2008-09-08 16:51:03 +00:00
|
|
|
heap_free(This);
|
2007-12-30 10:49:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return ref;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI queryresult_GetTypeInfoCount(
|
|
|
|
IXMLDOMNodeList *iface,
|
|
|
|
UINT* pctinfo )
|
|
|
|
{
|
2008-09-08 16:51:03 +00:00
|
|
|
queryresult *This = impl_from_IXMLDOMNodeList( iface );
|
|
|
|
|
|
|
|
TRACE("(%p)->(%p)\n", This, pctinfo);
|
|
|
|
|
|
|
|
*pctinfo = 1;
|
|
|
|
|
|
|
|
return S_OK;
|
2007-12-30 10:49:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI queryresult_GetTypeInfo(
|
|
|
|
IXMLDOMNodeList *iface,
|
|
|
|
UINT iTInfo,
|
|
|
|
LCID lcid,
|
|
|
|
ITypeInfo** ppTInfo )
|
|
|
|
{
|
2008-09-08 16:51:03 +00:00
|
|
|
queryresult *This = impl_from_IXMLDOMNodeList( iface );
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
|
|
|
|
|
|
|
|
hr = get_typeinfo(IXMLDOMNodeList_tid, ppTInfo);
|
|
|
|
|
|
|
|
return hr;
|
2007-12-30 10:49:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI queryresult_GetIDsOfNames(
|
|
|
|
IXMLDOMNodeList *iface,
|
|
|
|
REFIID riid,
|
|
|
|
LPOLESTR* rgszNames,
|
|
|
|
UINT cNames,
|
|
|
|
LCID lcid,
|
|
|
|
DISPID* rgDispId )
|
|
|
|
{
|
2008-09-08 16:51:03 +00:00
|
|
|
queryresult *This = impl_from_IXMLDOMNodeList( iface );
|
|
|
|
ITypeInfo *typeinfo;
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
|
|
|
|
lcid, rgDispId);
|
|
|
|
|
|
|
|
if(!rgszNames || cNames == 0 || !rgDispId)
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
hr = get_typeinfo(IXMLDOMNodeList_tid, &typeinfo);
|
|
|
|
if(SUCCEEDED(hr))
|
|
|
|
{
|
|
|
|
hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
|
|
|
|
ITypeInfo_Release(typeinfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
return hr;
|
2007-12-30 10:49:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI queryresult_Invoke(
|
|
|
|
IXMLDOMNodeList *iface,
|
|
|
|
DISPID dispIdMember,
|
|
|
|
REFIID riid,
|
|
|
|
LCID lcid,
|
|
|
|
WORD wFlags,
|
|
|
|
DISPPARAMS* pDispParams,
|
|
|
|
VARIANT* pVarResult,
|
|
|
|
EXCEPINFO* pExcepInfo,
|
|
|
|
UINT* puArgErr )
|
|
|
|
{
|
2008-09-08 16:51:03 +00:00
|
|
|
queryresult *This = impl_from_IXMLDOMNodeList( iface );
|
|
|
|
ITypeInfo *typeinfo;
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
|
|
|
|
lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
|
|
|
|
|
|
|
|
hr = get_typeinfo(IXMLDOMNodeList_tid, &typeinfo);
|
|
|
|
if(SUCCEEDED(hr))
|
|
|
|
{
|
|
|
|
hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
|
|
|
|
pVarResult, pExcepInfo, puArgErr);
|
|
|
|
ITypeInfo_Release(typeinfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
return hr;
|
2007-12-30 10:49:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI queryresult_get_item(
|
|
|
|
IXMLDOMNodeList* iface,
|
2009-04-28 19:57:36 +00:00
|
|
|
LONG index,
|
2007-12-30 10:49:17 +00:00
|
|
|
IXMLDOMNode** listItem)
|
|
|
|
{
|
|
|
|
queryresult *This = impl_from_IXMLDOMNodeList( iface );
|
|
|
|
|
2010-03-01 11:10:15 +00:00
|
|
|
TRACE("(%p)->(%d %p)\n", This, index, listItem);
|
2007-12-30 10:49:17 +00:00
|
|
|
|
2008-09-08 16:51:03 +00:00
|
|
|
if(!listItem)
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
2007-12-30 10:49:17 +00:00
|
|
|
*listItem = NULL;
|
|
|
|
|
2008-09-08 16:51:03 +00:00
|
|
|
if (index < 0 || index >= xmlXPathNodeSetGetLength(This->result->nodesetval))
|
2007-12-30 10:49:17 +00:00
|
|
|
return S_FALSE;
|
|
|
|
|
Sync avifil, credui, crypt32, cryptdlg, cryptui, dnsapi, gdiplus, hhctrl, hnetcfg, iccvid, imaadp32, imm32, jscript, localspl, localui, mapi32, mciavi32, mcicda, mciqtz32, mciseq, mciwave, mshtml, msrle32, msvfw32, msvidc32, msxml3, oleacc, oleaut32 to Wine 1.2rc5 (Samuel Serapion, small changes by me)
Remove Esperanto and Walon languages from comctl32, comdlg32, mpr, msi, shlwapi, wininet
svn path=/trunk/; revision=47920
2010-07-01 11:09:47 +00:00
|
|
|
*listItem = create_node(xmlXPathNodeSetItem(This->result->nodesetval, index));
|
2007-12-30 10:49:17 +00:00
|
|
|
This->resultPos = index + 1;
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI queryresult_get_length(
|
|
|
|
IXMLDOMNodeList* iface,
|
2009-04-28 19:57:36 +00:00
|
|
|
LONG* listLength)
|
2007-12-30 10:49:17 +00:00
|
|
|
{
|
|
|
|
queryresult *This = impl_from_IXMLDOMNodeList( iface );
|
|
|
|
|
2010-03-01 11:10:15 +00:00
|
|
|
TRACE("(%p)->(%p)\n", This, listLength);
|
2007-12-30 10:49:17 +00:00
|
|
|
|
2008-09-08 16:51:03 +00:00
|
|
|
if(!listLength)
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
*listLength = xmlXPathNodeSetGetLength(This->result->nodesetval);
|
2007-12-30 10:49:17 +00:00
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI queryresult_nextNode(
|
|
|
|
IXMLDOMNodeList* iface,
|
|
|
|
IXMLDOMNode** nextItem)
|
|
|
|
{
|
|
|
|
queryresult *This = impl_from_IXMLDOMNodeList( iface );
|
|
|
|
|
2010-03-01 11:10:15 +00:00
|
|
|
TRACE("(%p)->(%p)\n", This, nextItem );
|
2007-12-30 10:49:17 +00:00
|
|
|
|
2008-09-08 16:51:03 +00:00
|
|
|
if(!nextItem)
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
2007-12-30 10:49:17 +00:00
|
|
|
*nextItem = NULL;
|
|
|
|
|
2008-09-08 16:51:03 +00:00
|
|
|
if (This->resultPos >= xmlXPathNodeSetGetLength(This->result->nodesetval))
|
2007-12-30 10:49:17 +00:00
|
|
|
return S_FALSE;
|
|
|
|
|
Sync avifil, credui, crypt32, cryptdlg, cryptui, dnsapi, gdiplus, hhctrl, hnetcfg, iccvid, imaadp32, imm32, jscript, localspl, localui, mapi32, mciavi32, mcicda, mciqtz32, mciseq, mciwave, mshtml, msrle32, msvfw32, msvidc32, msxml3, oleacc, oleaut32 to Wine 1.2rc5 (Samuel Serapion, small changes by me)
Remove Esperanto and Walon languages from comctl32, comdlg32, mpr, msi, shlwapi, wininet
svn path=/trunk/; revision=47920
2010-07-01 11:09:47 +00:00
|
|
|
*nextItem = create_node(xmlXPathNodeSetItem(This->result->nodesetval, This->resultPos));
|
2007-12-30 10:49:17 +00:00
|
|
|
This->resultPos++;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI queryresult_reset(
|
|
|
|
IXMLDOMNodeList* iface)
|
|
|
|
{
|
|
|
|
queryresult *This = impl_from_IXMLDOMNodeList( iface );
|
|
|
|
|
|
|
|
TRACE("%p\n", This);
|
|
|
|
This->resultPos = 0;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI queryresult__newEnum(
|
|
|
|
IXMLDOMNodeList* iface,
|
|
|
|
IUnknown** ppUnk)
|
|
|
|
{
|
2010-03-01 11:10:15 +00:00
|
|
|
queryresult *This = impl_from_IXMLDOMNodeList( iface );
|
|
|
|
FIXME("(%p)->(%p)\n", This, ppUnk);
|
2007-12-30 10:49:17 +00:00
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static const struct IXMLDOMNodeListVtbl queryresult_vtbl =
|
|
|
|
{
|
|
|
|
queryresult_QueryInterface,
|
|
|
|
queryresult_AddRef,
|
|
|
|
queryresult_Release,
|
|
|
|
queryresult_GetTypeInfoCount,
|
|
|
|
queryresult_GetTypeInfo,
|
|
|
|
queryresult_GetIDsOfNames,
|
|
|
|
queryresult_Invoke,
|
|
|
|
queryresult_get_item,
|
|
|
|
queryresult_get_length,
|
|
|
|
queryresult_nextNode,
|
|
|
|
queryresult_reset,
|
|
|
|
queryresult__newEnum,
|
|
|
|
};
|
|
|
|
|
2008-09-14 06:24:36 +00:00
|
|
|
static HRESULT queryresult_get_dispid(IUnknown *iface, BSTR name, DWORD flags, DISPID *dispid)
|
|
|
|
{
|
|
|
|
queryresult *This = impl_from_IXMLDOMNodeList( (IXMLDOMNodeList*)iface );
|
|
|
|
WCHAR *ptr;
|
2009-01-04 10:48:19 +00:00
|
|
|
int idx = 0;
|
2008-09-14 06:24:36 +00:00
|
|
|
|
|
|
|
for(ptr = name; *ptr && isdigitW(*ptr); ptr++)
|
|
|
|
idx = idx*10 + (*ptr-'0');
|
|
|
|
if(*ptr)
|
|
|
|
return DISP_E_UNKNOWNNAME;
|
|
|
|
|
|
|
|
if(idx >= xmlXPathNodeSetGetLength(This->result->nodesetval))
|
|
|
|
return DISP_E_UNKNOWNNAME;
|
|
|
|
|
|
|
|
*dispid = MSXML_DISPID_CUSTOM_MIN + idx;
|
|
|
|
TRACE("ret %x\n", *dispid);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT queryresult_invoke(IUnknown *iface, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params,
|
|
|
|
VARIANT *res, EXCEPINFO *ei)
|
|
|
|
{
|
|
|
|
queryresult *This = impl_from_IXMLDOMNodeList( (IXMLDOMNodeList*)iface );
|
|
|
|
|
2008-09-21 13:03:20 +00:00
|
|
|
TRACE("(%p)->(%x %x %x %p %p %p)\n", This, id, lcid, flags, params, res, ei);
|
2008-09-14 06:24:36 +00:00
|
|
|
|
|
|
|
V_VT(res) = VT_DISPATCH;
|
2008-09-21 13:03:20 +00:00
|
|
|
V_DISPATCH(res) = NULL;
|
|
|
|
|
|
|
|
switch(flags)
|
|
|
|
{
|
|
|
|
case INVOKE_PROPERTYGET:
|
|
|
|
{
|
|
|
|
IXMLDOMNode *disp = NULL;
|
|
|
|
|
|
|
|
queryresult_get_item(XMLQUERYRES(This), id - MSXML_DISPID_CUSTOM_MIN, &disp);
|
2009-01-04 10:48:19 +00:00
|
|
|
V_DISPATCH(res) = (IDispatch*)disp;
|
2008-09-21 13:03:20 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
FIXME("unimplemented flags %x\n", flags);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-01-04 10:48:19 +00:00
|
|
|
TRACE("ret %p\n", V_DISPATCH(res));
|
|
|
|
|
2008-09-14 06:24:36 +00:00
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const dispex_static_data_vtbl_t queryresult_dispex_vtbl = {
|
|
|
|
queryresult_get_dispid,
|
|
|
|
queryresult_invoke
|
|
|
|
};
|
|
|
|
|
2008-09-08 16:51:03 +00:00
|
|
|
static const tid_t queryresult_iface_tids[] = {
|
|
|
|
IXMLDOMNodeList_tid,
|
|
|
|
0
|
|
|
|
};
|
|
|
|
static dispex_static_data_t queryresult_dispex = {
|
2008-09-14 06:24:36 +00:00
|
|
|
&queryresult_dispex_vtbl,
|
2009-09-05 15:02:49 +00:00
|
|
|
IXMLDOMSelection_tid,
|
2008-09-08 16:51:03 +00:00
|
|
|
NULL,
|
|
|
|
queryresult_iface_tids
|
|
|
|
};
|
|
|
|
|
|
|
|
HRESULT queryresult_create(xmlNodePtr node, LPWSTR szQuery, IXMLDOMNodeList **out)
|
|
|
|
{
|
|
|
|
queryresult *This = heap_alloc_zero(sizeof(queryresult));
|
|
|
|
xmlXPathContextPtr ctxt = xmlXPathNewContext(node->doc);
|
|
|
|
xmlChar *str = xmlChar_from_wchar(szQuery);
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
TRACE("(%p, %s, %p)\n", node, wine_dbgstr_w(szQuery), out);
|
|
|
|
|
|
|
|
*out = NULL;
|
|
|
|
if (This == NULL || ctxt == NULL || str == NULL)
|
|
|
|
{
|
|
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
This->lpVtbl = &queryresult_vtbl;
|
|
|
|
This->ref = 1;
|
|
|
|
This->resultPos = 0;
|
|
|
|
This->node = node;
|
|
|
|
xmldoc_add_ref(This->node->doc);
|
|
|
|
|
|
|
|
ctxt->node = node;
|
|
|
|
This->result = xmlXPathEval(str, ctxt);
|
|
|
|
if (!This->result || This->result->type != XPATH_NODESET)
|
|
|
|
{
|
|
|
|
hr = E_FAIL;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
init_dispex(&This->dispex, (IUnknown*)&This->lpVtbl, &queryresult_dispex);
|
|
|
|
|
|
|
|
*out = (IXMLDOMNodeList *) &This->lpVtbl;
|
|
|
|
hr = S_OK;
|
|
|
|
TRACE("found %d matches\n", xmlXPathNodeSetGetLength(This->result->nodesetval));
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (This != NULL && FAILED(hr))
|
|
|
|
IXMLDOMNodeList_Release( (IXMLDOMNodeList*) &This->lpVtbl );
|
Sync avifil, credui, crypt32, cryptdlg, cryptui, dnsapi, gdiplus, hhctrl, hnetcfg, iccvid, imaadp32, imm32, jscript, localspl, localui, mapi32, mciavi32, mcicda, mciqtz32, mciseq, mciwave, mshtml, msrle32, msvfw32, msvidc32, msxml3, oleacc, oleaut32 to Wine 1.2rc5 (Samuel Serapion, small changes by me)
Remove Esperanto and Walon languages from comctl32, comdlg32, mpr, msi, shlwapi, wininet
svn path=/trunk/; revision=47920
2010-07-01 11:09:47 +00:00
|
|
|
xmlXPathFreeContext(ctxt);
|
2010-02-06 21:34:28 +00:00
|
|
|
heap_free(str);
|
2008-09-08 16:51:03 +00:00
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
2007-12-30 10:49:17 +00:00
|
|
|
#endif
|