Implement selectSingleNode.
[wine/hacks.git] / dlls / msxml3 / node.c
blob2014fc5ff4df15ab63362690a32c132874725c77
1 /*
2 * Node 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
21 #include "config.h"
23 #define COBJMACROS
25 #include <stdarg.h>
26 #include <assert.h>
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winuser.h"
30 #include "winnls.h"
31 #include "ole2.h"
32 #include "ocidl.h"
33 #include "msxml.h"
34 #include "xmldom.h"
35 #include "msxml.h"
37 #include "msxml_private.h"
39 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
43 #ifdef HAVE_LIBXML2
45 typedef struct _xmlnode
47 const struct IXMLDOMNodeVtbl *lpVtbl;
48 LONG ref;
49 xmlNodePtr node;
50 } xmlnode;
52 static inline xmlnode *impl_from_IXMLDOMNode( IXMLDOMNode *iface )
54 return (xmlnode *)((char*)iface - FIELD_OFFSET(xmlnode, lpVtbl));
57 xmlNodePtr xmlNodePtr_from_domnode( IXMLDOMNode *iface, xmlElementType type )
59 xmlnode *This;
61 if ( !iface )
62 return NULL;
63 This = impl_from_IXMLDOMNode( iface );
64 if ( !This->node )
65 return NULL;
66 if ( type && This->node->type != type )
67 return NULL;
68 return This->node;
71 static HRESULT WINAPI xmlnode_QueryInterface(
72 IXMLDOMNode *iface,
73 REFIID riid,
74 void** ppvObject )
76 TRACE("%p %s %p\n", iface, debugstr_guid(riid), ppvObject);
78 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
79 IsEqualGUID( riid, &IID_IDispatch ) ||
80 IsEqualGUID( riid, &IID_IXMLDOMNode ) )
82 *ppvObject = iface;
84 else
85 return E_NOINTERFACE;
87 IXMLDOMElement_AddRef( iface );
89 return S_OK;
92 static ULONG WINAPI xmlnode_AddRef(
93 IXMLDOMNode *iface )
95 xmlnode *This = impl_from_IXMLDOMNode( iface );
96 return InterlockedIncrement( &This->ref );
99 static ULONG WINAPI xmlnode_Release(
100 IXMLDOMNode *iface )
102 xmlnode *This = impl_from_IXMLDOMNode( iface );
103 ULONG ref;
105 ref = InterlockedDecrement( &This->ref );
106 if ( ref == 0 )
108 if( This->node->type == XML_DOCUMENT_NODE )
110 xmlFreeDoc( (xmlDocPtr) This->node );
112 else
114 IXMLDOMNode *root;
115 assert( This->node->doc );
116 root = This->node->doc->_private;
117 assert( root );
118 IXMLDOMNode_Release( root );
119 This->node->_private = NULL;
121 HeapFree( GetProcessHeap(), 0, This );
124 return ref;
127 static HRESULT WINAPI xmlnode_GetTypeInfoCount(
128 IXMLDOMNode *iface,
129 UINT* pctinfo )
131 FIXME("\n");
132 return E_NOTIMPL;
135 static HRESULT WINAPI xmlnode_GetTypeInfo(
136 IXMLDOMNode *iface,
137 UINT iTInfo,
138 LCID lcid,
139 ITypeInfo** ppTInfo )
141 FIXME("\n");
142 return E_NOTIMPL;
145 static HRESULT WINAPI xmlnode_GetIDsOfNames(
146 IXMLDOMNode *iface,
147 REFIID riid,
148 LPOLESTR* rgszNames,
149 UINT cNames,
150 LCID lcid,
151 DISPID* rgDispId )
153 FIXME("\n");
154 return E_NOTIMPL;
157 static HRESULT WINAPI xmlnode_Invoke(
158 IXMLDOMNode *iface,
159 DISPID dispIdMember,
160 REFIID riid,
161 LCID lcid,
162 WORD wFlags,
163 DISPPARAMS* pDispParams,
164 VARIANT* pVarResult,
165 EXCEPINFO* pExcepInfo,
166 UINT* puArgErr )
168 FIXME("\n");
169 return E_NOTIMPL;
172 static HRESULT WINAPI xmlnode_get_nodeName(
173 IXMLDOMNode *iface,
174 BSTR* name)
176 xmlnode *This = impl_from_IXMLDOMNode( iface );
177 const xmlChar *str;
179 TRACE("%p\n", This );
181 if (!name)
182 return E_INVALIDARG;
184 if ( !This->node )
185 return E_FAIL;
187 switch( This->node->type )
189 case XML_TEXT_NODE:
190 str = (const xmlChar*) "#text";
191 break;
192 case XML_DOCUMENT_NODE:
193 str = (const xmlChar*) "#document";
194 break;
195 default:
196 str = This->node->name;
197 break;
200 *name = bstr_from_xmlChar( str );
201 if (!*name)
202 return S_FALSE;
204 return S_OK;
207 BSTR bstr_from_xmlChar( const xmlChar *buf )
209 DWORD len;
210 LPWSTR str;
211 BSTR bstr;
213 if ( !buf )
214 return NULL;
216 len = MultiByteToWideChar( CP_UTF8, 0, (LPCSTR) buf, -1, NULL, 0 );
217 str = (LPWSTR) HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) );
218 if ( !str )
219 return NULL;
220 MultiByteToWideChar( CP_UTF8, 0, (LPCSTR) buf, -1, str, len );
221 bstr = SysAllocString( str );
222 HeapFree( GetProcessHeap(), 0, str );
223 return bstr;
226 static HRESULT WINAPI xmlnode_get_nodeValue(
227 IXMLDOMNode *iface,
228 VARIANT* value)
230 xmlnode *This = impl_from_IXMLDOMNode( iface );
231 HRESULT r = S_FALSE;
233 TRACE("%p %p\n", This, value);
235 V_BSTR(value) = NULL;
236 V_VT(value) = VT_NULL;
238 switch ( This->node->type )
240 case XML_ATTRIBUTE_NODE:
241 V_VT(value) = VT_BSTR;
242 V_BSTR(value) = bstr_from_xmlChar( This->node->name );
243 r = S_OK;
244 break;
245 case XML_TEXT_NODE:
246 V_VT(value) = VT_BSTR;
247 V_BSTR(value) = bstr_from_xmlChar( This->node->content );
248 r = S_OK;
249 break;
250 case XML_ELEMENT_NODE:
251 case XML_DOCUMENT_NODE:
252 /* these seem to return NULL */
253 break;
254 case XML_PI_NODE:
255 default:
256 FIXME("node %p type %d\n", This, This->node->type);
259 TRACE("%p returned %s\n", This, debugstr_w( V_BSTR(value) ) );
261 return r;
264 static HRESULT WINAPI xmlnode_put_nodeValue(
265 IXMLDOMNode *iface,
266 VARIANT value)
268 FIXME("\n");
269 return E_NOTIMPL;
272 static HRESULT WINAPI xmlnode_get_nodeType(
273 IXMLDOMNode *iface,
274 DOMNodeType* type)
276 xmlnode *This = impl_from_IXMLDOMNode( iface );
278 TRACE("%p %p\n", This, type);
280 assert( NODE_ELEMENT == XML_ELEMENT_NODE );
281 assert( NODE_NOTATION == XML_NOTATION_NODE );
283 *type = This->node->type;
285 return S_OK;
288 static HRESULT get_node(
289 xmlnode *This,
290 const char *name,
291 xmlNodePtr node,
292 IXMLDOMNode **out )
294 TRACE("%p->%s %p\n", This, name, node );
296 if ( !out )
297 return E_INVALIDARG;
298 *out = create_node( node );
299 if (!*out)
300 return S_FALSE;
301 return S_OK;
304 static HRESULT WINAPI xmlnode_get_parentNode(
305 IXMLDOMNode *iface,
306 IXMLDOMNode** parent)
308 xmlnode *This = impl_from_IXMLDOMNode( iface );
309 return get_node( This, "parent", This->node->parent, parent );
312 static HRESULT WINAPI xmlnode_get_childNodes(
313 IXMLDOMNode *iface,
314 IXMLDOMNodeList** childList)
316 xmlnode *This = impl_from_IXMLDOMNode( iface );
318 TRACE("%p %p\n", This, childList );
320 if ( !childList )
321 return E_INVALIDARG;
323 switch(This->node->type)
325 case XML_ELEMENT_NODE:
326 *childList = create_filtered_nodelist( This->node->children, (const xmlChar *)"*" );
327 break;
329 case XML_ATTRIBUTE_NODE:
330 *childList = create_filtered_nodelist( This->node->children, (const xmlChar *)"node()" );
331 break;
333 default:
334 FIXME("unhandled node type %d\n", This->node->type);
335 break;
338 if (!*childList)
339 return S_FALSE;
340 return S_OK;
343 static HRESULT WINAPI xmlnode_get_firstChild(
344 IXMLDOMNode *iface,
345 IXMLDOMNode** firstChild)
347 xmlnode *This = impl_from_IXMLDOMNode( iface );
348 return get_node( This, "firstChild", This->node->children, firstChild );
351 static HRESULT WINAPI xmlnode_get_lastChild(
352 IXMLDOMNode *iface,
353 IXMLDOMNode** lastChild)
355 xmlnode *This = impl_from_IXMLDOMNode( iface );
356 return get_node( This, "lastChild", This->node->last, lastChild );
359 static HRESULT WINAPI xmlnode_get_previousSibling(
360 IXMLDOMNode *iface,
361 IXMLDOMNode** previousSibling)
363 xmlnode *This = impl_from_IXMLDOMNode( iface );
364 return get_node( This, "previous", This->node->prev, previousSibling );
367 static HRESULT WINAPI xmlnode_get_nextSibling(
368 IXMLDOMNode *iface,
369 IXMLDOMNode** nextSibling)
371 xmlnode *This = impl_from_IXMLDOMNode( iface );
372 return get_node( This, "next", This->node->next, nextSibling );
375 static HRESULT WINAPI xmlnode_get_attributes(
376 IXMLDOMNode *iface,
377 IXMLDOMNamedNodeMap** attributeMap)
379 xmlnode *This = impl_from_IXMLDOMNode( iface );
380 TRACE("%p\n", This);
381 *attributeMap = create_nodemap( iface );
382 return S_OK;
385 static HRESULT WINAPI xmlnode_insertBefore(
386 IXMLDOMNode *iface,
387 IXMLDOMNode* newChild,
388 VARIANT refChild,
389 IXMLDOMNode** outNewChild)
391 FIXME("\n");
392 return E_NOTIMPL;
395 static HRESULT WINAPI xmlnode_replaceChild(
396 IXMLDOMNode *iface,
397 IXMLDOMNode* newChild,
398 IXMLDOMNode* oldChild,
399 IXMLDOMNode** outOldChild)
401 FIXME("\n");
402 return E_NOTIMPL;
405 static HRESULT WINAPI xmlnode_removeChild(
406 IXMLDOMNode *iface,
407 IXMLDOMNode* childNode,
408 IXMLDOMNode** oldChild)
410 FIXME("\n");
411 return E_NOTIMPL;
414 static HRESULT WINAPI xmlnode_appendChild(
415 IXMLDOMNode *iface,
416 IXMLDOMNode* newChild,
417 IXMLDOMNode** outNewChild)
419 FIXME("\n");
420 return E_NOTIMPL;
423 static HRESULT WINAPI xmlnode_hasChildNodes(
424 IXMLDOMNode *iface,
425 VARIANT_BOOL* hasChild)
427 xmlnode *This = impl_from_IXMLDOMNode( iface );
429 TRACE("%p\n", This);
431 if (!hasChild)
432 return E_INVALIDARG;
433 if (!This->node->children)
435 *hasChild = VARIANT_FALSE;
436 return S_FALSE;
439 *hasChild = VARIANT_TRUE;
440 return S_OK;
443 static HRESULT WINAPI xmlnode_get_ownerDocument(
444 IXMLDOMNode *iface,
445 IXMLDOMDocument** DOMDocument)
447 FIXME("\n");
448 return E_NOTIMPL;
451 static HRESULT WINAPI xmlnode_cloneNode(
452 IXMLDOMNode *iface,
453 VARIANT_BOOL deep,
454 IXMLDOMNode** cloneRoot)
456 FIXME("\n");
457 return E_NOTIMPL;
460 static HRESULT WINAPI xmlnode_get_nodeTypeString(
461 IXMLDOMNode *iface,
462 BSTR* xmlnodeType)
464 FIXME("\n");
465 return E_NOTIMPL;
468 static HRESULT WINAPI xmlnode_get_text(
469 IXMLDOMNode *iface,
470 BSTR* text)
472 xmlnode *This = impl_from_IXMLDOMNode( iface );
473 xmlNodePtr child;
474 BSTR str = NULL;
476 TRACE("%p\n", This);
478 if ( !text )
479 return E_INVALIDARG;
481 child = This->node->children;
482 if ( child && child->type == XML_TEXT_NODE )
483 str = bstr_from_xmlChar( child->content );
485 TRACE("%p %s\n", This, debugstr_w(str) );
486 *text = str;
488 return S_OK;
491 static HRESULT WINAPI xmlnode_put_text(
492 IXMLDOMNode *iface,
493 BSTR text)
495 FIXME("\n");
496 return E_NOTIMPL;
499 static HRESULT WINAPI xmlnode_get_specified(
500 IXMLDOMNode *iface,
501 VARIANT_BOOL* isSpecified)
503 FIXME("\n");
504 return E_NOTIMPL;
507 static HRESULT WINAPI xmlnode_get_definition(
508 IXMLDOMNode *iface,
509 IXMLDOMNode** definitionNode)
511 FIXME("\n");
512 return E_NOTIMPL;
515 static HRESULT WINAPI xmlnode_get_nodeTypedValue(
516 IXMLDOMNode *iface,
517 VARIANT* typedValue)
519 FIXME("\n");
520 return E_NOTIMPL;
523 static HRESULT WINAPI xmlnode_put_nodeTypedValue(
524 IXMLDOMNode *iface,
525 VARIANT typedValue)
527 FIXME("\n");
528 return E_NOTIMPL;
531 static HRESULT WINAPI xmlnode_get_dataType(
532 IXMLDOMNode *iface,
533 VARIANT* dataTypeName)
535 FIXME("\n");
536 return E_NOTIMPL;
539 static HRESULT WINAPI xmlnode_put_dataType(
540 IXMLDOMNode *iface,
541 BSTR dataTypeName)
543 FIXME("\n");
544 return E_NOTIMPL;
547 static HRESULT WINAPI xmlnode_get_xml(
548 IXMLDOMNode *iface,
549 BSTR* xmlString)
551 FIXME("\n");
552 return E_NOTIMPL;
555 static HRESULT WINAPI xmlnode_transformNode(
556 IXMLDOMNode *iface,
557 IXMLDOMNode* styleSheet,
558 BSTR* xmlString)
560 FIXME("\n");
561 return E_NOTIMPL;
564 static HRESULT WINAPI xmlnode_selectNodes(
565 IXMLDOMNode *iface,
566 BSTR queryString,
567 IXMLDOMNodeList** resultList)
569 xmlnode *This = impl_from_IXMLDOMNode( iface );
570 xmlChar *str = NULL;
571 HRESULT r = E_FAIL;
573 TRACE("%p %s %p\n", This, debugstr_w(queryString), resultList );
575 str = xmlChar_from_wchar( queryString );
576 if (!str)
577 return r;
579 *resultList = create_filtered_nodelist( This->node->children, str );
580 HeapFree( GetProcessHeap(), 0, str );
581 return S_OK;
584 static HRESULT WINAPI xmlnode_selectSingleNode(
585 IXMLDOMNode *iface,
586 BSTR queryString,
587 IXMLDOMNode** resultNode)
589 xmlnode *This = impl_from_IXMLDOMNode( iface );
590 IXMLDOMNodeList *list;
591 HRESULT r;
593 TRACE("%p %s %p\n", This, debugstr_w(queryString), resultNode );
595 r = IXMLDOMNode_selectNodes(iface, queryString, &list);
596 if(SUCCEEDED(r))
598 r = IXMLDOMNodeList_nextNode(list, resultNode);
599 IXMLDOMNodeList_Release(list);
601 return r;
604 static HRESULT WINAPI xmlnode_get_parsed(
605 IXMLDOMNode *iface,
606 VARIANT_BOOL* isParsed)
608 FIXME("\n");
609 return E_NOTIMPL;
612 static HRESULT WINAPI xmlnode_get_namespaceURI(
613 IXMLDOMNode *iface,
614 BSTR* namespaceURI)
616 FIXME("\n");
617 return E_NOTIMPL;
620 static HRESULT WINAPI xmlnode_get_prefix(
621 IXMLDOMNode *iface,
622 BSTR* prefixString)
624 FIXME("\n");
625 return E_NOTIMPL;
628 static HRESULT WINAPI xmlnode_get_baseName(
629 IXMLDOMNode *iface,
630 BSTR* nameString)
632 xmlnode *This = impl_from_IXMLDOMNode( iface );
633 BSTR str = NULL;
634 HRESULT r = S_FALSE;
636 TRACE("%p %p\n", This, nameString );
638 if ( !nameString )
639 return E_INVALIDARG;
641 switch ( This->node->type )
643 case XML_ELEMENT_NODE:
644 case XML_ATTRIBUTE_NODE:
645 str = bstr_from_xmlChar( This->node->name );
646 r = S_OK;
647 break;
648 case XML_TEXT_NODE:
649 break;
650 default:
651 ERR("Unhandled type %d\n", This->node->type );
652 break;
655 TRACE("returning %08lx str = %s\n", r, debugstr_w( str ) );
657 *nameString = str;
658 return r;
661 static HRESULT WINAPI xmlnode_transformNodeToObject(
662 IXMLDOMNode *iface,
663 IXMLDOMNode* stylesheet,
664 VARIANT outputObject)
666 FIXME("\n");
667 return E_NOTIMPL;
670 static const struct IXMLDOMNodeVtbl xmlnode_vtbl =
672 xmlnode_QueryInterface,
673 xmlnode_AddRef,
674 xmlnode_Release,
675 xmlnode_GetTypeInfoCount,
676 xmlnode_GetTypeInfo,
677 xmlnode_GetIDsOfNames,
678 xmlnode_Invoke,
679 xmlnode_get_nodeName,
680 xmlnode_get_nodeValue,
681 xmlnode_put_nodeValue,
682 xmlnode_get_nodeType,
683 xmlnode_get_parentNode,
684 xmlnode_get_childNodes,
685 xmlnode_get_firstChild,
686 xmlnode_get_lastChild,
687 xmlnode_get_previousSibling,
688 xmlnode_get_nextSibling,
689 xmlnode_get_attributes,
690 xmlnode_insertBefore,
691 xmlnode_replaceChild,
692 xmlnode_removeChild,
693 xmlnode_appendChild,
694 xmlnode_hasChildNodes,
695 xmlnode_get_ownerDocument,
696 xmlnode_cloneNode,
697 xmlnode_get_nodeTypeString,
698 xmlnode_get_text,
699 xmlnode_put_text,
700 xmlnode_get_specified,
701 xmlnode_get_definition,
702 xmlnode_get_nodeTypedValue,
703 xmlnode_put_nodeTypedValue,
704 xmlnode_get_dataType,
705 xmlnode_put_dataType,
706 xmlnode_get_xml,
707 xmlnode_transformNode,
708 xmlnode_selectNodes,
709 xmlnode_selectSingleNode,
710 xmlnode_get_parsed,
711 xmlnode_get_namespaceURI,
712 xmlnode_get_prefix,
713 xmlnode_get_baseName,
714 xmlnode_transformNodeToObject,
717 IXMLDOMNode *create_node( xmlNodePtr node )
719 xmlnode *This;
721 if ( !node )
722 return NULL;
724 assert( node->doc );
726 /* if an interface already exists for this node, return it */
727 if ( node->_private )
729 IXMLDOMNode *n = node->_private;
730 IXMLDOMNode_AddRef( n );
731 return n;
735 * Try adding a reference to the IXMLDOMNode implementation
736 * containing the document's root element.
738 if ( node->type != XML_DOCUMENT_NODE )
740 IXMLDOMNode *root = NULL;
742 root = node->doc->_private;
743 assert( root );
744 IXMLDOMNode_AddRef( root );
746 else
747 assert( node->doc == (xmlDocPtr) node );
749 This = HeapAlloc( GetProcessHeap(), 0, sizeof *This );
750 if ( !This )
751 return NULL;
753 This->lpVtbl = &xmlnode_vtbl;
754 This->ref = 1;
755 This->node = node;
757 /* remember which interface we associated with this node */
758 node->_private = This;
760 return (IXMLDOMNode*) &This->lpVtbl;
763 #endif