2 * DOM Document implementation
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
27 # include <libxml/parser.h>
28 # include <libxml/xmlerror.h>
38 #include "msxml_private.h"
40 #include "wine/debug.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
46 static const xmlChar DT_prefix[] = "dt";
47 static const xmlChar DT_nsURI[] = "urn:schemas-microsoft-com:datatypes";
49 typedef struct _domelem
52 IXMLDOMElement IXMLDOMElement_iface;
56 static inline domelem *impl_from_IXMLDOMElement( IXMLDOMElement *iface )
58 return CONTAINING_RECORD(iface, domelem, IXMLDOMElement_iface);
61 static inline xmlNodePtr get_element( const domelem *This )
63 return This->node.node;
66 static HRESULT WINAPI domelem_QueryInterface(
67 IXMLDOMElement *iface,
71 domelem *This = impl_from_IXMLDOMElement( iface );
73 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
75 if ( IsEqualGUID( riid, &IID_IXMLDOMElement ) ||
76 IsEqualGUID( riid, &IID_IXMLDOMNode ) ||
77 IsEqualGUID( riid, &IID_IDispatch ) ||
78 IsEqualGUID( riid, &IID_IUnknown ) )
80 *ppvObject = &This->IXMLDOMElement_iface;
82 else if(node_query_interface(&This->node, riid, ppvObject))
84 return *ppvObject ? S_OK : E_NOINTERFACE;
88 FIXME("interface %s not implemented\n", debugstr_guid(riid));
93 IUnknown_AddRef( (IUnknown*)*ppvObject );
97 static ULONG WINAPI domelem_AddRef(
98 IXMLDOMElement *iface )
100 domelem *This = impl_from_IXMLDOMElement( iface );
101 LONG ref = InterlockedIncrement(&This->ref);
103 TRACE("(%p)->(%d)\n", This, ref);
108 static ULONG WINAPI domelem_Release(
109 IXMLDOMElement *iface )
111 domelem *This = impl_from_IXMLDOMElement( iface );
112 ULONG ref = InterlockedDecrement(&This->ref);
114 TRACE("(%p)->(%d)\n", This, ref);
117 destroy_xmlnode(&This->node);
124 static HRESULT WINAPI domelem_GetTypeInfoCount(
125 IXMLDOMElement *iface,
128 domelem *This = impl_from_IXMLDOMElement( iface );
130 TRACE("(%p)->(%p)\n", This, pctinfo);
137 static HRESULT WINAPI domelem_GetTypeInfo(
138 IXMLDOMElement *iface,
139 UINT iTInfo, LCID lcid,
140 ITypeInfo** ppTInfo )
142 domelem *This = impl_from_IXMLDOMElement( iface );
145 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
147 hr = get_typeinfo(IXMLDOMElement_tid, ppTInfo);
152 static HRESULT WINAPI domelem_GetIDsOfNames(
153 IXMLDOMElement *iface,
154 REFIID riid, LPOLESTR* rgszNames,
155 UINT cNames, LCID lcid, DISPID* rgDispId )
157 domelem *This = impl_from_IXMLDOMElement( iface );
161 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
164 if(!rgszNames || cNames == 0 || !rgDispId)
167 hr = get_typeinfo(IXMLDOMElement_tid, &typeinfo);
170 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
171 ITypeInfo_Release(typeinfo);
177 static HRESULT WINAPI domelem_Invoke(
178 IXMLDOMElement *iface,
179 DISPID dispIdMember, REFIID riid, LCID lcid,
180 WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult,
181 EXCEPINFO* pExcepInfo, UINT* puArgErr )
183 domelem *This = impl_from_IXMLDOMElement( iface );
187 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
188 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
190 hr = get_typeinfo(IXMLDOMElement_tid, &typeinfo);
193 hr = ITypeInfo_Invoke(typeinfo, &This->IXMLDOMElement_iface, dispIdMember, wFlags,
194 pDispParams, pVarResult, pExcepInfo, puArgErr);
195 ITypeInfo_Release(typeinfo);
201 static HRESULT WINAPI domelem_get_nodeName(
202 IXMLDOMElement *iface,
205 domelem *This = impl_from_IXMLDOMElement( iface );
207 TRACE("(%p)->(%p)\n", This, p);
209 return node_get_nodeName(&This->node, p);
212 static HRESULT WINAPI domelem_get_nodeValue(
213 IXMLDOMElement *iface,
216 domelem *This = impl_from_IXMLDOMElement( iface );
218 TRACE("(%p)->(%p)\n", This, value);
223 V_VT(value) = VT_NULL;
224 V_BSTR(value) = NULL; /* tests show that we should do this */
228 static HRESULT WINAPI domelem_put_nodeValue(
229 IXMLDOMElement *iface,
232 domelem *This = impl_from_IXMLDOMElement( iface );
233 TRACE("(%p)->(%s)\n", This, debugstr_variant(&value));
237 static HRESULT WINAPI domelem_get_nodeType(
238 IXMLDOMElement *iface,
239 DOMNodeType* domNodeType )
241 domelem *This = impl_from_IXMLDOMElement( iface );
243 TRACE("(%p)->(%p)\n", This, domNodeType);
245 *domNodeType = NODE_ELEMENT;
249 static HRESULT WINAPI domelem_get_parentNode(
250 IXMLDOMElement *iface,
251 IXMLDOMNode** parent )
253 domelem *This = impl_from_IXMLDOMElement( iface );
255 TRACE("(%p)->(%p)\n", This, parent);
257 return node_get_parent(&This->node, parent);
260 static HRESULT WINAPI domelem_get_childNodes(
261 IXMLDOMElement *iface,
262 IXMLDOMNodeList** outList)
264 domelem *This = impl_from_IXMLDOMElement( iface );
266 TRACE("(%p)->(%p)\n", This, outList);
268 return node_get_child_nodes(&This->node, outList);
271 static HRESULT WINAPI domelem_get_firstChild(
272 IXMLDOMElement *iface,
273 IXMLDOMNode** domNode)
275 domelem *This = impl_from_IXMLDOMElement( iface );
277 TRACE("(%p)->(%p)\n", This, domNode);
279 return node_get_first_child(&This->node, domNode);
282 static HRESULT WINAPI domelem_get_lastChild(
283 IXMLDOMElement *iface,
284 IXMLDOMNode** domNode)
286 domelem *This = impl_from_IXMLDOMElement( iface );
288 TRACE("(%p)->(%p)\n", This, domNode);
290 return node_get_last_child(&This->node, domNode);
293 static HRESULT WINAPI domelem_get_previousSibling(
294 IXMLDOMElement *iface,
295 IXMLDOMNode** domNode)
297 domelem *This = impl_from_IXMLDOMElement( iface );
299 TRACE("(%p)->(%p)\n", This, domNode);
301 return node_get_previous_sibling(&This->node, domNode);
304 static HRESULT WINAPI domelem_get_nextSibling(
305 IXMLDOMElement *iface,
306 IXMLDOMNode** domNode)
308 domelem *This = impl_from_IXMLDOMElement( iface );
310 TRACE("(%p)->(%p)\n", This, domNode);
312 return node_get_next_sibling(&This->node, domNode);
315 static HRESULT WINAPI domelem_get_attributes(
316 IXMLDOMElement *iface,
317 IXMLDOMNamedNodeMap** attributeMap)
319 domelem *This = impl_from_IXMLDOMElement( iface );
321 TRACE("(%p)->(%p)\n", This, attributeMap);
323 *attributeMap = create_nodemap((IXMLDOMNode*)&This->IXMLDOMElement_iface);
327 static HRESULT WINAPI domelem_insertBefore(
328 IXMLDOMElement *iface,
329 IXMLDOMNode* newNode, VARIANT refChild,
330 IXMLDOMNode** outOldNode)
332 domelem *This = impl_from_IXMLDOMElement( iface );
334 TRACE("(%p)->(%p %s %p)\n", This, newNode, debugstr_variant(&refChild), outOldNode);
336 return node_insert_before(&This->node, newNode, &refChild, outOldNode);
339 static HRESULT WINAPI domelem_replaceChild(
340 IXMLDOMElement *iface,
341 IXMLDOMNode* newNode,
342 IXMLDOMNode* oldNode,
343 IXMLDOMNode** outOldNode)
345 domelem *This = impl_from_IXMLDOMElement( iface );
347 TRACE("(%p)->(%p %p %p)\n", This, newNode, oldNode, outOldNode);
349 return node_replace_child(&This->node, newNode, oldNode, outOldNode);
352 static HRESULT WINAPI domelem_removeChild(
353 IXMLDOMElement *iface,
354 IXMLDOMNode *child, IXMLDOMNode **oldChild)
356 domelem *This = impl_from_IXMLDOMElement( iface );
357 TRACE("(%p)->(%p %p)\n", This, child, oldChild);
358 return node_remove_child(&This->node, child, oldChild);
361 static HRESULT WINAPI domelem_appendChild(
362 IXMLDOMElement *iface,
363 IXMLDOMNode *child, IXMLDOMNode **outChild)
365 domelem *This = impl_from_IXMLDOMElement( iface );
366 TRACE("(%p)->(%p %p)\n", This, child, outChild);
367 return node_append_child(&This->node, child, outChild);
370 static HRESULT WINAPI domelem_hasChildNodes(
371 IXMLDOMElement *iface,
374 domelem *This = impl_from_IXMLDOMElement( iface );
375 TRACE("(%p)->(%p)\n", This, ret);
376 return node_has_childnodes(&This->node, ret);
379 static HRESULT WINAPI domelem_get_ownerDocument(
380 IXMLDOMElement *iface,
381 IXMLDOMDocument **doc)
383 domelem *This = impl_from_IXMLDOMElement( iface );
384 TRACE("(%p)->(%p)\n", This, doc);
385 return node_get_owner_doc(&This->node, doc);
388 static HRESULT WINAPI domelem_cloneNode(
389 IXMLDOMElement *iface,
390 VARIANT_BOOL deep, IXMLDOMNode** outNode)
392 domelem *This = impl_from_IXMLDOMElement( iface );
393 TRACE("(%p)->(%d %p)\n", This, deep, outNode);
394 return node_clone( &This->node, deep, outNode );
397 static HRESULT WINAPI domelem_get_nodeTypeString(
398 IXMLDOMElement *iface,
401 domelem *This = impl_from_IXMLDOMElement( iface );
402 static const WCHAR elementW[] = {'e','l','e','m','e','n','t',0};
404 TRACE("(%p)->(%p)\n", This, p);
406 return return_bstr(elementW, p);
409 static HRESULT WINAPI domelem_get_text(
410 IXMLDOMElement *iface,
413 domelem *This = impl_from_IXMLDOMElement( iface );
414 TRACE("(%p)->(%p)\n", This, p);
415 return node_get_text(&This->node, p);
418 static HRESULT WINAPI domelem_put_text(
419 IXMLDOMElement *iface,
422 domelem *This = impl_from_IXMLDOMElement( iface );
423 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
424 return node_put_text( &This->node, p );
427 static HRESULT WINAPI domelem_get_specified(
428 IXMLDOMElement *iface,
429 VARIANT_BOOL* isSpecified)
431 domelem *This = impl_from_IXMLDOMElement( iface );
432 FIXME("(%p)->(%p) stub!\n", This, isSpecified);
433 *isSpecified = VARIANT_TRUE;
437 static HRESULT WINAPI domelem_get_definition(
438 IXMLDOMElement *iface,
439 IXMLDOMNode** definitionNode)
441 domelem *This = impl_from_IXMLDOMElement( iface );
442 FIXME("(%p)->(%p)\n", This, definitionNode);
446 static inline BYTE hex_to_byte(xmlChar c)
448 if(c <= '9') return c-'0';
449 if(c <= 'F') return c-'A'+10;
453 static inline BYTE base64_to_byte(xmlChar c)
455 if(c == '+') return 62;
456 if(c == '/') return 63;
457 if(c <= '9') return c-'0'+52;
458 if(c <= 'Z') return c-'A';
462 static inline HRESULT VARIANT_from_DT(XDR_DT dt, xmlChar* str, VARIANT* v)
466 BOOL handled = FALSE;
481 V_BSTR(v) = bstr_from_xmlChar(str);
484 return E_OUTOFMEMORY;
502 st.wDayOfWeek = st.wHour = st.wMinute = st.wSecond = st.wMilliseconds = 0;
504 V_VT(&src) = VT_BSTR;
505 V_BSTR(&src) = bstr_from_xmlChar(str);
508 return E_OUTOFMEMORY;
511 e = p + SysStringLen(V_BSTR(&src));
513 if(p+4<e && *(p+4)=='-') /* parse date (yyyy-mm-dd) */
516 st.wMonth = atoiW(p+5);
517 st.wDay = atoiW(p+8);
523 if(p+2<e && *(p+2)==':') /* parse time (hh:mm:ss.?) */
526 st.wMinute = atoiW(p+3);
527 st.wSecond = atoiW(p+6);
533 while(isdigitW(*p)) p++;
537 SystemTimeToVariantTime(&st, &date);
541 if(*p == '+') /* parse timezone offset (+hh:mm) */
542 V_DATE(v) += (DOUBLE)atoiW(p+1)/24 + (DOUBLE)atoiW(p+4)/1440;
543 else if(*p == '-') /* parse timezone offset (-hh:mm) */
544 V_DATE(v) -= (DOUBLE)atoiW(p+1)/24 + (DOUBLE)atoiW(p+4)/1440;
555 len = xmlStrlen(str)/2;
559 V_VT(v) = (VT_ARRAY|VT_UI1);
560 V_ARRAY(v) = SafeArrayCreate(VT_UI1, 1, &sab);
563 return E_OUTOFMEMORY;
566 ((BYTE*)V_ARRAY(v)->pvData)[i] = (hex_to_byte(str[2*i])<<4)
567 + hex_to_byte(str[2*i+1]);
576 len = xmlStrlen(str);
577 if(str[len-2] == '=') i = 2;
578 else if(str[len-1] == '=') i = 1;
582 sab.cElements = len/4*3-i;
584 V_VT(v) = (VT_ARRAY|VT_UI1);
585 V_ARRAY(v) = SafeArrayCreate(VT_UI1, 1, &sab);
588 return E_OUTOFMEMORY;
590 for(i=0; i<len/4; i++)
592 ((BYTE*)V_ARRAY(v)->pvData)[3*i] = (base64_to_byte(str[4*i])<<2)
593 + (base64_to_byte(str[4*i+1])>>4);
594 if(3*i+1 < sab.cElements)
595 ((BYTE*)V_ARRAY(v)->pvData)[3*i+1] = (base64_to_byte(str[4*i+1])<<4)
596 + (base64_to_byte(str[4*i+2])>>2);
597 if(3*i+2 < sab.cElements)
598 ((BYTE*)V_ARRAY(v)->pvData)[3*i+2] = (base64_to_byte(str[4*i+2])<<6)
599 + base64_to_byte(str[4*i+3]);
650 FIXME("need to handle dt:%s\n", dt_to_str(dt));
652 V_BSTR(v) = bstr_from_xmlChar(str);
654 return E_OUTOFMEMORY;
661 V_VT(&src) = VT_BSTR;
662 V_BSTR(&src) = bstr_from_xmlChar(str);
665 return E_OUTOFMEMORY;
667 hr = VariantChangeTypeEx(v, &src,
668 MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT),0, V_VT(v));
674 static HRESULT WINAPI domelem_get_nodeTypedValue(
675 IXMLDOMElement *iface,
678 domelem *This = impl_from_IXMLDOMElement( iface );
683 TRACE("(%p)->(%p)\n", This, var1);
688 V_VT(var1) = VT_NULL;
690 dt = element_get_dt(get_element(This));
691 content = xmlNodeGetContent(get_element(This));
692 hr = VARIANT_from_DT(dt, content, var1);
698 static HRESULT WINAPI domelem_put_nodeTypedValue(
699 IXMLDOMElement *iface,
702 domelem *This = impl_from_IXMLDOMElement( iface );
706 TRACE("(%p)->(%s)\n", This, debugstr_variant(&value));
708 /* for untyped node coerce to BSTR and set */
709 if (IXMLDOMElement_get_dataType(iface, &type) == S_FALSE)
711 if (V_VT(&value) != VT_BSTR)
713 hr = VariantChangeType(&value, &value, 0, VT_BSTR);
716 hr = node_set_content(&This->node, V_BSTR(&value));
717 VariantClear(&value);
721 hr = node_set_content(&This->node, V_BSTR(&value));
725 FIXME("not implemented for typed nodes. type %s\n", debugstr_w(V_BSTR(&value)));
733 XDR_DT element_get_dt(xmlNodePtr node)
735 XDR_DT dt = DT_INVALID;
737 TRACE("(%p)\n", node);
738 if(node->type != XML_ELEMENT_NODE)
740 FIXME("invalid element node\n");
744 if (node->ns && xmlStrEqual(node->ns->href, DT_nsURI))
746 dt = str_to_dt(node->name, -1);
750 xmlChar* pVal = xmlGetNsProp(node, BAD_CAST "dt", DT_nsURI);
753 dt = str_to_dt(pVal, -1);
758 IXMLDOMDocument3* doc = (IXMLDOMDocument3*)create_domdoc((xmlNodePtr)node->doc);
764 if (IXMLDOMDocument3_get_schemas(doc, &v) == S_OK &&
765 V_VT(&v) == VT_DISPATCH)
767 dt = SchemaCache_get_node_dt((IXMLDOMSchemaCollection2*)V_DISPATCH(&v), node);
770 IXMLDOMDocument3_Release(doc);
775 TRACE("=> dt:%s\n", dt_to_str(dt));
779 static HRESULT WINAPI domelem_get_dataType(
780 IXMLDOMElement *iface,
783 domelem *This = impl_from_IXMLDOMElement( iface );
786 TRACE("(%p)->(%p)\n", This, typename);
791 dt = element_get_dt(get_element(This));
820 V_VT(typename) = VT_BSTR;
821 V_BSTR(typename) = SysAllocString(dt_to_bstr(dt));
823 if (!V_BSTR(typename))
824 return E_OUTOFMEMORY;
827 /* Other types (DTD equivalents) do not return anything here,
828 * but the pointer part of the VARIANT is set to NULL */
829 V_VT(typename) = VT_NULL;
830 V_BSTR(typename) = NULL;
833 return (V_VT(typename) != VT_NULL) ? S_OK : S_FALSE;
836 static HRESULT WINAPI domelem_put_dataType(
837 IXMLDOMElement *iface,
840 domelem *This = impl_from_IXMLDOMElement( iface );
845 TRACE("(%p)->(%s)\n", This, debugstr_w(dtName));
850 dt = bstr_to_dt(dtName, -1);
852 /* An example of this is. The Text in the node needs to be a 0 or 1 for a boolean type.
853 This applies to changing types (string->bool) or setting a new one
855 str = xmlNodeGetContent(get_element(This));
856 hr = dt_validate(dt, str);
859 /* Check all supported types. */
894 xmlAttrPtr attr = xmlHasNsProp(get_element(This), DT_prefix, DT_nsURI);
897 attr = xmlSetNsProp(get_element(This), attr->ns, DT_prefix, dt_to_str(dt));
902 xmlNsPtr ns = xmlNewNs(get_element(This), DT_nsURI, DT_prefix);
905 attr = xmlNewNsProp(get_element(This), ns, DT_prefix, dt_to_str(dt));
908 xmlAddChild(get_element(This), (xmlNodePtr)attr);
912 ERR("Failed to create Attribute\n");
915 ERR("Failed to create Namespace\n");
920 FIXME("need to handle dt:%s\n", dt_to_str(dt));
928 static HRESULT WINAPI domelem_get_xml(
929 IXMLDOMElement *iface,
932 domelem *This = impl_from_IXMLDOMElement( iface );
934 TRACE("(%p)->(%p)\n", This, p);
936 return node_get_xml(&This->node, TRUE, FALSE, p);
939 static HRESULT WINAPI domelem_transformNode(
940 IXMLDOMElement *iface,
941 IXMLDOMNode *node, BSTR *p)
943 domelem *This = impl_from_IXMLDOMElement( iface );
944 TRACE("(%p)->(%p %p)\n", This, node, p);
945 return node_transform_node(&This->node, node, p);
948 static HRESULT WINAPI domelem_selectNodes(
949 IXMLDOMElement *iface,
950 BSTR p, IXMLDOMNodeList** outList)
952 domelem *This = impl_from_IXMLDOMElement( iface );
953 TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outList);
954 return node_select_nodes(&This->node, p, outList);
957 static HRESULT WINAPI domelem_selectSingleNode(
958 IXMLDOMElement *iface,
959 BSTR p, IXMLDOMNode** outNode)
961 domelem *This = impl_from_IXMLDOMElement( iface );
962 TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outNode);
963 return node_select_singlenode(&This->node, p, outNode);
966 static HRESULT WINAPI domelem_get_parsed(
967 IXMLDOMElement *iface,
968 VARIANT_BOOL* isParsed)
970 domelem *This = impl_from_IXMLDOMElement( iface );
971 FIXME("(%p)->(%p) stub!\n", This, isParsed);
972 *isParsed = VARIANT_TRUE;
976 static HRESULT WINAPI domelem_get_namespaceURI(
977 IXMLDOMElement *iface,
980 domelem *This = impl_from_IXMLDOMElement( iface );
981 TRACE("(%p)->(%p)\n", This, p);
982 return node_get_namespaceURI(&This->node, p);
985 static HRESULT WINAPI domelem_get_prefix(
986 IXMLDOMElement *iface,
989 domelem *This = impl_from_IXMLDOMElement( iface );
990 TRACE("(%p)->(%p)\n", This, prefix);
991 return node_get_prefix( &This->node, prefix );
994 static HRESULT WINAPI domelem_get_baseName(
995 IXMLDOMElement *iface,
998 domelem *This = impl_from_IXMLDOMElement( iface );
999 TRACE("(%p)->(%p)\n", This, name);
1000 return node_get_base_name( &This->node, name );
1003 static HRESULT WINAPI domelem_transformNodeToObject(
1004 IXMLDOMElement *iface,
1005 IXMLDOMNode* domNode, VARIANT var1)
1007 domelem *This = impl_from_IXMLDOMElement( iface );
1008 FIXME("(%p)->(%p %s)\n", This, domNode, debugstr_variant(&var1));
1012 static HRESULT WINAPI domelem_get_tagName(
1013 IXMLDOMElement *iface,
1016 domelem *This = impl_from_IXMLDOMElement( iface );
1018 const xmlChar *prefix;
1021 TRACE("(%p)->(%p)\n", This, p );
1023 if (!p) return E_INVALIDARG;
1025 element = get_element( This );
1029 prefix = element->ns ? element->ns->prefix : NULL;
1030 qname = xmlBuildQName(element->name, prefix, NULL, 0);
1032 *p = bstr_from_xmlChar(qname);
1033 if (qname != element->name) xmlFree(qname);
1035 return *p ? S_OK : E_OUTOFMEMORY;
1038 static HRESULT WINAPI domelem_getAttribute(
1039 IXMLDOMElement *iface,
1040 BSTR name, VARIANT* value)
1042 domelem *This = impl_from_IXMLDOMElement( iface );
1044 xmlChar *xml_name, *xml_value = NULL;
1045 HRESULT hr = S_FALSE;
1047 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), value);
1050 return E_INVALIDARG;
1052 element = get_element( This );
1056 V_BSTR(value) = NULL;
1057 V_VT(value) = VT_NULL;
1059 xml_name = xmlChar_from_wchar( name );
1061 if(!xmlValidateNameValue(xml_name))
1064 xml_value = xmlGetNsProp(element, xml_name, NULL);
1066 heap_free(xml_name);
1069 V_VT(value) = VT_BSTR;
1070 V_BSTR(value) = bstr_from_xmlChar( xml_value );
1078 static HRESULT WINAPI domelem_setAttribute(
1079 IXMLDOMElement *iface,
1080 BSTR name, VARIANT value)
1082 domelem *This = impl_from_IXMLDOMElement( iface );
1084 xmlChar *xml_name, *xml_value;
1088 TRACE("(%p)->(%s %s)\n", This, debugstr_w(name), debugstr_variant(&value));
1090 element = get_element( This );
1095 hr = VariantChangeType(&var, &value, 0, VT_BSTR);
1098 FIXME("VariantChangeType failed\n");
1102 xml_name = xmlChar_from_wchar( name );
1103 xml_value = xmlChar_from_wchar( V_BSTR(&var) );
1105 if(!xmlSetNsProp(element, NULL, xml_name, xml_value))
1108 heap_free(xml_value);
1109 heap_free(xml_name);
1115 static HRESULT WINAPI domelem_removeAttribute(
1116 IXMLDOMElement *iface,
1119 domelem *This = impl_from_IXMLDOMElement( iface );
1120 IXMLDOMNamedNodeMap *attr;
1123 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
1125 hr = IXMLDOMElement_get_attributes(iface, &attr);
1126 if (hr != S_OK) return hr;
1128 hr = IXMLDOMNamedNodeMap_removeNamedItem(attr, p, NULL);
1129 IXMLDOMNamedNodeMap_Release(attr);
1134 static HRESULT WINAPI domelem_getAttributeNode(
1135 IXMLDOMElement *iface,
1136 BSTR p, IXMLDOMAttribute** attributeNode )
1138 domelem *This = impl_from_IXMLDOMElement( iface );
1143 HRESULT hr = S_FALSE;
1145 TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), attributeNode);
1150 *attributeNode = NULL;
1152 element = get_element( This );
1156 xml_name = xmlChar_from_wchar(p);
1158 if(!xmlValidateNameValue(xml_name))
1160 heap_free(xml_name);
1164 attr = xmlHasProp(element, xml_name);
1166 unk = create_attribute((xmlNodePtr)attr);
1167 hr = IUnknown_QueryInterface(unk, &IID_IXMLDOMAttribute, (void**)attributeNode);
1168 IUnknown_Release(unk);
1171 heap_free(xml_name);
1176 static HRESULT WINAPI domelem_setAttributeNode(
1177 IXMLDOMElement *iface,
1178 IXMLDOMAttribute* attribute,
1179 IXMLDOMAttribute** old)
1181 domelem *This = impl_from_IXMLDOMElement( iface );
1182 static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
1183 xmlChar *name, *value;
1190 FIXME("(%p)->(%p %p): semi-stub\n", This, attribute, old);
1192 if (!attribute) return E_INVALIDARG;
1194 attr_node = get_node_obj((IXMLDOMNode*)attribute);
1195 if (!attr_node) return E_FAIL;
1197 if (attr_node->parent)
1199 WARN("attempt to add already used attribute\n");
1203 hr = IXMLDOMAttribute_get_nodeName(attribute, &nameW);
1204 if (hr != S_OK) return hr;
1206 /* adding xmlns attribute doesn't change a tree or existing namespace definition */
1207 if (!strcmpW(nameW, xmlnsW))
1209 SysFreeString(nameW);
1210 return DISP_E_UNKNOWNNAME;
1213 hr = IXMLDOMAttribute_get_nodeValue(attribute, &valueW);
1216 SysFreeString(nameW);
1220 if (old) *old = NULL;
1222 TRACE("attribute: %s=%s\n", debugstr_w(nameW), debugstr_w(V_BSTR(&valueW)));
1224 hr = IXMLDOMAttribute_get_prefix(attribute, &prefix);
1227 FIXME("namespaces not supported: %s\n", debugstr_w(prefix));
1228 SysFreeString(prefix);
1231 name = xmlChar_from_wchar(nameW);
1232 value = xmlChar_from_wchar(V_BSTR(&valueW));
1234 if (!name || !value)
1236 SysFreeString(nameW);
1237 VariantClear(&valueW);
1240 return E_OUTOFMEMORY;
1243 attr = xmlSetNsProp(get_element(This), NULL, name, value);
1245 attr_node->parent = (IXMLDOMNode*)iface;
1247 SysFreeString(nameW);
1248 VariantClear(&valueW);
1252 return attr ? S_OK : E_FAIL;
1255 static HRESULT WINAPI domelem_removeAttributeNode(
1256 IXMLDOMElement *iface,
1257 IXMLDOMAttribute* domAttribute,
1258 IXMLDOMAttribute** attributeNode)
1260 domelem *This = impl_from_IXMLDOMElement( iface );
1261 FIXME("(%p)->(%p %p)\n", This, domAttribute, attributeNode);
1265 static HRESULT WINAPI domelem_getElementsByTagName(
1266 IXMLDOMElement *iface,
1267 BSTR tagName, IXMLDOMNodeList** resultList)
1269 domelem *This = impl_from_IXMLDOMElement( iface );
1274 TRACE("(%p)->(%s, %p)\n", This, debugstr_w(tagName), resultList);
1276 if (!tagName || !resultList) return E_INVALIDARG;
1278 XPath = is_xpathmode(get_element(This)->doc);
1279 set_xpathmode(get_element(This)->doc, TRUE);
1280 query = tagName_to_XPath(tagName);
1281 hr = queryresult_create(get_element(This), query, resultList);
1283 set_xpathmode(get_element(This)->doc, XPath);
1288 static HRESULT WINAPI domelem_normalize(
1289 IXMLDOMElement *iface )
1291 domelem *This = impl_from_IXMLDOMElement( iface );
1292 FIXME("%p\n", This);
1296 static const struct IXMLDOMElementVtbl domelem_vtbl =
1298 domelem_QueryInterface,
1301 domelem_GetTypeInfoCount,
1302 domelem_GetTypeInfo,
1303 domelem_GetIDsOfNames,
1305 domelem_get_nodeName,
1306 domelem_get_nodeValue,
1307 domelem_put_nodeValue,
1308 domelem_get_nodeType,
1309 domelem_get_parentNode,
1310 domelem_get_childNodes,
1311 domelem_get_firstChild,
1312 domelem_get_lastChild,
1313 domelem_get_previousSibling,
1314 domelem_get_nextSibling,
1315 domelem_get_attributes,
1316 domelem_insertBefore,
1317 domelem_replaceChild,
1318 domelem_removeChild,
1319 domelem_appendChild,
1320 domelem_hasChildNodes,
1321 domelem_get_ownerDocument,
1323 domelem_get_nodeTypeString,
1326 domelem_get_specified,
1327 domelem_get_definition,
1328 domelem_get_nodeTypedValue,
1329 domelem_put_nodeTypedValue,
1330 domelem_get_dataType,
1331 domelem_put_dataType,
1333 domelem_transformNode,
1334 domelem_selectNodes,
1335 domelem_selectSingleNode,
1337 domelem_get_namespaceURI,
1339 domelem_get_baseName,
1340 domelem_transformNodeToObject,
1341 domelem_get_tagName,
1342 domelem_getAttribute,
1343 domelem_setAttribute,
1344 domelem_removeAttribute,
1345 domelem_getAttributeNode,
1346 domelem_setAttributeNode,
1347 domelem_removeAttributeNode,
1348 domelem_getElementsByTagName,
1352 static const tid_t domelem_iface_tids[] = {
1357 static dispex_static_data_t domelem_dispex = {
1364 IUnknown* create_element( xmlNodePtr element )
1368 This = heap_alloc( sizeof *This );
1372 This->IXMLDOMElement_iface.lpVtbl = &domelem_vtbl;
1375 init_xmlnode(&This->node, element, (IXMLDOMNode*)&This->IXMLDOMElement_iface, &domelem_dispex);
1377 return (IUnknown*)&This->IXMLDOMElement_iface;