2 * Node list implementation
4 * Copyright 2005 Mike McCormack
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32 #include "msxml_private.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(msxml
);
42 #ifdef HAVE_LIBXSLT_PATTERN_H
43 #include <libxslt/pattern.h>
45 #ifdef HAVE_LIBXSLT_TRANSFORM_H
46 #include <libxslt/transform.h>
50 xsltTransformContextPtr ctxt
;
51 xsltCompMatchPtr pattern
;
52 xsltStylesheetPtr sheet
;
55 static void xlst_info_init( struct xslt_info
*info
)
62 static int create_xslt_parser( struct xslt_info
*info
, xmlNodePtr node
, const xmlChar
*str
)
64 info
->sheet
= xsltNewStylesheet();
68 info
->ctxt
= xsltNewTransformContext( info
->sheet
, node
->doc
);
72 info
->pattern
= xsltCompilePattern( str
, node
->doc
,
73 node
, info
->sheet
, info
->ctxt
);
79 void free_xslt_info( struct xslt_info
*info
)
82 xsltFreeCompMatchList( info
->pattern
);
84 xsltFreeStylesheet( info
->sheet
);
86 xsltFreeTransformContext( info
->ctxt
);
89 static HRESULT
xslt_next_match( struct xslt_info
*info
, xmlNodePtr
*node
)
94 /* make sure that the current element matches the pattern */
99 r
= xsltTestCompMatchList( info
->ctxt
, *node
, info
->pattern
);
102 TRACE("Matched %p (%s)\n", *node
, (*node
)->name
);
107 ERR("Pattern match failed\n");
110 *node
= (*node
)->next
;
121 static void xlst_info_init( struct xslt_info
*info
)
125 void free_xslt_info( struct xslt_info
*info
)
129 static int create_xslt_parser( struct xslt_info
*info
, xmlNodePtr node
, const xmlChar
*str
)
131 MESSAGE("libxslt was missing at compile time\n");
135 static HRESULT
xslt_next_match( struct xslt_info
*info
, xmlNodePtr
*node
)
142 typedef struct _xmlnodelist
144 const struct IXMLDOMNodeListVtbl
*lpVtbl
;
148 struct xslt_info xinfo
;
151 static inline xmlnodelist
*impl_from_IXMLDOMNodeList( IXMLDOMNodeList
*iface
)
153 return (xmlnodelist
*)((char*)iface
- FIELD_OFFSET(xmlnodelist
, lpVtbl
));
156 static HRESULT WINAPI
xmlnodelist_QueryInterface(
157 IXMLDOMNodeList
*iface
,
161 TRACE("%p %s %p\n", iface
, debugstr_guid(riid
), ppvObject
);
163 if ( IsEqualGUID( riid
, &IID_IUnknown
) ||
164 IsEqualGUID( riid
, &IID_IDispatch
) ||
165 IsEqualGUID( riid
, &IID_IXMLDOMNodeList
) )
170 return E_NOINTERFACE
;
172 IXMLDOMNodeList_AddRef( iface
);
177 static ULONG WINAPI
xmlnodelist_AddRef(
178 IXMLDOMNodeList
*iface
)
180 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
181 return InterlockedIncrement( &This
->ref
);
184 static ULONG WINAPI
xmlnodelist_Release(
185 IXMLDOMNodeList
*iface
)
187 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
190 ref
= InterlockedDecrement( &This
->ref
);
193 free_xslt_info( &This
->xinfo
);
194 xmldoc_release( This
->node
->doc
);
195 HeapFree( GetProcessHeap(), 0, This
);
201 static HRESULT WINAPI
xmlnodelist_GetTypeInfoCount(
202 IXMLDOMNodeList
*iface
,
209 static HRESULT WINAPI
xmlnodelist_GetTypeInfo(
210 IXMLDOMNodeList
*iface
,
213 ITypeInfo
** ppTInfo
)
219 static HRESULT WINAPI
xmlnodelist_GetIDsOfNames(
220 IXMLDOMNodeList
*iface
,
231 static HRESULT WINAPI
xmlnodelist_Invoke(
232 IXMLDOMNodeList
*iface
,
237 DISPPARAMS
* pDispParams
,
239 EXCEPINFO
* pExcepInfo
,
246 static HRESULT WINAPI
xmlnodelist_get_item(
247 IXMLDOMNodeList
* iface
,
249 IXMLDOMNode
** listItem
)
251 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
256 TRACE("%p %ld\n", This
, index
);
267 r
= xslt_next_match( &This
->xinfo
, &curr
);
268 if(FAILED(r
) || !curr
) return S_FALSE
;
269 if(nodeIndex
++ == index
) break;
272 if(!curr
) return S_FALSE
;
274 *listItem
= create_node( curr
);
279 static HRESULT WINAPI
xmlnodelist_get_length(
280 IXMLDOMNodeList
* iface
,
288 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
292 if (This
->node
== NULL
) {
297 for(curr
= This
->node
; curr
; curr
= curr
->next
)
299 r
= xslt_next_match( &This
->xinfo
, &curr
);
300 if(FAILED(r
) || !curr
) break;
304 *listLength
= nodeCount
;
308 static HRESULT WINAPI
xmlnodelist_nextNode(
309 IXMLDOMNodeList
* iface
,
310 IXMLDOMNode
** nextItem
)
312 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
315 TRACE("%p %p\n", This
, nextItem
);
317 r
= xslt_next_match( &This
->xinfo
, &This
->current
);
324 *nextItem
= create_node( This
->current
);
325 This
->current
= This
->current
->next
;
329 static HRESULT WINAPI
xmlnodelist_reset(
330 IXMLDOMNodeList
* iface
)
332 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
335 This
->current
= This
->node
;
339 static HRESULT WINAPI
xmlnodelist__newEnum(
340 IXMLDOMNodeList
* iface
,
348 static const struct IXMLDOMNodeListVtbl xmlnodelist_vtbl
=
350 xmlnodelist_QueryInterface
,
353 xmlnodelist_GetTypeInfoCount
,
354 xmlnodelist_GetTypeInfo
,
355 xmlnodelist_GetIDsOfNames
,
357 xmlnodelist_get_item
,
358 xmlnodelist_get_length
,
359 xmlnodelist_nextNode
,
361 xmlnodelist__newEnum
,
364 static xmlnodelist
*new_nodelist( xmlNodePtr node
)
366 xmlnodelist
*nodelist
;
368 nodelist
= HeapAlloc( GetProcessHeap(), 0, sizeof *nodelist
);
372 nodelist
->lpVtbl
= &xmlnodelist_vtbl
;
374 nodelist
->node
= node
;
375 nodelist
->current
= node
;
376 xlst_info_init( &nodelist
->xinfo
);
378 xmldoc_add_ref( node
->doc
);
383 IXMLDOMNodeList
* create_nodelist( xmlNodePtr node
)
385 xmlnodelist
*nodelist
= new_nodelist( node
);
388 return (IXMLDOMNodeList
*) &nodelist
->lpVtbl
;
391 IXMLDOMNodeList
* create_filtered_nodelist( xmlNodePtr node
, const xmlChar
*str
)
393 xmlnodelist
*This
= new_nodelist( node
);
395 if (create_xslt_parser( &This
->xinfo
, node
, str
))
396 return (IXMLDOMNodeList
*) &This
->lpVtbl
;
398 IXMLDOMNodeList_Release( (IXMLDOMNodeList
*) &This
->lpVtbl
);