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 BSTR EnsureCorrectEOL(BSTR sInput)
883 nLen = SysStringLen(sInput);
884 /* Count line endings */
885 for(i=0; i < nLen; i++)
887 if(sInput[i] == '\n')
891 TRACE("len=%d, num=%d\n", nLen, nNum);
893 /* Add linefeed as needed */
897 sNew = SysAllocStringLen(NULL, nLen + nNum+1);
898 for(i=0; i < nLen; i++)
900 if(sInput[i] == '\n')
902 sNew[i+nPlace] = '\r';
905 sNew[i+nPlace] = sInput[i];
908 SysFreeString(sInput);
915 TRACE("len %d\n", SysStringLen(sNew));
920 /* Removes encoding information and last character (nullbyte) */
921 static BSTR EnsureNoEncoding(BSTR sInput)
923 static const WCHAR wszEncoding[] = {'e','n','c','o','d','i','n','g','='};
928 while(*pBeg != '\n' && memcmp(pBeg, wszEncoding, sizeof(wszEncoding)))
933 SysReAllocStringLen(&sInput, sInput, SysStringLen(sInput)-1);
938 pEnd = pBeg + sizeof(wszEncoding)/sizeof(WCHAR) + 2;
939 while(*pEnd != '\"') pEnd++;
942 sNew = SysAllocStringLen(NULL,
943 pBeg-sInput + SysStringLen(sInput)-(pEnd-sInput)-1);
944 memcpy(sNew, sInput, (pBeg-sInput)*sizeof(WCHAR));
945 memcpy(&sNew[pBeg-sInput], pEnd, (SysStringLen(sInput)-(pEnd-sInput)-1)*sizeof(WCHAR));
947 SysFreeString(sInput);
952 * We are trying to replicate the same behaviour as msxml by converting
953 * line endings to \r\n and using indents as \t. The problem is that msxml
954 * only formats nodes that have a line ending. Using libxml we cannot
955 * reproduce behaviour exactly.
958 HRESULT node_get_xml(xmlnode *This, BOOL ensure_eol, BOOL ensure_no_encoding, BSTR *ret)
960 xmlBufferPtr xml_buf;
969 xml_buf = xmlBufferCreate();
971 return E_OUTOFMEMORY;
973 xmldecl = xmldoc_unlink_xmldecl( This->node->doc );
975 size = xmlNodeDump(xml_buf, This->node->doc, This->node, 0, 1);
977 const xmlChar *buf_content;
980 /* Attribute Nodes return a space in front of their name */
981 buf_content = xmlBufferContent(xml_buf);
983 content = bstr_from_xmlChar(buf_content + (buf_content[0] == ' ' ? 1 : 0));
985 content = EnsureCorrectEOL(content);
986 if(ensure_no_encoding)
987 content = EnsureNoEncoding(content);
991 *ret = SysAllocStringLen(NULL, 0);
994 xmlBufferFree(xml_buf);
995 xmldoc_link_xmldecl( This->node->doc, xmldecl );
996 return *ret ? S_OK : E_OUTOFMEMORY;
999 static HRESULT WINAPI xmlnode_transformNode(
1001 IXMLDOMNode* styleSheet,
1004 #ifdef SONAME_LIBXSLT
1005 xmlnode *This = impl_from_IXMLDOMNode( iface );
1006 xmlnode *pStyleSheet = NULL;
1007 xsltStylesheetPtr xsltSS = NULL;
1008 xmlDocPtr result = NULL;
1010 TRACE("(%p)->(%p %p)\n", This, styleSheet, xmlString);
1012 if (!libxslt_handle)
1014 if(!styleSheet || !xmlString)
1015 return E_INVALIDARG;
1019 pStyleSheet = get_node_obj(styleSheet);
1021 FIXME("styleSheet is not our xmlnode implementation\n");
1025 xsltSS = pxsltParseStylesheetDoc( pStyleSheet->node->doc);
1028 result = pxsltApplyStylesheet(xsltSS, This->node->doc, NULL);
1031 const xmlChar *pContent;
1033 if(result->type == XML_HTML_DOCUMENT_NODE)
1035 xmlOutputBufferPtr pOutput = xmlAllocOutputBuffer(NULL);
1038 htmlDocContentDumpOutput(pOutput, result->doc, NULL);
1039 pContent = xmlBufferContent(pOutput->buffer);
1040 *xmlString = bstr_from_xmlChar(pContent);
1041 xmlOutputBufferClose(pOutput);
1046 xmlBufferPtr pXmlBuf;
1049 pXmlBuf = xmlBufferCreate();
1052 nSize = xmlNodeDump(pXmlBuf, NULL, (xmlNodePtr)result, 0, 0);
1055 pContent = xmlBufferContent(pXmlBuf);
1056 *xmlString = bstr_from_xmlChar(pContent);
1058 xmlBufferFree(pXmlBuf);
1063 /* libxslt "helpfully" frees the XML document the stylesheet was
1064 generated from, too */
1066 pxsltFreeStylesheet(xsltSS);
1069 if(*xmlString == NULL)
1070 *xmlString = SysAllocStringLen(NULL, 0);
1074 FIXME("libxslt headers were not found at compile time\n");
1079 static HRESULT WINAPI xmlnode_selectNodes(
1082 IXMLDOMNodeList** resultList)
1084 xmlnode *This = impl_from_IXMLDOMNode( iface );
1088 TRACE("(%p)->(%s %p)\n", This, debugstr_w(queryString), resultList );
1090 if (!queryString || !resultList) return E_INVALIDARG;
1092 str = xmlChar_from_wchar(queryString);
1093 hr = queryresult_create(This->node, str, resultList);
1099 static HRESULT WINAPI xmlnode_selectSingleNode(
1102 IXMLDOMNode** resultNode)
1104 xmlnode *This = impl_from_IXMLDOMNode( iface );
1105 IXMLDOMNodeList *list;
1108 TRACE("(%p)->(%s %p)\n", This, debugstr_w(queryString), resultNode );
1110 r = IXMLDOMNode_selectNodes(This->iface, queryString, &list);
1113 r = IXMLDOMNodeList_nextNode(list, resultNode);
1114 IXMLDOMNodeList_Release(list);
1119 static HRESULT WINAPI xmlnode_get_namespaceURI(
1123 xmlnode *This = impl_from_IXMLDOMNode( iface );
1126 TRACE("(%p)->(%p)\n", This, namespaceURI );
1129 return E_INVALIDARG;
1131 *namespaceURI = NULL;
1133 if ((ns = xmlGetNsList(This->node->doc, This->node)))
1135 if (ns[0]->href) *namespaceURI = bstr_from_xmlChar( ns[0]->href );
1139 TRACE("uri: %s\n", debugstr_w(*namespaceURI));
1141 return *namespaceURI ? S_OK : S_FALSE;
1144 HRESULT node_get_prefix(xmlnode *This, BSTR *prefix)
1148 if (!prefix) return E_INVALIDARG;
1152 if ((ns = xmlGetNsList(This->node->doc, This->node)))
1154 if (ns[0]->prefix) *prefix = bstr_from_xmlChar( ns[0]->prefix );
1158 TRACE("prefix: %s\n", debugstr_w(*prefix));
1160 return *prefix ? S_OK : S_FALSE;
1163 HRESULT node_get_base_name(xmlnode *This, BSTR *name)
1165 if (!name) return E_INVALIDARG;
1167 *name = bstr_from_xmlChar(This->node->name);
1168 if (!*name) return E_OUTOFMEMORY;
1170 TRACE("returning %s\n", debugstr_w(*name));
1175 static HRESULT WINAPI xmlnode_transformNodeToObject(
1177 IXMLDOMNode* stylesheet,
1178 VARIANT outputObject)
1180 xmlnode *This = impl_from_IXMLDOMNode( iface );
1181 FIXME("(%p)->(%p)\n", This, stylesheet);
1185 static const struct IXMLDOMNodeVtbl xmlnode_vtbl =
1207 xmlnode_removeChild,
1208 xmlnode_appendChild,
1209 xmlnode_hasChildNodes,
1210 xmlnode_get_ownerDocument,
1217 xmlnode_get_nodeTypedValue,
1222 xmlnode_transformNode,
1223 xmlnode_selectNodes,
1224 xmlnode_selectSingleNode,
1226 xmlnode_get_namespaceURI,
1229 xmlnode_transformNodeToObject,
1232 void destroy_xmlnode(xmlnode *This)
1235 xmldoc_release(This->node->doc);
1238 void init_xmlnode(xmlnode *This, xmlNodePtr node, IXMLDOMNode *node_iface, dispex_static_data_t *dispex_data)
1241 xmldoc_add_ref( node->doc );
1243 This->lpVtbl = &xmlnode_vtbl;
1245 This->iface = node_iface;
1248 init_dispex(&This->dispex, (IUnknown*)This->iface, dispex_data);
1250 This->dispex.outer = NULL;
1255 const IXMLDOMNodeVtbl *lpVtbl;
1259 static inline unknode *impl_from_unkIXMLDOMNode(IXMLDOMNode *iface)
1261 return (unknode *)((char*)iface - FIELD_OFFSET(unknode, lpVtbl));
1264 static HRESULT WINAPI unknode_QueryInterface(
1269 unknode *This = impl_from_unkIXMLDOMNode( iface );
1271 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
1273 if (IsEqualGUID(riid, &IID_IUnknown)) {
1275 }else if (IsEqualGUID( riid, &IID_IDispatch) ||
1276 IsEqualGUID( riid, &IID_IXMLDOMNode)) {
1277 *ppvObject = &This->lpVtbl;
1278 }else if(node_query_interface(&This->node, riid, ppvObject)) {
1279 return *ppvObject ? S_OK : E_NOINTERFACE;
1281 FIXME("interface %s not implemented\n", debugstr_guid(riid));
1283 return E_NOINTERFACE;
1286 IUnknown_AddRef((IUnknown*)*ppvObject);
1290 static ULONG WINAPI unknode_AddRef(
1291 IXMLDOMNode *iface )
1293 unknode *This = impl_from_unkIXMLDOMNode( iface );
1295 return InterlockedIncrement(&This->ref);
1298 static ULONG WINAPI unknode_Release(
1299 IXMLDOMNode *iface )
1301 unknode *This = impl_from_unkIXMLDOMNode( iface );
1304 ref = InterlockedDecrement( &This->ref );
1306 destroy_xmlnode(&This->node);
1313 static HRESULT WINAPI unknode_GetTypeInfoCount(
1317 unknode *This = impl_from_unkIXMLDOMNode( iface );
1319 TRACE("(%p)->(%p)\n", This, pctinfo);
1326 static HRESULT WINAPI unknode_GetTypeInfo(
1330 ITypeInfo** ppTInfo )
1332 unknode *This = impl_from_unkIXMLDOMNode( iface );
1335 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1337 hr = get_typeinfo(IXMLDOMNode_tid, ppTInfo);
1342 static HRESULT WINAPI unknode_GetIDsOfNames(
1345 LPOLESTR* rgszNames,
1350 unknode *This = impl_from_unkIXMLDOMNode( iface );
1352 ITypeInfo *typeinfo;
1355 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1358 if(!rgszNames || cNames == 0 || !rgDispId)
1359 return E_INVALIDARG;
1361 hr = get_typeinfo(IXMLDOMNode_tid, &typeinfo);
1364 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1365 ITypeInfo_Release(typeinfo);
1371 static HRESULT WINAPI unknode_Invoke(
1373 DISPID dispIdMember,
1377 DISPPARAMS* pDispParams,
1378 VARIANT* pVarResult,
1379 EXCEPINFO* pExcepInfo,
1382 unknode *This = impl_from_unkIXMLDOMNode( iface );
1383 ITypeInfo *typeinfo;
1386 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1387 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1389 hr = get_typeinfo(IXMLDOMNode_tid, &typeinfo);
1392 hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
1393 pVarResult, pExcepInfo, puArgErr);
1394 ITypeInfo_Release(typeinfo);
1400 static HRESULT WINAPI unknode_get_nodeName(
1404 unknode *This = impl_from_unkIXMLDOMNode( iface );
1406 FIXME("(%p)->(%p)\n", This, p);
1408 return node_get_nodeName(&This->node, p);
1411 static HRESULT WINAPI unknode_get_nodeValue(
1415 unknode *This = impl_from_unkIXMLDOMNode( iface );
1417 FIXME("(%p)->(%p)\n", This, value);
1420 return E_INVALIDARG;
1422 V_VT(value) = VT_NULL;
1426 static HRESULT WINAPI unknode_put_nodeValue(
1430 unknode *This = impl_from_unkIXMLDOMNode( iface );
1431 FIXME("(%p)->(v%d)\n", This, V_VT(&value));
1435 static HRESULT WINAPI unknode_get_nodeType(
1437 DOMNodeType* domNodeType )
1439 unknode *This = impl_from_unkIXMLDOMNode( iface );
1441 FIXME("(%p)->(%p)\n", This, domNodeType);
1443 *domNodeType = This->node.node->type;
1447 static HRESULT WINAPI unknode_get_parentNode(
1449 IXMLDOMNode** parent )
1451 unknode *This = impl_from_unkIXMLDOMNode( iface );
1452 FIXME("(%p)->(%p)\n", This, parent);
1453 if (!parent) return E_INVALIDARG;
1458 static HRESULT WINAPI unknode_get_childNodes(
1460 IXMLDOMNodeList** outList)
1462 unknode *This = impl_from_unkIXMLDOMNode( iface );
1464 TRACE("(%p)->(%p)\n", This, outList);
1466 return node_get_child_nodes(&This->node, outList);
1469 static HRESULT WINAPI unknode_get_firstChild(
1471 IXMLDOMNode** domNode)
1473 unknode *This = impl_from_unkIXMLDOMNode( iface );
1475 TRACE("(%p)->(%p)\n", This, domNode);
1477 return node_get_first_child(&This->node, domNode);
1480 static HRESULT WINAPI unknode_get_lastChild(
1482 IXMLDOMNode** domNode)
1484 unknode *This = impl_from_unkIXMLDOMNode( iface );
1486 TRACE("(%p)->(%p)\n", This, domNode);
1488 return node_get_last_child(&This->node, domNode);
1491 static HRESULT WINAPI unknode_get_previousSibling(
1493 IXMLDOMNode** domNode)
1495 unknode *This = impl_from_unkIXMLDOMNode( iface );
1497 TRACE("(%p)->(%p)\n", This, domNode);
1499 return node_get_previous_sibling(&This->node, domNode);
1502 static HRESULT WINAPI unknode_get_nextSibling(
1504 IXMLDOMNode** domNode)
1506 unknode *This = impl_from_unkIXMLDOMNode( iface );
1508 TRACE("(%p)->(%p)\n", This, domNode);
1510 return node_get_next_sibling(&This->node, domNode);
1513 static HRESULT WINAPI unknode_get_attributes(
1515 IXMLDOMNamedNodeMap** attributeMap)
1517 unknode *This = impl_from_unkIXMLDOMNode( iface );
1519 FIXME("(%p)->(%p)\n", This, attributeMap);
1521 return return_null_ptr((void**)attributeMap);
1524 static HRESULT WINAPI unknode_insertBefore(
1526 IXMLDOMNode* newNode, VARIANT refChild,
1527 IXMLDOMNode** outOldNode)
1529 unknode *This = impl_from_unkIXMLDOMNode( iface );
1531 FIXME("(%p)->(%p x%d %p)\n", This, newNode, V_VT(&refChild), outOldNode);
1533 return node_insert_before(&This->node, newNode, &refChild, outOldNode);
1536 static HRESULT WINAPI unknode_replaceChild(
1538 IXMLDOMNode* newNode,
1539 IXMLDOMNode* oldNode,
1540 IXMLDOMNode** outOldNode)
1542 unknode *This = impl_from_unkIXMLDOMNode( iface );
1544 FIXME("(%p)->(%p %p %p)\n", This, newNode, oldNode, outOldNode);
1546 return node_replace_child(&This->node, newNode, oldNode, outOldNode);
1549 static HRESULT WINAPI unknode_removeChild(
1551 IXMLDOMNode* domNode, IXMLDOMNode** oldNode)
1553 unknode *This = impl_from_unkIXMLDOMNode( iface );
1554 return IXMLDOMNode_removeChild( IXMLDOMNode_from_impl(&This->node), domNode, oldNode );
1557 static HRESULT WINAPI unknode_appendChild(
1559 IXMLDOMNode* newNode, IXMLDOMNode** outNewNode)
1561 unknode *This = impl_from_unkIXMLDOMNode( iface );
1562 return IXMLDOMNode_appendChild( IXMLDOMNode_from_impl(&This->node), newNode, outNewNode );
1565 static HRESULT WINAPI unknode_hasChildNodes(
1567 VARIANT_BOOL* pbool)
1569 unknode *This = impl_from_unkIXMLDOMNode( iface );
1570 return IXMLDOMNode_hasChildNodes( IXMLDOMNode_from_impl(&This->node), pbool );
1573 static HRESULT WINAPI unknode_get_ownerDocument(
1575 IXMLDOMDocument** domDocument)
1577 unknode *This = impl_from_unkIXMLDOMNode( iface );
1578 return IXMLDOMNode_get_ownerDocument( IXMLDOMNode_from_impl(&This->node), domDocument );
1581 static HRESULT WINAPI unknode_cloneNode(
1583 VARIANT_BOOL pbool, IXMLDOMNode** outNode)
1585 unknode *This = impl_from_unkIXMLDOMNode( iface );
1586 return IXMLDOMNode_cloneNode( IXMLDOMNode_from_impl(&This->node), pbool, outNode );
1589 static HRESULT WINAPI unknode_get_nodeTypeString(
1593 unknode *This = impl_from_unkIXMLDOMNode( iface );
1595 FIXME("(%p)->(%p)\n", This, p);
1597 return node_get_nodeName(&This->node, p);
1600 static HRESULT WINAPI unknode_get_text(
1604 unknode *This = impl_from_unkIXMLDOMNode( iface );
1605 return IXMLDOMNode_get_text( IXMLDOMNode_from_impl(&This->node), p );
1608 static HRESULT WINAPI unknode_put_text(
1612 unknode *This = impl_from_unkIXMLDOMNode( iface );
1613 return IXMLDOMNode_put_text( IXMLDOMNode_from_impl(&This->node), p );
1616 static HRESULT WINAPI unknode_get_specified(
1618 VARIANT_BOOL* isSpecified)
1620 unknode *This = impl_from_unkIXMLDOMNode( iface );
1621 FIXME("(%p)->(%p) stub!\n", This, isSpecified);
1622 *isSpecified = VARIANT_TRUE;
1626 static HRESULT WINAPI unknode_get_definition(
1628 IXMLDOMNode** definitionNode)
1630 unknode *This = impl_from_unkIXMLDOMNode( iface );
1631 FIXME("(%p)->(%p)\n", This, definitionNode);
1635 static HRESULT WINAPI unknode_get_nodeTypedValue(
1639 unknode *This = impl_from_unkIXMLDOMNode( iface );
1640 return IXMLDOMNode_get_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), var1 );
1643 static HRESULT WINAPI unknode_put_nodeTypedValue(
1647 unknode *This = impl_from_unkIXMLDOMNode( iface );
1648 FIXME("(%p)->(%s)\n", This, debugstr_variant(&typedValue));
1652 static HRESULT WINAPI unknode_get_dataType(
1656 unknode *This = impl_from_unkIXMLDOMNode( iface );
1657 return IXMLDOMNode_get_dataType( IXMLDOMNode_from_impl(&This->node), var1 );
1660 static HRESULT WINAPI unknode_put_dataType(
1664 unknode *This = impl_from_unkIXMLDOMNode( iface );
1666 FIXME("(%p)->(%s)\n", This, debugstr_w(p));
1669 return E_INVALIDARG;
1674 static HRESULT WINAPI unknode_get_xml(
1678 unknode *This = impl_from_unkIXMLDOMNode( iface );
1680 FIXME("(%p)->(%p)\n", This, p);
1682 return node_get_xml(&This->node, FALSE, FALSE, p);
1685 static HRESULT WINAPI unknode_transformNode(
1687 IXMLDOMNode* domNode, BSTR* p)
1689 unknode *This = impl_from_unkIXMLDOMNode( iface );
1690 return IXMLDOMNode_transformNode( IXMLDOMNode_from_impl(&This->node), domNode, p );
1693 static HRESULT WINAPI unknode_selectNodes(
1695 BSTR p, IXMLDOMNodeList** outList)
1697 unknode *This = impl_from_unkIXMLDOMNode( iface );
1698 return IXMLDOMNode_selectNodes( IXMLDOMNode_from_impl(&This->node), p, outList );
1701 static HRESULT WINAPI unknode_selectSingleNode(
1703 BSTR p, IXMLDOMNode** outNode)
1705 unknode *This = impl_from_unkIXMLDOMNode( iface );
1706 return IXMLDOMNode_selectSingleNode( IXMLDOMNode_from_impl(&This->node), p, outNode );
1709 static HRESULT WINAPI unknode_get_parsed(
1711 VARIANT_BOOL* isParsed)
1713 unknode *This = impl_from_unkIXMLDOMNode( iface );
1714 FIXME("(%p)->(%p) stub!\n", This, isParsed);
1715 *isParsed = VARIANT_TRUE;
1719 static HRESULT WINAPI unknode_get_namespaceURI(
1723 unknode *This = impl_from_unkIXMLDOMNode( iface );
1724 return IXMLDOMNode_get_namespaceURI( IXMLDOMNode_from_impl(&This->node), p );
1727 static HRESULT WINAPI unknode_get_prefix(
1731 unknode *This = impl_from_unkIXMLDOMNode( iface );
1732 return IXMLDOMNode_get_prefix( IXMLDOMNode_from_impl(&This->node), p );
1735 static HRESULT WINAPI unknode_get_baseName(
1739 unknode *This = impl_from_unkIXMLDOMNode( iface );
1740 return IXMLDOMNode_get_baseName( IXMLDOMNode_from_impl(&This->node), p );
1743 static HRESULT WINAPI unknode_transformNodeToObject(
1745 IXMLDOMNode* domNode, VARIANT var1)
1747 unknode *This = impl_from_unkIXMLDOMNode( iface );
1748 return IXMLDOMNode_transformNodeToObject( IXMLDOMNode_from_impl(&This->node), domNode, var1 );
1751 static const struct IXMLDOMNodeVtbl unknode_vtbl =
1753 unknode_QueryInterface,
1756 unknode_GetTypeInfoCount,
1757 unknode_GetTypeInfo,
1758 unknode_GetIDsOfNames,
1760 unknode_get_nodeName,
1761 unknode_get_nodeValue,
1762 unknode_put_nodeValue,
1763 unknode_get_nodeType,
1764 unknode_get_parentNode,
1765 unknode_get_childNodes,
1766 unknode_get_firstChild,
1767 unknode_get_lastChild,
1768 unknode_get_previousSibling,
1769 unknode_get_nextSibling,
1770 unknode_get_attributes,
1771 unknode_insertBefore,
1772 unknode_replaceChild,
1773 unknode_removeChild,
1774 unknode_appendChild,
1775 unknode_hasChildNodes,
1776 unknode_get_ownerDocument,
1778 unknode_get_nodeTypeString,
1781 unknode_get_specified,
1782 unknode_get_definition,
1783 unknode_get_nodeTypedValue,
1784 unknode_put_nodeTypedValue,
1785 unknode_get_dataType,
1786 unknode_put_dataType,
1788 unknode_transformNode,
1789 unknode_selectNodes,
1790 unknode_selectSingleNode,
1792 unknode_get_namespaceURI,
1794 unknode_get_baseName,
1795 unknode_transformNodeToObject
1798 IXMLDOMNode *create_node( xmlNodePtr node )
1807 TRACE("type %d\n", node->type);
1810 case XML_ELEMENT_NODE:
1811 pUnk = create_element( node );
1813 case XML_ATTRIBUTE_NODE:
1814 pUnk = create_attribute( node );
1817 pUnk = create_text( node );
1819 case XML_CDATA_SECTION_NODE:
1820 pUnk = create_cdata( node );
1822 case XML_ENTITY_REF_NODE:
1823 pUnk = create_doc_entity_ref( node );
1826 pUnk = create_pi( node );
1828 case XML_COMMENT_NODE:
1829 pUnk = create_comment( node );
1831 case XML_DOCUMENT_NODE:
1832 pUnk = create_domdoc( node );
1834 case XML_DOCUMENT_FRAG_NODE:
1835 pUnk = create_doc_fragment( node );
1838 pUnk = create_doc_type( node );
1843 FIXME("only creating basic node for type %d\n", node->type);
1845 new_node = heap_alloc(sizeof(unknode));
1849 new_node->lpVtbl = &unknode_vtbl;
1851 init_xmlnode(&new_node->node, node, (IXMLDOMNode*)&new_node->lpVtbl, NULL);
1852 pUnk = (IUnknown*)&new_node->lpVtbl;
1856 hr = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMNode, (LPVOID*)&ret);
1857 IUnknown_Release(pUnk);
1858 if(FAILED(hr)) return NULL;