urlmon/tests: Use BOOL type where appropriate.
[wine/multimedia.git] / dlls / msxml3 / node.c
blobe3016a5f02358e1d65f74acdd8cde69551cbc5f9
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>
27 #ifdef HAVE_LIBXML2
28 # include <libxml/parser.h>
29 # include <libxml/xmlerror.h>
30 # include <libxml/HTMLtree.h>
31 # ifdef SONAME_LIBXSLT
32 # ifdef HAVE_LIBXSLT_PATTERN_H
33 # include <libxslt/pattern.h>
34 # endif
35 # ifdef HAVE_LIBXSLT_TRANSFORM_H
36 # include <libxslt/transform.h>
37 # endif
38 # include <libxslt/variables.h>
39 # include <libxslt/xsltutils.h>
40 # include <libxslt/xsltInternals.h>
41 # endif
42 #endif
44 #include "windef.h"
45 #include "winbase.h"
46 #include "winuser.h"
47 #include "winnls.h"
48 #include "ole2.h"
49 #include "msxml6.h"
51 #include "msxml_private.h"
53 #include "wine/debug.h"
55 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
57 #ifdef HAVE_LIBXML2
59 #ifdef SONAME_LIBXSLT
60 extern void* libxslt_handle;
61 # define MAKE_FUNCPTR(f) extern typeof(f) * p##f
62 MAKE_FUNCPTR(xsltApplyStylesheet);
63 MAKE_FUNCPTR(xsltApplyStylesheetUser);
64 MAKE_FUNCPTR(xsltCleanupGlobals);
65 MAKE_FUNCPTR(xsltFreeStylesheet);
66 MAKE_FUNCPTR(xsltFreeTransformContext);
67 MAKE_FUNCPTR(xsltNewTransformContext);
68 MAKE_FUNCPTR(xsltParseStylesheetDoc);
69 MAKE_FUNCPTR(xsltQuoteUserParams);
70 MAKE_FUNCPTR(xsltSaveResultTo);
71 # undef MAKE_FUNCPTR
72 #endif
74 static const IID IID_xmlnode = {0x4f2f4ba2,0xb822,0x11df,{0x8b,0x8a,0x68,0x50,0xdf,0xd7,0x20,0x85}};
76 xmlNodePtr xmlNodePtr_from_domnode( IXMLDOMNode *iface, xmlElementType type )
78 xmlnode *This;
80 if ( !iface )
81 return NULL;
82 This = get_node_obj( iface );
83 if ( !This || !This->node )
84 return NULL;
85 if ( type && This->node->type != type )
86 return NULL;
87 return This->node;
90 BOOL node_query_interface(xmlnode *This, REFIID riid, void **ppv)
92 if(IsEqualGUID(&IID_xmlnode, riid)) {
93 TRACE("(%p)->(IID_xmlnode %p)\n", This, ppv);
94 *ppv = This;
95 return TRUE;
98 return dispex_query_interface(&This->dispex, riid, ppv);
101 /* common ISupportErrorInfo implementation */
102 typedef struct {
103 ISupportErrorInfo ISupportErrorInfo_iface;
104 LONG ref;
106 const tid_t* iids;
107 } SupportErrorInfo;
109 static inline SupportErrorInfo *impl_from_ISupportErrorInfo(ISupportErrorInfo *iface)
111 return CONTAINING_RECORD(iface, SupportErrorInfo, ISupportErrorInfo_iface);
114 static HRESULT WINAPI SupportErrorInfo_QueryInterface(ISupportErrorInfo *iface, REFIID riid, void **obj)
116 SupportErrorInfo *This = impl_from_ISupportErrorInfo(iface);
117 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
119 *obj = NULL;
121 if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_ISupportErrorInfo)) {
122 *obj = iface;
123 ISupportErrorInfo_AddRef(iface);
124 return S_OK;
127 return E_NOINTERFACE;
130 static ULONG WINAPI SupportErrorInfo_AddRef(ISupportErrorInfo *iface)
132 SupportErrorInfo *This = impl_from_ISupportErrorInfo(iface);
133 ULONG ref = InterlockedIncrement(&This->ref);
134 TRACE("(%p)->(%d)\n", This, ref );
135 return ref;
138 static ULONG WINAPI SupportErrorInfo_Release(ISupportErrorInfo *iface)
140 SupportErrorInfo *This = impl_from_ISupportErrorInfo(iface);
141 LONG ref = InterlockedDecrement(&This->ref);
143 TRACE("(%p)->(%d)\n", This, ref);
145 if (ref == 0)
146 heap_free(This);
148 return ref;
151 static HRESULT WINAPI SupportErrorInfo_InterfaceSupportsErrorInfo(ISupportErrorInfo *iface, REFIID riid)
153 SupportErrorInfo *This = impl_from_ISupportErrorInfo(iface);
154 enum tid_t const *tid;
156 TRACE("(%p)->(%s)\n", This, debugstr_guid(riid));
158 tid = This->iids;
159 while (*tid != NULL_tid)
161 if (IsEqualGUID(riid, get_riid_from_tid(*tid)))
162 return S_OK;
163 tid++;
166 return S_FALSE;
169 static const struct ISupportErrorInfoVtbl SupportErrorInfoVtbl = {
170 SupportErrorInfo_QueryInterface,
171 SupportErrorInfo_AddRef,
172 SupportErrorInfo_Release,
173 SupportErrorInfo_InterfaceSupportsErrorInfo
176 HRESULT node_create_supporterrorinfo(enum tid_t const *iids, void **obj)
178 SupportErrorInfo *This;
180 This = heap_alloc(sizeof(*This));
181 if (!This) return E_OUTOFMEMORY;
183 This->ISupportErrorInfo_iface.lpVtbl = &SupportErrorInfoVtbl;
184 This->ref = 1;
185 This->iids = iids;
187 *obj = &This->ISupportErrorInfo_iface;
189 return S_OK;
192 xmlnode *get_node_obj(IXMLDOMNode *node)
194 xmlnode *obj = NULL;
195 HRESULT hres;
197 hres = IXMLDOMNode_QueryInterface(node, &IID_xmlnode, (void**)&obj);
198 if (!obj) WARN("node is not our IXMLDOMNode implementation\n");
199 return SUCCEEDED(hres) ? obj : NULL;
202 HRESULT node_get_nodeName(xmlnode *This, BSTR *name)
204 BSTR prefix, base;
205 HRESULT hr;
207 if (!name)
208 return E_INVALIDARG;
210 hr = node_get_base_name(This, &base);
211 if (hr != S_OK) return hr;
213 hr = node_get_prefix(This, &prefix);
214 if (hr == S_OK)
216 static const WCHAR colW = ':';
217 WCHAR *ptr;
219 /* +1 for ':' */
220 ptr = *name = SysAllocStringLen(NULL, SysStringLen(base) + SysStringLen(prefix) + 1);
221 memcpy(ptr, prefix, SysStringByteLen(prefix));
222 ptr += SysStringLen(prefix);
223 memcpy(ptr++, &colW, sizeof(WCHAR));
224 memcpy(ptr, base, SysStringByteLen(base));
226 SysFreeString(base);
227 SysFreeString(prefix);
229 else
230 *name = base;
232 return S_OK;
235 HRESULT node_get_content(xmlnode *This, VARIANT *value)
237 xmlChar *content;
239 if(!value)
240 return E_INVALIDARG;
242 content = xmlNodeGetContent(This->node);
243 V_VT(value) = VT_BSTR;
244 V_BSTR(value) = bstr_from_xmlChar( content );
245 xmlFree(content);
247 TRACE("%p returned %s\n", This, debugstr_w(V_BSTR(value)));
248 return S_OK;
251 HRESULT node_set_content(xmlnode *This, LPCWSTR value)
253 xmlChar *str;
255 TRACE("(%p)->(%s)\n", This, debugstr_w(value));
256 str = xmlchar_from_wchar(value);
257 if(!str)
258 return E_OUTOFMEMORY;
260 xmlNodeSetContent(This->node, str);
261 heap_free(str);
262 return S_OK;
265 static HRESULT node_set_content_escaped(xmlnode *This, LPCWSTR value)
267 xmlChar *str, *escaped;
269 TRACE("(%p)->(%s)\n", This, debugstr_w(value));
270 str = xmlchar_from_wchar(value);
271 if(!str)
272 return E_OUTOFMEMORY;
274 escaped = xmlEncodeSpecialChars(NULL, str);
275 if(!escaped)
277 heap_free(str);
278 return E_OUTOFMEMORY;
281 xmlNodeSetContent(This->node, escaped);
283 heap_free(str);
284 xmlFree(escaped);
286 return S_OK;
289 HRESULT node_put_value(xmlnode *This, VARIANT *value)
291 HRESULT hr;
293 if (V_VT(value) != VT_BSTR)
295 VARIANT string_value;
297 VariantInit(&string_value);
298 hr = VariantChangeType(&string_value, value, 0, VT_BSTR);
299 if(FAILED(hr)) {
300 WARN("Couldn't convert to VT_BSTR\n");
301 return hr;
304 hr = node_set_content(This, V_BSTR(&string_value));
305 VariantClear(&string_value);
307 else
308 hr = node_set_content(This, V_BSTR(value));
310 return hr;
313 HRESULT node_put_value_escaped(xmlnode *This, VARIANT *value)
315 HRESULT hr;
317 if (V_VT(value) != VT_BSTR)
319 VARIANT string_value;
321 VariantInit(&string_value);
322 hr = VariantChangeType(&string_value, value, 0, VT_BSTR);
323 if(FAILED(hr)) {
324 WARN("Couldn't convert to VT_BSTR\n");
325 return hr;
328 hr = node_set_content_escaped(This, V_BSTR(&string_value));
329 VariantClear(&string_value);
331 else
332 hr = node_set_content_escaped(This, V_BSTR(value));
334 return hr;
337 static HRESULT get_node(
338 xmlnode *This,
339 const char *name,
340 xmlNodePtr node,
341 IXMLDOMNode **out )
343 TRACE("(%p)->(%s %p %p)\n", This, name, node, out );
345 if ( !out )
346 return E_INVALIDARG;
348 /* if we don't have a doc, use our parent. */
349 if(node && !node->doc && node->parent)
350 node->doc = node->parent->doc;
352 *out = create_node( node );
353 if (!*out)
354 return S_FALSE;
355 return S_OK;
358 HRESULT node_get_parent(xmlnode *This, IXMLDOMNode **parent)
360 return get_node( This, "parent", This->node->parent, parent );
363 HRESULT node_get_child_nodes(xmlnode *This, IXMLDOMNodeList **ret)
365 if(!ret)
366 return E_INVALIDARG;
368 *ret = create_children_nodelist(This->node);
369 if(!*ret)
370 return E_OUTOFMEMORY;
372 return S_OK;
375 HRESULT node_get_first_child(xmlnode *This, IXMLDOMNode **ret)
377 return get_node(This, "firstChild", This->node->children, ret);
380 HRESULT node_get_last_child(xmlnode *This, IXMLDOMNode **ret)
382 return get_node(This, "lastChild", This->node->last, ret);
385 HRESULT node_get_previous_sibling(xmlnode *This, IXMLDOMNode **ret)
387 return get_node(This, "previous", This->node->prev, ret);
390 HRESULT node_get_next_sibling(xmlnode *This, IXMLDOMNode **ret)
392 return get_node(This, "next", This->node->next, ret);
395 static int node_get_inst_cnt(xmlNodePtr node)
397 int ret = *(LONG *)&node->_private;
398 xmlNodePtr child;
400 /* add attribute counts */
401 if (node->type == XML_ELEMENT_NODE)
403 xmlAttrPtr prop = node->properties;
405 while (prop)
407 ret += node_get_inst_cnt((xmlNodePtr)prop);
408 prop = prop->next;
412 /* add children counts */
413 child = node->children;
414 while (child)
416 ret += node_get_inst_cnt(child);
417 child = child->next;
420 return ret;
423 int xmlnode_get_inst_cnt(xmlnode *node)
425 return node_get_inst_cnt(node->node);
428 HRESULT node_insert_before(xmlnode *This, IXMLDOMNode *new_child, const VARIANT *ref_child,
429 IXMLDOMNode **ret)
431 IXMLDOMNode *before = NULL;
432 xmlnode *node_obj;
433 int refcount = 0;
434 xmlDocPtr doc;
435 HRESULT hr;
437 if(!new_child)
438 return E_INVALIDARG;
440 node_obj = get_node_obj(new_child);
441 if(!node_obj) return E_FAIL;
443 switch(V_VT(ref_child))
445 case VT_EMPTY:
446 case VT_NULL:
447 break;
449 case VT_UNKNOWN:
450 case VT_DISPATCH:
451 if (V_UNKNOWN(ref_child))
453 hr = IUnknown_QueryInterface(V_UNKNOWN(ref_child), &IID_IXMLDOMNode, (void**)&before);
454 if(FAILED(hr)) return hr;
456 break;
458 default:
459 FIXME("refChild var type %x\n", V_VT(ref_child));
460 return E_FAIL;
463 TRACE("new child %p, This->node %p\n", node_obj->node, This->node);
465 if(!node_obj->node->parent)
466 if(xmldoc_remove_orphan(node_obj->node->doc, node_obj->node) != S_OK)
467 WARN("%p is not an orphan of %p\n", node_obj->node, node_obj->node->doc);
469 refcount = xmlnode_get_inst_cnt(node_obj);
471 if(before)
473 xmlnode *before_node_obj = get_node_obj(before);
474 IXMLDOMNode_Release(before);
475 if(!before_node_obj) return E_FAIL;
477 /* unlink from current parent first */
478 if(node_obj->parent)
480 hr = IXMLDOMNode_removeChild(node_obj->parent, node_obj->iface, NULL);
481 if (hr == S_OK) xmldoc_remove_orphan(node_obj->node->doc, node_obj->node);
484 doc = node_obj->node->doc;
486 /* refs count including subtree */
487 if (doc != before_node_obj->node->doc)
488 refcount = xmlnode_get_inst_cnt(node_obj);
490 if (refcount) xmldoc_add_refs(before_node_obj->node->doc, refcount);
491 xmlAddPrevSibling(before_node_obj->node, node_obj->node);
492 if (refcount) xmldoc_release_refs(doc, refcount);
493 node_obj->parent = This->parent;
495 else
497 /* unlink from current parent first */
498 if(node_obj->parent)
500 hr = IXMLDOMNode_removeChild(node_obj->parent, node_obj->iface, NULL);
501 if (hr == S_OK) xmldoc_remove_orphan(node_obj->node->doc, node_obj->node);
503 doc = node_obj->node->doc;
505 if (doc != This->node->doc)
506 refcount = xmlnode_get_inst_cnt(node_obj);
508 if (refcount) xmldoc_add_refs(This->node->doc, refcount);
509 /* xmlAddChild doesn't unlink node from previous parent */
510 xmlUnlinkNode(node_obj->node);
511 xmlAddChild(This->node, node_obj->node);
512 if (refcount) xmldoc_release_refs(doc, refcount);
513 node_obj->parent = This->iface;
516 if(ret)
518 IXMLDOMNode_AddRef(new_child);
519 *ret = new_child;
522 TRACE("ret S_OK\n");
523 return S_OK;
526 HRESULT node_replace_child(xmlnode *This, IXMLDOMNode *newChild, IXMLDOMNode *oldChild,
527 IXMLDOMNode **ret)
529 xmlnode *old_child, *new_child;
530 xmlDocPtr leaving_doc;
531 xmlNode *my_ancestor;
532 int refcount = 0;
534 /* Do not believe any documentation telling that newChild == NULL
535 means removal. It does certainly *not* apply to msxml3! */
536 if(!newChild || !oldChild)
537 return E_INVALIDARG;
539 if(ret)
540 *ret = NULL;
542 old_child = get_node_obj(oldChild);
543 if(!old_child) return E_FAIL;
545 if(old_child->node->parent != This->node)
547 WARN("childNode %p is not a child of %p\n", oldChild, This);
548 return E_INVALIDARG;
551 new_child = get_node_obj(newChild);
552 if(!new_child) return E_FAIL;
554 my_ancestor = This->node;
555 while(my_ancestor)
557 if(my_ancestor == new_child->node)
559 WARN("tried to create loop\n");
560 return E_FAIL;
562 my_ancestor = my_ancestor->parent;
565 if(!new_child->node->parent)
566 if(xmldoc_remove_orphan(new_child->node->doc, new_child->node) != S_OK)
567 WARN("%p is not an orphan of %p\n", new_child->node, new_child->node->doc);
569 leaving_doc = new_child->node->doc;
571 if (leaving_doc != old_child->node->doc)
572 refcount = xmlnode_get_inst_cnt(new_child);
574 if (refcount) xmldoc_add_refs(old_child->node->doc, refcount);
575 xmlReplaceNode(old_child->node, new_child->node);
576 if (refcount) xmldoc_release_refs(leaving_doc, refcount);
577 new_child->parent = old_child->parent;
578 old_child->parent = NULL;
580 xmldoc_add_orphan(old_child->node->doc, old_child->node);
582 if(ret)
584 IXMLDOMNode_AddRef(oldChild);
585 *ret = oldChild;
588 return S_OK;
591 HRESULT node_remove_child(xmlnode *This, IXMLDOMNode* child, IXMLDOMNode** oldChild)
593 xmlnode *child_node;
595 if(!child) return E_INVALIDARG;
597 if(oldChild)
598 *oldChild = NULL;
600 child_node = get_node_obj(child);
601 if(!child_node) return E_FAIL;
603 if(child_node->node->parent != This->node)
605 WARN("childNode %p is not a child of %p\n", child, This);
606 return E_INVALIDARG;
609 xmlUnlinkNode(child_node->node);
610 child_node->parent = NULL;
611 xmldoc_add_orphan(child_node->node->doc, child_node->node);
613 if(oldChild)
615 IXMLDOMNode_AddRef(child);
616 *oldChild = child;
619 return S_OK;
622 HRESULT node_append_child(xmlnode *This, IXMLDOMNode *child, IXMLDOMNode **outChild)
624 DOMNodeType type;
625 VARIANT var;
626 HRESULT hr;
628 hr = IXMLDOMNode_get_nodeType(child, &type);
629 if(FAILED(hr) || type == NODE_ATTRIBUTE) {
630 if (outChild) *outChild = NULL;
631 return E_FAIL;
634 VariantInit(&var);
635 return IXMLDOMNode_insertBefore(This->iface, child, var, outChild);
638 HRESULT node_has_childnodes(const xmlnode *This, VARIANT_BOOL *ret)
640 if (!ret) return E_INVALIDARG;
642 if (!This->node->children)
644 *ret = VARIANT_FALSE;
645 return S_FALSE;
648 *ret = VARIANT_TRUE;
649 return S_OK;
652 HRESULT node_get_owner_doc(const xmlnode *This, IXMLDOMDocument **doc)
654 return get_domdoc_from_xmldoc(This->node->doc, (IXMLDOMDocument3**)doc);
657 HRESULT node_clone(xmlnode *This, VARIANT_BOOL deep, IXMLDOMNode **cloneNode)
659 IXMLDOMNode *node;
660 xmlNodePtr clone;
662 if(!cloneNode) return E_INVALIDARG;
664 clone = xmlCopyNode(This->node, deep ? 1 : 2);
665 if (clone)
667 xmlSetTreeDoc(clone, This->node->doc);
668 xmldoc_add_orphan(clone->doc, clone);
670 node = create_node(clone);
671 if (!node)
673 ERR("Copy failed\n");
674 xmldoc_remove_orphan(clone->doc, clone);
675 xmlFreeNode(clone);
676 return E_FAIL;
679 *cloneNode = node;
681 else
683 ERR("Copy failed\n");
684 return E_FAIL;
687 return S_OK;
690 static inline xmlChar* trim_whitespace(xmlChar* str)
692 xmlChar* ret = str;
693 int len;
695 if (!str)
696 return NULL;
698 while (*ret && isspace(*ret))
699 ++ret;
700 len = xmlStrlen(ret);
701 if (len)
702 while (isspace(ret[len-1])) --len;
704 ret = xmlStrndup(ret, len);
705 xmlFree(str);
706 return ret;
709 static xmlChar* do_get_text(xmlNodePtr node)
711 xmlNodePtr child;
712 xmlChar* str;
713 BOOL preserving = is_preserving_whitespace(node);
715 if (!node->children)
717 str = xmlNodeGetContent(node);
719 else
721 xmlElementType prev_type = XML_TEXT_NODE;
722 xmlChar* tmp;
723 str = xmlStrdup(BAD_CAST "");
724 for (child = node->children; child != NULL; child = child->next)
726 switch (child->type)
728 case XML_ELEMENT_NODE:
729 tmp = do_get_text(child);
730 break;
731 case XML_TEXT_NODE:
732 case XML_CDATA_SECTION_NODE:
733 case XML_ENTITY_REF_NODE:
734 case XML_ENTITY_NODE:
735 tmp = xmlNodeGetContent(child);
736 break;
737 default:
738 tmp = NULL;
739 break;
742 if (tmp)
744 if (*tmp)
746 if (prev_type == XML_ELEMENT_NODE && child->type == XML_ELEMENT_NODE)
747 str = xmlStrcat(str, BAD_CAST " ");
748 str = xmlStrcat(str, tmp);
749 prev_type = child->type;
751 xmlFree(tmp);
756 switch (node->type)
758 case XML_ELEMENT_NODE:
759 case XML_TEXT_NODE:
760 case XML_ENTITY_REF_NODE:
761 case XML_ENTITY_NODE:
762 case XML_DOCUMENT_NODE:
763 case XML_DOCUMENT_FRAG_NODE:
764 if (!preserving)
765 str = trim_whitespace(str);
766 break;
767 default:
768 break;
771 return str;
774 HRESULT node_get_text(const xmlnode *This, BSTR *text)
776 BSTR str = NULL;
777 xmlChar *content;
779 if (!text) return E_INVALIDARG;
781 content = do_get_text(This->node);
782 if (content)
784 str = bstr_from_xmlChar(content);
785 xmlFree(content);
788 /* Always return a string. */
789 if (!str) str = SysAllocStringLen( NULL, 0 );
791 TRACE("%p %s\n", This, debugstr_w(str) );
792 *text = str;
794 return S_OK;
797 HRESULT node_put_text(xmlnode *This, BSTR text)
799 xmlChar *str, *str2;
801 TRACE("(%p)->(%s)\n", This, debugstr_w(text));
803 str = xmlchar_from_wchar(text);
805 /* Escape the string. */
806 str2 = xmlEncodeEntitiesReentrant(This->node->doc, str);
807 heap_free(str);
809 xmlNodeSetContent(This->node, str2);
810 xmlFree(str2);
812 return S_OK;
815 BSTR EnsureCorrectEOL(BSTR sInput)
817 int nNum = 0;
818 BSTR sNew;
819 int nLen;
820 int i;
822 nLen = SysStringLen(sInput);
823 /* Count line endings */
824 for(i=0; i < nLen; i++)
826 if(sInput[i] == '\n')
827 nNum++;
830 TRACE("len=%d, num=%d\n", nLen, nNum);
832 /* Add linefeed as needed */
833 if(nNum > 0)
835 int nPlace = 0;
836 sNew = SysAllocStringLen(NULL, nLen + nNum);
837 for(i=0; i < nLen; i++)
839 if(sInput[i] == '\n')
841 sNew[i+nPlace] = '\r';
842 nPlace++;
844 sNew[i+nPlace] = sInput[i];
847 SysFreeString(sInput);
849 else
851 sNew = sInput;
854 TRACE("len %d\n", SysStringLen(sNew));
856 return sNew;
860 * We are trying to replicate the same behaviour as msxml by converting
861 * line endings to \r\n and using indents as \t. The problem is that msxml
862 * only formats nodes that have a line ending. Using libxml we cannot
863 * reproduce behaviour exactly.
866 HRESULT node_get_xml(xmlnode *This, BOOL ensure_eol, BSTR *ret)
868 xmlBufferPtr xml_buf;
869 xmlNodePtr xmldecl;
870 int size;
872 if(!ret)
873 return E_INVALIDARG;
875 *ret = NULL;
877 xml_buf = xmlBufferCreate();
878 if(!xml_buf)
879 return E_OUTOFMEMORY;
881 xmldecl = xmldoc_unlink_xmldecl( This->node->doc );
883 size = xmlNodeDump(xml_buf, This->node->doc, This->node, 0, 1);
884 if(size > 0) {
885 const xmlChar *buf_content;
886 BSTR content;
888 /* Attribute Nodes return a space in front of their name */
889 buf_content = xmlBufferContent(xml_buf);
891 content = bstr_from_xmlChar(buf_content + (buf_content[0] == ' ' ? 1 : 0));
892 if(ensure_eol)
893 content = EnsureCorrectEOL(content);
895 *ret = content;
896 }else {
897 *ret = SysAllocStringLen(NULL, 0);
900 xmlBufferFree(xml_buf);
901 xmldoc_link_xmldecl( This->node->doc, xmldecl );
902 return *ret ? S_OK : E_OUTOFMEMORY;
905 /* duplicates xmlBufferWriteQuotedString() logic */
906 static void xml_write_quotedstring(xmlOutputBufferPtr buf, const xmlChar *string)
908 const xmlChar *cur, *base;
910 if (xmlStrchr(string, '\"'))
912 if (xmlStrchr(string, '\''))
914 xmlOutputBufferWrite(buf, 1, "\"");
915 base = cur = string;
917 while (*cur)
919 if (*cur == '"')
921 if (base != cur)
922 xmlOutputBufferWrite(buf, cur-base, (const char*)base);
923 xmlOutputBufferWrite(buf, 6, "&quot;");
924 cur++;
925 base = cur;
927 else
928 cur++;
930 if (base != cur)
931 xmlOutputBufferWrite(buf, cur-base, (const char*)base);
932 xmlOutputBufferWrite(buf, 1, "\"");
934 else
936 xmlOutputBufferWrite(buf, 1, "\'");
937 xmlOutputBufferWriteString(buf, (const char*)string);
938 xmlOutputBufferWrite(buf, 1, "\'");
941 else
943 xmlOutputBufferWrite(buf, 1, "\"");
944 xmlOutputBufferWriteString(buf, (const char*)string);
945 xmlOutputBufferWrite(buf, 1, "\"");
949 static void htmldtd_dumpcontent(xmlOutputBufferPtr buf, xmlDocPtr doc)
951 xmlDtdPtr cur = doc->intSubset;
953 xmlOutputBufferWriteString(buf, "<!DOCTYPE ");
954 xmlOutputBufferWriteString(buf, (const char *)cur->name);
955 if (cur->ExternalID)
957 xmlOutputBufferWriteString(buf, " PUBLIC ");
958 xml_write_quotedstring(buf, cur->ExternalID);
959 if (cur->SystemID)
961 xmlOutputBufferWriteString(buf, " ");
962 xml_write_quotedstring(buf, cur->SystemID);
965 else if (cur->SystemID)
967 xmlOutputBufferWriteString(buf, " SYSTEM ");
968 xml_write_quotedstring(buf, cur->SystemID);
970 xmlOutputBufferWriteString(buf, ">\n");
973 static void htmldoc_dumpcontent(xmlOutputBufferPtr buf, xmlDocPtr doc)
975 xmlElementType type;
977 /* force HTML output */
978 type = doc->type;
979 doc->type = XML_HTML_DOCUMENT_NODE;
980 if (doc->intSubset)
981 htmldtd_dumpcontent(buf, doc);
982 if (doc->children)
984 xmlNodePtr cur = doc->children;
986 while (cur)
988 htmlNodeDumpFormatOutput(buf, doc, cur, NULL, 1);
989 cur = cur->next;
993 doc->type = type;
996 static const xmlChar *get_output_buffer_content(xmlOutputBufferPtr output)
998 #ifdef LIBXML2_NEW_BUFFER
999 return xmlOutputBufferGetContent(output);
1000 #else
1001 return xmlBufferContent(output->buffer);
1002 #endif
1005 HRESULT node_transform_node_params(const xmlnode *This, IXMLDOMNode *stylesheet, BSTR *p,
1006 const struct xslprocessor_params *params)
1008 #ifdef SONAME_LIBXSLT
1009 xsltStylesheetPtr xsltSS;
1010 xmlnode *sheet;
1012 if (!libxslt_handle) return E_NOTIMPL;
1013 if (!stylesheet || !p) return E_INVALIDARG;
1015 *p = NULL;
1017 sheet = get_node_obj(stylesheet);
1018 if(!sheet) return E_FAIL;
1020 xsltSS = pxsltParseStylesheetDoc(sheet->node->doc);
1021 if(xsltSS)
1023 const char **xslparams = NULL;
1024 xmlDocPtr result;
1025 unsigned int i;
1027 /* convert our parameter list to libxml2 format */
1028 if (params && params->count)
1030 struct xslprocessor_par *par;
1032 i = 0;
1033 xslparams = heap_alloc((params->count*2 + 1)*sizeof(char*));
1034 LIST_FOR_EACH_ENTRY(par, &params->list, struct xslprocessor_par, entry)
1036 xslparams[i++] = (char*)xmlchar_from_wchar(par->name);
1037 xslparams[i++] = (char*)xmlchar_from_wchar(par->value);
1039 xslparams[i] = NULL;
1042 if (xslparams)
1044 xsltTransformContextPtr ctxt = pxsltNewTransformContext(xsltSS, This->node->doc);
1046 /* push parameters to user context */
1047 pxsltQuoteUserParams(ctxt, xslparams);
1048 result = pxsltApplyStylesheetUser(xsltSS, This->node->doc, NULL, NULL, NULL, ctxt);
1049 pxsltFreeTransformContext(ctxt);
1051 for (i = 0; i < params->count*2; i++)
1052 heap_free((char*)xslparams[i]);
1053 heap_free(xslparams);
1055 else
1056 result = pxsltApplyStylesheet(xsltSS, This->node->doc, NULL);
1058 if(result)
1060 const xmlChar *content;
1062 xmlOutputBufferPtr output = xmlAllocOutputBuffer(NULL);
1063 if (output)
1065 if(result->type == XML_HTML_DOCUMENT_NODE)
1066 htmldoc_dumpcontent(output, result->doc);
1067 else
1068 pxsltSaveResultTo(output, result->doc, xsltSS);
1069 content = get_output_buffer_content(output);
1070 *p = bstr_from_xmlChar(content);
1071 xmlOutputBufferClose(output);
1073 xmlFreeDoc(result);
1075 /* libxslt "helpfully" frees the XML document the stylesheet was
1076 generated from, too */
1077 xsltSS->doc = NULL;
1078 pxsltFreeStylesheet(xsltSS);
1081 if(!*p) *p = SysAllocStringLen(NULL, 0);
1083 return S_OK;
1084 #else
1085 FIXME("libxslt headers were not found at compile time\n");
1086 return E_NOTIMPL;
1087 #endif
1090 HRESULT node_transform_node(const xmlnode *node, IXMLDOMNode *stylesheet, BSTR *p)
1092 return node_transform_node_params(node, stylesheet, p, NULL);
1095 HRESULT node_select_nodes(const xmlnode *This, BSTR query, IXMLDOMNodeList **nodes)
1097 xmlChar* str;
1098 HRESULT hr;
1100 if (!query || !nodes) return E_INVALIDARG;
1102 str = xmlchar_from_wchar(query);
1103 hr = create_selection(This->node, str, nodes);
1104 heap_free(str);
1106 return hr;
1109 HRESULT node_select_singlenode(const xmlnode *This, BSTR query, IXMLDOMNode **node)
1111 IXMLDOMNodeList *list;
1112 HRESULT hr;
1114 hr = node_select_nodes(This, query, &list);
1115 if (hr == S_OK)
1117 hr = IXMLDOMNodeList_nextNode(list, node);
1118 IXMLDOMNodeList_Release(list);
1120 return hr;
1123 HRESULT node_get_namespaceURI(xmlnode *This, BSTR *namespaceURI)
1125 xmlNsPtr ns = This->node->ns;
1127 if(!namespaceURI)
1128 return E_INVALIDARG;
1130 *namespaceURI = NULL;
1132 if (ns && ns->href)
1133 *namespaceURI = bstr_from_xmlChar(ns->href);
1135 TRACE("uri: %s\n", debugstr_w(*namespaceURI));
1137 return *namespaceURI ? S_OK : S_FALSE;
1140 HRESULT node_get_prefix(xmlnode *This, BSTR *prefix)
1142 xmlNsPtr ns = This->node->ns;
1144 if (!prefix) return E_INVALIDARG;
1146 *prefix = NULL;
1148 if (ns && ns->prefix)
1149 *prefix = bstr_from_xmlChar(ns->prefix);
1151 TRACE("prefix: %s\n", debugstr_w(*prefix));
1153 return *prefix ? S_OK : S_FALSE;
1156 HRESULT node_get_base_name(xmlnode *This, BSTR *name)
1158 if (!name) return E_INVALIDARG;
1160 *name = bstr_from_xmlChar(This->node->name);
1161 if (!*name) return E_OUTOFMEMORY;
1163 TRACE("returning %s\n", debugstr_w(*name));
1165 return S_OK;
1168 /* _private field holds a number of COM instances spawned from this libxml2 node */
1169 static void xmlnode_add_ref(xmlNodePtr node)
1171 if (node->type == XML_DOCUMENT_NODE) return;
1172 InterlockedIncrement((LONG*)&node->_private);
1175 static void xmlnode_release(xmlNodePtr node)
1177 if (node->type == XML_DOCUMENT_NODE) return;
1178 InterlockedDecrement((LONG*)&node->_private);
1181 void destroy_xmlnode(xmlnode *This)
1183 if(This->node)
1185 xmlnode_release(This->node);
1186 xmldoc_release(This->node->doc);
1190 void init_xmlnode(xmlnode *This, xmlNodePtr node, IXMLDOMNode *node_iface, dispex_static_data_t *dispex_data)
1192 if(node)
1194 xmlnode_add_ref(node);
1195 xmldoc_add_ref(node->doc);
1198 This->node = node;
1199 This->iface = node_iface;
1200 This->parent = NULL;
1202 init_dispex(&This->dispex, (IUnknown*)This->iface, dispex_data);
1205 typedef struct {
1206 xmlnode node;
1207 IXMLDOMNode IXMLDOMNode_iface;
1208 LONG ref;
1209 } unknode;
1211 static inline unknode *unknode_from_IXMLDOMNode(IXMLDOMNode *iface)
1213 return CONTAINING_RECORD(iface, unknode, IXMLDOMNode_iface);
1216 static HRESULT WINAPI unknode_QueryInterface(
1217 IXMLDOMNode *iface,
1218 REFIID riid,
1219 void** ppvObject )
1221 unknode *This = unknode_from_IXMLDOMNode( iface );
1223 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
1225 if (IsEqualGUID(riid, &IID_IUnknown)) {
1226 *ppvObject = iface;
1227 }else if (IsEqualGUID( riid, &IID_IDispatch) ||
1228 IsEqualGUID( riid, &IID_IXMLDOMNode)) {
1229 *ppvObject = &This->IXMLDOMNode_iface;
1230 }else if(node_query_interface(&This->node, riid, ppvObject)) {
1231 return *ppvObject ? S_OK : E_NOINTERFACE;
1232 }else {
1233 FIXME("interface %s not implemented\n", debugstr_guid(riid));
1234 *ppvObject = NULL;
1235 return E_NOINTERFACE;
1238 IUnknown_AddRef((IUnknown*)*ppvObject);
1239 return S_OK;
1242 static ULONG WINAPI unknode_AddRef(
1243 IXMLDOMNode *iface )
1245 unknode *This = unknode_from_IXMLDOMNode( iface );
1247 return InterlockedIncrement(&This->ref);
1250 static ULONG WINAPI unknode_Release(
1251 IXMLDOMNode *iface )
1253 unknode *This = unknode_from_IXMLDOMNode( iface );
1254 LONG ref;
1256 ref = InterlockedDecrement( &This->ref );
1257 if(!ref) {
1258 destroy_xmlnode(&This->node);
1259 heap_free(This);
1262 return ref;
1265 static HRESULT WINAPI unknode_GetTypeInfoCount(
1266 IXMLDOMNode *iface,
1267 UINT* pctinfo )
1269 unknode *This = unknode_from_IXMLDOMNode( iface );
1271 TRACE("(%p)->(%p)\n", This, pctinfo);
1273 *pctinfo = 1;
1275 return S_OK;
1278 static HRESULT WINAPI unknode_GetTypeInfo(
1279 IXMLDOMNode *iface,
1280 UINT iTInfo,
1281 LCID lcid,
1282 ITypeInfo** ppTInfo )
1284 unknode *This = unknode_from_IXMLDOMNode( iface );
1285 HRESULT hr;
1287 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1289 hr = get_typeinfo(IXMLDOMNode_tid, ppTInfo);
1291 return hr;
1294 static HRESULT WINAPI unknode_GetIDsOfNames(
1295 IXMLDOMNode *iface,
1296 REFIID riid,
1297 LPOLESTR* rgszNames,
1298 UINT cNames,
1299 LCID lcid,
1300 DISPID* rgDispId )
1302 unknode *This = unknode_from_IXMLDOMNode( iface );
1304 ITypeInfo *typeinfo;
1305 HRESULT hr;
1307 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1308 lcid, rgDispId);
1310 if(!rgszNames || cNames == 0 || !rgDispId)
1311 return E_INVALIDARG;
1313 hr = get_typeinfo(IXMLDOMNode_tid, &typeinfo);
1314 if(SUCCEEDED(hr))
1316 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1317 ITypeInfo_Release(typeinfo);
1320 return hr;
1323 static HRESULT WINAPI unknode_Invoke(
1324 IXMLDOMNode *iface,
1325 DISPID dispIdMember,
1326 REFIID riid,
1327 LCID lcid,
1328 WORD wFlags,
1329 DISPPARAMS* pDispParams,
1330 VARIANT* pVarResult,
1331 EXCEPINFO* pExcepInfo,
1332 UINT* puArgErr )
1334 unknode *This = unknode_from_IXMLDOMNode( iface );
1335 ITypeInfo *typeinfo;
1336 HRESULT hr;
1338 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1339 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1341 hr = get_typeinfo(IXMLDOMNode_tid, &typeinfo);
1342 if(SUCCEEDED(hr))
1344 hr = ITypeInfo_Invoke(typeinfo, &This->IXMLDOMNode_iface, dispIdMember, wFlags, pDispParams,
1345 pVarResult, pExcepInfo, puArgErr);
1346 ITypeInfo_Release(typeinfo);
1349 return hr;
1352 static HRESULT WINAPI unknode_get_nodeName(
1353 IXMLDOMNode *iface,
1354 BSTR* p )
1356 unknode *This = unknode_from_IXMLDOMNode( iface );
1358 FIXME("(%p)->(%p)\n", This, p);
1360 return node_get_nodeName(&This->node, p);
1363 static HRESULT WINAPI unknode_get_nodeValue(
1364 IXMLDOMNode *iface,
1365 VARIANT* value)
1367 unknode *This = unknode_from_IXMLDOMNode( iface );
1369 FIXME("(%p)->(%p)\n", This, value);
1371 if(!value)
1372 return E_INVALIDARG;
1374 V_VT(value) = VT_NULL;
1375 return S_FALSE;
1378 static HRESULT WINAPI unknode_put_nodeValue(
1379 IXMLDOMNode *iface,
1380 VARIANT value)
1382 unknode *This = unknode_from_IXMLDOMNode( iface );
1383 FIXME("(%p)->(v%d)\n", This, V_VT(&value));
1384 return E_FAIL;
1387 static HRESULT WINAPI unknode_get_nodeType(
1388 IXMLDOMNode *iface,
1389 DOMNodeType* domNodeType )
1391 unknode *This = unknode_from_IXMLDOMNode( iface );
1393 FIXME("(%p)->(%p)\n", This, domNodeType);
1395 *domNodeType = This->node.node->type;
1396 return S_OK;
1399 static HRESULT WINAPI unknode_get_parentNode(
1400 IXMLDOMNode *iface,
1401 IXMLDOMNode** parent )
1403 unknode *This = unknode_from_IXMLDOMNode( iface );
1404 FIXME("(%p)->(%p)\n", This, parent);
1405 if (!parent) return E_INVALIDARG;
1406 *parent = NULL;
1407 return S_FALSE;
1410 static HRESULT WINAPI unknode_get_childNodes(
1411 IXMLDOMNode *iface,
1412 IXMLDOMNodeList** outList)
1414 unknode *This = unknode_from_IXMLDOMNode( iface );
1416 TRACE("(%p)->(%p)\n", This, outList);
1418 return node_get_child_nodes(&This->node, outList);
1421 static HRESULT WINAPI unknode_get_firstChild(
1422 IXMLDOMNode *iface,
1423 IXMLDOMNode** domNode)
1425 unknode *This = unknode_from_IXMLDOMNode( iface );
1427 TRACE("(%p)->(%p)\n", This, domNode);
1429 return node_get_first_child(&This->node, domNode);
1432 static HRESULT WINAPI unknode_get_lastChild(
1433 IXMLDOMNode *iface,
1434 IXMLDOMNode** domNode)
1436 unknode *This = unknode_from_IXMLDOMNode( iface );
1438 TRACE("(%p)->(%p)\n", This, domNode);
1440 return node_get_last_child(&This->node, domNode);
1443 static HRESULT WINAPI unknode_get_previousSibling(
1444 IXMLDOMNode *iface,
1445 IXMLDOMNode** domNode)
1447 unknode *This = unknode_from_IXMLDOMNode( iface );
1449 TRACE("(%p)->(%p)\n", This, domNode);
1451 return node_get_previous_sibling(&This->node, domNode);
1454 static HRESULT WINAPI unknode_get_nextSibling(
1455 IXMLDOMNode *iface,
1456 IXMLDOMNode** domNode)
1458 unknode *This = unknode_from_IXMLDOMNode( iface );
1460 TRACE("(%p)->(%p)\n", This, domNode);
1462 return node_get_next_sibling(&This->node, domNode);
1465 static HRESULT WINAPI unknode_get_attributes(
1466 IXMLDOMNode *iface,
1467 IXMLDOMNamedNodeMap** attributeMap)
1469 unknode *This = unknode_from_IXMLDOMNode( iface );
1471 FIXME("(%p)->(%p)\n", This, attributeMap);
1473 return return_null_ptr((void**)attributeMap);
1476 static HRESULT WINAPI unknode_insertBefore(
1477 IXMLDOMNode *iface,
1478 IXMLDOMNode* newNode, VARIANT refChild,
1479 IXMLDOMNode** outOldNode)
1481 unknode *This = unknode_from_IXMLDOMNode( iface );
1483 FIXME("(%p)->(%p x%d %p)\n", This, newNode, V_VT(&refChild), outOldNode);
1485 return node_insert_before(&This->node, newNode, &refChild, outOldNode);
1488 static HRESULT WINAPI unknode_replaceChild(
1489 IXMLDOMNode *iface,
1490 IXMLDOMNode* newNode,
1491 IXMLDOMNode* oldNode,
1492 IXMLDOMNode** outOldNode)
1494 unknode *This = unknode_from_IXMLDOMNode( iface );
1496 FIXME("(%p)->(%p %p %p)\n", This, newNode, oldNode, outOldNode);
1498 return node_replace_child(&This->node, newNode, oldNode, outOldNode);
1501 static HRESULT WINAPI unknode_removeChild(
1502 IXMLDOMNode *iface,
1503 IXMLDOMNode* domNode, IXMLDOMNode** oldNode)
1505 unknode *This = unknode_from_IXMLDOMNode( iface );
1506 return node_remove_child(&This->node, domNode, oldNode);
1509 static HRESULT WINAPI unknode_appendChild(
1510 IXMLDOMNode *iface,
1511 IXMLDOMNode* newNode, IXMLDOMNode** outNewNode)
1513 unknode *This = unknode_from_IXMLDOMNode( iface );
1514 return node_append_child(&This->node, newNode, outNewNode);
1517 static HRESULT WINAPI unknode_hasChildNodes(
1518 IXMLDOMNode *iface,
1519 VARIANT_BOOL* pbool)
1521 unknode *This = unknode_from_IXMLDOMNode( iface );
1522 return node_has_childnodes(&This->node, pbool);
1525 static HRESULT WINAPI unknode_get_ownerDocument(
1526 IXMLDOMNode *iface,
1527 IXMLDOMDocument** domDocument)
1529 unknode *This = unknode_from_IXMLDOMNode( iface );
1530 return node_get_owner_doc(&This->node, domDocument);
1533 static HRESULT WINAPI unknode_cloneNode(
1534 IXMLDOMNode *iface,
1535 VARIANT_BOOL pbool, IXMLDOMNode** outNode)
1537 unknode *This = unknode_from_IXMLDOMNode( iface );
1538 return node_clone(&This->node, pbool, outNode );
1541 static HRESULT WINAPI unknode_get_nodeTypeString(
1542 IXMLDOMNode *iface,
1543 BSTR* p)
1545 unknode *This = unknode_from_IXMLDOMNode( iface );
1547 FIXME("(%p)->(%p)\n", This, p);
1549 return node_get_nodeName(&This->node, p);
1552 static HRESULT WINAPI unknode_get_text(
1553 IXMLDOMNode *iface,
1554 BSTR* p)
1556 unknode *This = unknode_from_IXMLDOMNode( iface );
1557 return node_get_text(&This->node, p);
1560 static HRESULT WINAPI unknode_put_text(
1561 IXMLDOMNode *iface,
1562 BSTR p)
1564 unknode *This = unknode_from_IXMLDOMNode( iface );
1565 return node_put_text(&This->node, p);
1568 static HRESULT WINAPI unknode_get_specified(
1569 IXMLDOMNode *iface,
1570 VARIANT_BOOL* isSpecified)
1572 unknode *This = unknode_from_IXMLDOMNode( iface );
1573 FIXME("(%p)->(%p) stub!\n", This, isSpecified);
1574 *isSpecified = VARIANT_TRUE;
1575 return S_OK;
1578 static HRESULT WINAPI unknode_get_definition(
1579 IXMLDOMNode *iface,
1580 IXMLDOMNode** definitionNode)
1582 unknode *This = unknode_from_IXMLDOMNode( iface );
1583 FIXME("(%p)->(%p)\n", This, definitionNode);
1584 return E_NOTIMPL;
1587 static HRESULT WINAPI unknode_get_nodeTypedValue(
1588 IXMLDOMNode *iface,
1589 VARIANT* var1)
1591 unknode *This = unknode_from_IXMLDOMNode( iface );
1592 FIXME("(%p)->(%p)\n", This, var1);
1593 return return_null_var(var1);
1596 static HRESULT WINAPI unknode_put_nodeTypedValue(
1597 IXMLDOMNode *iface,
1598 VARIANT typedValue)
1600 unknode *This = unknode_from_IXMLDOMNode( iface );
1601 FIXME("(%p)->(%s)\n", This, debugstr_variant(&typedValue));
1602 return E_NOTIMPL;
1605 static HRESULT WINAPI unknode_get_dataType(
1606 IXMLDOMNode *iface,
1607 VARIANT* var1)
1609 unknode *This = unknode_from_IXMLDOMNode( iface );
1610 TRACE("(%p)->(%p)\n", This, var1);
1611 return return_null_var(var1);
1614 static HRESULT WINAPI unknode_put_dataType(
1615 IXMLDOMNode *iface,
1616 BSTR p)
1618 unknode *This = unknode_from_IXMLDOMNode( iface );
1620 FIXME("(%p)->(%s)\n", This, debugstr_w(p));
1622 if(!p)
1623 return E_INVALIDARG;
1625 return E_FAIL;
1628 static HRESULT WINAPI unknode_get_xml(
1629 IXMLDOMNode *iface,
1630 BSTR* p)
1632 unknode *This = unknode_from_IXMLDOMNode( iface );
1634 FIXME("(%p)->(%p)\n", This, p);
1636 return node_get_xml(&This->node, FALSE, p);
1639 static HRESULT WINAPI unknode_transformNode(
1640 IXMLDOMNode *iface,
1641 IXMLDOMNode* domNode, BSTR* p)
1643 unknode *This = unknode_from_IXMLDOMNode( iface );
1644 return node_transform_node(&This->node, domNode, p);
1647 static HRESULT WINAPI unknode_selectNodes(
1648 IXMLDOMNode *iface,
1649 BSTR p, IXMLDOMNodeList** outList)
1651 unknode *This = unknode_from_IXMLDOMNode( iface );
1652 return node_select_nodes(&This->node, p, outList);
1655 static HRESULT WINAPI unknode_selectSingleNode(
1656 IXMLDOMNode *iface,
1657 BSTR p, IXMLDOMNode** outNode)
1659 unknode *This = unknode_from_IXMLDOMNode( iface );
1660 return node_select_singlenode(&This->node, p, outNode);
1663 static HRESULT WINAPI unknode_get_parsed(
1664 IXMLDOMNode *iface,
1665 VARIANT_BOOL* isParsed)
1667 unknode *This = unknode_from_IXMLDOMNode( iface );
1668 FIXME("(%p)->(%p) stub!\n", This, isParsed);
1669 *isParsed = VARIANT_TRUE;
1670 return S_OK;
1673 static HRESULT WINAPI unknode_get_namespaceURI(
1674 IXMLDOMNode *iface,
1675 BSTR* p)
1677 unknode *This = unknode_from_IXMLDOMNode( iface );
1678 TRACE("(%p)->(%p)\n", This, p);
1679 return node_get_namespaceURI(&This->node, p);
1682 static HRESULT WINAPI unknode_get_prefix(
1683 IXMLDOMNode *iface,
1684 BSTR* p)
1686 unknode *This = unknode_from_IXMLDOMNode( iface );
1687 return node_get_prefix(&This->node, p);
1690 static HRESULT WINAPI unknode_get_baseName(
1691 IXMLDOMNode *iface,
1692 BSTR* p)
1694 unknode *This = unknode_from_IXMLDOMNode( iface );
1695 return node_get_base_name(&This->node, p);
1698 static HRESULT WINAPI unknode_transformNodeToObject(
1699 IXMLDOMNode *iface,
1700 IXMLDOMNode* domNode, VARIANT var1)
1702 unknode *This = unknode_from_IXMLDOMNode( iface );
1703 FIXME("(%p)->(%p %s)\n", This, domNode, debugstr_variant(&var1));
1704 return E_NOTIMPL;
1707 static const struct IXMLDOMNodeVtbl unknode_vtbl =
1709 unknode_QueryInterface,
1710 unknode_AddRef,
1711 unknode_Release,
1712 unknode_GetTypeInfoCount,
1713 unknode_GetTypeInfo,
1714 unknode_GetIDsOfNames,
1715 unknode_Invoke,
1716 unknode_get_nodeName,
1717 unknode_get_nodeValue,
1718 unknode_put_nodeValue,
1719 unknode_get_nodeType,
1720 unknode_get_parentNode,
1721 unknode_get_childNodes,
1722 unknode_get_firstChild,
1723 unknode_get_lastChild,
1724 unknode_get_previousSibling,
1725 unknode_get_nextSibling,
1726 unknode_get_attributes,
1727 unknode_insertBefore,
1728 unknode_replaceChild,
1729 unknode_removeChild,
1730 unknode_appendChild,
1731 unknode_hasChildNodes,
1732 unknode_get_ownerDocument,
1733 unknode_cloneNode,
1734 unknode_get_nodeTypeString,
1735 unknode_get_text,
1736 unknode_put_text,
1737 unknode_get_specified,
1738 unknode_get_definition,
1739 unknode_get_nodeTypedValue,
1740 unknode_put_nodeTypedValue,
1741 unknode_get_dataType,
1742 unknode_put_dataType,
1743 unknode_get_xml,
1744 unknode_transformNode,
1745 unknode_selectNodes,
1746 unknode_selectSingleNode,
1747 unknode_get_parsed,
1748 unknode_get_namespaceURI,
1749 unknode_get_prefix,
1750 unknode_get_baseName,
1751 unknode_transformNodeToObject
1754 IXMLDOMNode *create_node( xmlNodePtr node )
1756 IUnknown *pUnk;
1757 IXMLDOMNode *ret;
1758 HRESULT hr;
1760 if ( !node )
1761 return NULL;
1763 TRACE("type %d\n", node->type);
1764 switch(node->type)
1766 case XML_ELEMENT_NODE:
1767 pUnk = create_element( node );
1768 break;
1769 case XML_ATTRIBUTE_NODE:
1770 pUnk = create_attribute( node );
1771 break;
1772 case XML_TEXT_NODE:
1773 pUnk = create_text( node );
1774 break;
1775 case XML_CDATA_SECTION_NODE:
1776 pUnk = create_cdata( node );
1777 break;
1778 case XML_ENTITY_REF_NODE:
1779 pUnk = create_doc_entity_ref( node );
1780 break;
1781 case XML_PI_NODE:
1782 pUnk = create_pi( node );
1783 break;
1784 case XML_COMMENT_NODE:
1785 pUnk = create_comment( node );
1786 break;
1787 case XML_DOCUMENT_NODE:
1788 pUnk = create_domdoc( node );
1789 break;
1790 case XML_DOCUMENT_FRAG_NODE:
1791 pUnk = create_doc_fragment( node );
1792 break;
1793 case XML_DTD_NODE:
1794 pUnk = create_doc_type( node );
1795 break;
1796 default: {
1797 unknode *new_node;
1799 FIXME("only creating basic node for type %d\n", node->type);
1801 new_node = heap_alloc(sizeof(unknode));
1802 if(!new_node)
1803 return NULL;
1805 new_node->IXMLDOMNode_iface.lpVtbl = &unknode_vtbl;
1806 new_node->ref = 1;
1807 init_xmlnode(&new_node->node, node, &new_node->IXMLDOMNode_iface, NULL);
1808 pUnk = (IUnknown*)&new_node->IXMLDOMNode_iface;
1812 hr = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMNode, (LPVOID*)&ret);
1813 IUnknown_Release(pUnk);
1814 if(FAILED(hr)) return NULL;
1815 return ret;
1817 #endif