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 static HRESULT WINAPI xmlnode_cloneNode(
455 IXMLDOMNode** cloneRoot)
457 xmlnode *This = impl_from_IXMLDOMNode( iface );
458 xmlNodePtr pClone = NULL;
459 IXMLDOMNode *pNode = NULL;
461 TRACE("(%p)->(%d %p)\n", This, deep, cloneRoot);
466 pClone = xmlCopyNode(This->node, deep ? 1 : 2);
469 pClone->doc = This->node->doc;
470 xmldoc_add_orphan(pClone->doc, pClone);
472 pNode = create_node(pClone);
475 ERR("Copy failed\n");
483 ERR("Copy failed\n");
490 static HRESULT WINAPI xmlnode_get_nodeTypeString(
494 xmlnode *This = impl_from_IXMLDOMNode( iface );
497 TRACE("(%p)->(%p)\n", This, xmlnodeType );
505 switch( This->node->type )
507 case XML_ATTRIBUTE_NODE:
508 str = (const xmlChar*) "attribute";
510 case XML_CDATA_SECTION_NODE:
511 str = (const xmlChar*) "cdatasection";
513 case XML_COMMENT_NODE:
514 str = (const xmlChar*) "comment";
516 case XML_DOCUMENT_NODE:
517 str = (const xmlChar*) "document";
519 case XML_DOCUMENT_FRAG_NODE:
520 str = (const xmlChar*) "documentfragment";
522 case XML_ELEMENT_NODE:
523 str = (const xmlChar*) "element";
525 case XML_ENTITY_NODE:
526 str = (const xmlChar*) "entity";
528 case XML_ENTITY_REF_NODE:
529 str = (const xmlChar*) "entityreference";
531 case XML_NOTATION_NODE:
532 str = (const xmlChar*) "notation";
535 str = (const xmlChar*) "processinginstruction";
538 str = (const xmlChar*) "text";
541 FIXME("Unknown node type (%d)\n", This->node->type);
542 str = This->node->name;
546 *xmlnodeType = bstr_from_xmlChar( str );
553 static HRESULT WINAPI xmlnode_get_text(
557 xmlnode *This = impl_from_IXMLDOMNode( iface );
561 TRACE("(%p, type %d)->(%p)\n", This, This->node->type, text);
566 pContent = xmlNodeGetContent((xmlNodePtr)This->node);
569 str = bstr_from_xmlChar(pContent);
573 /* Always return a string. */
574 if (!str) str = SysAllocStringLen( NULL, 0 );
576 TRACE("%p %s\n", This, debugstr_w(str) );
582 HRESULT node_put_text(xmlnode *This, BSTR text)
586 TRACE("(%p)->(%s)\n", This, debugstr_w(text));
588 str = xmlChar_from_wchar(text);
590 /* Escape the string. */
591 str2 = xmlEncodeEntitiesReentrant(This->node->doc, str);
594 xmlNodeSetContent(This->node, str2);
600 static inline BYTE hex_to_byte(xmlChar c)
602 if(c <= '9') return c-'0';
603 if(c <= 'F') return c-'A'+10;
607 static inline BYTE base64_to_byte(xmlChar c)
609 if(c == '+') return 62;
610 if(c == '/') return 63;
611 if(c <= '9') return c-'0'+52;
612 if(c <= 'Z') return c-'A';
616 static inline HRESULT VARIANT_from_xmlChar(xmlChar *str, VARIANT *v, BSTR type)
618 if(!type || !lstrcmpiW(type, szString) ||
619 !lstrcmpiW(type, szNumber) || !lstrcmpiW(type, szUUID))
622 V_BSTR(v) = bstr_from_xmlChar(str);
625 return E_OUTOFMEMORY;
627 else if(!lstrcmpiW(type, szDateTime) || !lstrcmpiW(type, szDateTimeTZ) ||
628 !lstrcmpiW(type, szDate) || !lstrcmpiW(type, szTime) ||
629 !lstrcmpiW(type, szTimeTZ))
639 st.wDayOfWeek = st.wHour = st.wMinute = st.wSecond = st.wMilliseconds = 0;
641 V_VT(&src) = VT_BSTR;
642 V_BSTR(&src) = bstr_from_xmlChar(str);
645 return E_OUTOFMEMORY;
648 e = p + SysStringLen(V_BSTR(&src));
650 if(p+4<e && *(p+4)=='-') /* parse date (yyyy-mm-dd) */
653 st.wMonth = atoiW(p+5);
654 st.wDay = atoiW(p+8);
660 if(p+2<e && *(p+2)==':') /* parse time (hh:mm:ss.?) */
663 st.wMinute = atoiW(p+3);
664 st.wSecond = atoiW(p+6);
670 while(isdigitW(*p)) p++;
674 SystemTimeToVariantTime(&st, &date);
678 if(*p == '+') /* parse timezone offset (+hh:mm) */
679 V_DATE(v) += (DOUBLE)atoiW(p+1)/24 + (DOUBLE)atoiW(p+4)/1440;
680 else if(*p == '-') /* parse timezone offset (-hh:mm) */
681 V_DATE(v) -= (DOUBLE)atoiW(p+1)/24 + (DOUBLE)atoiW(p+4)/1440;
685 else if(!lstrcmpiW(type, szBinHex))
690 len = xmlStrlen(str)/2;
694 V_VT(v) = (VT_ARRAY|VT_UI1);
695 V_ARRAY(v) = SafeArrayCreate(VT_UI1, 1, &sab);
698 return E_OUTOFMEMORY;
701 ((BYTE*)V_ARRAY(v)->pvData)[i] = (hex_to_byte(str[2*i])<<4)
702 + hex_to_byte(str[2*i+1]);
704 else if(!lstrcmpiW(type, szBinBase64))
709 len = xmlStrlen(str);
710 if(str[len-2] == '=') i = 2;
711 else if(str[len-1] == '=') i = 1;
715 sab.cElements = len/4*3-i;
717 V_VT(v) = (VT_ARRAY|VT_UI1);
718 V_ARRAY(v) = SafeArrayCreate(VT_UI1, 1, &sab);
721 return E_OUTOFMEMORY;
723 for(i=0; i<len/4; i++)
725 ((BYTE*)V_ARRAY(v)->pvData)[3*i] = (base64_to_byte(str[4*i])<<2)
726 + (base64_to_byte(str[4*i+1])>>4);
727 if(3*i+1 < sab.cElements)
728 ((BYTE*)V_ARRAY(v)->pvData)[3*i+1] = (base64_to_byte(str[4*i+1])<<4)
729 + (base64_to_byte(str[4*i+2])>>2);
730 if(3*i+2 < sab.cElements)
731 ((BYTE*)V_ARRAY(v)->pvData)[3*i+2] = (base64_to_byte(str[4*i+2])<<6)
732 + base64_to_byte(str[4*i+3]);
740 if(!lstrcmpiW(type, szInt) || !lstrcmpiW(type, szI4))
742 else if(!lstrcmpiW(type, szFixed))
744 else if(!lstrcmpiW(type, szBoolean))
746 else if(!lstrcmpiW(type, szI1))
748 else if(!lstrcmpiW(type, szI2))
750 else if(!lstrcmpiW(type, szIU1))
752 else if(!lstrcmpiW(type, szIU2))
754 else if(!lstrcmpiW(type, szIU4))
756 else if(!lstrcmpiW(type, szR4))
758 else if(!lstrcmpiW(type, szR8) || !lstrcmpiW(type, szFloat))
762 FIXME("Type handling not yet implemented\n");
766 V_VT(&src) = VT_BSTR;
767 V_BSTR(&src) = bstr_from_xmlChar(str);
770 return E_OUTOFMEMORY;
772 hres = VariantChangeTypeEx(v, &src, MAKELCID(MAKELANGID(
773 LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT),0, V_VT(v));
781 static HRESULT WINAPI xmlnode_get_nodeTypedValue(
785 xmlnode *This = impl_from_IXMLDOMNode( iface );
788 HRESULT hres = S_FALSE;
790 TRACE("(%p)->(%p)\n", This, typedValue);
795 V_VT(typedValue) = VT_NULL;
797 if(This->node->type == XML_ELEMENT_NODE ||
798 This->node->type == XML_TEXT_NODE ||
799 This->node->type == XML_ENTITY_REF_NODE)
800 hres = IXMLDOMNode_get_dataType(This->iface, &type);
802 if(hres != S_OK && This->node->type != XML_ELEMENT_NODE)
803 return IXMLDOMNode_get_nodeValue(This->iface, typedValue);
805 content = xmlNodeGetContent(This->node);
806 hres = VARIANT_from_xmlChar(content, typedValue,
807 hres==S_OK ? V_BSTR(&type) : NULL);
814 static HRESULT WINAPI xmlnode_put_nodeTypedValue(
818 xmlnode *This = impl_from_IXMLDOMNode( iface );
823 static HRESULT WINAPI xmlnode_put_dataType(
827 xmlnode *This = impl_from_IXMLDOMNode( iface );
830 TRACE("(%p)->(%s)\n", This, debugstr_w(dataTypeName));
832 if(dataTypeName == NULL)
835 /* An example of this is. The Text in the node needs to be a 0 or 1 for a boolean type.
836 This applies to changing types (string->bool) or setting a new one
838 FIXME("Need to Validate the data before allowing a type to be set.\n");
840 /* Check all supported types. */
841 if(lstrcmpiW(dataTypeName,szString) == 0 ||
842 lstrcmpiW(dataTypeName,szNumber) == 0 ||
843 lstrcmpiW(dataTypeName,szUUID) == 0 ||
844 lstrcmpiW(dataTypeName,szInt) == 0 ||
845 lstrcmpiW(dataTypeName,szI4) == 0 ||
846 lstrcmpiW(dataTypeName,szFixed) == 0 ||
847 lstrcmpiW(dataTypeName,szBoolean) == 0 ||
848 lstrcmpiW(dataTypeName,szDateTime) == 0 ||
849 lstrcmpiW(dataTypeName,szDateTimeTZ) == 0 ||
850 lstrcmpiW(dataTypeName,szDate) == 0 ||
851 lstrcmpiW(dataTypeName,szTime) == 0 ||
852 lstrcmpiW(dataTypeName,szTimeTZ) == 0 ||
853 lstrcmpiW(dataTypeName,szI1) == 0 ||
854 lstrcmpiW(dataTypeName,szI2) == 0 ||
855 lstrcmpiW(dataTypeName,szIU1) == 0 ||
856 lstrcmpiW(dataTypeName,szIU2) == 0 ||
857 lstrcmpiW(dataTypeName,szIU4) == 0 ||
858 lstrcmpiW(dataTypeName,szR4) == 0 ||
859 lstrcmpiW(dataTypeName,szR8) == 0 ||
860 lstrcmpiW(dataTypeName,szFloat) == 0 ||
861 lstrcmpiW(dataTypeName,szBinHex) == 0 ||
862 lstrcmpiW(dataTypeName,szBinBase64) == 0)
864 xmlChar* str = xmlChar_from_wchar(dataTypeName);
867 if (!str) return E_OUTOFMEMORY;
869 attr = xmlHasNsProp(This->node, (const xmlChar*)"dt",
870 (const xmlChar*)"urn:schemas-microsoft-com:datatypes");
873 attr = xmlSetNsProp(This->node, attr->ns, (const xmlChar*)"dt", str);
878 xmlNsPtr ns = xmlNewNs(This->node, (const xmlChar*)"urn:schemas-microsoft-com:datatypes", (const xmlChar*)"dt");
881 attr = xmlNewNsProp(This->node, ns, (const xmlChar*)"dt", str);
884 xmlAddChild(This->node, (xmlNodePtr)attr);
888 ERR("Failed to create Attribute\n");
891 ERR("Failed to create Namespace\n");
899 static BSTR EnsureCorrectEOL(BSTR sInput)
906 nLen = SysStringLen(sInput);
907 /* Count line endings */
908 for(i=0; i < nLen; i++)
910 if(sInput[i] == '\n')
914 TRACE("len=%d, num=%d\n", nLen, nNum);
916 /* Add linefeed as needed */
920 sNew = SysAllocStringLen(NULL, nLen + nNum+1);
921 for(i=0; i < nLen; i++)
923 if(sInput[i] == '\n')
925 sNew[i+nPlace] = '\r';
928 sNew[i+nPlace] = sInput[i];
931 SysFreeString(sInput);
938 TRACE("len %d\n", SysStringLen(sNew));
943 /* Removes encoding information and last character (nullbyte) */
944 static BSTR EnsureNoEncoding(BSTR sInput)
946 static const WCHAR wszEncoding[] = {'e','n','c','o','d','i','n','g','='};
951 while(*pBeg != '\n' && memcmp(pBeg, wszEncoding, sizeof(wszEncoding)))
956 SysReAllocStringLen(&sInput, sInput, SysStringLen(sInput)-1);
961 pEnd = pBeg + sizeof(wszEncoding)/sizeof(WCHAR) + 2;
962 while(*pEnd != '\"') pEnd++;
965 sNew = SysAllocStringLen(NULL,
966 pBeg-sInput + SysStringLen(sInput)-(pEnd-sInput)-1);
967 memcpy(sNew, sInput, (pBeg-sInput)*sizeof(WCHAR));
968 memcpy(&sNew[pBeg-sInput], pEnd, (SysStringLen(sInput)-(pEnd-sInput)-1)*sizeof(WCHAR));
970 SysFreeString(sInput);
975 * We are trying to replicate the same behaviour as msxml by converting
976 * line endings to \r\n and using indents as \t. The problem is that msxml
977 * only formats nodes that have a line ending. Using libxml we cannot
978 * reproduce behaviour exactly.
981 static HRESULT WINAPI xmlnode_get_xml(
985 xmlnode *This = impl_from_IXMLDOMNode( iface );
986 xmlBufferPtr pXmlBuf;
990 TRACE("(%p %d)->(%p)\n", This, This->node->type, xmlString);
997 xmldecl = xmldoc_unlink_xmldecl( This->node->doc );
999 pXmlBuf = xmlBufferCreate();
1002 nSize = xmlNodeDump(pXmlBuf, This->node->doc, This->node, 0, 1);
1005 const xmlChar *pContent;
1008 /* Attribute Nodes return a space in front of their name */
1009 pContent = xmlBufferContent(pXmlBuf);
1010 if( ((const char*)pContent)[0] == ' ')
1011 bstrContent = bstr_from_xmlChar(pContent+1);
1013 bstrContent = bstr_from_xmlChar(pContent);
1015 switch(This->node->type)
1017 case XML_ELEMENT_NODE:
1018 *xmlString = EnsureCorrectEOL(bstrContent);
1020 case XML_DOCUMENT_NODE:
1021 *xmlString = EnsureCorrectEOL(bstrContent);
1022 *xmlString = EnsureNoEncoding(*xmlString);
1025 *xmlString = bstrContent;
1029 xmlBufferFree(pXmlBuf);
1032 xmldoc_link_xmldecl( This->node->doc, xmldecl );
1034 /* Always returns a string. */
1035 if(*xmlString == NULL) *xmlString = SysAllocStringLen( NULL, 0 );
1040 static HRESULT WINAPI xmlnode_transformNode(
1042 IXMLDOMNode* styleSheet,
1045 #ifdef SONAME_LIBXSLT
1046 xmlnode *This = impl_from_IXMLDOMNode( iface );
1047 xmlnode *pStyleSheet = NULL;
1048 xsltStylesheetPtr xsltSS = NULL;
1049 xmlDocPtr result = NULL;
1051 TRACE("(%p)->(%p %p)\n", This, styleSheet, xmlString);
1053 if (!libxslt_handle)
1055 if(!styleSheet || !xmlString)
1056 return E_INVALIDARG;
1060 pStyleSheet = get_node_obj(styleSheet);
1062 FIXME("styleSheet is not our xmlnode implementation\n");
1066 xsltSS = pxsltParseStylesheetDoc( pStyleSheet->node->doc);
1069 result = pxsltApplyStylesheet(xsltSS, This->node->doc, NULL);
1072 const xmlChar *pContent;
1074 if(result->type == XML_HTML_DOCUMENT_NODE)
1076 xmlOutputBufferPtr pOutput = xmlAllocOutputBuffer(NULL);
1079 htmlDocContentDumpOutput(pOutput, result->doc, NULL);
1080 pContent = xmlBufferContent(pOutput->buffer);
1081 *xmlString = bstr_from_xmlChar(pContent);
1082 xmlOutputBufferClose(pOutput);
1087 xmlBufferPtr pXmlBuf;
1090 pXmlBuf = xmlBufferCreate();
1093 nSize = xmlNodeDump(pXmlBuf, NULL, (xmlNodePtr)result, 0, 0);
1096 pContent = xmlBufferContent(pXmlBuf);
1097 *xmlString = bstr_from_xmlChar(pContent);
1099 xmlBufferFree(pXmlBuf);
1104 /* libxslt "helpfully" frees the XML document the stylesheet was
1105 generated from, too */
1107 pxsltFreeStylesheet(xsltSS);
1110 if(*xmlString == NULL)
1111 *xmlString = SysAllocStringLen(NULL, 0);
1115 FIXME("libxslt headers were not found at compile time\n");
1120 static HRESULT WINAPI xmlnode_selectNodes(
1123 IXMLDOMNodeList** resultList)
1125 xmlnode *This = impl_from_IXMLDOMNode( iface );
1127 TRACE("(%p)->(%s %p)\n", This, debugstr_w(queryString), resultList );
1129 if (!queryString || !resultList) return E_INVALIDARG;
1131 return queryresult_create( This->node, queryString, resultList );
1134 static HRESULT WINAPI xmlnode_selectSingleNode(
1137 IXMLDOMNode** resultNode)
1139 xmlnode *This = impl_from_IXMLDOMNode( iface );
1140 IXMLDOMNodeList *list;
1143 TRACE("(%p)->(%s %p)\n", This, debugstr_w(queryString), resultNode );
1145 r = IXMLDOMNode_selectNodes(This->iface, queryString, &list);
1148 r = IXMLDOMNodeList_nextNode(list, resultNode);
1149 IXMLDOMNodeList_Release(list);
1154 static HRESULT WINAPI xmlnode_get_namespaceURI(
1158 xmlnode *This = impl_from_IXMLDOMNode( iface );
1161 TRACE("(%p)->(%p)\n", This, namespaceURI );
1164 return E_INVALIDARG;
1166 *namespaceURI = NULL;
1168 if ((ns = xmlGetNsList(This->node->doc, This->node)))
1170 if (ns[0]->href) *namespaceURI = bstr_from_xmlChar( ns[0]->href );
1174 TRACE("uri: %s\n", debugstr_w(*namespaceURI));
1176 return *namespaceURI ? S_OK : S_FALSE;
1179 static HRESULT WINAPI xmlnode_get_prefix(
1183 xmlnode *This = impl_from_IXMLDOMNode( iface );
1186 TRACE("(%p)->(%p)\n", This, prefixString );
1189 return E_INVALIDARG;
1191 *prefixString = NULL;
1193 if ((ns = xmlGetNsList(This->node->doc, This->node)))
1195 if (ns[0]->prefix) *prefixString = bstr_from_xmlChar( ns[0]->prefix );
1199 TRACE("prefix: %s\n", debugstr_w(*prefixString));
1201 return *prefixString ? S_OK : S_FALSE;
1204 static HRESULT WINAPI xmlnode_get_baseName(
1208 xmlnode *This = impl_from_IXMLDOMNode( iface );
1210 HRESULT r = S_FALSE;
1212 TRACE("(%p)->(%p)\n", This, nameString );
1215 return E_INVALIDARG;
1217 switch ( This->node->type )
1219 case XML_ELEMENT_NODE:
1220 case XML_ATTRIBUTE_NODE:
1222 str = bstr_from_xmlChar( This->node->name );
1226 case XML_COMMENT_NODE:
1227 case XML_DOCUMENT_NODE:
1230 ERR("Unhandled type %d\n", This->node->type );
1234 TRACE("returning %08x str = %s\n", r, debugstr_w( str ) );
1240 static HRESULT WINAPI xmlnode_transformNodeToObject(
1242 IXMLDOMNode* stylesheet,
1243 VARIANT outputObject)
1245 xmlnode *This = impl_from_IXMLDOMNode( iface );
1246 FIXME("(%p)->(%p)\n", This, stylesheet);
1250 static const struct IXMLDOMNodeVtbl xmlnode_vtbl =
1272 xmlnode_removeChild,
1273 xmlnode_appendChild,
1274 xmlnode_hasChildNodes,
1275 xmlnode_get_ownerDocument,
1277 xmlnode_get_nodeTypeString,
1282 xmlnode_get_nodeTypedValue,
1283 xmlnode_put_nodeTypedValue,
1285 xmlnode_put_dataType,
1287 xmlnode_transformNode,
1288 xmlnode_selectNodes,
1289 xmlnode_selectSingleNode,
1291 xmlnode_get_namespaceURI,
1293 xmlnode_get_baseName,
1294 xmlnode_transformNodeToObject,
1297 void destroy_xmlnode(xmlnode *This)
1300 xmldoc_release(This->node->doc);
1303 void init_xmlnode(xmlnode *This, xmlNodePtr node, IXMLDOMNode *node_iface, dispex_static_data_t *dispex_data)
1306 xmldoc_add_ref( node->doc );
1308 This->lpVtbl = &xmlnode_vtbl;
1310 This->iface = node_iface;
1313 init_dispex(&This->dispex, (IUnknown*)This->iface, dispex_data);
1315 This->dispex.outer = NULL;
1320 const IXMLDOMNodeVtbl *lpVtbl;
1324 static inline unknode *impl_from_unkIXMLDOMNode(IXMLDOMNode *iface)
1326 return (unknode *)((char*)iface - FIELD_OFFSET(unknode, lpVtbl));
1329 static HRESULT WINAPI unknode_QueryInterface(
1334 unknode *This = impl_from_unkIXMLDOMNode( iface );
1336 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
1338 if (IsEqualGUID(riid, &IID_IUnknown)) {
1340 }else if (IsEqualGUID( riid, &IID_IDispatch) ||
1341 IsEqualGUID( riid, &IID_IXMLDOMNode)) {
1342 *ppvObject = &This->lpVtbl;
1343 }else if(node_query_interface(&This->node, riid, ppvObject)) {
1344 return *ppvObject ? S_OK : E_NOINTERFACE;
1346 FIXME("interface %s not implemented\n", debugstr_guid(riid));
1348 return E_NOINTERFACE;
1351 IUnknown_AddRef((IUnknown*)*ppvObject);
1355 static ULONG WINAPI unknode_AddRef(
1356 IXMLDOMNode *iface )
1358 unknode *This = impl_from_unkIXMLDOMNode( iface );
1360 return InterlockedIncrement(&This->ref);
1363 static ULONG WINAPI unknode_Release(
1364 IXMLDOMNode *iface )
1366 unknode *This = impl_from_unkIXMLDOMNode( iface );
1369 ref = InterlockedDecrement( &This->ref );
1371 destroy_xmlnode(&This->node);
1378 static HRESULT WINAPI unknode_GetTypeInfoCount(
1382 unknode *This = impl_from_unkIXMLDOMNode( iface );
1384 TRACE("(%p)->(%p)\n", This, pctinfo);
1391 static HRESULT WINAPI unknode_GetTypeInfo(
1395 ITypeInfo** ppTInfo )
1397 unknode *This = impl_from_unkIXMLDOMNode( iface );
1400 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1402 hr = get_typeinfo(IXMLDOMNode_tid, ppTInfo);
1407 static HRESULT WINAPI unknode_GetIDsOfNames(
1410 LPOLESTR* rgszNames,
1415 unknode *This = impl_from_unkIXMLDOMNode( iface );
1417 ITypeInfo *typeinfo;
1420 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1423 if(!rgszNames || cNames == 0 || !rgDispId)
1424 return E_INVALIDARG;
1426 hr = get_typeinfo(IXMLDOMNode_tid, &typeinfo);
1429 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1430 ITypeInfo_Release(typeinfo);
1436 static HRESULT WINAPI unknode_Invoke(
1438 DISPID dispIdMember,
1442 DISPPARAMS* pDispParams,
1443 VARIANT* pVarResult,
1444 EXCEPINFO* pExcepInfo,
1447 unknode *This = impl_from_unkIXMLDOMNode( iface );
1448 ITypeInfo *typeinfo;
1451 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1452 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1454 hr = get_typeinfo(IXMLDOMNode_tid, &typeinfo);
1457 hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
1458 pVarResult, pExcepInfo, puArgErr);
1459 ITypeInfo_Release(typeinfo);
1465 static HRESULT WINAPI unknode_get_nodeName(
1469 unknode *This = impl_from_unkIXMLDOMNode( iface );
1471 FIXME("(%p)->(%p)\n", This, p);
1473 return node_get_nodeName(&This->node, p);
1476 static HRESULT WINAPI unknode_get_nodeValue(
1480 unknode *This = impl_from_unkIXMLDOMNode( iface );
1482 FIXME("(%p)->(%p)\n", This, value);
1485 return E_INVALIDARG;
1487 V_VT(value) = VT_NULL;
1491 static HRESULT WINAPI unknode_put_nodeValue(
1495 unknode *This = impl_from_unkIXMLDOMNode( iface );
1496 FIXME("(%p)->(v%d)\n", This, V_VT(&value));
1500 static HRESULT WINAPI unknode_get_nodeType(
1502 DOMNodeType* domNodeType )
1504 unknode *This = impl_from_unkIXMLDOMNode( iface );
1506 FIXME("(%p)->(%p)\n", This, domNodeType);
1508 *domNodeType = This->node.node->type;
1512 static HRESULT WINAPI unknode_get_parentNode(
1514 IXMLDOMNode** parent )
1516 unknode *This = impl_from_unkIXMLDOMNode( iface );
1517 FIXME("(%p)->(%p)\n", This, parent);
1518 if (!parent) return E_INVALIDARG;
1523 static HRESULT WINAPI unknode_get_childNodes(
1525 IXMLDOMNodeList** outList)
1527 unknode *This = impl_from_unkIXMLDOMNode( iface );
1529 TRACE("(%p)->(%p)\n", This, outList);
1531 return node_get_child_nodes(&This->node, outList);
1534 static HRESULT WINAPI unknode_get_firstChild(
1536 IXMLDOMNode** domNode)
1538 unknode *This = impl_from_unkIXMLDOMNode( iface );
1540 TRACE("(%p)->(%p)\n", This, domNode);
1542 return node_get_first_child(&This->node, domNode);
1545 static HRESULT WINAPI unknode_get_lastChild(
1547 IXMLDOMNode** domNode)
1549 unknode *This = impl_from_unkIXMLDOMNode( iface );
1551 TRACE("(%p)->(%p)\n", This, domNode);
1553 return node_get_last_child(&This->node, domNode);
1556 static HRESULT WINAPI unknode_get_previousSibling(
1558 IXMLDOMNode** domNode)
1560 unknode *This = impl_from_unkIXMLDOMNode( iface );
1562 TRACE("(%p)->(%p)\n", This, domNode);
1564 return node_get_previous_sibling(&This->node, domNode);
1567 static HRESULT WINAPI unknode_get_nextSibling(
1569 IXMLDOMNode** domNode)
1571 unknode *This = impl_from_unkIXMLDOMNode( iface );
1573 TRACE("(%p)->(%p)\n", This, domNode);
1575 return node_get_next_sibling(&This->node, domNode);
1578 static HRESULT WINAPI unknode_get_attributes(
1580 IXMLDOMNamedNodeMap** attributeMap)
1582 unknode *This = impl_from_unkIXMLDOMNode( iface );
1584 FIXME("(%p)->(%p)\n", This, attributeMap);
1586 return return_null_ptr((void**)attributeMap);
1589 static HRESULT WINAPI unknode_insertBefore(
1591 IXMLDOMNode* newNode, VARIANT refChild,
1592 IXMLDOMNode** outOldNode)
1594 unknode *This = impl_from_unkIXMLDOMNode( iface );
1596 FIXME("(%p)->(%p x%d %p)\n", This, newNode, V_VT(&refChild), outOldNode);
1598 return node_insert_before(&This->node, newNode, &refChild, outOldNode);
1601 static HRESULT WINAPI unknode_replaceChild(
1603 IXMLDOMNode* newNode,
1604 IXMLDOMNode* oldNode,
1605 IXMLDOMNode** outOldNode)
1607 unknode *This = impl_from_unkIXMLDOMNode( iface );
1609 FIXME("(%p)->(%p %p %p)\n", This, newNode, oldNode, outOldNode);
1611 return node_replace_child(&This->node, newNode, oldNode, outOldNode);
1614 static HRESULT WINAPI unknode_removeChild(
1616 IXMLDOMNode* domNode, IXMLDOMNode** oldNode)
1618 unknode *This = impl_from_unkIXMLDOMNode( iface );
1619 return IXMLDOMNode_removeChild( IXMLDOMNode_from_impl(&This->node), domNode, oldNode );
1622 static HRESULT WINAPI unknode_appendChild(
1624 IXMLDOMNode* newNode, IXMLDOMNode** outNewNode)
1626 unknode *This = impl_from_unkIXMLDOMNode( iface );
1627 return IXMLDOMNode_appendChild( IXMLDOMNode_from_impl(&This->node), newNode, outNewNode );
1630 static HRESULT WINAPI unknode_hasChildNodes(
1632 VARIANT_BOOL* pbool)
1634 unknode *This = impl_from_unkIXMLDOMNode( iface );
1635 return IXMLDOMNode_hasChildNodes( IXMLDOMNode_from_impl(&This->node), pbool );
1638 static HRESULT WINAPI unknode_get_ownerDocument(
1640 IXMLDOMDocument** domDocument)
1642 unknode *This = impl_from_unkIXMLDOMNode( iface );
1643 return IXMLDOMNode_get_ownerDocument( IXMLDOMNode_from_impl(&This->node), domDocument );
1646 static HRESULT WINAPI unknode_cloneNode(
1648 VARIANT_BOOL pbool, IXMLDOMNode** outNode)
1650 unknode *This = impl_from_unkIXMLDOMNode( iface );
1651 return IXMLDOMNode_cloneNode( IXMLDOMNode_from_impl(&This->node), pbool, outNode );
1654 static HRESULT WINAPI unknode_get_nodeTypeString(
1658 unknode *This = impl_from_unkIXMLDOMNode( iface );
1659 return IXMLDOMNode_get_nodeTypeString( IXMLDOMNode_from_impl(&This->node), p );
1662 static HRESULT WINAPI unknode_get_text(
1666 unknode *This = impl_from_unkIXMLDOMNode( iface );
1667 return IXMLDOMNode_get_text( IXMLDOMNode_from_impl(&This->node), p );
1670 static HRESULT WINAPI unknode_put_text(
1674 unknode *This = impl_from_unkIXMLDOMNode( iface );
1675 return IXMLDOMNode_put_text( IXMLDOMNode_from_impl(&This->node), p );
1678 static HRESULT WINAPI unknode_get_specified(
1680 VARIANT_BOOL* isSpecified)
1682 unknode *This = impl_from_unkIXMLDOMNode( iface );
1683 FIXME("(%p)->(%p) stub!\n", This, isSpecified);
1684 *isSpecified = VARIANT_TRUE;
1688 static HRESULT WINAPI unknode_get_definition(
1690 IXMLDOMNode** definitionNode)
1692 unknode *This = impl_from_unkIXMLDOMNode( iface );
1693 FIXME("(%p)->(%p)\n", This, definitionNode);
1697 static HRESULT WINAPI unknode_get_nodeTypedValue(
1701 unknode *This = impl_from_unkIXMLDOMNode( iface );
1702 return IXMLDOMNode_get_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), var1 );
1705 static HRESULT WINAPI unknode_put_nodeTypedValue(
1709 unknode *This = impl_from_unkIXMLDOMNode( iface );
1710 return IXMLDOMNode_put_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), var1 );
1713 static HRESULT WINAPI unknode_get_dataType(
1717 unknode *This = impl_from_unkIXMLDOMNode( iface );
1718 return IXMLDOMNode_get_dataType( IXMLDOMNode_from_impl(&This->node), var1 );
1721 static HRESULT WINAPI unknode_put_dataType(
1725 unknode *This = impl_from_unkIXMLDOMNode( iface );
1726 return IXMLDOMNode_put_dataType( IXMLDOMNode_from_impl(&This->node), p );
1729 static HRESULT WINAPI unknode_get_xml(
1733 unknode *This = impl_from_unkIXMLDOMNode( iface );
1734 return IXMLDOMNode_get_xml( IXMLDOMNode_from_impl(&This->node), p );
1737 static HRESULT WINAPI unknode_transformNode(
1739 IXMLDOMNode* domNode, BSTR* p)
1741 unknode *This = impl_from_unkIXMLDOMNode( iface );
1742 return IXMLDOMNode_transformNode( IXMLDOMNode_from_impl(&This->node), domNode, p );
1745 static HRESULT WINAPI unknode_selectNodes(
1747 BSTR p, IXMLDOMNodeList** outList)
1749 unknode *This = impl_from_unkIXMLDOMNode( iface );
1750 return IXMLDOMNode_selectNodes( IXMLDOMNode_from_impl(&This->node), p, outList );
1753 static HRESULT WINAPI unknode_selectSingleNode(
1755 BSTR p, IXMLDOMNode** outNode)
1757 unknode *This = impl_from_unkIXMLDOMNode( iface );
1758 return IXMLDOMNode_selectSingleNode( IXMLDOMNode_from_impl(&This->node), p, outNode );
1761 static HRESULT WINAPI unknode_get_parsed(
1763 VARIANT_BOOL* isParsed)
1765 unknode *This = impl_from_unkIXMLDOMNode( iface );
1766 FIXME("(%p)->(%p) stub!\n", This, isParsed);
1767 *isParsed = VARIANT_TRUE;
1771 static HRESULT WINAPI unknode_get_namespaceURI(
1775 unknode *This = impl_from_unkIXMLDOMNode( iface );
1776 return IXMLDOMNode_get_namespaceURI( IXMLDOMNode_from_impl(&This->node), p );
1779 static HRESULT WINAPI unknode_get_prefix(
1783 unknode *This = impl_from_unkIXMLDOMNode( iface );
1784 return IXMLDOMNode_get_prefix( IXMLDOMNode_from_impl(&This->node), p );
1787 static HRESULT WINAPI unknode_get_baseName(
1791 unknode *This = impl_from_unkIXMLDOMNode( iface );
1792 return IXMLDOMNode_get_baseName( IXMLDOMNode_from_impl(&This->node), p );
1795 static HRESULT WINAPI unknode_transformNodeToObject(
1797 IXMLDOMNode* domNode, VARIANT var1)
1799 unknode *This = impl_from_unkIXMLDOMNode( iface );
1800 return IXMLDOMNode_transformNodeToObject( IXMLDOMNode_from_impl(&This->node), domNode, var1 );
1803 static const struct IXMLDOMNodeVtbl unknode_vtbl =
1805 unknode_QueryInterface,
1808 unknode_GetTypeInfoCount,
1809 unknode_GetTypeInfo,
1810 unknode_GetIDsOfNames,
1812 unknode_get_nodeName,
1813 unknode_get_nodeValue,
1814 unknode_put_nodeValue,
1815 unknode_get_nodeType,
1816 unknode_get_parentNode,
1817 unknode_get_childNodes,
1818 unknode_get_firstChild,
1819 unknode_get_lastChild,
1820 unknode_get_previousSibling,
1821 unknode_get_nextSibling,
1822 unknode_get_attributes,
1823 unknode_insertBefore,
1824 unknode_replaceChild,
1825 unknode_removeChild,
1826 unknode_appendChild,
1827 unknode_hasChildNodes,
1828 unknode_get_ownerDocument,
1830 unknode_get_nodeTypeString,
1833 unknode_get_specified,
1834 unknode_get_definition,
1835 unknode_get_nodeTypedValue,
1836 unknode_put_nodeTypedValue,
1837 unknode_get_dataType,
1838 unknode_put_dataType,
1840 unknode_transformNode,
1841 unknode_selectNodes,
1842 unknode_selectSingleNode,
1844 unknode_get_namespaceURI,
1846 unknode_get_baseName,
1847 unknode_transformNodeToObject
1850 IXMLDOMNode *create_node( xmlNodePtr node )
1859 TRACE("type %d\n", node->type);
1862 case XML_ELEMENT_NODE:
1863 pUnk = create_element( node );
1865 case XML_ATTRIBUTE_NODE:
1866 pUnk = create_attribute( node );
1869 pUnk = create_text( node );
1871 case XML_CDATA_SECTION_NODE:
1872 pUnk = create_cdata( node );
1874 case XML_ENTITY_REF_NODE:
1875 pUnk = create_doc_entity_ref( node );
1878 pUnk = create_pi( node );
1880 case XML_COMMENT_NODE:
1881 pUnk = create_comment( node );
1883 case XML_DOCUMENT_NODE:
1884 pUnk = create_domdoc( node );
1886 case XML_DOCUMENT_FRAG_NODE:
1887 pUnk = create_doc_fragment( node );
1892 FIXME("only creating basic node for type %d\n", node->type);
1894 new_node = heap_alloc(sizeof(unknode));
1898 new_node->lpVtbl = &unknode_vtbl;
1900 init_xmlnode(&new_node->node, node, (IXMLDOMNode*)&new_node->lpVtbl, NULL);
1901 pUnk = (IUnknown*)&new_node->lpVtbl;
1905 hr = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMNode, (LPVOID*)&ret);
1906 IUnknown_Release(pUnk);
1907 if(FAILED(hr)) return NULL;