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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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 xslt_info_init( struct xslt_info
*info
)
62 static int create_xslt_parser( struct xslt_info
*info
, xmlNodePtr node
, const xmlChar
*str
)
66 info
->sheet
= xsltNewStylesheet();
70 info
->ctxt
= xsltNewTransformContext( info
->sheet
, node
->doc
);
74 info
->pattern
= xsltCompilePattern( str
, node
->doc
,
75 node
, info
->sheet
, info
->ctxt
);
81 void free_xslt_info( struct xslt_info
*info
)
84 xsltFreeCompMatchList( info
->pattern
);
86 xsltFreeStylesheet( info
->sheet
);
88 xsltFreeTransformContext( info
->ctxt
);
92 static xmlNodePtr
get_next_node( struct xslt_info
*info
, xmlNodePtr node
, xmlNodePtr
*top_level_node
);
94 static HRESULT
xslt_next_match( struct xslt_info
*info
, xmlNodePtr
*node
, xmlNodePtr
*top_level_node
)
99 /* make sure that the current element matches the pattern */
104 r
= xsltTestCompMatchList( info
->ctxt
, *node
, info
->pattern
);
107 TRACE("Matched %p (%s)\n", *node
, (*node
)->name
);
112 ERR("Pattern match failed\n");
115 *node
= get_next_node(info
, *node
, top_level_node
);
126 static void xslt_info_init( struct xslt_info
*info
)
130 void free_xslt_info( struct xslt_info
*info
)
134 static int create_xslt_parser( struct xslt_info
*info
, xmlNodePtr node
, const xmlChar
*str
)
136 MESSAGE("libxslt was missing at compile time\n");
140 static HRESULT
xslt_next_match( struct xslt_info
*info
, xmlNodePtr
*node
, xmlNodePtr
*top_level_node
)
147 static xmlNodePtr
get_next_node( struct xslt_info
*info
, xmlNodePtr node
, xmlNodePtr
*top_level_node
)
149 if(!top_level_node
) return node
->next
;
151 if(node
->children
) return node
->children
;
154 if(node
== *top_level_node
)
155 *top_level_node
= node
->next
;
159 if(node
!= *top_level_node
&& node
->parent
)
161 if(node
->parent
== *top_level_node
)
162 *top_level_node
= node
->parent
->next
;
163 return node
->parent
->next
;
168 typedef struct _xmlnodelist
170 const struct IXMLDOMNodeListVtbl
*lpVtbl
;
174 xmlNodePtr top_level_node
;
176 struct xslt_info xinfo
;
179 static inline xmlnodelist
*impl_from_IXMLDOMNodeList( IXMLDOMNodeList
*iface
)
181 return (xmlnodelist
*)((char*)iface
- FIELD_OFFSET(xmlnodelist
, lpVtbl
));
184 static HRESULT WINAPI
xmlnodelist_QueryInterface(
185 IXMLDOMNodeList
*iface
,
189 TRACE("%p %s %p\n", iface
, debugstr_guid(riid
), ppvObject
);
191 if ( IsEqualGUID( riid
, &IID_IUnknown
) ||
192 IsEqualGUID( riid
, &IID_IDispatch
) ||
193 IsEqualGUID( riid
, &IID_IXMLDOMNodeList
) )
199 FIXME("interface %s not implemented\n", debugstr_guid(riid
));
200 return E_NOINTERFACE
;
203 IXMLDOMNodeList_AddRef( iface
);
208 static ULONG WINAPI
xmlnodelist_AddRef(
209 IXMLDOMNodeList
*iface
)
211 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
212 return InterlockedIncrement( &This
->ref
);
215 static ULONG WINAPI
xmlnodelist_Release(
216 IXMLDOMNodeList
*iface
)
218 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
221 ref
= InterlockedDecrement( &This
->ref
);
224 free_xslt_info( &This
->xinfo
);
225 if(This
->node
) xmldoc_release( This
->node
->doc
);
226 HeapFree( GetProcessHeap(), 0, This
);
232 static HRESULT WINAPI
xmlnodelist_GetTypeInfoCount(
233 IXMLDOMNodeList
*iface
,
240 static HRESULT WINAPI
xmlnodelist_GetTypeInfo(
241 IXMLDOMNodeList
*iface
,
244 ITypeInfo
** ppTInfo
)
250 static HRESULT WINAPI
xmlnodelist_GetIDsOfNames(
251 IXMLDOMNodeList
*iface
,
262 static HRESULT WINAPI
xmlnodelist_Invoke(
263 IXMLDOMNodeList
*iface
,
268 DISPPARAMS
* pDispParams
,
270 EXCEPINFO
* pExcepInfo
,
277 static HRESULT WINAPI
xmlnodelist_get_item(
278 IXMLDOMNodeList
* iface
,
280 IXMLDOMNode
** listItem
)
282 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
283 xmlNodePtr curr
, tmp
;
284 xmlNodePtr
*top_level_node
= NULL
;
288 TRACE("%p %ld\n", This
, index
);
297 if(This
->enum_children
)
300 top_level_node
= &tmp
;
305 r
= xslt_next_match( &This
->xinfo
, &curr
, top_level_node
);
306 if(FAILED(r
) || !curr
) return S_FALSE
;
307 if(nodeIndex
++ == index
) break;
308 curr
= get_next_node(&This
->xinfo
, curr
, top_level_node
);
310 if(!curr
) return S_FALSE
;
312 *listItem
= create_node( curr
);
317 static HRESULT WINAPI
xmlnodelist_get_length(
318 IXMLDOMNodeList
* iface
,
322 xmlNodePtr curr
, tmp
;
323 xmlNodePtr
*top_level_node
= NULL
;
327 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
331 if (This
->node
== NULL
) {
336 if(This
->enum_children
)
339 top_level_node
= &tmp
;
342 for(curr
= This
->node
; curr
; curr
= get_next_node(&This
->xinfo
, curr
, top_level_node
))
344 r
= xslt_next_match( &This
->xinfo
, &curr
, top_level_node
);
345 if(FAILED(r
) || !curr
) break;
349 *listLength
= nodeCount
;
353 static HRESULT WINAPI
xmlnodelist_nextNode(
354 IXMLDOMNodeList
* iface
,
355 IXMLDOMNode
** nextItem
)
357 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
359 xmlNodePtr
*top_level_node
= NULL
;
361 TRACE("%p %p\n", This
, nextItem
);
363 if(This
->enum_children
)
364 top_level_node
= &This
->top_level_node
;
366 r
= xslt_next_match( &This
->xinfo
, &This
->current
, top_level_node
);
373 *nextItem
= create_node( This
->current
);
374 This
->current
= get_next_node(&This
->xinfo
, This
->current
, top_level_node
);
378 static HRESULT WINAPI
xmlnodelist_reset(
379 IXMLDOMNodeList
* iface
)
381 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
384 This
->current
= This
->node
;
388 static HRESULT WINAPI
xmlnodelist__newEnum(
389 IXMLDOMNodeList
* iface
,
397 static const struct IXMLDOMNodeListVtbl xmlnodelist_vtbl
=
399 xmlnodelist_QueryInterface
,
402 xmlnodelist_GetTypeInfoCount
,
403 xmlnodelist_GetTypeInfo
,
404 xmlnodelist_GetIDsOfNames
,
406 xmlnodelist_get_item
,
407 xmlnodelist_get_length
,
408 xmlnodelist_nextNode
,
410 xmlnodelist__newEnum
,
413 static xmlnodelist
*new_nodelist( xmlNodePtr node
)
415 xmlnodelist
*nodelist
;
417 nodelist
= HeapAlloc( GetProcessHeap(), 0, sizeof *nodelist
);
421 nodelist
->lpVtbl
= &xmlnodelist_vtbl
;
423 nodelist
->node
= node
;
424 nodelist
->current
= node
;
425 nodelist
->top_level_node
= node
;
426 nodelist
->enum_children
= FALSE
;
427 xslt_info_init( &nodelist
->xinfo
);
429 if(node
) xmldoc_add_ref( node
->doc
);
434 IXMLDOMNodeList
* create_nodelist( xmlNodePtr node
)
436 xmlnodelist
*nodelist
= new_nodelist( node
);
437 return (IXMLDOMNodeList
*) &nodelist
->lpVtbl
;
440 IXMLDOMNodeList
* create_filtered_nodelist( xmlNodePtr node
, const xmlChar
*str
, BOOL enum_children
)
442 xmlnodelist
*This
= new_nodelist( node
);
443 if (create_xslt_parser( &This
->xinfo
, node
, str
))
445 This
->enum_children
= enum_children
;
446 return (IXMLDOMNodeList
*) &This
->lpVtbl
;
449 IXMLDOMNodeList_Release( (IXMLDOMNodeList
*) &This
->lpVtbl
);