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
34 #include "msxml_private.h"
37 # include <libxml/HTMLtree.h>
40 #include "wine/debug.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
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 str = xmlChar_from_wchar(value);
147 return E_OUTOFMEMORY;
149 xmlNodeSetContent(This->node, str);
154 HRESULT node_put_value(xmlnode *This, VARIANT *value)
156 VARIANT string_value;
159 VariantInit(&string_value);
160 hr = VariantChangeType(&string_value, value, 0, VT_BSTR);
162 WARN("Couldn't convert to VT_BSTR\n");
166 hr = node_set_content(This, V_BSTR(&string_value));
167 VariantClear(&string_value);
172 static HRESULT get_node(
178 TRACE("(%p)->(%s %p %p)\n", This, name, node, out );
183 /* if we don't have a doc, use our parent. */
184 if(node && !node->doc && node->parent)
185 node->doc = node->parent->doc;
187 *out = create_node( node );
193 HRESULT node_get_parent(xmlnode *This, IXMLDOMNode **parent)
195 return get_node( This, "parent", This->node->parent, parent );
198 HRESULT node_get_child_nodes(xmlnode *This, IXMLDOMNodeList **ret)
203 *ret = create_children_nodelist(This->node);
205 return E_OUTOFMEMORY;
210 HRESULT node_get_first_child(xmlnode *This, IXMLDOMNode **ret)
212 return get_node(This, "firstChild", This->node->children, ret);
215 HRESULT node_get_last_child(xmlnode *This, IXMLDOMNode **ret)
217 return get_node(This, "lastChild", This->node->last, ret);
220 HRESULT node_get_previous_sibling(xmlnode *This, IXMLDOMNode **ret)
222 return get_node(This, "previous", This->node->prev, ret);
225 HRESULT node_get_next_sibling(xmlnode *This, IXMLDOMNode **ret)
227 return get_node(This, "next", This->node->next, ret);
230 HRESULT node_insert_before(xmlnode *This, IXMLDOMNode *new_child, const VARIANT *ref_child,
233 xmlNodePtr before_node, new_child_node;
234 IXMLDOMNode *before = NULL;
241 node_obj = get_node_obj(new_child);
243 FIXME("newChild is not our node implementation\n");
247 switch(V_VT(ref_child))
255 hr = IUnknown_QueryInterface(V_UNKNOWN(ref_child), &IID_IXMLDOMNode, (LPVOID)&before);
256 if(FAILED(hr)) return hr;
260 FIXME("refChild var type %x\n", V_VT(ref_child));
264 new_child_node = node_obj->node;
265 TRACE("new_child_node %p This->node %p\n", new_child_node, This->node);
267 if(!new_child_node->parent)
268 if(xmldoc_remove_orphan(new_child_node->doc, new_child_node) != S_OK)
269 WARN("%p is not an orphan of %p\n", new_child_node, new_child_node->doc);
273 node_obj = get_node_obj(before);
274 IXMLDOMNode_Release(before);
276 FIXME("before node is not our node implementation\n");
280 before_node = node_obj->node;
281 xmlAddPrevSibling(before_node, new_child_node);
285 xmlAddChild(This->node, new_child_node);
289 IXMLDOMNode_AddRef(new_child);
297 HRESULT node_replace_child(xmlnode *This, IXMLDOMNode *newChild, IXMLDOMNode *oldChild,
300 xmlnode *old_child, *new_child;
301 xmlDocPtr leaving_doc;
302 xmlNode *my_ancestor;
304 /* Do not believe any documentation telling that newChild == NULL
305 means removal. It does certainly *not* apply to msxml3! */
306 if(!newChild || !oldChild)
312 old_child = get_node_obj(oldChild);
314 FIXME("oldChild is not our node implementation\n");
318 if(old_child->node->parent != This->node)
320 WARN("childNode %p is not a child of %p\n", oldChild, This);
324 new_child = get_node_obj(newChild);
326 FIXME("newChild is not our node implementation\n");
330 my_ancestor = This->node;
333 if(my_ancestor == new_child->node)
335 WARN("tried to create loop\n");
338 my_ancestor = my_ancestor->parent;
341 if(!new_child->node->parent)
342 if(xmldoc_remove_orphan(new_child->node->doc, new_child->node) != S_OK)
343 WARN("%p is not an orphan of %p\n", new_child->node, new_child->node->doc);
345 leaving_doc = new_child->node->doc;
346 xmldoc_add_ref(old_child->node->doc);
347 xmlReplaceNode(old_child->node, new_child->node);
348 xmldoc_release(leaving_doc);
350 xmldoc_add_orphan(old_child->node->doc, old_child->node);
354 IXMLDOMNode_AddRef(oldChild);
361 static HRESULT WINAPI xmlnode_removeChild(
363 IXMLDOMNode* childNode,
364 IXMLDOMNode** oldChild)
366 xmlnode *This = impl_from_IXMLDOMNode( iface );
369 TRACE("(%p)->(%p %p)\n", This, childNode, oldChild);
371 if(!childNode) return E_INVALIDARG;
376 child_node = get_node_obj(childNode);
378 FIXME("childNode is not our node implementation\n");
382 if(child_node->node->parent != This->node)
384 WARN("childNode %p is not a child of %p\n", childNode, iface);
388 xmlUnlinkNode(child_node->node);
392 IXMLDOMNode_AddRef(childNode);
393 *oldChild = childNode;
399 static HRESULT WINAPI xmlnode_appendChild(
401 IXMLDOMNode* newChild,
402 IXMLDOMNode** outNewChild)
404 xmlnode *This = impl_from_IXMLDOMNode( iface );
409 TRACE("(%p)->(%p %p)\n", This, newChild, outNewChild);
411 hr = IXMLDOMNode_get_nodeType(newChild, &type);
412 if(FAILED(hr) || type == NODE_ATTRIBUTE) {
413 if(outNewChild) *outNewChild = NULL;
418 return IXMLDOMNode_insertBefore(This->iface, newChild, var, outNewChild);
421 static HRESULT WINAPI xmlnode_hasChildNodes(
423 VARIANT_BOOL* hasChild)
425 xmlnode *This = impl_from_IXMLDOMNode( iface );
427 TRACE("(%p)->(%p)\n", This, hasChild);
431 if (!This->node->children)
433 *hasChild = VARIANT_FALSE;
437 *hasChild = VARIANT_TRUE;
441 static HRESULT WINAPI xmlnode_get_ownerDocument(
443 IXMLDOMDocument** DOMDocument)
445 xmlnode *This = impl_from_IXMLDOMNode( iface );
447 TRACE("(%p)->(%p)\n", This, DOMDocument);
449 return DOMDocument_create_from_xmldoc(This->node->doc, (IXMLDOMDocument3**)DOMDocument);
452 HRESULT node_clone(xmlnode *This, VARIANT_BOOL deep, IXMLDOMNode **cloneNode)
457 if(!cloneNode) return E_INVALIDARG;
459 clone = xmlCopyNode(This->node, deep ? 1 : 2);
462 clone->doc = This->node->doc;
463 xmldoc_add_orphan(clone->doc, clone);
465 node = create_node(clone);
468 ERR("Copy failed\n");
476 ERR("Copy failed\n");
483 static HRESULT WINAPI xmlnode_get_nodeTypeString(
487 xmlnode *This = impl_from_IXMLDOMNode( iface );
490 TRACE("(%p)->(%p)\n", This, xmlnodeType );
498 switch( This->node->type )
500 case XML_ATTRIBUTE_NODE:
501 str = (const xmlChar*) "attribute";
503 case XML_CDATA_SECTION_NODE:
504 str = (const xmlChar*) "cdatasection";
506 case XML_COMMENT_NODE:
507 str = (const xmlChar*) "comment";
509 case XML_DOCUMENT_NODE:
510 str = (const xmlChar*) "document";
512 case XML_DOCUMENT_FRAG_NODE:
513 str = (const xmlChar*) "documentfragment";
515 case XML_ELEMENT_NODE:
516 str = (const xmlChar*) "element";
518 case XML_ENTITY_NODE:
519 str = (const xmlChar*) "entity";
521 case XML_ENTITY_REF_NODE:
522 str = (const xmlChar*) "entityreference";
524 case XML_NOTATION_NODE:
525 str = (const xmlChar*) "notation";
528 str = (const xmlChar*) "processinginstruction";
531 str = (const xmlChar*) "text";
534 FIXME("Unknown node type (%d)\n", This->node->type);
535 str = This->node->name;
539 *xmlnodeType = bstr_from_xmlChar( str );
546 static HRESULT WINAPI xmlnode_get_text(
550 xmlnode *This = impl_from_IXMLDOMNode( iface );
554 TRACE("(%p, type %d)->(%p)\n", This, This->node->type, text);
559 pContent = xmlNodeGetContent((xmlNodePtr)This->node);
562 str = bstr_from_xmlChar(pContent);
566 /* Always return a string. */
567 if (!str) str = SysAllocStringLen( NULL, 0 );
569 TRACE("%p %s\n", This, debugstr_w(str) );
575 HRESULT node_put_text(xmlnode *This, BSTR text)
579 TRACE("(%p)->(%s)\n", This, debugstr_w(text));
581 str = xmlChar_from_wchar(text);
583 /* Escape the string. */
584 str2 = xmlEncodeEntitiesReentrant(This->node->doc, str);
587 xmlNodeSetContent(This->node, str2);
593 static inline BYTE hex_to_byte(xmlChar c)
595 if(c <= '9') return c-'0';
596 if(c <= 'F') return c-'A'+10;
600 static inline BYTE base64_to_byte(xmlChar c)
602 if(c == '+') return 62;
603 if(c == '/') return 63;
604 if(c <= '9') return c-'0'+52;
605 if(c <= 'Z') return c-'A';
609 static inline HRESULT VARIANT_from_xmlChar(xmlChar *str, VARIANT *v, BSTR type)
611 if(!type || !lstrcmpiW(type, szString) ||
612 !lstrcmpiW(type, szNumber) || !lstrcmpiW(type, szUUID))
615 V_BSTR(v) = bstr_from_xmlChar(str);
618 return E_OUTOFMEMORY;
620 else if(!lstrcmpiW(type, szDateTime) || !lstrcmpiW(type, szDateTimeTZ) ||
621 !lstrcmpiW(type, szDate) || !lstrcmpiW(type, szTime) ||
622 !lstrcmpiW(type, szTimeTZ))
632 st.wDayOfWeek = st.wHour = st.wMinute = st.wSecond = st.wMilliseconds = 0;
634 V_VT(&src) = VT_BSTR;
635 V_BSTR(&src) = bstr_from_xmlChar(str);
638 return E_OUTOFMEMORY;
641 e = p + SysStringLen(V_BSTR(&src));
643 if(p+4<e && *(p+4)=='-') /* parse date (yyyy-mm-dd) */
646 st.wMonth = atoiW(p+5);
647 st.wDay = atoiW(p+8);
653 if(p+2<e && *(p+2)==':') /* parse time (hh:mm:ss.?) */
656 st.wMinute = atoiW(p+3);
657 st.wSecond = atoiW(p+6);
663 while(isdigitW(*p)) p++;
667 SystemTimeToVariantTime(&st, &date);
671 if(*p == '+') /* parse timezone offset (+hh:mm) */
672 V_DATE(v) += (DOUBLE)atoiW(p+1)/24 + (DOUBLE)atoiW(p+4)/1440;
673 else if(*p == '-') /* parse timezone offset (-hh:mm) */
674 V_DATE(v) -= (DOUBLE)atoiW(p+1)/24 + (DOUBLE)atoiW(p+4)/1440;
678 else if(!lstrcmpiW(type, szBinHex))
683 len = xmlStrlen(str)/2;
687 V_VT(v) = (VT_ARRAY|VT_UI1);
688 V_ARRAY(v) = SafeArrayCreate(VT_UI1, 1, &sab);
691 return E_OUTOFMEMORY;
694 ((BYTE*)V_ARRAY(v)->pvData)[i] = (hex_to_byte(str[2*i])<<4)
695 + hex_to_byte(str[2*i+1]);
697 else if(!lstrcmpiW(type, szBinBase64))
702 len = xmlStrlen(str);
703 if(str[len-2] == '=') i = 2;
704 else if(str[len-1] == '=') i = 1;
708 sab.cElements = len/4*3-i;
710 V_VT(v) = (VT_ARRAY|VT_UI1);
711 V_ARRAY(v) = SafeArrayCreate(VT_UI1, 1, &sab);
714 return E_OUTOFMEMORY;
716 for(i=0; i<len/4; i++)
718 ((BYTE*)V_ARRAY(v)->pvData)[3*i] = (base64_to_byte(str[4*i])<<2)
719 + (base64_to_byte(str[4*i+1])>>4);
720 if(3*i+1 < sab.cElements)
721 ((BYTE*)V_ARRAY(v)->pvData)[3*i+1] = (base64_to_byte(str[4*i+1])<<4)
722 + (base64_to_byte(str[4*i+2])>>2);
723 if(3*i+2 < sab.cElements)
724 ((BYTE*)V_ARRAY(v)->pvData)[3*i+2] = (base64_to_byte(str[4*i+2])<<6)
725 + base64_to_byte(str[4*i+3]);
733 if(!lstrcmpiW(type, szInt) || !lstrcmpiW(type, szI4))
735 else if(!lstrcmpiW(type, szFixed))
737 else if(!lstrcmpiW(type, szBoolean))
739 else if(!lstrcmpiW(type, szI1))
741 else if(!lstrcmpiW(type, szI2))
743 else if(!lstrcmpiW(type, szIU1))
745 else if(!lstrcmpiW(type, szIU2))
747 else if(!lstrcmpiW(type, szIU4))
749 else if(!lstrcmpiW(type, szR4))
751 else if(!lstrcmpiW(type, szR8) || !lstrcmpiW(type, szFloat))
755 FIXME("Type handling not yet implemented\n");
759 V_VT(&src) = VT_BSTR;
760 V_BSTR(&src) = bstr_from_xmlChar(str);
763 return E_OUTOFMEMORY;
765 hres = VariantChangeTypeEx(v, &src, MAKELCID(MAKELANGID(
766 LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT),0, V_VT(v));
774 static HRESULT WINAPI xmlnode_get_nodeTypedValue(
778 xmlnode *This = impl_from_IXMLDOMNode( iface );
781 HRESULT hres = S_FALSE;
783 TRACE("(%p)->(%p)\n", This, typedValue);
788 V_VT(typedValue) = VT_NULL;
790 if(This->node->type == XML_ELEMENT_NODE ||
791 This->node->type == XML_TEXT_NODE ||
792 This->node->type == XML_ENTITY_REF_NODE)
793 hres = IXMLDOMNode_get_dataType(This->iface, &type);
795 if(hres != S_OK && This->node->type != XML_ELEMENT_NODE)
796 return IXMLDOMNode_get_nodeValue(This->iface, typedValue);
798 content = xmlNodeGetContent(This->node);
799 hres = VARIANT_from_xmlChar(content, typedValue,
800 hres==S_OK ? V_BSTR(&type) : NULL);
807 static HRESULT WINAPI xmlnode_put_nodeTypedValue(
811 xmlnode *This = impl_from_IXMLDOMNode( iface );
816 static HRESULT WINAPI xmlnode_put_dataType(
820 xmlnode *This = impl_from_IXMLDOMNode( iface );
823 TRACE("(%p)->(%s)\n", This, debugstr_w(dataTypeName));
825 if(dataTypeName == NULL)
828 /* An example of this is. The Text in the node needs to be a 0 or 1 for a boolean type.
829 This applies to changing types (string->bool) or setting a new one
831 FIXME("Need to Validate the data before allowing a type to be set.\n");
833 /* Check all supported types. */
834 if(lstrcmpiW(dataTypeName,szString) == 0 ||
835 lstrcmpiW(dataTypeName,szNumber) == 0 ||
836 lstrcmpiW(dataTypeName,szUUID) == 0 ||
837 lstrcmpiW(dataTypeName,szInt) == 0 ||
838 lstrcmpiW(dataTypeName,szI4) == 0 ||
839 lstrcmpiW(dataTypeName,szFixed) == 0 ||
840 lstrcmpiW(dataTypeName,szBoolean) == 0 ||
841 lstrcmpiW(dataTypeName,szDateTime) == 0 ||
842 lstrcmpiW(dataTypeName,szDateTimeTZ) == 0 ||
843 lstrcmpiW(dataTypeName,szDate) == 0 ||
844 lstrcmpiW(dataTypeName,szTime) == 0 ||
845 lstrcmpiW(dataTypeName,szTimeTZ) == 0 ||
846 lstrcmpiW(dataTypeName,szI1) == 0 ||
847 lstrcmpiW(dataTypeName,szI2) == 0 ||
848 lstrcmpiW(dataTypeName,szIU1) == 0 ||
849 lstrcmpiW(dataTypeName,szIU2) == 0 ||
850 lstrcmpiW(dataTypeName,szIU4) == 0 ||
851 lstrcmpiW(dataTypeName,szR4) == 0 ||
852 lstrcmpiW(dataTypeName,szR8) == 0 ||
853 lstrcmpiW(dataTypeName,szFloat) == 0 ||
854 lstrcmpiW(dataTypeName,szBinHex) == 0 ||
855 lstrcmpiW(dataTypeName,szBinBase64) == 0)
857 xmlChar* str = xmlChar_from_wchar(dataTypeName);
860 if (!str) return E_OUTOFMEMORY;
862 attr = xmlHasNsProp(This->node, (const xmlChar*)"dt",
863 (const xmlChar*)"urn:schemas-microsoft-com:datatypes");
866 attr = xmlSetNsProp(This->node, attr->ns, (const xmlChar*)"dt", str);
871 xmlNsPtr ns = xmlNewNs(This->node, (const xmlChar*)"urn:schemas-microsoft-com:datatypes", (const xmlChar*)"dt");
874 attr = xmlNewNsProp(This->node, ns, (const xmlChar*)"dt", str);
877 xmlAddChild(This->node, (xmlNodePtr)attr);
881 ERR("Failed to create Attribute\n");
884 ERR("Failed to create Namespace\n");
892 static BSTR EnsureCorrectEOL(BSTR sInput)
899 nLen = SysStringLen(sInput);
900 /* Count line endings */
901 for(i=0; i < nLen; i++)
903 if(sInput[i] == '\n')
907 TRACE("len=%d, num=%d\n", nLen, nNum);
909 /* Add linefeed as needed */
913 sNew = SysAllocStringLen(NULL, nLen + nNum+1);
914 for(i=0; i < nLen; i++)
916 if(sInput[i] == '\n')
918 sNew[i+nPlace] = '\r';
921 sNew[i+nPlace] = sInput[i];
924 SysFreeString(sInput);
931 TRACE("len %d\n", SysStringLen(sNew));
936 /* Removes encoding information and last character (nullbyte) */
937 static BSTR EnsureNoEncoding(BSTR sInput)
939 static const WCHAR wszEncoding[] = {'e','n','c','o','d','i','n','g','='};
944 while(*pBeg != '\n' && memcmp(pBeg, wszEncoding, sizeof(wszEncoding)))
949 SysReAllocStringLen(&sInput, sInput, SysStringLen(sInput)-1);
954 pEnd = pBeg + sizeof(wszEncoding)/sizeof(WCHAR) + 2;
955 while(*pEnd != '\"') pEnd++;
958 sNew = SysAllocStringLen(NULL,
959 pBeg-sInput + SysStringLen(sInput)-(pEnd-sInput)-1);
960 memcpy(sNew, sInput, (pBeg-sInput)*sizeof(WCHAR));
961 memcpy(&sNew[pBeg-sInput], pEnd, (SysStringLen(sInput)-(pEnd-sInput)-1)*sizeof(WCHAR));
963 SysFreeString(sInput);
968 * We are trying to replicate the same behaviour as msxml by converting
969 * line endings to \r\n and using indents as \t. The problem is that msxml
970 * only formats nodes that have a line ending. Using libxml we cannot
971 * reproduce behaviour exactly.
974 HRESULT node_get_xml(xmlnode *This, BOOL ensure_eol, BOOL ensure_no_encoding, BSTR *ret)
976 xmlBufferPtr xml_buf;
985 xml_buf = xmlBufferCreate();
987 return E_OUTOFMEMORY;
989 xmldecl = xmldoc_unlink_xmldecl( This->node->doc );
991 size = xmlNodeDump(xml_buf, This->node->doc, This->node, 0, 1);
993 const xmlChar *buf_content;
996 /* Attribute Nodes return a space in front of their name */
997 buf_content = xmlBufferContent(xml_buf);
999 content = bstr_from_xmlChar(buf_content + (buf_content[0] == ' ' ? 1 : 0));
1001 content = EnsureCorrectEOL(content);
1002 if(ensure_no_encoding)
1003 content = EnsureNoEncoding(content);
1007 *ret = SysAllocStringLen(NULL, 0);
1010 xmlBufferFree(xml_buf);
1011 xmldoc_link_xmldecl( This->node->doc, xmldecl );
1012 return *ret ? S_OK : E_OUTOFMEMORY;
1015 static HRESULT WINAPI xmlnode_transformNode(
1017 IXMLDOMNode* styleSheet,
1020 #ifdef SONAME_LIBXSLT
1021 xmlnode *This = impl_from_IXMLDOMNode( iface );
1022 xmlnode *pStyleSheet = NULL;
1023 xsltStylesheetPtr xsltSS = NULL;
1024 xmlDocPtr result = NULL;
1026 TRACE("(%p)->(%p %p)\n", This, styleSheet, xmlString);
1028 if (!libxslt_handle)
1030 if(!styleSheet || !xmlString)
1031 return E_INVALIDARG;
1035 pStyleSheet = get_node_obj(styleSheet);
1037 FIXME("styleSheet is not our xmlnode implementation\n");
1041 xsltSS = pxsltParseStylesheetDoc( pStyleSheet->node->doc);
1044 result = pxsltApplyStylesheet(xsltSS, This->node->doc, NULL);
1047 const xmlChar *pContent;
1049 if(result->type == XML_HTML_DOCUMENT_NODE)
1051 xmlOutputBufferPtr pOutput = xmlAllocOutputBuffer(NULL);
1054 htmlDocContentDumpOutput(pOutput, result->doc, NULL);
1055 pContent = xmlBufferContent(pOutput->buffer);
1056 *xmlString = bstr_from_xmlChar(pContent);
1057 xmlOutputBufferClose(pOutput);
1062 xmlBufferPtr pXmlBuf;
1065 pXmlBuf = xmlBufferCreate();
1068 nSize = xmlNodeDump(pXmlBuf, NULL, (xmlNodePtr)result, 0, 0);
1071 pContent = xmlBufferContent(pXmlBuf);
1072 *xmlString = bstr_from_xmlChar(pContent);
1074 xmlBufferFree(pXmlBuf);
1079 /* libxslt "helpfully" frees the XML document the stylesheet was
1080 generated from, too */
1082 pxsltFreeStylesheet(xsltSS);
1085 if(*xmlString == NULL)
1086 *xmlString = SysAllocStringLen(NULL, 0);
1090 FIXME("libxslt headers were not found at compile time\n");
1095 static HRESULT WINAPI xmlnode_selectNodes(
1098 IXMLDOMNodeList** resultList)
1100 xmlnode *This = impl_from_IXMLDOMNode( iface );
1102 TRACE("(%p)->(%s %p)\n", This, debugstr_w(queryString), resultList );
1104 if (!queryString || !resultList) return E_INVALIDARG;
1106 return queryresult_create( This->node, queryString, resultList );
1109 static HRESULT WINAPI xmlnode_selectSingleNode(
1112 IXMLDOMNode** resultNode)
1114 xmlnode *This = impl_from_IXMLDOMNode( iface );
1115 IXMLDOMNodeList *list;
1118 TRACE("(%p)->(%s %p)\n", This, debugstr_w(queryString), resultNode );
1120 r = IXMLDOMNode_selectNodes(This->iface, queryString, &list);
1123 r = IXMLDOMNodeList_nextNode(list, resultNode);
1124 IXMLDOMNodeList_Release(list);
1129 static HRESULT WINAPI xmlnode_get_namespaceURI(
1133 xmlnode *This = impl_from_IXMLDOMNode( iface );
1136 TRACE("(%p)->(%p)\n", This, namespaceURI );
1139 return E_INVALIDARG;
1141 *namespaceURI = NULL;
1143 if ((ns = xmlGetNsList(This->node->doc, This->node)))
1145 if (ns[0]->href) *namespaceURI = bstr_from_xmlChar( ns[0]->href );
1149 TRACE("uri: %s\n", debugstr_w(*namespaceURI));
1151 return *namespaceURI ? S_OK : S_FALSE;
1154 HRESULT node_get_prefix(xmlnode *This, BSTR *prefix)
1158 if (!prefix) return E_INVALIDARG;
1162 if ((ns = xmlGetNsList(This->node->doc, This->node)))
1164 if (ns[0]->prefix) *prefix = bstr_from_xmlChar( ns[0]->prefix );
1168 TRACE("prefix: %s\n", debugstr_w(*prefix));
1170 return *prefix ? S_OK : S_FALSE;
1173 HRESULT node_get_base_name(xmlnode *This, BSTR *name)
1175 if (!name) return E_INVALIDARG;
1177 *name = bstr_from_xmlChar(This->node->name);
1178 if (!*name) return E_OUTOFMEMORY;
1180 TRACE("returning %s\n", debugstr_w(*name));
1185 static HRESULT WINAPI xmlnode_transformNodeToObject(
1187 IXMLDOMNode* stylesheet,
1188 VARIANT outputObject)
1190 xmlnode *This = impl_from_IXMLDOMNode( iface );
1191 FIXME("(%p)->(%p)\n", This, stylesheet);
1195 static const struct IXMLDOMNodeVtbl xmlnode_vtbl =
1217 xmlnode_removeChild,
1218 xmlnode_appendChild,
1219 xmlnode_hasChildNodes,
1220 xmlnode_get_ownerDocument,
1222 xmlnode_get_nodeTypeString,
1227 xmlnode_get_nodeTypedValue,
1228 xmlnode_put_nodeTypedValue,
1230 xmlnode_put_dataType,
1232 xmlnode_transformNode,
1233 xmlnode_selectNodes,
1234 xmlnode_selectSingleNode,
1236 xmlnode_get_namespaceURI,
1239 xmlnode_transformNodeToObject,
1242 void destroy_xmlnode(xmlnode *This)
1245 xmldoc_release(This->node->doc);
1248 void init_xmlnode(xmlnode *This, xmlNodePtr node, IXMLDOMNode *node_iface, dispex_static_data_t *dispex_data)
1251 xmldoc_add_ref( node->doc );
1253 This->lpVtbl = &xmlnode_vtbl;
1255 This->iface = node_iface;
1258 init_dispex(&This->dispex, (IUnknown*)This->iface, dispex_data);
1260 This->dispex.outer = NULL;
1265 const IXMLDOMNodeVtbl *lpVtbl;
1269 static inline unknode *impl_from_unkIXMLDOMNode(IXMLDOMNode *iface)
1271 return (unknode *)((char*)iface - FIELD_OFFSET(unknode, lpVtbl));
1274 static HRESULT WINAPI unknode_QueryInterface(
1279 unknode *This = impl_from_unkIXMLDOMNode( iface );
1281 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
1283 if (IsEqualGUID(riid, &IID_IUnknown)) {
1285 }else if (IsEqualGUID( riid, &IID_IDispatch) ||
1286 IsEqualGUID( riid, &IID_IXMLDOMNode)) {
1287 *ppvObject = &This->lpVtbl;
1288 }else if(node_query_interface(&This->node, riid, ppvObject)) {
1289 return *ppvObject ? S_OK : E_NOINTERFACE;
1291 FIXME("interface %s not implemented\n", debugstr_guid(riid));
1293 return E_NOINTERFACE;
1296 IUnknown_AddRef((IUnknown*)*ppvObject);
1300 static ULONG WINAPI unknode_AddRef(
1301 IXMLDOMNode *iface )
1303 unknode *This = impl_from_unkIXMLDOMNode( iface );
1305 return InterlockedIncrement(&This->ref);
1308 static ULONG WINAPI unknode_Release(
1309 IXMLDOMNode *iface )
1311 unknode *This = impl_from_unkIXMLDOMNode( iface );
1314 ref = InterlockedDecrement( &This->ref );
1316 destroy_xmlnode(&This->node);
1323 static HRESULT WINAPI unknode_GetTypeInfoCount(
1327 unknode *This = impl_from_unkIXMLDOMNode( iface );
1329 TRACE("(%p)->(%p)\n", This, pctinfo);
1336 static HRESULT WINAPI unknode_GetTypeInfo(
1340 ITypeInfo** ppTInfo )
1342 unknode *This = impl_from_unkIXMLDOMNode( iface );
1345 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1347 hr = get_typeinfo(IXMLDOMNode_tid, ppTInfo);
1352 static HRESULT WINAPI unknode_GetIDsOfNames(
1355 LPOLESTR* rgszNames,
1360 unknode *This = impl_from_unkIXMLDOMNode( iface );
1362 ITypeInfo *typeinfo;
1365 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1368 if(!rgszNames || cNames == 0 || !rgDispId)
1369 return E_INVALIDARG;
1371 hr = get_typeinfo(IXMLDOMNode_tid, &typeinfo);
1374 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1375 ITypeInfo_Release(typeinfo);
1381 static HRESULT WINAPI unknode_Invoke(
1383 DISPID dispIdMember,
1387 DISPPARAMS* pDispParams,
1388 VARIANT* pVarResult,
1389 EXCEPINFO* pExcepInfo,
1392 unknode *This = impl_from_unkIXMLDOMNode( iface );
1393 ITypeInfo *typeinfo;
1396 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1397 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1399 hr = get_typeinfo(IXMLDOMNode_tid, &typeinfo);
1402 hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
1403 pVarResult, pExcepInfo, puArgErr);
1404 ITypeInfo_Release(typeinfo);
1410 static HRESULT WINAPI unknode_get_nodeName(
1414 unknode *This = impl_from_unkIXMLDOMNode( iface );
1416 FIXME("(%p)->(%p)\n", This, p);
1418 return node_get_nodeName(&This->node, p);
1421 static HRESULT WINAPI unknode_get_nodeValue(
1425 unknode *This = impl_from_unkIXMLDOMNode( iface );
1427 FIXME("(%p)->(%p)\n", This, value);
1430 return E_INVALIDARG;
1432 V_VT(value) = VT_NULL;
1436 static HRESULT WINAPI unknode_put_nodeValue(
1440 unknode *This = impl_from_unkIXMLDOMNode( iface );
1441 FIXME("(%p)->(v%d)\n", This, V_VT(&value));
1445 static HRESULT WINAPI unknode_get_nodeType(
1447 DOMNodeType* domNodeType )
1449 unknode *This = impl_from_unkIXMLDOMNode( iface );
1451 FIXME("(%p)->(%p)\n", This, domNodeType);
1453 *domNodeType = This->node.node->type;
1457 static HRESULT WINAPI unknode_get_parentNode(
1459 IXMLDOMNode** parent )
1461 unknode *This = impl_from_unkIXMLDOMNode( iface );
1462 FIXME("(%p)->(%p)\n", This, parent);
1463 if (!parent) return E_INVALIDARG;
1468 static HRESULT WINAPI unknode_get_childNodes(
1470 IXMLDOMNodeList** outList)
1472 unknode *This = impl_from_unkIXMLDOMNode( iface );
1474 TRACE("(%p)->(%p)\n", This, outList);
1476 return node_get_child_nodes(&This->node, outList);
1479 static HRESULT WINAPI unknode_get_firstChild(
1481 IXMLDOMNode** domNode)
1483 unknode *This = impl_from_unkIXMLDOMNode( iface );
1485 TRACE("(%p)->(%p)\n", This, domNode);
1487 return node_get_first_child(&This->node, domNode);
1490 static HRESULT WINAPI unknode_get_lastChild(
1492 IXMLDOMNode** domNode)
1494 unknode *This = impl_from_unkIXMLDOMNode( iface );
1496 TRACE("(%p)->(%p)\n", This, domNode);
1498 return node_get_last_child(&This->node, domNode);
1501 static HRESULT WINAPI unknode_get_previousSibling(
1503 IXMLDOMNode** domNode)
1505 unknode *This = impl_from_unkIXMLDOMNode( iface );
1507 TRACE("(%p)->(%p)\n", This, domNode);
1509 return node_get_previous_sibling(&This->node, domNode);
1512 static HRESULT WINAPI unknode_get_nextSibling(
1514 IXMLDOMNode** domNode)
1516 unknode *This = impl_from_unkIXMLDOMNode( iface );
1518 TRACE("(%p)->(%p)\n", This, domNode);
1520 return node_get_next_sibling(&This->node, domNode);
1523 static HRESULT WINAPI unknode_get_attributes(
1525 IXMLDOMNamedNodeMap** attributeMap)
1527 unknode *This = impl_from_unkIXMLDOMNode( iface );
1529 FIXME("(%p)->(%p)\n", This, attributeMap);
1531 return return_null_ptr((void**)attributeMap);
1534 static HRESULT WINAPI unknode_insertBefore(
1536 IXMLDOMNode* newNode, VARIANT refChild,
1537 IXMLDOMNode** outOldNode)
1539 unknode *This = impl_from_unkIXMLDOMNode( iface );
1541 FIXME("(%p)->(%p x%d %p)\n", This, newNode, V_VT(&refChild), outOldNode);
1543 return node_insert_before(&This->node, newNode, &refChild, outOldNode);
1546 static HRESULT WINAPI unknode_replaceChild(
1548 IXMLDOMNode* newNode,
1549 IXMLDOMNode* oldNode,
1550 IXMLDOMNode** outOldNode)
1552 unknode *This = impl_from_unkIXMLDOMNode( iface );
1554 FIXME("(%p)->(%p %p %p)\n", This, newNode, oldNode, outOldNode);
1556 return node_replace_child(&This->node, newNode, oldNode, outOldNode);
1559 static HRESULT WINAPI unknode_removeChild(
1561 IXMLDOMNode* domNode, IXMLDOMNode** oldNode)
1563 unknode *This = impl_from_unkIXMLDOMNode( iface );
1564 return IXMLDOMNode_removeChild( IXMLDOMNode_from_impl(&This->node), domNode, oldNode );
1567 static HRESULT WINAPI unknode_appendChild(
1569 IXMLDOMNode* newNode, IXMLDOMNode** outNewNode)
1571 unknode *This = impl_from_unkIXMLDOMNode( iface );
1572 return IXMLDOMNode_appendChild( IXMLDOMNode_from_impl(&This->node), newNode, outNewNode );
1575 static HRESULT WINAPI unknode_hasChildNodes(
1577 VARIANT_BOOL* pbool)
1579 unknode *This = impl_from_unkIXMLDOMNode( iface );
1580 return IXMLDOMNode_hasChildNodes( IXMLDOMNode_from_impl(&This->node), pbool );
1583 static HRESULT WINAPI unknode_get_ownerDocument(
1585 IXMLDOMDocument** domDocument)
1587 unknode *This = impl_from_unkIXMLDOMNode( iface );
1588 return IXMLDOMNode_get_ownerDocument( IXMLDOMNode_from_impl(&This->node), domDocument );
1591 static HRESULT WINAPI unknode_cloneNode(
1593 VARIANT_BOOL pbool, IXMLDOMNode** outNode)
1595 unknode *This = impl_from_unkIXMLDOMNode( iface );
1596 return IXMLDOMNode_cloneNode( IXMLDOMNode_from_impl(&This->node), pbool, outNode );
1599 static HRESULT WINAPI unknode_get_nodeTypeString(
1603 unknode *This = impl_from_unkIXMLDOMNode( iface );
1604 return IXMLDOMNode_get_nodeTypeString( IXMLDOMNode_from_impl(&This->node), p );
1607 static HRESULT WINAPI unknode_get_text(
1611 unknode *This = impl_from_unkIXMLDOMNode( iface );
1612 return IXMLDOMNode_get_text( IXMLDOMNode_from_impl(&This->node), p );
1615 static HRESULT WINAPI unknode_put_text(
1619 unknode *This = impl_from_unkIXMLDOMNode( iface );
1620 return IXMLDOMNode_put_text( IXMLDOMNode_from_impl(&This->node), p );
1623 static HRESULT WINAPI unknode_get_specified(
1625 VARIANT_BOOL* isSpecified)
1627 unknode *This = impl_from_unkIXMLDOMNode( iface );
1628 FIXME("(%p)->(%p) stub!\n", This, isSpecified);
1629 *isSpecified = VARIANT_TRUE;
1633 static HRESULT WINAPI unknode_get_definition(
1635 IXMLDOMNode** definitionNode)
1637 unknode *This = impl_from_unkIXMLDOMNode( iface );
1638 FIXME("(%p)->(%p)\n", This, definitionNode);
1642 static HRESULT WINAPI unknode_get_nodeTypedValue(
1646 unknode *This = impl_from_unkIXMLDOMNode( iface );
1647 return IXMLDOMNode_get_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), var1 );
1650 static HRESULT WINAPI unknode_put_nodeTypedValue(
1654 unknode *This = impl_from_unkIXMLDOMNode( iface );
1655 return IXMLDOMNode_put_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), var1 );
1658 static HRESULT WINAPI unknode_get_dataType(
1662 unknode *This = impl_from_unkIXMLDOMNode( iface );
1663 return IXMLDOMNode_get_dataType( IXMLDOMNode_from_impl(&This->node), var1 );
1666 static HRESULT WINAPI unknode_put_dataType(
1670 unknode *This = impl_from_unkIXMLDOMNode( iface );
1671 return IXMLDOMNode_put_dataType( IXMLDOMNode_from_impl(&This->node), p );
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 );
1840 FIXME("only creating basic node for type %d\n", node->type);
1842 new_node = heap_alloc(sizeof(unknode));
1846 new_node->lpVtbl = &unknode_vtbl;
1848 init_xmlnode(&new_node->node, node, (IXMLDOMNode*)&new_node->lpVtbl, NULL);
1849 pUnk = (IUnknown*)&new_node->lpVtbl;
1853 hr = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMNode, (LPVOID*)&ret);
1854 IUnknown_Release(pUnk);
1855 if(FAILED(hr)) return NULL;