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 const struct nodemap_funcs domelem_attr_map;
58 static inline domelem *impl_from_IXMLDOMElement( IXMLDOMElement *iface )
60 return CONTAINING_RECORD(iface, domelem, IXMLDOMElement_iface);
63 static inline xmlNodePtr get_element( const domelem *This )
65 return This->node.node;
68 static HRESULT WINAPI domelem_QueryInterface(
69 IXMLDOMElement *iface,
73 domelem *This = impl_from_IXMLDOMElement( iface );
75 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
77 if ( IsEqualGUID( riid, &IID_IXMLDOMElement ) ||
78 IsEqualGUID( riid, &IID_IXMLDOMNode ) ||
79 IsEqualGUID( riid, &IID_IDispatch ) ||
80 IsEqualGUID( riid, &IID_IUnknown ) )
82 *ppvObject = &This->IXMLDOMElement_iface;
84 else if(node_query_interface(&This->node, riid, ppvObject))
86 return *ppvObject ? S_OK : E_NOINTERFACE;
90 TRACE("interface %s not implemented\n", debugstr_guid(riid));
95 IUnknown_AddRef( (IUnknown*)*ppvObject );
99 static ULONG WINAPI domelem_AddRef(
100 IXMLDOMElement *iface )
102 domelem *This = impl_from_IXMLDOMElement( iface );
103 LONG ref = InterlockedIncrement(&This->ref);
105 TRACE("(%p)->(%d)\n", This, ref);
110 static ULONG WINAPI domelem_Release(
111 IXMLDOMElement *iface )
113 domelem *This = impl_from_IXMLDOMElement( iface );
114 ULONG ref = InterlockedDecrement(&This->ref);
116 TRACE("(%p)->(%d)\n", This, ref);
119 destroy_xmlnode(&This->node);
126 static HRESULT WINAPI domelem_GetTypeInfoCount(
127 IXMLDOMElement *iface,
130 domelem *This = impl_from_IXMLDOMElement( iface );
132 TRACE("(%p)->(%p)\n", This, pctinfo);
139 static HRESULT WINAPI domelem_GetTypeInfo(
140 IXMLDOMElement *iface,
141 UINT iTInfo, LCID lcid,
142 ITypeInfo** ppTInfo )
144 domelem *This = impl_from_IXMLDOMElement( iface );
147 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
149 hr = get_typeinfo(IXMLDOMElement_tid, ppTInfo);
154 static HRESULT WINAPI domelem_GetIDsOfNames(
155 IXMLDOMElement *iface,
156 REFIID riid, LPOLESTR* rgszNames,
157 UINT cNames, LCID lcid, DISPID* rgDispId )
159 domelem *This = impl_from_IXMLDOMElement( iface );
163 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
166 if(!rgszNames || cNames == 0 || !rgDispId)
169 hr = get_typeinfo(IXMLDOMElement_tid, &typeinfo);
172 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
173 ITypeInfo_Release(typeinfo);
179 static HRESULT WINAPI domelem_Invoke(
180 IXMLDOMElement *iface,
181 DISPID dispIdMember, REFIID riid, LCID lcid,
182 WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult,
183 EXCEPINFO* pExcepInfo, UINT* puArgErr )
185 domelem *This = impl_from_IXMLDOMElement( iface );
189 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
190 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
192 hr = get_typeinfo(IXMLDOMElement_tid, &typeinfo);
195 hr = ITypeInfo_Invoke(typeinfo, &This->IXMLDOMElement_iface, dispIdMember, wFlags,
196 pDispParams, pVarResult, pExcepInfo, puArgErr);
197 ITypeInfo_Release(typeinfo);
203 static HRESULT WINAPI domelem_get_nodeName(
204 IXMLDOMElement *iface,
207 domelem *This = impl_from_IXMLDOMElement( iface );
209 TRACE("(%p)->(%p)\n", This, p);
211 return node_get_nodeName(&This->node, p);
214 static HRESULT WINAPI domelem_get_nodeValue(
215 IXMLDOMElement *iface,
218 domelem *This = impl_from_IXMLDOMElement( iface );
220 TRACE("(%p)->(%p)\n", This, value);
225 V_VT(value) = VT_NULL;
226 V_BSTR(value) = NULL; /* tests show that we should do this */
230 static HRESULT WINAPI domelem_put_nodeValue(
231 IXMLDOMElement *iface,
234 domelem *This = impl_from_IXMLDOMElement( iface );
235 TRACE("(%p)->(%s)\n", This, debugstr_variant(&value));
239 static HRESULT WINAPI domelem_get_nodeType(
240 IXMLDOMElement *iface,
241 DOMNodeType* domNodeType )
243 domelem *This = impl_from_IXMLDOMElement( iface );
245 TRACE("(%p)->(%p)\n", This, domNodeType);
247 *domNodeType = NODE_ELEMENT;
251 static HRESULT WINAPI domelem_get_parentNode(
252 IXMLDOMElement *iface,
253 IXMLDOMNode** parent )
255 domelem *This = impl_from_IXMLDOMElement( iface );
257 TRACE("(%p)->(%p)\n", This, parent);
259 return node_get_parent(&This->node, parent);
262 static HRESULT WINAPI domelem_get_childNodes(
263 IXMLDOMElement *iface,
264 IXMLDOMNodeList** outList)
266 domelem *This = impl_from_IXMLDOMElement( iface );
268 TRACE("(%p)->(%p)\n", This, outList);
270 return node_get_child_nodes(&This->node, outList);
273 static HRESULT WINAPI domelem_get_firstChild(
274 IXMLDOMElement *iface,
275 IXMLDOMNode** domNode)
277 domelem *This = impl_from_IXMLDOMElement( iface );
279 TRACE("(%p)->(%p)\n", This, domNode);
281 return node_get_first_child(&This->node, domNode);
284 static HRESULT WINAPI domelem_get_lastChild(
285 IXMLDOMElement *iface,
286 IXMLDOMNode** domNode)
288 domelem *This = impl_from_IXMLDOMElement( iface );
290 TRACE("(%p)->(%p)\n", This, domNode);
292 return node_get_last_child(&This->node, domNode);
295 static HRESULT WINAPI domelem_get_previousSibling(
296 IXMLDOMElement *iface,
297 IXMLDOMNode** domNode)
299 domelem *This = impl_from_IXMLDOMElement( iface );
301 TRACE("(%p)->(%p)\n", This, domNode);
303 return node_get_previous_sibling(&This->node, domNode);
306 static HRESULT WINAPI domelem_get_nextSibling(
307 IXMLDOMElement *iface,
308 IXMLDOMNode** domNode)
310 domelem *This = impl_from_IXMLDOMElement( iface );
312 TRACE("(%p)->(%p)\n", This, domNode);
314 return node_get_next_sibling(&This->node, domNode);
317 static HRESULT WINAPI domelem_get_attributes(
318 IXMLDOMElement *iface,
319 IXMLDOMNamedNodeMap** map)
321 domelem *This = impl_from_IXMLDOMElement( iface );
323 TRACE("(%p)->(%p)\n", This, map);
325 *map = create_nodemap(This->node.node, &domelem_attr_map);
329 static HRESULT WINAPI domelem_insertBefore(
330 IXMLDOMElement *iface,
331 IXMLDOMNode* newNode, VARIANT refChild,
332 IXMLDOMNode** outOldNode)
334 domelem *This = impl_from_IXMLDOMElement( iface );
336 TRACE("(%p)->(%p %s %p)\n", This, newNode, debugstr_variant(&refChild), outOldNode);
338 return node_insert_before(&This->node, newNode, &refChild, outOldNode);
341 static HRESULT WINAPI domelem_replaceChild(
342 IXMLDOMElement *iface,
343 IXMLDOMNode* newNode,
344 IXMLDOMNode* oldNode,
345 IXMLDOMNode** outOldNode)
347 domelem *This = impl_from_IXMLDOMElement( iface );
349 TRACE("(%p)->(%p %p %p)\n", This, newNode, oldNode, outOldNode);
351 return node_replace_child(&This->node, newNode, oldNode, outOldNode);
354 static HRESULT WINAPI domelem_removeChild(
355 IXMLDOMElement *iface,
356 IXMLDOMNode *child, IXMLDOMNode **oldChild)
358 domelem *This = impl_from_IXMLDOMElement( iface );
359 TRACE("(%p)->(%p %p)\n", This, child, oldChild);
360 return node_remove_child(&This->node, child, oldChild);
363 static HRESULT WINAPI domelem_appendChild(
364 IXMLDOMElement *iface,
365 IXMLDOMNode *child, IXMLDOMNode **outChild)
367 domelem *This = impl_from_IXMLDOMElement( iface );
368 TRACE("(%p)->(%p %p)\n", This, child, outChild);
369 return node_append_child(&This->node, child, outChild);
372 static HRESULT WINAPI domelem_hasChildNodes(
373 IXMLDOMElement *iface,
376 domelem *This = impl_from_IXMLDOMElement( iface );
377 TRACE("(%p)->(%p)\n", This, ret);
378 return node_has_childnodes(&This->node, ret);
381 static HRESULT WINAPI domelem_get_ownerDocument(
382 IXMLDOMElement *iface,
383 IXMLDOMDocument **doc)
385 domelem *This = impl_from_IXMLDOMElement( iface );
386 TRACE("(%p)->(%p)\n", This, doc);
387 return node_get_owner_doc(&This->node, doc);
390 static HRESULT WINAPI domelem_cloneNode(
391 IXMLDOMElement *iface,
392 VARIANT_BOOL deep, IXMLDOMNode** outNode)
394 domelem *This = impl_from_IXMLDOMElement( iface );
395 TRACE("(%p)->(%d %p)\n", This, deep, outNode);
396 return node_clone( &This->node, deep, outNode );
399 static HRESULT WINAPI domelem_get_nodeTypeString(
400 IXMLDOMElement *iface,
403 domelem *This = impl_from_IXMLDOMElement( iface );
404 static const WCHAR elementW[] = {'e','l','e','m','e','n','t',0};
406 TRACE("(%p)->(%p)\n", This, p);
408 return return_bstr(elementW, p);
411 static HRESULT WINAPI domelem_get_text(
412 IXMLDOMElement *iface,
415 domelem *This = impl_from_IXMLDOMElement( iface );
416 TRACE("(%p)->(%p)\n", This, p);
417 return node_get_text(&This->node, p);
420 static HRESULT WINAPI domelem_put_text(
421 IXMLDOMElement *iface,
424 domelem *This = impl_from_IXMLDOMElement( iface );
425 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
426 return node_put_text( &This->node, p );
429 static HRESULT WINAPI domelem_get_specified(
430 IXMLDOMElement *iface,
431 VARIANT_BOOL* isSpecified)
433 domelem *This = impl_from_IXMLDOMElement( iface );
434 FIXME("(%p)->(%p) stub!\n", This, isSpecified);
435 *isSpecified = VARIANT_TRUE;
439 static HRESULT WINAPI domelem_get_definition(
440 IXMLDOMElement *iface,
441 IXMLDOMNode** definitionNode)
443 domelem *This = impl_from_IXMLDOMElement( iface );
444 FIXME("(%p)->(%p)\n", This, definitionNode);
448 static inline BYTE hex_to_byte(xmlChar c)
450 if(c <= '9') return c-'0';
451 if(c <= 'F') return c-'A'+10;
455 static inline BYTE base64_to_byte(xmlChar c)
457 if(c == '+') return 62;
458 if(c == '/') return 63;
459 if(c <= '9') return c-'0'+52;
460 if(c <= 'Z') return c-'A';
464 static inline HRESULT variant_from_dt(XDR_DT dt, xmlChar* str, VARIANT* v)
468 BOOL handled = FALSE;
483 V_BSTR(v) = bstr_from_xmlChar(str);
486 return E_OUTOFMEMORY;
504 st.wDayOfWeek = st.wHour = st.wMinute = st.wSecond = st.wMilliseconds = 0;
506 V_VT(&src) = VT_BSTR;
507 V_BSTR(&src) = bstr_from_xmlChar(str);
510 return E_OUTOFMEMORY;
513 e = p + SysStringLen(V_BSTR(&src));
515 if(p+4<e && *(p+4)=='-') /* parse date (yyyy-mm-dd) */
518 st.wMonth = atoiW(p+5);
519 st.wDay = atoiW(p+8);
525 if(p+2<e && *(p+2)==':') /* parse time (hh:mm:ss.?) */
528 st.wMinute = atoiW(p+3);
529 st.wSecond = atoiW(p+6);
535 while(isdigitW(*p)) p++;
539 SystemTimeToVariantTime(&st, &date);
543 if(*p == '+') /* parse timezone offset (+hh:mm) */
544 V_DATE(v) += (DOUBLE)atoiW(p+1)/24 + (DOUBLE)atoiW(p+4)/1440;
545 else if(*p == '-') /* parse timezone offset (-hh:mm) */
546 V_DATE(v) -= (DOUBLE)atoiW(p+1)/24 + (DOUBLE)atoiW(p+4)/1440;
557 len = xmlStrlen(str)/2;
561 V_VT(v) = (VT_ARRAY|VT_UI1);
562 V_ARRAY(v) = SafeArrayCreate(VT_UI1, 1, &sab);
565 return E_OUTOFMEMORY;
568 ((BYTE*)V_ARRAY(v)->pvData)[i] = (hex_to_byte(str[2*i])<<4)
569 + hex_to_byte(str[2*i+1]);
579 /* remove all formatting chars */
584 if ( *c2 == ' ' || *c2 == '\t' ||
585 *c2 == '\n' || *c2 == '\r' )
595 if(str[len-2] == '=') i = 2;
596 else if(str[len-1] == '=') i = 1;
600 sab.cElements = len/4*3-i;
602 V_VT(v) = (VT_ARRAY|VT_UI1);
603 V_ARRAY(v) = SafeArrayCreate(VT_UI1, 1, &sab);
606 return E_OUTOFMEMORY;
608 for(i=0; i<len/4; i++)
610 ((BYTE*)V_ARRAY(v)->pvData)[3*i] = (base64_to_byte(str[4*i])<<2)
611 + (base64_to_byte(str[4*i+1])>>4);
612 if(3*i+1 < sab.cElements)
613 ((BYTE*)V_ARRAY(v)->pvData)[3*i+1] = (base64_to_byte(str[4*i+1])<<4)
614 + (base64_to_byte(str[4*i+2])>>2);
615 if(3*i+2 < sab.cElements)
616 ((BYTE*)V_ARRAY(v)->pvData)[3*i+2] = (base64_to_byte(str[4*i+2])<<6)
617 + base64_to_byte(str[4*i+3]);
668 FIXME("need to handle dt:%s\n", debugstr_dt(dt));
670 V_BSTR(v) = bstr_from_xmlChar(str);
672 return E_OUTOFMEMORY;
679 V_VT(&src) = VT_BSTR;
680 V_BSTR(&src) = bstr_from_xmlChar(str);
683 return E_OUTOFMEMORY;
685 hr = VariantChangeTypeEx(v, &src,
686 MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT),0, V_VT(v));
692 static XDR_DT element_get_dt(xmlNodePtr node)
694 XDR_DT dt = DT_INVALID;
696 TRACE("(%p)\n", node);
697 if(node->type != XML_ELEMENT_NODE)
699 FIXME("invalid element node\n");
703 if (node->ns && xmlStrEqual(node->ns->href, DT_nsURI))
705 dt = str_to_dt(node->name, -1);
709 xmlChar* pVal = xmlGetNsProp(node, BAD_CAST "dt", DT_nsURI);
712 dt = str_to_dt(pVal, -1);
717 IXMLDOMDocument3* doc = (IXMLDOMDocument3*)create_domdoc((xmlNodePtr)node->doc);
723 if (IXMLDOMDocument3_get_schemas(doc, &v) == S_OK &&
724 V_VT(&v) == VT_DISPATCH)
726 dt = SchemaCache_get_node_dt((IXMLDOMSchemaCollection2*)V_DISPATCH(&v), node);
729 IXMLDOMDocument3_Release(doc);
734 TRACE("=> dt:%s\n", debugstr_dt(dt));
738 static HRESULT WINAPI domelem_get_nodeTypedValue(
739 IXMLDOMElement *iface,
742 domelem *This = impl_from_IXMLDOMElement( iface );
747 TRACE("(%p)->(%p)\n", This, v);
749 if(!v) return E_INVALIDARG;
753 dt = element_get_dt(get_element(This));
754 content = xmlNodeGetContent(get_element(This));
755 hr = variant_from_dt(dt, content, v);
761 static HRESULT WINAPI domelem_put_nodeTypedValue(
762 IXMLDOMElement *iface,
765 domelem *This = impl_from_IXMLDOMElement( iface );
769 TRACE("(%p)->(%s)\n", This, debugstr_variant(&value));
771 dt = element_get_dt(get_element(This));
772 /* for untyped node coerce to BSTR and set */
773 if (dt == DT_INVALID)
775 if (V_VT(&value) != VT_BSTR)
778 VariantInit(&content);
779 hr = VariantChangeType(&content, &value, 0, VT_BSTR);
782 hr = node_set_content(&This->node, V_BSTR(&content));
783 VariantClear(&content);
787 hr = node_set_content(&This->node, V_BSTR(&value));
791 FIXME("not implemented for dt:%s\n", debugstr_dt(dt));
798 static HRESULT WINAPI domelem_get_dataType(
799 IXMLDOMElement *iface,
802 domelem *This = impl_from_IXMLDOMElement( iface );
805 TRACE("(%p)->(%p)\n", This, typename);
810 dt = element_get_dt(get_element(This));
839 V_VT(typename) = VT_BSTR;
840 V_BSTR(typename) = SysAllocString(dt_to_bstr(dt));
842 if (!V_BSTR(typename))
843 return E_OUTOFMEMORY;
846 /* Other types (DTD equivalents) do not return anything here,
847 * but the pointer part of the VARIANT is set to NULL */
848 V_VT(typename) = VT_NULL;
849 V_BSTR(typename) = NULL;
852 return (V_VT(typename) != VT_NULL) ? S_OK : S_FALSE;
855 static HRESULT WINAPI domelem_put_dataType(
856 IXMLDOMElement *iface,
859 domelem *This = impl_from_IXMLDOMElement( iface );
864 TRACE("(%p)->(%s)\n", This, debugstr_w(dtName));
869 dt = bstr_to_dt(dtName, -1);
871 /* An example of this is. The Text in the node needs to be a 0 or 1 for a boolean type.
872 This applies to changing types (string->bool) or setting a new one
874 str = xmlNodeGetContent(get_element(This));
875 hr = dt_validate(dt, str);
878 /* Check all supported types. */
913 xmlAttrPtr attr = xmlHasNsProp(get_element(This), DT_prefix, DT_nsURI);
916 attr = xmlSetNsProp(get_element(This), attr->ns, DT_prefix, dt_to_str(dt));
921 xmlNsPtr ns = xmlNewNs(get_element(This), DT_nsURI, DT_prefix);
924 attr = xmlNewNsProp(get_element(This), ns, DT_prefix, dt_to_str(dt));
927 xmlAddChild(get_element(This), (xmlNodePtr)attr);
931 ERR("Failed to create Attribute\n");
934 ERR("Failed to create Namespace\n");
939 FIXME("need to handle dt:%s\n", debugstr_dt(dt));
947 static HRESULT WINAPI domelem_get_xml(
948 IXMLDOMElement *iface,
951 domelem *This = impl_from_IXMLDOMElement( iface );
953 TRACE("(%p)->(%p)\n", This, p);
955 return node_get_xml(&This->node, TRUE, FALSE, p);
958 static HRESULT WINAPI domelem_transformNode(
959 IXMLDOMElement *iface,
960 IXMLDOMNode *node, BSTR *p)
962 domelem *This = impl_from_IXMLDOMElement( iface );
963 TRACE("(%p)->(%p %p)\n", This, node, p);
964 return node_transform_node(&This->node, node, p);
967 static HRESULT WINAPI domelem_selectNodes(
968 IXMLDOMElement *iface,
969 BSTR p, IXMLDOMNodeList** outList)
971 domelem *This = impl_from_IXMLDOMElement( iface );
972 TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outList);
973 return node_select_nodes(&This->node, p, outList);
976 static HRESULT WINAPI domelem_selectSingleNode(
977 IXMLDOMElement *iface,
978 BSTR p, IXMLDOMNode** outNode)
980 domelem *This = impl_from_IXMLDOMElement( iface );
981 TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outNode);
982 return node_select_singlenode(&This->node, p, outNode);
985 static HRESULT WINAPI domelem_get_parsed(
986 IXMLDOMElement *iface,
987 VARIANT_BOOL* isParsed)
989 domelem *This = impl_from_IXMLDOMElement( iface );
990 FIXME("(%p)->(%p) stub!\n", This, isParsed);
991 *isParsed = VARIANT_TRUE;
995 static HRESULT WINAPI domelem_get_namespaceURI(
996 IXMLDOMElement *iface,
999 domelem *This = impl_from_IXMLDOMElement( iface );
1000 TRACE("(%p)->(%p)\n", This, p);
1001 return node_get_namespaceURI(&This->node, p);
1004 static HRESULT WINAPI domelem_get_prefix(
1005 IXMLDOMElement *iface,
1008 domelem *This = impl_from_IXMLDOMElement( iface );
1009 TRACE("(%p)->(%p)\n", This, prefix);
1010 return node_get_prefix( &This->node, prefix );
1013 static HRESULT WINAPI domelem_get_baseName(
1014 IXMLDOMElement *iface,
1017 domelem *This = impl_from_IXMLDOMElement( iface );
1018 TRACE("(%p)->(%p)\n", This, name);
1019 return node_get_base_name( &This->node, name );
1022 static HRESULT WINAPI domelem_transformNodeToObject(
1023 IXMLDOMElement *iface,
1024 IXMLDOMNode* domNode, VARIANT var1)
1026 domelem *This = impl_from_IXMLDOMElement( iface );
1027 FIXME("(%p)->(%p %s)\n", This, domNode, debugstr_variant(&var1));
1031 static HRESULT WINAPI domelem_get_tagName(
1032 IXMLDOMElement *iface,
1035 domelem *This = impl_from_IXMLDOMElement( iface );
1037 const xmlChar *prefix;
1040 TRACE("(%p)->(%p)\n", This, p );
1042 if (!p) return E_INVALIDARG;
1044 element = get_element( This );
1048 prefix = element->ns ? element->ns->prefix : NULL;
1049 qname = xmlBuildQName(element->name, prefix, NULL, 0);
1051 *p = bstr_from_xmlChar(qname);
1052 if (qname != element->name) xmlFree(qname);
1054 return *p ? S_OK : E_OUTOFMEMORY;
1057 static HRESULT WINAPI domelem_getAttribute(
1058 IXMLDOMElement *iface,
1059 BSTR name, VARIANT* value)
1061 domelem *This = impl_from_IXMLDOMElement( iface );
1063 xmlChar *xml_name, *xml_value = NULL;
1064 HRESULT hr = S_FALSE;
1066 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), value);
1069 return E_INVALIDARG;
1071 element = get_element( This );
1075 V_BSTR(value) = NULL;
1076 V_VT(value) = VT_NULL;
1078 xml_name = xmlchar_from_wchar( name );
1080 if(!xmlValidateNameValue(xml_name))
1083 xml_value = xmlGetNsProp(element, xml_name, NULL);
1085 heap_free(xml_name);
1088 V_VT(value) = VT_BSTR;
1089 V_BSTR(value) = bstr_from_xmlChar( xml_value );
1097 static HRESULT WINAPI domelem_setAttribute(
1098 IXMLDOMElement *iface,
1099 BSTR name, VARIANT value)
1101 domelem *This = impl_from_IXMLDOMElement( iface );
1102 xmlChar *xml_name, *xml_value, *local, *prefix;
1107 TRACE("(%p)->(%s %s)\n", This, debugstr_w(name), debugstr_variant(&value));
1109 element = get_element( This );
1114 hr = VariantChangeType(&var, &value, 0, VT_BSTR);
1117 FIXME("VariantChangeType failed\n");
1121 xml_name = xmlchar_from_wchar( name );
1122 xml_value = xmlchar_from_wchar( V_BSTR(&var) );
1124 if ((local = xmlSplitQName2(xml_name, &prefix)))
1126 static const xmlChar* xmlnsA = (const xmlChar*)"xmlns";
1129 /* it's not allowed to modify existing namespace definition */
1130 if (xmlStrEqual(prefix, xmlnsA))
1131 ns = xmlSearchNs(element->doc, element, local);
1137 return xmlStrEqual(ns->href, xml_value) ? S_OK : E_INVALIDARG;
1140 if (!xmlSetNsProp(element, NULL, xml_name, xml_value))
1143 heap_free(xml_value);
1144 heap_free(xml_name);
1150 static HRESULT WINAPI domelem_removeAttribute(
1151 IXMLDOMElement *iface,
1154 domelem *This = impl_from_IXMLDOMElement( iface );
1155 IXMLDOMNamedNodeMap *attr;
1158 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
1160 hr = IXMLDOMElement_get_attributes(iface, &attr);
1161 if (hr != S_OK) return hr;
1163 hr = IXMLDOMNamedNodeMap_removeNamedItem(attr, p, NULL);
1164 IXMLDOMNamedNodeMap_Release(attr);
1169 static HRESULT WINAPI domelem_getAttributeNode(
1170 IXMLDOMElement *iface,
1171 BSTR p, IXMLDOMAttribute** attributeNode )
1173 domelem *This = impl_from_IXMLDOMElement( iface );
1174 xmlChar *local, *prefix, *nameA;
1175 HRESULT hr = S_FALSE;
1179 TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), attributeNode);
1181 element = get_element( This );
1182 if (!element) return E_FAIL;
1184 if (attributeNode) *attributeNode = NULL;
1186 nameA = xmlchar_from_wchar(p);
1187 if (!xmlValidateNameValue(nameA))
1199 *attributeNode = NULL;
1201 local = xmlSplitQName2(nameA, &prefix);
1205 /* try to get namespace for supplied qualified name */
1206 xmlNsPtr ns = xmlSearchNs(element->doc, element, prefix);
1209 attr = xmlHasNsProp(element, local, ns ? ns->href : NULL);
1214 attr = xmlHasProp(element, nameA);
1215 /* attribute has attached namespace and we requested non-qualified
1216 name - it's a failure case */
1217 if (attr && attr->ns) attr = NULL;
1224 IUnknown *unk = create_attribute((xmlNodePtr)attr);
1225 hr = IUnknown_QueryInterface(unk, &IID_IXMLDOMAttribute, (void**)attributeNode);
1226 IUnknown_Release(unk);
1232 static HRESULT WINAPI domelem_setAttributeNode(
1233 IXMLDOMElement *iface,
1234 IXMLDOMAttribute* attribute,
1235 IXMLDOMAttribute** old)
1237 domelem *This = impl_from_IXMLDOMElement( iface );
1238 static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
1239 xmlChar *name, *value;
1246 FIXME("(%p)->(%p %p): semi-stub\n", This, attribute, old);
1248 if (!attribute) return E_INVALIDARG;
1250 attr_node = get_node_obj((IXMLDOMNode*)attribute);
1251 if (!attr_node) return E_FAIL;
1253 if (attr_node->parent)
1255 WARN("attempt to add already used attribute\n");
1259 hr = IXMLDOMAttribute_get_nodeName(attribute, &nameW);
1260 if (hr != S_OK) return hr;
1262 /* adding xmlns attribute doesn't change a tree or existing namespace definition */
1263 if (!strcmpW(nameW, xmlnsW))
1265 SysFreeString(nameW);
1266 return DISP_E_UNKNOWNNAME;
1269 hr = IXMLDOMAttribute_get_nodeValue(attribute, &valueW);
1272 SysFreeString(nameW);
1276 if (old) *old = NULL;
1278 TRACE("attribute: %s=%s\n", debugstr_w(nameW), debugstr_w(V_BSTR(&valueW)));
1280 hr = IXMLDOMAttribute_get_prefix(attribute, &prefix);
1283 FIXME("namespaces not supported: %s\n", debugstr_w(prefix));
1284 SysFreeString(prefix);
1287 name = xmlchar_from_wchar(nameW);
1288 value = xmlchar_from_wchar(V_BSTR(&valueW));
1290 if (!name || !value)
1292 SysFreeString(nameW);
1293 VariantClear(&valueW);
1296 return E_OUTOFMEMORY;
1299 attr = xmlSetNsProp(get_element(This), NULL, name, value);
1301 attr_node->parent = (IXMLDOMNode*)iface;
1303 SysFreeString(nameW);
1304 VariantClear(&valueW);
1308 return attr ? S_OK : E_FAIL;
1311 static HRESULT WINAPI domelem_removeAttributeNode(
1312 IXMLDOMElement *iface,
1313 IXMLDOMAttribute* domAttribute,
1314 IXMLDOMAttribute** attributeNode)
1316 domelem *This = impl_from_IXMLDOMElement( iface );
1317 FIXME("(%p)->(%p %p)\n", This, domAttribute, attributeNode);
1321 static HRESULT WINAPI domelem_getElementsByTagName(
1322 IXMLDOMElement *iface,
1323 BSTR tagName, IXMLDOMNodeList** resultList)
1325 domelem *This = impl_from_IXMLDOMElement( iface );
1330 TRACE("(%p)->(%s, %p)\n", This, debugstr_w(tagName), resultList);
1332 if (!tagName || !resultList) return E_INVALIDARG;
1334 XPath = is_xpathmode(get_element(This)->doc);
1335 set_xpathmode(get_element(This)->doc, TRUE);
1336 query = tagName_to_XPath(tagName);
1337 hr = create_selection(get_element(This), query, resultList);
1339 set_xpathmode(get_element(This)->doc, XPath);
1344 static HRESULT WINAPI domelem_normalize(
1345 IXMLDOMElement *iface )
1347 domelem *This = impl_from_IXMLDOMElement( iface );
1348 FIXME("%p\n", This);
1352 static const struct IXMLDOMElementVtbl domelem_vtbl =
1354 domelem_QueryInterface,
1357 domelem_GetTypeInfoCount,
1358 domelem_GetTypeInfo,
1359 domelem_GetIDsOfNames,
1361 domelem_get_nodeName,
1362 domelem_get_nodeValue,
1363 domelem_put_nodeValue,
1364 domelem_get_nodeType,
1365 domelem_get_parentNode,
1366 domelem_get_childNodes,
1367 domelem_get_firstChild,
1368 domelem_get_lastChild,
1369 domelem_get_previousSibling,
1370 domelem_get_nextSibling,
1371 domelem_get_attributes,
1372 domelem_insertBefore,
1373 domelem_replaceChild,
1374 domelem_removeChild,
1375 domelem_appendChild,
1376 domelem_hasChildNodes,
1377 domelem_get_ownerDocument,
1379 domelem_get_nodeTypeString,
1382 domelem_get_specified,
1383 domelem_get_definition,
1384 domelem_get_nodeTypedValue,
1385 domelem_put_nodeTypedValue,
1386 domelem_get_dataType,
1387 domelem_put_dataType,
1389 domelem_transformNode,
1390 domelem_selectNodes,
1391 domelem_selectSingleNode,
1393 domelem_get_namespaceURI,
1395 domelem_get_baseName,
1396 domelem_transformNodeToObject,
1397 domelem_get_tagName,
1398 domelem_getAttribute,
1399 domelem_setAttribute,
1400 domelem_removeAttribute,
1401 domelem_getAttributeNode,
1402 domelem_setAttributeNode,
1403 domelem_removeAttributeNode,
1404 domelem_getElementsByTagName,
1408 static HRESULT domelem_get_qualified_item(const xmlNodePtr node, BSTR name, BSTR uri,
1415 TRACE("(%p)->(%s %s %p)\n", node, debugstr_w(name), debugstr_w(uri), item);
1417 if (!name || !item) return E_INVALIDARG;
1421 href = xmlchar_from_wchar(uri);
1422 if (!href) return E_OUTOFMEMORY;
1427 nameA = xmlchar_from_wchar(name);
1431 return E_OUTOFMEMORY;
1434 attr = xmlHasNsProp(node, nameA, href);
1445 *item = create_node((xmlNodePtr)attr);
1450 static HRESULT domelem_get_named_item(const xmlNodePtr node, BSTR name, IXMLDOMNode **item)
1452 xmlChar *nameA, *local, *prefix;
1457 TRACE("(%p)->(%s %p)\n", node, debugstr_w(name), item );
1459 nameA = xmlchar_from_wchar(name);
1460 local = xmlSplitQName2(nameA, &prefix);
1464 return domelem_get_qualified_item(node, name, NULL, item);
1466 /* try to get namespace uri for supplied qualified name */
1467 ns = xmlSearchNs(node->doc, node, prefix);
1474 if (item) *item = NULL;
1475 return item ? S_FALSE : E_INVALIDARG;
1478 uriW = bstr_from_xmlChar(ns->href);
1479 localW = bstr_from_xmlChar(local);
1482 TRACE("got qualified node %s, uri=%s\n", debugstr_w(localW), debugstr_w(uriW));
1484 hr = domelem_get_qualified_item(node, localW, uriW, item);
1486 SysFreeString(localW);
1487 SysFreeString(uriW);
1492 static HRESULT domelem_set_named_item(xmlNodePtr node, IXMLDOMNode *newItem, IXMLDOMNode **namedItem)
1497 TRACE("(%p)->(%p %p)\n", node, newItem, namedItem );
1500 return E_INVALIDARG;
1502 if(namedItem) *namedItem = NULL;
1504 /* Must be an Attribute */
1505 ThisNew = get_node_obj( newItem );
1506 if(!ThisNew) return E_FAIL;
1508 if(ThisNew->node->type != XML_ATTRIBUTE_NODE)
1511 if(!ThisNew->node->parent)
1512 if(xmldoc_remove_orphan(ThisNew->node->doc, ThisNew->node) != S_OK)
1513 WARN("%p is not an orphan of %p\n", ThisNew->node, ThisNew->node->doc);
1515 nodeNew = xmlAddChild(node, ThisNew->node);
1518 *namedItem = create_node( nodeNew );
1522 static HRESULT domelem_remove_qualified_item(xmlNodePtr node, BSTR name, BSTR uri, IXMLDOMNode **item)
1524 xmlChar *nameA, *href;
1527 TRACE("(%p)->(%s %s %p)\n", node, debugstr_w(name), debugstr_w(uri), item);
1529 if (!name) return E_INVALIDARG;
1533 href = xmlchar_from_wchar(uri);
1534 if (!href) return E_OUTOFMEMORY;
1539 nameA = xmlchar_from_wchar(name);
1543 return E_OUTOFMEMORY;
1546 attr = xmlHasNsProp(node, nameA, href);
1553 if (item) *item = NULL;
1559 xmlUnlinkNode( (xmlNodePtr) attr );
1560 xmldoc_add_orphan( attr->doc, (xmlNodePtr) attr );
1561 *item = create_node( (xmlNodePtr) attr );
1565 if (xmlRemoveProp(attr) == -1)
1566 ERR("xmlRemoveProp failed\n");
1572 static HRESULT domelem_remove_named_item(xmlNodePtr node, BSTR name, IXMLDOMNode **item)
1574 TRACE("(%p)->(%s %p)\n", node, debugstr_w(name), item);
1575 return domelem_remove_qualified_item(node, name, NULL, item);
1578 static HRESULT domelem_get_item(const xmlNodePtr node, LONG index, IXMLDOMNode **item)
1583 TRACE("(%p)->(%d %p)\n", node, index, item);
1590 curr = node->properties;
1592 for (attrIndex = 0; attrIndex < index; attrIndex++) {
1593 if (curr->next == NULL)
1599 *item = create_node( (xmlNodePtr) curr );
1604 static HRESULT domelem_get_length(const xmlNodePtr node, LONG *length)
1610 TRACE("(%p)->(%p)\n", node, length);
1613 return E_INVALIDARG;
1615 first = node->properties;
1616 if (first == NULL) {
1623 while (curr->next) {
1627 *length = attrCount;
1632 static HRESULT domelem_next_node(const xmlNodePtr node, LONG *iter, IXMLDOMNode **nextNode)
1637 TRACE("(%p)->(%d: %p)\n", node, *iter, nextNode);
1641 curr = node->properties;
1643 for (i = 0; i < *iter; i++) {
1644 if (curr->next == NULL)
1651 *nextNode = create_node((xmlNodePtr)curr);
1656 static const struct nodemap_funcs domelem_attr_map = {
1657 domelem_get_named_item,
1658 domelem_set_named_item,
1659 domelem_remove_named_item,
1662 domelem_get_qualified_item,
1663 domelem_remove_qualified_item,
1667 static const tid_t domelem_iface_tids[] = {
1672 static dispex_static_data_t domelem_dispex = {
1679 IUnknown* create_element( xmlNodePtr element )
1683 This = heap_alloc( sizeof *This );
1687 This->IXMLDOMElement_iface.lpVtbl = &domelem_vtbl;
1690 init_xmlnode(&This->node, element, (IXMLDOMNode*)&This->IXMLDOMElement_iface, &domelem_dispex);
1692 return (IUnknown*)&This->IXMLDOMElement_iface;