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 (xmlnode *)((char*)iface - FIELD_OFFSET(xmlnode, lpVtbl));
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 static HRESULT WINAPI xmlnode_removeChild(
406 IXMLDOMNode* childNode,
407 IXMLDOMNode** oldChild)
409 xmlnode *This = impl_from_IXMLDOMNode( iface );
412 TRACE("(%p)->(%p %p)\n", This, childNode, oldChild);
414 if(!childNode) return E_INVALIDARG;
419 child_node = get_node_obj(childNode);
421 FIXME("childNode is not our node implementation\n");
425 if(child_node->node->parent != This->node)
427 WARN("childNode %p is not a child of %p\n", childNode, iface);
431 xmlUnlinkNode(child_node->node);
435 IXMLDOMNode_AddRef(childNode);
436 *oldChild = childNode;
442 static HRESULT WINAPI xmlnode_appendChild(
444 IXMLDOMNode* newChild,
445 IXMLDOMNode** outNewChild)
447 xmlnode *This = impl_from_IXMLDOMNode( iface );
452 TRACE("(%p)->(%p %p)\n", This, newChild, outNewChild);
454 hr = IXMLDOMNode_get_nodeType(newChild, &type);
455 if(FAILED(hr) || type == NODE_ATTRIBUTE) {
456 if(outNewChild) *outNewChild = NULL;
461 return IXMLDOMNode_insertBefore(This->iface, newChild, var, outNewChild);
464 static HRESULT WINAPI xmlnode_hasChildNodes(
466 VARIANT_BOOL* hasChild)
468 xmlnode *This = impl_from_IXMLDOMNode( iface );
470 TRACE("(%p)->(%p)\n", This, hasChild);
474 if (!This->node->children)
476 *hasChild = VARIANT_FALSE;
480 *hasChild = VARIANT_TRUE;
484 static HRESULT WINAPI xmlnode_get_ownerDocument(
486 IXMLDOMDocument** DOMDocument)
488 xmlnode *This = impl_from_IXMLDOMNode( iface );
490 TRACE("(%p)->(%p)\n", This, DOMDocument);
492 return DOMDocument_create_from_xmldoc(This->node->doc, (IXMLDOMDocument3**)DOMDocument);
495 HRESULT node_clone(xmlnode *This, VARIANT_BOOL deep, IXMLDOMNode **cloneNode)
500 if(!cloneNode) return E_INVALIDARG;
502 clone = xmlCopyNode(This->node, deep ? 1 : 2);
505 clone->doc = This->node->doc;
506 xmldoc_add_orphan(clone->doc, clone);
508 node = create_node(clone);
511 ERR("Copy failed\n");
519 ERR("Copy failed\n");
526 static inline xmlChar* trim_whitespace(xmlChar* str)
534 while (*ret && isspace(*ret))
536 len = xmlStrlen(ret);
537 while (isspace(ret[len-1]))
540 ret = xmlStrndup(ret, len);
545 static xmlChar* do_get_text(xmlNodePtr node)
549 BOOL preserving = is_preserving_whitespace(node);
553 str = xmlNodeGetContent(node);
557 xmlElementType prev_type = XML_TEXT_NODE;
559 str = xmlStrdup(BAD_CAST "");
560 for (child = node->children; child != NULL; child = child->next)
564 case XML_ELEMENT_NODE:
565 tmp = do_get_text(child);
568 case XML_CDATA_SECTION_NODE:
569 case XML_ENTITY_REF_NODE:
570 case XML_ENTITY_NODE:
571 tmp = xmlNodeGetContent(child);
582 if (prev_type == XML_ELEMENT_NODE && child->type == XML_ELEMENT_NODE)
583 str = xmlStrcat(str, BAD_CAST " ");
584 str = xmlStrcat(str, tmp);
585 prev_type = child->type;
594 case XML_ELEMENT_NODE:
596 case XML_ENTITY_REF_NODE:
597 case XML_ENTITY_NODE:
598 case XML_DOCUMENT_NODE:
599 case XML_DOCUMENT_FRAG_NODE:
601 str = trim_whitespace(str);
610 static HRESULT WINAPI xmlnode_get_text(
614 xmlnode *This = impl_from_IXMLDOMNode( iface );
618 TRACE("(%p, type %d)->(%p)\n", This, This->node->type, text);
623 pContent = do_get_text((xmlNodePtr)This->node);
626 str = bstr_from_xmlChar(pContent);
630 /* Always return a string. */
631 if (!str) str = SysAllocStringLen( NULL, 0 );
633 TRACE("%p %s\n", This, debugstr_w(str) );
639 HRESULT node_put_text(xmlnode *This, BSTR text)
643 TRACE("(%p)->(%s)\n", This, debugstr_w(text));
645 str = xmlChar_from_wchar(text);
647 /* Escape the string. */
648 str2 = xmlEncodeEntitiesReentrant(This->node->doc, str);
651 xmlNodeSetContent(This->node, str2);
657 static inline BYTE hex_to_byte(xmlChar c)
659 if(c <= '9') return c-'0';
660 if(c <= 'F') return c-'A'+10;
664 static inline BYTE base64_to_byte(xmlChar c)
666 if(c == '+') return 62;
667 if(c == '/') return 63;
668 if(c <= '9') return c-'0'+52;
669 if(c <= 'Z') return c-'A';
673 /* TODO: phasing this version out */
674 static inline HRESULT VARIANT_from_xmlChar(xmlChar *str, VARIANT *v, BSTR type)
676 if(!type || !lstrcmpiW(type, szString) ||
677 !lstrcmpiW(type, szNumber) || !lstrcmpiW(type, szUUID))
680 V_BSTR(v) = bstr_from_xmlChar(str);
683 return E_OUTOFMEMORY;
685 else if(!lstrcmpiW(type, szDateTime) || !lstrcmpiW(type, szDateTimeTZ) ||
686 !lstrcmpiW(type, szDate) || !lstrcmpiW(type, szTime) ||
687 !lstrcmpiW(type, szTimeTZ))
697 st.wDayOfWeek = st.wHour = st.wMinute = st.wSecond = st.wMilliseconds = 0;
699 V_VT(&src) = VT_BSTR;
700 V_BSTR(&src) = bstr_from_xmlChar(str);
703 return E_OUTOFMEMORY;
706 e = p + SysStringLen(V_BSTR(&src));
708 if(p+4<e && *(p+4)=='-') /* parse date (yyyy-mm-dd) */
711 st.wMonth = atoiW(p+5);
712 st.wDay = atoiW(p+8);
718 if(p+2<e && *(p+2)==':') /* parse time (hh:mm:ss.?) */
721 st.wMinute = atoiW(p+3);
722 st.wSecond = atoiW(p+6);
728 while(isdigitW(*p)) p++;
732 SystemTimeToVariantTime(&st, &date);
736 if(*p == '+') /* parse timezone offset (+hh:mm) */
737 V_DATE(v) += (DOUBLE)atoiW(p+1)/24 + (DOUBLE)atoiW(p+4)/1440;
738 else if(*p == '-') /* parse timezone offset (-hh:mm) */
739 V_DATE(v) -= (DOUBLE)atoiW(p+1)/24 + (DOUBLE)atoiW(p+4)/1440;
743 else if(!lstrcmpiW(type, szBinHex))
748 len = xmlStrlen(str)/2;
752 V_VT(v) = (VT_ARRAY|VT_UI1);
753 V_ARRAY(v) = SafeArrayCreate(VT_UI1, 1, &sab);
756 return E_OUTOFMEMORY;
759 ((BYTE*)V_ARRAY(v)->pvData)[i] = (hex_to_byte(str[2*i])<<4)
760 + hex_to_byte(str[2*i+1]);
762 else if(!lstrcmpiW(type, szBinBase64))
767 len = xmlStrlen(str);
768 if(str[len-2] == '=') i = 2;
769 else if(str[len-1] == '=') i = 1;
773 sab.cElements = len/4*3-i;
775 V_VT(v) = (VT_ARRAY|VT_UI1);
776 V_ARRAY(v) = SafeArrayCreate(VT_UI1, 1, &sab);
779 return E_OUTOFMEMORY;
781 for(i=0; i<len/4; i++)
783 ((BYTE*)V_ARRAY(v)->pvData)[3*i] = (base64_to_byte(str[4*i])<<2)
784 + (base64_to_byte(str[4*i+1])>>4);
785 if(3*i+1 < sab.cElements)
786 ((BYTE*)V_ARRAY(v)->pvData)[3*i+1] = (base64_to_byte(str[4*i+1])<<4)
787 + (base64_to_byte(str[4*i+2])>>2);
788 if(3*i+2 < sab.cElements)
789 ((BYTE*)V_ARRAY(v)->pvData)[3*i+2] = (base64_to_byte(str[4*i+2])<<6)
790 + base64_to_byte(str[4*i+3]);
798 if(!lstrcmpiW(type, szInt) || !lstrcmpiW(type, szI4))
800 else if(!lstrcmpiW(type, szFixed))
802 else if(!lstrcmpiW(type, szBoolean))
804 else if(!lstrcmpiW(type, szI1))
806 else if(!lstrcmpiW(type, szI2))
808 else if(!lstrcmpiW(type, szIU1))
810 else if(!lstrcmpiW(type, szIU2))
812 else if(!lstrcmpiW(type, szIU4))
814 else if(!lstrcmpiW(type, szR4))
816 else if(!lstrcmpiW(type, szR8) || !lstrcmpiW(type, szFloat))
820 FIXME("Type handling not yet implemented\n");
824 V_VT(&src) = VT_BSTR;
825 V_BSTR(&src) = bstr_from_xmlChar(str);
828 return E_OUTOFMEMORY;
830 hres = VariantChangeTypeEx(v, &src, MAKELCID(MAKELANGID(
831 LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT),0, V_VT(v));
839 static HRESULT WINAPI xmlnode_get_nodeTypedValue(
843 xmlnode *This = impl_from_IXMLDOMNode( iface );
846 HRESULT hres = S_FALSE;
848 TRACE("(%p)->(%p)\n", This, typedValue);
853 V_VT(typedValue) = VT_NULL;
855 if (This->node->type == XML_ENTITY_REF_NODE)
858 hres = IXMLDOMNode_get_dataType(This->iface, &type);
861 return IXMLDOMNode_get_nodeValue(This->iface, typedValue);
863 content = xmlNodeGetContent(This->node);
864 hres = VARIANT_from_xmlChar(content, typedValue, hres==S_OK ? V_BSTR(&type) : NULL);
870 FIXME("need to handle node type %i\n", This->node->type);
876 static HRESULT WINAPI xmlnode_put_nodeTypedValue(
880 xmlnode *This = impl_from_IXMLDOMNode( iface );
885 static HRESULT WINAPI xmlnode_put_dataType(
889 xmlnode *This = impl_from_IXMLDOMNode( iface );
891 TRACE("(%p)->(%s)\n", This, debugstr_w(dtName));
896 FIXME("need to handle node type %i\n", This->node->type);
901 BSTR EnsureCorrectEOL(BSTR sInput)
908 nLen = SysStringLen(sInput);
909 /* Count line endings */
910 for(i=0; i < nLen; i++)
912 if(sInput[i] == '\n')
916 TRACE("len=%d, num=%d\n", nLen, nNum);
918 /* Add linefeed as needed */
922 sNew = SysAllocStringLen(NULL, nLen + nNum+1);
923 for(i=0; i < nLen; i++)
925 if(sInput[i] == '\n')
927 sNew[i+nPlace] = '\r';
930 sNew[i+nPlace] = sInput[i];
933 SysFreeString(sInput);
940 TRACE("len %d\n", SysStringLen(sNew));
945 /* Removes encoding information and last character (nullbyte) */
946 static BSTR EnsureNoEncoding(BSTR sInput)
948 static const WCHAR wszEncoding[] = {'e','n','c','o','d','i','n','g','='};
953 while(*pBeg != '\n' && memcmp(pBeg, wszEncoding, sizeof(wszEncoding)))
958 SysReAllocStringLen(&sInput, sInput, SysStringLen(sInput)-1);
963 pEnd = pBeg + sizeof(wszEncoding)/sizeof(WCHAR) + 2;
964 while(*pEnd != '\"') pEnd++;
967 sNew = SysAllocStringLen(NULL,
968 pBeg-sInput + SysStringLen(sInput)-(pEnd-sInput)-1);
969 memcpy(sNew, sInput, (pBeg-sInput)*sizeof(WCHAR));
970 memcpy(&sNew[pBeg-sInput], pEnd, (SysStringLen(sInput)-(pEnd-sInput)-1)*sizeof(WCHAR));
972 SysFreeString(sInput);
977 * We are trying to replicate the same behaviour as msxml by converting
978 * line endings to \r\n and using indents as \t. The problem is that msxml
979 * only formats nodes that have a line ending. Using libxml we cannot
980 * reproduce behaviour exactly.
983 HRESULT node_get_xml(xmlnode *This, BOOL ensure_eol, BOOL ensure_no_encoding, BSTR *ret)
985 xmlBufferPtr xml_buf;
994 xml_buf = xmlBufferCreate();
996 return E_OUTOFMEMORY;
998 xmldecl = xmldoc_unlink_xmldecl( This->node->doc );
1000 size = xmlNodeDump(xml_buf, This->node->doc, This->node, 0, 1);
1002 const xmlChar *buf_content;
1005 /* Attribute Nodes return a space in front of their name */
1006 buf_content = xmlBufferContent(xml_buf);
1008 content = bstr_from_xmlChar(buf_content + (buf_content[0] == ' ' ? 1 : 0));
1010 content = EnsureCorrectEOL(content);
1011 if(ensure_no_encoding)
1012 content = EnsureNoEncoding(content);
1016 *ret = SysAllocStringLen(NULL, 0);
1019 xmlBufferFree(xml_buf);
1020 xmldoc_link_xmldecl( This->node->doc, xmldecl );
1021 return *ret ? S_OK : E_OUTOFMEMORY;
1024 static HRESULT WINAPI xmlnode_transformNode(
1026 IXMLDOMNode* styleSheet,
1029 #ifdef SONAME_LIBXSLT
1030 xmlnode *This = impl_from_IXMLDOMNode( iface );
1031 xmlnode *pStyleSheet = NULL;
1032 xsltStylesheetPtr xsltSS = NULL;
1033 xmlDocPtr result = NULL;
1035 TRACE("(%p)->(%p %p)\n", This, styleSheet, xmlString);
1037 if (!libxslt_handle)
1039 if(!styleSheet || !xmlString)
1040 return E_INVALIDARG;
1044 pStyleSheet = get_node_obj(styleSheet);
1046 FIXME("styleSheet is not our xmlnode implementation\n");
1050 xsltSS = pxsltParseStylesheetDoc( pStyleSheet->node->doc);
1053 result = pxsltApplyStylesheet(xsltSS, This->node->doc, NULL);
1056 const xmlChar *pContent;
1058 if(result->type == XML_HTML_DOCUMENT_NODE)
1060 xmlOutputBufferPtr pOutput = xmlAllocOutputBuffer(NULL);
1063 htmlDocContentDumpOutput(pOutput, result->doc, NULL);
1064 pContent = xmlBufferContent(pOutput->buffer);
1065 *xmlString = bstr_from_xmlChar(pContent);
1066 xmlOutputBufferClose(pOutput);
1071 xmlBufferPtr pXmlBuf;
1074 pXmlBuf = xmlBufferCreate();
1077 nSize = xmlNodeDump(pXmlBuf, NULL, (xmlNodePtr)result, 0, 0);
1080 pContent = xmlBufferContent(pXmlBuf);
1081 *xmlString = bstr_from_xmlChar(pContent);
1083 xmlBufferFree(pXmlBuf);
1088 /* libxslt "helpfully" frees the XML document the stylesheet was
1089 generated from, too */
1091 pxsltFreeStylesheet(xsltSS);
1094 if(*xmlString == NULL)
1095 *xmlString = SysAllocStringLen(NULL, 0);
1099 FIXME("libxslt headers were not found at compile time\n");
1104 static HRESULT WINAPI xmlnode_selectNodes(
1107 IXMLDOMNodeList** resultList)
1109 xmlnode *This = impl_from_IXMLDOMNode( iface );
1113 TRACE("(%p)->(%s %p)\n", This, debugstr_w(queryString), resultList );
1115 if (!queryString || !resultList) return E_INVALIDARG;
1117 str = xmlChar_from_wchar(queryString);
1118 hr = queryresult_create(This->node, str, resultList);
1124 static HRESULT WINAPI xmlnode_selectSingleNode(
1127 IXMLDOMNode** resultNode)
1129 xmlnode *This = impl_from_IXMLDOMNode( iface );
1130 IXMLDOMNodeList *list;
1133 TRACE("(%p)->(%s %p)\n", This, debugstr_w(queryString), resultNode );
1135 r = IXMLDOMNode_selectNodes(This->iface, queryString, &list);
1138 r = IXMLDOMNodeList_nextNode(list, resultNode);
1139 IXMLDOMNodeList_Release(list);
1144 static HRESULT WINAPI xmlnode_get_namespaceURI(
1148 xmlnode *This = impl_from_IXMLDOMNode( iface );
1151 TRACE("(%p)->(%p)\n", This, namespaceURI );
1154 return E_INVALIDARG;
1156 *namespaceURI = NULL;
1158 if ((ns = xmlGetNsList(This->node->doc, This->node)))
1160 if (ns[0]->href) *namespaceURI = bstr_from_xmlChar( ns[0]->href );
1164 TRACE("uri: %s\n", debugstr_w(*namespaceURI));
1166 return *namespaceURI ? S_OK : S_FALSE;
1169 HRESULT node_get_prefix(xmlnode *This, BSTR *prefix)
1173 if (!prefix) return E_INVALIDARG;
1177 if ((ns = xmlGetNsList(This->node->doc, This->node)))
1179 if (ns[0]->prefix) *prefix = bstr_from_xmlChar( ns[0]->prefix );
1183 TRACE("prefix: %s\n", debugstr_w(*prefix));
1185 return *prefix ? S_OK : S_FALSE;
1188 HRESULT node_get_base_name(xmlnode *This, BSTR *name)
1190 if (!name) return E_INVALIDARG;
1192 *name = bstr_from_xmlChar(This->node->name);
1193 if (!*name) return E_OUTOFMEMORY;
1195 TRACE("returning %s\n", debugstr_w(*name));
1200 static HRESULT WINAPI xmlnode_transformNodeToObject(
1202 IXMLDOMNode* stylesheet,
1203 VARIANT outputObject)
1205 xmlnode *This = impl_from_IXMLDOMNode( iface );
1206 FIXME("(%p)->(%p)\n", This, stylesheet);
1210 static const struct IXMLDOMNodeVtbl xmlnode_vtbl =
1232 xmlnode_removeChild,
1233 xmlnode_appendChild,
1234 xmlnode_hasChildNodes,
1235 xmlnode_get_ownerDocument,
1242 xmlnode_get_nodeTypedValue,
1243 xmlnode_put_nodeTypedValue,
1245 xmlnode_put_dataType,
1247 xmlnode_transformNode,
1248 xmlnode_selectNodes,
1249 xmlnode_selectSingleNode,
1251 xmlnode_get_namespaceURI,
1254 xmlnode_transformNodeToObject,
1257 void destroy_xmlnode(xmlnode *This)
1260 xmldoc_release(This->node->doc);
1263 void init_xmlnode(xmlnode *This, xmlNodePtr node, IXMLDOMNode *node_iface, dispex_static_data_t *dispex_data)
1266 xmldoc_add_ref( node->doc );
1268 This->lpVtbl = &xmlnode_vtbl;
1270 This->iface = node_iface;
1273 init_dispex(&This->dispex, (IUnknown*)This->iface, dispex_data);
1275 This->dispex.outer = NULL;
1280 const IXMLDOMNodeVtbl *lpVtbl;
1284 static inline unknode *impl_from_unkIXMLDOMNode(IXMLDOMNode *iface)
1286 return (unknode *)((char*)iface - FIELD_OFFSET(unknode, lpVtbl));
1289 static HRESULT WINAPI unknode_QueryInterface(
1294 unknode *This = impl_from_unkIXMLDOMNode( iface );
1296 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
1298 if (IsEqualGUID(riid, &IID_IUnknown)) {
1300 }else if (IsEqualGUID( riid, &IID_IDispatch) ||
1301 IsEqualGUID( riid, &IID_IXMLDOMNode)) {
1302 *ppvObject = &This->lpVtbl;
1303 }else if(node_query_interface(&This->node, riid, ppvObject)) {
1304 return *ppvObject ? S_OK : E_NOINTERFACE;
1306 FIXME("interface %s not implemented\n", debugstr_guid(riid));
1308 return E_NOINTERFACE;
1311 IUnknown_AddRef((IUnknown*)*ppvObject);
1315 static ULONG WINAPI unknode_AddRef(
1316 IXMLDOMNode *iface )
1318 unknode *This = impl_from_unkIXMLDOMNode( iface );
1320 return InterlockedIncrement(&This->ref);
1323 static ULONG WINAPI unknode_Release(
1324 IXMLDOMNode *iface )
1326 unknode *This = impl_from_unkIXMLDOMNode( iface );
1329 ref = InterlockedDecrement( &This->ref );
1331 destroy_xmlnode(&This->node);
1338 static HRESULT WINAPI unknode_GetTypeInfoCount(
1342 unknode *This = impl_from_unkIXMLDOMNode( iface );
1344 TRACE("(%p)->(%p)\n", This, pctinfo);
1351 static HRESULT WINAPI unknode_GetTypeInfo(
1355 ITypeInfo** ppTInfo )
1357 unknode *This = impl_from_unkIXMLDOMNode( iface );
1360 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1362 hr = get_typeinfo(IXMLDOMNode_tid, ppTInfo);
1367 static HRESULT WINAPI unknode_GetIDsOfNames(
1370 LPOLESTR* rgszNames,
1375 unknode *This = impl_from_unkIXMLDOMNode( iface );
1377 ITypeInfo *typeinfo;
1380 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1383 if(!rgszNames || cNames == 0 || !rgDispId)
1384 return E_INVALIDARG;
1386 hr = get_typeinfo(IXMLDOMNode_tid, &typeinfo);
1389 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1390 ITypeInfo_Release(typeinfo);
1396 static HRESULT WINAPI unknode_Invoke(
1398 DISPID dispIdMember,
1402 DISPPARAMS* pDispParams,
1403 VARIANT* pVarResult,
1404 EXCEPINFO* pExcepInfo,
1407 unknode *This = impl_from_unkIXMLDOMNode( iface );
1408 ITypeInfo *typeinfo;
1411 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1412 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1414 hr = get_typeinfo(IXMLDOMNode_tid, &typeinfo);
1417 hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
1418 pVarResult, pExcepInfo, puArgErr);
1419 ITypeInfo_Release(typeinfo);
1425 static HRESULT WINAPI unknode_get_nodeName(
1429 unknode *This = impl_from_unkIXMLDOMNode( iface );
1431 FIXME("(%p)->(%p)\n", This, p);
1433 return node_get_nodeName(&This->node, p);
1436 static HRESULT WINAPI unknode_get_nodeValue(
1440 unknode *This = impl_from_unkIXMLDOMNode( iface );
1442 FIXME("(%p)->(%p)\n", This, value);
1445 return E_INVALIDARG;
1447 V_VT(value) = VT_NULL;
1451 static HRESULT WINAPI unknode_put_nodeValue(
1455 unknode *This = impl_from_unkIXMLDOMNode( iface );
1456 FIXME("(%p)->(v%d)\n", This, V_VT(&value));
1460 static HRESULT WINAPI unknode_get_nodeType(
1462 DOMNodeType* domNodeType )
1464 unknode *This = impl_from_unkIXMLDOMNode( iface );
1466 FIXME("(%p)->(%p)\n", This, domNodeType);
1468 *domNodeType = This->node.node->type;
1472 static HRESULT WINAPI unknode_get_parentNode(
1474 IXMLDOMNode** parent )
1476 unknode *This = impl_from_unkIXMLDOMNode( iface );
1477 FIXME("(%p)->(%p)\n", This, parent);
1478 if (!parent) return E_INVALIDARG;
1483 static HRESULT WINAPI unknode_get_childNodes(
1485 IXMLDOMNodeList** outList)
1487 unknode *This = impl_from_unkIXMLDOMNode( iface );
1489 TRACE("(%p)->(%p)\n", This, outList);
1491 return node_get_child_nodes(&This->node, outList);
1494 static HRESULT WINAPI unknode_get_firstChild(
1496 IXMLDOMNode** domNode)
1498 unknode *This = impl_from_unkIXMLDOMNode( iface );
1500 TRACE("(%p)->(%p)\n", This, domNode);
1502 return node_get_first_child(&This->node, domNode);
1505 static HRESULT WINAPI unknode_get_lastChild(
1507 IXMLDOMNode** domNode)
1509 unknode *This = impl_from_unkIXMLDOMNode( iface );
1511 TRACE("(%p)->(%p)\n", This, domNode);
1513 return node_get_last_child(&This->node, domNode);
1516 static HRESULT WINAPI unknode_get_previousSibling(
1518 IXMLDOMNode** domNode)
1520 unknode *This = impl_from_unkIXMLDOMNode( iface );
1522 TRACE("(%p)->(%p)\n", This, domNode);
1524 return node_get_previous_sibling(&This->node, domNode);
1527 static HRESULT WINAPI unknode_get_nextSibling(
1529 IXMLDOMNode** domNode)
1531 unknode *This = impl_from_unkIXMLDOMNode( iface );
1533 TRACE("(%p)->(%p)\n", This, domNode);
1535 return node_get_next_sibling(&This->node, domNode);
1538 static HRESULT WINAPI unknode_get_attributes(
1540 IXMLDOMNamedNodeMap** attributeMap)
1542 unknode *This = impl_from_unkIXMLDOMNode( iface );
1544 FIXME("(%p)->(%p)\n", This, attributeMap);
1546 return return_null_ptr((void**)attributeMap);
1549 static HRESULT WINAPI unknode_insertBefore(
1551 IXMLDOMNode* newNode, VARIANT refChild,
1552 IXMLDOMNode** outOldNode)
1554 unknode *This = impl_from_unkIXMLDOMNode( iface );
1556 FIXME("(%p)->(%p x%d %p)\n", This, newNode, V_VT(&refChild), outOldNode);
1558 return node_insert_before(&This->node, newNode, &refChild, outOldNode);
1561 static HRESULT WINAPI unknode_replaceChild(
1563 IXMLDOMNode* newNode,
1564 IXMLDOMNode* oldNode,
1565 IXMLDOMNode** outOldNode)
1567 unknode *This = impl_from_unkIXMLDOMNode( iface );
1569 FIXME("(%p)->(%p %p %p)\n", This, newNode, oldNode, outOldNode);
1571 return node_replace_child(&This->node, newNode, oldNode, outOldNode);
1574 static HRESULT WINAPI unknode_removeChild(
1576 IXMLDOMNode* domNode, IXMLDOMNode** oldNode)
1578 unknode *This = impl_from_unkIXMLDOMNode( iface );
1579 return IXMLDOMNode_removeChild( IXMLDOMNode_from_impl(&This->node), domNode, oldNode );
1582 static HRESULT WINAPI unknode_appendChild(
1584 IXMLDOMNode* newNode, IXMLDOMNode** outNewNode)
1586 unknode *This = impl_from_unkIXMLDOMNode( iface );
1587 return IXMLDOMNode_appendChild( IXMLDOMNode_from_impl(&This->node), newNode, outNewNode );
1590 static HRESULT WINAPI unknode_hasChildNodes(
1592 VARIANT_BOOL* pbool)
1594 unknode *This = impl_from_unkIXMLDOMNode( iface );
1595 return IXMLDOMNode_hasChildNodes( IXMLDOMNode_from_impl(&This->node), pbool );
1598 static HRESULT WINAPI unknode_get_ownerDocument(
1600 IXMLDOMDocument** domDocument)
1602 unknode *This = impl_from_unkIXMLDOMNode( iface );
1603 return IXMLDOMNode_get_ownerDocument( IXMLDOMNode_from_impl(&This->node), domDocument );
1606 static HRESULT WINAPI unknode_cloneNode(
1608 VARIANT_BOOL pbool, IXMLDOMNode** outNode)
1610 unknode *This = impl_from_unkIXMLDOMNode( iface );
1611 return IXMLDOMNode_cloneNode( IXMLDOMNode_from_impl(&This->node), pbool, outNode );
1614 static HRESULT WINAPI unknode_get_nodeTypeString(
1618 unknode *This = impl_from_unkIXMLDOMNode( iface );
1620 FIXME("(%p)->(%p)\n", This, p);
1622 return node_get_nodeName(&This->node, p);
1625 static HRESULT WINAPI unknode_get_text(
1629 unknode *This = impl_from_unkIXMLDOMNode( iface );
1630 return IXMLDOMNode_get_text( IXMLDOMNode_from_impl(&This->node), p );
1633 static HRESULT WINAPI unknode_put_text(
1637 unknode *This = impl_from_unkIXMLDOMNode( iface );
1638 return IXMLDOMNode_put_text( IXMLDOMNode_from_impl(&This->node), p );
1641 static HRESULT WINAPI unknode_get_specified(
1643 VARIANT_BOOL* isSpecified)
1645 unknode *This = impl_from_unkIXMLDOMNode( iface );
1646 FIXME("(%p)->(%p) stub!\n", This, isSpecified);
1647 *isSpecified = VARIANT_TRUE;
1651 static HRESULT WINAPI unknode_get_definition(
1653 IXMLDOMNode** definitionNode)
1655 unknode *This = impl_from_unkIXMLDOMNode( iface );
1656 FIXME("(%p)->(%p)\n", This, definitionNode);
1660 static HRESULT WINAPI unknode_get_nodeTypedValue(
1664 unknode *This = impl_from_unkIXMLDOMNode( iface );
1665 return IXMLDOMNode_get_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), var1 );
1668 static HRESULT WINAPI unknode_put_nodeTypedValue(
1672 unknode *This = impl_from_unkIXMLDOMNode( iface );
1673 return IXMLDOMNode_put_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), var1 );
1676 static HRESULT WINAPI unknode_get_dataType(
1680 unknode *This = impl_from_unkIXMLDOMNode( iface );
1681 return IXMLDOMNode_get_dataType( IXMLDOMNode_from_impl(&This->node), var1 );
1684 static HRESULT WINAPI unknode_put_dataType(
1688 unknode *This = impl_from_unkIXMLDOMNode( iface );
1689 return IXMLDOMNode_put_dataType( IXMLDOMNode_from_impl(&This->node), p );
1692 static HRESULT WINAPI unknode_get_xml(
1696 unknode *This = impl_from_unkIXMLDOMNode( iface );
1698 FIXME("(%p)->(%p)\n", This, p);
1700 return node_get_xml(&This->node, FALSE, FALSE, p);
1703 static HRESULT WINAPI unknode_transformNode(
1705 IXMLDOMNode* domNode, BSTR* p)
1707 unknode *This = impl_from_unkIXMLDOMNode( iface );
1708 return IXMLDOMNode_transformNode( IXMLDOMNode_from_impl(&This->node), domNode, p );
1711 static HRESULT WINAPI unknode_selectNodes(
1713 BSTR p, IXMLDOMNodeList** outList)
1715 unknode *This = impl_from_unkIXMLDOMNode( iface );
1716 return IXMLDOMNode_selectNodes( IXMLDOMNode_from_impl(&This->node), p, outList );
1719 static HRESULT WINAPI unknode_selectSingleNode(
1721 BSTR p, IXMLDOMNode** outNode)
1723 unknode *This = impl_from_unkIXMLDOMNode( iface );
1724 return IXMLDOMNode_selectSingleNode( IXMLDOMNode_from_impl(&This->node), p, outNode );
1727 static HRESULT WINAPI unknode_get_parsed(
1729 VARIANT_BOOL* isParsed)
1731 unknode *This = impl_from_unkIXMLDOMNode( iface );
1732 FIXME("(%p)->(%p) stub!\n", This, isParsed);
1733 *isParsed = VARIANT_TRUE;
1737 static HRESULT WINAPI unknode_get_namespaceURI(
1741 unknode *This = impl_from_unkIXMLDOMNode( iface );
1742 return IXMLDOMNode_get_namespaceURI( IXMLDOMNode_from_impl(&This->node), p );
1745 static HRESULT WINAPI unknode_get_prefix(
1749 unknode *This = impl_from_unkIXMLDOMNode( iface );
1750 return IXMLDOMNode_get_prefix( IXMLDOMNode_from_impl(&This->node), p );
1753 static HRESULT WINAPI unknode_get_baseName(
1757 unknode *This = impl_from_unkIXMLDOMNode( iface );
1758 return IXMLDOMNode_get_baseName( IXMLDOMNode_from_impl(&This->node), p );
1761 static HRESULT WINAPI unknode_transformNodeToObject(
1763 IXMLDOMNode* domNode, VARIANT var1)
1765 unknode *This = impl_from_unkIXMLDOMNode( iface );
1766 return IXMLDOMNode_transformNodeToObject( IXMLDOMNode_from_impl(&This->node), domNode, var1 );
1769 static const struct IXMLDOMNodeVtbl unknode_vtbl =
1771 unknode_QueryInterface,
1774 unknode_GetTypeInfoCount,
1775 unknode_GetTypeInfo,
1776 unknode_GetIDsOfNames,
1778 unknode_get_nodeName,
1779 unknode_get_nodeValue,
1780 unknode_put_nodeValue,
1781 unknode_get_nodeType,
1782 unknode_get_parentNode,
1783 unknode_get_childNodes,
1784 unknode_get_firstChild,
1785 unknode_get_lastChild,
1786 unknode_get_previousSibling,
1787 unknode_get_nextSibling,
1788 unknode_get_attributes,
1789 unknode_insertBefore,
1790 unknode_replaceChild,
1791 unknode_removeChild,
1792 unknode_appendChild,
1793 unknode_hasChildNodes,
1794 unknode_get_ownerDocument,
1796 unknode_get_nodeTypeString,
1799 unknode_get_specified,
1800 unknode_get_definition,
1801 unknode_get_nodeTypedValue,
1802 unknode_put_nodeTypedValue,
1803 unknode_get_dataType,
1804 unknode_put_dataType,
1806 unknode_transformNode,
1807 unknode_selectNodes,
1808 unknode_selectSingleNode,
1810 unknode_get_namespaceURI,
1812 unknode_get_baseName,
1813 unknode_transformNodeToObject
1816 IXMLDOMNode *create_node( xmlNodePtr node )
1825 TRACE("type %d\n", node->type);
1828 case XML_ELEMENT_NODE:
1829 pUnk = create_element( node );
1831 case XML_ATTRIBUTE_NODE:
1832 pUnk = create_attribute( node );
1835 pUnk = create_text( node );
1837 case XML_CDATA_SECTION_NODE:
1838 pUnk = create_cdata( node );
1840 case XML_ENTITY_REF_NODE:
1841 pUnk = create_doc_entity_ref( node );
1844 pUnk = create_pi( node );
1846 case XML_COMMENT_NODE:
1847 pUnk = create_comment( node );
1849 case XML_DOCUMENT_NODE:
1850 pUnk = create_domdoc( node );
1852 case XML_DOCUMENT_FRAG_NODE:
1853 pUnk = create_doc_fragment( node );
1856 pUnk = create_doc_type( node );
1861 FIXME("only creating basic node for type %d\n", node->type);
1863 new_node = heap_alloc(sizeof(unknode));
1867 new_node->lpVtbl = &unknode_vtbl;
1869 init_xmlnode(&new_node->node, node, (IXMLDOMNode*)&new_node->lpVtbl, NULL);
1870 pUnk = (IUnknown*)&new_node->lpVtbl;
1874 hr = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMNode, (LPVOID*)&ret);
1875 IUnknown_Release(pUnk);
1876 if(FAILED(hr)) return NULL;