msxml3: Dump set node value.
[wine/multimedia.git] / dlls / msxml3 / node.c
blob221abc26b7a451969f82f2901126c21ea9865d47
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 <assert.h>
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winuser.h"
30 #include "winnls.h"
31 #include "ole2.h"
32 #include "msxml6.h"
34 #include "msxml_private.h"
36 #ifdef HAVE_LIBXML2
37 # include <libxml/HTMLtree.h>
38 #endif
40 #include "wine/debug.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
44 #ifdef HAVE_LIBXML2
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 (xmlnode *)((char*)iface - FIELD_OFFSET(xmlnode, lpVtbl));
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 static HRESULT WINAPI xmlnode_removeChild(
405 IXMLDOMNode *iface,
406 IXMLDOMNode* childNode,
407 IXMLDOMNode** oldChild)
409 xmlnode *This = impl_from_IXMLDOMNode( iface );
410 xmlnode *child_node;
412 TRACE("(%p)->(%p %p)\n", This, childNode, oldChild);
414 if(!childNode) return E_INVALIDARG;
416 if(oldChild)
417 *oldChild = NULL;
419 child_node = get_node_obj(childNode);
420 if(!child_node) {
421 FIXME("childNode is not our node implementation\n");
422 return E_FAIL;
425 if(child_node->node->parent != This->node)
427 WARN("childNode %p is not a child of %p\n", childNode, iface);
428 return E_INVALIDARG;
431 xmlUnlinkNode(child_node->node);
433 if(oldChild)
435 IXMLDOMNode_AddRef(childNode);
436 *oldChild = childNode;
439 return S_OK;
442 static HRESULT WINAPI xmlnode_appendChild(
443 IXMLDOMNode *iface,
444 IXMLDOMNode* newChild,
445 IXMLDOMNode** outNewChild)
447 xmlnode *This = impl_from_IXMLDOMNode( iface );
448 DOMNodeType type;
449 VARIANT var;
450 HRESULT hr;
452 TRACE("(%p)->(%p %p)\n", This, newChild, outNewChild);
454 hr = IXMLDOMNode_get_nodeType(newChild, &type);
455 if(FAILED(hr) || type == NODE_ATTRIBUTE) {
456 if(outNewChild) *outNewChild = NULL;
457 return E_FAIL;
460 VariantInit(&var);
461 return IXMLDOMNode_insertBefore(This->iface, newChild, var, outNewChild);
464 static HRESULT WINAPI xmlnode_hasChildNodes(
465 IXMLDOMNode *iface,
466 VARIANT_BOOL* hasChild)
468 xmlnode *This = impl_from_IXMLDOMNode( iface );
470 TRACE("(%p)->(%p)\n", This, hasChild);
472 if (!hasChild)
473 return E_INVALIDARG;
474 if (!This->node->children)
476 *hasChild = VARIANT_FALSE;
477 return S_FALSE;
480 *hasChild = VARIANT_TRUE;
481 return S_OK;
484 static HRESULT WINAPI xmlnode_get_ownerDocument(
485 IXMLDOMNode *iface,
486 IXMLDOMDocument** DOMDocument)
488 xmlnode *This = impl_from_IXMLDOMNode( iface );
490 TRACE("(%p)->(%p)\n", This, DOMDocument);
492 return DOMDocument_create_from_xmldoc(This->node->doc, (IXMLDOMDocument3**)DOMDocument);
495 HRESULT node_clone(xmlnode *This, VARIANT_BOOL deep, IXMLDOMNode **cloneNode)
497 IXMLDOMNode *node;
498 xmlNodePtr clone;
500 if(!cloneNode) return E_INVALIDARG;
502 clone = xmlCopyNode(This->node, deep ? 1 : 2);
503 if (clone)
505 clone->doc = This->node->doc;
506 xmldoc_add_orphan(clone->doc, clone);
508 node = create_node(clone);
509 if (!node)
511 ERR("Copy failed\n");
512 return E_FAIL;
515 *cloneNode = node;
517 else
519 ERR("Copy failed\n");
520 return E_FAIL;
523 return S_OK;
526 static inline xmlChar* trim_whitespace(xmlChar* str)
528 xmlChar* ret = str;
529 int len;
531 if (!str)
532 return NULL;
534 while (*ret && isspace(*ret))
535 ++ret;
536 len = xmlStrlen(ret);
537 while (isspace(ret[len-1]))
538 --len;
540 ret = xmlStrndup(ret, len);
541 xmlFree(str);
542 return ret;
545 static xmlChar* do_get_text(xmlNodePtr node)
547 xmlNodePtr child;
548 xmlChar* str;
549 BOOL preserving = is_preserving_whitespace(node);
551 if (!node->children)
553 str = xmlNodeGetContent(node);
555 else
557 xmlElementType prev_type = XML_TEXT_NODE;
558 xmlChar* tmp;
559 str = xmlStrdup(BAD_CAST "");
560 for (child = node->children; child != NULL; child = child->next)
562 switch (child->type)
564 case XML_ELEMENT_NODE:
565 tmp = do_get_text(child);
566 break;
567 case XML_TEXT_NODE:
568 case XML_CDATA_SECTION_NODE:
569 case XML_ENTITY_REF_NODE:
570 case XML_ENTITY_NODE:
571 tmp = xmlNodeGetContent(child);
572 break;
573 default:
574 tmp = NULL;
575 break;
578 if (tmp)
580 if (*tmp)
582 if (prev_type == XML_ELEMENT_NODE && child->type == XML_ELEMENT_NODE)
583 str = xmlStrcat(str, BAD_CAST " ");
584 str = xmlStrcat(str, tmp);
585 prev_type = child->type;
587 xmlFree(tmp);
592 switch (node->type)
594 case XML_ELEMENT_NODE:
595 case XML_TEXT_NODE:
596 case XML_ENTITY_REF_NODE:
597 case XML_ENTITY_NODE:
598 case XML_DOCUMENT_NODE:
599 case XML_DOCUMENT_FRAG_NODE:
600 if (!preserving)
601 str = trim_whitespace(str);
602 break;
603 default:
604 break;
607 return str;
610 static HRESULT WINAPI xmlnode_get_text(
611 IXMLDOMNode *iface,
612 BSTR* text)
614 xmlnode *This = impl_from_IXMLDOMNode( iface );
615 BSTR str = NULL;
616 xmlChar *pContent;
618 TRACE("(%p, type %d)->(%p)\n", This, This->node->type, text);
620 if ( !text )
621 return E_INVALIDARG;
623 pContent = do_get_text((xmlNodePtr)This->node);
624 if(pContent)
626 str = bstr_from_xmlChar(pContent);
627 xmlFree(pContent);
630 /* Always return a string. */
631 if (!str) str = SysAllocStringLen( NULL, 0 );
633 TRACE("%p %s\n", This, debugstr_w(str) );
634 *text = str;
636 return S_OK;
639 HRESULT node_put_text(xmlnode *This, BSTR text)
641 xmlChar *str, *str2;
643 TRACE("(%p)->(%s)\n", This, debugstr_w(text));
645 str = xmlChar_from_wchar(text);
647 /* Escape the string. */
648 str2 = xmlEncodeEntitiesReentrant(This->node->doc, str);
649 heap_free(str);
651 xmlNodeSetContent(This->node, str2);
652 xmlFree(str2);
654 return S_OK;
657 static inline BYTE hex_to_byte(xmlChar c)
659 if(c <= '9') return c-'0';
660 if(c <= 'F') return c-'A'+10;
661 return c-'a'+10;
664 static inline BYTE base64_to_byte(xmlChar c)
666 if(c == '+') return 62;
667 if(c == '/') return 63;
668 if(c <= '9') return c-'0'+52;
669 if(c <= 'Z') return c-'A';
670 return c-'a'+26;
673 static inline HRESULT VARIANT_from_xmlChar(xmlChar *str, VARIANT *v, BSTR type)
675 if(!type || !lstrcmpiW(type, szString) ||
676 !lstrcmpiW(type, szNumber) || !lstrcmpiW(type, szUUID))
678 V_VT(v) = VT_BSTR;
679 V_BSTR(v) = bstr_from_xmlChar(str);
681 if(!V_BSTR(v))
682 return E_OUTOFMEMORY;
684 else if(!lstrcmpiW(type, szDateTime) || !lstrcmpiW(type, szDateTimeTZ) ||
685 !lstrcmpiW(type, szDate) || !lstrcmpiW(type, szTime) ||
686 !lstrcmpiW(type, szTimeTZ))
688 VARIANT src;
689 WCHAR *p, *e;
690 SYSTEMTIME st;
691 DOUBLE date = 0.0;
693 st.wYear = 1899;
694 st.wMonth = 12;
695 st.wDay = 30;
696 st.wDayOfWeek = st.wHour = st.wMinute = st.wSecond = st.wMilliseconds = 0;
698 V_VT(&src) = VT_BSTR;
699 V_BSTR(&src) = bstr_from_xmlChar(str);
701 if(!V_BSTR(&src))
702 return E_OUTOFMEMORY;
704 p = V_BSTR(&src);
705 e = p + SysStringLen(V_BSTR(&src));
707 if(p+4<e && *(p+4)=='-') /* parse date (yyyy-mm-dd) */
709 st.wYear = atoiW(p);
710 st.wMonth = atoiW(p+5);
711 st.wDay = atoiW(p+8);
712 p += 10;
714 if(*p == 'T') p++;
717 if(p+2<e && *(p+2)==':') /* parse time (hh:mm:ss.?) */
719 st.wHour = atoiW(p);
720 st.wMinute = atoiW(p+3);
721 st.wSecond = atoiW(p+6);
722 p += 8;
724 if(*p == '.')
726 p++;
727 while(isdigitW(*p)) p++;
731 SystemTimeToVariantTime(&st, &date);
732 V_VT(v) = VT_DATE;
733 V_DATE(v) = date;
735 if(*p == '+') /* parse timezone offset (+hh:mm) */
736 V_DATE(v) += (DOUBLE)atoiW(p+1)/24 + (DOUBLE)atoiW(p+4)/1440;
737 else if(*p == '-') /* parse timezone offset (-hh:mm) */
738 V_DATE(v) -= (DOUBLE)atoiW(p+1)/24 + (DOUBLE)atoiW(p+4)/1440;
740 VariantClear(&src);
742 else if(!lstrcmpiW(type, szBinHex))
744 SAFEARRAYBOUND sab;
745 int i, len;
747 len = xmlStrlen(str)/2;
748 sab.lLbound = 0;
749 sab.cElements = len;
751 V_VT(v) = (VT_ARRAY|VT_UI1);
752 V_ARRAY(v) = SafeArrayCreate(VT_UI1, 1, &sab);
754 if(!V_ARRAY(v))
755 return E_OUTOFMEMORY;
757 for(i=0; i<len; i++)
758 ((BYTE*)V_ARRAY(v)->pvData)[i] = (hex_to_byte(str[2*i])<<4)
759 + hex_to_byte(str[2*i+1]);
761 else if(!lstrcmpiW(type, szBinBase64))
763 SAFEARRAYBOUND sab;
764 int i, len;
766 len = xmlStrlen(str);
767 if(str[len-2] == '=') i = 2;
768 else if(str[len-1] == '=') i = 1;
769 else i = 0;
771 sab.lLbound = 0;
772 sab.cElements = len/4*3-i;
774 V_VT(v) = (VT_ARRAY|VT_UI1);
775 V_ARRAY(v) = SafeArrayCreate(VT_UI1, 1, &sab);
777 if(!V_ARRAY(v))
778 return E_OUTOFMEMORY;
780 for(i=0; i<len/4; i++)
782 ((BYTE*)V_ARRAY(v)->pvData)[3*i] = (base64_to_byte(str[4*i])<<2)
783 + (base64_to_byte(str[4*i+1])>>4);
784 if(3*i+1 < sab.cElements)
785 ((BYTE*)V_ARRAY(v)->pvData)[3*i+1] = (base64_to_byte(str[4*i+1])<<4)
786 + (base64_to_byte(str[4*i+2])>>2);
787 if(3*i+2 < sab.cElements)
788 ((BYTE*)V_ARRAY(v)->pvData)[3*i+2] = (base64_to_byte(str[4*i+2])<<6)
789 + base64_to_byte(str[4*i+3]);
792 else
794 VARIANT src;
795 HRESULT hres;
797 if(!lstrcmpiW(type, szInt) || !lstrcmpiW(type, szI4))
798 V_VT(v) = VT_I4;
799 else if(!lstrcmpiW(type, szFixed))
800 V_VT(v) = VT_CY;
801 else if(!lstrcmpiW(type, szBoolean))
802 V_VT(v) = VT_BOOL;
803 else if(!lstrcmpiW(type, szI1))
804 V_VT(v) = VT_I1;
805 else if(!lstrcmpiW(type, szI2))
806 V_VT(v) = VT_I2;
807 else if(!lstrcmpiW(type, szIU1))
808 V_VT(v) = VT_UI1;
809 else if(!lstrcmpiW(type, szIU2))
810 V_VT(v) = VT_UI2;
811 else if(!lstrcmpiW(type, szIU4))
812 V_VT(v) = VT_UI4;
813 else if(!lstrcmpiW(type, szR4))
814 V_VT(v) = VT_R4;
815 else if(!lstrcmpiW(type, szR8) || !lstrcmpiW(type, szFloat))
816 V_VT(v) = VT_R8;
817 else
819 FIXME("Type handling not yet implemented\n");
820 V_VT(v) = VT_BSTR;
823 V_VT(&src) = VT_BSTR;
824 V_BSTR(&src) = bstr_from_xmlChar(str);
826 if(!V_BSTR(&src))
827 return E_OUTOFMEMORY;
829 hres = VariantChangeTypeEx(v, &src, MAKELCID(MAKELANGID(
830 LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT),0, V_VT(v));
831 VariantClear(&src);
832 return hres;
835 return S_OK;
838 static HRESULT WINAPI xmlnode_get_nodeTypedValue(
839 IXMLDOMNode *iface,
840 VARIANT* typedValue)
842 xmlnode *This = impl_from_IXMLDOMNode( iface );
843 VARIANT type;
844 xmlChar *content;
845 HRESULT hres = S_FALSE;
847 TRACE("(%p)->(%p)\n", This, typedValue);
849 if(!typedValue)
850 return E_INVALIDARG;
852 V_VT(typedValue) = VT_NULL;
854 if(This->node->type == XML_ELEMENT_NODE ||
855 This->node->type == XML_TEXT_NODE ||
856 This->node->type == XML_ENTITY_REF_NODE)
857 hres = IXMLDOMNode_get_dataType(This->iface, &type);
859 if(hres != S_OK && This->node->type != XML_ELEMENT_NODE)
860 return IXMLDOMNode_get_nodeValue(This->iface, typedValue);
862 content = xmlNodeGetContent(This->node);
863 hres = VARIANT_from_xmlChar(content, typedValue,
864 hres==S_OK ? V_BSTR(&type) : NULL);
865 xmlFree(content);
866 VariantClear(&type);
868 return hres;
871 static HRESULT WINAPI xmlnode_put_nodeTypedValue(
872 IXMLDOMNode *iface,
873 VARIANT typedValue)
875 xmlnode *This = impl_from_IXMLDOMNode( iface );
876 FIXME("%p\n", This);
877 return E_NOTIMPL;
880 static HRESULT WINAPI xmlnode_put_dataType(
881 IXMLDOMNode *iface,
882 BSTR dataTypeName)
884 xmlnode *This = impl_from_IXMLDOMNode( iface );
885 HRESULT hr = E_FAIL;
887 TRACE("(%p)->(%s)\n", This, debugstr_w(dataTypeName));
889 if(dataTypeName == NULL)
890 return E_INVALIDARG;
892 /* An example of this is. The Text in the node needs to be a 0 or 1 for a boolean type.
893 This applies to changing types (string->bool) or setting a new one
895 FIXME("Need to Validate the data before allowing a type to be set.\n");
897 /* Check all supported types. */
898 if(lstrcmpiW(dataTypeName,szString) == 0 ||
899 lstrcmpiW(dataTypeName,szNumber) == 0 ||
900 lstrcmpiW(dataTypeName,szUUID) == 0 ||
901 lstrcmpiW(dataTypeName,szInt) == 0 ||
902 lstrcmpiW(dataTypeName,szI4) == 0 ||
903 lstrcmpiW(dataTypeName,szFixed) == 0 ||
904 lstrcmpiW(dataTypeName,szBoolean) == 0 ||
905 lstrcmpiW(dataTypeName,szDateTime) == 0 ||
906 lstrcmpiW(dataTypeName,szDateTimeTZ) == 0 ||
907 lstrcmpiW(dataTypeName,szDate) == 0 ||
908 lstrcmpiW(dataTypeName,szTime) == 0 ||
909 lstrcmpiW(dataTypeName,szTimeTZ) == 0 ||
910 lstrcmpiW(dataTypeName,szI1) == 0 ||
911 lstrcmpiW(dataTypeName,szI2) == 0 ||
912 lstrcmpiW(dataTypeName,szIU1) == 0 ||
913 lstrcmpiW(dataTypeName,szIU2) == 0 ||
914 lstrcmpiW(dataTypeName,szIU4) == 0 ||
915 lstrcmpiW(dataTypeName,szR4) == 0 ||
916 lstrcmpiW(dataTypeName,szR8) == 0 ||
917 lstrcmpiW(dataTypeName,szFloat) == 0 ||
918 lstrcmpiW(dataTypeName,szBinHex) == 0 ||
919 lstrcmpiW(dataTypeName,szBinBase64) == 0)
921 xmlChar* str = xmlChar_from_wchar(dataTypeName);
922 xmlAttrPtr attr;
924 if (!str) return E_OUTOFMEMORY;
926 attr = xmlHasNsProp(This->node, (const xmlChar*)"dt",
927 (const xmlChar*)"urn:schemas-microsoft-com:datatypes");
928 if (attr)
930 attr = xmlSetNsProp(This->node, attr->ns, (const xmlChar*)"dt", str);
931 hr = S_OK;
933 else
935 xmlNsPtr ns = xmlNewNs(This->node, (const xmlChar*)"urn:schemas-microsoft-com:datatypes", (const xmlChar*)"dt");
936 if (ns)
938 attr = xmlNewNsProp(This->node, ns, (const xmlChar*)"dt", str);
939 if (attr)
941 xmlAddChild(This->node, (xmlNodePtr)attr);
942 hr = S_OK;
944 else
945 ERR("Failed to create Attribute\n");
947 else
948 ERR("Failed to create Namespace\n");
950 heap_free( str );
953 return hr;
956 BSTR EnsureCorrectEOL(BSTR sInput)
958 int nNum = 0;
959 BSTR sNew;
960 int nLen;
961 int i;
963 nLen = SysStringLen(sInput);
964 /* Count line endings */
965 for(i=0; i < nLen; i++)
967 if(sInput[i] == '\n')
968 nNum++;
971 TRACE("len=%d, num=%d\n", nLen, nNum);
973 /* Add linefeed as needed */
974 if(nNum > 0)
976 int nPlace = 0;
977 sNew = SysAllocStringLen(NULL, nLen + nNum+1);
978 for(i=0; i < nLen; i++)
980 if(sInput[i] == '\n')
982 sNew[i+nPlace] = '\r';
983 nPlace++;
985 sNew[i+nPlace] = sInput[i];
988 SysFreeString(sInput);
990 else
992 sNew = sInput;
995 TRACE("len %d\n", SysStringLen(sNew));
997 return sNew;
1000 /* Removes encoding information and last character (nullbyte) */
1001 static BSTR EnsureNoEncoding(BSTR sInput)
1003 static const WCHAR wszEncoding[] = {'e','n','c','o','d','i','n','g','='};
1004 BSTR sNew;
1005 WCHAR *pBeg, *pEnd;
1007 pBeg = sInput;
1008 while(*pBeg != '\n' && memcmp(pBeg, wszEncoding, sizeof(wszEncoding)))
1009 pBeg++;
1011 if(*pBeg == '\n')
1013 SysReAllocStringLen(&sInput, sInput, SysStringLen(sInput)-1);
1014 return sInput;
1016 pBeg--;
1018 pEnd = pBeg + sizeof(wszEncoding)/sizeof(WCHAR) + 2;
1019 while(*pEnd != '\"') pEnd++;
1020 pEnd++;
1022 sNew = SysAllocStringLen(NULL,
1023 pBeg-sInput + SysStringLen(sInput)-(pEnd-sInput)-1);
1024 memcpy(sNew, sInput, (pBeg-sInput)*sizeof(WCHAR));
1025 memcpy(&sNew[pBeg-sInput], pEnd, (SysStringLen(sInput)-(pEnd-sInput)-1)*sizeof(WCHAR));
1027 SysFreeString(sInput);
1028 return sNew;
1032 * We are trying to replicate the same behaviour as msxml by converting
1033 * line endings to \r\n and using indents as \t. The problem is that msxml
1034 * only formats nodes that have a line ending. Using libxml we cannot
1035 * reproduce behaviour exactly.
1038 HRESULT node_get_xml(xmlnode *This, BOOL ensure_eol, BOOL ensure_no_encoding, BSTR *ret)
1040 xmlBufferPtr xml_buf;
1041 xmlNodePtr xmldecl;
1042 int size;
1044 if(!ret)
1045 return E_INVALIDARG;
1047 *ret = NULL;
1049 xml_buf = xmlBufferCreate();
1050 if(!xml_buf)
1051 return E_OUTOFMEMORY;
1053 xmldecl = xmldoc_unlink_xmldecl( This->node->doc );
1055 size = xmlNodeDump(xml_buf, This->node->doc, This->node, 0, 1);
1056 if(size > 0) {
1057 const xmlChar *buf_content;
1058 BSTR content;
1060 /* Attribute Nodes return a space in front of their name */
1061 buf_content = xmlBufferContent(xml_buf);
1063 content = bstr_from_xmlChar(buf_content + (buf_content[0] == ' ' ? 1 : 0));
1064 if(ensure_eol)
1065 content = EnsureCorrectEOL(content);
1066 if(ensure_no_encoding)
1067 content = EnsureNoEncoding(content);
1069 *ret = content;
1070 }else {
1071 *ret = SysAllocStringLen(NULL, 0);
1074 xmlBufferFree(xml_buf);
1075 xmldoc_link_xmldecl( This->node->doc, xmldecl );
1076 return *ret ? S_OK : E_OUTOFMEMORY;
1079 static HRESULT WINAPI xmlnode_transformNode(
1080 IXMLDOMNode *iface,
1081 IXMLDOMNode* styleSheet,
1082 BSTR* xmlString)
1084 #ifdef SONAME_LIBXSLT
1085 xmlnode *This = impl_from_IXMLDOMNode( iface );
1086 xmlnode *pStyleSheet = NULL;
1087 xsltStylesheetPtr xsltSS = NULL;
1088 xmlDocPtr result = NULL;
1090 TRACE("(%p)->(%p %p)\n", This, styleSheet, xmlString);
1092 if (!libxslt_handle)
1093 return E_NOTIMPL;
1094 if(!styleSheet || !xmlString)
1095 return E_INVALIDARG;
1097 *xmlString = NULL;
1099 pStyleSheet = get_node_obj(styleSheet);
1100 if(!pStyleSheet) {
1101 FIXME("styleSheet is not our xmlnode implementation\n");
1102 return E_FAIL;
1105 xsltSS = pxsltParseStylesheetDoc( pStyleSheet->node->doc);
1106 if(xsltSS)
1108 result = pxsltApplyStylesheet(xsltSS, This->node->doc, NULL);
1109 if(result)
1111 const xmlChar *pContent;
1113 if(result->type == XML_HTML_DOCUMENT_NODE)
1115 xmlOutputBufferPtr pOutput = xmlAllocOutputBuffer(NULL);
1116 if(pOutput)
1118 htmlDocContentDumpOutput(pOutput, result->doc, NULL);
1119 pContent = xmlBufferContent(pOutput->buffer);
1120 *xmlString = bstr_from_xmlChar(pContent);
1121 xmlOutputBufferClose(pOutput);
1124 else
1126 xmlBufferPtr pXmlBuf;
1127 int nSize;
1129 pXmlBuf = xmlBufferCreate();
1130 if(pXmlBuf)
1132 nSize = xmlNodeDump(pXmlBuf, NULL, (xmlNodePtr)result, 0, 0);
1133 if(nSize > 0)
1135 pContent = xmlBufferContent(pXmlBuf);
1136 *xmlString = bstr_from_xmlChar(pContent);
1138 xmlBufferFree(pXmlBuf);
1141 xmlFreeDoc(result);
1143 /* libxslt "helpfully" frees the XML document the stylesheet was
1144 generated from, too */
1145 xsltSS->doc = NULL;
1146 pxsltFreeStylesheet(xsltSS);
1149 if(*xmlString == NULL)
1150 *xmlString = SysAllocStringLen(NULL, 0);
1152 return S_OK;
1153 #else
1154 FIXME("libxslt headers were not found at compile time\n");
1155 return E_NOTIMPL;
1156 #endif
1159 static HRESULT WINAPI xmlnode_selectNodes(
1160 IXMLDOMNode *iface,
1161 BSTR queryString,
1162 IXMLDOMNodeList** resultList)
1164 xmlnode *This = impl_from_IXMLDOMNode( iface );
1166 TRACE("(%p)->(%s %p)\n", This, debugstr_w(queryString), resultList );
1168 if (!queryString || !resultList) return E_INVALIDARG;
1170 return queryresult_create( This->node, queryString, resultList );
1173 static HRESULT WINAPI xmlnode_selectSingleNode(
1174 IXMLDOMNode *iface,
1175 BSTR queryString,
1176 IXMLDOMNode** resultNode)
1178 xmlnode *This = impl_from_IXMLDOMNode( iface );
1179 IXMLDOMNodeList *list;
1180 HRESULT r;
1182 TRACE("(%p)->(%s %p)\n", This, debugstr_w(queryString), resultNode );
1184 r = IXMLDOMNode_selectNodes(This->iface, queryString, &list);
1185 if(r == S_OK)
1187 r = IXMLDOMNodeList_nextNode(list, resultNode);
1188 IXMLDOMNodeList_Release(list);
1190 return r;
1193 static HRESULT WINAPI xmlnode_get_namespaceURI(
1194 IXMLDOMNode *iface,
1195 BSTR* namespaceURI)
1197 xmlnode *This = impl_from_IXMLDOMNode( iface );
1198 xmlNsPtr *ns;
1200 TRACE("(%p)->(%p)\n", This, namespaceURI );
1202 if(!namespaceURI)
1203 return E_INVALIDARG;
1205 *namespaceURI = NULL;
1207 if ((ns = xmlGetNsList(This->node->doc, This->node)))
1209 if (ns[0]->href) *namespaceURI = bstr_from_xmlChar( ns[0]->href );
1210 xmlFree(ns);
1213 TRACE("uri: %s\n", debugstr_w(*namespaceURI));
1215 return *namespaceURI ? S_OK : S_FALSE;
1218 HRESULT node_get_prefix(xmlnode *This, BSTR *prefix)
1220 xmlNsPtr *ns;
1222 if (!prefix) return E_INVALIDARG;
1224 *prefix = NULL;
1226 if ((ns = xmlGetNsList(This->node->doc, This->node)))
1228 if (ns[0]->prefix) *prefix = bstr_from_xmlChar( ns[0]->prefix );
1229 xmlFree(ns);
1232 TRACE("prefix: %s\n", debugstr_w(*prefix));
1234 return *prefix ? S_OK : S_FALSE;
1237 HRESULT node_get_base_name(xmlnode *This, BSTR *name)
1239 if (!name) return E_INVALIDARG;
1241 *name = bstr_from_xmlChar(This->node->name);
1242 if (!*name) return E_OUTOFMEMORY;
1244 TRACE("returning %s\n", debugstr_w(*name));
1246 return S_OK;
1249 static HRESULT WINAPI xmlnode_transformNodeToObject(
1250 IXMLDOMNode *iface,
1251 IXMLDOMNode* stylesheet,
1252 VARIANT outputObject)
1254 xmlnode *This = impl_from_IXMLDOMNode( iface );
1255 FIXME("(%p)->(%p)\n", This, stylesheet);
1256 return E_NOTIMPL;
1259 static const struct IXMLDOMNodeVtbl xmlnode_vtbl =
1261 NULL,
1262 NULL,
1263 NULL,
1264 NULL,
1265 NULL,
1266 NULL,
1267 NULL,
1268 NULL,
1269 NULL,
1270 NULL,
1271 NULL,
1272 NULL,
1273 NULL,
1274 NULL,
1275 NULL,
1276 NULL,
1277 NULL,
1278 NULL,
1279 NULL,
1280 NULL,
1281 xmlnode_removeChild,
1282 xmlnode_appendChild,
1283 xmlnode_hasChildNodes,
1284 xmlnode_get_ownerDocument,
1285 NULL,
1286 NULL,
1287 xmlnode_get_text,
1288 NULL,
1289 NULL,
1290 NULL,
1291 xmlnode_get_nodeTypedValue,
1292 xmlnode_put_nodeTypedValue,
1293 NULL,
1294 xmlnode_put_dataType,
1295 NULL,
1296 xmlnode_transformNode,
1297 xmlnode_selectNodes,
1298 xmlnode_selectSingleNode,
1299 NULL,
1300 xmlnode_get_namespaceURI,
1301 NULL,
1302 NULL,
1303 xmlnode_transformNodeToObject,
1306 void destroy_xmlnode(xmlnode *This)
1308 if(This->node)
1309 xmldoc_release(This->node->doc);
1312 void init_xmlnode(xmlnode *This, xmlNodePtr node, IXMLDOMNode *node_iface, dispex_static_data_t *dispex_data)
1314 if(node)
1315 xmldoc_add_ref( node->doc );
1317 This->lpVtbl = &xmlnode_vtbl;
1318 This->node = node;
1319 This->iface = node_iface;
1321 if(dispex_data)
1322 init_dispex(&This->dispex, (IUnknown*)This->iface, dispex_data);
1323 else
1324 This->dispex.outer = NULL;
1327 typedef struct {
1328 xmlnode node;
1329 const IXMLDOMNodeVtbl *lpVtbl;
1330 LONG ref;
1331 } unknode;
1333 static inline unknode *impl_from_unkIXMLDOMNode(IXMLDOMNode *iface)
1335 return (unknode *)((char*)iface - FIELD_OFFSET(unknode, lpVtbl));
1338 static HRESULT WINAPI unknode_QueryInterface(
1339 IXMLDOMNode *iface,
1340 REFIID riid,
1341 void** ppvObject )
1343 unknode *This = impl_from_unkIXMLDOMNode( iface );
1345 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
1347 if (IsEqualGUID(riid, &IID_IUnknown)) {
1348 *ppvObject = iface;
1349 }else if (IsEqualGUID( riid, &IID_IDispatch) ||
1350 IsEqualGUID( riid, &IID_IXMLDOMNode)) {
1351 *ppvObject = &This->lpVtbl;
1352 }else if(node_query_interface(&This->node, riid, ppvObject)) {
1353 return *ppvObject ? S_OK : E_NOINTERFACE;
1354 }else {
1355 FIXME("interface %s not implemented\n", debugstr_guid(riid));
1356 *ppvObject = NULL;
1357 return E_NOINTERFACE;
1360 IUnknown_AddRef((IUnknown*)*ppvObject);
1361 return S_OK;
1364 static ULONG WINAPI unknode_AddRef(
1365 IXMLDOMNode *iface )
1367 unknode *This = impl_from_unkIXMLDOMNode( iface );
1369 return InterlockedIncrement(&This->ref);
1372 static ULONG WINAPI unknode_Release(
1373 IXMLDOMNode *iface )
1375 unknode *This = impl_from_unkIXMLDOMNode( iface );
1376 LONG ref;
1378 ref = InterlockedDecrement( &This->ref );
1379 if(!ref) {
1380 destroy_xmlnode(&This->node);
1381 heap_free(This);
1384 return ref;
1387 static HRESULT WINAPI unknode_GetTypeInfoCount(
1388 IXMLDOMNode *iface,
1389 UINT* pctinfo )
1391 unknode *This = impl_from_unkIXMLDOMNode( iface );
1393 TRACE("(%p)->(%p)\n", This, pctinfo);
1395 *pctinfo = 1;
1397 return S_OK;
1400 static HRESULT WINAPI unknode_GetTypeInfo(
1401 IXMLDOMNode *iface,
1402 UINT iTInfo,
1403 LCID lcid,
1404 ITypeInfo** ppTInfo )
1406 unknode *This = impl_from_unkIXMLDOMNode( iface );
1407 HRESULT hr;
1409 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1411 hr = get_typeinfo(IXMLDOMNode_tid, ppTInfo);
1413 return hr;
1416 static HRESULT WINAPI unknode_GetIDsOfNames(
1417 IXMLDOMNode *iface,
1418 REFIID riid,
1419 LPOLESTR* rgszNames,
1420 UINT cNames,
1421 LCID lcid,
1422 DISPID* rgDispId )
1424 unknode *This = impl_from_unkIXMLDOMNode( iface );
1426 ITypeInfo *typeinfo;
1427 HRESULT hr;
1429 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1430 lcid, rgDispId);
1432 if(!rgszNames || cNames == 0 || !rgDispId)
1433 return E_INVALIDARG;
1435 hr = get_typeinfo(IXMLDOMNode_tid, &typeinfo);
1436 if(SUCCEEDED(hr))
1438 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1439 ITypeInfo_Release(typeinfo);
1442 return hr;
1445 static HRESULT WINAPI unknode_Invoke(
1446 IXMLDOMNode *iface,
1447 DISPID dispIdMember,
1448 REFIID riid,
1449 LCID lcid,
1450 WORD wFlags,
1451 DISPPARAMS* pDispParams,
1452 VARIANT* pVarResult,
1453 EXCEPINFO* pExcepInfo,
1454 UINT* puArgErr )
1456 unknode *This = impl_from_unkIXMLDOMNode( iface );
1457 ITypeInfo *typeinfo;
1458 HRESULT hr;
1460 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1461 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1463 hr = get_typeinfo(IXMLDOMNode_tid, &typeinfo);
1464 if(SUCCEEDED(hr))
1466 hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
1467 pVarResult, pExcepInfo, puArgErr);
1468 ITypeInfo_Release(typeinfo);
1471 return hr;
1474 static HRESULT WINAPI unknode_get_nodeName(
1475 IXMLDOMNode *iface,
1476 BSTR* p )
1478 unknode *This = impl_from_unkIXMLDOMNode( iface );
1480 FIXME("(%p)->(%p)\n", This, p);
1482 return node_get_nodeName(&This->node, p);
1485 static HRESULT WINAPI unknode_get_nodeValue(
1486 IXMLDOMNode *iface,
1487 VARIANT* value)
1489 unknode *This = impl_from_unkIXMLDOMNode( iface );
1491 FIXME("(%p)->(%p)\n", This, value);
1493 if(!value)
1494 return E_INVALIDARG;
1496 V_VT(value) = VT_NULL;
1497 return S_FALSE;
1500 static HRESULT WINAPI unknode_put_nodeValue(
1501 IXMLDOMNode *iface,
1502 VARIANT value)
1504 unknode *This = impl_from_unkIXMLDOMNode( iface );
1505 FIXME("(%p)->(v%d)\n", This, V_VT(&value));
1506 return E_FAIL;
1509 static HRESULT WINAPI unknode_get_nodeType(
1510 IXMLDOMNode *iface,
1511 DOMNodeType* domNodeType )
1513 unknode *This = impl_from_unkIXMLDOMNode( iface );
1515 FIXME("(%p)->(%p)\n", This, domNodeType);
1517 *domNodeType = This->node.node->type;
1518 return S_OK;
1521 static HRESULT WINAPI unknode_get_parentNode(
1522 IXMLDOMNode *iface,
1523 IXMLDOMNode** parent )
1525 unknode *This = impl_from_unkIXMLDOMNode( iface );
1526 FIXME("(%p)->(%p)\n", This, parent);
1527 if (!parent) return E_INVALIDARG;
1528 *parent = NULL;
1529 return S_FALSE;
1532 static HRESULT WINAPI unknode_get_childNodes(
1533 IXMLDOMNode *iface,
1534 IXMLDOMNodeList** outList)
1536 unknode *This = impl_from_unkIXMLDOMNode( iface );
1538 TRACE("(%p)->(%p)\n", This, outList);
1540 return node_get_child_nodes(&This->node, outList);
1543 static HRESULT WINAPI unknode_get_firstChild(
1544 IXMLDOMNode *iface,
1545 IXMLDOMNode** domNode)
1547 unknode *This = impl_from_unkIXMLDOMNode( iface );
1549 TRACE("(%p)->(%p)\n", This, domNode);
1551 return node_get_first_child(&This->node, domNode);
1554 static HRESULT WINAPI unknode_get_lastChild(
1555 IXMLDOMNode *iface,
1556 IXMLDOMNode** domNode)
1558 unknode *This = impl_from_unkIXMLDOMNode( iface );
1560 TRACE("(%p)->(%p)\n", This, domNode);
1562 return node_get_last_child(&This->node, domNode);
1565 static HRESULT WINAPI unknode_get_previousSibling(
1566 IXMLDOMNode *iface,
1567 IXMLDOMNode** domNode)
1569 unknode *This = impl_from_unkIXMLDOMNode( iface );
1571 TRACE("(%p)->(%p)\n", This, domNode);
1573 return node_get_previous_sibling(&This->node, domNode);
1576 static HRESULT WINAPI unknode_get_nextSibling(
1577 IXMLDOMNode *iface,
1578 IXMLDOMNode** domNode)
1580 unknode *This = impl_from_unkIXMLDOMNode( iface );
1582 TRACE("(%p)->(%p)\n", This, domNode);
1584 return node_get_next_sibling(&This->node, domNode);
1587 static HRESULT WINAPI unknode_get_attributes(
1588 IXMLDOMNode *iface,
1589 IXMLDOMNamedNodeMap** attributeMap)
1591 unknode *This = impl_from_unkIXMLDOMNode( iface );
1593 FIXME("(%p)->(%p)\n", This, attributeMap);
1595 return return_null_ptr((void**)attributeMap);
1598 static HRESULT WINAPI unknode_insertBefore(
1599 IXMLDOMNode *iface,
1600 IXMLDOMNode* newNode, VARIANT refChild,
1601 IXMLDOMNode** outOldNode)
1603 unknode *This = impl_from_unkIXMLDOMNode( iface );
1605 FIXME("(%p)->(%p x%d %p)\n", This, newNode, V_VT(&refChild), outOldNode);
1607 return node_insert_before(&This->node, newNode, &refChild, outOldNode);
1610 static HRESULT WINAPI unknode_replaceChild(
1611 IXMLDOMNode *iface,
1612 IXMLDOMNode* newNode,
1613 IXMLDOMNode* oldNode,
1614 IXMLDOMNode** outOldNode)
1616 unknode *This = impl_from_unkIXMLDOMNode( iface );
1618 FIXME("(%p)->(%p %p %p)\n", This, newNode, oldNode, outOldNode);
1620 return node_replace_child(&This->node, newNode, oldNode, outOldNode);
1623 static HRESULT WINAPI unknode_removeChild(
1624 IXMLDOMNode *iface,
1625 IXMLDOMNode* domNode, IXMLDOMNode** oldNode)
1627 unknode *This = impl_from_unkIXMLDOMNode( iface );
1628 return IXMLDOMNode_removeChild( IXMLDOMNode_from_impl(&This->node), domNode, oldNode );
1631 static HRESULT WINAPI unknode_appendChild(
1632 IXMLDOMNode *iface,
1633 IXMLDOMNode* newNode, IXMLDOMNode** outNewNode)
1635 unknode *This = impl_from_unkIXMLDOMNode( iface );
1636 return IXMLDOMNode_appendChild( IXMLDOMNode_from_impl(&This->node), newNode, outNewNode );
1639 static HRESULT WINAPI unknode_hasChildNodes(
1640 IXMLDOMNode *iface,
1641 VARIANT_BOOL* pbool)
1643 unknode *This = impl_from_unkIXMLDOMNode( iface );
1644 return IXMLDOMNode_hasChildNodes( IXMLDOMNode_from_impl(&This->node), pbool );
1647 static HRESULT WINAPI unknode_get_ownerDocument(
1648 IXMLDOMNode *iface,
1649 IXMLDOMDocument** domDocument)
1651 unknode *This = impl_from_unkIXMLDOMNode( iface );
1652 return IXMLDOMNode_get_ownerDocument( IXMLDOMNode_from_impl(&This->node), domDocument );
1655 static HRESULT WINAPI unknode_cloneNode(
1656 IXMLDOMNode *iface,
1657 VARIANT_BOOL pbool, IXMLDOMNode** outNode)
1659 unknode *This = impl_from_unkIXMLDOMNode( iface );
1660 return IXMLDOMNode_cloneNode( IXMLDOMNode_from_impl(&This->node), pbool, outNode );
1663 static HRESULT WINAPI unknode_get_nodeTypeString(
1664 IXMLDOMNode *iface,
1665 BSTR* p)
1667 unknode *This = impl_from_unkIXMLDOMNode( iface );
1669 FIXME("(%p)->(%p)\n", This, p);
1671 return node_get_nodeName(&This->node, p);
1674 static HRESULT WINAPI unknode_get_text(
1675 IXMLDOMNode *iface,
1676 BSTR* p)
1678 unknode *This = impl_from_unkIXMLDOMNode( iface );
1679 return IXMLDOMNode_get_text( IXMLDOMNode_from_impl(&This->node), p );
1682 static HRESULT WINAPI unknode_put_text(
1683 IXMLDOMNode *iface,
1684 BSTR p)
1686 unknode *This = impl_from_unkIXMLDOMNode( iface );
1687 return IXMLDOMNode_put_text( IXMLDOMNode_from_impl(&This->node), p );
1690 static HRESULT WINAPI unknode_get_specified(
1691 IXMLDOMNode *iface,
1692 VARIANT_BOOL* isSpecified)
1694 unknode *This = impl_from_unkIXMLDOMNode( iface );
1695 FIXME("(%p)->(%p) stub!\n", This, isSpecified);
1696 *isSpecified = VARIANT_TRUE;
1697 return S_OK;
1700 static HRESULT WINAPI unknode_get_definition(
1701 IXMLDOMNode *iface,
1702 IXMLDOMNode** definitionNode)
1704 unknode *This = impl_from_unkIXMLDOMNode( iface );
1705 FIXME("(%p)->(%p)\n", This, definitionNode);
1706 return E_NOTIMPL;
1709 static HRESULT WINAPI unknode_get_nodeTypedValue(
1710 IXMLDOMNode *iface,
1711 VARIANT* var1)
1713 unknode *This = impl_from_unkIXMLDOMNode( iface );
1714 return IXMLDOMNode_get_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), var1 );
1717 static HRESULT WINAPI unknode_put_nodeTypedValue(
1718 IXMLDOMNode *iface,
1719 VARIANT var1)
1721 unknode *This = impl_from_unkIXMLDOMNode( iface );
1722 return IXMLDOMNode_put_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), var1 );
1725 static HRESULT WINAPI unknode_get_dataType(
1726 IXMLDOMNode *iface,
1727 VARIANT* var1)
1729 unknode *This = impl_from_unkIXMLDOMNode( iface );
1730 return IXMLDOMNode_get_dataType( IXMLDOMNode_from_impl(&This->node), var1 );
1733 static HRESULT WINAPI unknode_put_dataType(
1734 IXMLDOMNode *iface,
1735 BSTR p)
1737 unknode *This = impl_from_unkIXMLDOMNode( iface );
1738 return IXMLDOMNode_put_dataType( IXMLDOMNode_from_impl(&This->node), p );
1741 static HRESULT WINAPI unknode_get_xml(
1742 IXMLDOMNode *iface,
1743 BSTR* p)
1745 unknode *This = impl_from_unkIXMLDOMNode( iface );
1747 FIXME("(%p)->(%p)\n", This, p);
1749 return node_get_xml(&This->node, FALSE, FALSE, p);
1752 static HRESULT WINAPI unknode_transformNode(
1753 IXMLDOMNode *iface,
1754 IXMLDOMNode* domNode, BSTR* p)
1756 unknode *This = impl_from_unkIXMLDOMNode( iface );
1757 return IXMLDOMNode_transformNode( IXMLDOMNode_from_impl(&This->node), domNode, p );
1760 static HRESULT WINAPI unknode_selectNodes(
1761 IXMLDOMNode *iface,
1762 BSTR p, IXMLDOMNodeList** outList)
1764 unknode *This = impl_from_unkIXMLDOMNode( iface );
1765 return IXMLDOMNode_selectNodes( IXMLDOMNode_from_impl(&This->node), p, outList );
1768 static HRESULT WINAPI unknode_selectSingleNode(
1769 IXMLDOMNode *iface,
1770 BSTR p, IXMLDOMNode** outNode)
1772 unknode *This = impl_from_unkIXMLDOMNode( iface );
1773 return IXMLDOMNode_selectSingleNode( IXMLDOMNode_from_impl(&This->node), p, outNode );
1776 static HRESULT WINAPI unknode_get_parsed(
1777 IXMLDOMNode *iface,
1778 VARIANT_BOOL* isParsed)
1780 unknode *This = impl_from_unkIXMLDOMNode( iface );
1781 FIXME("(%p)->(%p) stub!\n", This, isParsed);
1782 *isParsed = VARIANT_TRUE;
1783 return S_OK;
1786 static HRESULT WINAPI unknode_get_namespaceURI(
1787 IXMLDOMNode *iface,
1788 BSTR* p)
1790 unknode *This = impl_from_unkIXMLDOMNode( iface );
1791 return IXMLDOMNode_get_namespaceURI( IXMLDOMNode_from_impl(&This->node), p );
1794 static HRESULT WINAPI unknode_get_prefix(
1795 IXMLDOMNode *iface,
1796 BSTR* p)
1798 unknode *This = impl_from_unkIXMLDOMNode( iface );
1799 return IXMLDOMNode_get_prefix( IXMLDOMNode_from_impl(&This->node), p );
1802 static HRESULT WINAPI unknode_get_baseName(
1803 IXMLDOMNode *iface,
1804 BSTR* p)
1806 unknode *This = impl_from_unkIXMLDOMNode( iface );
1807 return IXMLDOMNode_get_baseName( IXMLDOMNode_from_impl(&This->node), p );
1810 static HRESULT WINAPI unknode_transformNodeToObject(
1811 IXMLDOMNode *iface,
1812 IXMLDOMNode* domNode, VARIANT var1)
1814 unknode *This = impl_from_unkIXMLDOMNode( iface );
1815 return IXMLDOMNode_transformNodeToObject( IXMLDOMNode_from_impl(&This->node), domNode, var1 );
1818 static const struct IXMLDOMNodeVtbl unknode_vtbl =
1820 unknode_QueryInterface,
1821 unknode_AddRef,
1822 unknode_Release,
1823 unknode_GetTypeInfoCount,
1824 unknode_GetTypeInfo,
1825 unknode_GetIDsOfNames,
1826 unknode_Invoke,
1827 unknode_get_nodeName,
1828 unknode_get_nodeValue,
1829 unknode_put_nodeValue,
1830 unknode_get_nodeType,
1831 unknode_get_parentNode,
1832 unknode_get_childNodes,
1833 unknode_get_firstChild,
1834 unknode_get_lastChild,
1835 unknode_get_previousSibling,
1836 unknode_get_nextSibling,
1837 unknode_get_attributes,
1838 unknode_insertBefore,
1839 unknode_replaceChild,
1840 unknode_removeChild,
1841 unknode_appendChild,
1842 unknode_hasChildNodes,
1843 unknode_get_ownerDocument,
1844 unknode_cloneNode,
1845 unknode_get_nodeTypeString,
1846 unknode_get_text,
1847 unknode_put_text,
1848 unknode_get_specified,
1849 unknode_get_definition,
1850 unknode_get_nodeTypedValue,
1851 unknode_put_nodeTypedValue,
1852 unknode_get_dataType,
1853 unknode_put_dataType,
1854 unknode_get_xml,
1855 unknode_transformNode,
1856 unknode_selectNodes,
1857 unknode_selectSingleNode,
1858 unknode_get_parsed,
1859 unknode_get_namespaceURI,
1860 unknode_get_prefix,
1861 unknode_get_baseName,
1862 unknode_transformNodeToObject
1865 IXMLDOMNode *create_node( xmlNodePtr node )
1867 IUnknown *pUnk;
1868 IXMLDOMNode *ret;
1869 HRESULT hr;
1871 if ( !node )
1872 return NULL;
1874 TRACE("type %d\n", node->type);
1875 switch(node->type)
1877 case XML_ELEMENT_NODE:
1878 pUnk = create_element( node );
1879 break;
1880 case XML_ATTRIBUTE_NODE:
1881 pUnk = create_attribute( node );
1882 break;
1883 case XML_TEXT_NODE:
1884 pUnk = create_text( node );
1885 break;
1886 case XML_CDATA_SECTION_NODE:
1887 pUnk = create_cdata( node );
1888 break;
1889 case XML_ENTITY_REF_NODE:
1890 pUnk = create_doc_entity_ref( node );
1891 break;
1892 case XML_PI_NODE:
1893 pUnk = create_pi( node );
1894 break;
1895 case XML_COMMENT_NODE:
1896 pUnk = create_comment( node );
1897 break;
1898 case XML_DOCUMENT_NODE:
1899 pUnk = create_domdoc( node );
1900 break;
1901 case XML_DOCUMENT_FRAG_NODE:
1902 pUnk = create_doc_fragment( node );
1903 break;
1904 case XML_DTD_NODE:
1905 pUnk = create_doc_type( node );
1906 break;
1907 default: {
1908 unknode *new_node;
1910 FIXME("only creating basic node for type %d\n", node->type);
1912 new_node = heap_alloc(sizeof(unknode));
1913 if(!new_node)
1914 return NULL;
1916 new_node->lpVtbl = &unknode_vtbl;
1917 new_node->ref = 1;
1918 init_xmlnode(&new_node->node, node, (IXMLDOMNode*)&new_node->lpVtbl, NULL);
1919 pUnk = (IUnknown*)&new_node->lpVtbl;
1923 hr = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMNode, (LPVOID*)&ret);
1924 IUnknown_Release(pUnk);
1925 if(FAILED(hr)) return NULL;
1926 return ret;
1928 #endif