include: Add more ARM64 CV constants.
[wine.git] / dlls / msxml3 / node.c
blob1ddc9bfa172e7aebc203c4398dfb42f65e7babbb
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/imports.h>
39 # include <libxslt/variables.h>
40 # include <libxslt/xsltutils.h>
41 # include <libxslt/xsltInternals.h>
42 # endif
43 #endif
45 #include "windef.h"
46 #include "winbase.h"
47 #include "winuser.h"
48 #include "winnls.h"
49 #include "ole2.h"
50 #include "msxml6.h"
52 #include "msxml_private.h"
54 #include "wine/debug.h"
56 #ifdef HAVE_LIBXML2
58 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
60 #ifdef SONAME_LIBXSLT
61 extern void* libxslt_handle;
62 # define MAKE_FUNCPTR(f) extern typeof(f) * p##f
63 MAKE_FUNCPTR(xsltApplyStylesheet);
64 MAKE_FUNCPTR(xsltApplyStylesheetUser);
65 MAKE_FUNCPTR(xsltCleanupGlobals);
66 MAKE_FUNCPTR(xsltFreeStylesheet);
67 MAKE_FUNCPTR(xsltFreeTransformContext);
68 MAKE_FUNCPTR(xsltNewTransformContext);
69 MAKE_FUNCPTR(xsltNextImport);
70 MAKE_FUNCPTR(xsltParseStylesheetDoc);
71 MAKE_FUNCPTR(xsltQuoteUserParams);
72 MAKE_FUNCPTR(xsltSaveResultTo);
73 # undef MAKE_FUNCPTR
74 #else
75 WINE_DECLARE_DEBUG_CHANNEL(winediag);
76 #endif
78 static const IID IID_xmlnode = {0x4f2f4ba2,0xb822,0x11df,{0x8b,0x8a,0x68,0x50,0xdf,0xd7,0x20,0x85}};
80 xmlNodePtr xmlNodePtr_from_domnode( IXMLDOMNode *iface, xmlElementType type )
82 xmlnode *This;
84 if ( !iface )
85 return NULL;
86 This = get_node_obj( iface );
87 if ( !This || !This->node )
88 return NULL;
89 if ( type && This->node->type != type )
90 return NULL;
91 return This->node;
94 BOOL node_query_interface(xmlnode *This, REFIID riid, void **ppv)
96 if(IsEqualGUID(&IID_xmlnode, riid)) {
97 TRACE("(%p)->(IID_xmlnode %p)\n", This, ppv);
98 *ppv = This;
99 return TRUE;
102 return dispex_query_interface(&This->dispex, riid, ppv);
105 /* common ISupportErrorInfo implementation */
106 typedef struct {
107 ISupportErrorInfo ISupportErrorInfo_iface;
108 LONG ref;
110 const tid_t* iids;
111 } SupportErrorInfo;
113 static inline SupportErrorInfo *impl_from_ISupportErrorInfo(ISupportErrorInfo *iface)
115 return CONTAINING_RECORD(iface, SupportErrorInfo, ISupportErrorInfo_iface);
118 static HRESULT WINAPI SupportErrorInfo_QueryInterface(ISupportErrorInfo *iface, REFIID riid, void **obj)
120 SupportErrorInfo *This = impl_from_ISupportErrorInfo(iface);
121 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
123 *obj = NULL;
125 if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_ISupportErrorInfo)) {
126 *obj = iface;
127 ISupportErrorInfo_AddRef(iface);
128 return S_OK;
131 return E_NOINTERFACE;
134 static ULONG WINAPI SupportErrorInfo_AddRef(ISupportErrorInfo *iface)
136 SupportErrorInfo *This = impl_from_ISupportErrorInfo(iface);
137 ULONG ref = InterlockedIncrement(&This->ref);
138 TRACE("(%p)->(%d)\n", This, ref );
139 return ref;
142 static ULONG WINAPI SupportErrorInfo_Release(ISupportErrorInfo *iface)
144 SupportErrorInfo *This = impl_from_ISupportErrorInfo(iface);
145 LONG ref = InterlockedDecrement(&This->ref);
147 TRACE("(%p)->(%d)\n", This, ref);
149 if (ref == 0)
150 heap_free(This);
152 return ref;
155 static HRESULT WINAPI SupportErrorInfo_InterfaceSupportsErrorInfo(ISupportErrorInfo *iface, REFIID riid)
157 SupportErrorInfo *This = impl_from_ISupportErrorInfo(iface);
158 enum tid_t const *tid;
160 TRACE("(%p)->(%s)\n", This, debugstr_guid(riid));
162 tid = This->iids;
163 while (*tid != NULL_tid)
165 if (IsEqualGUID(riid, get_riid_from_tid(*tid)))
166 return S_OK;
167 tid++;
170 return S_FALSE;
173 static const struct ISupportErrorInfoVtbl SupportErrorInfoVtbl = {
174 SupportErrorInfo_QueryInterface,
175 SupportErrorInfo_AddRef,
176 SupportErrorInfo_Release,
177 SupportErrorInfo_InterfaceSupportsErrorInfo
180 HRESULT node_create_supporterrorinfo(enum tid_t const *iids, void **obj)
182 SupportErrorInfo *This;
184 This = heap_alloc(sizeof(*This));
185 if (!This) return E_OUTOFMEMORY;
187 This->ISupportErrorInfo_iface.lpVtbl = &SupportErrorInfoVtbl;
188 This->ref = 1;
189 This->iids = iids;
191 *obj = &This->ISupportErrorInfo_iface;
193 return S_OK;
196 xmlnode *get_node_obj(IXMLDOMNode *node)
198 xmlnode *obj = NULL;
199 HRESULT hres;
201 hres = IXMLDOMNode_QueryInterface(node, &IID_xmlnode, (void**)&obj);
202 if (!obj) WARN("node is not our IXMLDOMNode implementation\n");
203 return SUCCEEDED(hres) ? obj : NULL;
206 HRESULT node_get_nodeName(xmlnode *This, BSTR *name)
208 BSTR prefix, base;
209 HRESULT hr;
211 if (!name)
212 return E_INVALIDARG;
214 hr = node_get_base_name(This, &base);
215 if (hr != S_OK) return hr;
217 hr = node_get_prefix(This, &prefix);
218 if (hr == S_OK)
220 static const WCHAR colW = ':';
221 WCHAR *ptr;
223 /* +1 for ':' */
224 ptr = *name = SysAllocStringLen(NULL, SysStringLen(base) + SysStringLen(prefix) + 1);
225 memcpy(ptr, prefix, SysStringByteLen(prefix));
226 ptr += SysStringLen(prefix);
227 memcpy(ptr++, &colW, sizeof(WCHAR));
228 memcpy(ptr, base, SysStringByteLen(base));
230 SysFreeString(base);
231 SysFreeString(prefix);
233 else
234 *name = base;
236 return S_OK;
239 HRESULT node_get_content(xmlnode *This, VARIANT *value)
241 xmlChar *content;
243 if(!value)
244 return E_INVALIDARG;
246 content = xmlNodeGetContent(This->node);
247 V_VT(value) = VT_BSTR;
248 V_BSTR(value) = bstr_from_xmlChar( content );
249 xmlFree(content);
251 TRACE("%p returned %s\n", This, debugstr_w(V_BSTR(value)));
252 return S_OK;
255 HRESULT node_set_content(xmlnode *This, LPCWSTR value)
257 xmlChar *str;
259 TRACE("(%p)->(%s)\n", This, debugstr_w(value));
260 str = xmlchar_from_wchar(value);
261 if(!str)
262 return E_OUTOFMEMORY;
264 xmlNodeSetContent(This->node, str);
265 heap_free(str);
266 return S_OK;
269 static HRESULT node_set_content_escaped(xmlnode *This, LPCWSTR value)
271 xmlChar *str, *escaped;
273 TRACE("(%p)->(%s)\n", This, debugstr_w(value));
274 str = xmlchar_from_wchar(value);
275 if(!str)
276 return E_OUTOFMEMORY;
278 escaped = xmlEncodeSpecialChars(NULL, str);
279 if(!escaped)
281 heap_free(str);
282 return E_OUTOFMEMORY;
285 xmlNodeSetContent(This->node, escaped);
287 heap_free(str);
288 xmlFree(escaped);
290 return S_OK;
293 HRESULT node_put_value(xmlnode *This, VARIANT *value)
295 HRESULT hr;
297 if (V_VT(value) != VT_BSTR)
299 VARIANT string_value;
301 VariantInit(&string_value);
302 hr = VariantChangeType(&string_value, value, 0, VT_BSTR);
303 if(FAILED(hr)) {
304 WARN("Couldn't convert to VT_BSTR\n");
305 return hr;
308 hr = node_set_content(This, V_BSTR(&string_value));
309 VariantClear(&string_value);
311 else
312 hr = node_set_content(This, V_BSTR(value));
314 return hr;
317 HRESULT node_put_value_escaped(xmlnode *This, VARIANT *value)
319 HRESULT hr;
321 if (V_VT(value) != VT_BSTR)
323 VARIANT string_value;
325 VariantInit(&string_value);
326 hr = VariantChangeType(&string_value, value, 0, VT_BSTR);
327 if(FAILED(hr)) {
328 WARN("Couldn't convert to VT_BSTR\n");
329 return hr;
332 hr = node_set_content_escaped(This, V_BSTR(&string_value));
333 VariantClear(&string_value);
335 else
336 hr = node_set_content_escaped(This, V_BSTR(value));
338 return hr;
341 static HRESULT get_node(
342 xmlnode *This,
343 const char *name,
344 xmlNodePtr node,
345 IXMLDOMNode **out )
347 TRACE("(%p)->(%s %p %p)\n", This, name, node, out );
349 if ( !out )
350 return E_INVALIDARG;
352 /* if we don't have a doc, use our parent. */
353 if(node && !node->doc && node->parent)
354 node->doc = node->parent->doc;
356 *out = create_node( node );
357 if (!*out)
358 return S_FALSE;
359 return S_OK;
362 HRESULT node_get_parent(xmlnode *This, IXMLDOMNode **parent)
364 return get_node( This, "parent", This->node->parent, parent );
367 HRESULT node_get_child_nodes(xmlnode *This, IXMLDOMNodeList **ret)
369 if(!ret)
370 return E_INVALIDARG;
372 *ret = create_children_nodelist(This->node);
373 if(!*ret)
374 return E_OUTOFMEMORY;
376 return S_OK;
379 HRESULT node_get_first_child(xmlnode *This, IXMLDOMNode **ret)
381 return get_node(This, "firstChild", This->node->children, ret);
384 HRESULT node_get_last_child(xmlnode *This, IXMLDOMNode **ret)
386 return get_node(This, "lastChild", This->node->last, ret);
389 HRESULT node_get_previous_sibling(xmlnode *This, IXMLDOMNode **ret)
391 return get_node(This, "previous", This->node->prev, ret);
394 HRESULT node_get_next_sibling(xmlnode *This, IXMLDOMNode **ret)
396 return get_node(This, "next", This->node->next, ret);
399 static int node_get_inst_cnt(xmlNodePtr node)
401 int ret = *(LONG *)&node->_private;
402 xmlNodePtr child;
404 /* add attribute counts */
405 if (node->type == XML_ELEMENT_NODE)
407 xmlAttrPtr prop = node->properties;
409 while (prop)
411 ret += node_get_inst_cnt((xmlNodePtr)prop);
412 prop = prop->next;
416 /* add children counts */
417 child = node->children;
418 while (child)
420 ret += node_get_inst_cnt(child);
421 child = child->next;
424 return ret;
427 int xmlnode_get_inst_cnt(xmlnode *node)
429 return node_get_inst_cnt(node->node);
432 HRESULT node_insert_before(xmlnode *This, IXMLDOMNode *new_child, const VARIANT *ref_child,
433 IXMLDOMNode **ret)
435 IXMLDOMNode *before = NULL;
436 xmlnode *node_obj;
437 int refcount = 0;
438 xmlDocPtr doc;
439 HRESULT hr;
441 if(!new_child)
442 return E_INVALIDARG;
444 node_obj = get_node_obj(new_child);
445 if(!node_obj) return E_FAIL;
447 switch(V_VT(ref_child))
449 case VT_EMPTY:
450 case VT_NULL:
451 break;
453 case VT_UNKNOWN:
454 case VT_DISPATCH:
455 if (V_UNKNOWN(ref_child))
457 hr = IUnknown_QueryInterface(V_UNKNOWN(ref_child), &IID_IXMLDOMNode, (void**)&before);
458 if(FAILED(hr)) return hr;
460 break;
462 default:
463 FIXME("refChild var type %x\n", V_VT(ref_child));
464 return E_FAIL;
467 TRACE("new child %p, This->node %p\n", node_obj->node, This->node);
469 if(!node_obj->node->parent)
470 if(xmldoc_remove_orphan(node_obj->node->doc, node_obj->node) != S_OK)
471 WARN("%p is not an orphan of %p\n", node_obj->node, node_obj->node->doc);
473 refcount = xmlnode_get_inst_cnt(node_obj);
475 if(before)
477 xmlnode *before_node_obj = get_node_obj(before);
478 IXMLDOMNode_Release(before);
479 if(!before_node_obj) return E_FAIL;
482 /* unlink from current parent first */
483 if(node_obj->parent)
485 hr = IXMLDOMNode_removeChild(node_obj->parent, node_obj->iface, NULL);
486 if (hr == S_OK) xmldoc_remove_orphan(node_obj->node->doc, node_obj->node);
488 doc = node_obj->node->doc;
490 if(before)
492 xmlnode *before_node_obj = get_node_obj(before);
494 /* refs count including subtree */
495 if (doc != before_node_obj->node->doc)
496 refcount = xmlnode_get_inst_cnt(node_obj);
498 if (refcount) xmldoc_add_refs(before_node_obj->node->doc, refcount);
499 xmlAddPrevSibling(before_node_obj->node, node_obj->node);
500 if (refcount) xmldoc_release_refs(doc, refcount);
501 node_obj->parent = This->parent;
503 else
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 if (!child)
629 return E_INVALIDARG;
631 hr = IXMLDOMNode_get_nodeType(child, &type);
632 if(FAILED(hr) || type == NODE_ATTRIBUTE) {
633 if (outChild) *outChild = NULL;
634 return E_FAIL;
637 VariantInit(&var);
638 return IXMLDOMNode_insertBefore(This->iface, child, var, outChild);
641 HRESULT node_has_childnodes(const xmlnode *This, VARIANT_BOOL *ret)
643 if (!ret) return E_INVALIDARG;
645 if (!This->node->children)
647 *ret = VARIANT_FALSE;
648 return S_FALSE;
651 *ret = VARIANT_TRUE;
652 return S_OK;
655 HRESULT node_get_owner_doc(const xmlnode *This, IXMLDOMDocument **doc)
657 return get_domdoc_from_xmldoc(This->node->doc, (IXMLDOMDocument3**)doc);
660 HRESULT node_clone(xmlnode *This, VARIANT_BOOL deep, IXMLDOMNode **cloneNode)
662 IXMLDOMNode *node;
663 xmlNodePtr clone;
665 if(!cloneNode) return E_INVALIDARG;
667 clone = xmlCopyNode(This->node, deep ? 1 : 2);
668 if (clone)
670 xmlSetTreeDoc(clone, This->node->doc);
671 xmldoc_add_orphan(clone->doc, clone);
673 node = create_node(clone);
674 if (!node)
676 ERR("Copy failed\n");
677 xmldoc_remove_orphan(clone->doc, clone);
678 xmlFreeNode(clone);
679 return E_FAIL;
682 *cloneNode = node;
684 else
686 ERR("Copy failed\n");
687 return E_FAIL;
690 return S_OK;
693 static inline xmlChar* trim_whitespace(xmlChar* str)
695 xmlChar* ret = str;
696 int len;
698 if (!str)
699 return NULL;
701 while (*ret && isspace(*ret))
702 ++ret;
703 len = xmlStrlen(ret);
704 if (len)
705 while (isspace(ret[len-1])) --len;
707 ret = xmlStrndup(ret, len);
708 xmlFree(str);
709 return ret;
712 static xmlChar* do_get_text(xmlNodePtr node)
714 xmlNodePtr child;
715 xmlChar* str;
716 BOOL preserving = is_preserving_whitespace(node);
718 if (!node->children)
720 str = xmlNodeGetContent(node);
722 else
724 xmlElementType prev_type = XML_TEXT_NODE;
725 xmlChar* tmp;
726 str = xmlStrdup(BAD_CAST "");
727 for (child = node->children; child != NULL; child = child->next)
729 switch (child->type)
731 case XML_ELEMENT_NODE:
732 tmp = do_get_text(child);
733 break;
734 case XML_TEXT_NODE:
735 case XML_CDATA_SECTION_NODE:
736 case XML_ENTITY_REF_NODE:
737 case XML_ENTITY_NODE:
738 tmp = xmlNodeGetContent(child);
739 break;
740 default:
741 tmp = NULL;
742 break;
745 if (tmp)
747 if (*tmp)
749 if (prev_type == XML_ELEMENT_NODE && child->type == XML_ELEMENT_NODE)
750 str = xmlStrcat(str, BAD_CAST " ");
751 str = xmlStrcat(str, tmp);
752 prev_type = child->type;
754 xmlFree(tmp);
759 switch (node->type)
761 case XML_ELEMENT_NODE:
762 case XML_TEXT_NODE:
763 case XML_ENTITY_REF_NODE:
764 case XML_ENTITY_NODE:
765 case XML_DOCUMENT_NODE:
766 case XML_DOCUMENT_FRAG_NODE:
767 if (!preserving)
768 str = trim_whitespace(str);
769 break;
770 default:
771 break;
774 return str;
777 HRESULT node_get_text(const xmlnode *This, BSTR *text)
779 BSTR str = NULL;
780 xmlChar *content;
782 if (!text) return E_INVALIDARG;
784 content = do_get_text(This->node);
785 if (content)
787 str = bstr_from_xmlChar(content);
788 xmlFree(content);
791 /* Always return a string. */
792 if (!str) str = SysAllocStringLen( NULL, 0 );
794 TRACE("%p %s\n", This, debugstr_w(str) );
795 *text = str;
797 return S_OK;
800 HRESULT node_put_text(xmlnode *This, BSTR text)
802 xmlChar *str, *str2;
804 TRACE("(%p)->(%s)\n", This, debugstr_w(text));
806 str = xmlchar_from_wchar(text);
808 /* Escape the string. */
809 str2 = xmlEncodeEntitiesReentrant(This->node->doc, str);
810 heap_free(str);
812 xmlNodeSetContent(This->node, str2);
813 xmlFree(str2);
815 return S_OK;
818 BSTR EnsureCorrectEOL(BSTR sInput)
820 int nNum = 0;
821 BSTR sNew;
822 int nLen;
823 int i;
825 nLen = SysStringLen(sInput);
826 /* Count line endings */
827 for(i=0; i < nLen; i++)
829 if(sInput[i] == '\n')
830 nNum++;
833 TRACE("len=%d, num=%d\n", nLen, nNum);
835 /* Add linefeed as needed */
836 if(nNum > 0)
838 int nPlace = 0;
839 sNew = SysAllocStringLen(NULL, nLen + nNum);
840 for(i=0; i < nLen; i++)
842 if(sInput[i] == '\n')
844 sNew[i+nPlace] = '\r';
845 nPlace++;
847 sNew[i+nPlace] = sInput[i];
850 SysFreeString(sInput);
852 else
854 sNew = sInput;
857 TRACE("len %d\n", SysStringLen(sNew));
859 return sNew;
863 * We are trying to replicate the same behaviour as msxml by converting
864 * line endings to \r\n and using indents as \t. The problem is that msxml
865 * only formats nodes that have a line ending. Using libxml we cannot
866 * reproduce behaviour exactly.
869 HRESULT node_get_xml(xmlnode *This, BOOL ensure_eol, BSTR *ret)
871 xmlBufferPtr xml_buf;
872 xmlNodePtr xmldecl;
873 int size;
875 if(!ret)
876 return E_INVALIDARG;
878 *ret = NULL;
880 xml_buf = xmlBufferCreate();
881 if(!xml_buf)
882 return E_OUTOFMEMORY;
884 xmldecl = xmldoc_unlink_xmldecl( This->node->doc );
886 size = xmlNodeDump(xml_buf, This->node->doc, This->node, 0, 1);
887 if(size > 0) {
888 const xmlChar *buf_content;
889 BSTR content;
891 /* Attribute Nodes return a space in front of their name */
892 buf_content = xmlBufferContent(xml_buf);
894 content = bstr_from_xmlChar(buf_content + (buf_content[0] == ' ' ? 1 : 0));
895 if(ensure_eol)
896 content = EnsureCorrectEOL(content);
898 *ret = content;
899 }else {
900 *ret = SysAllocStringLen(NULL, 0);
903 xmlBufferFree(xml_buf);
904 xmldoc_link_xmldecl( This->node->doc, xmldecl );
905 return *ret ? S_OK : E_OUTOFMEMORY;
908 #ifdef SONAME_LIBXSLT
910 /* duplicates xmlBufferWriteQuotedString() logic */
911 static void xml_write_quotedstring(xmlOutputBufferPtr buf, const xmlChar *string)
913 const xmlChar *cur, *base;
915 if (xmlStrchr(string, '\"'))
917 if (xmlStrchr(string, '\''))
919 xmlOutputBufferWrite(buf, 1, "\"");
920 base = cur = string;
922 while (*cur)
924 if (*cur == '"')
926 if (base != cur)
927 xmlOutputBufferWrite(buf, cur-base, (const char*)base);
928 xmlOutputBufferWrite(buf, 6, "&quot;");
929 cur++;
930 base = cur;
932 else
933 cur++;
935 if (base != cur)
936 xmlOutputBufferWrite(buf, cur-base, (const char*)base);
937 xmlOutputBufferWrite(buf, 1, "\"");
939 else
941 xmlOutputBufferWrite(buf, 1, "\'");
942 xmlOutputBufferWriteString(buf, (const char*)string);
943 xmlOutputBufferWrite(buf, 1, "\'");
946 else
948 xmlOutputBufferWrite(buf, 1, "\"");
949 xmlOutputBufferWriteString(buf, (const char*)string);
950 xmlOutputBufferWrite(buf, 1, "\"");
954 static int XMLCALL transform_to_stream_write(void *context, const char *buffer, int len)
956 DWORD written;
957 HRESULT hr = IStream_Write((IStream*)context, buffer, len, &written);
958 return hr == S_OK ? written : -1;
961 /* Output for method "text" */
962 static void transform_write_text(xmlDocPtr result, xsltStylesheetPtr style, xmlOutputBufferPtr output)
964 xmlNodePtr cur = result->children;
965 while (cur)
967 if (cur->type == XML_TEXT_NODE)
968 xmlOutputBufferWriteString(output, (const char*)cur->content);
970 /* skip to next node */
971 if (cur->children)
973 if ((cur->children->type != XML_ENTITY_DECL) &&
974 (cur->children->type != XML_ENTITY_REF_NODE) &&
975 (cur->children->type != XML_ENTITY_NODE))
977 cur = cur->children;
978 continue;
982 if (cur->next) {
983 cur = cur->next;
984 continue;
989 cur = cur->parent;
990 if (cur == NULL)
991 break;
992 if (cur == (xmlNodePtr) style->doc) {
993 cur = NULL;
994 break;
996 if (cur->next) {
997 cur = cur->next;
998 break;
1000 } while (cur);
1004 #undef XSLT_GET_IMPORT_PTR
1005 #define XSLT_GET_IMPORT_PTR(res, style, name) { \
1006 xsltStylesheetPtr st = style; \
1007 res = NULL; \
1008 while (st != NULL) { \
1009 if (st->name != NULL) { res = st->name; break; } \
1010 st = pxsltNextImport(st); \
1013 #undef XSLT_GET_IMPORT_INT
1014 #define XSLT_GET_IMPORT_INT(res, style, name) { \
1015 xsltStylesheetPtr st = style; \
1016 res = -1; \
1017 while (st != NULL) { \
1018 if (st->name != -1) { res = st->name; break; } \
1019 st = pxsltNextImport(st); \
1022 static void transform_write_xmldecl(xmlDocPtr result, xsltStylesheetPtr style, BOOL omit_encoding, xmlOutputBufferPtr output)
1024 int omit_xmldecl, standalone;
1026 XSLT_GET_IMPORT_INT(omit_xmldecl, style, omitXmlDeclaration);
1027 if (omit_xmldecl == 1) return;
1029 XSLT_GET_IMPORT_INT(standalone, style, standalone);
1031 xmlOutputBufferWriteString(output, "<?xml version=");
1032 if (result->version)
1034 xmlOutputBufferWriteString(output, "\"");
1035 xmlOutputBufferWriteString(output, (const char *)result->version);
1036 xmlOutputBufferWriteString(output, "\"");
1038 else
1039 xmlOutputBufferWriteString(output, "\"1.0\"");
1041 if (!omit_encoding)
1043 const xmlChar *encoding;
1045 /* default encoding is UTF-16 */
1046 XSLT_GET_IMPORT_PTR(encoding, style, encoding);
1047 xmlOutputBufferWriteString(output, " encoding=");
1048 xmlOutputBufferWriteString(output, "\"");
1049 xmlOutputBufferWriteString(output, encoding ? (const char *)encoding : "UTF-16");
1050 xmlOutputBufferWriteString(output, "\"");
1053 /* standalone attribute */
1054 if (standalone != -1)
1055 xmlOutputBufferWriteString(output, standalone == 0 ? " standalone=\"no\"" : " standalone=\"yes\"");
1057 xmlOutputBufferWriteString(output, "?>");
1060 static void htmldtd_dumpcontent(xmlOutputBufferPtr buf, xmlDocPtr doc)
1062 xmlDtdPtr cur = doc->intSubset;
1064 xmlOutputBufferWriteString(buf, "<!DOCTYPE ");
1065 xmlOutputBufferWriteString(buf, (const char *)cur->name);
1066 if (cur->ExternalID)
1068 xmlOutputBufferWriteString(buf, " PUBLIC ");
1069 xml_write_quotedstring(buf, cur->ExternalID);
1070 if (cur->SystemID)
1072 xmlOutputBufferWriteString(buf, " ");
1073 xml_write_quotedstring(buf, cur->SystemID);
1076 else if (cur->SystemID)
1078 xmlOutputBufferWriteString(buf, " SYSTEM ");
1079 xml_write_quotedstring(buf, cur->SystemID);
1081 xmlOutputBufferWriteString(buf, ">\n");
1084 /* Duplicates htmlDocContentDumpFormatOutput() the way we need it - doesn't add trailing newline. */
1085 static void htmldoc_dumpcontent(xmlOutputBufferPtr buf, xmlDocPtr doc, const char *encoding, int format)
1087 xmlElementType type;
1089 /* force HTML output */
1090 type = doc->type;
1091 doc->type = XML_HTML_DOCUMENT_NODE;
1092 if (doc->intSubset)
1093 htmldtd_dumpcontent(buf, doc);
1094 if (doc->children) {
1095 xmlNodePtr cur = doc->children;
1096 while (cur) {
1097 htmlNodeDumpFormatOutput(buf, doc, cur, encoding, format);
1098 cur = cur->next;
1101 doc->type = type;
1104 static inline BOOL transform_is_empty_resultdoc(xmlDocPtr result)
1106 return !result->children || ((result->children->type == XML_DTD_NODE) && !result->children->next);
1109 static inline BOOL transform_is_valid_method(xsltStylesheetPtr style)
1111 return !style->methodURI || !(style->method && xmlStrEqual(style->method, (const xmlChar *)"xhtml"));
1114 /* Helper to write transformation result to specified output buffer. */
1115 static HRESULT node_transform_write(xsltStylesheetPtr style, xmlDocPtr result, BOOL omit_encoding, const char *encoding, xmlOutputBufferPtr output)
1117 const xmlChar *method;
1118 int indent;
1120 if (!transform_is_valid_method(style))
1122 ERR("unknown output method\n");
1123 return E_FAIL;
1126 XSLT_GET_IMPORT_PTR(method, style, method)
1127 XSLT_GET_IMPORT_INT(indent, style, indent);
1129 if (!method && (result->type == XML_HTML_DOCUMENT_NODE))
1130 method = (const xmlChar *) "html";
1132 if (method && xmlStrEqual(method, (const xmlChar *)"html"))
1134 htmlSetMetaEncoding(result, (const xmlChar *)encoding);
1135 if (indent == -1)
1136 indent = 1;
1137 htmldoc_dumpcontent(output, result, (const char*)encoding, indent);
1139 else if (method && xmlStrEqual(method, (const xmlChar *)"xhtml"))
1141 htmlSetMetaEncoding(result, (const xmlChar *) encoding);
1142 htmlDocContentDumpOutput(output, result, encoding);
1144 else if (method && xmlStrEqual(method, (const xmlChar *)"text"))
1145 transform_write_text(result, style, output);
1146 else
1148 transform_write_xmldecl(result, style, omit_encoding, output);
1150 if (result->children)
1152 xmlNodePtr child = result->children;
1154 while (child)
1156 xmlNodeDumpOutput(output, result, child, 0, indent == 1, encoding);
1157 if (indent && ((child->type == XML_DTD_NODE) || ((child->type == XML_COMMENT_NODE) && child->next)))
1158 xmlOutputBufferWriteString(output, "\r\n");
1159 child = child->next;
1164 xmlOutputBufferFlush(output);
1165 return S_OK;
1168 /* For BSTR output is always UTF-16, without 'encoding' attribute */
1169 static HRESULT node_transform_write_to_bstr(xsltStylesheetPtr style, xmlDocPtr result, BSTR *str)
1171 HRESULT hr = S_OK;
1173 if (transform_is_empty_resultdoc(result))
1174 *str = SysAllocStringLen(NULL, 0);
1175 else
1177 xmlOutputBufferPtr output = xmlAllocOutputBuffer(xmlFindCharEncodingHandler("UTF-16"));
1178 const xmlChar *content;
1179 size_t len;
1181 *str = NULL;
1182 if (!output)
1183 return E_OUTOFMEMORY;
1185 hr = node_transform_write(style, result, TRUE, "UTF-16", output);
1186 #ifdef LIBXML2_NEW_BUFFER
1187 content = xmlBufContent(output->conv);
1188 len = xmlBufUse(output->conv);
1189 #else
1190 content = xmlBufferContent(output->conv);
1191 len = xmlBufferLength(output->conv);
1192 #endif
1193 /* UTF-16 encoder places UTF-16 bom, we don't need it for BSTR */
1194 content += sizeof(WCHAR);
1195 *str = SysAllocStringLen((WCHAR*)content, len/sizeof(WCHAR) - 1);
1196 xmlOutputBufferClose(output);
1199 return *str ? hr : E_OUTOFMEMORY;
1202 static HRESULT node_transform_write_to_stream(xsltStylesheetPtr style, xmlDocPtr result, IStream *stream)
1204 static const xmlChar *utf16 = (const xmlChar*)"UTF-16";
1205 xmlOutputBufferPtr output;
1206 const xmlChar *encoding;
1207 HRESULT hr;
1209 if (transform_is_empty_resultdoc(result))
1211 WARN("empty result document\n");
1212 return S_OK;
1215 if (style->methodURI && (!style->method || !xmlStrEqual(style->method, (const xmlChar *) "xhtml")))
1217 ERR("unknown output method\n");
1218 return E_FAIL;
1221 /* default encoding is UTF-16 */
1222 XSLT_GET_IMPORT_PTR(encoding, style, encoding);
1223 if (!encoding)
1224 encoding = utf16;
1226 output = xmlOutputBufferCreateIO(transform_to_stream_write, NULL, stream, xmlFindCharEncodingHandler((const char*)encoding));
1227 if (!output)
1228 return E_OUTOFMEMORY;
1230 hr = node_transform_write(style, result, FALSE, (const char*)encoding, output);
1231 xmlOutputBufferClose(output);
1232 return hr;
1235 #endif
1237 HRESULT node_transform_node_params(const xmlnode *This, IXMLDOMNode *stylesheet, BSTR *p,
1238 IStream *stream, const struct xslprocessor_params *params)
1240 #ifdef SONAME_LIBXSLT
1241 xsltStylesheetPtr xsltSS;
1242 HRESULT hr = S_OK;
1243 xmlnode *sheet;
1245 if (!libxslt_handle) return E_NOTIMPL;
1246 if (!stylesheet || !p) return E_INVALIDARG;
1248 *p = NULL;
1250 sheet = get_node_obj(stylesheet);
1251 if(!sheet) return E_FAIL;
1253 xsltSS = pxsltParseStylesheetDoc(sheet->node->doc);
1254 if(xsltSS)
1256 const char **xslparams = NULL;
1257 xmlDocPtr result;
1258 unsigned int i;
1260 /* convert our parameter list to libxml2 format */
1261 if (params && params->count)
1263 struct xslprocessor_par *par;
1265 i = 0;
1266 xslparams = heap_alloc((params->count*2 + 1)*sizeof(char*));
1267 LIST_FOR_EACH_ENTRY(par, &params->list, struct xslprocessor_par, entry)
1269 xslparams[i++] = (char*)xmlchar_from_wchar(par->name);
1270 xslparams[i++] = (char*)xmlchar_from_wchar(par->value);
1272 xslparams[i] = NULL;
1275 if (xslparams)
1277 xsltTransformContextPtr ctxt = pxsltNewTransformContext(xsltSS, This->node->doc);
1279 /* push parameters to user context */
1280 pxsltQuoteUserParams(ctxt, xslparams);
1281 result = pxsltApplyStylesheetUser(xsltSS, This->node->doc, NULL, NULL, NULL, ctxt);
1282 pxsltFreeTransformContext(ctxt);
1284 for (i = 0; i < params->count*2; i++)
1285 heap_free((char*)xslparams[i]);
1286 heap_free(xslparams);
1288 else
1289 result = pxsltApplyStylesheet(xsltSS, This->node->doc, NULL);
1291 if (result)
1293 if (stream)
1294 hr = node_transform_write_to_stream(xsltSS, result, stream);
1295 else
1296 hr = node_transform_write_to_bstr(xsltSS, result, p);
1297 xmlFreeDoc(result);
1299 /* libxslt "helpfully" frees the XML document the stylesheet was
1300 generated from, too */
1301 xsltSS->doc = NULL;
1302 pxsltFreeStylesheet(xsltSS);
1305 if(!*p) *p = SysAllocStringLen(NULL, 0);
1307 return hr;
1308 #else
1309 ERR_(winediag)("libxslt headers were not found at compile time. Expect problems.\n");
1311 return E_NOTIMPL;
1312 #endif
1315 HRESULT node_transform_node(const xmlnode *node, IXMLDOMNode *stylesheet, BSTR *p)
1317 return node_transform_node_params(node, stylesheet, p, NULL, NULL);
1320 HRESULT node_select_nodes(const xmlnode *This, BSTR query, IXMLDOMNodeList **nodes)
1322 xmlChar* str;
1323 HRESULT hr;
1325 if (!query || !nodes) return E_INVALIDARG;
1327 str = xmlchar_from_wchar(query);
1328 hr = create_selection(This->node, str, nodes);
1329 heap_free(str);
1331 return hr;
1334 HRESULT node_select_singlenode(const xmlnode *This, BSTR query, IXMLDOMNode **node)
1336 IXMLDOMNodeList *list;
1337 HRESULT hr;
1339 hr = node_select_nodes(This, query, &list);
1340 if (hr == S_OK)
1342 hr = IXMLDOMNodeList_nextNode(list, node);
1343 IXMLDOMNodeList_Release(list);
1345 return hr;
1348 HRESULT node_get_namespaceURI(xmlnode *This, BSTR *namespaceURI)
1350 xmlNsPtr ns = This->node->ns;
1352 if(!namespaceURI)
1353 return E_INVALIDARG;
1355 *namespaceURI = NULL;
1357 if (ns && ns->href)
1358 *namespaceURI = bstr_from_xmlChar(ns->href);
1360 TRACE("uri: %s\n", debugstr_w(*namespaceURI));
1362 return *namespaceURI ? S_OK : S_FALSE;
1365 HRESULT node_get_prefix(xmlnode *This, BSTR *prefix)
1367 xmlNsPtr ns = This->node->ns;
1369 if (!prefix) return E_INVALIDARG;
1371 *prefix = NULL;
1373 if (ns && ns->prefix)
1374 *prefix = bstr_from_xmlChar(ns->prefix);
1376 TRACE("prefix: %s\n", debugstr_w(*prefix));
1378 return *prefix ? S_OK : S_FALSE;
1381 HRESULT node_get_base_name(xmlnode *This, BSTR *name)
1383 if (!name) return E_INVALIDARG;
1385 *name = bstr_from_xmlChar(This->node->name);
1386 if (!*name) return E_OUTOFMEMORY;
1388 TRACE("returning %s\n", debugstr_w(*name));
1390 return S_OK;
1393 /* _private field holds a number of COM instances spawned from this libxml2 node */
1394 static void xmlnode_add_ref(xmlNodePtr node)
1396 if (node->type == XML_DOCUMENT_NODE) return;
1397 InterlockedIncrement((LONG*)&node->_private);
1400 static void xmlnode_release(xmlNodePtr node)
1402 if (node->type == XML_DOCUMENT_NODE) return;
1403 InterlockedDecrement((LONG*)&node->_private);
1406 void destroy_xmlnode(xmlnode *This)
1408 if(This->node)
1410 xmlnode_release(This->node);
1411 xmldoc_release(This->node->doc);
1415 void init_xmlnode(xmlnode *This, xmlNodePtr node, IXMLDOMNode *node_iface, dispex_static_data_t *dispex_data)
1417 if(node)
1419 xmlnode_add_ref(node);
1420 xmldoc_add_ref(node->doc);
1423 This->node = node;
1424 This->iface = node_iface;
1425 This->parent = NULL;
1427 init_dispex(&This->dispex, (IUnknown*)This->iface, dispex_data);
1430 typedef struct {
1431 xmlnode node;
1432 IXMLDOMNode IXMLDOMNode_iface;
1433 LONG ref;
1434 } unknode;
1436 static inline unknode *unknode_from_IXMLDOMNode(IXMLDOMNode *iface)
1438 return CONTAINING_RECORD(iface, unknode, IXMLDOMNode_iface);
1441 static HRESULT WINAPI unknode_QueryInterface(
1442 IXMLDOMNode *iface,
1443 REFIID riid,
1444 void** ppvObject )
1446 unknode *This = unknode_from_IXMLDOMNode( iface );
1448 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
1450 if (IsEqualGUID(riid, &IID_IUnknown)) {
1451 *ppvObject = iface;
1452 }else if (IsEqualGUID( riid, &IID_IDispatch) ||
1453 IsEqualGUID( riid, &IID_IXMLDOMNode)) {
1454 *ppvObject = &This->IXMLDOMNode_iface;
1455 }else if(node_query_interface(&This->node, riid, ppvObject)) {
1456 return *ppvObject ? S_OK : E_NOINTERFACE;
1457 }else {
1458 FIXME("interface %s not implemented\n", debugstr_guid(riid));
1459 *ppvObject = NULL;
1460 return E_NOINTERFACE;
1463 IUnknown_AddRef((IUnknown*)*ppvObject);
1464 return S_OK;
1467 static ULONG WINAPI unknode_AddRef(
1468 IXMLDOMNode *iface )
1470 unknode *This = unknode_from_IXMLDOMNode( iface );
1472 return InterlockedIncrement(&This->ref);
1475 static ULONG WINAPI unknode_Release(
1476 IXMLDOMNode *iface )
1478 unknode *This = unknode_from_IXMLDOMNode( iface );
1479 LONG ref;
1481 ref = InterlockedDecrement( &This->ref );
1482 if(!ref) {
1483 destroy_xmlnode(&This->node);
1484 heap_free(This);
1487 return ref;
1490 static HRESULT WINAPI unknode_GetTypeInfoCount(
1491 IXMLDOMNode *iface,
1492 UINT* pctinfo )
1494 unknode *This = unknode_from_IXMLDOMNode( iface );
1496 TRACE("(%p)->(%p)\n", This, pctinfo);
1498 *pctinfo = 1;
1500 return S_OK;
1503 static HRESULT WINAPI unknode_GetTypeInfo(
1504 IXMLDOMNode *iface,
1505 UINT iTInfo,
1506 LCID lcid,
1507 ITypeInfo** ppTInfo )
1509 unknode *This = unknode_from_IXMLDOMNode( iface );
1510 HRESULT hr;
1512 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1514 hr = get_typeinfo(IXMLDOMNode_tid, ppTInfo);
1516 return hr;
1519 static HRESULT WINAPI unknode_GetIDsOfNames(
1520 IXMLDOMNode *iface,
1521 REFIID riid,
1522 LPOLESTR* rgszNames,
1523 UINT cNames,
1524 LCID lcid,
1525 DISPID* rgDispId )
1527 unknode *This = unknode_from_IXMLDOMNode( iface );
1529 ITypeInfo *typeinfo;
1530 HRESULT hr;
1532 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1533 lcid, rgDispId);
1535 if(!rgszNames || cNames == 0 || !rgDispId)
1536 return E_INVALIDARG;
1538 hr = get_typeinfo(IXMLDOMNode_tid, &typeinfo);
1539 if(SUCCEEDED(hr))
1541 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1542 ITypeInfo_Release(typeinfo);
1545 return hr;
1548 static HRESULT WINAPI unknode_Invoke(
1549 IXMLDOMNode *iface,
1550 DISPID dispIdMember,
1551 REFIID riid,
1552 LCID lcid,
1553 WORD wFlags,
1554 DISPPARAMS* pDispParams,
1555 VARIANT* pVarResult,
1556 EXCEPINFO* pExcepInfo,
1557 UINT* puArgErr )
1559 unknode *This = unknode_from_IXMLDOMNode( iface );
1560 ITypeInfo *typeinfo;
1561 HRESULT hr;
1563 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1564 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1566 hr = get_typeinfo(IXMLDOMNode_tid, &typeinfo);
1567 if(SUCCEEDED(hr))
1569 hr = ITypeInfo_Invoke(typeinfo, &This->IXMLDOMNode_iface, dispIdMember, wFlags, pDispParams,
1570 pVarResult, pExcepInfo, puArgErr);
1571 ITypeInfo_Release(typeinfo);
1574 return hr;
1577 static HRESULT WINAPI unknode_get_nodeName(
1578 IXMLDOMNode *iface,
1579 BSTR* p )
1581 unknode *This = unknode_from_IXMLDOMNode( iface );
1583 FIXME("(%p)->(%p)\n", This, p);
1585 return node_get_nodeName(&This->node, p);
1588 static HRESULT WINAPI unknode_get_nodeValue(
1589 IXMLDOMNode *iface,
1590 VARIANT* value)
1592 unknode *This = unknode_from_IXMLDOMNode( iface );
1594 FIXME("(%p)->(%p)\n", This, value);
1596 if(!value)
1597 return E_INVALIDARG;
1599 V_VT(value) = VT_NULL;
1600 return S_FALSE;
1603 static HRESULT WINAPI unknode_put_nodeValue(
1604 IXMLDOMNode *iface,
1605 VARIANT value)
1607 unknode *This = unknode_from_IXMLDOMNode( iface );
1608 FIXME("(%p)->(v%d)\n", This, V_VT(&value));
1609 return E_FAIL;
1612 static HRESULT WINAPI unknode_get_nodeType(
1613 IXMLDOMNode *iface,
1614 DOMNodeType* domNodeType )
1616 unknode *This = unknode_from_IXMLDOMNode( iface );
1618 FIXME("(%p)->(%p)\n", This, domNodeType);
1620 switch (This->node.node->type)
1622 case XML_ELEMENT_NODE:
1623 case XML_ATTRIBUTE_NODE:
1624 case XML_TEXT_NODE:
1625 case XML_CDATA_SECTION_NODE:
1626 case XML_ENTITY_REF_NODE:
1627 case XML_ENTITY_NODE:
1628 case XML_PI_NODE:
1629 case XML_COMMENT_NODE:
1630 case XML_DOCUMENT_NODE:
1631 case XML_DOCUMENT_TYPE_NODE:
1632 case XML_DOCUMENT_FRAG_NODE:
1633 case XML_NOTATION_NODE:
1634 /* we only care about this set of types, libxml2 type values are
1635 exactly what we need */
1636 *domNodeType = (DOMNodeType)This->node.node->type;
1637 break;
1638 default:
1639 *domNodeType = NODE_INVALID;
1640 break;
1643 return S_OK;
1646 static HRESULT WINAPI unknode_get_parentNode(
1647 IXMLDOMNode *iface,
1648 IXMLDOMNode** parent )
1650 unknode *This = unknode_from_IXMLDOMNode( iface );
1651 FIXME("(%p)->(%p)\n", This, parent);
1652 if (!parent) return E_INVALIDARG;
1653 *parent = NULL;
1654 return S_FALSE;
1657 static HRESULT WINAPI unknode_get_childNodes(
1658 IXMLDOMNode *iface,
1659 IXMLDOMNodeList** outList)
1661 unknode *This = unknode_from_IXMLDOMNode( iface );
1663 TRACE("(%p)->(%p)\n", This, outList);
1665 return node_get_child_nodes(&This->node, outList);
1668 static HRESULT WINAPI unknode_get_firstChild(
1669 IXMLDOMNode *iface,
1670 IXMLDOMNode** domNode)
1672 unknode *This = unknode_from_IXMLDOMNode( iface );
1674 TRACE("(%p)->(%p)\n", This, domNode);
1676 return node_get_first_child(&This->node, domNode);
1679 static HRESULT WINAPI unknode_get_lastChild(
1680 IXMLDOMNode *iface,
1681 IXMLDOMNode** domNode)
1683 unknode *This = unknode_from_IXMLDOMNode( iface );
1685 TRACE("(%p)->(%p)\n", This, domNode);
1687 return node_get_last_child(&This->node, domNode);
1690 static HRESULT WINAPI unknode_get_previousSibling(
1691 IXMLDOMNode *iface,
1692 IXMLDOMNode** domNode)
1694 unknode *This = unknode_from_IXMLDOMNode( iface );
1696 TRACE("(%p)->(%p)\n", This, domNode);
1698 return node_get_previous_sibling(&This->node, domNode);
1701 static HRESULT WINAPI unknode_get_nextSibling(
1702 IXMLDOMNode *iface,
1703 IXMLDOMNode** domNode)
1705 unknode *This = unknode_from_IXMLDOMNode( iface );
1707 TRACE("(%p)->(%p)\n", This, domNode);
1709 return node_get_next_sibling(&This->node, domNode);
1712 static HRESULT WINAPI unknode_get_attributes(
1713 IXMLDOMNode *iface,
1714 IXMLDOMNamedNodeMap** attributeMap)
1716 unknode *This = unknode_from_IXMLDOMNode( iface );
1718 FIXME("(%p)->(%p)\n", This, attributeMap);
1720 return return_null_ptr((void**)attributeMap);
1723 static HRESULT WINAPI unknode_insertBefore(
1724 IXMLDOMNode *iface,
1725 IXMLDOMNode* newNode, VARIANT refChild,
1726 IXMLDOMNode** outOldNode)
1728 unknode *This = unknode_from_IXMLDOMNode( iface );
1730 FIXME("(%p)->(%p x%d %p)\n", This, newNode, V_VT(&refChild), outOldNode);
1732 return node_insert_before(&This->node, newNode, &refChild, outOldNode);
1735 static HRESULT WINAPI unknode_replaceChild(
1736 IXMLDOMNode *iface,
1737 IXMLDOMNode* newNode,
1738 IXMLDOMNode* oldNode,
1739 IXMLDOMNode** outOldNode)
1741 unknode *This = unknode_from_IXMLDOMNode( iface );
1743 FIXME("(%p)->(%p %p %p)\n", This, newNode, oldNode, outOldNode);
1745 return node_replace_child(&This->node, newNode, oldNode, outOldNode);
1748 static HRESULT WINAPI unknode_removeChild(
1749 IXMLDOMNode *iface,
1750 IXMLDOMNode* domNode, IXMLDOMNode** oldNode)
1752 unknode *This = unknode_from_IXMLDOMNode( iface );
1753 return node_remove_child(&This->node, domNode, oldNode);
1756 static HRESULT WINAPI unknode_appendChild(
1757 IXMLDOMNode *iface,
1758 IXMLDOMNode* newNode, IXMLDOMNode** outNewNode)
1760 unknode *This = unknode_from_IXMLDOMNode( iface );
1761 return node_append_child(&This->node, newNode, outNewNode);
1764 static HRESULT WINAPI unknode_hasChildNodes(
1765 IXMLDOMNode *iface,
1766 VARIANT_BOOL* pbool)
1768 unknode *This = unknode_from_IXMLDOMNode( iface );
1769 return node_has_childnodes(&This->node, pbool);
1772 static HRESULT WINAPI unknode_get_ownerDocument(
1773 IXMLDOMNode *iface,
1774 IXMLDOMDocument** domDocument)
1776 unknode *This = unknode_from_IXMLDOMNode( iface );
1777 return node_get_owner_doc(&This->node, domDocument);
1780 static HRESULT WINAPI unknode_cloneNode(
1781 IXMLDOMNode *iface,
1782 VARIANT_BOOL pbool, IXMLDOMNode** outNode)
1784 unknode *This = unknode_from_IXMLDOMNode( iface );
1785 return node_clone(&This->node, pbool, outNode );
1788 static HRESULT WINAPI unknode_get_nodeTypeString(
1789 IXMLDOMNode *iface,
1790 BSTR* p)
1792 unknode *This = unknode_from_IXMLDOMNode( iface );
1794 FIXME("(%p)->(%p)\n", This, p);
1796 return node_get_nodeName(&This->node, p);
1799 static HRESULT WINAPI unknode_get_text(
1800 IXMLDOMNode *iface,
1801 BSTR* p)
1803 unknode *This = unknode_from_IXMLDOMNode( iface );
1804 return node_get_text(&This->node, p);
1807 static HRESULT WINAPI unknode_put_text(
1808 IXMLDOMNode *iface,
1809 BSTR p)
1811 unknode *This = unknode_from_IXMLDOMNode( iface );
1812 return node_put_text(&This->node, p);
1815 static HRESULT WINAPI unknode_get_specified(
1816 IXMLDOMNode *iface,
1817 VARIANT_BOOL* isSpecified)
1819 unknode *This = unknode_from_IXMLDOMNode( iface );
1820 FIXME("(%p)->(%p) stub!\n", This, isSpecified);
1821 *isSpecified = VARIANT_TRUE;
1822 return S_OK;
1825 static HRESULT WINAPI unknode_get_definition(
1826 IXMLDOMNode *iface,
1827 IXMLDOMNode** definitionNode)
1829 unknode *This = unknode_from_IXMLDOMNode( iface );
1830 FIXME("(%p)->(%p)\n", This, definitionNode);
1831 return E_NOTIMPL;
1834 static HRESULT WINAPI unknode_get_nodeTypedValue(
1835 IXMLDOMNode *iface,
1836 VARIANT* var1)
1838 unknode *This = unknode_from_IXMLDOMNode( iface );
1839 FIXME("(%p)->(%p)\n", This, var1);
1840 return return_null_var(var1);
1843 static HRESULT WINAPI unknode_put_nodeTypedValue(
1844 IXMLDOMNode *iface,
1845 VARIANT typedValue)
1847 unknode *This = unknode_from_IXMLDOMNode( iface );
1848 FIXME("(%p)->(%s)\n", This, debugstr_variant(&typedValue));
1849 return E_NOTIMPL;
1852 static HRESULT WINAPI unknode_get_dataType(
1853 IXMLDOMNode *iface,
1854 VARIANT* var1)
1856 unknode *This = unknode_from_IXMLDOMNode( iface );
1857 TRACE("(%p)->(%p)\n", This, var1);
1858 return return_null_var(var1);
1861 static HRESULT WINAPI unknode_put_dataType(
1862 IXMLDOMNode *iface,
1863 BSTR p)
1865 unknode *This = unknode_from_IXMLDOMNode( iface );
1867 FIXME("(%p)->(%s)\n", This, debugstr_w(p));
1869 if(!p)
1870 return E_INVALIDARG;
1872 return E_FAIL;
1875 static HRESULT WINAPI unknode_get_xml(
1876 IXMLDOMNode *iface,
1877 BSTR* p)
1879 unknode *This = unknode_from_IXMLDOMNode( iface );
1881 FIXME("(%p)->(%p)\n", This, p);
1883 return node_get_xml(&This->node, FALSE, p);
1886 static HRESULT WINAPI unknode_transformNode(
1887 IXMLDOMNode *iface,
1888 IXMLDOMNode* domNode, BSTR* p)
1890 unknode *This = unknode_from_IXMLDOMNode( iface );
1891 return node_transform_node(&This->node, domNode, p);
1894 static HRESULT WINAPI unknode_selectNodes(
1895 IXMLDOMNode *iface,
1896 BSTR p, IXMLDOMNodeList** outList)
1898 unknode *This = unknode_from_IXMLDOMNode( iface );
1899 return node_select_nodes(&This->node, p, outList);
1902 static HRESULT WINAPI unknode_selectSingleNode(
1903 IXMLDOMNode *iface,
1904 BSTR p, IXMLDOMNode** outNode)
1906 unknode *This = unknode_from_IXMLDOMNode( iface );
1907 return node_select_singlenode(&This->node, p, outNode);
1910 static HRESULT WINAPI unknode_get_parsed(
1911 IXMLDOMNode *iface,
1912 VARIANT_BOOL* isParsed)
1914 unknode *This = unknode_from_IXMLDOMNode( iface );
1915 FIXME("(%p)->(%p) stub!\n", This, isParsed);
1916 *isParsed = VARIANT_TRUE;
1917 return S_OK;
1920 static HRESULT WINAPI unknode_get_namespaceURI(
1921 IXMLDOMNode *iface,
1922 BSTR* p)
1924 unknode *This = unknode_from_IXMLDOMNode( iface );
1925 TRACE("(%p)->(%p)\n", This, p);
1926 return node_get_namespaceURI(&This->node, p);
1929 static HRESULT WINAPI unknode_get_prefix(
1930 IXMLDOMNode *iface,
1931 BSTR* p)
1933 unknode *This = unknode_from_IXMLDOMNode( iface );
1934 return node_get_prefix(&This->node, p);
1937 static HRESULT WINAPI unknode_get_baseName(
1938 IXMLDOMNode *iface,
1939 BSTR* p)
1941 unknode *This = unknode_from_IXMLDOMNode( iface );
1942 return node_get_base_name(&This->node, p);
1945 static HRESULT WINAPI unknode_transformNodeToObject(
1946 IXMLDOMNode *iface,
1947 IXMLDOMNode* domNode, VARIANT var1)
1949 unknode *This = unknode_from_IXMLDOMNode( iface );
1950 FIXME("(%p)->(%p %s)\n", This, domNode, debugstr_variant(&var1));
1951 return E_NOTIMPL;
1954 static const struct IXMLDOMNodeVtbl unknode_vtbl =
1956 unknode_QueryInterface,
1957 unknode_AddRef,
1958 unknode_Release,
1959 unknode_GetTypeInfoCount,
1960 unknode_GetTypeInfo,
1961 unknode_GetIDsOfNames,
1962 unknode_Invoke,
1963 unknode_get_nodeName,
1964 unknode_get_nodeValue,
1965 unknode_put_nodeValue,
1966 unknode_get_nodeType,
1967 unknode_get_parentNode,
1968 unknode_get_childNodes,
1969 unknode_get_firstChild,
1970 unknode_get_lastChild,
1971 unknode_get_previousSibling,
1972 unknode_get_nextSibling,
1973 unknode_get_attributes,
1974 unknode_insertBefore,
1975 unknode_replaceChild,
1976 unknode_removeChild,
1977 unknode_appendChild,
1978 unknode_hasChildNodes,
1979 unknode_get_ownerDocument,
1980 unknode_cloneNode,
1981 unknode_get_nodeTypeString,
1982 unknode_get_text,
1983 unknode_put_text,
1984 unknode_get_specified,
1985 unknode_get_definition,
1986 unknode_get_nodeTypedValue,
1987 unknode_put_nodeTypedValue,
1988 unknode_get_dataType,
1989 unknode_put_dataType,
1990 unknode_get_xml,
1991 unknode_transformNode,
1992 unknode_selectNodes,
1993 unknode_selectSingleNode,
1994 unknode_get_parsed,
1995 unknode_get_namespaceURI,
1996 unknode_get_prefix,
1997 unknode_get_baseName,
1998 unknode_transformNodeToObject
2001 IXMLDOMNode *create_node( xmlNodePtr node )
2003 IUnknown *pUnk;
2004 IXMLDOMNode *ret;
2005 HRESULT hr;
2007 if ( !node )
2008 return NULL;
2010 TRACE("type %d\n", node->type);
2011 switch(node->type)
2013 case XML_ELEMENT_NODE:
2014 pUnk = create_element( node );
2015 break;
2016 case XML_ATTRIBUTE_NODE:
2017 pUnk = create_attribute( node );
2018 break;
2019 case XML_TEXT_NODE:
2020 pUnk = create_text( node );
2021 break;
2022 case XML_CDATA_SECTION_NODE:
2023 pUnk = create_cdata( node );
2024 break;
2025 case XML_ENTITY_REF_NODE:
2026 pUnk = create_doc_entity_ref( node );
2027 break;
2028 case XML_PI_NODE:
2029 pUnk = create_pi( node );
2030 break;
2031 case XML_COMMENT_NODE:
2032 pUnk = create_comment( node );
2033 break;
2034 case XML_DOCUMENT_NODE:
2035 pUnk = create_domdoc( node );
2036 break;
2037 case XML_DOCUMENT_FRAG_NODE:
2038 pUnk = create_doc_fragment( node );
2039 break;
2040 case XML_DTD_NODE:
2041 case XML_DOCUMENT_TYPE_NODE:
2042 pUnk = create_doc_type( node );
2043 break;
2044 case XML_ENTITY_NODE:
2045 case XML_NOTATION_NODE: {
2046 unknode *new_node;
2048 FIXME("only creating basic node for type %d\n", node->type);
2050 new_node = heap_alloc(sizeof(unknode));
2051 if(!new_node)
2052 return NULL;
2054 new_node->IXMLDOMNode_iface.lpVtbl = &unknode_vtbl;
2055 new_node->ref = 1;
2056 init_xmlnode(&new_node->node, node, &new_node->IXMLDOMNode_iface, NULL);
2057 pUnk = (IUnknown*)&new_node->IXMLDOMNode_iface;
2058 break;
2060 default:
2061 ERR("Called for unsupported node type %d\n", node->type);
2062 return NULL;
2065 hr = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMNode, (LPVOID*)&ret);
2066 IUnknown_Release(pUnk);
2067 if(FAILED(hr)) return NULL;
2068 return ret;
2070 #endif