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;
1111 init_dispex(&This->dispex, (IUnknown*)This->iface, dispex_data);
1113 This->dispex.outer = NULL;
1118 IXMLDOMNode IXMLDOMNode_iface;
1122 static inline unknode *unknode_from_IXMLDOMNode(IXMLDOMNode *iface)
1124 return CONTAINING_RECORD(iface, unknode, IXMLDOMNode_iface);
1127 static HRESULT WINAPI unknode_QueryInterface(
1132 unknode *This = unknode_from_IXMLDOMNode( iface );
1134 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
1136 if (IsEqualGUID(riid, &IID_IUnknown)) {
1138 }else if (IsEqualGUID( riid, &IID_IDispatch) ||
1139 IsEqualGUID( riid, &IID_IXMLDOMNode)) {
1140 *ppvObject = &This->IXMLDOMNode_iface;
1141 }else if(node_query_interface(&This->node, riid, ppvObject)) {
1142 return *ppvObject ? S_OK : E_NOINTERFACE;
1144 FIXME("interface %s not implemented\n", debugstr_guid(riid));
1146 return E_NOINTERFACE;
1149 IUnknown_AddRef((IUnknown*)*ppvObject);
1153 static ULONG WINAPI unknode_AddRef(
1154 IXMLDOMNode *iface )
1156 unknode *This = unknode_from_IXMLDOMNode( iface );
1158 return InterlockedIncrement(&This->ref);
1161 static ULONG WINAPI unknode_Release(
1162 IXMLDOMNode *iface )
1164 unknode *This = unknode_from_IXMLDOMNode( iface );
1167 ref = InterlockedDecrement( &This->ref );
1169 destroy_xmlnode(&This->node);
1176 static HRESULT WINAPI unknode_GetTypeInfoCount(
1180 unknode *This = unknode_from_IXMLDOMNode( iface );
1182 TRACE("(%p)->(%p)\n", This, pctinfo);
1189 static HRESULT WINAPI unknode_GetTypeInfo(
1193 ITypeInfo** ppTInfo )
1195 unknode *This = unknode_from_IXMLDOMNode( iface );
1198 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1200 hr = get_typeinfo(IXMLDOMNode_tid, ppTInfo);
1205 static HRESULT WINAPI unknode_GetIDsOfNames(
1208 LPOLESTR* rgszNames,
1213 unknode *This = unknode_from_IXMLDOMNode( iface );
1215 ITypeInfo *typeinfo;
1218 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1221 if(!rgszNames || cNames == 0 || !rgDispId)
1222 return E_INVALIDARG;
1224 hr = get_typeinfo(IXMLDOMNode_tid, &typeinfo);
1227 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1228 ITypeInfo_Release(typeinfo);
1234 static HRESULT WINAPI unknode_Invoke(
1236 DISPID dispIdMember,
1240 DISPPARAMS* pDispParams,
1241 VARIANT* pVarResult,
1242 EXCEPINFO* pExcepInfo,
1245 unknode *This = unknode_from_IXMLDOMNode( iface );
1246 ITypeInfo *typeinfo;
1249 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1250 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1252 hr = get_typeinfo(IXMLDOMNode_tid, &typeinfo);
1255 hr = ITypeInfo_Invoke(typeinfo, &This->IXMLDOMNode_iface, dispIdMember, wFlags, pDispParams,
1256 pVarResult, pExcepInfo, puArgErr);
1257 ITypeInfo_Release(typeinfo);
1263 static HRESULT WINAPI unknode_get_nodeName(
1267 unknode *This = unknode_from_IXMLDOMNode( iface );
1269 FIXME("(%p)->(%p)\n", This, p);
1271 return node_get_nodeName(&This->node, p);
1274 static HRESULT WINAPI unknode_get_nodeValue(
1278 unknode *This = unknode_from_IXMLDOMNode( iface );
1280 FIXME("(%p)->(%p)\n", This, value);
1283 return E_INVALIDARG;
1285 V_VT(value) = VT_NULL;
1289 static HRESULT WINAPI unknode_put_nodeValue(
1293 unknode *This = unknode_from_IXMLDOMNode( iface );
1294 FIXME("(%p)->(v%d)\n", This, V_VT(&value));
1298 static HRESULT WINAPI unknode_get_nodeType(
1300 DOMNodeType* domNodeType )
1302 unknode *This = unknode_from_IXMLDOMNode( iface );
1304 FIXME("(%p)->(%p)\n", This, domNodeType);
1306 *domNodeType = This->node.node->type;
1310 static HRESULT WINAPI unknode_get_parentNode(
1312 IXMLDOMNode** parent )
1314 unknode *This = unknode_from_IXMLDOMNode( iface );
1315 FIXME("(%p)->(%p)\n", This, parent);
1316 if (!parent) return E_INVALIDARG;
1321 static HRESULT WINAPI unknode_get_childNodes(
1323 IXMLDOMNodeList** outList)
1325 unknode *This = unknode_from_IXMLDOMNode( iface );
1327 TRACE("(%p)->(%p)\n", This, outList);
1329 return node_get_child_nodes(&This->node, outList);
1332 static HRESULT WINAPI unknode_get_firstChild(
1334 IXMLDOMNode** domNode)
1336 unknode *This = unknode_from_IXMLDOMNode( iface );
1338 TRACE("(%p)->(%p)\n", This, domNode);
1340 return node_get_first_child(&This->node, domNode);
1343 static HRESULT WINAPI unknode_get_lastChild(
1345 IXMLDOMNode** domNode)
1347 unknode *This = unknode_from_IXMLDOMNode( iface );
1349 TRACE("(%p)->(%p)\n", This, domNode);
1351 return node_get_last_child(&This->node, domNode);
1354 static HRESULT WINAPI unknode_get_previousSibling(
1356 IXMLDOMNode** domNode)
1358 unknode *This = unknode_from_IXMLDOMNode( iface );
1360 TRACE("(%p)->(%p)\n", This, domNode);
1362 return node_get_previous_sibling(&This->node, domNode);
1365 static HRESULT WINAPI unknode_get_nextSibling(
1367 IXMLDOMNode** domNode)
1369 unknode *This = unknode_from_IXMLDOMNode( iface );
1371 TRACE("(%p)->(%p)\n", This, domNode);
1373 return node_get_next_sibling(&This->node, domNode);
1376 static HRESULT WINAPI unknode_get_attributes(
1378 IXMLDOMNamedNodeMap** attributeMap)
1380 unknode *This = unknode_from_IXMLDOMNode( iface );
1382 FIXME("(%p)->(%p)\n", This, attributeMap);
1384 return return_null_ptr((void**)attributeMap);
1387 static HRESULT WINAPI unknode_insertBefore(
1389 IXMLDOMNode* newNode, VARIANT refChild,
1390 IXMLDOMNode** outOldNode)
1392 unknode *This = unknode_from_IXMLDOMNode( iface );
1394 FIXME("(%p)->(%p x%d %p)\n", This, newNode, V_VT(&refChild), outOldNode);
1396 return node_insert_before(&This->node, newNode, &refChild, outOldNode);
1399 static HRESULT WINAPI unknode_replaceChild(
1401 IXMLDOMNode* newNode,
1402 IXMLDOMNode* oldNode,
1403 IXMLDOMNode** outOldNode)
1405 unknode *This = unknode_from_IXMLDOMNode( iface );
1407 FIXME("(%p)->(%p %p %p)\n", This, newNode, oldNode, outOldNode);
1409 return node_replace_child(&This->node, newNode, oldNode, outOldNode);
1412 static HRESULT WINAPI unknode_removeChild(
1414 IXMLDOMNode* domNode, IXMLDOMNode** oldNode)
1416 unknode *This = unknode_from_IXMLDOMNode( iface );
1417 return node_remove_child(&This->node, domNode, oldNode);
1420 static HRESULT WINAPI unknode_appendChild(
1422 IXMLDOMNode* newNode, IXMLDOMNode** outNewNode)
1424 unknode *This = unknode_from_IXMLDOMNode( iface );
1425 return node_append_child(&This->node, newNode, outNewNode);
1428 static HRESULT WINAPI unknode_hasChildNodes(
1430 VARIANT_BOOL* pbool)
1432 unknode *This = unknode_from_IXMLDOMNode( iface );
1433 return node_has_childnodes(&This->node, pbool);
1436 static HRESULT WINAPI unknode_get_ownerDocument(
1438 IXMLDOMDocument** domDocument)
1440 unknode *This = unknode_from_IXMLDOMNode( iface );
1441 return node_get_owner_doc(&This->node, domDocument);
1444 static HRESULT WINAPI unknode_cloneNode(
1446 VARIANT_BOOL pbool, IXMLDOMNode** outNode)
1448 unknode *This = unknode_from_IXMLDOMNode( iface );
1449 return node_clone(&This->node, pbool, outNode );
1452 static HRESULT WINAPI unknode_get_nodeTypeString(
1456 unknode *This = unknode_from_IXMLDOMNode( iface );
1458 FIXME("(%p)->(%p)\n", This, p);
1460 return node_get_nodeName(&This->node, p);
1463 static HRESULT WINAPI unknode_get_text(
1467 unknode *This = unknode_from_IXMLDOMNode( iface );
1468 return node_get_text(&This->node, p);
1471 static HRESULT WINAPI unknode_put_text(
1475 unknode *This = unknode_from_IXMLDOMNode( iface );
1476 return node_put_text(&This->node, p);
1479 static HRESULT WINAPI unknode_get_specified(
1481 VARIANT_BOOL* isSpecified)
1483 unknode *This = unknode_from_IXMLDOMNode( iface );
1484 FIXME("(%p)->(%p) stub!\n", This, isSpecified);
1485 *isSpecified = VARIANT_TRUE;
1489 static HRESULT WINAPI unknode_get_definition(
1491 IXMLDOMNode** definitionNode)
1493 unknode *This = unknode_from_IXMLDOMNode( iface );
1494 FIXME("(%p)->(%p)\n", This, definitionNode);
1498 static HRESULT WINAPI unknode_get_nodeTypedValue(
1502 unknode *This = unknode_from_IXMLDOMNode( iface );
1503 FIXME("(%p)->(%p)\n", This, var1);
1504 return return_null_var(var1);
1507 static HRESULT WINAPI unknode_put_nodeTypedValue(
1511 unknode *This = unknode_from_IXMLDOMNode( iface );
1512 FIXME("(%p)->(%s)\n", This, debugstr_variant(&typedValue));
1516 static HRESULT WINAPI unknode_get_dataType(
1520 unknode *This = unknode_from_IXMLDOMNode( iface );
1521 TRACE("(%p)->(%p)\n", This, var1);
1522 return return_null_var(var1);
1525 static HRESULT WINAPI unknode_put_dataType(
1529 unknode *This = unknode_from_IXMLDOMNode( iface );
1531 FIXME("(%p)->(%s)\n", This, debugstr_w(p));
1534 return E_INVALIDARG;
1539 static HRESULT WINAPI unknode_get_xml(
1543 unknode *This = unknode_from_IXMLDOMNode( iface );
1545 FIXME("(%p)->(%p)\n", This, p);
1547 return node_get_xml(&This->node, FALSE, FALSE, p);
1550 static HRESULT WINAPI unknode_transformNode(
1552 IXMLDOMNode* domNode, BSTR* p)
1554 unknode *This = unknode_from_IXMLDOMNode( iface );
1555 return node_transform_node(&This->node, domNode, p);
1558 static HRESULT WINAPI unknode_selectNodes(
1560 BSTR p, IXMLDOMNodeList** outList)
1562 unknode *This = unknode_from_IXMLDOMNode( iface );
1563 return node_select_nodes(&This->node, p, outList);
1566 static HRESULT WINAPI unknode_selectSingleNode(
1568 BSTR p, IXMLDOMNode** outNode)
1570 unknode *This = unknode_from_IXMLDOMNode( iface );
1571 return node_select_singlenode(&This->node, p, outNode);
1574 static HRESULT WINAPI unknode_get_parsed(
1576 VARIANT_BOOL* isParsed)
1578 unknode *This = unknode_from_IXMLDOMNode( iface );
1579 FIXME("(%p)->(%p) stub!\n", This, isParsed);
1580 *isParsed = VARIANT_TRUE;
1584 static HRESULT WINAPI unknode_get_namespaceURI(
1588 unknode *This = unknode_from_IXMLDOMNode( iface );
1589 TRACE("(%p)->(%p)\n", This, p);
1590 return node_get_namespaceURI(&This->node, p);
1593 static HRESULT WINAPI unknode_get_prefix(
1597 unknode *This = unknode_from_IXMLDOMNode( iface );
1598 return node_get_prefix(&This->node, p);
1601 static HRESULT WINAPI unknode_get_baseName(
1605 unknode *This = unknode_from_IXMLDOMNode( iface );
1606 return node_get_base_name(&This->node, p);
1609 static HRESULT WINAPI unknode_transformNodeToObject(
1611 IXMLDOMNode* domNode, VARIANT var1)
1613 unknode *This = unknode_from_IXMLDOMNode( iface );
1614 FIXME("(%p)->(%p %s)\n", This, domNode, debugstr_variant(&var1));
1618 static const struct IXMLDOMNodeVtbl unknode_vtbl =
1620 unknode_QueryInterface,
1623 unknode_GetTypeInfoCount,
1624 unknode_GetTypeInfo,
1625 unknode_GetIDsOfNames,
1627 unknode_get_nodeName,
1628 unknode_get_nodeValue,
1629 unknode_put_nodeValue,
1630 unknode_get_nodeType,
1631 unknode_get_parentNode,
1632 unknode_get_childNodes,
1633 unknode_get_firstChild,
1634 unknode_get_lastChild,
1635 unknode_get_previousSibling,
1636 unknode_get_nextSibling,
1637 unknode_get_attributes,
1638 unknode_insertBefore,
1639 unknode_replaceChild,
1640 unknode_removeChild,
1641 unknode_appendChild,
1642 unknode_hasChildNodes,
1643 unknode_get_ownerDocument,
1645 unknode_get_nodeTypeString,
1648 unknode_get_specified,
1649 unknode_get_definition,
1650 unknode_get_nodeTypedValue,
1651 unknode_put_nodeTypedValue,
1652 unknode_get_dataType,
1653 unknode_put_dataType,
1655 unknode_transformNode,
1656 unknode_selectNodes,
1657 unknode_selectSingleNode,
1659 unknode_get_namespaceURI,
1661 unknode_get_baseName,
1662 unknode_transformNodeToObject
1665 IXMLDOMNode *create_node( xmlNodePtr node )
1674 TRACE("type %d\n", node->type);
1677 case XML_ELEMENT_NODE:
1678 pUnk = create_element( node );
1680 case XML_ATTRIBUTE_NODE:
1681 pUnk = create_attribute( node );
1684 pUnk = create_text( node );
1686 case XML_CDATA_SECTION_NODE:
1687 pUnk = create_cdata( node );
1689 case XML_ENTITY_REF_NODE:
1690 pUnk = create_doc_entity_ref( node );
1693 pUnk = create_pi( node );
1695 case XML_COMMENT_NODE:
1696 pUnk = create_comment( node );
1698 case XML_DOCUMENT_NODE:
1699 pUnk = create_domdoc( node );
1701 case XML_DOCUMENT_FRAG_NODE:
1702 pUnk = create_doc_fragment( node );
1705 pUnk = create_doc_type( node );
1710 FIXME("only creating basic node for type %d\n", node->type);
1712 new_node = heap_alloc(sizeof(unknode));
1716 new_node->IXMLDOMNode_iface.lpVtbl = &unknode_vtbl;
1718 init_xmlnode(&new_node->node, node, &new_node->IXMLDOMNode_iface, NULL);
1719 pUnk = (IUnknown*)&new_node->IXMLDOMNode_iface;
1723 hr = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMNode, (LPVOID*)&ret);
1724 IUnknown_Release(pUnk);
1725 if(FAILED(hr)) return NULL;