2 * XSLTemplate/XSLProcessor support
4 * Copyright 2011 Nikolay Sivov for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 # include <libxml/parser.h>
28 # include <libxml/xmlerror.h>
37 #include "msxml_private.h"
39 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(msxml
);
46 IXSLTemplate IXSLTemplate_iface
;
55 IXSLProcessor IXSLProcessor_iface
;
58 xsltemplate
*stylesheet
;
64 struct xslprocessor_params params
;
67 static HRESULT
XSLProcessor_create(xsltemplate
*, IXSLProcessor
**);
69 static inline xsltemplate
*impl_from_IXSLTemplate( IXSLTemplate
*iface
)
71 return CONTAINING_RECORD(iface
, xsltemplate
, IXSLTemplate_iface
);
74 static inline xslprocessor
*impl_from_IXSLProcessor( IXSLProcessor
*iface
)
76 return CONTAINING_RECORD(iface
, xslprocessor
, IXSLProcessor_iface
);
79 static void xslprocessor_par_free(struct xslprocessor_params
*params
, struct xslprocessor_par
*par
)
82 list_remove(&par
->entry
);
83 SysFreeString(par
->name
);
84 SysFreeString(par
->value
);
88 static void xsltemplate_set_node( xsltemplate
*This
, IXMLDOMNode
*node
)
90 if (This
->node
) IXMLDOMNode_Release(This
->node
);
92 if (node
) IXMLDOMNode_AddRef(node
);
95 static HRESULT WINAPI
xsltemplate_QueryInterface(
100 xsltemplate
*This
= impl_from_IXSLTemplate( iface
);
101 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppvObject
);
103 if ( IsEqualGUID( riid
, &IID_IXSLTemplate
) ||
104 IsEqualGUID( riid
, &IID_IDispatch
) ||
105 IsEqualGUID( riid
, &IID_IUnknown
) )
109 else if (dispex_query_interface(&This
->dispex
, riid
, ppvObject
))
111 return *ppvObject
? S_OK
: E_NOINTERFACE
;
115 FIXME("Unsupported interface %s\n", debugstr_guid(riid
));
117 return E_NOINTERFACE
;
120 IUnknown_AddRef((IUnknown
*)*ppvObject
);
124 static ULONG WINAPI
xsltemplate_AddRef( IXSLTemplate
*iface
)
126 xsltemplate
*This
= impl_from_IXSLTemplate( iface
);
127 ULONG ref
= InterlockedIncrement( &This
->ref
);
128 TRACE("(%p)->(%d)\n", This
, ref
);
132 static ULONG WINAPI
xsltemplate_Release( IXSLTemplate
*iface
)
134 xsltemplate
*This
= impl_from_IXSLTemplate( iface
);
135 ULONG ref
= InterlockedDecrement( &This
->ref
);
137 TRACE("(%p)->(%d)\n", This
, ref
);
140 if (This
->node
) IXMLDOMNode_Release( This
->node
);
141 release_dispex(&This
->dispex
);
148 static HRESULT WINAPI
xsltemplate_GetTypeInfoCount( IXSLTemplate
*iface
, UINT
* pctinfo
)
150 xsltemplate
*This
= impl_from_IXSLTemplate( iface
);
151 return IDispatchEx_GetTypeInfoCount(&This
->dispex
.IDispatchEx_iface
, pctinfo
);
154 static HRESULT WINAPI
xsltemplate_GetTypeInfo(
156 UINT iTInfo
, LCID lcid
,
157 ITypeInfo
** ppTInfo
)
159 xsltemplate
*This
= impl_from_IXSLTemplate( iface
);
160 return IDispatchEx_GetTypeInfo(&This
->dispex
.IDispatchEx_iface
,
161 iTInfo
, lcid
, ppTInfo
);
164 static HRESULT WINAPI
xsltemplate_GetIDsOfNames(
166 REFIID riid
, LPOLESTR
* rgszNames
,
167 UINT cNames
, LCID lcid
, DISPID
* rgDispId
)
169 xsltemplate
*This
= impl_from_IXSLTemplate( iface
);
170 return IDispatchEx_GetIDsOfNames(&This
->dispex
.IDispatchEx_iface
,
171 riid
, rgszNames
, cNames
, lcid
, rgDispId
);
174 static HRESULT WINAPI
xsltemplate_Invoke(
176 DISPID dispIdMember
, REFIID riid
, LCID lcid
,
177 WORD wFlags
, DISPPARAMS
* pDispParams
, VARIANT
* pVarResult
,
178 EXCEPINFO
* pExcepInfo
, UINT
* puArgErr
)
180 xsltemplate
*This
= impl_from_IXSLTemplate( iface
);
181 return IDispatchEx_Invoke(&This
->dispex
.IDispatchEx_iface
,
182 dispIdMember
, riid
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
185 static HRESULT WINAPI
xsltemplate_putref_stylesheet( IXSLTemplate
*iface
,
188 xsltemplate
*This
= impl_from_IXSLTemplate( iface
);
190 TRACE("(%p)->(%p)\n", This
, node
);
194 xsltemplate_set_node(This
, NULL
);
198 /* FIXME: test for document type */
199 xsltemplate_set_node(This
, node
);
204 static HRESULT WINAPI
xsltemplate_get_stylesheet( IXSLTemplate
*iface
,
207 xsltemplate
*This
= impl_from_IXSLTemplate( iface
);
209 FIXME("(%p)->(%p): stub\n", This
, node
);
213 static HRESULT WINAPI
xsltemplate_createProcessor( IXSLTemplate
*iface
,
214 IXSLProcessor
**processor
)
216 xsltemplate
*This
= impl_from_IXSLTemplate( iface
);
218 TRACE("(%p)->(%p)\n", This
, processor
);
220 if (!processor
) return E_INVALIDARG
;
222 return XSLProcessor_create(This
, processor
);
225 static const struct IXSLTemplateVtbl XSLTemplateVtbl
=
227 xsltemplate_QueryInterface
,
230 xsltemplate_GetTypeInfoCount
,
231 xsltemplate_GetTypeInfo
,
232 xsltemplate_GetIDsOfNames
,
234 xsltemplate_putref_stylesheet
,
235 xsltemplate_get_stylesheet
,
236 xsltemplate_createProcessor
239 static const tid_t xsltemplate_iface_tids
[] = {
244 static dispex_static_data_t xsltemplate_dispex
= {
248 xsltemplate_iface_tids
251 HRESULT
XSLTemplate_create(void **ppObj
)
255 TRACE("(%p)\n", ppObj
);
257 This
= heap_alloc( sizeof (*This
) );
259 return E_OUTOFMEMORY
;
261 This
->IXSLTemplate_iface
.lpVtbl
= &XSLTemplateVtbl
;
264 init_dispex(&This
->dispex
, (IUnknown
*)&This
->IXSLTemplate_iface
, &xsltemplate_dispex
);
266 *ppObj
= &This
->IXSLTemplate_iface
;
268 TRACE("returning iface %p\n", *ppObj
);
273 /*** IXSLProcessor ***/
274 static HRESULT WINAPI
xslprocessor_QueryInterface(
275 IXSLProcessor
*iface
,
279 xslprocessor
*This
= impl_from_IXSLProcessor( iface
);
280 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppvObject
);
282 if ( IsEqualGUID( riid
, &IID_IXSLProcessor
) ||
283 IsEqualGUID( riid
, &IID_IDispatch
) ||
284 IsEqualGUID( riid
, &IID_IUnknown
) )
288 else if (dispex_query_interface(&This
->dispex
, riid
, ppvObject
))
290 return *ppvObject
? S_OK
: E_NOINTERFACE
;
294 FIXME("Unsupported interface %s\n", debugstr_guid(riid
));
296 return E_NOINTERFACE
;
299 IUnknown_AddRef((IUnknown
*)*ppvObject
);
303 static ULONG WINAPI
xslprocessor_AddRef( IXSLProcessor
*iface
)
305 xslprocessor
*This
= impl_from_IXSLProcessor( iface
);
306 ULONG ref
= InterlockedIncrement( &This
->ref
);
307 TRACE("(%p)->(%d)\n", This
, ref
);
311 static ULONG WINAPI
xslprocessor_Release( IXSLProcessor
*iface
)
313 xslprocessor
*This
= impl_from_IXSLProcessor( iface
);
314 ULONG ref
= InterlockedDecrement( &This
->ref
);
316 TRACE("(%p)->(%d)\n", This
, ref
);
319 struct xslprocessor_par
*par
, *par2
;
321 if (This
->input
) IXMLDOMNode_Release(This
->input
);
322 if (This
->output
) IStream_Release(This
->output
);
323 SysFreeString(This
->outstr
);
325 LIST_FOR_EACH_ENTRY_SAFE(par
, par2
, &This
->params
.list
, struct xslprocessor_par
, entry
)
326 xslprocessor_par_free(&This
->params
, par
);
328 IXSLTemplate_Release(&This
->stylesheet
->IXSLTemplate_iface
);
329 release_dispex(&This
->dispex
);
336 static HRESULT WINAPI
xslprocessor_GetTypeInfoCount( IXSLProcessor
*iface
, UINT
* pctinfo
)
338 xslprocessor
*This
= impl_from_IXSLProcessor( iface
);
339 return IDispatchEx_GetTypeInfoCount(&This
->dispex
.IDispatchEx_iface
, pctinfo
);
342 static HRESULT WINAPI
xslprocessor_GetTypeInfo(
343 IXSLProcessor
*iface
,
344 UINT iTInfo
, LCID lcid
,
345 ITypeInfo
** ppTInfo
)
347 xslprocessor
*This
= impl_from_IXSLProcessor( iface
);
348 return IDispatchEx_GetTypeInfo(&This
->dispex
.IDispatchEx_iface
,
349 iTInfo
, lcid
, ppTInfo
);
352 static HRESULT WINAPI
xslprocessor_GetIDsOfNames(
353 IXSLProcessor
*iface
,
354 REFIID riid
, LPOLESTR
* rgszNames
,
355 UINT cNames
, LCID lcid
, DISPID
* rgDispId
)
357 xslprocessor
*This
= impl_from_IXSLProcessor( iface
);
358 return IDispatchEx_GetIDsOfNames(&This
->dispex
.IDispatchEx_iface
,
359 riid
, rgszNames
, cNames
, lcid
, rgDispId
);
362 static HRESULT WINAPI
xslprocessor_Invoke(
363 IXSLProcessor
*iface
,
364 DISPID dispIdMember
, REFIID riid
, LCID lcid
,
365 WORD wFlags
, DISPPARAMS
* pDispParams
, VARIANT
* pVarResult
,
366 EXCEPINFO
* pExcepInfo
, UINT
* puArgErr
)
368 xslprocessor
*This
= impl_from_IXSLProcessor( iface
);
369 return IDispatchEx_Invoke(&This
->dispex
.IDispatchEx_iface
,
370 dispIdMember
, riid
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
373 static HRESULT WINAPI
xslprocessor_put_input( IXSLProcessor
*iface
, VARIANT input
)
375 xslprocessor
*This
= impl_from_IXSLProcessor( iface
);
376 IXMLDOMNode
*input_node
;
379 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&input
));
381 /* try IXMLDOMNode directly first */
382 if (V_VT(&input
) == VT_UNKNOWN
)
383 hr
= IUnknown_QueryInterface(V_UNKNOWN(&input
), &IID_IXMLDOMNode
, (void**)&input_node
);
384 else if (V_VT(&input
) == VT_DISPATCH
)
385 hr
= IDispatch_QueryInterface(V_DISPATCH(&input
), &IID_IXMLDOMNode
, (void**)&input_node
);
388 IXMLDOMDocument
*doc
;
390 hr
= DOMDocument_create(MSXML_DEFAULT
, (void**)&doc
);
395 hr
= IXMLDOMDocument_load(doc
, input
, &b
);
397 hr
= IXMLDOMDocument_QueryInterface(doc
, &IID_IXMLDOMNode
, (void**)&input_node
);
398 IXMLDOMDocument_Release(doc
);
404 if (This
->input
) IXMLDOMNode_Release(This
->input
);
405 This
->input
= input_node
;
411 static HRESULT WINAPI
xslprocessor_get_input( IXSLProcessor
*iface
, VARIANT
*input
)
413 xslprocessor
*This
= impl_from_IXSLProcessor( iface
);
415 FIXME("(%p)->(%p): stub\n", This
, input
);
419 static HRESULT WINAPI
xslprocessor_get_ownerTemplate(
420 IXSLProcessor
*iface
,
421 IXSLTemplate
**template)
423 xslprocessor
*This
= impl_from_IXSLProcessor( iface
);
425 FIXME("(%p)->(%p): stub\n", This
, template);
429 static HRESULT WINAPI
xslprocessor_setStartMode(
430 IXSLProcessor
*iface
,
434 xslprocessor
*This
= impl_from_IXSLProcessor( iface
);
436 FIXME("(%p)->(%s %s): stub\n", This
, debugstr_w(p
), debugstr_w(uri
));
440 static HRESULT WINAPI
xslprocessor_get_startMode(
441 IXSLProcessor
*iface
,
444 xslprocessor
*This
= impl_from_IXSLProcessor( iface
);
446 FIXME("(%p)->(%p): stub\n", This
, p
);
450 static HRESULT WINAPI
xslprocessor_get_startModeURI(
451 IXSLProcessor
*iface
,
454 xslprocessor
*This
= impl_from_IXSLProcessor( iface
);
456 FIXME("(%p)->(%p): stub\n", This
, uri
);
460 static HRESULT WINAPI
xslprocessor_put_output(
461 IXSLProcessor
*iface
,
464 xslprocessor
*This
= impl_from_IXSLProcessor( iface
);
468 FIXME("(%p)->(%s): semi-stub\n", This
, debugstr_variant(&output
));
470 switch (V_VT(&output
))
477 hr
= IUnknown_QueryInterface(V_UNKNOWN(&output
), &IID_IStream
, (void**)&stream
);
485 if (This
->output
) IStream_Release(This
->output
);
486 This
->output
= stream
;
492 static HRESULT WINAPI
xslprocessor_get_output(
493 IXSLProcessor
*iface
,
496 xslprocessor
*This
= impl_from_IXSLProcessor( iface
);
498 TRACE("(%p)->(%p)\n", This
, output
);
500 if (!output
) return E_INVALIDARG
;
504 V_VT(output
) = VT_UNKNOWN
;
505 V_UNKNOWN(output
) = (IUnknown
*)This
->output
;
506 IStream_AddRef(This
->output
);
508 else if (This
->outstr
)
510 V_VT(output
) = VT_BSTR
;
511 V_BSTR(output
) = SysAllocString(This
->outstr
);
514 V_VT(output
) = VT_EMPTY
;
519 static HRESULT WINAPI
xslprocessor_transform(
520 IXSLProcessor
*iface
,
524 xslprocessor
*This
= impl_from_IXSLProcessor( iface
);
527 TRACE("(%p)->(%p)\n", This
, ret
);
529 if (!ret
) return E_INVALIDARG
;
531 SysFreeString(This
->outstr
);
533 hr
= node_transform_node_params(get_node_obj(This
->input
), This
->stylesheet
->node
, &This
->outstr
, &This
->params
);
540 /* output to stream */
541 hr
= IStream_Write(This
->output
, This
->outstr
, SysStringByteLen(This
->outstr
), &len
);
542 *ret
= len
== SysStringByteLen(This
->outstr
) ? VARIANT_TRUE
: VARIANT_FALSE
;
546 *ret
= VARIANT_FALSE
;
550 FIXME("libxml2 is required but wasn't present at compile time\n");
555 static HRESULT WINAPI
xslprocessor_reset( IXSLProcessor
*iface
)
557 xslprocessor
*This
= impl_from_IXSLProcessor( iface
);
559 FIXME("(%p): stub\n", This
);
563 static HRESULT WINAPI
xslprocessor_get_readyState(
564 IXSLProcessor
*iface
,
567 xslprocessor
*This
= impl_from_IXSLProcessor( iface
);
569 FIXME("(%p)->(%p): stub\n", This
, state
);
573 static HRESULT
xslprocessor_set_parvalue(const VARIANT
*var
, struct xslprocessor_par
*par
)
581 par
->value
= SysAllocString(V_BSTR(var
));
582 if (!par
->value
) hr
= E_OUTOFMEMORY
;
586 FIXME("value type %d not handled\n", V_VT(var
));
593 static HRESULT WINAPI
xslprocessor_addParameter(
594 IXSLProcessor
*iface
,
599 xslprocessor
*This
= impl_from_IXSLProcessor( iface
);
600 struct xslprocessor_par
*cur
, *par
= NULL
;
603 TRACE("(%p)->(%s %s %s)\n", This
, debugstr_w(p
), debugstr_variant(&var
),
607 FIXME("namespace uri is not supported\n");
609 /* search for existing parameter first */
610 LIST_FOR_EACH_ENTRY(cur
, &This
->params
.list
, struct xslprocessor_par
, entry
)
612 if (!strcmpW(cur
->name
, p
))
619 /* override with new value or add new parameter */
622 if (V_VT(&var
) == VT_NULL
|| V_VT(&var
) == VT_EMPTY
)
624 /* remove parameter */
625 xslprocessor_par_free(&This
->params
, par
);
628 SysFreeString(par
->value
);
634 par
= heap_alloc(sizeof(struct xslprocessor_par
));
635 if (!par
) return E_OUTOFMEMORY
;
637 par
->name
= SysAllocString(p
);
641 return E_OUTOFMEMORY
;
643 list_add_tail(&This
->params
.list
, &par
->entry
);
644 This
->params
.count
++;
647 hr
= xslprocessor_set_parvalue(&var
, par
);
649 xslprocessor_par_free(&This
->params
, par
);
654 static HRESULT WINAPI
xslprocessor_addObject(
655 IXSLProcessor
*iface
,
659 xslprocessor
*This
= impl_from_IXSLProcessor( iface
);
661 FIXME("(%p)->(%p %s): stub\n", This
, obj
, debugstr_w(uri
));
665 static HRESULT WINAPI
xslprocessor_get_stylesheet(
666 IXSLProcessor
*iface
,
669 xslprocessor
*This
= impl_from_IXSLProcessor( iface
);
671 FIXME("(%p)->(%p): stub\n", This
, node
);
675 static const struct IXSLProcessorVtbl XSLProcessorVtbl
=
677 xslprocessor_QueryInterface
,
679 xslprocessor_Release
,
680 xslprocessor_GetTypeInfoCount
,
681 xslprocessor_GetTypeInfo
,
682 xslprocessor_GetIDsOfNames
,
684 xslprocessor_put_input
,
685 xslprocessor_get_input
,
686 xslprocessor_get_ownerTemplate
,
687 xslprocessor_setStartMode
,
688 xslprocessor_get_startMode
,
689 xslprocessor_get_startModeURI
,
690 xslprocessor_put_output
,
691 xslprocessor_get_output
,
692 xslprocessor_transform
,
694 xslprocessor_get_readyState
,
695 xslprocessor_addParameter
,
696 xslprocessor_addObject
,
697 xslprocessor_get_stylesheet
700 static const tid_t xslprocessor_iface_tids
[] = {
705 static dispex_static_data_t xslprocessor_dispex
= {
709 xslprocessor_iface_tids
712 HRESULT
XSLProcessor_create(xsltemplate
*template, IXSLProcessor
**ppObj
)
716 TRACE("(%p)\n", ppObj
);
718 This
= heap_alloc( sizeof (*This
) );
720 return E_OUTOFMEMORY
;
722 This
->IXSLProcessor_iface
.lpVtbl
= &XSLProcessorVtbl
;
727 list_init(&This
->params
.list
);
728 This
->params
.count
= 0;
729 This
->stylesheet
= template;
730 IXSLTemplate_AddRef(&template->IXSLTemplate_iface
);
731 init_dispex(&This
->dispex
, (IUnknown
*)&This
->IXSLProcessor_iface
, &xslprocessor_dispex
);
733 *ppObj
= &This
->IXSLProcessor_iface
;
735 TRACE("returning iface %p\n", *ppObj
);