msxml3: Block attempt to modify namespace definition with setAttribute().
[wine/multimedia.git] / dlls / msxml3 / element.c
blob834f39b7c020036ff028d474794881de0a7b16c8
1 /*
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
21 #define COBJMACROS
23 #include "config.h"
25 #include <stdarg.h>
26 #ifdef HAVE_LIBXML2
27 # include <libxml/parser.h>
28 # include <libxml/xmlerror.h>
29 #endif
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winuser.h"
34 #include "winnls.h"
35 #include "ole2.h"
36 #include "msxml6.h"
38 #include "msxml_private.h"
40 #include "wine/debug.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
44 #ifdef HAVE_LIBXML2
46 static const xmlChar DT_prefix[] = "dt";
47 static const xmlChar DT_nsURI[] = "urn:schemas-microsoft-com:datatypes";
49 typedef struct _domelem
51 xmlnode node;
52 IXMLDOMElement IXMLDOMElement_iface;
53 LONG ref;
54 } domelem;
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,
68 REFIID riid,
69 void** ppvObject )
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;
86 else
88 TRACE("interface %s not implemented\n", debugstr_guid(riid));
89 *ppvObject = NULL;
90 return E_NOINTERFACE;
93 IUnknown_AddRef( (IUnknown*)*ppvObject );
94 return S_OK;
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);
105 return 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);
116 if(!ref) {
117 destroy_xmlnode(&This->node);
118 heap_free(This);
121 return ref;
124 static HRESULT WINAPI domelem_GetTypeInfoCount(
125 IXMLDOMElement *iface,
126 UINT* pctinfo )
128 domelem *This = impl_from_IXMLDOMElement( iface );
130 TRACE("(%p)->(%p)\n", This, pctinfo);
132 *pctinfo = 1;
134 return S_OK;
137 static HRESULT WINAPI domelem_GetTypeInfo(
138 IXMLDOMElement *iface,
139 UINT iTInfo, LCID lcid,
140 ITypeInfo** ppTInfo )
142 domelem *This = impl_from_IXMLDOMElement( iface );
143 HRESULT hr;
145 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
147 hr = get_typeinfo(IXMLDOMElement_tid, ppTInfo);
149 return hr;
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 );
158 ITypeInfo *typeinfo;
159 HRESULT hr;
161 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
162 lcid, rgDispId);
164 if(!rgszNames || cNames == 0 || !rgDispId)
165 return E_INVALIDARG;
167 hr = get_typeinfo(IXMLDOMElement_tid, &typeinfo);
168 if(SUCCEEDED(hr))
170 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
171 ITypeInfo_Release(typeinfo);
174 return hr;
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 );
184 ITypeInfo *typeinfo;
185 HRESULT hr;
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);
191 if(SUCCEEDED(hr))
193 hr = ITypeInfo_Invoke(typeinfo, &This->IXMLDOMElement_iface, dispIdMember, wFlags,
194 pDispParams, pVarResult, pExcepInfo, puArgErr);
195 ITypeInfo_Release(typeinfo);
198 return hr;
201 static HRESULT WINAPI domelem_get_nodeName(
202 IXMLDOMElement *iface,
203 BSTR* p )
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,
214 VARIANT* value)
216 domelem *This = impl_from_IXMLDOMElement( iface );
218 TRACE("(%p)->(%p)\n", This, value);
220 if(!value)
221 return E_INVALIDARG;
223 V_VT(value) = VT_NULL;
224 V_BSTR(value) = NULL; /* tests show that we should do this */
225 return S_FALSE;
228 static HRESULT WINAPI domelem_put_nodeValue(
229 IXMLDOMElement *iface,
230 VARIANT value)
232 domelem *This = impl_from_IXMLDOMElement( iface );
233 TRACE("(%p)->(%s)\n", This, debugstr_variant(&value));
234 return E_FAIL;
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;
246 return S_OK;
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** map)
319 domelem *This = impl_from_IXMLDOMElement( iface );
321 TRACE("(%p)->(%p)\n", This, map);
323 *map = create_nodemap(This->node.node);
324 return S_OK;
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,
372 VARIANT_BOOL *ret)
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,
399 BSTR* p)
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,
411 BSTR* p)
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,
420 BSTR p)
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;
434 return S_OK;
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);
443 return E_NOTIMPL;
446 static inline BYTE hex_to_byte(xmlChar c)
448 if(c <= '9') return c-'0';
449 if(c <= 'F') return c-'A'+10;
450 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';
459 return c-'a'+26;
462 static inline HRESULT variant_from_dt(XDR_DT dt, xmlChar* str, VARIANT* v)
464 VARIANT src;
465 HRESULT hr = S_OK;
466 BOOL handled = FALSE;
468 VariantInit(&src);
470 switch (dt)
472 case DT_INVALID:
473 case DT_STRING:
474 case DT_NMTOKEN:
475 case DT_NMTOKENS:
476 case DT_NUMBER:
477 case DT_URI:
478 case DT_UUID:
480 V_VT(v) = VT_BSTR;
481 V_BSTR(v) = bstr_from_xmlChar(str);
483 if(!V_BSTR(v))
484 return E_OUTOFMEMORY;
485 handled = TRUE;
487 break;
488 case DT_DATE:
489 case DT_DATE_TZ:
490 case DT_DATETIME:
491 case DT_DATETIME_TZ:
492 case DT_TIME:
493 case DT_TIME_TZ:
495 WCHAR *p, *e;
496 SYSTEMTIME st;
497 DOUBLE date = 0.0;
499 st.wYear = 1899;
500 st.wMonth = 12;
501 st.wDay = 30;
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);
507 if(!V_BSTR(&src))
508 return E_OUTOFMEMORY;
510 p = V_BSTR(&src);
511 e = p + SysStringLen(V_BSTR(&src));
513 if(p+4<e && *(p+4)=='-') /* parse date (yyyy-mm-dd) */
515 st.wYear = atoiW(p);
516 st.wMonth = atoiW(p+5);
517 st.wDay = atoiW(p+8);
518 p += 10;
520 if(*p == 'T') p++;
523 if(p+2<e && *(p+2)==':') /* parse time (hh:mm:ss.?) */
525 st.wHour = atoiW(p);
526 st.wMinute = atoiW(p+3);
527 st.wSecond = atoiW(p+6);
528 p += 8;
530 if(*p == '.')
532 p++;
533 while(isdigitW(*p)) p++;
537 SystemTimeToVariantTime(&st, &date);
538 V_VT(v) = VT_DATE;
539 V_DATE(v) = 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;
546 VariantClear(&src);
547 handled = TRUE;
549 break;
550 case DT_BIN_HEX:
552 SAFEARRAYBOUND sab;
553 int i, len;
555 len = xmlStrlen(str)/2;
556 sab.lLbound = 0;
557 sab.cElements = len;
559 V_VT(v) = (VT_ARRAY|VT_UI1);
560 V_ARRAY(v) = SafeArrayCreate(VT_UI1, 1, &sab);
562 if(!V_ARRAY(v))
563 return E_OUTOFMEMORY;
565 for(i=0; i<len; i++)
566 ((BYTE*)V_ARRAY(v)->pvData)[i] = (hex_to_byte(str[2*i])<<4)
567 + hex_to_byte(str[2*i+1]);
568 handled = TRUE;
570 break;
571 case DT_BIN_BASE64:
573 SAFEARRAYBOUND sab;
574 xmlChar *c1, *c2;
575 int i, len;
577 /* remove all formatting chars */
578 c1 = c2 = str;
579 len = 0;
580 while (*c2)
582 if ( *c2 == ' ' || *c2 == '\t' ||
583 *c2 == '\n' || *c2 == '\r' )
585 c2++;
586 continue;
588 *c1++ = *c2++;
589 len++;
592 /* skip padding */
593 if(str[len-2] == '=') i = 2;
594 else if(str[len-1] == '=') i = 1;
595 else i = 0;
597 sab.lLbound = 0;
598 sab.cElements = len/4*3-i;
600 V_VT(v) = (VT_ARRAY|VT_UI1);
601 V_ARRAY(v) = SafeArrayCreate(VT_UI1, 1, &sab);
603 if(!V_ARRAY(v))
604 return E_OUTOFMEMORY;
606 for(i=0; i<len/4; i++)
608 ((BYTE*)V_ARRAY(v)->pvData)[3*i] = (base64_to_byte(str[4*i])<<2)
609 + (base64_to_byte(str[4*i+1])>>4);
610 if(3*i+1 < sab.cElements)
611 ((BYTE*)V_ARRAY(v)->pvData)[3*i+1] = (base64_to_byte(str[4*i+1])<<4)
612 + (base64_to_byte(str[4*i+2])>>2);
613 if(3*i+2 < sab.cElements)
614 ((BYTE*)V_ARRAY(v)->pvData)[3*i+2] = (base64_to_byte(str[4*i+2])<<6)
615 + base64_to_byte(str[4*i+3]);
617 handled = TRUE;
619 break;
620 case DT_BOOLEAN:
621 V_VT(v) = VT_BOOL;
622 break;
623 case DT_FIXED_14_4:
624 V_VT(v) = VT_CY;
625 break;
626 case DT_I1:
627 V_VT(v) = VT_I1;
628 break;
629 case DT_I2:
630 V_VT(v) = VT_I2;
631 break;
632 case DT_I4:
633 case DT_INT:
634 V_VT(v) = VT_I4;
635 break;
636 case DT_I8:
637 V_VT(v) = VT_I8;
638 break;
639 case DT_R4:
640 V_VT(v) = VT_R4;
641 break;
642 case DT_FLOAT:
643 case DT_R8:
644 V_VT(v) = VT_R8;
645 break;
646 case DT_UI1:
647 V_VT(v) = VT_UI1;
648 break;
649 case DT_UI2:
650 V_VT(v) = VT_UI2;
651 break;
652 case DT_UI4:
653 V_VT(v) = VT_UI4;
654 break;
655 case DT_UI8:
656 V_VT(v) = VT_UI8;
657 break;
658 case DT_CHAR:
659 case DT_ENTITY:
660 case DT_ENTITIES:
661 case DT_ENUMERATION:
662 case DT_ID:
663 case DT_IDREF:
664 case DT_IDREFS:
665 case DT_NOTATION:
666 FIXME("need to handle dt:%s\n", debugstr_dt(dt));
667 V_VT(v) = VT_BSTR;
668 V_BSTR(v) = bstr_from_xmlChar(str);
669 if (!V_BSTR(v))
670 return E_OUTOFMEMORY;
671 handled = TRUE;
672 break;
675 if (!handled)
677 V_VT(&src) = VT_BSTR;
678 V_BSTR(&src) = bstr_from_xmlChar(str);
680 if(!V_BSTR(&src))
681 return E_OUTOFMEMORY;
683 hr = VariantChangeTypeEx(v, &src,
684 MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT),0, V_VT(v));
685 VariantClear(&src);
687 return hr;
690 static XDR_DT element_get_dt(xmlNodePtr node)
692 XDR_DT dt = DT_INVALID;
694 TRACE("(%p)\n", node);
695 if(node->type != XML_ELEMENT_NODE)
697 FIXME("invalid element node\n");
698 return dt;
701 if (node->ns && xmlStrEqual(node->ns->href, DT_nsURI))
703 dt = str_to_dt(node->name, -1);
705 else
707 xmlChar* pVal = xmlGetNsProp(node, BAD_CAST "dt", DT_nsURI);
708 if (pVal)
710 dt = str_to_dt(pVal, -1);
711 xmlFree(pVal);
713 else if (node->doc)
715 IXMLDOMDocument3* doc = (IXMLDOMDocument3*)create_domdoc((xmlNodePtr)node->doc);
716 if (doc)
718 VARIANT v;
719 VariantInit(&v);
721 if (IXMLDOMDocument3_get_schemas(doc, &v) == S_OK &&
722 V_VT(&v) == VT_DISPATCH)
724 dt = SchemaCache_get_node_dt((IXMLDOMSchemaCollection2*)V_DISPATCH(&v), node);
726 VariantClear(&v);
727 IXMLDOMDocument3_Release(doc);
732 TRACE("=> dt:%s\n", debugstr_dt(dt));
733 return dt;
736 static HRESULT WINAPI domelem_get_nodeTypedValue(
737 IXMLDOMElement *iface,
738 VARIANT* v)
740 domelem *This = impl_from_IXMLDOMElement( iface );
741 XDR_DT dt;
742 xmlChar* content;
743 HRESULT hr;
745 TRACE("(%p)->(%p)\n", This, v);
747 if(!v) return E_INVALIDARG;
749 V_VT(v) = VT_NULL;
751 dt = element_get_dt(get_element(This));
752 content = xmlNodeGetContent(get_element(This));
753 hr = variant_from_dt(dt, content, v);
754 xmlFree(content);
756 return hr;
759 static HRESULT WINAPI domelem_put_nodeTypedValue(
760 IXMLDOMElement *iface,
761 VARIANT value)
763 domelem *This = impl_from_IXMLDOMElement( iface );
764 XDR_DT dt;
765 HRESULT hr;
767 TRACE("(%p)->(%s)\n", This, debugstr_variant(&value));
769 dt = element_get_dt(get_element(This));
770 /* for untyped node coerce to BSTR and set */
771 if (dt == DT_INVALID)
773 if (V_VT(&value) != VT_BSTR)
775 VARIANT content;
776 VariantInit(&content);
777 hr = VariantChangeType(&content, &value, 0, VT_BSTR);
778 if (hr == S_OK)
780 hr = node_set_content(&This->node, V_BSTR(&content));
781 VariantClear(&content);
784 else
785 hr = node_set_content(&This->node, V_BSTR(&value));
787 else
789 FIXME("not implemented for dt:%s\n", debugstr_dt(dt));
790 return E_NOTIMPL;
793 return hr;
796 static HRESULT WINAPI domelem_get_dataType(
797 IXMLDOMElement *iface,
798 VARIANT* typename)
800 domelem *This = impl_from_IXMLDOMElement( iface );
801 XDR_DT dt;
803 TRACE("(%p)->(%p)\n", This, typename);
805 if (!typename)
806 return E_INVALIDARG;
808 dt = element_get_dt(get_element(This));
809 switch (dt)
811 case DT_BIN_BASE64:
812 case DT_BIN_HEX:
813 case DT_BOOLEAN:
814 case DT_CHAR:
815 case DT_DATE:
816 case DT_DATE_TZ:
817 case DT_DATETIME:
818 case DT_DATETIME_TZ:
819 case DT_FIXED_14_4:
820 case DT_FLOAT:
821 case DT_I1:
822 case DT_I2:
823 case DT_I4:
824 case DT_I8:
825 case DT_INT:
826 case DT_NUMBER:
827 case DT_R4:
828 case DT_R8:
829 case DT_TIME:
830 case DT_TIME_TZ:
831 case DT_UI1:
832 case DT_UI2:
833 case DT_UI4:
834 case DT_UI8:
835 case DT_URI:
836 case DT_UUID:
837 V_VT(typename) = VT_BSTR;
838 V_BSTR(typename) = SysAllocString(dt_to_bstr(dt));
840 if (!V_BSTR(typename))
841 return E_OUTOFMEMORY;
842 break;
843 default:
844 /* Other types (DTD equivalents) do not return anything here,
845 * but the pointer part of the VARIANT is set to NULL */
846 V_VT(typename) = VT_NULL;
847 V_BSTR(typename) = NULL;
848 break;
850 return (V_VT(typename) != VT_NULL) ? S_OK : S_FALSE;
853 static HRESULT WINAPI domelem_put_dataType(
854 IXMLDOMElement *iface,
855 BSTR dtName)
857 domelem *This = impl_from_IXMLDOMElement( iface );
858 HRESULT hr = E_FAIL;
859 xmlChar *str;
860 XDR_DT dt;
862 TRACE("(%p)->(%s)\n", This, debugstr_w(dtName));
864 if(dtName == NULL)
865 return E_INVALIDARG;
867 dt = bstr_to_dt(dtName, -1);
869 /* An example of this is. The Text in the node needs to be a 0 or 1 for a boolean type.
870 This applies to changing types (string->bool) or setting a new one
872 str = xmlNodeGetContent(get_element(This));
873 hr = dt_validate(dt, str);
874 xmlFree(str);
876 /* Check all supported types. */
877 if (hr == S_OK)
879 switch (dt)
881 case DT_BIN_BASE64:
882 case DT_BIN_HEX:
883 case DT_BOOLEAN:
884 case DT_CHAR:
885 case DT_DATE:
886 case DT_DATE_TZ:
887 case DT_DATETIME:
888 case DT_DATETIME_TZ:
889 case DT_FIXED_14_4:
890 case DT_FLOAT:
891 case DT_I1:
892 case DT_I2:
893 case DT_I4:
894 case DT_I8:
895 case DT_INT:
896 case DT_NMTOKEN:
897 case DT_NMTOKENS:
898 case DT_NUMBER:
899 case DT_R4:
900 case DT_R8:
901 case DT_STRING:
902 case DT_TIME:
903 case DT_TIME_TZ:
904 case DT_UI1:
905 case DT_UI2:
906 case DT_UI4:
907 case DT_UI8:
908 case DT_URI:
909 case DT_UUID:
911 xmlAttrPtr attr = xmlHasNsProp(get_element(This), DT_prefix, DT_nsURI);
912 if (attr)
914 attr = xmlSetNsProp(get_element(This), attr->ns, DT_prefix, dt_to_str(dt));
915 hr = S_OK;
917 else
919 xmlNsPtr ns = xmlNewNs(get_element(This), DT_nsURI, DT_prefix);
920 if (ns)
922 attr = xmlNewNsProp(get_element(This), ns, DT_prefix, dt_to_str(dt));
923 if (attr)
925 xmlAddChild(get_element(This), (xmlNodePtr)attr);
926 hr = S_OK;
928 else
929 ERR("Failed to create Attribute\n");
931 else
932 ERR("Failed to create Namespace\n");
935 break;
936 default:
937 FIXME("need to handle dt:%s\n", debugstr_dt(dt));
938 break;
942 return hr;
945 static HRESULT WINAPI domelem_get_xml(
946 IXMLDOMElement *iface,
947 BSTR* p)
949 domelem *This = impl_from_IXMLDOMElement( iface );
951 TRACE("(%p)->(%p)\n", This, p);
953 return node_get_xml(&This->node, TRUE, FALSE, p);
956 static HRESULT WINAPI domelem_transformNode(
957 IXMLDOMElement *iface,
958 IXMLDOMNode *node, BSTR *p)
960 domelem *This = impl_from_IXMLDOMElement( iface );
961 TRACE("(%p)->(%p %p)\n", This, node, p);
962 return node_transform_node(&This->node, node, p);
965 static HRESULT WINAPI domelem_selectNodes(
966 IXMLDOMElement *iface,
967 BSTR p, IXMLDOMNodeList** outList)
969 domelem *This = impl_from_IXMLDOMElement( iface );
970 TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outList);
971 return node_select_nodes(&This->node, p, outList);
974 static HRESULT WINAPI domelem_selectSingleNode(
975 IXMLDOMElement *iface,
976 BSTR p, IXMLDOMNode** outNode)
978 domelem *This = impl_from_IXMLDOMElement( iface );
979 TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outNode);
980 return node_select_singlenode(&This->node, p, outNode);
983 static HRESULT WINAPI domelem_get_parsed(
984 IXMLDOMElement *iface,
985 VARIANT_BOOL* isParsed)
987 domelem *This = impl_from_IXMLDOMElement( iface );
988 FIXME("(%p)->(%p) stub!\n", This, isParsed);
989 *isParsed = VARIANT_TRUE;
990 return S_OK;
993 static HRESULT WINAPI domelem_get_namespaceURI(
994 IXMLDOMElement *iface,
995 BSTR* p)
997 domelem *This = impl_from_IXMLDOMElement( iface );
998 TRACE("(%p)->(%p)\n", This, p);
999 return node_get_namespaceURI(&This->node, p);
1002 static HRESULT WINAPI domelem_get_prefix(
1003 IXMLDOMElement *iface,
1004 BSTR* prefix)
1006 domelem *This = impl_from_IXMLDOMElement( iface );
1007 TRACE("(%p)->(%p)\n", This, prefix);
1008 return node_get_prefix( &This->node, prefix );
1011 static HRESULT WINAPI domelem_get_baseName(
1012 IXMLDOMElement *iface,
1013 BSTR* name)
1015 domelem *This = impl_from_IXMLDOMElement( iface );
1016 TRACE("(%p)->(%p)\n", This, name);
1017 return node_get_base_name( &This->node, name );
1020 static HRESULT WINAPI domelem_transformNodeToObject(
1021 IXMLDOMElement *iface,
1022 IXMLDOMNode* domNode, VARIANT var1)
1024 domelem *This = impl_from_IXMLDOMElement( iface );
1025 FIXME("(%p)->(%p %s)\n", This, domNode, debugstr_variant(&var1));
1026 return E_NOTIMPL;
1029 static HRESULT WINAPI domelem_get_tagName(
1030 IXMLDOMElement *iface,
1031 BSTR* p)
1033 domelem *This = impl_from_IXMLDOMElement( iface );
1034 xmlNodePtr element;
1035 const xmlChar *prefix;
1036 xmlChar *qname;
1038 TRACE("(%p)->(%p)\n", This, p );
1040 if (!p) return E_INVALIDARG;
1042 element = get_element( This );
1043 if ( !element )
1044 return E_FAIL;
1046 prefix = element->ns ? element->ns->prefix : NULL;
1047 qname = xmlBuildQName(element->name, prefix, NULL, 0);
1049 *p = bstr_from_xmlChar(qname);
1050 if (qname != element->name) xmlFree(qname);
1052 return *p ? S_OK : E_OUTOFMEMORY;
1055 static HRESULT WINAPI domelem_getAttribute(
1056 IXMLDOMElement *iface,
1057 BSTR name, VARIANT* value)
1059 domelem *This = impl_from_IXMLDOMElement( iface );
1060 xmlNodePtr element;
1061 xmlChar *xml_name, *xml_value = NULL;
1062 HRESULT hr = S_FALSE;
1064 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), value);
1066 if(!value || !name)
1067 return E_INVALIDARG;
1069 element = get_element( This );
1070 if ( !element )
1071 return E_FAIL;
1073 V_BSTR(value) = NULL;
1074 V_VT(value) = VT_NULL;
1076 xml_name = xmlchar_from_wchar( name );
1078 if(!xmlValidateNameValue(xml_name))
1079 hr = E_FAIL;
1080 else
1081 xml_value = xmlGetNsProp(element, xml_name, NULL);
1083 heap_free(xml_name);
1084 if(xml_value)
1086 V_VT(value) = VT_BSTR;
1087 V_BSTR(value) = bstr_from_xmlChar( xml_value );
1088 xmlFree(xml_value);
1089 hr = S_OK;
1092 return hr;
1095 static HRESULT WINAPI domelem_setAttribute(
1096 IXMLDOMElement *iface,
1097 BSTR name, VARIANT value)
1099 domelem *This = impl_from_IXMLDOMElement( iface );
1100 xmlChar *xml_name, *xml_value, *local, *prefix;
1101 xmlNodePtr element;
1102 HRESULT hr;
1103 VARIANT var;
1105 TRACE("(%p)->(%s %s)\n", This, debugstr_w(name), debugstr_variant(&value));
1107 element = get_element( This );
1108 if ( !element )
1109 return E_FAIL;
1111 VariantInit(&var);
1112 hr = VariantChangeType(&var, &value, 0, VT_BSTR);
1113 if(hr != S_OK)
1115 FIXME("VariantChangeType failed\n");
1116 return hr;
1119 xml_name = xmlchar_from_wchar( name );
1120 xml_value = xmlchar_from_wchar( V_BSTR(&var) );
1122 if ((local = xmlSplitQName2(xml_name, &prefix)))
1124 static const xmlChar* xmlnsA = (const xmlChar*)"xmlns";
1125 xmlNsPtr ns = NULL;
1127 /* it's not allowed to modify existing namespace definition */
1128 if (xmlStrEqual(prefix, xmlnsA))
1129 ns = xmlSearchNs(element->doc, element, local);
1131 xmlFree(prefix);
1132 xmlFree(local);
1134 if (ns)
1135 return xmlStrEqual(ns->href, xml_value) ? S_OK : E_INVALIDARG;
1138 if (!xmlSetNsProp(element, NULL, xml_name, xml_value))
1139 hr = E_FAIL;
1141 heap_free(xml_value);
1142 heap_free(xml_name);
1143 VariantClear(&var);
1145 return hr;
1148 static HRESULT WINAPI domelem_removeAttribute(
1149 IXMLDOMElement *iface,
1150 BSTR p)
1152 domelem *This = impl_from_IXMLDOMElement( iface );
1153 IXMLDOMNamedNodeMap *attr;
1154 HRESULT hr;
1156 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
1158 hr = IXMLDOMElement_get_attributes(iface, &attr);
1159 if (hr != S_OK) return hr;
1161 hr = IXMLDOMNamedNodeMap_removeNamedItem(attr, p, NULL);
1162 IXMLDOMNamedNodeMap_Release(attr);
1164 return hr;
1167 static HRESULT WINAPI domelem_getAttributeNode(
1168 IXMLDOMElement *iface,
1169 BSTR p, IXMLDOMAttribute** attributeNode )
1171 domelem *This = impl_from_IXMLDOMElement( iface );
1172 xmlChar *xml_name;
1173 xmlNodePtr element;
1174 xmlAttrPtr attr;
1175 IUnknown *unk;
1176 HRESULT hr = S_FALSE;
1178 TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), attributeNode);
1180 if(!attributeNode)
1181 return E_FAIL;
1183 *attributeNode = NULL;
1185 element = get_element( This );
1186 if ( !element )
1187 return E_FAIL;
1189 xml_name = xmlchar_from_wchar(p);
1191 if(!xmlValidateNameValue(xml_name))
1193 heap_free(xml_name);
1194 return E_FAIL;
1197 attr = xmlHasProp(element, xml_name);
1198 if(attr) {
1199 unk = create_attribute((xmlNodePtr)attr);
1200 hr = IUnknown_QueryInterface(unk, &IID_IXMLDOMAttribute, (void**)attributeNode);
1201 IUnknown_Release(unk);
1204 heap_free(xml_name);
1206 return hr;
1209 static HRESULT WINAPI domelem_setAttributeNode(
1210 IXMLDOMElement *iface,
1211 IXMLDOMAttribute* attribute,
1212 IXMLDOMAttribute** old)
1214 domelem *This = impl_from_IXMLDOMElement( iface );
1215 static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
1216 xmlChar *name, *value;
1217 BSTR nameW, prefix;
1218 xmlnode *attr_node;
1219 xmlAttrPtr attr;
1220 VARIANT valueW;
1221 HRESULT hr;
1223 FIXME("(%p)->(%p %p): semi-stub\n", This, attribute, old);
1225 if (!attribute) return E_INVALIDARG;
1227 attr_node = get_node_obj((IXMLDOMNode*)attribute);
1228 if (!attr_node) return E_FAIL;
1230 if (attr_node->parent)
1232 WARN("attempt to add already used attribute\n");
1233 return E_FAIL;
1236 hr = IXMLDOMAttribute_get_nodeName(attribute, &nameW);
1237 if (hr != S_OK) return hr;
1239 /* adding xmlns attribute doesn't change a tree or existing namespace definition */
1240 if (!strcmpW(nameW, xmlnsW))
1242 SysFreeString(nameW);
1243 return DISP_E_UNKNOWNNAME;
1246 hr = IXMLDOMAttribute_get_nodeValue(attribute, &valueW);
1247 if (hr != S_OK)
1249 SysFreeString(nameW);
1250 return hr;
1253 if (old) *old = NULL;
1255 TRACE("attribute: %s=%s\n", debugstr_w(nameW), debugstr_w(V_BSTR(&valueW)));
1257 hr = IXMLDOMAttribute_get_prefix(attribute, &prefix);
1258 if (hr == S_OK)
1260 FIXME("namespaces not supported: %s\n", debugstr_w(prefix));
1261 SysFreeString(prefix);
1264 name = xmlchar_from_wchar(nameW);
1265 value = xmlchar_from_wchar(V_BSTR(&valueW));
1267 if (!name || !value)
1269 SysFreeString(nameW);
1270 VariantClear(&valueW);
1271 heap_free(name);
1272 heap_free(value);
1273 return E_OUTOFMEMORY;
1276 attr = xmlSetNsProp(get_element(This), NULL, name, value);
1277 if (attr)
1278 attr_node->parent = (IXMLDOMNode*)iface;
1280 SysFreeString(nameW);
1281 VariantClear(&valueW);
1282 heap_free(name);
1283 heap_free(value);
1285 return attr ? S_OK : E_FAIL;
1288 static HRESULT WINAPI domelem_removeAttributeNode(
1289 IXMLDOMElement *iface,
1290 IXMLDOMAttribute* domAttribute,
1291 IXMLDOMAttribute** attributeNode)
1293 domelem *This = impl_from_IXMLDOMElement( iface );
1294 FIXME("(%p)->(%p %p)\n", This, domAttribute, attributeNode);
1295 return E_NOTIMPL;
1298 static HRESULT WINAPI domelem_getElementsByTagName(
1299 IXMLDOMElement *iface,
1300 BSTR tagName, IXMLDOMNodeList** resultList)
1302 domelem *This = impl_from_IXMLDOMElement( iface );
1303 xmlChar *query;
1304 HRESULT hr;
1305 BOOL XPath;
1307 TRACE("(%p)->(%s, %p)\n", This, debugstr_w(tagName), resultList);
1309 if (!tagName || !resultList) return E_INVALIDARG;
1311 XPath = is_xpathmode(get_element(This)->doc);
1312 set_xpathmode(get_element(This)->doc, TRUE);
1313 query = tagName_to_XPath(tagName);
1314 hr = create_selection(get_element(This), query, resultList);
1315 xmlFree(query);
1316 set_xpathmode(get_element(This)->doc, XPath);
1318 return hr;
1321 static HRESULT WINAPI domelem_normalize(
1322 IXMLDOMElement *iface )
1324 domelem *This = impl_from_IXMLDOMElement( iface );
1325 FIXME("%p\n", This);
1326 return E_NOTIMPL;
1329 static const struct IXMLDOMElementVtbl domelem_vtbl =
1331 domelem_QueryInterface,
1332 domelem_AddRef,
1333 domelem_Release,
1334 domelem_GetTypeInfoCount,
1335 domelem_GetTypeInfo,
1336 domelem_GetIDsOfNames,
1337 domelem_Invoke,
1338 domelem_get_nodeName,
1339 domelem_get_nodeValue,
1340 domelem_put_nodeValue,
1341 domelem_get_nodeType,
1342 domelem_get_parentNode,
1343 domelem_get_childNodes,
1344 domelem_get_firstChild,
1345 domelem_get_lastChild,
1346 domelem_get_previousSibling,
1347 domelem_get_nextSibling,
1348 domelem_get_attributes,
1349 domelem_insertBefore,
1350 domelem_replaceChild,
1351 domelem_removeChild,
1352 domelem_appendChild,
1353 domelem_hasChildNodes,
1354 domelem_get_ownerDocument,
1355 domelem_cloneNode,
1356 domelem_get_nodeTypeString,
1357 domelem_get_text,
1358 domelem_put_text,
1359 domelem_get_specified,
1360 domelem_get_definition,
1361 domelem_get_nodeTypedValue,
1362 domelem_put_nodeTypedValue,
1363 domelem_get_dataType,
1364 domelem_put_dataType,
1365 domelem_get_xml,
1366 domelem_transformNode,
1367 domelem_selectNodes,
1368 domelem_selectSingleNode,
1369 domelem_get_parsed,
1370 domelem_get_namespaceURI,
1371 domelem_get_prefix,
1372 domelem_get_baseName,
1373 domelem_transformNodeToObject,
1374 domelem_get_tagName,
1375 domelem_getAttribute,
1376 domelem_setAttribute,
1377 domelem_removeAttribute,
1378 domelem_getAttributeNode,
1379 domelem_setAttributeNode,
1380 domelem_removeAttributeNode,
1381 domelem_getElementsByTagName,
1382 domelem_normalize,
1385 static const tid_t domelem_iface_tids[] = {
1386 IXMLDOMElement_tid,
1390 static dispex_static_data_t domelem_dispex = {
1391 NULL,
1392 IXMLDOMElement_tid,
1393 NULL,
1394 domelem_iface_tids
1397 IUnknown* create_element( xmlNodePtr element )
1399 domelem *This;
1401 This = heap_alloc( sizeof *This );
1402 if ( !This )
1403 return NULL;
1405 This->IXMLDOMElement_iface.lpVtbl = &domelem_vtbl;
1406 This->ref = 1;
1408 init_xmlnode(&This->node, element, (IXMLDOMNode*)&This->IXMLDOMElement_iface, &domelem_dispex);
1410 return (IUnknown*)&This->IXMLDOMElement_iface;
1413 #endif