msxml3: Use xmlNodeGetContent to get text data.
[wine] / dlls / msxml3 / node.c
1 /*
2  *    Node implementation
3  *
4  * Copyright 2005 Mike McCormack
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include "config.h"
22
23 #define COBJMACROS
24
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 "msxml2.h"
33
34 #include "msxml_private.h"
35
36 #ifdef HAVE_LIBXML2
37 # include <libxml/HTMLtree.h>
38 #endif
39
40 #include "wine/debug.h"
41
42 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
43
44 #ifdef HAVE_LIBXML2
45
46 static const WCHAR szBinBase64[]  = {'b','i','n','.','b','a','s','e','6','4',0};
47 static const WCHAR szString[]     = {'s','t','r','i','n','g',0};
48 static const WCHAR szNumber[]     = {'n','u','m','b','e','r',0};
49 static const WCHAR szInt[]        = {'I','n','t',0};
50 static const WCHAR szFixed[]      = {'F','i','x','e','d','.','1','4','.','4',0};
51 static const WCHAR szBoolean[]    = {'B','o','o','l','e','a','n',0};
52 static const WCHAR szDateTime[]   = {'d','a','t','e','T','i','m','e',0};
53 static const WCHAR szDateTimeTZ[] = {'d','a','t','e','T','i','m','e','.','t','z',0};
54 static const WCHAR szDate[]       = {'D','a','t','e',0};
55 static const WCHAR szTime[]       = {'T','i','m','e',0};
56 static const WCHAR szTimeTZ[]     = {'T','i','m','e','.','t','z',0};
57 static const WCHAR szI1[]         = {'i','1',0};
58 static const WCHAR szI2[]         = {'i','2',0};
59 static const WCHAR szI4[]         = {'i','4',0};
60 static const WCHAR szIU1[]        = {'u','i','1',0};
61 static const WCHAR szIU2[]        = {'u','i','2',0};
62 static const WCHAR szIU4[]        = {'u','i','4',0};
63 static const WCHAR szR4[]         = {'r','4',0};
64 static const WCHAR szR8[]         = {'r','8',0};
65 static const WCHAR szFloat[]      = {'f','l','o','a','t',0};
66 static const WCHAR szUUID[]       = {'u','u','i','d',0};
67 static const WCHAR szBinHex[]     = {'b','i','n','.','h','e','x',0};
68
69 static inline xmlnode *impl_from_InternalUnknown( IUnknown *iface )
70 {
71     return (xmlnode *)((char*)iface - FIELD_OFFSET(xmlnode, lpInternalUnkVtbl));
72 }
73
74 xmlNodePtr xmlNodePtr_from_domnode( IXMLDOMNode *iface, xmlElementType type )
75 {
76     xmlnode *This;
77
78     if ( !iface )
79         return NULL;
80     This = impl_from_IXMLDOMNode( iface );
81     if ( !This->node )
82         return NULL;
83     if ( type && This->node->type != type )
84         return NULL;
85     return This->node;
86 }
87
88 static HRESULT WINAPI xmlnode_QueryInterface(
89     IXMLDOMNode *iface,
90     REFIID riid,
91     void** ppvObject )
92 {
93     xmlnode *This = impl_from_IXMLDOMNode( iface );
94     TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
95
96     return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObject);
97 }
98
99 static ULONG WINAPI xmlnode_AddRef(
100     IXMLDOMNode *iface )
101 {
102     xmlnode *This = impl_from_IXMLDOMNode( iface );
103     return IUnknown_AddRef(This->pUnkOuter);
104 }
105
106 static ULONG WINAPI xmlnode_Release(
107     IXMLDOMNode *iface )
108 {
109     xmlnode *This = impl_from_IXMLDOMNode( iface );
110     return IUnknown_Release(This->pUnkOuter);
111 }
112
113 static HRESULT WINAPI xmlnode_GetTypeInfoCount(
114     IXMLDOMNode *iface,
115     UINT* pctinfo )
116 {
117     xmlnode *This = impl_from_IXMLDOMNode( iface );
118
119     TRACE("(%p)->(%p)\n", This, pctinfo);
120
121     *pctinfo = 1;
122
123     return S_OK;
124 }
125
126 static HRESULT WINAPI xmlnode_GetTypeInfo(
127     IXMLDOMNode *iface,
128     UINT iTInfo,
129     LCID lcid,
130     ITypeInfo** ppTInfo )
131 {
132     xmlnode *This = impl_from_IXMLDOMNode( iface );
133     HRESULT hr;
134
135     TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
136
137     hr = get_typeinfo(IXMLDOMNode_tid, ppTInfo);
138
139     return hr;
140 }
141
142 static HRESULT WINAPI xmlnode_GetIDsOfNames(
143     IXMLDOMNode *iface,
144     REFIID riid,
145     LPOLESTR* rgszNames,
146     UINT cNames,
147     LCID lcid,
148     DISPID* rgDispId )
149 {
150     xmlnode *This = impl_from_IXMLDOMNode( iface );
151
152     ITypeInfo *typeinfo;
153     HRESULT hr;
154
155     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
156           lcid, rgDispId);
157
158     if(!rgszNames || cNames == 0 || !rgDispId)
159         return E_INVALIDARG;
160
161     hr = get_typeinfo(IXMLDOMNode_tid, &typeinfo);
162     if(SUCCEEDED(hr))
163     {
164         hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
165         ITypeInfo_Release(typeinfo);
166     }
167
168     return hr;
169 }
170
171 static HRESULT WINAPI xmlnode_Invoke(
172     IXMLDOMNode *iface,
173     DISPID dispIdMember,
174     REFIID riid,
175     LCID lcid,
176     WORD wFlags,
177     DISPPARAMS* pDispParams,
178     VARIANT* pVarResult,
179     EXCEPINFO* pExcepInfo,
180     UINT* puArgErr )
181 {
182     xmlnode *This = impl_from_IXMLDOMNode( iface );
183     ITypeInfo *typeinfo;
184     HRESULT hr;
185
186     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
187           lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
188
189     hr = get_typeinfo(IXMLDOMNode_tid, &typeinfo);
190     if(SUCCEEDED(hr))
191     {
192         hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
193                 pVarResult, pExcepInfo, puArgErr);
194         ITypeInfo_Release(typeinfo);
195     }
196
197     return hr;
198 }
199
200 static HRESULT WINAPI xmlnode_get_nodeName(
201     IXMLDOMNode *iface,
202     BSTR* name)
203 {
204     xmlnode *This = impl_from_IXMLDOMNode( iface );
205     const xmlChar *str;
206
207     TRACE("%p\n", This );
208
209     if (!name)
210         return E_INVALIDARG;
211
212     if ( !This->node )
213         return E_FAIL;
214
215     switch( This->node->type )
216     {
217     case XML_CDATA_SECTION_NODE:
218         str = (const xmlChar*) "#cdata-section";
219         break;
220     case XML_COMMENT_NODE:
221         str = (const xmlChar*) "#comment";
222         break;
223     case XML_DOCUMENT_FRAG_NODE:
224         str = (const xmlChar*) "#document-fragment";
225         break;
226     case XML_TEXT_NODE:
227          str = (const xmlChar*) "#text";
228          break;
229     case XML_DOCUMENT_NODE:
230          str = (const xmlChar*) "#document";
231             break;
232         case XML_ATTRIBUTE_NODE:
233         case XML_ELEMENT_NODE:
234         case XML_PI_NODE:
235         str = This->node->name;
236             break;
237     default:
238         FIXME("nodeName not mapped correctly (%d)\n", This->node->type);
239         str = This->node->name;
240         break;
241     }
242
243     *name = bstr_from_xmlChar( str );
244     if (!*name)
245         return S_FALSE;
246
247     return S_OK;
248 }
249
250 BSTR bstr_from_xmlChar( const xmlChar *buf )
251 {
252     DWORD len;
253     LPWSTR str;
254     BSTR bstr;
255
256     if ( !buf )
257         return NULL;
258
259     len = MultiByteToWideChar( CP_UTF8, 0, (LPCSTR) buf, -1, NULL, 0 );
260     str = HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) );
261     if ( !str )
262         return NULL;
263     MultiByteToWideChar( CP_UTF8, 0, (LPCSTR) buf, -1, str, len );
264     bstr = SysAllocString( str );
265     HeapFree( GetProcessHeap(), 0, str );
266     return bstr;
267 }
268
269 static HRESULT WINAPI xmlnode_get_nodeValue(
270     IXMLDOMNode *iface,
271     VARIANT* value)
272 {
273     xmlnode *This = impl_from_IXMLDOMNode( iface );
274     HRESULT r = S_FALSE;
275
276     TRACE("%p %p\n", This, value);
277
278     if(!value)
279         return E_INVALIDARG;
280
281     V_BSTR(value) = NULL;
282     V_VT(value) = VT_NULL;
283
284     switch ( This->node->type )
285     {
286     case XML_CDATA_SECTION_NODE:
287     case XML_COMMENT_NODE:
288     case XML_PI_NODE:
289     case XML_ATTRIBUTE_NODE:
290       {
291         xmlChar *content = xmlNodeGetContent(This->node);
292         V_VT(value) = VT_BSTR;
293         V_BSTR(value) = bstr_from_xmlChar( content );
294         xmlFree(content);
295         r = S_OK;
296         break;
297       }
298     case XML_TEXT_NODE:
299         V_VT(value) = VT_BSTR;
300         V_BSTR(value) = bstr_from_xmlChar( This->node->content );
301         r = S_OK;
302         break;
303     case XML_ELEMENT_NODE:
304     case XML_DOCUMENT_NODE:
305         /* these seem to return NULL */
306         break;
307
308     default:
309         FIXME("node %p type %d\n", This, This->node->type);
310     }
311  
312     TRACE("%p returned %s\n", This, debugstr_w( V_BSTR(value) ) );
313
314     return r;
315 }
316
317 static HRESULT WINAPI xmlnode_put_nodeValue(
318     IXMLDOMNode *iface,
319     VARIANT value)
320 {
321     xmlnode *This = impl_from_IXMLDOMNode( iface );
322     HRESULT hr;
323     xmlChar *str = NULL;
324     VARIANT string_value;
325
326     TRACE("%p type(%d)\n", This, This->node->type);
327
328     VariantInit(&string_value);
329     hr = VariantChangeType(&string_value, &value, 0, VT_BSTR);
330     if(FAILED(hr))
331     {
332         VariantClear(&string_value);
333         WARN("Couldn't convert to VT_BSTR\n");
334         return hr;
335     }
336
337     hr = S_FALSE;
338     /* Document, Document Fragment, Document Type, Element,
339         Entity, Entity Reference, Notation aren't supported. */
340     switch ( This->node->type )
341     {
342     case XML_ATTRIBUTE_NODE:
343     case XML_CDATA_SECTION_NODE:
344     case XML_COMMENT_NODE:
345     case XML_PI_NODE:
346     case XML_TEXT_NODE:
347       {
348         str = xmlChar_from_wchar((WCHAR*)V_BSTR(&string_value));
349         xmlNodeSetContent(This->node, str);
350         HeapFree(GetProcessHeap(),0,str);
351         hr = S_OK;
352         break;
353       }
354     default:
355         /* Do nothing for unsupported types. */
356         break;
357     }
358
359     VariantClear(&string_value);
360
361     return hr;
362 }
363
364 static HRESULT WINAPI xmlnode_get_nodeType(
365     IXMLDOMNode *iface,
366     DOMNodeType* type)
367 {
368     xmlnode *This = impl_from_IXMLDOMNode( iface );
369
370     TRACE("%p %p\n", This, type);
371
372     assert( NODE_ELEMENT == XML_ELEMENT_NODE );
373     assert( NODE_NOTATION == XML_NOTATION_NODE );
374
375     *type = This->node->type;
376
377     return S_OK;
378 }
379
380 static HRESULT get_node(
381     xmlnode *This,
382     const char *name,
383     xmlNodePtr node,
384     IXMLDOMNode **out )
385 {
386     TRACE("%p->%s %p\n", This, name, node );
387
388     if ( !out )
389         return E_INVALIDARG;
390     *out = create_node( node );
391     if (!*out)
392         return S_FALSE;
393     return S_OK;
394 }
395
396 static HRESULT WINAPI xmlnode_get_parentNode(
397     IXMLDOMNode *iface,
398     IXMLDOMNode** parent)
399 {
400     xmlnode *This = impl_from_IXMLDOMNode( iface );
401     return get_node( This, "parent", This->node->parent, parent );
402 }
403
404 static HRESULT WINAPI xmlnode_get_childNodes(
405     IXMLDOMNode *iface,
406     IXMLDOMNodeList** childList)
407 {
408     xmlnode *This = impl_from_IXMLDOMNode( iface );
409
410     TRACE("%p %p\n", This, childList );
411
412     if ( !childList )
413         return E_INVALIDARG;
414
415     *childList = create_children_nodelist(This->node);
416     if (*childList == NULL)
417         return E_OUTOFMEMORY;
418
419     return S_OK;
420 }
421
422 static HRESULT WINAPI xmlnode_get_firstChild(
423     IXMLDOMNode *iface,
424     IXMLDOMNode** firstChild)
425 {
426     xmlnode *This = impl_from_IXMLDOMNode( iface );
427     return get_node( This, "firstChild", This->node->children, firstChild );
428 }
429
430 static HRESULT WINAPI xmlnode_get_lastChild(
431     IXMLDOMNode *iface,
432     IXMLDOMNode** lastChild)
433 {
434     xmlnode *This = impl_from_IXMLDOMNode( iface );
435
436     TRACE("%p\n", This );
437
438     if (!lastChild)
439         return E_INVALIDARG;
440
441     switch( This->node->type )
442     {
443     /* CDATASection, Comment, PI and Text Nodes do not support lastChild */
444     case XML_TEXT_NODE:
445     case XML_CDATA_SECTION_NODE:
446     case XML_PI_NODE:
447     case XML_COMMENT_NODE:
448         *lastChild = NULL;
449         return S_FALSE;
450     default:
451         return get_node( This, "lastChild", This->node->last, lastChild );
452     }
453 }
454
455 static HRESULT WINAPI xmlnode_get_previousSibling(
456     IXMLDOMNode *iface,
457     IXMLDOMNode** previousSibling)
458 {
459     xmlnode *This = impl_from_IXMLDOMNode( iface );
460
461     TRACE("%p\n", This );
462
463     if (!previousSibling)
464         return E_INVALIDARG;
465
466     switch( This->node->type )
467     {
468     /* Attribute, Document and Document Fragment Nodes do not support previousSibling */
469     case XML_DOCUMENT_NODE:
470     case XML_DOCUMENT_FRAG_NODE:
471     case XML_ATTRIBUTE_NODE:
472         *previousSibling = NULL;
473         return S_FALSE;
474     default:
475         return get_node( This, "previous", This->node->prev, previousSibling );
476     }
477 }
478
479 static HRESULT WINAPI xmlnode_get_nextSibling(
480     IXMLDOMNode *iface,
481     IXMLDOMNode** nextSibling)
482 {
483     xmlnode *This = impl_from_IXMLDOMNode( iface );
484
485     TRACE("%p\n", This );
486
487     if (!nextSibling)
488         return E_INVALIDARG;
489
490     switch( This->node->type )
491     {
492     /* Attribute, Document and Document Fragment Nodes do not support nextSibling */
493     case XML_DOCUMENT_NODE:
494     case XML_DOCUMENT_FRAG_NODE:
495     case XML_ATTRIBUTE_NODE:
496         *nextSibling = NULL;
497         return S_FALSE;
498     default:
499         return get_node( This, "next", This->node->next, nextSibling );
500     }
501 }
502
503 static HRESULT WINAPI xmlnode_get_attributes(
504     IXMLDOMNode *iface,
505     IXMLDOMNamedNodeMap** attributeMap)
506 {
507     xmlnode *This = impl_from_IXMLDOMNode( iface );
508     TRACE("%p\n", This);
509
510     if (!attributeMap)
511         return E_INVALIDARG;
512
513     switch( This->node->type )
514     {
515     /* Attribute, CDataSection, Comment, Documents, Documents Fragments,
516        Entity and Text Nodes does not support get_attributes */
517     case XML_ATTRIBUTE_NODE:
518     case XML_CDATA_SECTION_NODE:
519     case XML_COMMENT_NODE:
520     case XML_DOCUMENT_NODE:
521     case XML_DOCUMENT_FRAG_NODE:
522     case XML_ENTITY_NODE:
523     case XML_ENTITY_REF_NODE:
524     case XML_TEXT_NODE:
525         *attributeMap = NULL;
526         return S_FALSE;
527     default:
528         *attributeMap = create_nodemap( iface );
529         return S_OK;
530     }
531 }
532
533 static HRESULT WINAPI xmlnode_insertBefore(
534     IXMLDOMNode *iface,
535     IXMLDOMNode* newChild,
536     VARIANT refChild,
537     IXMLDOMNode** outNewChild)
538 {
539     xmlnode *This = impl_from_IXMLDOMNode( iface );
540     xmlNodePtr before_node, new_child_node;
541     IXMLDOMNode *before = NULL, *new;
542     HRESULT hr;
543
544     TRACE("(%p)->(%p,var,%p)\n",This,newChild,outNewChild);
545
546     if (!newChild)
547         return E_INVALIDARG;
548
549     switch(V_VT(&refChild))
550     {
551     case VT_EMPTY:
552     case VT_NULL:
553         break;
554
555     case VT_UNKNOWN:
556         hr = IUnknown_QueryInterface(V_UNKNOWN(&refChild), &IID_IXMLDOMNode, (LPVOID)&before);
557         if(FAILED(hr)) return hr;
558         break;
559
560     case VT_DISPATCH:
561         hr = IDispatch_QueryInterface(V_DISPATCH(&refChild), &IID_IXMLDOMNode, (LPVOID)&before);
562         if(FAILED(hr)) return hr;
563         break;
564
565     default:
566         FIXME("refChild var type %x\n", V_VT(&refChild));
567         return E_FAIL;
568     }
569
570     IXMLDOMNode_QueryInterface(newChild, &IID_IXMLDOMNode, (LPVOID)&new);
571     new_child_node = impl_from_IXMLDOMNode(new)->node;
572     TRACE("new_child_node %p This->node %p\n", new_child_node, This->node);
573
574     if(!new_child_node->parent)
575         if(xmldoc_remove_orphan(new_child_node->doc, new_child_node) != S_OK)
576             WARN("%p is not an orphan of %p\n", new_child_node, new_child_node->doc);
577
578     if(before)
579     {
580         before_node = impl_from_IXMLDOMNode(before)->node;
581         xmlAddPrevSibling(before_node, new_child_node);
582         IXMLDOMNode_Release(before);
583     }
584     else
585     {
586         xmlAddChild(This->node, new_child_node);
587     }
588
589     IXMLDOMNode_Release(new);
590     IXMLDOMNode_AddRef(newChild);
591     if(outNewChild)
592         *outNewChild = newChild;
593
594     TRACE("ret S_OK\n");
595     return S_OK;
596 }
597
598 static HRESULT WINAPI xmlnode_replaceChild(
599     IXMLDOMNode *iface,
600     IXMLDOMNode* newChild,
601     IXMLDOMNode* oldChild,
602     IXMLDOMNode** outOldChild)
603 {
604     xmlnode *This = impl_from_IXMLDOMNode( iface );
605     xmlNode *old_child_ptr, *new_child_ptr;
606     xmlDocPtr leaving_doc;
607     xmlNode *my_ancestor;
608     IXMLDOMNode *realOldChild;
609     HRESULT hr;
610
611     TRACE("%p->(%p,%p,%p)\n",This,newChild,oldChild,outOldChild);
612
613     /* Do not believe any documentation telling that newChild == NULL
614        means removal. It does certainly *not* apply to msxml3! */
615     if(!newChild || !oldChild)
616         return E_INVALIDARG;
617
618     if(outOldChild)
619         *outOldChild = NULL;
620
621     hr = IXMLDOMNode_QueryInterface(oldChild,&IID_IXMLDOMNode,(LPVOID*)&realOldChild);
622     if(FAILED(hr))
623         return hr;
624
625     old_child_ptr = impl_from_IXMLDOMNode(realOldChild)->node;
626     IXMLDOMNode_Release(realOldChild);
627     if(old_child_ptr->parent != This->node)
628     {
629         WARN("childNode %p is not a child of %p\n", oldChild, iface);
630         return E_INVALIDARG;
631     }
632
633     new_child_ptr = impl_from_IXMLDOMNode(newChild)->node;
634     my_ancestor = This->node;
635     while(my_ancestor)
636     {
637         if(my_ancestor == new_child_ptr)
638         {
639             WARN("tried to create loop\n");
640             return E_FAIL;
641         }
642         my_ancestor = my_ancestor->parent;
643     }
644
645     if(!new_child_ptr->parent)
646         if(xmldoc_remove_orphan(new_child_ptr->doc, new_child_ptr) != S_OK)
647             WARN("%p is not an orphan of %p\n", new_child_ptr, new_child_ptr->doc);
648
649     leaving_doc = new_child_ptr->doc;
650     xmldoc_add_ref(old_child_ptr->doc);
651     xmlReplaceNode(old_child_ptr, new_child_ptr);
652     xmldoc_release(leaving_doc);
653
654     xmldoc_add_orphan(old_child_ptr->doc, old_child_ptr);
655
656     if(outOldChild)
657     {
658         IXMLDOMNode_AddRef(oldChild);
659         *outOldChild = oldChild;
660     }
661
662     return S_OK;
663 }
664
665 static HRESULT WINAPI xmlnode_removeChild(
666     IXMLDOMNode *iface,
667     IXMLDOMNode* childNode,
668     IXMLDOMNode** oldChild)
669 {
670     xmlnode *This = impl_from_IXMLDOMNode( iface );
671     xmlNode *child_node_ptr;
672     HRESULT hr;
673     IXMLDOMNode *child;
674
675     TRACE("%p->(%p, %p)\n", This, childNode, oldChild);
676
677     if(!childNode) return E_INVALIDARG;
678
679     if(oldChild)
680         *oldChild = NULL;
681
682     hr = IXMLDOMNode_QueryInterface(childNode, &IID_IXMLDOMNode, (LPVOID)&child);
683     if(FAILED(hr))
684         return hr;
685
686     child_node_ptr = impl_from_IXMLDOMNode(child)->node;
687     if(child_node_ptr->parent != This->node)
688     {
689         WARN("childNode %p is not a child of %p\n", childNode, iface);
690         IXMLDOMNode_Release(child);
691         return E_INVALIDARG;
692     }
693
694     xmlUnlinkNode(child_node_ptr);
695
696     IXMLDOMNode_Release(child);
697
698     if(oldChild)
699     {
700         IXMLDOMNode_AddRef(childNode);
701         *oldChild = childNode;
702     }
703
704     return S_OK;
705 }
706
707 static HRESULT WINAPI xmlnode_appendChild(
708     IXMLDOMNode *iface,
709     IXMLDOMNode* newChild,
710     IXMLDOMNode** outNewChild)
711 {
712     xmlnode *This = impl_from_IXMLDOMNode( iface );
713     DOMNodeType type;
714     VARIANT var;
715     HRESULT hr;
716
717     TRACE("(%p)->(%p,%p)\n", This, newChild, outNewChild);
718
719     hr = IXMLDOMNode_get_nodeType(newChild, &type);
720     if(FAILED(hr) || type == NODE_ATTRIBUTE) {
721         if(outNewChild) *outNewChild = NULL;
722         return E_FAIL;
723     }
724
725     VariantInit(&var);
726     return IXMLDOMNode_insertBefore(iface, newChild, var, outNewChild);
727 }
728
729 static HRESULT WINAPI xmlnode_hasChildNodes(
730     IXMLDOMNode *iface,
731     VARIANT_BOOL* hasChild)
732 {
733     xmlnode *This = impl_from_IXMLDOMNode( iface );
734
735     TRACE("%p\n", This);
736
737     if (!hasChild)
738         return E_INVALIDARG;
739     if (!This->node->children)
740     {
741         *hasChild = VARIANT_FALSE;
742         return S_FALSE;
743     }
744
745     *hasChild = VARIANT_TRUE;
746     return S_OK;
747 }
748
749 static HRESULT WINAPI xmlnode_get_ownerDocument(
750     IXMLDOMNode *iface,
751     IXMLDOMDocument** DOMDocument)
752 {
753     xmlnode *This = impl_from_IXMLDOMNode( iface );
754
755     TRACE("%p (%p)\n", This, DOMDocument);
756
757     return DOMDocument_create_from_xmldoc(This->node->doc, (IXMLDOMDocument2**)DOMDocument);
758 }
759
760 static HRESULT WINAPI xmlnode_cloneNode(
761     IXMLDOMNode *iface,
762     VARIANT_BOOL deep,
763     IXMLDOMNode** cloneRoot)
764 {
765     xmlnode *This = impl_from_IXMLDOMNode( iface );
766     xmlNodePtr pClone = NULL;
767     IXMLDOMNode *pNode = NULL;
768
769     TRACE("%p (%d)\n", This, deep);
770
771     if(!cloneRoot)
772         return E_INVALIDARG;
773
774     pClone = xmlCopyNode(This->node, deep ? 1 : 2);
775     if(pClone)
776     {
777         pClone->doc = This->node->doc;
778         xmldoc_add_orphan(pClone->doc, pClone);
779
780         pNode = create_node(pClone);
781         if(!pNode)
782         {
783             ERR("Copy failed\n");
784             return E_FAIL;
785         }
786
787         *cloneRoot = pNode;
788     }
789     else
790     {
791         ERR("Copy failed\n");
792         return E_FAIL;
793     }
794
795     return S_OK;
796 }
797
798 static HRESULT WINAPI xmlnode_get_nodeTypeString(
799     IXMLDOMNode *iface,
800     BSTR* xmlnodeType)
801 {
802     xmlnode *This = impl_from_IXMLDOMNode( iface );
803     const xmlChar *str;
804
805     TRACE("%p\n", This );
806
807     if (!xmlnodeType)
808         return E_INVALIDARG;
809
810     if ( !This->node )
811         return E_FAIL;
812
813     switch( This->node->type )
814     {
815     case XML_ATTRIBUTE_NODE:
816         str = (const xmlChar*) "attribute";
817         break;
818     case XML_CDATA_SECTION_NODE:
819         str = (const xmlChar*) "cdatasection";
820         break;
821     case XML_COMMENT_NODE:
822         str = (const xmlChar*) "comment";
823         break;
824     case XML_DOCUMENT_NODE:
825         str = (const xmlChar*) "document";
826         break;
827     case XML_DOCUMENT_FRAG_NODE:
828         str = (const xmlChar*) "documentfragment";
829         break;
830     case XML_ELEMENT_NODE:
831         str = (const xmlChar*) "element";
832         break;
833     case XML_ENTITY_NODE:
834         str = (const xmlChar*) "entity";
835         break;
836     case XML_ENTITY_REF_NODE:
837         str = (const xmlChar*) "entityreference";
838         break;
839     case XML_NOTATION_NODE:
840         str = (const xmlChar*) "notation";
841         break;
842     case XML_PI_NODE:
843         str = (const xmlChar*) "processinginstruction";
844         break;
845     case XML_TEXT_NODE:
846         str = (const xmlChar*) "text";
847         break;
848     default:
849         FIXME("Unknown node type (%d)\n", This->node->type);
850         str = This->node->name;
851         break;
852     }
853
854     *xmlnodeType = bstr_from_xmlChar( str );
855     if (!*xmlnodeType)
856         return S_FALSE;
857
858     return S_OK;
859 }
860
861 static HRESULT WINAPI xmlnode_get_text(
862     IXMLDOMNode *iface,
863     BSTR* text)
864 {
865     xmlnode *This = impl_from_IXMLDOMNode( iface );
866     BSTR str = NULL;
867     xmlChar *pContent;
868
869     TRACE("%p type %d\n", This, This->node->type);
870
871     if ( !text )
872         return E_INVALIDARG;
873
874     pContent = xmlNodeGetContent((xmlNodePtr)This->node);
875     if(pContent)
876     {
877         str = bstr_from_xmlChar(pContent);
878         xmlFree(pContent);
879     }
880
881     /* Always return a string. */
882     if (!str) str = SysAllocStringLen( NULL, 0 );
883
884     TRACE("%p %s\n", This, debugstr_w(str) );
885     *text = str;
886  
887     return S_OK;
888 }
889
890 static HRESULT WINAPI xmlnode_put_text(
891     IXMLDOMNode *iface,
892     BSTR text)
893 {
894     xmlnode *This = impl_from_IXMLDOMNode( iface );
895     xmlChar *str, *str2;
896
897     TRACE("%p\n", This);
898
899     switch(This->node->type)
900     {
901     case XML_DOCUMENT_NODE:
902         return E_FAIL;
903     default:
904         break;
905     }
906
907     str = xmlChar_from_wchar((WCHAR*)text);
908
909     /* Escape the string. */
910     str2 = xmlEncodeEntitiesReentrant(This->node->doc, str);
911     HeapFree(GetProcessHeap(), 0, str);
912
913     xmlNodeSetContent(This->node, str2);
914     xmlFree(str2);
915
916     return S_OK;
917 }
918
919 static HRESULT WINAPI xmlnode_get_specified(
920     IXMLDOMNode *iface,
921     VARIANT_BOOL* isSpecified)
922 {
923     FIXME("\n");
924     return E_NOTIMPL;
925 }
926
927 static HRESULT WINAPI xmlnode_get_definition(
928     IXMLDOMNode *iface,
929     IXMLDOMNode** definitionNode)
930 {
931     FIXME("\n");
932     return E_NOTIMPL;
933 }
934
935 static HRESULT WINAPI xmlnode_get_nodeTypedValue(
936     IXMLDOMNode *iface,
937     VARIANT* typedValue)
938 {
939     xmlnode *This = impl_from_IXMLDOMNode( iface );
940     HRESULT r = S_FALSE;
941
942     FIXME("ignoring data type %p %p\n", This, typedValue);
943
944     if(!typedValue)
945         return E_INVALIDARG;
946
947     V_VT(typedValue) = VT_NULL;
948
949     switch ( This->node->type )
950     {
951     case XML_ELEMENT_NODE:
952     {
953         xmlChar *content = xmlNodeGetContent(This->node);
954         V_VT(typedValue) = VT_BSTR;
955         V_BSTR(typedValue) = bstr_from_xmlChar( content );
956         xmlFree(content);
957         r = S_OK;
958         break;
959     }
960     default:
961         r = xmlnode_get_nodeValue(iface, typedValue);
962     }
963
964     return r;
965 }
966
967 static HRESULT WINAPI xmlnode_put_nodeTypedValue(
968     IXMLDOMNode *iface,
969     VARIANT typedValue)
970 {
971     FIXME("\n");
972     return E_NOTIMPL;
973 }
974
975 static HRESULT WINAPI xmlnode_get_dataType(
976     IXMLDOMNode *iface,
977     VARIANT* dataTypeName)
978 {
979     xmlnode *This = impl_from_IXMLDOMNode( iface );
980     xmlChar *pVal;
981
982     TRACE("iface %p\n", iface);
983
984     if(!dataTypeName)
985         return E_INVALIDARG;
986
987     /* Attribute, CDATA Section, Comment, Document, Document Fragment,
988         Entity, Notation, PI, and Text Node are non-typed. */
989     V_BSTR(dataTypeName) = NULL;
990     V_VT(dataTypeName) = VT_NULL;
991
992     switch ( This->node->type )
993     {
994     case XML_ELEMENT_NODE:
995         pVal = xmlGetNsProp(This->node, (xmlChar*)"dt",
996                             (xmlChar*)"urn:schemas-microsoft-com:datatypes");
997         if (pVal)
998         {
999             V_VT(dataTypeName) = VT_BSTR;
1000             V_BSTR(dataTypeName) = bstr_from_xmlChar( pVal );
1001             xmlFree(pVal);
1002         }
1003         break;
1004     case XML_ENTITY_REF_NODE:
1005         FIXME("XML_ENTITY_REF_NODE should return a valid value.\n");
1006         break;
1007     default:
1008         TRACE("Type %d returning NULL\n", This->node->type);
1009     }
1010
1011     /* non-typed nodes return S_FALSE */
1012     if(V_VT(dataTypeName) == VT_NULL)
1013     {
1014         return S_FALSE;
1015     }
1016
1017     return S_OK;
1018 }
1019
1020 static HRESULT WINAPI xmlnode_put_dataType(
1021     IXMLDOMNode *iface,
1022     BSTR dataTypeName)
1023 {
1024     xmlnode *This = impl_from_IXMLDOMNode( iface );
1025     HRESULT hr = E_FAIL;
1026
1027     TRACE("iface %p\n", iface);
1028
1029     if(dataTypeName == NULL)
1030         return E_INVALIDARG;
1031
1032     /* An example of this is. The Text in the node needs to be a 0 or 1 for a boolean type.
1033        This applies to changing types (string->bool) or setting a new one
1034      */
1035     FIXME("Need to Validate the data before allowing a type to be set.\n");
1036
1037     /* Check all supported types. */
1038     if(lstrcmpiW(dataTypeName,szString) == 0  ||
1039        lstrcmpiW(dataTypeName,szNumber) == 0  ||
1040        lstrcmpiW(dataTypeName,szUUID) == 0    ||
1041        lstrcmpiW(dataTypeName,szInt) == 0     ||
1042        lstrcmpiW(dataTypeName,szI4) == 0      ||
1043        lstrcmpiW(dataTypeName,szFixed) == 0   ||
1044        lstrcmpiW(dataTypeName,szBoolean) == 0 ||
1045        lstrcmpiW(dataTypeName,szDateTime) == 0 ||
1046        lstrcmpiW(dataTypeName,szDateTimeTZ) == 0 ||
1047        lstrcmpiW(dataTypeName,szDate) == 0    ||
1048        lstrcmpiW(dataTypeName,szTime) == 0    ||
1049        lstrcmpiW(dataTypeName,szTimeTZ) == 0  ||
1050        lstrcmpiW(dataTypeName,szI1) == 0      ||
1051        lstrcmpiW(dataTypeName,szI2) == 0      ||
1052        lstrcmpiW(dataTypeName,szIU1) == 0     ||
1053        lstrcmpiW(dataTypeName,szIU2) == 0     ||
1054        lstrcmpiW(dataTypeName,szIU4) == 0     ||
1055        lstrcmpiW(dataTypeName,szR4) == 0      ||
1056        lstrcmpiW(dataTypeName,szR8) == 0      ||
1057        lstrcmpiW(dataTypeName,szFloat) == 0   ||
1058        lstrcmpiW(dataTypeName,szBinHex) == 0  ||
1059        lstrcmpiW(dataTypeName,szBinBase64) == 0)
1060     {
1061         xmlNsPtr pNS = NULL;
1062         xmlAttrPtr pAttr = NULL;
1063         xmlChar* str = xmlChar_from_wchar((WCHAR*)dataTypeName);
1064
1065         pAttr = xmlHasNsProp(This->node, (xmlChar*)"dt",
1066                             (xmlChar*)"urn:schemas-microsoft-com:datatypes");
1067         if (pAttr)
1068         {
1069             pAttr = xmlSetNsProp(This->node, pAttr->ns, (xmlChar*)"dt", str);
1070
1071             hr = S_OK;
1072         }
1073         else
1074         {
1075             pNS = xmlNewNs(This->node, (xmlChar*)"urn:schemas-microsoft-com:datatypes", (xmlChar*)"dt");
1076             if(pNS)
1077             {
1078                 pAttr = xmlNewNsProp(This->node, pNS, (xmlChar*)"dt", str);
1079                 if(pAttr)
1080                 {
1081                     xmlAddChild(This->node, (xmlNodePtr)pAttr);
1082
1083                     hr = S_OK;
1084                 }
1085                 else
1086                     ERR("Failed to create Attribute\n");
1087             }
1088             else
1089                 ERR("Failed to Create Namepsace\n");
1090         }
1091         HeapFree( GetProcessHeap(), 0, str );
1092     }
1093
1094     return hr;
1095 }
1096
1097 static BSTR EnsureCorrectEOL(BSTR sInput)
1098 {
1099     static const WCHAR SZ_RETURN[] = {'\n',0};
1100     static const WCHAR SZ_LINEFEED[] = {'\r',0};
1101     int nNum = 0;
1102     BSTR sNew;
1103     int nLen;
1104     int i;
1105
1106     nLen = lstrlenW(sInput);
1107     /* Count line endings */
1108     for(i=0; i < nLen; i++)
1109     {
1110         if(sInput[i] == SZ_RETURN[0])
1111             nNum++;
1112     }
1113
1114     TRACE("len=%d, num=%d\n", nLen, nNum);
1115
1116     /* Add linefeed as needed */
1117     if(nNum > 0)
1118     {
1119         int nPlace = 0;
1120         sNew = SysAllocStringLen(NULL, nLen + nNum+1);
1121         for(i=0; i < nLen; i++)
1122         {
1123             if(sInput[i] == SZ_RETURN[0])
1124             {
1125                 sNew[i+nPlace] = SZ_LINEFEED[0];
1126                 nPlace++;
1127             }
1128             sNew[i+nPlace] = sInput[i];
1129         }
1130
1131         SysFreeString(sInput);
1132     }
1133     else
1134     {
1135         sNew = sInput;
1136     }
1137
1138     TRACE("len %d\n", lstrlenW(sNew));
1139
1140     return sNew;
1141 }
1142
1143 /* Removes encoding information and last character (nullbyte) */
1144 static BSTR EnsureNoEncoding(BSTR sInput)
1145 {
1146     static const WCHAR wszEncoding[] = {'e','n','c','o','d','i','n','g','='};
1147     BSTR sNew;
1148     WCHAR *pBeg, *pEnd;
1149
1150     pBeg = sInput;
1151     while(*pBeg != '\n' && memcmp(pBeg, wszEncoding, sizeof(wszEncoding)))
1152         pBeg++;
1153
1154     if(*pBeg == '\n')
1155     {
1156         SysReAllocStringLen(&sInput, sInput, SysStringLen(sInput)-1);
1157         return sInput;
1158     }
1159     pBeg--;
1160
1161     pEnd = pBeg + sizeof(wszEncoding)/sizeof(WCHAR) + 2;
1162     while(*pEnd != '\"') pEnd++;
1163     pEnd++;
1164
1165     sNew = SysAllocStringLen(NULL,
1166             pBeg-sInput + SysStringLen(sInput)-(pEnd-sInput)-1);
1167     memcpy(sNew, sInput, (pBeg-sInput)*sizeof(WCHAR));
1168     memcpy(&sNew[pBeg-sInput], pEnd, (SysStringLen(sInput)-(pEnd-sInput)-1)*sizeof(WCHAR));
1169
1170     SysFreeString(sInput);
1171     return sNew;
1172 }
1173
1174 /*
1175  * We are trying to replicate the same behaviour as msxml by converting
1176  * line endings to \r\n and using idents as \t. The problem is that msxml
1177  * only formats nodes that have a line ending. Using libxml we cannot
1178  * reproduce behaviour exactly.
1179  *
1180  */
1181 static HRESULT WINAPI xmlnode_get_xml(
1182     IXMLDOMNode *iface,
1183     BSTR* xmlString)
1184 {
1185     xmlnode *This = impl_from_IXMLDOMNode( iface );
1186     xmlBufferPtr pXmlBuf;
1187     int nSize;
1188
1189     TRACE("iface %p %d\n", iface, This->node->type);
1190
1191     if(!xmlString)
1192         return E_INVALIDARG;
1193
1194     *xmlString = NULL;
1195
1196     pXmlBuf = xmlBufferCreate();
1197     if(pXmlBuf)
1198     {
1199         nSize = xmlNodeDump(pXmlBuf, This->node->doc, This->node, 0, 1);
1200         if(nSize > 0)
1201         {
1202             const xmlChar *pContent;
1203             BSTR bstrContent;
1204
1205             /* Attribute Nodes return a space in front of their name */
1206             pContent = xmlBufferContent(pXmlBuf);
1207             if( ((char*)pContent)[0] == ' ')
1208                 bstrContent = bstr_from_xmlChar(pContent+1);
1209             else
1210                 bstrContent = bstr_from_xmlChar(pContent);
1211
1212             switch(This->node->type)
1213             {
1214                 case XML_ELEMENT_NODE:
1215                     *xmlString = EnsureCorrectEOL(bstrContent);
1216                     break;
1217                 case XML_DOCUMENT_NODE:
1218                     *xmlString = EnsureCorrectEOL(bstrContent);
1219                     *xmlString = EnsureNoEncoding(*xmlString);
1220                     break;
1221                 default:
1222                     *xmlString = bstrContent;
1223             }
1224         }
1225
1226         xmlBufferFree(pXmlBuf);
1227     }
1228
1229     /* Always returns a string. */
1230     if(*xmlString == NULL)  *xmlString = SysAllocStringLen( NULL, 0 );
1231
1232     return S_OK;
1233 }
1234
1235 static HRESULT WINAPI xmlnode_transformNode(
1236     IXMLDOMNode *iface,
1237     IXMLDOMNode* styleSheet,
1238     BSTR* xmlString)
1239 {
1240 #ifdef SONAME_LIBXSLT
1241     xmlnode *This = impl_from_IXMLDOMNode( iface );
1242     xmlnode *pStyleSheet = NULL;
1243     xsltStylesheetPtr xsltSS = NULL;
1244     xmlDocPtr result = NULL;
1245     IXMLDOMNode *ssNew;
1246
1247     TRACE("%p %p %p\n", This, styleSheet, xmlString);
1248
1249     if (!libxslt_handle)
1250         return E_NOTIMPL;
1251     if(!styleSheet || !xmlString)
1252         return E_INVALIDARG;
1253
1254     *xmlString = NULL;
1255
1256     if(IXMLDOMNode_QueryInterface(styleSheet, &IID_IXMLDOMNode, (LPVOID)&ssNew) == S_OK)
1257     {
1258         pStyleSheet = impl_from_IXMLDOMNode( ssNew );
1259
1260         xsltSS = pxsltParseStylesheetDoc( pStyleSheet->node->doc);
1261         if(xsltSS)
1262         {
1263             result = pxsltApplyStylesheet(xsltSS, This->node->doc, NULL);
1264             if(result)
1265             {
1266                 const xmlChar *pContent;
1267
1268                 if(result->type == XML_HTML_DOCUMENT_NODE)
1269                 {
1270                     xmlOutputBufferPtr  pOutput = xmlAllocOutputBuffer(NULL);
1271                     if(pOutput)
1272                     {
1273                         htmlDocContentDumpOutput(pOutput, result->doc, NULL);
1274                         pContent = xmlBufferContent(pOutput->buffer);
1275                         *xmlString = bstr_from_xmlChar(pContent);
1276                         xmlOutputBufferClose(pOutput);
1277                     }
1278                 }
1279                 else
1280                 {
1281                     xmlBufferPtr pXmlBuf;
1282                     int nSize;
1283
1284                     pXmlBuf = xmlBufferCreate();
1285                     if(pXmlBuf)
1286                     {
1287                         nSize = xmlNodeDump(pXmlBuf, NULL, (xmlNodePtr)result, 0, 0);
1288                         if(nSize > 0)
1289                         {
1290                             pContent = xmlBufferContent(pXmlBuf);
1291                             *xmlString = bstr_from_xmlChar(pContent);
1292                         }
1293                         xmlBufferFree(pXmlBuf);
1294                     }
1295                 }
1296                 xmlFreeDoc(result);
1297             }
1298             /* libxslt "helpfully" frees the XML document the stylesheet was
1299                generated from, too */
1300             xsltSS->doc = NULL;
1301             pxsltFreeStylesheet(xsltSS);
1302         }
1303
1304         IXMLDOMNode_Release(ssNew);
1305     }
1306
1307     if(*xmlString == NULL)
1308         *xmlString = SysAllocStringLen(NULL, 0);
1309
1310     return S_OK;
1311 #else
1312     FIXME("libxslt headers were not found at compile time\n");
1313     return E_NOTIMPL;
1314 #endif
1315 }
1316
1317 static HRESULT WINAPI xmlnode_selectNodes(
1318     IXMLDOMNode *iface,
1319     BSTR queryString,
1320     IXMLDOMNodeList** resultList)
1321 {
1322     xmlnode *This = impl_from_IXMLDOMNode( iface );
1323
1324     TRACE("%p %s %p\n", This, debugstr_w(queryString), resultList );
1325
1326     return queryresult_create( This->node, queryString, resultList );
1327 }
1328
1329 static HRESULT WINAPI xmlnode_selectSingleNode(
1330     IXMLDOMNode *iface,
1331     BSTR queryString,
1332     IXMLDOMNode** resultNode)
1333 {
1334     xmlnode *This = impl_from_IXMLDOMNode( iface );
1335     IXMLDOMNodeList *list;
1336     HRESULT r;
1337
1338     TRACE("%p %s %p\n", This, debugstr_w(queryString), resultNode );
1339
1340     *resultNode = NULL;
1341     r = IXMLDOMNode_selectNodes(iface, queryString, &list);
1342     if(r == S_OK)
1343     {
1344         r = IXMLDOMNodeList_nextNode(list, resultNode);
1345         IXMLDOMNodeList_Release(list);
1346     }
1347     return r;
1348 }
1349
1350 static HRESULT WINAPI xmlnode_get_parsed(
1351     IXMLDOMNode *iface,
1352     VARIANT_BOOL* isParsed)
1353 {
1354     FIXME("\n");
1355     return E_NOTIMPL;
1356 }
1357
1358 static HRESULT WINAPI xmlnode_get_namespaceURI(
1359     IXMLDOMNode *iface,
1360     BSTR* namespaceURI)
1361 {
1362     xmlnode *This = impl_from_IXMLDOMNode( iface );
1363     HRESULT hr = S_FALSE;
1364     xmlNsPtr *pNSList;
1365
1366     TRACE("%p %p\n", This, namespaceURI );
1367
1368     if(!namespaceURI)
1369         return E_INVALIDARG;
1370
1371     *namespaceURI = NULL;
1372
1373     pNSList = xmlGetNsList(This->node->doc, This->node);
1374     if(pNSList)
1375     {
1376         *namespaceURI = bstr_from_xmlChar( pNSList[0]->href );
1377
1378         xmlFree( pNSList );
1379         hr = S_OK;
1380     }
1381
1382     return hr;
1383 }
1384
1385 static HRESULT WINAPI xmlnode_get_prefix(
1386     IXMLDOMNode *iface,
1387     BSTR* prefixString)
1388 {
1389     xmlnode *This = impl_from_IXMLDOMNode( iface );
1390     HRESULT hr = S_FALSE;
1391     xmlNsPtr *pNSList;
1392
1393     TRACE("%p %p\n", This, prefixString );
1394
1395     if(!prefixString)
1396         return E_INVALIDARG;
1397
1398     *prefixString = NULL;
1399
1400     pNSList = xmlGetNsList(This->node->doc, This->node);
1401     if(pNSList)
1402     {
1403         *prefixString = bstr_from_xmlChar( pNSList[0]->prefix );
1404
1405         xmlFree(pNSList);
1406         hr = S_OK;
1407     }
1408
1409     return hr;
1410 }
1411
1412 static HRESULT WINAPI xmlnode_get_baseName(
1413     IXMLDOMNode *iface,
1414     BSTR* nameString)
1415 {
1416     xmlnode *This = impl_from_IXMLDOMNode( iface );
1417     BSTR str = NULL;
1418     HRESULT r = S_FALSE;
1419
1420     TRACE("%p %p\n", This, nameString );
1421
1422     if ( !nameString )
1423         return E_INVALIDARG;
1424
1425     switch ( This->node->type )
1426     {
1427     case XML_ELEMENT_NODE:
1428     case XML_ATTRIBUTE_NODE:
1429         str = bstr_from_xmlChar( This->node->name );
1430         r = S_OK;
1431         break;
1432     case XML_TEXT_NODE:
1433         break;
1434     default:
1435         ERR("Unhandled type %d\n", This->node->type );
1436         break;
1437     }
1438
1439     TRACE("returning %08x str = %s\n", r, debugstr_w( str ) );
1440
1441     *nameString = str;
1442     return r;
1443 }
1444
1445 static HRESULT WINAPI xmlnode_transformNodeToObject(
1446     IXMLDOMNode *iface,
1447     IXMLDOMNode* stylesheet,
1448     VARIANT outputObject)
1449 {
1450     FIXME("\n");
1451     return E_NOTIMPL;
1452 }
1453
1454 static const struct IXMLDOMNodeVtbl xmlnode_vtbl =
1455 {
1456     xmlnode_QueryInterface,
1457     xmlnode_AddRef,
1458     xmlnode_Release,
1459     xmlnode_GetTypeInfoCount,
1460     xmlnode_GetTypeInfo,
1461     xmlnode_GetIDsOfNames,
1462     xmlnode_Invoke,
1463     xmlnode_get_nodeName,
1464     xmlnode_get_nodeValue,
1465     xmlnode_put_nodeValue,
1466     xmlnode_get_nodeType,
1467     xmlnode_get_parentNode,
1468     xmlnode_get_childNodes,
1469     xmlnode_get_firstChild,
1470     xmlnode_get_lastChild,
1471     xmlnode_get_previousSibling,
1472     xmlnode_get_nextSibling,
1473     xmlnode_get_attributes,
1474     xmlnode_insertBefore,
1475     xmlnode_replaceChild,
1476     xmlnode_removeChild,
1477     xmlnode_appendChild,
1478     xmlnode_hasChildNodes,
1479     xmlnode_get_ownerDocument,
1480     xmlnode_cloneNode,
1481     xmlnode_get_nodeTypeString,
1482     xmlnode_get_text,
1483     xmlnode_put_text,
1484     xmlnode_get_specified,
1485     xmlnode_get_definition,
1486     xmlnode_get_nodeTypedValue,
1487     xmlnode_put_nodeTypedValue,
1488     xmlnode_get_dataType,
1489     xmlnode_put_dataType,
1490     xmlnode_get_xml,
1491     xmlnode_transformNode,
1492     xmlnode_selectNodes,
1493     xmlnode_selectSingleNode,
1494     xmlnode_get_parsed,
1495     xmlnode_get_namespaceURI,
1496     xmlnode_get_prefix,
1497     xmlnode_get_baseName,
1498     xmlnode_transformNodeToObject,
1499 };
1500
1501 static HRESULT WINAPI Internal_QueryInterface(
1502     IUnknown *iface,
1503     REFIID riid,
1504     void** ppvObject )
1505 {
1506     xmlnode *This = impl_from_InternalUnknown( iface );
1507
1508     TRACE("%p %s %p\n", iface, debugstr_guid(riid), ppvObject);
1509
1510
1511     if ( IsEqualGUID( riid, &IID_IUnknown ))
1512         *ppvObject = iface;
1513     else if ( IsEqualGUID( riid, &IID_IDispatch ) ||
1514               IsEqualGUID( riid, &IID_IXMLDOMNode ) )
1515         *ppvObject = &This->lpVtbl;
1516     else
1517     {
1518         FIXME("interface %s not implemented\n", debugstr_guid(riid));
1519         *ppvObject = NULL;
1520         return E_NOINTERFACE;
1521     }
1522
1523     IUnknown_AddRef( (IUnknown*)*ppvObject );
1524
1525     return S_OK;
1526 }
1527
1528 static ULONG WINAPI Internal_AddRef(
1529                  IUnknown *iface )
1530 {
1531     xmlnode *This = impl_from_InternalUnknown( iface );
1532     return InterlockedIncrement( &This->ref );
1533 }
1534
1535 static ULONG WINAPI Internal_Release(
1536     IUnknown *iface )
1537 {
1538     xmlnode *This = impl_from_InternalUnknown( iface );
1539     ULONG ref;
1540
1541     ref = InterlockedDecrement( &This->ref );
1542     if ( ref == 0 )
1543     {
1544         if( This->node )
1545             xmldoc_release( This->node->doc );
1546         HeapFree( GetProcessHeap(), 0, This );
1547     }
1548
1549     return ref;
1550 }
1551
1552 static const struct IUnknownVtbl internal_unk_vtbl =
1553 {
1554     Internal_QueryInterface,
1555     Internal_AddRef,
1556     Internal_Release
1557 };
1558
1559 IUnknown *create_basic_node( xmlNodePtr node, IUnknown *pUnkOuter )
1560 {
1561     xmlnode *This;
1562
1563     This = HeapAlloc( GetProcessHeap(), 0, sizeof *This );
1564     if ( !This )
1565         return NULL;
1566
1567     if(node)
1568         xmldoc_add_ref( node->doc );
1569
1570     This->lpVtbl = &xmlnode_vtbl;
1571     This->lpInternalUnkVtbl = &internal_unk_vtbl;
1572
1573     if(pUnkOuter)
1574         This->pUnkOuter = pUnkOuter; /* Don't take a ref on outer Unknown */
1575     else
1576         This->pUnkOuter = (IUnknown *)&This->lpInternalUnkVtbl;
1577
1578     This->ref = 1;
1579     This->node = node;
1580
1581     return (IUnknown*)&This->lpInternalUnkVtbl;
1582 }
1583
1584 IXMLDOMNode *create_node( xmlNodePtr node )
1585 {
1586     IUnknown *pUnk;
1587     IXMLDOMNode *ret;
1588     HRESULT hr;
1589
1590     if ( !node )
1591         return NULL;
1592
1593     TRACE("type %d\n", node->type);
1594     switch(node->type)
1595     {
1596     case XML_ELEMENT_NODE:
1597         pUnk = create_element( node, NULL );
1598         break;
1599     case XML_ATTRIBUTE_NODE:
1600         pUnk = create_attribute( node );
1601         break;
1602     case XML_TEXT_NODE:
1603         pUnk = create_text( node );
1604         break;
1605     case XML_CDATA_SECTION_NODE:
1606         pUnk = create_cdata( node );
1607         break;
1608     case XML_COMMENT_NODE:
1609         pUnk = create_comment( node );
1610         break;
1611     case XML_DOCUMENT_NODE:
1612         pUnk = create_domdoc( node );
1613         break;
1614     default:
1615         FIXME("only creating basic node for type %d\n", node->type);
1616         pUnk = create_basic_node( node, NULL );
1617     }
1618
1619     hr = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMNode, (LPVOID*)&ret);
1620     IUnknown_Release(pUnk);
1621     if(FAILED(hr)) return NULL;
1622     return ret;
1623 }
1624 #endif