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
33 #include "msxml_private.h"
36 # include <libxml/HTMLtree.h>
39 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
45 /* TODO: get rid of these and use the enum */
46 static const WCHAR szBinBase64[] = {'b','i','n','.','b','a','s','e','6','4',0};
47 static const WCHAR szString[] = {'s','t','r','i','n','g',0};
48 static const WCHAR szNumber[] = {'n','u','m','b','e','r',0};
49 static const WCHAR szInt[] = {'I','n','t',0};
50 static const WCHAR szFixed[] = {'F','i','x','e','d','.','1','4','.','4',0};
51 static const WCHAR szBoolean[] = {'B','o','o','l','e','a','n',0};
52 static const WCHAR szDateTime[] = {'d','a','t','e','T','i','m','e',0};
53 static const WCHAR szDateTimeTZ[] = {'d','a','t','e','T','i','m','e','.','t','z',0};
54 static const WCHAR szDate[] = {'D','a','t','e',0};
55 static const WCHAR szTime[] = {'T','i','m','e',0};
56 static const WCHAR szTimeTZ[] = {'T','i','m','e','.','t','z',0};
57 static const WCHAR szI1[] = {'i','1',0};
58 static const WCHAR szI2[] = {'i','2',0};
59 static const WCHAR szI4[] = {'i','4',0};
60 static const WCHAR szIU1[] = {'u','i','1',0};
61 static const WCHAR szIU2[] = {'u','i','2',0};
62 static const WCHAR szIU4[] = {'u','i','4',0};
63 static const WCHAR szR4[] = {'r','4',0};
64 static const WCHAR szR8[] = {'r','8',0};
65 static const WCHAR szFloat[] = {'f','l','o','a','t',0};
66 static const WCHAR szUUID[] = {'u','u','i','d',0};
67 static const WCHAR szBinHex[] = {'b','i','n','.','h','e','x',0};
69 static const IID IID_xmlnode = {0x4f2f4ba2,0xb822,0x11df,{0x8b,0x8a,0x68,0x50,0xdf,0xd7,0x20,0x85}};
71 xmlNodePtr xmlNodePtr_from_domnode( IXMLDOMNode *iface, xmlElementType type )
77 This = get_node_obj( iface );
78 if ( !This || !This->node )
80 if ( type && This->node->type != type )
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);
93 if(This->dispex.outer)
94 return dispex_query_interface(&This->dispex, riid, ppv);
99 xmlnode *get_node_obj(IXMLDOMNode *node)
104 hres = IXMLDOMNode_QueryInterface(node, &IID_xmlnode, (void**)&obj);
105 return SUCCEEDED(hres) ? obj : NULL;
108 static inline xmlnode *impl_from_IXMLDOMNode( IXMLDOMNode *iface )
110 return CONTAINING_RECORD(iface, xmlnode, IXMLDOMNode_iface);
113 HRESULT node_get_nodeName(xmlnode *This, BSTR *name)
118 *name = bstr_from_xmlChar(This->node->name);
125 HRESULT node_get_content(xmlnode *This, VARIANT *value)
132 content = xmlNodeGetContent(This->node);
133 V_VT(value) = VT_BSTR;
134 V_BSTR(value) = bstr_from_xmlChar( content );
137 TRACE("%p returned %s\n", This, debugstr_w(V_BSTR(value)));
141 HRESULT node_set_content(xmlnode *This, LPCWSTR value)
145 TRACE("(%p)->(%s)\n", This, debugstr_w(value));
146 str = xmlChar_from_wchar(value);
148 return E_OUTOFMEMORY;
150 xmlNodeSetContent(This->node, str);
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);
162 return E_OUTOFMEMORY;
164 escaped = xmlEncodeSpecialChars(NULL, str);
168 return E_OUTOFMEMORY;
171 xmlNodeSetContent(This->node, escaped);
179 HRESULT node_put_value(xmlnode *This, VARIANT *value)
181 VARIANT string_value;
184 VariantInit(&string_value);
185 hr = VariantChangeType(&string_value, value, 0, VT_BSTR);
187 WARN("Couldn't convert to VT_BSTR\n");
191 hr = node_set_content(This, V_BSTR(&string_value));
192 VariantClear(&string_value);
197 HRESULT node_put_value_escaped(xmlnode *This, VARIANT *value)
199 VARIANT string_value;
202 VariantInit(&string_value);
203 hr = VariantChangeType(&string_value, value, 0, VT_BSTR);
205 WARN("Couldn't convert to VT_BSTR\n");
209 hr = node_set_content_escaped(This, V_BSTR(&string_value));
210 VariantClear(&string_value);
215 static HRESULT get_node(
221 TRACE("(%p)->(%s %p %p)\n", This, name, node, out );
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 );
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)
246 *ret = create_children_nodelist(This->node);
248 return E_OUTOFMEMORY;
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,
276 xmlNodePtr before_node, new_child_node;
277 IXMLDOMNode *before = NULL;
284 node_obj = get_node_obj(new_child);
286 FIXME("newChild is not our node implementation\n");
290 switch(V_VT(ref_child))
298 hr = IUnknown_QueryInterface(V_UNKNOWN(ref_child), &IID_IXMLDOMNode, (LPVOID)&before);
299 if(FAILED(hr)) return hr;
303 FIXME("refChild var type %x\n", V_VT(ref_child));
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);
316 node_obj = get_node_obj(before);
317 IXMLDOMNode_Release(before);
319 FIXME("before node is not our node implementation\n");
323 before_node = node_obj->node;
324 xmlAddPrevSibling(before_node, new_child_node);
328 xmlAddChild(This->node, new_child_node);
332 IXMLDOMNode_AddRef(new_child);
340 HRESULT node_replace_child(xmlnode *This, IXMLDOMNode *newChild, IXMLDOMNode *oldChild,
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)
355 old_child = get_node_obj(oldChild);
357 FIXME("oldChild is not our node implementation\n");
361 if(old_child->node->parent != This->node)
363 WARN("childNode %p is not a child of %p\n", oldChild, This);
367 new_child = get_node_obj(newChild);
369 FIXME("newChild is not our node implementation\n");
373 my_ancestor = This->node;
376 if(my_ancestor == new_child->node)
378 WARN("tried to create loop\n");
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);
397 IXMLDOMNode_AddRef(oldChild);
404 HRESULT node_remove_child(xmlnode *This, IXMLDOMNode* child, IXMLDOMNode** oldChild)
408 if(!child) return E_INVALIDARG;
413 child_node = get_node_obj(child);
415 FIXME("childNode is not our node implementation\n");
419 if(child_node->node->parent != This->node)
421 WARN("childNode %p is not a child of %p\n", child, This);
425 xmlUnlinkNode(child_node->node);
429 IXMLDOMNode_AddRef(child);
436 HRESULT node_append_child(xmlnode *This, IXMLDOMNode *child, IXMLDOMNode **outChild)
442 hr = IXMLDOMNode_get_nodeType(child, &type);
443 if(FAILED(hr) || type == NODE_ATTRIBUTE) {
444 if (outChild) *outChild = NULL;
449 return IXMLDOMNode_insertBefore(This->iface, child, var, outChild);
452 HRESULT node_has_childnodes(const xmlnode *This, VARIANT_BOOL *ret)
454 if (!ret) return E_INVALIDARG;
456 if (!This->node->children)
458 *ret = VARIANT_FALSE;
466 HRESULT node_get_owner_doc(const xmlnode *This, IXMLDOMDocument **doc)
468 return get_domdoc_from_xmldoc(This->node->doc, (IXMLDOMDocument3**)doc);
471 HRESULT node_clone(xmlnode *This, VARIANT_BOOL deep, IXMLDOMNode **cloneNode)
476 if(!cloneNode) return E_INVALIDARG;
478 clone = xmlCopyNode(This->node, deep ? 1 : 2);
481 clone->doc = This->node->doc;
482 xmldoc_add_orphan(clone->doc, clone);
484 node = create_node(clone);
487 ERR("Copy failed\n");
495 ERR("Copy failed\n");
502 static inline xmlChar* trim_whitespace(xmlChar* str)
510 while (*ret && isspace(*ret))
512 len = xmlStrlen(ret);
514 while (isspace(ret[len-1])) --len;
516 ret = xmlStrndup(ret, len);
521 static xmlChar* do_get_text(xmlNodePtr node)
525 BOOL preserving = is_preserving_whitespace(node);
529 str = xmlNodeGetContent(node);
533 xmlElementType prev_type = XML_TEXT_NODE;
535 str = xmlStrdup(BAD_CAST "");
536 for (child = node->children; child != NULL; child = child->next)
540 case XML_ELEMENT_NODE:
541 tmp = do_get_text(child);
544 case XML_CDATA_SECTION_NODE:
545 case XML_ENTITY_REF_NODE:
546 case XML_ENTITY_NODE:
547 tmp = xmlNodeGetContent(child);
558 if (prev_type == XML_ELEMENT_NODE && child->type == XML_ELEMENT_NODE)
559 str = xmlStrcat(str, BAD_CAST " ");
560 str = xmlStrcat(str, tmp);
561 prev_type = child->type;
570 case XML_ELEMENT_NODE:
572 case XML_ENTITY_REF_NODE:
573 case XML_ENTITY_NODE:
574 case XML_DOCUMENT_NODE:
575 case XML_DOCUMENT_FRAG_NODE:
577 str = trim_whitespace(str);
586 HRESULT node_get_text(const xmlnode *This, BSTR *text)
591 if (!text) return E_INVALIDARG;
593 content = do_get_text(This->node);
596 str = bstr_from_xmlChar(content);
600 /* Always return a string. */
601 if (!str) str = SysAllocStringLen( NULL, 0 );
603 TRACE("%p %s\n", This, debugstr_w(str) );
609 HRESULT node_put_text(xmlnode *This, BSTR text)
613 TRACE("(%p)->(%s)\n", This, debugstr_w(text));
615 str = xmlChar_from_wchar(text);
617 /* Escape the string. */
618 str2 = xmlEncodeEntitiesReentrant(This->node->doc, str);
621 xmlNodeSetContent(This->node, str2);
627 static inline BYTE hex_to_byte(xmlChar c)
629 if(c <= '9') return c-'0';
630 if(c <= 'F') return c-'A'+10;
634 static inline BYTE base64_to_byte(xmlChar c)
636 if(c == '+') return 62;
637 if(c == '/') return 63;
638 if(c <= '9') return c-'0'+52;
639 if(c <= 'Z') return c-'A';
643 /* TODO: phasing this version out */
644 static inline HRESULT VARIANT_from_xmlChar(xmlChar *str, VARIANT *v, BSTR type)
646 if(!type || !lstrcmpiW(type, szString) ||
647 !lstrcmpiW(type, szNumber) || !lstrcmpiW(type, szUUID))
650 V_BSTR(v) = bstr_from_xmlChar(str);
653 return E_OUTOFMEMORY;
655 else if(!lstrcmpiW(type, szDateTime) || !lstrcmpiW(type, szDateTimeTZ) ||
656 !lstrcmpiW(type, szDate) || !lstrcmpiW(type, szTime) ||
657 !lstrcmpiW(type, szTimeTZ))
667 st.wDayOfWeek = st.wHour = st.wMinute = st.wSecond = st.wMilliseconds = 0;
669 V_VT(&src) = VT_BSTR;
670 V_BSTR(&src) = bstr_from_xmlChar(str);
673 return E_OUTOFMEMORY;
676 e = p + SysStringLen(V_BSTR(&src));
678 if(p+4<e && *(p+4)=='-') /* parse date (yyyy-mm-dd) */
681 st.wMonth = atoiW(p+5);
682 st.wDay = atoiW(p+8);
688 if(p+2<e && *(p+2)==':') /* parse time (hh:mm:ss.?) */
691 st.wMinute = atoiW(p+3);
692 st.wSecond = atoiW(p+6);
698 while(isdigitW(*p)) p++;
702 SystemTimeToVariantTime(&st, &date);
706 if(*p == '+') /* parse timezone offset (+hh:mm) */
707 V_DATE(v) += (DOUBLE)atoiW(p+1)/24 + (DOUBLE)atoiW(p+4)/1440;
708 else if(*p == '-') /* parse timezone offset (-hh:mm) */
709 V_DATE(v) -= (DOUBLE)atoiW(p+1)/24 + (DOUBLE)atoiW(p+4)/1440;
713 else if(!lstrcmpiW(type, szBinHex))
718 len = xmlStrlen(str)/2;
722 V_VT(v) = (VT_ARRAY|VT_UI1);
723 V_ARRAY(v) = SafeArrayCreate(VT_UI1, 1, &sab);
726 return E_OUTOFMEMORY;
729 ((BYTE*)V_ARRAY(v)->pvData)[i] = (hex_to_byte(str[2*i])<<4)
730 + hex_to_byte(str[2*i+1]);
732 else if(!lstrcmpiW(type, szBinBase64))
737 len = xmlStrlen(str);
738 if(str[len-2] == '=') i = 2;
739 else if(str[len-1] == '=') i = 1;
743 sab.cElements = len/4*3-i;
745 V_VT(v) = (VT_ARRAY|VT_UI1);
746 V_ARRAY(v) = SafeArrayCreate(VT_UI1, 1, &sab);
749 return E_OUTOFMEMORY;
751 for(i=0; i<len/4; i++)
753 ((BYTE*)V_ARRAY(v)->pvData)[3*i] = (base64_to_byte(str[4*i])<<2)
754 + (base64_to_byte(str[4*i+1])>>4);
755 if(3*i+1 < sab.cElements)
756 ((BYTE*)V_ARRAY(v)->pvData)[3*i+1] = (base64_to_byte(str[4*i+1])<<4)
757 + (base64_to_byte(str[4*i+2])>>2);
758 if(3*i+2 < sab.cElements)
759 ((BYTE*)V_ARRAY(v)->pvData)[3*i+2] = (base64_to_byte(str[4*i+2])<<6)
760 + base64_to_byte(str[4*i+3]);
768 if(!lstrcmpiW(type, szInt) || !lstrcmpiW(type, szI4))
770 else if(!lstrcmpiW(type, szFixed))
772 else if(!lstrcmpiW(type, szBoolean))
774 else if(!lstrcmpiW(type, szI1))
776 else if(!lstrcmpiW(type, szI2))
778 else if(!lstrcmpiW(type, szIU1))
780 else if(!lstrcmpiW(type, szIU2))
782 else if(!lstrcmpiW(type, szIU4))
784 else if(!lstrcmpiW(type, szR4))
786 else if(!lstrcmpiW(type, szR8) || !lstrcmpiW(type, szFloat))
790 FIXME("Type handling not yet implemented\n");
794 V_VT(&src) = VT_BSTR;
795 V_BSTR(&src) = bstr_from_xmlChar(str);
798 return E_OUTOFMEMORY;
800 hres = VariantChangeTypeEx(v, &src, MAKELCID(MAKELANGID(
801 LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT),0, V_VT(v));
809 BSTR EnsureCorrectEOL(BSTR sInput)
816 nLen = SysStringLen(sInput);
817 /* Count line endings */
818 for(i=0; i < nLen; i++)
820 if(sInput[i] == '\n')
824 TRACE("len=%d, num=%d\n", nLen, nNum);
826 /* Add linefeed as needed */
830 sNew = SysAllocStringLen(NULL, nLen + nNum+1);
831 for(i=0; i < nLen; i++)
833 if(sInput[i] == '\n')
835 sNew[i+nPlace] = '\r';
838 sNew[i+nPlace] = sInput[i];
841 SysFreeString(sInput);
848 TRACE("len %d\n", SysStringLen(sNew));
853 /* Removes encoding information and last character (nullbyte) */
854 static BSTR EnsureNoEncoding(BSTR sInput)
856 static const WCHAR wszEncoding[] = {'e','n','c','o','d','i','n','g','='};
861 while(*pBeg != '\n' && memcmp(pBeg, wszEncoding, sizeof(wszEncoding)))
866 SysReAllocStringLen(&sInput, sInput, SysStringLen(sInput)-1);
871 pEnd = pBeg + sizeof(wszEncoding)/sizeof(WCHAR) + 2;
872 while(*pEnd != '\"') pEnd++;
875 sNew = SysAllocStringLen(NULL,
876 pBeg-sInput + SysStringLen(sInput)-(pEnd-sInput)-1);
877 memcpy(sNew, sInput, (pBeg-sInput)*sizeof(WCHAR));
878 memcpy(&sNew[pBeg-sInput], pEnd, (SysStringLen(sInput)-(pEnd-sInput)-1)*sizeof(WCHAR));
880 SysFreeString(sInput);
885 * We are trying to replicate the same behaviour as msxml by converting
886 * line endings to \r\n and using indents as \t. The problem is that msxml
887 * only formats nodes that have a line ending. Using libxml we cannot
888 * reproduce behaviour exactly.
891 HRESULT node_get_xml(xmlnode *This, BOOL ensure_eol, BOOL ensure_no_encoding, BSTR *ret)
893 xmlBufferPtr xml_buf;
902 xml_buf = xmlBufferCreate();
904 return E_OUTOFMEMORY;
906 xmldecl = xmldoc_unlink_xmldecl( This->node->doc );
908 size = xmlNodeDump(xml_buf, This->node->doc, This->node, 0, 1);
910 const xmlChar *buf_content;
913 /* Attribute Nodes return a space in front of their name */
914 buf_content = xmlBufferContent(xml_buf);
916 content = bstr_from_xmlChar(buf_content + (buf_content[0] == ' ' ? 1 : 0));
918 content = EnsureCorrectEOL(content);
919 if(ensure_no_encoding)
920 content = EnsureNoEncoding(content);
924 *ret = SysAllocStringLen(NULL, 0);
927 xmlBufferFree(xml_buf);
928 xmldoc_link_xmldecl( This->node->doc, xmldecl );
929 return *ret ? S_OK : E_OUTOFMEMORY;
932 static HRESULT WINAPI xmlnode_transformNode(
934 IXMLDOMNode* styleSheet,
937 #ifdef SONAME_LIBXSLT
938 xmlnode *This = impl_from_IXMLDOMNode( iface );
939 xmlnode *pStyleSheet = NULL;
940 xsltStylesheetPtr xsltSS = NULL;
941 xmlDocPtr result = NULL;
943 TRACE("(%p)->(%p %p)\n", This, styleSheet, xmlString);
947 if(!styleSheet || !xmlString)
952 pStyleSheet = get_node_obj(styleSheet);
954 FIXME("styleSheet is not our xmlnode implementation\n");
958 xsltSS = pxsltParseStylesheetDoc( pStyleSheet->node->doc);
961 result = pxsltApplyStylesheet(xsltSS, This->node->doc, NULL);
964 const xmlChar *pContent;
966 if(result->type == XML_HTML_DOCUMENT_NODE)
968 xmlOutputBufferPtr pOutput = xmlAllocOutputBuffer(NULL);
971 htmlDocContentDumpOutput(pOutput, result->doc, NULL);
972 pContent = xmlBufferContent(pOutput->buffer);
973 *xmlString = bstr_from_xmlChar(pContent);
974 xmlOutputBufferClose(pOutput);
979 xmlBufferPtr pXmlBuf;
982 pXmlBuf = xmlBufferCreate();
985 nSize = xmlNodeDump(pXmlBuf, NULL, (xmlNodePtr)result, 0, 0);
988 pContent = xmlBufferContent(pXmlBuf);
989 *xmlString = bstr_from_xmlChar(pContent);
991 xmlBufferFree(pXmlBuf);
996 /* libxslt "helpfully" frees the XML document the stylesheet was
997 generated from, too */
999 pxsltFreeStylesheet(xsltSS);
1002 if(*xmlString == NULL)
1003 *xmlString = SysAllocStringLen(NULL, 0);
1007 FIXME("libxslt headers were not found at compile time\n");
1012 static HRESULT WINAPI xmlnode_selectNodes(
1015 IXMLDOMNodeList** resultList)
1017 xmlnode *This = impl_from_IXMLDOMNode( iface );
1021 TRACE("(%p)->(%s %p)\n", This, debugstr_w(queryString), resultList );
1023 if (!queryString || !resultList) return E_INVALIDARG;
1025 str = xmlChar_from_wchar(queryString);
1026 hr = queryresult_create(This->node, str, resultList);
1032 static HRESULT WINAPI xmlnode_selectSingleNode(
1035 IXMLDOMNode** resultNode)
1037 xmlnode *This = impl_from_IXMLDOMNode( iface );
1038 IXMLDOMNodeList *list;
1041 TRACE("(%p)->(%s %p)\n", This, debugstr_w(queryString), resultNode );
1043 r = IXMLDOMNode_selectNodes(This->iface, queryString, &list);
1046 r = IXMLDOMNodeList_nextNode(list, resultNode);
1047 IXMLDOMNodeList_Release(list);
1052 HRESULT node_get_namespaceURI(xmlnode *This, BSTR *namespaceURI)
1057 return E_INVALIDARG;
1059 *namespaceURI = NULL;
1061 if ((ns = xmlGetNsList(This->node->doc, This->node)))
1063 if (ns[0]->href) *namespaceURI = bstr_from_xmlChar( ns[0]->href );
1067 TRACE("uri: %s\n", debugstr_w(*namespaceURI));
1069 return *namespaceURI ? S_OK : S_FALSE;
1072 HRESULT node_get_prefix(xmlnode *This, BSTR *prefix)
1076 if (!prefix) return E_INVALIDARG;
1080 if ((ns = xmlGetNsList(This->node->doc, This->node)))
1082 if (ns[0]->prefix) *prefix = bstr_from_xmlChar( ns[0]->prefix );
1086 TRACE("prefix: %s\n", debugstr_w(*prefix));
1088 return *prefix ? S_OK : S_FALSE;
1091 HRESULT node_get_base_name(xmlnode *This, BSTR *name)
1093 if (!name) return E_INVALIDARG;
1095 *name = bstr_from_xmlChar(This->node->name);
1096 if (!*name) return E_OUTOFMEMORY;
1098 TRACE("returning %s\n", debugstr_w(*name));
1103 static const struct IXMLDOMNodeVtbl xmlnode_vtbl =
1140 xmlnode_transformNode,
1141 xmlnode_selectNodes,
1142 xmlnode_selectSingleNode
1145 void destroy_xmlnode(xmlnode *This)
1148 xmldoc_release(This->node->doc);
1151 void init_xmlnode(xmlnode *This, xmlNodePtr node, IXMLDOMNode *node_iface, dispex_static_data_t *dispex_data)
1154 xmldoc_add_ref( node->doc );
1156 This->IXMLDOMNode_iface.lpVtbl = &xmlnode_vtbl;
1158 This->iface = node_iface;
1161 init_dispex(&This->dispex, (IUnknown*)This->iface, dispex_data);
1163 This->dispex.outer = NULL;
1168 IXMLDOMNode IXMLDOMNode_iface;
1172 static inline unknode *unknode_from_IXMLDOMNode(IXMLDOMNode *iface)
1174 return CONTAINING_RECORD(iface, unknode, IXMLDOMNode_iface);
1177 static HRESULT WINAPI unknode_QueryInterface(
1182 unknode *This = unknode_from_IXMLDOMNode( iface );
1184 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
1186 if (IsEqualGUID(riid, &IID_IUnknown)) {
1188 }else if (IsEqualGUID( riid, &IID_IDispatch) ||
1189 IsEqualGUID( riid, &IID_IXMLDOMNode)) {
1190 *ppvObject = &This->IXMLDOMNode_iface;
1191 }else if(node_query_interface(&This->node, riid, ppvObject)) {
1192 return *ppvObject ? S_OK : E_NOINTERFACE;
1194 FIXME("interface %s not implemented\n", debugstr_guid(riid));
1196 return E_NOINTERFACE;
1199 IUnknown_AddRef((IUnknown*)*ppvObject);
1203 static ULONG WINAPI unknode_AddRef(
1204 IXMLDOMNode *iface )
1206 unknode *This = unknode_from_IXMLDOMNode( iface );
1208 return InterlockedIncrement(&This->ref);
1211 static ULONG WINAPI unknode_Release(
1212 IXMLDOMNode *iface )
1214 unknode *This = unknode_from_IXMLDOMNode( iface );
1217 ref = InterlockedDecrement( &This->ref );
1219 destroy_xmlnode(&This->node);
1226 static HRESULT WINAPI unknode_GetTypeInfoCount(
1230 unknode *This = unknode_from_IXMLDOMNode( iface );
1232 TRACE("(%p)->(%p)\n", This, pctinfo);
1239 static HRESULT WINAPI unknode_GetTypeInfo(
1243 ITypeInfo** ppTInfo )
1245 unknode *This = unknode_from_IXMLDOMNode( iface );
1248 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1250 hr = get_typeinfo(IXMLDOMNode_tid, ppTInfo);
1255 static HRESULT WINAPI unknode_GetIDsOfNames(
1258 LPOLESTR* rgszNames,
1263 unknode *This = unknode_from_IXMLDOMNode( iface );
1265 ITypeInfo *typeinfo;
1268 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1271 if(!rgszNames || cNames == 0 || !rgDispId)
1272 return E_INVALIDARG;
1274 hr = get_typeinfo(IXMLDOMNode_tid, &typeinfo);
1277 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1278 ITypeInfo_Release(typeinfo);
1284 static HRESULT WINAPI unknode_Invoke(
1286 DISPID dispIdMember,
1290 DISPPARAMS* pDispParams,
1291 VARIANT* pVarResult,
1292 EXCEPINFO* pExcepInfo,
1295 unknode *This = unknode_from_IXMLDOMNode( iface );
1296 ITypeInfo *typeinfo;
1299 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1300 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1302 hr = get_typeinfo(IXMLDOMNode_tid, &typeinfo);
1305 hr = ITypeInfo_Invoke(typeinfo, &This->IXMLDOMNode_iface, dispIdMember, wFlags, pDispParams,
1306 pVarResult, pExcepInfo, puArgErr);
1307 ITypeInfo_Release(typeinfo);
1313 static HRESULT WINAPI unknode_get_nodeName(
1317 unknode *This = unknode_from_IXMLDOMNode( iface );
1319 FIXME("(%p)->(%p)\n", This, p);
1321 return node_get_nodeName(&This->node, p);
1324 static HRESULT WINAPI unknode_get_nodeValue(
1328 unknode *This = unknode_from_IXMLDOMNode( iface );
1330 FIXME("(%p)->(%p)\n", This, value);
1333 return E_INVALIDARG;
1335 V_VT(value) = VT_NULL;
1339 static HRESULT WINAPI unknode_put_nodeValue(
1343 unknode *This = unknode_from_IXMLDOMNode( iface );
1344 FIXME("(%p)->(v%d)\n", This, V_VT(&value));
1348 static HRESULT WINAPI unknode_get_nodeType(
1350 DOMNodeType* domNodeType )
1352 unknode *This = unknode_from_IXMLDOMNode( iface );
1354 FIXME("(%p)->(%p)\n", This, domNodeType);
1356 *domNodeType = This->node.node->type;
1360 static HRESULT WINAPI unknode_get_parentNode(
1362 IXMLDOMNode** parent )
1364 unknode *This = unknode_from_IXMLDOMNode( iface );
1365 FIXME("(%p)->(%p)\n", This, parent);
1366 if (!parent) return E_INVALIDARG;
1371 static HRESULT WINAPI unknode_get_childNodes(
1373 IXMLDOMNodeList** outList)
1375 unknode *This = unknode_from_IXMLDOMNode( iface );
1377 TRACE("(%p)->(%p)\n", This, outList);
1379 return node_get_child_nodes(&This->node, outList);
1382 static HRESULT WINAPI unknode_get_firstChild(
1384 IXMLDOMNode** domNode)
1386 unknode *This = unknode_from_IXMLDOMNode( iface );
1388 TRACE("(%p)->(%p)\n", This, domNode);
1390 return node_get_first_child(&This->node, domNode);
1393 static HRESULT WINAPI unknode_get_lastChild(
1395 IXMLDOMNode** domNode)
1397 unknode *This = unknode_from_IXMLDOMNode( iface );
1399 TRACE("(%p)->(%p)\n", This, domNode);
1401 return node_get_last_child(&This->node, domNode);
1404 static HRESULT WINAPI unknode_get_previousSibling(
1406 IXMLDOMNode** domNode)
1408 unknode *This = unknode_from_IXMLDOMNode( iface );
1410 TRACE("(%p)->(%p)\n", This, domNode);
1412 return node_get_previous_sibling(&This->node, domNode);
1415 static HRESULT WINAPI unknode_get_nextSibling(
1417 IXMLDOMNode** domNode)
1419 unknode *This = unknode_from_IXMLDOMNode( iface );
1421 TRACE("(%p)->(%p)\n", This, domNode);
1423 return node_get_next_sibling(&This->node, domNode);
1426 static HRESULT WINAPI unknode_get_attributes(
1428 IXMLDOMNamedNodeMap** attributeMap)
1430 unknode *This = unknode_from_IXMLDOMNode( iface );
1432 FIXME("(%p)->(%p)\n", This, attributeMap);
1434 return return_null_ptr((void**)attributeMap);
1437 static HRESULT WINAPI unknode_insertBefore(
1439 IXMLDOMNode* newNode, VARIANT refChild,
1440 IXMLDOMNode** outOldNode)
1442 unknode *This = unknode_from_IXMLDOMNode( iface );
1444 FIXME("(%p)->(%p x%d %p)\n", This, newNode, V_VT(&refChild), outOldNode);
1446 return node_insert_before(&This->node, newNode, &refChild, outOldNode);
1449 static HRESULT WINAPI unknode_replaceChild(
1451 IXMLDOMNode* newNode,
1452 IXMLDOMNode* oldNode,
1453 IXMLDOMNode** outOldNode)
1455 unknode *This = unknode_from_IXMLDOMNode( iface );
1457 FIXME("(%p)->(%p %p %p)\n", This, newNode, oldNode, outOldNode);
1459 return node_replace_child(&This->node, newNode, oldNode, outOldNode);
1462 static HRESULT WINAPI unknode_removeChild(
1464 IXMLDOMNode* domNode, IXMLDOMNode** oldNode)
1466 unknode *This = unknode_from_IXMLDOMNode( iface );
1467 return node_remove_child(&This->node, domNode, oldNode);
1470 static HRESULT WINAPI unknode_appendChild(
1472 IXMLDOMNode* newNode, IXMLDOMNode** outNewNode)
1474 unknode *This = unknode_from_IXMLDOMNode( iface );
1475 return node_append_child(&This->node, newNode, outNewNode);
1478 static HRESULT WINAPI unknode_hasChildNodes(
1480 VARIANT_BOOL* pbool)
1482 unknode *This = unknode_from_IXMLDOMNode( iface );
1483 return node_has_childnodes(&This->node, pbool);
1486 static HRESULT WINAPI unknode_get_ownerDocument(
1488 IXMLDOMDocument** domDocument)
1490 unknode *This = unknode_from_IXMLDOMNode( iface );
1491 return node_get_owner_doc(&This->node, domDocument);
1494 static HRESULT WINAPI unknode_cloneNode(
1496 VARIANT_BOOL pbool, IXMLDOMNode** outNode)
1498 unknode *This = unknode_from_IXMLDOMNode( iface );
1499 return IXMLDOMNode_cloneNode( &This->node.IXMLDOMNode_iface, pbool, outNode );
1502 static HRESULT WINAPI unknode_get_nodeTypeString(
1506 unknode *This = unknode_from_IXMLDOMNode( iface );
1508 FIXME("(%p)->(%p)\n", This, p);
1510 return node_get_nodeName(&This->node, p);
1513 static HRESULT WINAPI unknode_get_text(
1517 unknode *This = unknode_from_IXMLDOMNode( iface );
1518 return node_get_text(&This->node, p);
1521 static HRESULT WINAPI unknode_put_text(
1525 unknode *This = unknode_from_IXMLDOMNode( iface );
1526 return IXMLDOMNode_put_text( &This->node.IXMLDOMNode_iface, p );
1529 static HRESULT WINAPI unknode_get_specified(
1531 VARIANT_BOOL* isSpecified)
1533 unknode *This = unknode_from_IXMLDOMNode( iface );
1534 FIXME("(%p)->(%p) stub!\n", This, isSpecified);
1535 *isSpecified = VARIANT_TRUE;
1539 static HRESULT WINAPI unknode_get_definition(
1541 IXMLDOMNode** definitionNode)
1543 unknode *This = unknode_from_IXMLDOMNode( iface );
1544 FIXME("(%p)->(%p)\n", This, definitionNode);
1548 static HRESULT WINAPI unknode_get_nodeTypedValue(
1552 unknode *This = unknode_from_IXMLDOMNode( iface );
1553 FIXME("(%p)->(%p)\n", This, var1);
1554 return return_null_var(var1);
1557 static HRESULT WINAPI unknode_put_nodeTypedValue(
1561 unknode *This = unknode_from_IXMLDOMNode( iface );
1562 FIXME("(%p)->(%s)\n", This, debugstr_variant(&typedValue));
1566 static HRESULT WINAPI unknode_get_dataType(
1570 unknode *This = unknode_from_IXMLDOMNode( iface );
1571 return IXMLDOMNode_get_dataType( &This->node.IXMLDOMNode_iface, var1 );
1574 static HRESULT WINAPI unknode_put_dataType(
1578 unknode *This = unknode_from_IXMLDOMNode( iface );
1580 FIXME("(%p)->(%s)\n", This, debugstr_w(p));
1583 return E_INVALIDARG;
1588 static HRESULT WINAPI unknode_get_xml(
1592 unknode *This = unknode_from_IXMLDOMNode( iface );
1594 FIXME("(%p)->(%p)\n", This, p);
1596 return node_get_xml(&This->node, FALSE, FALSE, p);
1599 static HRESULT WINAPI unknode_transformNode(
1601 IXMLDOMNode* domNode, BSTR* p)
1603 unknode *This = unknode_from_IXMLDOMNode( iface );
1604 return IXMLDOMNode_transformNode( &This->node.IXMLDOMNode_iface, domNode, p );
1607 static HRESULT WINAPI unknode_selectNodes(
1609 BSTR p, IXMLDOMNodeList** outList)
1611 unknode *This = unknode_from_IXMLDOMNode( iface );
1612 return IXMLDOMNode_selectNodes( &This->node.IXMLDOMNode_iface, p, outList );
1615 static HRESULT WINAPI unknode_selectSingleNode(
1617 BSTR p, IXMLDOMNode** outNode)
1619 unknode *This = unknode_from_IXMLDOMNode( iface );
1620 return IXMLDOMNode_selectSingleNode( &This->node.IXMLDOMNode_iface, p, outNode );
1623 static HRESULT WINAPI unknode_get_parsed(
1625 VARIANT_BOOL* isParsed)
1627 unknode *This = unknode_from_IXMLDOMNode( iface );
1628 FIXME("(%p)->(%p) stub!\n", This, isParsed);
1629 *isParsed = VARIANT_TRUE;
1633 static HRESULT WINAPI unknode_get_namespaceURI(
1637 unknode *This = unknode_from_IXMLDOMNode( iface );
1638 TRACE("(%p)->(%p)\n", This, p);
1639 return node_get_namespaceURI(&This->node, p);
1642 static HRESULT WINAPI unknode_get_prefix(
1646 unknode *This = unknode_from_IXMLDOMNode( iface );
1647 return IXMLDOMNode_get_prefix( &This->node.IXMLDOMNode_iface, p );
1650 static HRESULT WINAPI unknode_get_baseName(
1654 unknode *This = unknode_from_IXMLDOMNode( iface );
1655 return IXMLDOMNode_get_baseName( &This->node.IXMLDOMNode_iface, p );
1658 static HRESULT WINAPI unknode_transformNodeToObject(
1660 IXMLDOMNode* domNode, VARIANT var1)
1662 unknode *This = unknode_from_IXMLDOMNode( iface );
1663 FIXME("(%p)->(%p %s)\n", This, domNode, debugstr_variant(&var1));
1667 static const struct IXMLDOMNodeVtbl unknode_vtbl =
1669 unknode_QueryInterface,
1672 unknode_GetTypeInfoCount,
1673 unknode_GetTypeInfo,
1674 unknode_GetIDsOfNames,
1676 unknode_get_nodeName,
1677 unknode_get_nodeValue,
1678 unknode_put_nodeValue,
1679 unknode_get_nodeType,
1680 unknode_get_parentNode,
1681 unknode_get_childNodes,
1682 unknode_get_firstChild,
1683 unknode_get_lastChild,
1684 unknode_get_previousSibling,
1685 unknode_get_nextSibling,
1686 unknode_get_attributes,
1687 unknode_insertBefore,
1688 unknode_replaceChild,
1689 unknode_removeChild,
1690 unknode_appendChild,
1691 unknode_hasChildNodes,
1692 unknode_get_ownerDocument,
1694 unknode_get_nodeTypeString,
1697 unknode_get_specified,
1698 unknode_get_definition,
1699 unknode_get_nodeTypedValue,
1700 unknode_put_nodeTypedValue,
1701 unknode_get_dataType,
1702 unknode_put_dataType,
1704 unknode_transformNode,
1705 unknode_selectNodes,
1706 unknode_selectSingleNode,
1708 unknode_get_namespaceURI,
1710 unknode_get_baseName,
1711 unknode_transformNodeToObject
1714 IXMLDOMNode *create_node( xmlNodePtr node )
1723 TRACE("type %d\n", node->type);
1726 case XML_ELEMENT_NODE:
1727 pUnk = create_element( node );
1729 case XML_ATTRIBUTE_NODE:
1730 pUnk = create_attribute( node );
1733 pUnk = create_text( node );
1735 case XML_CDATA_SECTION_NODE:
1736 pUnk = create_cdata( node );
1738 case XML_ENTITY_REF_NODE:
1739 pUnk = create_doc_entity_ref( node );
1742 pUnk = create_pi( node );
1744 case XML_COMMENT_NODE:
1745 pUnk = create_comment( node );
1747 case XML_DOCUMENT_NODE:
1748 pUnk = create_domdoc( node );
1750 case XML_DOCUMENT_FRAG_NODE:
1751 pUnk = create_doc_fragment( node );
1754 pUnk = create_doc_type( node );
1759 FIXME("only creating basic node for type %d\n", node->type);
1761 new_node = heap_alloc(sizeof(unknode));
1765 new_node->IXMLDOMNode_iface.lpVtbl = &unknode_vtbl;
1767 init_xmlnode(&new_node->node, node, &new_node->IXMLDOMNode_iface, NULL);
1768 pUnk = (IUnknown*)&new_node->IXMLDOMNode_iface;
1772 hr = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMNode, (LPVOID*)&ret);
1773 IUnknown_Release(pUnk);
1774 if(FAILED(hr)) return NULL;