msxml3: Remove appendChild() forward.
[wine.git] / dlls / msxml3 / node.c
blob1e186effaddb3305a3dfae72a0506c4b8fe23991
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "config.h"
23 #define COBJMACROS
25 #include <stdarg.h>
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "winnls.h"
30 #include "ole2.h"
31 #include "msxml6.h"
33 #include "msxml_private.h"
35 #ifdef HAVE_LIBXML2
36 # include <libxml/HTMLtree.h>
37 #endif
39 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
43 #ifdef HAVE_LIBXML2
45 /* TODO: get rid of these and use the enum */
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};
69 static const IID IID_xmlnode = {0x4f2f4ba2,0xb822,0x11df,{0x8b,0x8a,0x68,0x50,0xdf,0xd7,0x20,0x85}};
71 xmlNodePtr xmlNodePtr_from_domnode( IXMLDOMNode *iface, xmlElementType type )
73 xmlnode *This;
75 if ( !iface )
76 return NULL;
77 This = get_node_obj( iface );
78 if ( !This || !This->node )
79 return NULL;
80 if ( type && This->node->type != type )
81 return NULL;
82 return This->node;
85 BOOL node_query_interface(xmlnode *This, REFIID riid, void **ppv)
87 if(IsEqualGUID(&IID_xmlnode, riid)) {
88 TRACE("(%p)->(IID_xmlnode %p)\n", This, ppv);
89 *ppv = This;
90 return TRUE;
93 if(This->dispex.outer)
94 return dispex_query_interface(&This->dispex, riid, ppv);
96 return FALSE;
99 xmlnode *get_node_obj(IXMLDOMNode *node)
101 xmlnode *obj;
102 HRESULT hres;
104 hres = IXMLDOMNode_QueryInterface(node, &IID_xmlnode, (void**)&obj);
105 return SUCCEEDED(hres) ? obj : NULL;
108 static inline xmlnode *impl_from_IXMLDOMNode( IXMLDOMNode *iface )
110 return CONTAINING_RECORD(iface, xmlnode, IXMLDOMNode_iface);
113 HRESULT node_get_nodeName(xmlnode *This, BSTR *name)
115 if (!name)
116 return E_INVALIDARG;
118 *name = bstr_from_xmlChar(This->node->name);
119 if (!*name)
120 return S_FALSE;
122 return S_OK;
125 HRESULT node_get_content(xmlnode *This, VARIANT *value)
127 xmlChar *content;
129 if(!value)
130 return E_INVALIDARG;
132 content = xmlNodeGetContent(This->node);
133 V_VT(value) = VT_BSTR;
134 V_BSTR(value) = bstr_from_xmlChar( content );
135 xmlFree(content);
137 TRACE("%p returned %s\n", This, debugstr_w(V_BSTR(value)));
138 return S_OK;
141 HRESULT node_set_content(xmlnode *This, LPCWSTR value)
143 xmlChar *str;
145 TRACE("(%p)->(%s)\n", This, debugstr_w(value));
146 str = xmlChar_from_wchar(value);
147 if(!str)
148 return E_OUTOFMEMORY;
150 xmlNodeSetContent(This->node, str);
151 heap_free(str);
152 return S_OK;
155 static HRESULT node_set_content_escaped(xmlnode *This, LPCWSTR value)
157 xmlChar *str, *escaped;
159 TRACE("(%p)->(%s)\n", This, debugstr_w(value));
160 str = xmlChar_from_wchar(value);
161 if(!str)
162 return E_OUTOFMEMORY;
164 escaped = xmlEncodeSpecialChars(NULL, str);
165 if(!escaped)
167 heap_free(str);
168 return E_OUTOFMEMORY;
171 xmlNodeSetContent(This->node, escaped);
173 heap_free(str);
174 xmlFree(escaped);
176 return S_OK;
179 HRESULT node_put_value(xmlnode *This, VARIANT *value)
181 VARIANT string_value;
182 HRESULT hr;
184 VariantInit(&string_value);
185 hr = VariantChangeType(&string_value, value, 0, VT_BSTR);
186 if(FAILED(hr)) {
187 WARN("Couldn't convert to VT_BSTR\n");
188 return hr;
191 hr = node_set_content(This, V_BSTR(&string_value));
192 VariantClear(&string_value);
194 return hr;
197 HRESULT node_put_value_escaped(xmlnode *This, VARIANT *value)
199 VARIANT string_value;
200 HRESULT hr;
202 VariantInit(&string_value);
203 hr = VariantChangeType(&string_value, value, 0, VT_BSTR);
204 if(FAILED(hr)) {
205 WARN("Couldn't convert to VT_BSTR\n");
206 return hr;
209 hr = node_set_content_escaped(This, V_BSTR(&string_value));
210 VariantClear(&string_value);
212 return hr;
215 static HRESULT get_node(
216 xmlnode *This,
217 const char *name,
218 xmlNodePtr node,
219 IXMLDOMNode **out )
221 TRACE("(%p)->(%s %p %p)\n", This, name, node, out );
223 if ( !out )
224 return E_INVALIDARG;
226 /* if we don't have a doc, use our parent. */
227 if(node && !node->doc && node->parent)
228 node->doc = node->parent->doc;
230 *out = create_node( node );
231 if (!*out)
232 return S_FALSE;
233 return S_OK;
236 HRESULT node_get_parent(xmlnode *This, IXMLDOMNode **parent)
238 return get_node( This, "parent", This->node->parent, parent );
241 HRESULT node_get_child_nodes(xmlnode *This, IXMLDOMNodeList **ret)
243 if(!ret)
244 return E_INVALIDARG;
246 *ret = create_children_nodelist(This->node);
247 if(!*ret)
248 return E_OUTOFMEMORY;
250 return S_OK;
253 HRESULT node_get_first_child(xmlnode *This, IXMLDOMNode **ret)
255 return get_node(This, "firstChild", This->node->children, ret);
258 HRESULT node_get_last_child(xmlnode *This, IXMLDOMNode **ret)
260 return get_node(This, "lastChild", This->node->last, ret);
263 HRESULT node_get_previous_sibling(xmlnode *This, IXMLDOMNode **ret)
265 return get_node(This, "previous", This->node->prev, ret);
268 HRESULT node_get_next_sibling(xmlnode *This, IXMLDOMNode **ret)
270 return get_node(This, "next", This->node->next, ret);
273 HRESULT node_insert_before(xmlnode *This, IXMLDOMNode *new_child, const VARIANT *ref_child,
274 IXMLDOMNode **ret)
276 xmlNodePtr before_node, new_child_node;
277 IXMLDOMNode *before = NULL;
278 xmlnode *node_obj;
279 HRESULT hr;
281 if(!new_child)
282 return E_INVALIDARG;
284 node_obj = get_node_obj(new_child);
285 if(!node_obj) {
286 FIXME("newChild is not our node implementation\n");
287 return E_FAIL;
290 switch(V_VT(ref_child))
292 case VT_EMPTY:
293 case VT_NULL:
294 break;
296 case VT_UNKNOWN:
297 case VT_DISPATCH:
298 hr = IUnknown_QueryInterface(V_UNKNOWN(ref_child), &IID_IXMLDOMNode, (LPVOID)&before);
299 if(FAILED(hr)) return hr;
300 break;
302 default:
303 FIXME("refChild var type %x\n", V_VT(ref_child));
304 return E_FAIL;
307 new_child_node = node_obj->node;
308 TRACE("new_child_node %p This->node %p\n", new_child_node, This->node);
310 if(!new_child_node->parent)
311 if(xmldoc_remove_orphan(new_child_node->doc, new_child_node) != S_OK)
312 WARN("%p is not an orphan of %p\n", new_child_node, new_child_node->doc);
314 if(before)
316 node_obj = get_node_obj(before);
317 IXMLDOMNode_Release(before);
318 if(!node_obj) {
319 FIXME("before node is not our node implementation\n");
320 return E_FAIL;
323 before_node = node_obj->node;
324 xmlAddPrevSibling(before_node, new_child_node);
326 else
328 xmlAddChild(This->node, new_child_node);
331 if(ret) {
332 IXMLDOMNode_AddRef(new_child);
333 *ret = new_child;
336 TRACE("ret S_OK\n");
337 return S_OK;
340 HRESULT node_replace_child(xmlnode *This, IXMLDOMNode *newChild, IXMLDOMNode *oldChild,
341 IXMLDOMNode **ret)
343 xmlnode *old_child, *new_child;
344 xmlDocPtr leaving_doc;
345 xmlNode *my_ancestor;
347 /* Do not believe any documentation telling that newChild == NULL
348 means removal. It does certainly *not* apply to msxml3! */
349 if(!newChild || !oldChild)
350 return E_INVALIDARG;
352 if(ret)
353 *ret = NULL;
355 old_child = get_node_obj(oldChild);
356 if(!old_child) {
357 FIXME("oldChild is not our node implementation\n");
358 return E_FAIL;
361 if(old_child->node->parent != This->node)
363 WARN("childNode %p is not a child of %p\n", oldChild, This);
364 return E_INVALIDARG;
367 new_child = get_node_obj(newChild);
368 if(!new_child) {
369 FIXME("newChild is not our node implementation\n");
370 return E_FAIL;
373 my_ancestor = This->node;
374 while(my_ancestor)
376 if(my_ancestor == new_child->node)
378 WARN("tried to create loop\n");
379 return E_FAIL;
381 my_ancestor = my_ancestor->parent;
384 if(!new_child->node->parent)
385 if(xmldoc_remove_orphan(new_child->node->doc, new_child->node) != S_OK)
386 WARN("%p is not an orphan of %p\n", new_child->node, new_child->node->doc);
388 leaving_doc = new_child->node->doc;
389 xmldoc_add_ref(old_child->node->doc);
390 xmlReplaceNode(old_child->node, new_child->node);
391 xmldoc_release(leaving_doc);
393 xmldoc_add_orphan(old_child->node->doc, old_child->node);
395 if(ret)
397 IXMLDOMNode_AddRef(oldChild);
398 *ret = oldChild;
401 return S_OK;
404 HRESULT node_remove_child(xmlnode *This, IXMLDOMNode* child, IXMLDOMNode** oldChild)
406 xmlnode *child_node;
408 if(!child) return E_INVALIDARG;
410 if(oldChild)
411 *oldChild = NULL;
413 child_node = get_node_obj(child);
414 if(!child_node) {
415 FIXME("childNode is not our node implementation\n");
416 return E_FAIL;
419 if(child_node->node->parent != This->node)
421 WARN("childNode %p is not a child of %p\n", child, This);
422 return E_INVALIDARG;
425 xmlUnlinkNode(child_node->node);
427 if(oldChild)
429 IXMLDOMNode_AddRef(child);
430 *oldChild = child;
433 return S_OK;
436 HRESULT node_append_child(xmlnode *This, IXMLDOMNode *child, IXMLDOMNode **outChild)
438 DOMNodeType type;
439 VARIANT var;
440 HRESULT hr;
442 hr = IXMLDOMNode_get_nodeType(child, &type);
443 if(FAILED(hr) || type == NODE_ATTRIBUTE) {
444 if (outChild) *outChild = NULL;
445 return E_FAIL;
448 VariantInit(&var);
449 return IXMLDOMNode_insertBefore(This->iface, child, var, outChild);
452 static HRESULT WINAPI xmlnode_hasChildNodes(
453 IXMLDOMNode *iface,
454 VARIANT_BOOL* hasChild)
456 xmlnode *This = impl_from_IXMLDOMNode( iface );
458 TRACE("(%p)->(%p)\n", This, hasChild);
460 if (!hasChild)
461 return E_INVALIDARG;
462 if (!This->node->children)
464 *hasChild = VARIANT_FALSE;
465 return S_FALSE;
468 *hasChild = VARIANT_TRUE;
469 return S_OK;
472 static HRESULT WINAPI xmlnode_get_ownerDocument(
473 IXMLDOMNode *iface,
474 IXMLDOMDocument** DOMDocument)
476 xmlnode *This = impl_from_IXMLDOMNode( iface );
478 TRACE("(%p)->(%p)\n", This, DOMDocument);
480 return DOMDocument_create_from_xmldoc(This->node->doc, (IXMLDOMDocument3**)DOMDocument);
483 HRESULT node_clone(xmlnode *This, VARIANT_BOOL deep, IXMLDOMNode **cloneNode)
485 IXMLDOMNode *node;
486 xmlNodePtr clone;
488 if(!cloneNode) return E_INVALIDARG;
490 clone = xmlCopyNode(This->node, deep ? 1 : 2);
491 if (clone)
493 clone->doc = This->node->doc;
494 xmldoc_add_orphan(clone->doc, clone);
496 node = create_node(clone);
497 if (!node)
499 ERR("Copy failed\n");
500 return E_FAIL;
503 *cloneNode = node;
505 else
507 ERR("Copy failed\n");
508 return E_FAIL;
511 return S_OK;
514 static inline xmlChar* trim_whitespace(xmlChar* str)
516 xmlChar* ret = str;
517 int len;
519 if (!str)
520 return NULL;
522 while (*ret && isspace(*ret))
523 ++ret;
524 len = xmlStrlen(ret);
525 if (len)
526 while (isspace(ret[len-1])) --len;
528 ret = xmlStrndup(ret, len);
529 xmlFree(str);
530 return ret;
533 static xmlChar* do_get_text(xmlNodePtr node)
535 xmlNodePtr child;
536 xmlChar* str;
537 BOOL preserving = is_preserving_whitespace(node);
539 if (!node->children)
541 str = xmlNodeGetContent(node);
543 else
545 xmlElementType prev_type = XML_TEXT_NODE;
546 xmlChar* tmp;
547 str = xmlStrdup(BAD_CAST "");
548 for (child = node->children; child != NULL; child = child->next)
550 switch (child->type)
552 case XML_ELEMENT_NODE:
553 tmp = do_get_text(child);
554 break;
555 case XML_TEXT_NODE:
556 case XML_CDATA_SECTION_NODE:
557 case XML_ENTITY_REF_NODE:
558 case XML_ENTITY_NODE:
559 tmp = xmlNodeGetContent(child);
560 break;
561 default:
562 tmp = NULL;
563 break;
566 if (tmp)
568 if (*tmp)
570 if (prev_type == XML_ELEMENT_NODE && child->type == XML_ELEMENT_NODE)
571 str = xmlStrcat(str, BAD_CAST " ");
572 str = xmlStrcat(str, tmp);
573 prev_type = child->type;
575 xmlFree(tmp);
580 switch (node->type)
582 case XML_ELEMENT_NODE:
583 case XML_TEXT_NODE:
584 case XML_ENTITY_REF_NODE:
585 case XML_ENTITY_NODE:
586 case XML_DOCUMENT_NODE:
587 case XML_DOCUMENT_FRAG_NODE:
588 if (!preserving)
589 str = trim_whitespace(str);
590 break;
591 default:
592 break;
595 return str;
598 static HRESULT WINAPI xmlnode_get_text(
599 IXMLDOMNode *iface,
600 BSTR* text)
602 xmlnode *This = impl_from_IXMLDOMNode( iface );
603 BSTR str = NULL;
604 xmlChar *pContent;
606 TRACE("(%p, type %d)->(%p)\n", This, This->node->type, text);
608 if ( !text )
609 return E_INVALIDARG;
611 pContent = do_get_text((xmlNodePtr)This->node);
612 if(pContent)
614 str = bstr_from_xmlChar(pContent);
615 xmlFree(pContent);
618 /* Always return a string. */
619 if (!str) str = SysAllocStringLen( NULL, 0 );
621 TRACE("%p %s\n", This, debugstr_w(str) );
622 *text = str;
624 return S_OK;
627 HRESULT node_put_text(xmlnode *This, BSTR text)
629 xmlChar *str, *str2;
631 TRACE("(%p)->(%s)\n", This, debugstr_w(text));
633 str = xmlChar_from_wchar(text);
635 /* Escape the string. */
636 str2 = xmlEncodeEntitiesReentrant(This->node->doc, str);
637 heap_free(str);
639 xmlNodeSetContent(This->node, str2);
640 xmlFree(str2);
642 return S_OK;
645 static inline BYTE hex_to_byte(xmlChar c)
647 if(c <= '9') return c-'0';
648 if(c <= 'F') return c-'A'+10;
649 return c-'a'+10;
652 static inline BYTE base64_to_byte(xmlChar c)
654 if(c == '+') return 62;
655 if(c == '/') return 63;
656 if(c <= '9') return c-'0'+52;
657 if(c <= 'Z') return c-'A';
658 return c-'a'+26;
661 /* TODO: phasing this version out */
662 static inline HRESULT VARIANT_from_xmlChar(xmlChar *str, VARIANT *v, BSTR type)
664 if(!type || !lstrcmpiW(type, szString) ||
665 !lstrcmpiW(type, szNumber) || !lstrcmpiW(type, szUUID))
667 V_VT(v) = VT_BSTR;
668 V_BSTR(v) = bstr_from_xmlChar(str);
670 if(!V_BSTR(v))
671 return E_OUTOFMEMORY;
673 else if(!lstrcmpiW(type, szDateTime) || !lstrcmpiW(type, szDateTimeTZ) ||
674 !lstrcmpiW(type, szDate) || !lstrcmpiW(type, szTime) ||
675 !lstrcmpiW(type, szTimeTZ))
677 VARIANT src;
678 WCHAR *p, *e;
679 SYSTEMTIME st;
680 DOUBLE date = 0.0;
682 st.wYear = 1899;
683 st.wMonth = 12;
684 st.wDay = 30;
685 st.wDayOfWeek = st.wHour = st.wMinute = st.wSecond = st.wMilliseconds = 0;
687 V_VT(&src) = VT_BSTR;
688 V_BSTR(&src) = bstr_from_xmlChar(str);
690 if(!V_BSTR(&src))
691 return E_OUTOFMEMORY;
693 p = V_BSTR(&src);
694 e = p + SysStringLen(V_BSTR(&src));
696 if(p+4<e && *(p+4)=='-') /* parse date (yyyy-mm-dd) */
698 st.wYear = atoiW(p);
699 st.wMonth = atoiW(p+5);
700 st.wDay = atoiW(p+8);
701 p += 10;
703 if(*p == 'T') p++;
706 if(p+2<e && *(p+2)==':') /* parse time (hh:mm:ss.?) */
708 st.wHour = atoiW(p);
709 st.wMinute = atoiW(p+3);
710 st.wSecond = atoiW(p+6);
711 p += 8;
713 if(*p == '.')
715 p++;
716 while(isdigitW(*p)) p++;
720 SystemTimeToVariantTime(&st, &date);
721 V_VT(v) = VT_DATE;
722 V_DATE(v) = date;
724 if(*p == '+') /* parse timezone offset (+hh:mm) */
725 V_DATE(v) += (DOUBLE)atoiW(p+1)/24 + (DOUBLE)atoiW(p+4)/1440;
726 else if(*p == '-') /* parse timezone offset (-hh:mm) */
727 V_DATE(v) -= (DOUBLE)atoiW(p+1)/24 + (DOUBLE)atoiW(p+4)/1440;
729 VariantClear(&src);
731 else if(!lstrcmpiW(type, szBinHex))
733 SAFEARRAYBOUND sab;
734 int i, len;
736 len = xmlStrlen(str)/2;
737 sab.lLbound = 0;
738 sab.cElements = len;
740 V_VT(v) = (VT_ARRAY|VT_UI1);
741 V_ARRAY(v) = SafeArrayCreate(VT_UI1, 1, &sab);
743 if(!V_ARRAY(v))
744 return E_OUTOFMEMORY;
746 for(i=0; i<len; i++)
747 ((BYTE*)V_ARRAY(v)->pvData)[i] = (hex_to_byte(str[2*i])<<4)
748 + hex_to_byte(str[2*i+1]);
750 else if(!lstrcmpiW(type, szBinBase64))
752 SAFEARRAYBOUND sab;
753 int i, len;
755 len = xmlStrlen(str);
756 if(str[len-2] == '=') i = 2;
757 else if(str[len-1] == '=') i = 1;
758 else i = 0;
760 sab.lLbound = 0;
761 sab.cElements = len/4*3-i;
763 V_VT(v) = (VT_ARRAY|VT_UI1);
764 V_ARRAY(v) = SafeArrayCreate(VT_UI1, 1, &sab);
766 if(!V_ARRAY(v))
767 return E_OUTOFMEMORY;
769 for(i=0; i<len/4; i++)
771 ((BYTE*)V_ARRAY(v)->pvData)[3*i] = (base64_to_byte(str[4*i])<<2)
772 + (base64_to_byte(str[4*i+1])>>4);
773 if(3*i+1 < sab.cElements)
774 ((BYTE*)V_ARRAY(v)->pvData)[3*i+1] = (base64_to_byte(str[4*i+1])<<4)
775 + (base64_to_byte(str[4*i+2])>>2);
776 if(3*i+2 < sab.cElements)
777 ((BYTE*)V_ARRAY(v)->pvData)[3*i+2] = (base64_to_byte(str[4*i+2])<<6)
778 + base64_to_byte(str[4*i+3]);
781 else
783 VARIANT src;
784 HRESULT hres;
786 if(!lstrcmpiW(type, szInt) || !lstrcmpiW(type, szI4))
787 V_VT(v) = VT_I4;
788 else if(!lstrcmpiW(type, szFixed))
789 V_VT(v) = VT_CY;
790 else if(!lstrcmpiW(type, szBoolean))
791 V_VT(v) = VT_BOOL;
792 else if(!lstrcmpiW(type, szI1))
793 V_VT(v) = VT_I1;
794 else if(!lstrcmpiW(type, szI2))
795 V_VT(v) = VT_I2;
796 else if(!lstrcmpiW(type, szIU1))
797 V_VT(v) = VT_UI1;
798 else if(!lstrcmpiW(type, szIU2))
799 V_VT(v) = VT_UI2;
800 else if(!lstrcmpiW(type, szIU4))
801 V_VT(v) = VT_UI4;
802 else if(!lstrcmpiW(type, szR4))
803 V_VT(v) = VT_R4;
804 else if(!lstrcmpiW(type, szR8) || !lstrcmpiW(type, szFloat))
805 V_VT(v) = VT_R8;
806 else
808 FIXME("Type handling not yet implemented\n");
809 V_VT(v) = VT_BSTR;
812 V_VT(&src) = VT_BSTR;
813 V_BSTR(&src) = bstr_from_xmlChar(str);
815 if(!V_BSTR(&src))
816 return E_OUTOFMEMORY;
818 hres = VariantChangeTypeEx(v, &src, MAKELCID(MAKELANGID(
819 LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT),0, V_VT(v));
820 VariantClear(&src);
821 return hres;
824 return S_OK;
827 BSTR EnsureCorrectEOL(BSTR sInput)
829 int nNum = 0;
830 BSTR sNew;
831 int nLen;
832 int i;
834 nLen = SysStringLen(sInput);
835 /* Count line endings */
836 for(i=0; i < nLen; i++)
838 if(sInput[i] == '\n')
839 nNum++;
842 TRACE("len=%d, num=%d\n", nLen, nNum);
844 /* Add linefeed as needed */
845 if(nNum > 0)
847 int nPlace = 0;
848 sNew = SysAllocStringLen(NULL, nLen + nNum+1);
849 for(i=0; i < nLen; i++)
851 if(sInput[i] == '\n')
853 sNew[i+nPlace] = '\r';
854 nPlace++;
856 sNew[i+nPlace] = sInput[i];
859 SysFreeString(sInput);
861 else
863 sNew = sInput;
866 TRACE("len %d\n", SysStringLen(sNew));
868 return sNew;
871 /* Removes encoding information and last character (nullbyte) */
872 static BSTR EnsureNoEncoding(BSTR sInput)
874 static const WCHAR wszEncoding[] = {'e','n','c','o','d','i','n','g','='};
875 BSTR sNew;
876 WCHAR *pBeg, *pEnd;
878 pBeg = sInput;
879 while(*pBeg != '\n' && memcmp(pBeg, wszEncoding, sizeof(wszEncoding)))
880 pBeg++;
882 if(*pBeg == '\n')
884 SysReAllocStringLen(&sInput, sInput, SysStringLen(sInput)-1);
885 return sInput;
887 pBeg--;
889 pEnd = pBeg + sizeof(wszEncoding)/sizeof(WCHAR) + 2;
890 while(*pEnd != '\"') pEnd++;
891 pEnd++;
893 sNew = SysAllocStringLen(NULL,
894 pBeg-sInput + SysStringLen(sInput)-(pEnd-sInput)-1);
895 memcpy(sNew, sInput, (pBeg-sInput)*sizeof(WCHAR));
896 memcpy(&sNew[pBeg-sInput], pEnd, (SysStringLen(sInput)-(pEnd-sInput)-1)*sizeof(WCHAR));
898 SysFreeString(sInput);
899 return sNew;
903 * We are trying to replicate the same behaviour as msxml by converting
904 * line endings to \r\n and using indents as \t. The problem is that msxml
905 * only formats nodes that have a line ending. Using libxml we cannot
906 * reproduce behaviour exactly.
909 HRESULT node_get_xml(xmlnode *This, BOOL ensure_eol, BOOL ensure_no_encoding, BSTR *ret)
911 xmlBufferPtr xml_buf;
912 xmlNodePtr xmldecl;
913 int size;
915 if(!ret)
916 return E_INVALIDARG;
918 *ret = NULL;
920 xml_buf = xmlBufferCreate();
921 if(!xml_buf)
922 return E_OUTOFMEMORY;
924 xmldecl = xmldoc_unlink_xmldecl( This->node->doc );
926 size = xmlNodeDump(xml_buf, This->node->doc, This->node, 0, 1);
927 if(size > 0) {
928 const xmlChar *buf_content;
929 BSTR content;
931 /* Attribute Nodes return a space in front of their name */
932 buf_content = xmlBufferContent(xml_buf);
934 content = bstr_from_xmlChar(buf_content + (buf_content[0] == ' ' ? 1 : 0));
935 if(ensure_eol)
936 content = EnsureCorrectEOL(content);
937 if(ensure_no_encoding)
938 content = EnsureNoEncoding(content);
940 *ret = content;
941 }else {
942 *ret = SysAllocStringLen(NULL, 0);
945 xmlBufferFree(xml_buf);
946 xmldoc_link_xmldecl( This->node->doc, xmldecl );
947 return *ret ? S_OK : E_OUTOFMEMORY;
950 static HRESULT WINAPI xmlnode_transformNode(
951 IXMLDOMNode *iface,
952 IXMLDOMNode* styleSheet,
953 BSTR* xmlString)
955 #ifdef SONAME_LIBXSLT
956 xmlnode *This = impl_from_IXMLDOMNode( iface );
957 xmlnode *pStyleSheet = NULL;
958 xsltStylesheetPtr xsltSS = NULL;
959 xmlDocPtr result = NULL;
961 TRACE("(%p)->(%p %p)\n", This, styleSheet, xmlString);
963 if (!libxslt_handle)
964 return E_NOTIMPL;
965 if(!styleSheet || !xmlString)
966 return E_INVALIDARG;
968 *xmlString = NULL;
970 pStyleSheet = get_node_obj(styleSheet);
971 if(!pStyleSheet) {
972 FIXME("styleSheet is not our xmlnode implementation\n");
973 return E_FAIL;
976 xsltSS = pxsltParseStylesheetDoc( pStyleSheet->node->doc);
977 if(xsltSS)
979 result = pxsltApplyStylesheet(xsltSS, This->node->doc, NULL);
980 if(result)
982 const xmlChar *pContent;
984 if(result->type == XML_HTML_DOCUMENT_NODE)
986 xmlOutputBufferPtr pOutput = xmlAllocOutputBuffer(NULL);
987 if(pOutput)
989 htmlDocContentDumpOutput(pOutput, result->doc, NULL);
990 pContent = xmlBufferContent(pOutput->buffer);
991 *xmlString = bstr_from_xmlChar(pContent);
992 xmlOutputBufferClose(pOutput);
995 else
997 xmlBufferPtr pXmlBuf;
998 int nSize;
1000 pXmlBuf = xmlBufferCreate();
1001 if(pXmlBuf)
1003 nSize = xmlNodeDump(pXmlBuf, NULL, (xmlNodePtr)result, 0, 0);
1004 if(nSize > 0)
1006 pContent = xmlBufferContent(pXmlBuf);
1007 *xmlString = bstr_from_xmlChar(pContent);
1009 xmlBufferFree(pXmlBuf);
1012 xmlFreeDoc(result);
1014 /* libxslt "helpfully" frees the XML document the stylesheet was
1015 generated from, too */
1016 xsltSS->doc = NULL;
1017 pxsltFreeStylesheet(xsltSS);
1020 if(*xmlString == NULL)
1021 *xmlString = SysAllocStringLen(NULL, 0);
1023 return S_OK;
1024 #else
1025 FIXME("libxslt headers were not found at compile time\n");
1026 return E_NOTIMPL;
1027 #endif
1030 static HRESULT WINAPI xmlnode_selectNodes(
1031 IXMLDOMNode *iface,
1032 BSTR queryString,
1033 IXMLDOMNodeList** resultList)
1035 xmlnode *This = impl_from_IXMLDOMNode( iface );
1036 xmlChar* str;
1037 HRESULT hr;
1039 TRACE("(%p)->(%s %p)\n", This, debugstr_w(queryString), resultList );
1041 if (!queryString || !resultList) return E_INVALIDARG;
1043 str = xmlChar_from_wchar(queryString);
1044 hr = queryresult_create(This->node, str, resultList);
1045 heap_free(str);
1047 return hr;
1050 static HRESULT WINAPI xmlnode_selectSingleNode(
1051 IXMLDOMNode *iface,
1052 BSTR queryString,
1053 IXMLDOMNode** resultNode)
1055 xmlnode *This = impl_from_IXMLDOMNode( iface );
1056 IXMLDOMNodeList *list;
1057 HRESULT r;
1059 TRACE("(%p)->(%s %p)\n", This, debugstr_w(queryString), resultNode );
1061 r = IXMLDOMNode_selectNodes(This->iface, queryString, &list);
1062 if(r == S_OK)
1064 r = IXMLDOMNodeList_nextNode(list, resultNode);
1065 IXMLDOMNodeList_Release(list);
1067 return r;
1070 HRESULT node_get_namespaceURI(xmlnode *This, BSTR *namespaceURI)
1072 xmlNsPtr *ns;
1074 if(!namespaceURI)
1075 return E_INVALIDARG;
1077 *namespaceURI = NULL;
1079 if ((ns = xmlGetNsList(This->node->doc, This->node)))
1081 if (ns[0]->href) *namespaceURI = bstr_from_xmlChar( ns[0]->href );
1082 xmlFree(ns);
1085 TRACE("uri: %s\n", debugstr_w(*namespaceURI));
1087 return *namespaceURI ? S_OK : S_FALSE;
1090 HRESULT node_get_prefix(xmlnode *This, BSTR *prefix)
1092 xmlNsPtr *ns;
1094 if (!prefix) return E_INVALIDARG;
1096 *prefix = NULL;
1098 if ((ns = xmlGetNsList(This->node->doc, This->node)))
1100 if (ns[0]->prefix) *prefix = bstr_from_xmlChar( ns[0]->prefix );
1101 xmlFree(ns);
1104 TRACE("prefix: %s\n", debugstr_w(*prefix));
1106 return *prefix ? S_OK : S_FALSE;
1109 HRESULT node_get_base_name(xmlnode *This, BSTR *name)
1111 if (!name) return E_INVALIDARG;
1113 *name = bstr_from_xmlChar(This->node->name);
1114 if (!*name) return E_OUTOFMEMORY;
1116 TRACE("returning %s\n", debugstr_w(*name));
1118 return S_OK;
1121 static const struct IXMLDOMNodeVtbl xmlnode_vtbl =
1123 NULL,
1124 NULL,
1125 NULL,
1126 NULL,
1127 NULL,
1128 NULL,
1129 NULL,
1130 NULL,
1131 NULL,
1132 NULL,
1133 NULL,
1134 NULL,
1135 NULL,
1136 NULL,
1137 NULL,
1138 NULL,
1139 NULL,
1140 NULL,
1141 NULL,
1142 NULL,
1143 NULL,
1144 NULL,
1145 xmlnode_hasChildNodes,
1146 xmlnode_get_ownerDocument,
1147 NULL,
1148 NULL,
1149 xmlnode_get_text,
1150 NULL,
1151 NULL,
1152 NULL,
1153 NULL,
1154 NULL,
1155 NULL,
1156 NULL,
1157 NULL,
1158 xmlnode_transformNode,
1159 xmlnode_selectNodes,
1160 xmlnode_selectSingleNode
1163 void destroy_xmlnode(xmlnode *This)
1165 if(This->node)
1166 xmldoc_release(This->node->doc);
1169 void init_xmlnode(xmlnode *This, xmlNodePtr node, IXMLDOMNode *node_iface, dispex_static_data_t *dispex_data)
1171 if(node)
1172 xmldoc_add_ref( node->doc );
1174 This->IXMLDOMNode_iface.lpVtbl = &xmlnode_vtbl;
1175 This->node = node;
1176 This->iface = node_iface;
1178 if(dispex_data)
1179 init_dispex(&This->dispex, (IUnknown*)This->iface, dispex_data);
1180 else
1181 This->dispex.outer = NULL;
1184 typedef struct {
1185 xmlnode node;
1186 IXMLDOMNode IXMLDOMNode_iface;
1187 LONG ref;
1188 } unknode;
1190 static inline unknode *unknode_from_IXMLDOMNode(IXMLDOMNode *iface)
1192 return CONTAINING_RECORD(iface, unknode, IXMLDOMNode_iface);
1195 static HRESULT WINAPI unknode_QueryInterface(
1196 IXMLDOMNode *iface,
1197 REFIID riid,
1198 void** ppvObject )
1200 unknode *This = unknode_from_IXMLDOMNode( iface );
1202 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
1204 if (IsEqualGUID(riid, &IID_IUnknown)) {
1205 *ppvObject = iface;
1206 }else if (IsEqualGUID( riid, &IID_IDispatch) ||
1207 IsEqualGUID( riid, &IID_IXMLDOMNode)) {
1208 *ppvObject = &This->IXMLDOMNode_iface;
1209 }else if(node_query_interface(&This->node, riid, ppvObject)) {
1210 return *ppvObject ? S_OK : E_NOINTERFACE;
1211 }else {
1212 FIXME("interface %s not implemented\n", debugstr_guid(riid));
1213 *ppvObject = NULL;
1214 return E_NOINTERFACE;
1217 IUnknown_AddRef((IUnknown*)*ppvObject);
1218 return S_OK;
1221 static ULONG WINAPI unknode_AddRef(
1222 IXMLDOMNode *iface )
1224 unknode *This = unknode_from_IXMLDOMNode( iface );
1226 return InterlockedIncrement(&This->ref);
1229 static ULONG WINAPI unknode_Release(
1230 IXMLDOMNode *iface )
1232 unknode *This = unknode_from_IXMLDOMNode( iface );
1233 LONG ref;
1235 ref = InterlockedDecrement( &This->ref );
1236 if(!ref) {
1237 destroy_xmlnode(&This->node);
1238 heap_free(This);
1241 return ref;
1244 static HRESULT WINAPI unknode_GetTypeInfoCount(
1245 IXMLDOMNode *iface,
1246 UINT* pctinfo )
1248 unknode *This = unknode_from_IXMLDOMNode( iface );
1250 TRACE("(%p)->(%p)\n", This, pctinfo);
1252 *pctinfo = 1;
1254 return S_OK;
1257 static HRESULT WINAPI unknode_GetTypeInfo(
1258 IXMLDOMNode *iface,
1259 UINT iTInfo,
1260 LCID lcid,
1261 ITypeInfo** ppTInfo )
1263 unknode *This = unknode_from_IXMLDOMNode( iface );
1264 HRESULT hr;
1266 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1268 hr = get_typeinfo(IXMLDOMNode_tid, ppTInfo);
1270 return hr;
1273 static HRESULT WINAPI unknode_GetIDsOfNames(
1274 IXMLDOMNode *iface,
1275 REFIID riid,
1276 LPOLESTR* rgszNames,
1277 UINT cNames,
1278 LCID lcid,
1279 DISPID* rgDispId )
1281 unknode *This = unknode_from_IXMLDOMNode( iface );
1283 ITypeInfo *typeinfo;
1284 HRESULT hr;
1286 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1287 lcid, rgDispId);
1289 if(!rgszNames || cNames == 0 || !rgDispId)
1290 return E_INVALIDARG;
1292 hr = get_typeinfo(IXMLDOMNode_tid, &typeinfo);
1293 if(SUCCEEDED(hr))
1295 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1296 ITypeInfo_Release(typeinfo);
1299 return hr;
1302 static HRESULT WINAPI unknode_Invoke(
1303 IXMLDOMNode *iface,
1304 DISPID dispIdMember,
1305 REFIID riid,
1306 LCID lcid,
1307 WORD wFlags,
1308 DISPPARAMS* pDispParams,
1309 VARIANT* pVarResult,
1310 EXCEPINFO* pExcepInfo,
1311 UINT* puArgErr )
1313 unknode *This = unknode_from_IXMLDOMNode( iface );
1314 ITypeInfo *typeinfo;
1315 HRESULT hr;
1317 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1318 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1320 hr = get_typeinfo(IXMLDOMNode_tid, &typeinfo);
1321 if(SUCCEEDED(hr))
1323 hr = ITypeInfo_Invoke(typeinfo, &This->IXMLDOMNode_iface, dispIdMember, wFlags, pDispParams,
1324 pVarResult, pExcepInfo, puArgErr);
1325 ITypeInfo_Release(typeinfo);
1328 return hr;
1331 static HRESULT WINAPI unknode_get_nodeName(
1332 IXMLDOMNode *iface,
1333 BSTR* p )
1335 unknode *This = unknode_from_IXMLDOMNode( iface );
1337 FIXME("(%p)->(%p)\n", This, p);
1339 return node_get_nodeName(&This->node, p);
1342 static HRESULT WINAPI unknode_get_nodeValue(
1343 IXMLDOMNode *iface,
1344 VARIANT* value)
1346 unknode *This = unknode_from_IXMLDOMNode( iface );
1348 FIXME("(%p)->(%p)\n", This, value);
1350 if(!value)
1351 return E_INVALIDARG;
1353 V_VT(value) = VT_NULL;
1354 return S_FALSE;
1357 static HRESULT WINAPI unknode_put_nodeValue(
1358 IXMLDOMNode *iface,
1359 VARIANT value)
1361 unknode *This = unknode_from_IXMLDOMNode( iface );
1362 FIXME("(%p)->(v%d)\n", This, V_VT(&value));
1363 return E_FAIL;
1366 static HRESULT WINAPI unknode_get_nodeType(
1367 IXMLDOMNode *iface,
1368 DOMNodeType* domNodeType )
1370 unknode *This = unknode_from_IXMLDOMNode( iface );
1372 FIXME("(%p)->(%p)\n", This, domNodeType);
1374 *domNodeType = This->node.node->type;
1375 return S_OK;
1378 static HRESULT WINAPI unknode_get_parentNode(
1379 IXMLDOMNode *iface,
1380 IXMLDOMNode** parent )
1382 unknode *This = unknode_from_IXMLDOMNode( iface );
1383 FIXME("(%p)->(%p)\n", This, parent);
1384 if (!parent) return E_INVALIDARG;
1385 *parent = NULL;
1386 return S_FALSE;
1389 static HRESULT WINAPI unknode_get_childNodes(
1390 IXMLDOMNode *iface,
1391 IXMLDOMNodeList** outList)
1393 unknode *This = unknode_from_IXMLDOMNode( iface );
1395 TRACE("(%p)->(%p)\n", This, outList);
1397 return node_get_child_nodes(&This->node, outList);
1400 static HRESULT WINAPI unknode_get_firstChild(
1401 IXMLDOMNode *iface,
1402 IXMLDOMNode** domNode)
1404 unknode *This = unknode_from_IXMLDOMNode( iface );
1406 TRACE("(%p)->(%p)\n", This, domNode);
1408 return node_get_first_child(&This->node, domNode);
1411 static HRESULT WINAPI unknode_get_lastChild(
1412 IXMLDOMNode *iface,
1413 IXMLDOMNode** domNode)
1415 unknode *This = unknode_from_IXMLDOMNode( iface );
1417 TRACE("(%p)->(%p)\n", This, domNode);
1419 return node_get_last_child(&This->node, domNode);
1422 static HRESULT WINAPI unknode_get_previousSibling(
1423 IXMLDOMNode *iface,
1424 IXMLDOMNode** domNode)
1426 unknode *This = unknode_from_IXMLDOMNode( iface );
1428 TRACE("(%p)->(%p)\n", This, domNode);
1430 return node_get_previous_sibling(&This->node, domNode);
1433 static HRESULT WINAPI unknode_get_nextSibling(
1434 IXMLDOMNode *iface,
1435 IXMLDOMNode** domNode)
1437 unknode *This = unknode_from_IXMLDOMNode( iface );
1439 TRACE("(%p)->(%p)\n", This, domNode);
1441 return node_get_next_sibling(&This->node, domNode);
1444 static HRESULT WINAPI unknode_get_attributes(
1445 IXMLDOMNode *iface,
1446 IXMLDOMNamedNodeMap** attributeMap)
1448 unknode *This = unknode_from_IXMLDOMNode( iface );
1450 FIXME("(%p)->(%p)\n", This, attributeMap);
1452 return return_null_ptr((void**)attributeMap);
1455 static HRESULT WINAPI unknode_insertBefore(
1456 IXMLDOMNode *iface,
1457 IXMLDOMNode* newNode, VARIANT refChild,
1458 IXMLDOMNode** outOldNode)
1460 unknode *This = unknode_from_IXMLDOMNode( iface );
1462 FIXME("(%p)->(%p x%d %p)\n", This, newNode, V_VT(&refChild), outOldNode);
1464 return node_insert_before(&This->node, newNode, &refChild, outOldNode);
1467 static HRESULT WINAPI unknode_replaceChild(
1468 IXMLDOMNode *iface,
1469 IXMLDOMNode* newNode,
1470 IXMLDOMNode* oldNode,
1471 IXMLDOMNode** outOldNode)
1473 unknode *This = unknode_from_IXMLDOMNode( iface );
1475 FIXME("(%p)->(%p %p %p)\n", This, newNode, oldNode, outOldNode);
1477 return node_replace_child(&This->node, newNode, oldNode, outOldNode);
1480 static HRESULT WINAPI unknode_removeChild(
1481 IXMLDOMNode *iface,
1482 IXMLDOMNode* domNode, IXMLDOMNode** oldNode)
1484 unknode *This = unknode_from_IXMLDOMNode( iface );
1485 return node_remove_child(&This->node, domNode, oldNode);
1488 static HRESULT WINAPI unknode_appendChild(
1489 IXMLDOMNode *iface,
1490 IXMLDOMNode* newNode, IXMLDOMNode** outNewNode)
1492 unknode *This = unknode_from_IXMLDOMNode( iface );
1493 return node_append_child(&This->node, newNode, outNewNode);
1496 static HRESULT WINAPI unknode_hasChildNodes(
1497 IXMLDOMNode *iface,
1498 VARIANT_BOOL* pbool)
1500 unknode *This = unknode_from_IXMLDOMNode( iface );
1501 return IXMLDOMNode_hasChildNodes( &This->node.IXMLDOMNode_iface, pbool );
1504 static HRESULT WINAPI unknode_get_ownerDocument(
1505 IXMLDOMNode *iface,
1506 IXMLDOMDocument** domDocument)
1508 unknode *This = unknode_from_IXMLDOMNode( iface );
1509 return IXMLDOMNode_get_ownerDocument( &This->node.IXMLDOMNode_iface, domDocument );
1512 static HRESULT WINAPI unknode_cloneNode(
1513 IXMLDOMNode *iface,
1514 VARIANT_BOOL pbool, IXMLDOMNode** outNode)
1516 unknode *This = unknode_from_IXMLDOMNode( iface );
1517 return IXMLDOMNode_cloneNode( &This->node.IXMLDOMNode_iface, pbool, outNode );
1520 static HRESULT WINAPI unknode_get_nodeTypeString(
1521 IXMLDOMNode *iface,
1522 BSTR* p)
1524 unknode *This = unknode_from_IXMLDOMNode( iface );
1526 FIXME("(%p)->(%p)\n", This, p);
1528 return node_get_nodeName(&This->node, p);
1531 static HRESULT WINAPI unknode_get_text(
1532 IXMLDOMNode *iface,
1533 BSTR* p)
1535 unknode *This = unknode_from_IXMLDOMNode( iface );
1536 return IXMLDOMNode_get_text( &This->node.IXMLDOMNode_iface, p );
1539 static HRESULT WINAPI unknode_put_text(
1540 IXMLDOMNode *iface,
1541 BSTR p)
1543 unknode *This = unknode_from_IXMLDOMNode( iface );
1544 return IXMLDOMNode_put_text( &This->node.IXMLDOMNode_iface, p );
1547 static HRESULT WINAPI unknode_get_specified(
1548 IXMLDOMNode *iface,
1549 VARIANT_BOOL* isSpecified)
1551 unknode *This = unknode_from_IXMLDOMNode( iface );
1552 FIXME("(%p)->(%p) stub!\n", This, isSpecified);
1553 *isSpecified = VARIANT_TRUE;
1554 return S_OK;
1557 static HRESULT WINAPI unknode_get_definition(
1558 IXMLDOMNode *iface,
1559 IXMLDOMNode** definitionNode)
1561 unknode *This = unknode_from_IXMLDOMNode( iface );
1562 FIXME("(%p)->(%p)\n", This, definitionNode);
1563 return E_NOTIMPL;
1566 static HRESULT WINAPI unknode_get_nodeTypedValue(
1567 IXMLDOMNode *iface,
1568 VARIANT* var1)
1570 unknode *This = unknode_from_IXMLDOMNode( iface );
1571 FIXME("(%p)->(%p)\n", This, var1);
1572 return return_null_var(var1);
1575 static HRESULT WINAPI unknode_put_nodeTypedValue(
1576 IXMLDOMNode *iface,
1577 VARIANT typedValue)
1579 unknode *This = unknode_from_IXMLDOMNode( iface );
1580 FIXME("(%p)->(%s)\n", This, debugstr_variant(&typedValue));
1581 return E_NOTIMPL;
1584 static HRESULT WINAPI unknode_get_dataType(
1585 IXMLDOMNode *iface,
1586 VARIANT* var1)
1588 unknode *This = unknode_from_IXMLDOMNode( iface );
1589 return IXMLDOMNode_get_dataType( &This->node.IXMLDOMNode_iface, var1 );
1592 static HRESULT WINAPI unknode_put_dataType(
1593 IXMLDOMNode *iface,
1594 BSTR p)
1596 unknode *This = unknode_from_IXMLDOMNode( iface );
1598 FIXME("(%p)->(%s)\n", This, debugstr_w(p));
1600 if(!p)
1601 return E_INVALIDARG;
1603 return E_FAIL;
1606 static HRESULT WINAPI unknode_get_xml(
1607 IXMLDOMNode *iface,
1608 BSTR* p)
1610 unknode *This = unknode_from_IXMLDOMNode( iface );
1612 FIXME("(%p)->(%p)\n", This, p);
1614 return node_get_xml(&This->node, FALSE, FALSE, p);
1617 static HRESULT WINAPI unknode_transformNode(
1618 IXMLDOMNode *iface,
1619 IXMLDOMNode* domNode, BSTR* p)
1621 unknode *This = unknode_from_IXMLDOMNode( iface );
1622 return IXMLDOMNode_transformNode( &This->node.IXMLDOMNode_iface, domNode, p );
1625 static HRESULT WINAPI unknode_selectNodes(
1626 IXMLDOMNode *iface,
1627 BSTR p, IXMLDOMNodeList** outList)
1629 unknode *This = unknode_from_IXMLDOMNode( iface );
1630 return IXMLDOMNode_selectNodes( &This->node.IXMLDOMNode_iface, p, outList );
1633 static HRESULT WINAPI unknode_selectSingleNode(
1634 IXMLDOMNode *iface,
1635 BSTR p, IXMLDOMNode** outNode)
1637 unknode *This = unknode_from_IXMLDOMNode( iface );
1638 return IXMLDOMNode_selectSingleNode( &This->node.IXMLDOMNode_iface, p, outNode );
1641 static HRESULT WINAPI unknode_get_parsed(
1642 IXMLDOMNode *iface,
1643 VARIANT_BOOL* isParsed)
1645 unknode *This = unknode_from_IXMLDOMNode( iface );
1646 FIXME("(%p)->(%p) stub!\n", This, isParsed);
1647 *isParsed = VARIANT_TRUE;
1648 return S_OK;
1651 static HRESULT WINAPI unknode_get_namespaceURI(
1652 IXMLDOMNode *iface,
1653 BSTR* p)
1655 unknode *This = unknode_from_IXMLDOMNode( iface );
1656 TRACE("(%p)->(%p)\n", This, p);
1657 return node_get_namespaceURI(&This->node, p);
1660 static HRESULT WINAPI unknode_get_prefix(
1661 IXMLDOMNode *iface,
1662 BSTR* p)
1664 unknode *This = unknode_from_IXMLDOMNode( iface );
1665 return IXMLDOMNode_get_prefix( &This->node.IXMLDOMNode_iface, p );
1668 static HRESULT WINAPI unknode_get_baseName(
1669 IXMLDOMNode *iface,
1670 BSTR* p)
1672 unknode *This = unknode_from_IXMLDOMNode( iface );
1673 return IXMLDOMNode_get_baseName( &This->node.IXMLDOMNode_iface, p );
1676 static HRESULT WINAPI unknode_transformNodeToObject(
1677 IXMLDOMNode *iface,
1678 IXMLDOMNode* domNode, VARIANT var1)
1680 unknode *This = unknode_from_IXMLDOMNode( iface );
1681 FIXME("(%p)->(%p %s)\n", This, domNode, debugstr_variant(&var1));
1682 return E_NOTIMPL;
1685 static const struct IXMLDOMNodeVtbl unknode_vtbl =
1687 unknode_QueryInterface,
1688 unknode_AddRef,
1689 unknode_Release,
1690 unknode_GetTypeInfoCount,
1691 unknode_GetTypeInfo,
1692 unknode_GetIDsOfNames,
1693 unknode_Invoke,
1694 unknode_get_nodeName,
1695 unknode_get_nodeValue,
1696 unknode_put_nodeValue,
1697 unknode_get_nodeType,
1698 unknode_get_parentNode,
1699 unknode_get_childNodes,
1700 unknode_get_firstChild,
1701 unknode_get_lastChild,
1702 unknode_get_previousSibling,
1703 unknode_get_nextSibling,
1704 unknode_get_attributes,
1705 unknode_insertBefore,
1706 unknode_replaceChild,
1707 unknode_removeChild,
1708 unknode_appendChild,
1709 unknode_hasChildNodes,
1710 unknode_get_ownerDocument,
1711 unknode_cloneNode,
1712 unknode_get_nodeTypeString,
1713 unknode_get_text,
1714 unknode_put_text,
1715 unknode_get_specified,
1716 unknode_get_definition,
1717 unknode_get_nodeTypedValue,
1718 unknode_put_nodeTypedValue,
1719 unknode_get_dataType,
1720 unknode_put_dataType,
1721 unknode_get_xml,
1722 unknode_transformNode,
1723 unknode_selectNodes,
1724 unknode_selectSingleNode,
1725 unknode_get_parsed,
1726 unknode_get_namespaceURI,
1727 unknode_get_prefix,
1728 unknode_get_baseName,
1729 unknode_transformNodeToObject
1732 IXMLDOMNode *create_node( xmlNodePtr node )
1734 IUnknown *pUnk;
1735 IXMLDOMNode *ret;
1736 HRESULT hr;
1738 if ( !node )
1739 return NULL;
1741 TRACE("type %d\n", node->type);
1742 switch(node->type)
1744 case XML_ELEMENT_NODE:
1745 pUnk = create_element( node );
1746 break;
1747 case XML_ATTRIBUTE_NODE:
1748 pUnk = create_attribute( node );
1749 break;
1750 case XML_TEXT_NODE:
1751 pUnk = create_text( node );
1752 break;
1753 case XML_CDATA_SECTION_NODE:
1754 pUnk = create_cdata( node );
1755 break;
1756 case XML_ENTITY_REF_NODE:
1757 pUnk = create_doc_entity_ref( node );
1758 break;
1759 case XML_PI_NODE:
1760 pUnk = create_pi( node );
1761 break;
1762 case XML_COMMENT_NODE:
1763 pUnk = create_comment( node );
1764 break;
1765 case XML_DOCUMENT_NODE:
1766 pUnk = create_domdoc( node );
1767 break;
1768 case XML_DOCUMENT_FRAG_NODE:
1769 pUnk = create_doc_fragment( node );
1770 break;
1771 case XML_DTD_NODE:
1772 pUnk = create_doc_type( node );
1773 break;
1774 default: {
1775 unknode *new_node;
1777 FIXME("only creating basic node for type %d\n", node->type);
1779 new_node = heap_alloc(sizeof(unknode));
1780 if(!new_node)
1781 return NULL;
1783 new_node->IXMLDOMNode_iface.lpVtbl = &unknode_vtbl;
1784 new_node->ref = 1;
1785 init_xmlnode(&new_node->node, node, &new_node->IXMLDOMNode_iface, NULL);
1786 pUnk = (IUnknown*)&new_node->IXMLDOMNode_iface;
1790 hr = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMNode, (LPVOID*)&ret);
1791 IUnknown_Release(pUnk);
1792 if(FAILED(hr)) return NULL;
1793 return ret;
1795 #endif