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 static 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
));
201 return E_NOINTERFACE
;
204 IXMLDOMNodeList_AddRef( iface
);
209 static ULONG WINAPI
xmlnodelist_AddRef(
210 IXMLDOMNodeList
*iface
)
212 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
213 return InterlockedIncrement( &This
->ref
);
216 static ULONG WINAPI
xmlnodelist_Release(
217 IXMLDOMNodeList
*iface
)
219 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
222 ref
= InterlockedDecrement( &This
->ref
);
225 free_xslt_info( &This
->xinfo
);
226 if(This
->node
) xmldoc_release( This
->node
->doc
);
227 HeapFree( GetProcessHeap(), 0, This
);
233 static HRESULT WINAPI
xmlnodelist_GetTypeInfoCount(
234 IXMLDOMNodeList
*iface
,
241 static HRESULT WINAPI
xmlnodelist_GetTypeInfo(
242 IXMLDOMNodeList
*iface
,
245 ITypeInfo
** ppTInfo
)
251 static HRESULT WINAPI
xmlnodelist_GetIDsOfNames(
252 IXMLDOMNodeList
*iface
,
263 static HRESULT WINAPI
xmlnodelist_Invoke(
264 IXMLDOMNodeList
*iface
,
269 DISPPARAMS
* pDispParams
,
271 EXCEPINFO
* pExcepInfo
,
278 static HRESULT WINAPI
xmlnodelist_get_item(
279 IXMLDOMNodeList
* iface
,
281 IXMLDOMNode
** listItem
)
283 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
284 xmlNodePtr curr
, tmp
;
285 xmlNodePtr
*top_level_node
= NULL
;
289 TRACE("%p %ld\n", This
, index
);
298 if(This
->enum_children
)
301 top_level_node
= &tmp
;
306 r
= xslt_next_match( &This
->xinfo
, &curr
, top_level_node
);
307 if(FAILED(r
) || !curr
) return S_FALSE
;
308 if(nodeIndex
++ == index
) break;
309 curr
= get_next_node(&This
->xinfo
, curr
, top_level_node
);
311 if(!curr
) return S_FALSE
;
313 *listItem
= create_node( curr
);
318 static HRESULT WINAPI
xmlnodelist_get_length(
319 IXMLDOMNodeList
* iface
,
323 xmlNodePtr curr
, tmp
;
324 xmlNodePtr
*top_level_node
= NULL
;
328 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
332 if (This
->node
== NULL
) {
339 if(This
->enum_children
)
342 top_level_node
= &tmp
;
347 r
= xslt_next_match( &This
->xinfo
, &curr
, top_level_node
);
348 if(FAILED(r
) || !curr
) break;
350 curr
= get_next_node(&This
->xinfo
, curr
, top_level_node
);
353 *listLength
= nodeCount
;
357 static HRESULT WINAPI
xmlnodelist_nextNode(
358 IXMLDOMNodeList
* iface
,
359 IXMLDOMNode
** nextItem
)
361 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
363 xmlNodePtr
*top_level_node
= NULL
;
365 TRACE("%p %p\n", This
, nextItem
);
369 if(This
->enum_children
)
370 top_level_node
= &This
->top_level_node
;
372 r
= xslt_next_match( &This
->xinfo
, &This
->current
, top_level_node
);
379 *nextItem
= create_node( This
->current
);
380 This
->current
= get_next_node(&This
->xinfo
, This
->current
, top_level_node
);
384 static HRESULT WINAPI
xmlnodelist_reset(
385 IXMLDOMNodeList
* iface
)
387 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
390 This
->current
= This
->node
;
394 static HRESULT WINAPI
xmlnodelist__newEnum(
395 IXMLDOMNodeList
* iface
,
403 static const struct IXMLDOMNodeListVtbl xmlnodelist_vtbl
=
405 xmlnodelist_QueryInterface
,
408 xmlnodelist_GetTypeInfoCount
,
409 xmlnodelist_GetTypeInfo
,
410 xmlnodelist_GetIDsOfNames
,
412 xmlnodelist_get_item
,
413 xmlnodelist_get_length
,
414 xmlnodelist_nextNode
,
416 xmlnodelist__newEnum
,
419 static xmlnodelist
*new_nodelist( xmlNodePtr node
)
421 xmlnodelist
*nodelist
;
423 nodelist
= HeapAlloc( GetProcessHeap(), 0, sizeof *nodelist
);
427 nodelist
->lpVtbl
= &xmlnodelist_vtbl
;
429 nodelist
->node
= node
;
430 nodelist
->current
= node
;
431 nodelist
->top_level_node
= node
;
432 nodelist
->enum_children
= FALSE
;
433 xslt_info_init( &nodelist
->xinfo
);
435 if(node
) xmldoc_add_ref( node
->doc
);
440 IXMLDOMNodeList
* create_nodelist( xmlNodePtr node
)
442 xmlnodelist
*nodelist
= new_nodelist( node
);
443 return (IXMLDOMNodeList
*) &nodelist
->lpVtbl
;
446 IXMLDOMNodeList
* create_filtered_nodelist( xmlNodePtr node
, const xmlChar
*str
, BOOL enum_children
)
448 xmlnodelist
*This
= new_nodelist( node
);
449 if (create_xslt_parser( &This
->xinfo
, node
, str
))
451 This
->enum_children
= enum_children
;
452 return (IXMLDOMNodeList
*) &This
->lpVtbl
;
455 IXMLDOMNodeList_Release( (IXMLDOMNodeList
*) &This
->lpVtbl
);