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
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>
35 # ifdef HAVE_LIBXSLT_TRANSFORM_H
36 # include <libxslt/transform.h>
38 # include <libxslt/xsltutils.h>
39 # include <libxslt/xsltInternals.h>
50 #include "msxml_private.h"
52 #include "wine/debug.h"
54 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
59 extern void* libxslt_handle;
60 # define MAKE_FUNCPTR(f) extern typeof(f) * p##f
61 MAKE_FUNCPTR(xsltApplyStylesheet);
62 MAKE_FUNCPTR(xsltCleanupGlobals);
63 MAKE_FUNCPTR(xsltFreeStylesheet);
64 MAKE_FUNCPTR(xsltParseStylesheetDoc);
68 /* TODO: get rid of these and use the enum */
69 static const WCHAR szBinBase64[] = {'b','i','n','.','b','a','s','e','6','4',0};
70 static const WCHAR szString[] = {'s','t','r','i','n','g',0};
71 static const WCHAR szNumber[] = {'n','u','m','b','e','r',0};
72 static const WCHAR szInt[] = {'I','n','t',0};
73 static const WCHAR szFixed[] = {'F','i','x','e','d','.','1','4','.','4',0};
74 static const WCHAR szBoolean[] = {'B','o','o','l','e','a','n',0};
75 static const WCHAR szDateTime[] = {'d','a','t','e','T','i','m','e',0};
76 static const WCHAR szDateTimeTZ[] = {'d','a','t','e','T','i','m','e','.','t','z',0};
77 static const WCHAR szDate[] = {'D','a','t','e',0};
78 static const WCHAR szTime[] = {'T','i','m','e',0};
79 static const WCHAR szTimeTZ[] = {'T','i','m','e','.','t','z',0};
80 static const WCHAR szI1[] = {'i','1',0};
81 static const WCHAR szI2[] = {'i','2',0};
82 static const WCHAR szI4[] = {'i','4',0};
83 static const WCHAR szIU1[] = {'u','i','1',0};
84 static const WCHAR szIU2[] = {'u','i','2',0};
85 static const WCHAR szIU4[] = {'u','i','4',0};
86 static const WCHAR szR4[] = {'r','4',0};
87 static const WCHAR szR8[] = {'r','8',0};
88 static const WCHAR szFloat[] = {'f','l','o','a','t',0};
89 static const WCHAR szUUID[] = {'u','u','i','d',0};
90 static const WCHAR szBinHex[] = {'b','i','n','.','h','e','x',0};
92 static const IID IID_xmlnode = {0x4f2f4ba2,0xb822,0x11df,{0x8b,0x8a,0x68,0x50,0xdf,0xd7,0x20,0x85}};
94 xmlNodePtr xmlNodePtr_from_domnode( IXMLDOMNode *iface, xmlElementType type )
100 This = get_node_obj( iface );
101 if ( !This || !This->node )
103 if ( type && This->node->type != type )
108 BOOL node_query_interface(xmlnode *This, REFIID riid, void **ppv)
110 if(IsEqualGUID(&IID_xmlnode, riid)) {
111 TRACE("(%p)->(IID_xmlnode %p)\n", This, ppv);
116 if(This->dispex.outer)
117 return dispex_query_interface(&This->dispex, riid, ppv);
122 xmlnode *get_node_obj(IXMLDOMNode *node)
127 hres = IXMLDOMNode_QueryInterface(node, &IID_xmlnode, (void**)&obj);
128 return SUCCEEDED(hres) ? obj : NULL;
131 HRESULT node_get_nodeName(xmlnode *This, BSTR *name)
136 *name = bstr_from_xmlChar(This->node->name);
143 HRESULT node_get_content(xmlnode *This, VARIANT *value)
150 content = xmlNodeGetContent(This->node);
151 V_VT(value) = VT_BSTR;
152 V_BSTR(value) = bstr_from_xmlChar( content );
155 TRACE("%p returned %s\n", This, debugstr_w(V_BSTR(value)));
159 HRESULT node_set_content(xmlnode *This, LPCWSTR value)
163 TRACE("(%p)->(%s)\n", This, debugstr_w(value));
164 str = xmlChar_from_wchar(value);
166 return E_OUTOFMEMORY;
168 xmlNodeSetContent(This->node, str);
173 static HRESULT node_set_content_escaped(xmlnode *This, LPCWSTR value)
175 xmlChar *str, *escaped;
177 TRACE("(%p)->(%s)\n", This, debugstr_w(value));
178 str = xmlChar_from_wchar(value);
180 return E_OUTOFMEMORY;
182 escaped = xmlEncodeSpecialChars(NULL, str);
186 return E_OUTOFMEMORY;
189 xmlNodeSetContent(This->node, escaped);
197 HRESULT node_put_value(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(This, V_BSTR(&string_value));
210 VariantClear(&string_value);
215 HRESULT node_put_value_escaped(xmlnode *This, VARIANT *value)
217 VARIANT string_value;
220 VariantInit(&string_value);
221 hr = VariantChangeType(&string_value, value, 0, VT_BSTR);
223 WARN("Couldn't convert to VT_BSTR\n");
227 hr = node_set_content_escaped(This, V_BSTR(&string_value));
228 VariantClear(&string_value);
233 static HRESULT get_node(
239 TRACE("(%p)->(%s %p %p)\n", This, name, node, out );
244 /* if we don't have a doc, use our parent. */
245 if(node && !node->doc && node->parent)
246 node->doc = node->parent->doc;
248 *out = create_node( node );
254 HRESULT node_get_parent(xmlnode *This, IXMLDOMNode **parent)
256 return get_node( This, "parent", This->node->parent, parent );
259 HRESULT node_get_child_nodes(xmlnode *This, IXMLDOMNodeList **ret)
264 *ret = create_children_nodelist(This->node);
266 return E_OUTOFMEMORY;
271 HRESULT node_get_first_child(xmlnode *This, IXMLDOMNode **ret)
273 return get_node(This, "firstChild", This->node->children, ret);
276 HRESULT node_get_last_child(xmlnode *This, IXMLDOMNode **ret)
278 return get_node(This, "lastChild", This->node->last, ret);
281 HRESULT node_get_previous_sibling(xmlnode *This, IXMLDOMNode **ret)
283 return get_node(This, "previous", This->node->prev, ret);
286 HRESULT node_get_next_sibling(xmlnode *This, IXMLDOMNode **ret)
288 return get_node(This, "next", This->node->next, ret);
291 HRESULT node_insert_before(xmlnode *This, IXMLDOMNode *new_child, const VARIANT *ref_child,
294 xmlNodePtr before_node, new_child_node;
295 IXMLDOMNode *before = NULL;
302 node_obj = get_node_obj(new_child);
304 FIXME("newChild is not our node implementation\n");
308 switch(V_VT(ref_child))
316 hr = IUnknown_QueryInterface(V_UNKNOWN(ref_child), &IID_IXMLDOMNode, (LPVOID)&before);
317 if(FAILED(hr)) return hr;
321 FIXME("refChild var type %x\n", V_VT(ref_child));
325 new_child_node = node_obj->node;
326 TRACE("new_child_node %p This->node %p\n", new_child_node, This->node);
328 if(!new_child_node->parent)
329 if(xmldoc_remove_orphan(new_child_node->doc, new_child_node) != S_OK)
330 WARN("%p is not an orphan of %p\n", new_child_node, new_child_node->doc);
334 node_obj = get_node_obj(before);
335 IXMLDOMNode_Release(before);
337 FIXME("before node is not our node implementation\n");
341 before_node = node_obj->node;
342 xmlAddPrevSibling(before_node, new_child_node);
346 xmlAddChild(This->node, new_child_node);
350 IXMLDOMNode_AddRef(new_child);
358 HRESULT node_replace_child(xmlnode *This, IXMLDOMNode *newChild, IXMLDOMNode *oldChild,
361 xmlnode *old_child, *new_child;
362 xmlDocPtr leaving_doc;
363 xmlNode *my_ancestor;
365 /* Do not believe any documentation telling that newChild == NULL
366 means removal. It does certainly *not* apply to msxml3! */
367 if(!newChild || !oldChild)
373 old_child = get_node_obj(oldChild);
375 FIXME("oldChild is not our node implementation\n");
379 if(old_child->node->parent != This->node)
381 WARN("childNode %p is not a child of %p\n", oldChild, This);
385 new_child = get_node_obj(newChild);
387 FIXME("newChild is not our node implementation\n");
391 my_ancestor = This->node;
394 if(my_ancestor == new_child->node)
396 WARN("tried to create loop\n");
399 my_ancestor = my_ancestor->parent;
402 if(!new_child->node->parent)
403 if(xmldoc_remove_orphan(new_child->node->doc, new_child->node) != S_OK)
404 WARN("%p is not an orphan of %p\n", new_child->node, new_child->node->doc);
406 leaving_doc = new_child->node->doc;
407 xmldoc_add_ref(old_child->node->doc);
408 xmlReplaceNode(old_child->node, new_child->node);
409 xmldoc_release(leaving_doc);
411 xmldoc_add_orphan(old_child->node->doc, old_child->node);
415 IXMLDOMNode_AddRef(oldChild);
422 HRESULT node_remove_child(xmlnode *This, IXMLDOMNode* child, IXMLDOMNode** oldChild)
426 if(!child) return E_INVALIDARG;
431 child_node = get_node_obj(child);
433 FIXME("childNode is not our node implementation\n");
437 if(child_node->node->parent != This->node)
439 WARN("childNode %p is not a child of %p\n", child, This);
443 xmlUnlinkNode(child_node->node);
447 IXMLDOMNode_AddRef(child);
454 HRESULT node_append_child(xmlnode *This, IXMLDOMNode *child, IXMLDOMNode **outChild)
460 hr = IXMLDOMNode_get_nodeType(child, &type);
461 if(FAILED(hr) || type == NODE_ATTRIBUTE) {
462 if (outChild) *outChild = NULL;
467 return IXMLDOMNode_insertBefore(This->iface, child, var, outChild);
470 HRESULT node_has_childnodes(const xmlnode *This, VARIANT_BOOL *ret)
472 if (!ret) return E_INVALIDARG;
474 if (!This->node->children)
476 *ret = VARIANT_FALSE;
484 HRESULT node_get_owner_doc(const xmlnode *This, IXMLDOMDocument **doc)
486 return get_domdoc_from_xmldoc(This->node->doc, (IXMLDOMDocument3**)doc);
489 HRESULT node_clone(xmlnode *This, VARIANT_BOOL deep, IXMLDOMNode **cloneNode)
494 if(!cloneNode) return E_INVALIDARG;
496 clone = xmlCopyNode(This->node, deep ? 1 : 2);
499 clone->doc = This->node->doc;
500 xmldoc_add_orphan(clone->doc, clone);
502 node = create_node(clone);
505 ERR("Copy failed\n");
513 ERR("Copy failed\n");
520 static inline xmlChar* trim_whitespace(xmlChar* str)
528 while (*ret && isspace(*ret))
530 len = xmlStrlen(ret);
532 while (isspace(ret[len-1])) --len;
534 ret = xmlStrndup(ret, len);
539 static xmlChar* do_get_text(xmlNodePtr node)
543 BOOL preserving = is_preserving_whitespace(node);
547 str = xmlNodeGetContent(node);
551 xmlElementType prev_type = XML_TEXT_NODE;
553 str = xmlStrdup(BAD_CAST "");
554 for (child = node->children; child != NULL; child = child->next)
558 case XML_ELEMENT_NODE:
559 tmp = do_get_text(child);
562 case XML_CDATA_SECTION_NODE:
563 case XML_ENTITY_REF_NODE:
564 case XML_ENTITY_NODE:
565 tmp = xmlNodeGetContent(child);
576 if (prev_type == XML_ELEMENT_NODE && child->type == XML_ELEMENT_NODE)
577 str = xmlStrcat(str, BAD_CAST " ");
578 str = xmlStrcat(str, tmp);
579 prev_type = child->type;
588 case XML_ELEMENT_NODE:
590 case XML_ENTITY_REF_NODE:
591 case XML_ENTITY_NODE:
592 case XML_DOCUMENT_NODE:
593 case XML_DOCUMENT_FRAG_NODE:
595 str = trim_whitespace(str);
604 HRESULT node_get_text(const xmlnode *This, BSTR *text)
609 if (!text) return E_INVALIDARG;
611 content = do_get_text(This->node);
614 str = bstr_from_xmlChar(content);
618 /* Always return a string. */
619 if (!str) str = SysAllocStringLen( NULL, 0 );
621 TRACE("%p %s\n", This, debugstr_w(str) );
627 HRESULT node_put_text(xmlnode *This, BSTR text)
631 TRACE("(%p)->(%s)\n", This, debugstr_w(text));
633 str = xmlChar_from_wchar(text);
635 /* Escape the string. */
636 str2 = xmlEncodeEntitiesReentrant(This->node->doc, str);
639 xmlNodeSetContent(This->node, str2);
645 static inline BYTE hex_to_byte(xmlChar c)
647 if(c <= '9') return c-'0';
648 if(c <= 'F') return c-'A'+10;
652 static inline BYTE base64_to_byte(xmlChar c)
654 if(c == '+') return 62;
655 if(c == '/') return 63;
656 if(c <= '9') return c-'0'+52;
657 if(c <= 'Z') return c-'A';
661 /* TODO: phasing this version out */
662 static inline HRESULT VARIANT_from_xmlChar(xmlChar *str, VARIANT *v, BSTR type)
664 if(!type || !lstrcmpiW(type, szString) ||
665 !lstrcmpiW(type, szNumber) || !lstrcmpiW(type, szUUID))
668 V_BSTR(v) = bstr_from_xmlChar(str);
671 return E_OUTOFMEMORY;
673 else if(!lstrcmpiW(type, szDateTime) || !lstrcmpiW(type, szDateTimeTZ) ||
674 !lstrcmpiW(type, szDate) || !lstrcmpiW(type, szTime) ||
675 !lstrcmpiW(type, szTimeTZ))
685 st.wDayOfWeek = st.wHour = st.wMinute = st.wSecond = st.wMilliseconds = 0;
687 V_VT(&src) = VT_BSTR;
688 V_BSTR(&src) = bstr_from_xmlChar(str);
691 return E_OUTOFMEMORY;
694 e = p + SysStringLen(V_BSTR(&src));
696 if(p+4<e && *(p+4)=='-') /* parse date (yyyy-mm-dd) */
699 st.wMonth = atoiW(p+5);
700 st.wDay = atoiW(p+8);
706 if(p+2<e && *(p+2)==':') /* parse time (hh:mm:ss.?) */
709 st.wMinute = atoiW(p+3);
710 st.wSecond = atoiW(p+6);
716 while(isdigitW(*p)) p++;
720 SystemTimeToVariantTime(&st, &date);
724 if(*p == '+') /* parse timezone offset (+hh:mm) */
725 V_DATE(v) += (DOUBLE)atoiW(p+1)/24 + (DOUBLE)atoiW(p+4)/1440;
726 else if(*p == '-') /* parse timezone offset (-hh:mm) */
727 V_DATE(v) -= (DOUBLE)atoiW(p+1)/24 + (DOUBLE)atoiW(p+4)/1440;
731 else if(!lstrcmpiW(type, szBinHex))
736 len = xmlStrlen(str)/2;
740 V_VT(v) = (VT_ARRAY|VT_UI1);
741 V_ARRAY(v) = SafeArrayCreate(VT_UI1, 1, &sab);
744 return E_OUTOFMEMORY;
747 ((BYTE*)V_ARRAY(v)->pvData)[i] = (hex_to_byte(str[2*i])<<4)
748 + hex_to_byte(str[2*i+1]);
750 else if(!lstrcmpiW(type, szBinBase64))
755 len = xmlStrlen(str);
756 if(str[len-2] == '=') i = 2;
757 else if(str[len-1] == '=') i = 1;
761 sab.cElements = len/4*3-i;
763 V_VT(v) = (VT_ARRAY|VT_UI1);
764 V_ARRAY(v) = SafeArrayCreate(VT_UI1, 1, &sab);
767 return E_OUTOFMEMORY;
769 for(i=0; i<len/4; i++)
771 ((BYTE*)V_ARRAY(v)->pvData)[3*i] = (base64_to_byte(str[4*i])<<2)
772 + (base64_to_byte(str[4*i+1])>>4);
773 if(3*i+1 < sab.cElements)
774 ((BYTE*)V_ARRAY(v)->pvData)[3*i+1] = (base64_to_byte(str[4*i+1])<<4)
775 + (base64_to_byte(str[4*i+2])>>2);
776 if(3*i+2 < sab.cElements)
777 ((BYTE*)V_ARRAY(v)->pvData)[3*i+2] = (base64_to_byte(str[4*i+2])<<6)
778 + base64_to_byte(str[4*i+3]);
786 if(!lstrcmpiW(type, szInt) || !lstrcmpiW(type, szI4))
788 else if(!lstrcmpiW(type, szFixed))
790 else if(!lstrcmpiW(type, szBoolean))
792 else if(!lstrcmpiW(type, szI1))
794 else if(!lstrcmpiW(type, szI2))
796 else if(!lstrcmpiW(type, szIU1))
798 else if(!lstrcmpiW(type, szIU2))
800 else if(!lstrcmpiW(type, szIU4))
802 else if(!lstrcmpiW(type, szR4))
804 else if(!lstrcmpiW(type, szR8) || !lstrcmpiW(type, szFloat))
808 FIXME("Type handling not yet implemented\n");
812 V_VT(&src) = VT_BSTR;
813 V_BSTR(&src) = bstr_from_xmlChar(str);
816 return E_OUTOFMEMORY;
818 hres = VariantChangeTypeEx(v, &src, MAKELCID(MAKELANGID(
819 LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT),0, V_VT(v));
827 BSTR EnsureCorrectEOL(BSTR sInput)
834 nLen = SysStringLen(sInput);
835 /* Count line endings */
836 for(i=0; i < nLen; i++)
838 if(sInput[i] == '\n')
842 TRACE("len=%d, num=%d\n", nLen, nNum);
844 /* Add linefeed as needed */
848 sNew = SysAllocStringLen(NULL, nLen + nNum+1);
849 for(i=0; i < nLen; i++)
851 if(sInput[i] == '\n')
853 sNew[i+nPlace] = '\r';
856 sNew[i+nPlace] = sInput[i];
859 SysFreeString(sInput);
866 TRACE("len %d\n", SysStringLen(sNew));
871 /* Removes encoding information and last character (nullbyte) */
872 static BSTR EnsureNoEncoding(BSTR sInput)
874 static const WCHAR wszEncoding[] = {'e','n','c','o','d','i','n','g','='};
879 while(*pBeg != '\n' && memcmp(pBeg, wszEncoding, sizeof(wszEncoding)))
884 SysReAllocStringLen(&sInput, sInput, SysStringLen(sInput)-1);
889 pEnd = pBeg + sizeof(wszEncoding)/sizeof(WCHAR) + 2;
890 while(*pEnd != '\"') pEnd++;
893 sNew = SysAllocStringLen(NULL,
894 pBeg-sInput + SysStringLen(sInput)-(pEnd-sInput)-1);
895 memcpy(sNew, sInput, (pBeg-sInput)*sizeof(WCHAR));
896 memcpy(&sNew[pBeg-sInput], pEnd, (SysStringLen(sInput)-(pEnd-sInput)-1)*sizeof(WCHAR));
898 SysFreeString(sInput);
903 * We are trying to replicate the same behaviour as msxml by converting
904 * line endings to \r\n and using indents as \t. The problem is that msxml
905 * only formats nodes that have a line ending. Using libxml we cannot
906 * reproduce behaviour exactly.
909 HRESULT node_get_xml(xmlnode *This, BOOL ensure_eol, BOOL ensure_no_encoding, BSTR *ret)
911 xmlBufferPtr xml_buf;
920 xml_buf = xmlBufferCreate();
922 return E_OUTOFMEMORY;
924 xmldecl = xmldoc_unlink_xmldecl( This->node->doc );
926 size = xmlNodeDump(xml_buf, This->node->doc, This->node, 0, 1);
928 const xmlChar *buf_content;
931 /* Attribute Nodes return a space in front of their name */
932 buf_content = xmlBufferContent(xml_buf);
934 content = bstr_from_xmlChar(buf_content + (buf_content[0] == ' ' ? 1 : 0));
936 content = EnsureCorrectEOL(content);
937 if(ensure_no_encoding)
938 content = EnsureNoEncoding(content);
942 *ret = SysAllocStringLen(NULL, 0);
945 xmlBufferFree(xml_buf);
946 xmldoc_link_xmldecl( This->node->doc, xmldecl );
947 return *ret ? S_OK : E_OUTOFMEMORY;
950 HRESULT node_transform_node(const xmlnode *This, IXMLDOMNode *stylesheet, BSTR *p)
952 #ifdef SONAME_LIBXSLT
953 xsltStylesheetPtr xsltSS;
956 if (!libxslt_handle) return E_NOTIMPL;
957 if (!stylesheet || !p) return E_INVALIDARG;
961 sheet = get_node_obj(stylesheet);
963 FIXME("styleSheet is not our xmlnode implementation\n");
967 xsltSS = pxsltParseStylesheetDoc(sheet->node->doc);
970 xmlDocPtr result = pxsltApplyStylesheet(xsltSS, This->node->doc, NULL);
973 const xmlChar *content;
975 if(result->type == XML_HTML_DOCUMENT_NODE)
977 xmlOutputBufferPtr output = xmlAllocOutputBuffer(NULL);
980 htmlDocContentDumpOutput(output, result->doc, NULL);
981 content = xmlBufferContent(output->buffer);
982 *p = bstr_from_xmlChar(content);
983 xmlOutputBufferClose(output);
988 xmlBufferPtr buf = xmlBufferCreate();
991 int size = xmlNodeDump(buf, NULL, (xmlNodePtr)result, 0, 0);
994 content = xmlBufferContent(buf);
995 *p = bstr_from_xmlChar(content);
1002 /* libxslt "helpfully" frees the XML document the stylesheet was
1003 generated from, too */
1005 pxsltFreeStylesheet(xsltSS);
1008 if(!*p) *p = SysAllocStringLen(NULL, 0);
1012 FIXME("libxslt headers were not found at compile time\n");
1017 HRESULT node_select_nodes(const xmlnode *This, BSTR query, IXMLDOMNodeList **nodes)
1022 if (!query || !nodes) return E_INVALIDARG;
1024 str = xmlChar_from_wchar(query);
1025 hr = queryresult_create(This->node, str, nodes);
1031 HRESULT node_select_singlenode(const xmlnode *This, BSTR query, IXMLDOMNode **node)
1033 IXMLDOMNodeList *list;
1036 hr = node_select_nodes(This, query, &list);
1039 hr = IXMLDOMNodeList_nextNode(list, node);
1040 IXMLDOMNodeList_Release(list);
1045 HRESULT node_get_namespaceURI(xmlnode *This, BSTR *namespaceURI)
1050 return E_INVALIDARG;
1052 *namespaceURI = NULL;
1054 if ((ns = xmlGetNsList(This->node->doc, This->node)))
1056 if (ns[0]->href) *namespaceURI = bstr_from_xmlChar( ns[0]->href );
1060 TRACE("uri: %s\n", debugstr_w(*namespaceURI));
1062 return *namespaceURI ? S_OK : S_FALSE;
1065 HRESULT node_get_prefix(xmlnode *This, BSTR *prefix)
1069 if (!prefix) return E_INVALIDARG;
1073 if ((ns = xmlGetNsList(This->node->doc, This->node)))
1075 if (ns[0]->prefix) *prefix = bstr_from_xmlChar( ns[0]->prefix );
1079 TRACE("prefix: %s\n", debugstr_w(*prefix));
1081 return *prefix ? S_OK : S_FALSE;
1084 HRESULT node_get_base_name(xmlnode *This, BSTR *name)
1086 if (!name) return E_INVALIDARG;
1088 *name = bstr_from_xmlChar(This->node->name);
1089 if (!*name) return E_OUTOFMEMORY;
1091 TRACE("returning %s\n", debugstr_w(*name));
1096 void destroy_xmlnode(xmlnode *This)
1099 xmldoc_release(This->node->doc);
1102 void init_xmlnode(xmlnode *This, xmlNodePtr node, IXMLDOMNode *node_iface, dispex_static_data_t *dispex_data)
1105 xmldoc_add_ref( node->doc );
1108 This->iface = node_iface;
1109 This->parent = NULL;
1112 init_dispex(&This->dispex, (IUnknown*)This->iface, dispex_data);
1114 This->dispex.outer = NULL;
1119 IXMLDOMNode IXMLDOMNode_iface;
1123 static inline unknode *unknode_from_IXMLDOMNode(IXMLDOMNode *iface)
1125 return CONTAINING_RECORD(iface, unknode, IXMLDOMNode_iface);
1128 static HRESULT WINAPI unknode_QueryInterface(
1133 unknode *This = unknode_from_IXMLDOMNode( iface );
1135 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
1137 if (IsEqualGUID(riid, &IID_IUnknown)) {
1139 }else if (IsEqualGUID( riid, &IID_IDispatch) ||
1140 IsEqualGUID( riid, &IID_IXMLDOMNode)) {
1141 *ppvObject = &This->IXMLDOMNode_iface;
1142 }else if(node_query_interface(&This->node, riid, ppvObject)) {
1143 return *ppvObject ? S_OK : E_NOINTERFACE;
1145 FIXME("interface %s not implemented\n", debugstr_guid(riid));
1147 return E_NOINTERFACE;
1150 IUnknown_AddRef((IUnknown*)*ppvObject);
1154 static ULONG WINAPI unknode_AddRef(
1155 IXMLDOMNode *iface )
1157 unknode *This = unknode_from_IXMLDOMNode( iface );
1159 return InterlockedIncrement(&This->ref);
1162 static ULONG WINAPI unknode_Release(
1163 IXMLDOMNode *iface )
1165 unknode *This = unknode_from_IXMLDOMNode( iface );
1168 ref = InterlockedDecrement( &This->ref );
1170 destroy_xmlnode(&This->node);
1177 static HRESULT WINAPI unknode_GetTypeInfoCount(
1181 unknode *This = unknode_from_IXMLDOMNode( iface );
1183 TRACE("(%p)->(%p)\n", This, pctinfo);
1190 static HRESULT WINAPI unknode_GetTypeInfo(
1194 ITypeInfo** ppTInfo )
1196 unknode *This = unknode_from_IXMLDOMNode( iface );
1199 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1201 hr = get_typeinfo(IXMLDOMNode_tid, ppTInfo);
1206 static HRESULT WINAPI unknode_GetIDsOfNames(
1209 LPOLESTR* rgszNames,
1214 unknode *This = unknode_from_IXMLDOMNode( iface );
1216 ITypeInfo *typeinfo;
1219 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1222 if(!rgszNames || cNames == 0 || !rgDispId)
1223 return E_INVALIDARG;
1225 hr = get_typeinfo(IXMLDOMNode_tid, &typeinfo);
1228 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1229 ITypeInfo_Release(typeinfo);
1235 static HRESULT WINAPI unknode_Invoke(
1237 DISPID dispIdMember,
1241 DISPPARAMS* pDispParams,
1242 VARIANT* pVarResult,
1243 EXCEPINFO* pExcepInfo,
1246 unknode *This = unknode_from_IXMLDOMNode( iface );
1247 ITypeInfo *typeinfo;
1250 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1251 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1253 hr = get_typeinfo(IXMLDOMNode_tid, &typeinfo);
1256 hr = ITypeInfo_Invoke(typeinfo, &This->IXMLDOMNode_iface, dispIdMember, wFlags, pDispParams,
1257 pVarResult, pExcepInfo, puArgErr);
1258 ITypeInfo_Release(typeinfo);
1264 static HRESULT WINAPI unknode_get_nodeName(
1268 unknode *This = unknode_from_IXMLDOMNode( iface );
1270 FIXME("(%p)->(%p)\n", This, p);
1272 return node_get_nodeName(&This->node, p);
1275 static HRESULT WINAPI unknode_get_nodeValue(
1279 unknode *This = unknode_from_IXMLDOMNode( iface );
1281 FIXME("(%p)->(%p)\n", This, value);
1284 return E_INVALIDARG;
1286 V_VT(value) = VT_NULL;
1290 static HRESULT WINAPI unknode_put_nodeValue(
1294 unknode *This = unknode_from_IXMLDOMNode( iface );
1295 FIXME("(%p)->(v%d)\n", This, V_VT(&value));
1299 static HRESULT WINAPI unknode_get_nodeType(
1301 DOMNodeType* domNodeType )
1303 unknode *This = unknode_from_IXMLDOMNode( iface );
1305 FIXME("(%p)->(%p)\n", This, domNodeType);
1307 *domNodeType = This->node.node->type;
1311 static HRESULT WINAPI unknode_get_parentNode(
1313 IXMLDOMNode** parent )
1315 unknode *This = unknode_from_IXMLDOMNode( iface );
1316 FIXME("(%p)->(%p)\n", This, parent);
1317 if (!parent) return E_INVALIDARG;
1322 static HRESULT WINAPI unknode_get_childNodes(
1324 IXMLDOMNodeList** outList)
1326 unknode *This = unknode_from_IXMLDOMNode( iface );
1328 TRACE("(%p)->(%p)\n", This, outList);
1330 return node_get_child_nodes(&This->node, outList);
1333 static HRESULT WINAPI unknode_get_firstChild(
1335 IXMLDOMNode** domNode)
1337 unknode *This = unknode_from_IXMLDOMNode( iface );
1339 TRACE("(%p)->(%p)\n", This, domNode);
1341 return node_get_first_child(&This->node, domNode);
1344 static HRESULT WINAPI unknode_get_lastChild(
1346 IXMLDOMNode** domNode)
1348 unknode *This = unknode_from_IXMLDOMNode( iface );
1350 TRACE("(%p)->(%p)\n", This, domNode);
1352 return node_get_last_child(&This->node, domNode);
1355 static HRESULT WINAPI unknode_get_previousSibling(
1357 IXMLDOMNode** domNode)
1359 unknode *This = unknode_from_IXMLDOMNode( iface );
1361 TRACE("(%p)->(%p)\n", This, domNode);
1363 return node_get_previous_sibling(&This->node, domNode);
1366 static HRESULT WINAPI unknode_get_nextSibling(
1368 IXMLDOMNode** domNode)
1370 unknode *This = unknode_from_IXMLDOMNode( iface );
1372 TRACE("(%p)->(%p)\n", This, domNode);
1374 return node_get_next_sibling(&This->node, domNode);
1377 static HRESULT WINAPI unknode_get_attributes(
1379 IXMLDOMNamedNodeMap** attributeMap)
1381 unknode *This = unknode_from_IXMLDOMNode( iface );
1383 FIXME("(%p)->(%p)\n", This, attributeMap);
1385 return return_null_ptr((void**)attributeMap);
1388 static HRESULT WINAPI unknode_insertBefore(
1390 IXMLDOMNode* newNode, VARIANT refChild,
1391 IXMLDOMNode** outOldNode)
1393 unknode *This = unknode_from_IXMLDOMNode( iface );
1395 FIXME("(%p)->(%p x%d %p)\n", This, newNode, V_VT(&refChild), outOldNode);
1397 return node_insert_before(&This->node, newNode, &refChild, outOldNode);
1400 static HRESULT WINAPI unknode_replaceChild(
1402 IXMLDOMNode* newNode,
1403 IXMLDOMNode* oldNode,
1404 IXMLDOMNode** outOldNode)
1406 unknode *This = unknode_from_IXMLDOMNode( iface );
1408 FIXME("(%p)->(%p %p %p)\n", This, newNode, oldNode, outOldNode);
1410 return node_replace_child(&This->node, newNode, oldNode, outOldNode);
1413 static HRESULT WINAPI unknode_removeChild(
1415 IXMLDOMNode* domNode, IXMLDOMNode** oldNode)
1417 unknode *This = unknode_from_IXMLDOMNode( iface );
1418 return node_remove_child(&This->node, domNode, oldNode);
1421 static HRESULT WINAPI unknode_appendChild(
1423 IXMLDOMNode* newNode, IXMLDOMNode** outNewNode)
1425 unknode *This = unknode_from_IXMLDOMNode( iface );
1426 return node_append_child(&This->node, newNode, outNewNode);
1429 static HRESULT WINAPI unknode_hasChildNodes(
1431 VARIANT_BOOL* pbool)
1433 unknode *This = unknode_from_IXMLDOMNode( iface );
1434 return node_has_childnodes(&This->node, pbool);
1437 static HRESULT WINAPI unknode_get_ownerDocument(
1439 IXMLDOMDocument** domDocument)
1441 unknode *This = unknode_from_IXMLDOMNode( iface );
1442 return node_get_owner_doc(&This->node, domDocument);
1445 static HRESULT WINAPI unknode_cloneNode(
1447 VARIANT_BOOL pbool, IXMLDOMNode** outNode)
1449 unknode *This = unknode_from_IXMLDOMNode( iface );
1450 return node_clone(&This->node, pbool, outNode );
1453 static HRESULT WINAPI unknode_get_nodeTypeString(
1457 unknode *This = unknode_from_IXMLDOMNode( iface );
1459 FIXME("(%p)->(%p)\n", This, p);
1461 return node_get_nodeName(&This->node, p);
1464 static HRESULT WINAPI unknode_get_text(
1468 unknode *This = unknode_from_IXMLDOMNode( iface );
1469 return node_get_text(&This->node, p);
1472 static HRESULT WINAPI unknode_put_text(
1476 unknode *This = unknode_from_IXMLDOMNode( iface );
1477 return node_put_text(&This->node, p);
1480 static HRESULT WINAPI unknode_get_specified(
1482 VARIANT_BOOL* isSpecified)
1484 unknode *This = unknode_from_IXMLDOMNode( iface );
1485 FIXME("(%p)->(%p) stub!\n", This, isSpecified);
1486 *isSpecified = VARIANT_TRUE;
1490 static HRESULT WINAPI unknode_get_definition(
1492 IXMLDOMNode** definitionNode)
1494 unknode *This = unknode_from_IXMLDOMNode( iface );
1495 FIXME("(%p)->(%p)\n", This, definitionNode);
1499 static HRESULT WINAPI unknode_get_nodeTypedValue(
1503 unknode *This = unknode_from_IXMLDOMNode( iface );
1504 FIXME("(%p)->(%p)\n", This, var1);
1505 return return_null_var(var1);
1508 static HRESULT WINAPI unknode_put_nodeTypedValue(
1512 unknode *This = unknode_from_IXMLDOMNode( iface );
1513 FIXME("(%p)->(%s)\n", This, debugstr_variant(&typedValue));
1517 static HRESULT WINAPI unknode_get_dataType(
1521 unknode *This = unknode_from_IXMLDOMNode( iface );
1522 TRACE("(%p)->(%p)\n", This, var1);
1523 return return_null_var(var1);
1526 static HRESULT WINAPI unknode_put_dataType(
1530 unknode *This = unknode_from_IXMLDOMNode( iface );
1532 FIXME("(%p)->(%s)\n", This, debugstr_w(p));
1535 return E_INVALIDARG;
1540 static HRESULT WINAPI unknode_get_xml(
1544 unknode *This = unknode_from_IXMLDOMNode( iface );
1546 FIXME("(%p)->(%p)\n", This, p);
1548 return node_get_xml(&This->node, FALSE, FALSE, p);
1551 static HRESULT WINAPI unknode_transformNode(
1553 IXMLDOMNode* domNode, BSTR* p)
1555 unknode *This = unknode_from_IXMLDOMNode( iface );
1556 return node_transform_node(&This->node, domNode, p);
1559 static HRESULT WINAPI unknode_selectNodes(
1561 BSTR p, IXMLDOMNodeList** outList)
1563 unknode *This = unknode_from_IXMLDOMNode( iface );
1564 return node_select_nodes(&This->node, p, outList);
1567 static HRESULT WINAPI unknode_selectSingleNode(
1569 BSTR p, IXMLDOMNode** outNode)
1571 unknode *This = unknode_from_IXMLDOMNode( iface );
1572 return node_select_singlenode(&This->node, p, outNode);
1575 static HRESULT WINAPI unknode_get_parsed(
1577 VARIANT_BOOL* isParsed)
1579 unknode *This = unknode_from_IXMLDOMNode( iface );
1580 FIXME("(%p)->(%p) stub!\n", This, isParsed);
1581 *isParsed = VARIANT_TRUE;
1585 static HRESULT WINAPI unknode_get_namespaceURI(
1589 unknode *This = unknode_from_IXMLDOMNode( iface );
1590 TRACE("(%p)->(%p)\n", This, p);
1591 return node_get_namespaceURI(&This->node, p);
1594 static HRESULT WINAPI unknode_get_prefix(
1598 unknode *This = unknode_from_IXMLDOMNode( iface );
1599 return node_get_prefix(&This->node, p);
1602 static HRESULT WINAPI unknode_get_baseName(
1606 unknode *This = unknode_from_IXMLDOMNode( iface );
1607 return node_get_base_name(&This->node, p);
1610 static HRESULT WINAPI unknode_transformNodeToObject(
1612 IXMLDOMNode* domNode, VARIANT var1)
1614 unknode *This = unknode_from_IXMLDOMNode( iface );
1615 FIXME("(%p)->(%p %s)\n", This, domNode, debugstr_variant(&var1));
1619 static const struct IXMLDOMNodeVtbl unknode_vtbl =
1621 unknode_QueryInterface,
1624 unknode_GetTypeInfoCount,
1625 unknode_GetTypeInfo,
1626 unknode_GetIDsOfNames,
1628 unknode_get_nodeName,
1629 unknode_get_nodeValue,
1630 unknode_put_nodeValue,
1631 unknode_get_nodeType,
1632 unknode_get_parentNode,
1633 unknode_get_childNodes,
1634 unknode_get_firstChild,
1635 unknode_get_lastChild,
1636 unknode_get_previousSibling,
1637 unknode_get_nextSibling,
1638 unknode_get_attributes,
1639 unknode_insertBefore,
1640 unknode_replaceChild,
1641 unknode_removeChild,
1642 unknode_appendChild,
1643 unknode_hasChildNodes,
1644 unknode_get_ownerDocument,
1646 unknode_get_nodeTypeString,
1649 unknode_get_specified,
1650 unknode_get_definition,
1651 unknode_get_nodeTypedValue,
1652 unknode_put_nodeTypedValue,
1653 unknode_get_dataType,
1654 unknode_put_dataType,
1656 unknode_transformNode,
1657 unknode_selectNodes,
1658 unknode_selectSingleNode,
1660 unknode_get_namespaceURI,
1662 unknode_get_baseName,
1663 unknode_transformNodeToObject
1666 IXMLDOMNode *create_node( xmlNodePtr node )
1675 TRACE("type %d\n", node->type);
1678 case XML_ELEMENT_NODE:
1679 pUnk = create_element( node );
1681 case XML_ATTRIBUTE_NODE:
1682 pUnk = create_attribute( node );
1685 pUnk = create_text( node );
1687 case XML_CDATA_SECTION_NODE:
1688 pUnk = create_cdata( node );
1690 case XML_ENTITY_REF_NODE:
1691 pUnk = create_doc_entity_ref( node );
1694 pUnk = create_pi( node );
1696 case XML_COMMENT_NODE:
1697 pUnk = create_comment( node );
1699 case XML_DOCUMENT_NODE:
1700 pUnk = create_domdoc( node );
1702 case XML_DOCUMENT_FRAG_NODE:
1703 pUnk = create_doc_fragment( node );
1706 pUnk = create_doc_type( node );
1711 FIXME("only creating basic node for type %d\n", node->type);
1713 new_node = heap_alloc(sizeof(unknode));
1717 new_node->IXMLDOMNode_iface.lpVtbl = &unknode_vtbl;
1719 init_xmlnode(&new_node->node, node, &new_node->IXMLDOMNode_iface, NULL);
1720 pUnk = (IUnknown*)&new_node->IXMLDOMNode_iface;
1724 hr = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMNode, (LPVOID*)&ret);
1725 IUnknown_Release(pUnk);
1726 if(FAILED(hr)) return NULL;