4 * Copyright 2005 Mike McCormack
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
33 #include "msxml_private.h"
36 # include <libxml/HTMLtree.h>
39 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
45 /* TODO: get rid of these and use the enum */
46 static const WCHAR szBinBase64[] = {'b','i','n','.','b','a','s','e','6','4',0};
47 static const WCHAR szString[] = {'s','t','r','i','n','g',0};
48 static const WCHAR szNumber[] = {'n','u','m','b','e','r',0};
49 static const WCHAR szInt[] = {'I','n','t',0};
50 static const WCHAR szFixed[] = {'F','i','x','e','d','.','1','4','.','4',0};
51 static const WCHAR szBoolean[] = {'B','o','o','l','e','a','n',0};
52 static const WCHAR szDateTime[] = {'d','a','t','e','T','i','m','e',0};
53 static const WCHAR szDateTimeTZ[] = {'d','a','t','e','T','i','m','e','.','t','z',0};
54 static const WCHAR szDate[] = {'D','a','t','e',0};
55 static const WCHAR szTime[] = {'T','i','m','e',0};
56 static const WCHAR szTimeTZ[] = {'T','i','m','e','.','t','z',0};
57 static const WCHAR szI1[] = {'i','1',0};
58 static const WCHAR szI2[] = {'i','2',0};
59 static const WCHAR szI4[] = {'i','4',0};
60 static const WCHAR szIU1[] = {'u','i','1',0};
61 static const WCHAR szIU2[] = {'u','i','2',0};
62 static const WCHAR szIU4[] = {'u','i','4',0};
63 static const WCHAR szR4[] = {'r','4',0};
64 static const WCHAR szR8[] = {'r','8',0};
65 static const WCHAR szFloat[] = {'f','l','o','a','t',0};
66 static const WCHAR szUUID[] = {'u','u','i','d',0};
67 static const WCHAR szBinHex[] = {'b','i','n','.','h','e','x',0};
69 static const IID IID_xmlnode = {0x4f2f4ba2,0xb822,0x11df,{0x8b,0x8a,0x68,0x50,0xdf,0xd7,0x20,0x85}};
71 xmlNodePtr xmlNodePtr_from_domnode( IXMLDOMNode *iface, xmlElementType type )
77 This = get_node_obj( iface );
78 if ( !This || !This->node )
80 if ( type && This->node->type != type )
85 BOOL node_query_interface(xmlnode *This, REFIID riid, void **ppv)
87 if(IsEqualGUID(&IID_xmlnode, riid)) {
88 TRACE("(%p)->(IID_xmlnode %p)\n", This, ppv);
93 if(This->dispex.outer)
94 return dispex_query_interface(&This->dispex, riid, ppv);
99 xmlnode *get_node_obj(IXMLDOMNode *node)
104 hres = IXMLDOMNode_QueryInterface(node, &IID_xmlnode, (void**)&obj);
105 return SUCCEEDED(hres) ? obj : NULL;
108 static inline xmlnode *impl_from_IXMLDOMNode( IXMLDOMNode *iface )
110 return CONTAINING_RECORD(iface, xmlnode, IXMLDOMNode_iface);
113 HRESULT node_get_nodeName(xmlnode *This, BSTR *name)
118 *name = bstr_from_xmlChar(This->node->name);
125 HRESULT node_get_content(xmlnode *This, VARIANT *value)
132 content = xmlNodeGetContent(This->node);
133 V_VT(value) = VT_BSTR;
134 V_BSTR(value) = bstr_from_xmlChar( content );
137 TRACE("%p returned %s\n", This, debugstr_w(V_BSTR(value)));
141 HRESULT node_set_content(xmlnode *This, LPCWSTR value)
145 TRACE("(%p)->(%s)\n", This, debugstr_w(value));
146 str = xmlChar_from_wchar(value);
148 return E_OUTOFMEMORY;
150 xmlNodeSetContent(This->node, str);
155 static HRESULT node_set_content_escaped(xmlnode *This, LPCWSTR value)
157 xmlChar *str, *escaped;
159 TRACE("(%p)->(%s)\n", This, debugstr_w(value));
160 str = xmlChar_from_wchar(value);
162 return E_OUTOFMEMORY;
164 escaped = xmlEncodeSpecialChars(NULL, str);
168 return E_OUTOFMEMORY;
171 xmlNodeSetContent(This->node, escaped);
179 HRESULT node_put_value(xmlnode *This, VARIANT *value)
181 VARIANT string_value;
184 VariantInit(&string_value);
185 hr = VariantChangeType(&string_value, value, 0, VT_BSTR);
187 WARN("Couldn't convert to VT_BSTR\n");
191 hr = node_set_content(This, V_BSTR(&string_value));
192 VariantClear(&string_value);
197 HRESULT node_put_value_escaped(xmlnode *This, VARIANT *value)
199 VARIANT string_value;
202 VariantInit(&string_value);
203 hr = VariantChangeType(&string_value, value, 0, VT_BSTR);
205 WARN("Couldn't convert to VT_BSTR\n");
209 hr = node_set_content_escaped(This, V_BSTR(&string_value));
210 VariantClear(&string_value);
215 static HRESULT get_node(
221 TRACE("(%p)->(%s %p %p)\n", This, name, node, out );
226 /* if we don't have a doc, use our parent. */
227 if(node && !node->doc && node->parent)
228 node->doc = node->parent->doc;
230 *out = create_node( node );
236 HRESULT node_get_parent(xmlnode *This, IXMLDOMNode **parent)
238 return get_node( This, "parent", This->node->parent, parent );
241 HRESULT node_get_child_nodes(xmlnode *This, IXMLDOMNodeList **ret)
246 *ret = create_children_nodelist(This->node);
248 return E_OUTOFMEMORY;
253 HRESULT node_get_first_child(xmlnode *This, IXMLDOMNode **ret)
255 return get_node(This, "firstChild", This->node->children, ret);
258 HRESULT node_get_last_child(xmlnode *This, IXMLDOMNode **ret)
260 return get_node(This, "lastChild", This->node->last, ret);
263 HRESULT node_get_previous_sibling(xmlnode *This, IXMLDOMNode **ret)
265 return get_node(This, "previous", This->node->prev, ret);
268 HRESULT node_get_next_sibling(xmlnode *This, IXMLDOMNode **ret)
270 return get_node(This, "next", This->node->next, ret);
273 HRESULT node_insert_before(xmlnode *This, IXMLDOMNode *new_child, const VARIANT *ref_child,
276 xmlNodePtr before_node, new_child_node;
277 IXMLDOMNode *before = NULL;
284 node_obj = get_node_obj(new_child);
286 FIXME("newChild is not our node implementation\n");
290 switch(V_VT(ref_child))
298 hr = IUnknown_QueryInterface(V_UNKNOWN(ref_child), &IID_IXMLDOMNode, (LPVOID)&before);
299 if(FAILED(hr)) return hr;
303 FIXME("refChild var type %x\n", V_VT(ref_child));
307 new_child_node = node_obj->node;
308 TRACE("new_child_node %p This->node %p\n", new_child_node, This->node);
310 if(!new_child_node->parent)
311 if(xmldoc_remove_orphan(new_child_node->doc, new_child_node) != S_OK)
312 WARN("%p is not an orphan of %p\n", new_child_node, new_child_node->doc);
316 node_obj = get_node_obj(before);
317 IXMLDOMNode_Release(before);
319 FIXME("before node is not our node implementation\n");
323 before_node = node_obj->node;
324 xmlAddPrevSibling(before_node, new_child_node);
328 xmlAddChild(This->node, new_child_node);
332 IXMLDOMNode_AddRef(new_child);
340 HRESULT node_replace_child(xmlnode *This, IXMLDOMNode *newChild, IXMLDOMNode *oldChild,
343 xmlnode *old_child, *new_child;
344 xmlDocPtr leaving_doc;
345 xmlNode *my_ancestor;
347 /* Do not believe any documentation telling that newChild == NULL
348 means removal. It does certainly *not* apply to msxml3! */
349 if(!newChild || !oldChild)
355 old_child = get_node_obj(oldChild);
357 FIXME("oldChild is not our node implementation\n");
361 if(old_child->node->parent != This->node)
363 WARN("childNode %p is not a child of %p\n", oldChild, This);
367 new_child = get_node_obj(newChild);
369 FIXME("newChild is not our node implementation\n");
373 my_ancestor = This->node;
376 if(my_ancestor == new_child->node)
378 WARN("tried to create loop\n");
381 my_ancestor = my_ancestor->parent;
384 if(!new_child->node->parent)
385 if(xmldoc_remove_orphan(new_child->node->doc, new_child->node) != S_OK)
386 WARN("%p is not an orphan of %p\n", new_child->node, new_child->node->doc);
388 leaving_doc = new_child->node->doc;
389 xmldoc_add_ref(old_child->node->doc);
390 xmlReplaceNode(old_child->node, new_child->node);
391 xmldoc_release(leaving_doc);
393 xmldoc_add_orphan(old_child->node->doc, old_child->node);
397 IXMLDOMNode_AddRef(oldChild);
404 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);
538 while (isspace(ret[len-1])) --len;
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 BSTR EnsureCorrectEOL(BSTR sInput)
846 nLen = SysStringLen(sInput);
847 /* Count line endings */
848 for(i=0; i < nLen; i++)
850 if(sInput[i] == '\n')
854 TRACE("len=%d, num=%d\n", nLen, nNum);
856 /* Add linefeed as needed */
860 sNew = SysAllocStringLen(NULL, nLen + nNum+1);
861 for(i=0; i < nLen; i++)
863 if(sInput[i] == '\n')
865 sNew[i+nPlace] = '\r';
868 sNew[i+nPlace] = sInput[i];
871 SysFreeString(sInput);
878 TRACE("len %d\n", SysStringLen(sNew));
883 /* Removes encoding information and last character (nullbyte) */
884 static BSTR EnsureNoEncoding(BSTR sInput)
886 static const WCHAR wszEncoding[] = {'e','n','c','o','d','i','n','g','='};
891 while(*pBeg != '\n' && memcmp(pBeg, wszEncoding, sizeof(wszEncoding)))
896 SysReAllocStringLen(&sInput, sInput, SysStringLen(sInput)-1);
901 pEnd = pBeg + sizeof(wszEncoding)/sizeof(WCHAR) + 2;
902 while(*pEnd != '\"') pEnd++;
905 sNew = SysAllocStringLen(NULL,
906 pBeg-sInput + SysStringLen(sInput)-(pEnd-sInput)-1);
907 memcpy(sNew, sInput, (pBeg-sInput)*sizeof(WCHAR));
908 memcpy(&sNew[pBeg-sInput], pEnd, (SysStringLen(sInput)-(pEnd-sInput)-1)*sizeof(WCHAR));
910 SysFreeString(sInput);
915 * We are trying to replicate the same behaviour as msxml by converting
916 * line endings to \r\n and using indents as \t. The problem is that msxml
917 * only formats nodes that have a line ending. Using libxml we cannot
918 * reproduce behaviour exactly.
921 HRESULT node_get_xml(xmlnode *This, BOOL ensure_eol, BOOL ensure_no_encoding, BSTR *ret)
923 xmlBufferPtr xml_buf;
932 xml_buf = xmlBufferCreate();
934 return E_OUTOFMEMORY;
936 xmldecl = xmldoc_unlink_xmldecl( This->node->doc );
938 size = xmlNodeDump(xml_buf, This->node->doc, This->node, 0, 1);
940 const xmlChar *buf_content;
943 /* Attribute Nodes return a space in front of their name */
944 buf_content = xmlBufferContent(xml_buf);
946 content = bstr_from_xmlChar(buf_content + (buf_content[0] == ' ' ? 1 : 0));
948 content = EnsureCorrectEOL(content);
949 if(ensure_no_encoding)
950 content = EnsureNoEncoding(content);
954 *ret = SysAllocStringLen(NULL, 0);
957 xmlBufferFree(xml_buf);
958 xmldoc_link_xmldecl( This->node->doc, xmldecl );
959 return *ret ? S_OK : E_OUTOFMEMORY;
962 static HRESULT WINAPI xmlnode_transformNode(
964 IXMLDOMNode* styleSheet,
967 #ifdef SONAME_LIBXSLT
968 xmlnode *This = impl_from_IXMLDOMNode( iface );
969 xmlnode *pStyleSheet = NULL;
970 xsltStylesheetPtr xsltSS = NULL;
971 xmlDocPtr result = NULL;
973 TRACE("(%p)->(%p %p)\n", This, styleSheet, xmlString);
977 if(!styleSheet || !xmlString)
982 pStyleSheet = get_node_obj(styleSheet);
984 FIXME("styleSheet is not our xmlnode implementation\n");
988 xsltSS = pxsltParseStylesheetDoc( pStyleSheet->node->doc);
991 result = pxsltApplyStylesheet(xsltSS, This->node->doc, NULL);
994 const xmlChar *pContent;
996 if(result->type == XML_HTML_DOCUMENT_NODE)
998 xmlOutputBufferPtr pOutput = xmlAllocOutputBuffer(NULL);
1001 htmlDocContentDumpOutput(pOutput, result->doc, NULL);
1002 pContent = xmlBufferContent(pOutput->buffer);
1003 *xmlString = bstr_from_xmlChar(pContent);
1004 xmlOutputBufferClose(pOutput);
1009 xmlBufferPtr pXmlBuf;
1012 pXmlBuf = xmlBufferCreate();
1015 nSize = xmlNodeDump(pXmlBuf, NULL, (xmlNodePtr)result, 0, 0);
1018 pContent = xmlBufferContent(pXmlBuf);
1019 *xmlString = bstr_from_xmlChar(pContent);
1021 xmlBufferFree(pXmlBuf);
1026 /* libxslt "helpfully" frees the XML document the stylesheet was
1027 generated from, too */
1029 pxsltFreeStylesheet(xsltSS);
1032 if(*xmlString == NULL)
1033 *xmlString = SysAllocStringLen(NULL, 0);
1037 FIXME("libxslt headers were not found at compile time\n");
1042 static HRESULT WINAPI xmlnode_selectNodes(
1045 IXMLDOMNodeList** resultList)
1047 xmlnode *This = impl_from_IXMLDOMNode( iface );
1051 TRACE("(%p)->(%s %p)\n", This, debugstr_w(queryString), resultList );
1053 if (!queryString || !resultList) return E_INVALIDARG;
1055 str = xmlChar_from_wchar(queryString);
1056 hr = queryresult_create(This->node, str, resultList);
1062 static HRESULT WINAPI xmlnode_selectSingleNode(
1065 IXMLDOMNode** resultNode)
1067 xmlnode *This = impl_from_IXMLDOMNode( iface );
1068 IXMLDOMNodeList *list;
1071 TRACE("(%p)->(%s %p)\n", This, debugstr_w(queryString), resultNode );
1073 r = IXMLDOMNode_selectNodes(This->iface, queryString, &list);
1076 r = IXMLDOMNodeList_nextNode(list, resultNode);
1077 IXMLDOMNodeList_Release(list);
1082 HRESULT node_get_namespaceURI(xmlnode *This, BSTR *namespaceURI)
1087 return E_INVALIDARG;
1089 *namespaceURI = NULL;
1091 if ((ns = xmlGetNsList(This->node->doc, This->node)))
1093 if (ns[0]->href) *namespaceURI = bstr_from_xmlChar( ns[0]->href );
1097 TRACE("uri: %s\n", debugstr_w(*namespaceURI));
1099 return *namespaceURI ? S_OK : S_FALSE;
1102 HRESULT node_get_prefix(xmlnode *This, BSTR *prefix)
1106 if (!prefix) return E_INVALIDARG;
1110 if ((ns = xmlGetNsList(This->node->doc, This->node)))
1112 if (ns[0]->prefix) *prefix = bstr_from_xmlChar( ns[0]->prefix );
1116 TRACE("prefix: %s\n", debugstr_w(*prefix));
1118 return *prefix ? S_OK : S_FALSE;
1121 HRESULT node_get_base_name(xmlnode *This, BSTR *name)
1123 if (!name) return E_INVALIDARG;
1125 *name = bstr_from_xmlChar(This->node->name);
1126 if (!*name) return E_OUTOFMEMORY;
1128 TRACE("returning %s\n", debugstr_w(*name));
1133 static const struct IXMLDOMNodeVtbl xmlnode_vtbl =
1155 xmlnode_removeChild,
1156 xmlnode_appendChild,
1157 xmlnode_hasChildNodes,
1158 xmlnode_get_ownerDocument,
1170 xmlnode_transformNode,
1171 xmlnode_selectNodes,
1172 xmlnode_selectSingleNode
1175 void destroy_xmlnode(xmlnode *This)
1178 xmldoc_release(This->node->doc);
1181 void init_xmlnode(xmlnode *This, xmlNodePtr node, IXMLDOMNode *node_iface, dispex_static_data_t *dispex_data)
1184 xmldoc_add_ref( node->doc );
1186 This->IXMLDOMNode_iface.lpVtbl = &xmlnode_vtbl;
1188 This->iface = node_iface;
1191 init_dispex(&This->dispex, (IUnknown*)This->iface, dispex_data);
1193 This->dispex.outer = NULL;
1198 IXMLDOMNode IXMLDOMNode_iface;
1202 static inline unknode *unknode_from_IXMLDOMNode(IXMLDOMNode *iface)
1204 return CONTAINING_RECORD(iface, unknode, IXMLDOMNode_iface);
1207 static HRESULT WINAPI unknode_QueryInterface(
1212 unknode *This = unknode_from_IXMLDOMNode( iface );
1214 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
1216 if (IsEqualGUID(riid, &IID_IUnknown)) {
1218 }else if (IsEqualGUID( riid, &IID_IDispatch) ||
1219 IsEqualGUID( riid, &IID_IXMLDOMNode)) {
1220 *ppvObject = &This->IXMLDOMNode_iface;
1221 }else if(node_query_interface(&This->node, riid, ppvObject)) {
1222 return *ppvObject ? S_OK : E_NOINTERFACE;
1224 FIXME("interface %s not implemented\n", debugstr_guid(riid));
1226 return E_NOINTERFACE;
1229 IUnknown_AddRef((IUnknown*)*ppvObject);
1233 static ULONG WINAPI unknode_AddRef(
1234 IXMLDOMNode *iface )
1236 unknode *This = unknode_from_IXMLDOMNode( iface );
1238 return InterlockedIncrement(&This->ref);
1241 static ULONG WINAPI unknode_Release(
1242 IXMLDOMNode *iface )
1244 unknode *This = unknode_from_IXMLDOMNode( iface );
1247 ref = InterlockedDecrement( &This->ref );
1249 destroy_xmlnode(&This->node);
1256 static HRESULT WINAPI unknode_GetTypeInfoCount(
1260 unknode *This = unknode_from_IXMLDOMNode( iface );
1262 TRACE("(%p)->(%p)\n", This, pctinfo);
1269 static HRESULT WINAPI unknode_GetTypeInfo(
1273 ITypeInfo** ppTInfo )
1275 unknode *This = unknode_from_IXMLDOMNode( iface );
1278 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1280 hr = get_typeinfo(IXMLDOMNode_tid, ppTInfo);
1285 static HRESULT WINAPI unknode_GetIDsOfNames(
1288 LPOLESTR* rgszNames,
1293 unknode *This = unknode_from_IXMLDOMNode( iface );
1295 ITypeInfo *typeinfo;
1298 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1301 if(!rgszNames || cNames == 0 || !rgDispId)
1302 return E_INVALIDARG;
1304 hr = get_typeinfo(IXMLDOMNode_tid, &typeinfo);
1307 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1308 ITypeInfo_Release(typeinfo);
1314 static HRESULT WINAPI unknode_Invoke(
1316 DISPID dispIdMember,
1320 DISPPARAMS* pDispParams,
1321 VARIANT* pVarResult,
1322 EXCEPINFO* pExcepInfo,
1325 unknode *This = unknode_from_IXMLDOMNode( iface );
1326 ITypeInfo *typeinfo;
1329 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1330 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1332 hr = get_typeinfo(IXMLDOMNode_tid, &typeinfo);
1335 hr = ITypeInfo_Invoke(typeinfo, &This->IXMLDOMNode_iface, dispIdMember, wFlags, pDispParams,
1336 pVarResult, pExcepInfo, puArgErr);
1337 ITypeInfo_Release(typeinfo);
1343 static HRESULT WINAPI unknode_get_nodeName(
1347 unknode *This = unknode_from_IXMLDOMNode( iface );
1349 FIXME("(%p)->(%p)\n", This, p);
1351 return node_get_nodeName(&This->node, p);
1354 static HRESULT WINAPI unknode_get_nodeValue(
1358 unknode *This = unknode_from_IXMLDOMNode( iface );
1360 FIXME("(%p)->(%p)\n", This, value);
1363 return E_INVALIDARG;
1365 V_VT(value) = VT_NULL;
1369 static HRESULT WINAPI unknode_put_nodeValue(
1373 unknode *This = unknode_from_IXMLDOMNode( iface );
1374 FIXME("(%p)->(v%d)\n", This, V_VT(&value));
1378 static HRESULT WINAPI unknode_get_nodeType(
1380 DOMNodeType* domNodeType )
1382 unknode *This = unknode_from_IXMLDOMNode( iface );
1384 FIXME("(%p)->(%p)\n", This, domNodeType);
1386 *domNodeType = This->node.node->type;
1390 static HRESULT WINAPI unknode_get_parentNode(
1392 IXMLDOMNode** parent )
1394 unknode *This = unknode_from_IXMLDOMNode( iface );
1395 FIXME("(%p)->(%p)\n", This, parent);
1396 if (!parent) return E_INVALIDARG;
1401 static HRESULT WINAPI unknode_get_childNodes(
1403 IXMLDOMNodeList** outList)
1405 unknode *This = unknode_from_IXMLDOMNode( iface );
1407 TRACE("(%p)->(%p)\n", This, outList);
1409 return node_get_child_nodes(&This->node, outList);
1412 static HRESULT WINAPI unknode_get_firstChild(
1414 IXMLDOMNode** domNode)
1416 unknode *This = unknode_from_IXMLDOMNode( iface );
1418 TRACE("(%p)->(%p)\n", This, domNode);
1420 return node_get_first_child(&This->node, domNode);
1423 static HRESULT WINAPI unknode_get_lastChild(
1425 IXMLDOMNode** domNode)
1427 unknode *This = unknode_from_IXMLDOMNode( iface );
1429 TRACE("(%p)->(%p)\n", This, domNode);
1431 return node_get_last_child(&This->node, domNode);
1434 static HRESULT WINAPI unknode_get_previousSibling(
1436 IXMLDOMNode** domNode)
1438 unknode *This = unknode_from_IXMLDOMNode( iface );
1440 TRACE("(%p)->(%p)\n", This, domNode);
1442 return node_get_previous_sibling(&This->node, domNode);
1445 static HRESULT WINAPI unknode_get_nextSibling(
1447 IXMLDOMNode** domNode)
1449 unknode *This = unknode_from_IXMLDOMNode( iface );
1451 TRACE("(%p)->(%p)\n", This, domNode);
1453 return node_get_next_sibling(&This->node, domNode);
1456 static HRESULT WINAPI unknode_get_attributes(
1458 IXMLDOMNamedNodeMap** attributeMap)
1460 unknode *This = unknode_from_IXMLDOMNode( iface );
1462 FIXME("(%p)->(%p)\n", This, attributeMap);
1464 return return_null_ptr((void**)attributeMap);
1467 static HRESULT WINAPI unknode_insertBefore(
1469 IXMLDOMNode* newNode, VARIANT refChild,
1470 IXMLDOMNode** outOldNode)
1472 unknode *This = unknode_from_IXMLDOMNode( iface );
1474 FIXME("(%p)->(%p x%d %p)\n", This, newNode, V_VT(&refChild), outOldNode);
1476 return node_insert_before(&This->node, newNode, &refChild, outOldNode);
1479 static HRESULT WINAPI unknode_replaceChild(
1481 IXMLDOMNode* newNode,
1482 IXMLDOMNode* oldNode,
1483 IXMLDOMNode** outOldNode)
1485 unknode *This = unknode_from_IXMLDOMNode( iface );
1487 FIXME("(%p)->(%p %p %p)\n", This, newNode, oldNode, outOldNode);
1489 return node_replace_child(&This->node, newNode, oldNode, outOldNode);
1492 static HRESULT WINAPI unknode_removeChild(
1494 IXMLDOMNode* domNode, IXMLDOMNode** oldNode)
1496 unknode *This = unknode_from_IXMLDOMNode( iface );
1497 return IXMLDOMNode_removeChild( &This->node.IXMLDOMNode_iface, domNode, oldNode );
1500 static HRESULT WINAPI unknode_appendChild(
1502 IXMLDOMNode* newNode, IXMLDOMNode** outNewNode)
1504 unknode *This = unknode_from_IXMLDOMNode( iface );
1505 return IXMLDOMNode_appendChild( &This->node.IXMLDOMNode_iface, newNode, outNewNode );
1508 static HRESULT WINAPI unknode_hasChildNodes(
1510 VARIANT_BOOL* pbool)
1512 unknode *This = unknode_from_IXMLDOMNode( iface );
1513 return IXMLDOMNode_hasChildNodes( &This->node.IXMLDOMNode_iface, pbool );
1516 static HRESULT WINAPI unknode_get_ownerDocument(
1518 IXMLDOMDocument** domDocument)
1520 unknode *This = unknode_from_IXMLDOMNode( iface );
1521 return IXMLDOMNode_get_ownerDocument( &This->node.IXMLDOMNode_iface, domDocument );
1524 static HRESULT WINAPI unknode_cloneNode(
1526 VARIANT_BOOL pbool, IXMLDOMNode** outNode)
1528 unknode *This = unknode_from_IXMLDOMNode( iface );
1529 return IXMLDOMNode_cloneNode( &This->node.IXMLDOMNode_iface, pbool, outNode );
1532 static HRESULT WINAPI unknode_get_nodeTypeString(
1536 unknode *This = unknode_from_IXMLDOMNode( iface );
1538 FIXME("(%p)->(%p)\n", This, p);
1540 return node_get_nodeName(&This->node, p);
1543 static HRESULT WINAPI unknode_get_text(
1547 unknode *This = unknode_from_IXMLDOMNode( iface );
1548 return IXMLDOMNode_get_text( &This->node.IXMLDOMNode_iface, p );
1551 static HRESULT WINAPI unknode_put_text(
1555 unknode *This = unknode_from_IXMLDOMNode( iface );
1556 return IXMLDOMNode_put_text( &This->node.IXMLDOMNode_iface, p );
1559 static HRESULT WINAPI unknode_get_specified(
1561 VARIANT_BOOL* isSpecified)
1563 unknode *This = unknode_from_IXMLDOMNode( iface );
1564 FIXME("(%p)->(%p) stub!\n", This, isSpecified);
1565 *isSpecified = VARIANT_TRUE;
1569 static HRESULT WINAPI unknode_get_definition(
1571 IXMLDOMNode** definitionNode)
1573 unknode *This = unknode_from_IXMLDOMNode( iface );
1574 FIXME("(%p)->(%p)\n", This, definitionNode);
1578 static HRESULT WINAPI unknode_get_nodeTypedValue(
1582 unknode *This = unknode_from_IXMLDOMNode( iface );
1583 FIXME("(%p)->(%p)\n", This, var1);
1584 return return_null_var(var1);
1587 static HRESULT WINAPI unknode_put_nodeTypedValue(
1591 unknode *This = unknode_from_IXMLDOMNode( iface );
1592 FIXME("(%p)->(%s)\n", This, debugstr_variant(&typedValue));
1596 static HRESULT WINAPI unknode_get_dataType(
1600 unknode *This = unknode_from_IXMLDOMNode( iface );
1601 return IXMLDOMNode_get_dataType( &This->node.IXMLDOMNode_iface, var1 );
1604 static HRESULT WINAPI unknode_put_dataType(
1608 unknode *This = unknode_from_IXMLDOMNode( iface );
1610 FIXME("(%p)->(%s)\n", This, debugstr_w(p));
1613 return E_INVALIDARG;
1618 static HRESULT WINAPI unknode_get_xml(
1622 unknode *This = unknode_from_IXMLDOMNode( iface );
1624 FIXME("(%p)->(%p)\n", This, p);
1626 return node_get_xml(&This->node, FALSE, FALSE, p);
1629 static HRESULT WINAPI unknode_transformNode(
1631 IXMLDOMNode* domNode, BSTR* p)
1633 unknode *This = unknode_from_IXMLDOMNode( iface );
1634 return IXMLDOMNode_transformNode( &This->node.IXMLDOMNode_iface, domNode, p );
1637 static HRESULT WINAPI unknode_selectNodes(
1639 BSTR p, IXMLDOMNodeList** outList)
1641 unknode *This = unknode_from_IXMLDOMNode( iface );
1642 return IXMLDOMNode_selectNodes( &This->node.IXMLDOMNode_iface, p, outList );
1645 static HRESULT WINAPI unknode_selectSingleNode(
1647 BSTR p, IXMLDOMNode** outNode)
1649 unknode *This = unknode_from_IXMLDOMNode( iface );
1650 return IXMLDOMNode_selectSingleNode( &This->node.IXMLDOMNode_iface, p, outNode );
1653 static HRESULT WINAPI unknode_get_parsed(
1655 VARIANT_BOOL* isParsed)
1657 unknode *This = unknode_from_IXMLDOMNode( iface );
1658 FIXME("(%p)->(%p) stub!\n", This, isParsed);
1659 *isParsed = VARIANT_TRUE;
1663 static HRESULT WINAPI unknode_get_namespaceURI(
1667 unknode *This = unknode_from_IXMLDOMNode( iface );
1668 TRACE("(%p)->(%p)\n", This, p);
1669 return node_get_namespaceURI(&This->node, p);
1672 static HRESULT WINAPI unknode_get_prefix(
1676 unknode *This = unknode_from_IXMLDOMNode( iface );
1677 return IXMLDOMNode_get_prefix( &This->node.IXMLDOMNode_iface, p );
1680 static HRESULT WINAPI unknode_get_baseName(
1684 unknode *This = unknode_from_IXMLDOMNode( iface );
1685 return IXMLDOMNode_get_baseName( &This->node.IXMLDOMNode_iface, p );
1688 static HRESULT WINAPI unknode_transformNodeToObject(
1690 IXMLDOMNode* domNode, VARIANT var1)
1692 unknode *This = unknode_from_IXMLDOMNode( iface );
1693 FIXME("(%p)->(%p %s)\n", This, domNode, debugstr_variant(&var1));
1697 static const struct IXMLDOMNodeVtbl unknode_vtbl =
1699 unknode_QueryInterface,
1702 unknode_GetTypeInfoCount,
1703 unknode_GetTypeInfo,
1704 unknode_GetIDsOfNames,
1706 unknode_get_nodeName,
1707 unknode_get_nodeValue,
1708 unknode_put_nodeValue,
1709 unknode_get_nodeType,
1710 unknode_get_parentNode,
1711 unknode_get_childNodes,
1712 unknode_get_firstChild,
1713 unknode_get_lastChild,
1714 unknode_get_previousSibling,
1715 unknode_get_nextSibling,
1716 unknode_get_attributes,
1717 unknode_insertBefore,
1718 unknode_replaceChild,
1719 unknode_removeChild,
1720 unknode_appendChild,
1721 unknode_hasChildNodes,
1722 unknode_get_ownerDocument,
1724 unknode_get_nodeTypeString,
1727 unknode_get_specified,
1728 unknode_get_definition,
1729 unknode_get_nodeTypedValue,
1730 unknode_put_nodeTypedValue,
1731 unknode_get_dataType,
1732 unknode_put_dataType,
1734 unknode_transformNode,
1735 unknode_selectNodes,
1736 unknode_selectSingleNode,
1738 unknode_get_namespaceURI,
1740 unknode_get_baseName,
1741 unknode_transformNodeToObject
1744 IXMLDOMNode *create_node( xmlNodePtr node )
1753 TRACE("type %d\n", node->type);
1756 case XML_ELEMENT_NODE:
1757 pUnk = create_element( node );
1759 case XML_ATTRIBUTE_NODE:
1760 pUnk = create_attribute( node );
1763 pUnk = create_text( node );
1765 case XML_CDATA_SECTION_NODE:
1766 pUnk = create_cdata( node );
1768 case XML_ENTITY_REF_NODE:
1769 pUnk = create_doc_entity_ref( node );
1772 pUnk = create_pi( node );
1774 case XML_COMMENT_NODE:
1775 pUnk = create_comment( node );
1777 case XML_DOCUMENT_NODE:
1778 pUnk = create_domdoc( node );
1780 case XML_DOCUMENT_FRAG_NODE:
1781 pUnk = create_doc_fragment( node );
1784 pUnk = create_doc_type( node );
1789 FIXME("only creating basic node for type %d\n", node->type);
1791 new_node = heap_alloc(sizeof(unknode));
1795 new_node->IXMLDOMNode_iface.lpVtbl = &unknode_vtbl;
1797 init_xmlnode(&new_node->node, node, &new_node->IXMLDOMNode_iface, NULL);
1798 pUnk = (IUnknown*)&new_node->IXMLDOMNode_iface;
1802 hr = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMNode, (LPVOID*)&ret);
1803 IUnknown_Release(pUnk);
1804 if(FAILED(hr)) return NULL;