diff --git a/dlls/msxml3/node.c b/dlls/msxml3/node.c index 9d43c093157..ba3fc58145e 100644 --- a/dlls/msxml3/node.c +++ b/dlls/msxml3/node.c @@ -39,6 +39,30 @@ WINE_DEFAULT_DEBUG_CHANNEL(msxml); #ifdef HAVE_LIBXML2 +static const WCHAR szBinBase64[] = {'b','i','n','.','b','a','s','e','6','4',0}; +static const WCHAR szString[] = {'s','t','r','i','n','g',0}; +static const WCHAR szNumber[] = {'n','u','m','b','e','r',0}; +static const WCHAR szInt[] = {'I','n','t',0}; +static const WCHAR szFixed[] = {'F','i','x','e','d','.','1','4','.','4',0}; +static const WCHAR szBoolean[] = {'B','o','o','l','e','a','n',0}; +static const WCHAR szDateTime[] = {'d','a','t','e','T','i','m','e',0}; +static const WCHAR szDateTimeTZ[] = {'d','a','t','e','T','i','m','e','.','t','z',0}; +static const WCHAR szDate[] = {'D','a','t','e',0}; +static const WCHAR szTime[] = {'T','i','m','e',0}; +static const WCHAR szTimeTZ[] = {'T','i','m','e','.','t','z',0}; +static const WCHAR szI1[] = {'i','1',0}; +static const WCHAR szByte[] = {'B','y','t','e',0}; +static const WCHAR szI2[] = {'i','2',0}; +static const WCHAR szI4[] = {'i','4',0}; +static const WCHAR szIU1[] = {'u','i','1',0}; +static const WCHAR szIU2[] = {'u','i','2',0}; +static const WCHAR szIU4[] = {'u','i','4',0}; +static const WCHAR szR4[] = {'r','4',0}; +static const WCHAR szR8[] = {'r','8',0}; +static const WCHAR szFloat[] = {'f','l','o','a','t',0}; +static const WCHAR szUUID[] = {'u','u','i','d',0}; +static const WCHAR szBinHex[] = {'b','i','n','.','h','e','x',0}; + static inline xmlnode *impl_from_InternalUnknown( IUnknown *iface ) { return (xmlnode *)((char*)iface - FIELD_OFFSET(xmlnode, lpInternalUnkVtbl)); @@ -859,8 +883,77 @@ static HRESULT WINAPI xmlnode_put_dataType( IXMLDOMNode *iface, BSTR dataTypeName) { - FIXME("\n"); - return E_NOTIMPL; + xmlnode *This = impl_from_IXMLDOMNode( iface ); + HRESULT hr = E_FAIL; + + TRACE("iface %p\n", iface); + + if(dataTypeName == NULL) + return E_INVALIDARG; + + /* An example of this is. The Text in the node needs to be a 0 or 1 for a boolean type. + This applies to changing types (string->bool) or setting a new one + */ + FIXME("Need to Validate the data before allowing a type to be set.\n"); + + /* Check all supported types. */ + if(lstrcmpiW(dataTypeName,szString) == 0 || + lstrcmpiW(dataTypeName,szNumber) == 0 || + lstrcmpiW(dataTypeName,szUUID) == 0 || + lstrcmpiW(dataTypeName,szInt) == 0 || + lstrcmpiW(dataTypeName,szI4) == 0 || + lstrcmpiW(dataTypeName,szFixed) == 0 || + lstrcmpiW(dataTypeName,szBoolean) == 0 || + lstrcmpiW(dataTypeName,szDateTime) == 0 || + lstrcmpiW(dataTypeName,szDateTimeTZ) == 0 || + lstrcmpiW(dataTypeName,szDate) == 0 || + lstrcmpiW(dataTypeName,szTime) == 0 || + lstrcmpiW(dataTypeName,szTimeTZ) == 0 || + lstrcmpiW(dataTypeName,szI1) == 0 || + lstrcmpiW(dataTypeName,szByte) == 0 || + lstrcmpiW(dataTypeName,szI2) == 0 || + lstrcmpiW(dataTypeName,szIU1) == 0 || + lstrcmpiW(dataTypeName,szIU2) == 0 || + lstrcmpiW(dataTypeName,szIU4) == 0 || + lstrcmpiW(dataTypeName,szR4) == 0 || + lstrcmpiW(dataTypeName,szR8) == 0 || + lstrcmpiW(dataTypeName,szFloat) == 0 || + lstrcmpiW(dataTypeName,szBinHex) == 0 || + lstrcmpiW(dataTypeName,szBinBase64) == 0) + { + xmlNsPtr pNS = NULL; + xmlAttrPtr pAttr = NULL; + xmlChar* str = xmlChar_from_wchar((WCHAR*)dataTypeName); + + pAttr = xmlHasNsProp(This->node, (xmlChar*)"dt", + (xmlChar*)"urn:schemas-microsoft-com:datatypes"); + if (pAttr) + { + pAttr = xmlSetNsProp(This->node, pAttr->ns, (xmlChar*)"dt", str); + + hr = S_OK; + } + else + { + pNS = xmlNewNs(This->node, (xmlChar*)"urn:schemas-microsoft-com:datatypes", (xmlChar*)"dt"); + if(pNS) + { + pAttr = xmlNewNsProp(This->node, pNS, (xmlChar*)"dt", str); + if(pAttr) + { + xmlAddChild(This->node, (xmlNodePtr)pAttr); + + hr = S_OK; + } + else + ERR("Failed to create Attribute\n"); + } + else + ERR("Failed to Create Namepsace\n"); + } + } + + return hr; } static HRESULT WINAPI xmlnode_get_xml( diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c index ef1b3d99793..8609e5d7902 100644 --- a/dlls/msxml3/tests/domdoc.c +++ b/dlls/msxml3/tests/domdoc.c @@ -2347,6 +2347,360 @@ static void test_xmlTypes(void) free_bstrs(); } +static void test_nodeTypeTests( void ) +{ + IXMLDOMDocument *doc = NULL; + IXMLDOMElement *pRoot; + IXMLDOMElement *pElement; + HRESULT hr; + + hr = CoCreateInstance( &CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument2, (LPVOID*)&doc ); + if( hr != S_OK ) + return; + + hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing"), &pRoot); + ok(hr == S_OK, "ret %08x\n", hr ); + if(hr == S_OK) + { + hr = IXMLDOMDocument_appendChild(doc, (IXMLDOMNode*)pRoot, NULL); + ok(hr == S_OK, "ret %08x\n", hr ); + if(hr == S_OK) + { + hr = IXMLDOMElement_put_dataType(pRoot, NULL); + ok(hr == E_INVALIDARG, "ret %08x\n", hr ); + + /* Invalid Value */ + hr = IXMLDOMElement_put_dataType(pRoot, _bstr_("abcdefg") ); + ok(hr == E_FAIL, "ret %08x\n", hr ); + + /* NOTE: + * The name passed into put_dataType is case-insensitive. So many of the names + * have been changed to reflect this. + */ + /* Boolean */ + hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing_Boolean"), &pElement); + ok(hr == S_OK, "ret %08x\n", hr ); + if(hr == S_OK) + { + IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pElement, NULL); + + hr = IXMLDOMElement_put_dataType(pElement, _bstr_("Boolean") ); + ok(hr == S_OK, "ret %08x\n", hr ); + + IXMLDOMElement_Release(pElement); + } + + /* String */ + hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing_String"), &pElement); + ok(hr == S_OK, "ret %08x\n", hr ); + if(hr == S_OK) + { + IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pElement, NULL); + + hr = IXMLDOMElement_put_dataType(pElement, _bstr_("String") ); + ok(hr == S_OK, "ret %08x\n", hr ); + + IXMLDOMElement_Release(pElement); + } + + /* Number */ + hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing_Number"), &pElement); + ok(hr == S_OK, "ret %08x\n", hr ); + if(hr == S_OK) + { + IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pElement, NULL); + + hr = IXMLDOMElement_put_dataType(pElement, _bstr_("number") ); + ok(hr == S_OK, "ret %08x\n", hr ); + + IXMLDOMElement_Release(pElement); + } + + /* Int */ + hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing_Int"), &pElement); + ok(hr == S_OK, "ret %08x\n", hr ); + if(hr == S_OK) + { + IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pElement, NULL); + + hr = IXMLDOMElement_put_dataType(pElement, _bstr_("InT") ); + ok(hr == S_OK, "ret %08x\n", hr ); + + IXMLDOMElement_Release(pElement); + } + + /* Fixed */ + hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing_Fixed"), &pElement); + ok(hr == S_OK, "ret %08x\n", hr ); + if(hr == S_OK) + { + IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pElement, NULL); + + hr = IXMLDOMElement_put_dataType(pElement, _bstr_("fixed.14.4") ); + ok(hr == S_OK, "ret %08x\n", hr ); + + IXMLDOMElement_Release(pElement); + } + + /* DateTime */ + hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing_DateTime"), &pElement); + ok(hr == S_OK, "ret %08x\n", hr ); + if(hr == S_OK) + { + IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pElement, NULL); + + hr = IXMLDOMElement_put_dataType(pElement, _bstr_("DateTime") ); + ok(hr == S_OK, "ret %08x\n", hr ); + + IXMLDOMElement_Release(pElement); + } + + /* DateTime TZ */ + hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing_DateTime_tz"), &pElement); + ok(hr == S_OK, "ret %08x\n", hr ); + if(hr == S_OK) + { + IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pElement, NULL); + + hr = IXMLDOMElement_put_dataType(pElement, _bstr_("DateTime.tz") ); + ok(hr == S_OK, "ret %08x\n", hr ); + + IXMLDOMElement_Release(pElement); + } + + /* Date */ + hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing_Date"), &pElement); + ok(hr == S_OK, "ret %08x\n", hr ); + if(hr == S_OK) + { + IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pElement, NULL); + + hr = IXMLDOMElement_put_dataType(pElement, _bstr_("Date") ); + ok(hr == S_OK, "ret %08x\n", hr ); + + IXMLDOMElement_Release(pElement); + } + + /* Time */ + hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing_Time"), &pElement); + ok(hr == S_OK, "ret %08x\n", hr ); + if(hr == S_OK) + { + IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pElement, NULL); + + hr = IXMLDOMElement_put_dataType(pElement, _bstr_("Time") ); + ok(hr == S_OK, "ret %08x\n", hr ); + + IXMLDOMElement_Release(pElement); + } + + /* Time.tz */ + hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing_Time_TZ"), &pElement); + ok(hr == S_OK, "ret %08x\n", hr ); + if(hr == S_OK) + { + IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pElement, NULL); + + hr = IXMLDOMElement_put_dataType(pElement, _bstr_("Time.tz") ); + ok(hr == S_OK, "ret %08x\n", hr ); + + IXMLDOMElement_Release(pElement); + } + + /* I1 */ + hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing_I1"), &pElement); + ok(hr == S_OK, "ret %08x\n", hr ); + if(hr == S_OK) + { + IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pElement, NULL); + + hr = IXMLDOMElement_put_dataType(pElement, _bstr_("I1") ); + ok(hr == S_OK, "ret %08x\n", hr ); + + IXMLDOMElement_Release(pElement); + } + + /* Byte */ + hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing_byte"), &pElement); + ok(hr == S_OK, "ret %08x\n", hr ); + if(hr == S_OK) + { + IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pElement, NULL); + + hr = IXMLDOMElement_put_dataType(pElement, _bstr_("byte") ); + ok(hr == S_OK, "ret %08x\n", hr ); + + IXMLDOMElement_Release(pElement); + } + + /* I2 */ + hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing_I2"), &pElement); + ok(hr == S_OK, "ret %08x\n", hr ); + if(hr == S_OK) + { + IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pElement, NULL); + + hr = IXMLDOMElement_put_dataType(pElement, _bstr_("I2") ); + ok(hr == S_OK, "ret %08x\n", hr ); + + IXMLDOMElement_Release(pElement); + } + + /* I4 */ + hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing_I4"), &pElement); + ok(hr == S_OK, "ret %08x\n", hr ); + if(hr == S_OK) + { + IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pElement, NULL); + + hr = IXMLDOMElement_put_dataType(pElement, _bstr_("I4") ); + ok(hr == S_OK, "ret %08x\n", hr ); + + IXMLDOMElement_Release(pElement); + } + + /* UI1 */ + hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing_UI1"), &pElement); + ok(hr == S_OK, "ret %08x\n", hr ); + if(hr == S_OK) + { + IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pElement, NULL); + + hr = IXMLDOMElement_put_dataType(pElement, _bstr_("UI1") ); + ok(hr == S_OK, "ret %08x\n", hr ); + + IXMLDOMElement_Release(pElement); + } + + /* UI2 */ + hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing_UI2"), &pElement); + ok(hr == S_OK, "ret %08x\n", hr ); + if(hr == S_OK) + { + IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pElement, NULL); + + hr = IXMLDOMElement_put_dataType(pElement, _bstr_("UI2") ); + ok(hr == S_OK, "ret %08x\n", hr ); + + IXMLDOMElement_Release(pElement); + } + + /* UI4 */ + hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing_UI4"), &pElement); + ok(hr == S_OK, "ret %08x\n", hr ); + if(hr == S_OK) + { + IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pElement, NULL); + + hr = IXMLDOMElement_put_dataType(pElement, _bstr_("UI4") ); + ok(hr == S_OK, "ret %08x\n", hr ); + + IXMLDOMElement_Release(pElement); + } + + /* r4 */ + hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing_r4"), &pElement); + ok(hr == S_OK, "ret %08x\n", hr ); + if(hr == S_OK) + { + IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pElement, NULL); + + hr = IXMLDOMElement_put_dataType(pElement, _bstr_("r4") ); + ok(hr == S_OK, "ret %08x\n", hr ); + + IXMLDOMElement_Release(pElement); + } + + /* r8 */ + hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing_r8"), &pElement); + ok(hr == S_OK, "ret %08x\n", hr ); + if(hr == S_OK) + { + IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pElement, NULL); + + hr = IXMLDOMElement_put_dataType(pElement, _bstr_("r8") ); + ok(hr == S_OK, "ret %08x\n", hr ); + + IXMLDOMElement_Release(pElement); + } + + /* float */ + hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing_float"), &pElement); + ok(hr == S_OK, "ret %08x\n", hr ); + if(hr == S_OK) + { + IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pElement, NULL); + + hr = IXMLDOMElement_put_dataType(pElement, _bstr_("float") ); + ok(hr == S_OK, "ret %08x\n", hr ); + + IXMLDOMElement_Release(pElement); + } + + /* uuid */ + hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing_uuid"), &pElement); + ok(hr == S_OK, "ret %08x\n", hr ); + if(hr == S_OK) + { + IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pElement, NULL); + + hr = IXMLDOMElement_put_dataType(pElement, _bstr_("UuId") ); + ok(hr == S_OK, "ret %08x\n", hr ); + + IXMLDOMElement_Release(pElement); + } + + /* bin.hex */ + hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing_bin_hex"), &pElement); + ok(hr == S_OK, "ret %08x\n", hr ); + if(hr == S_OK) + { + IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pElement, NULL); + + hr = IXMLDOMElement_put_dataType(pElement, _bstr_("bin.hex") ); + ok(hr == S_OK, "ret %08x\n", hr ); + + IXMLDOMElement_Release(pElement); + } + + /* bin.base64 */ + hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing_bin_base64"), &pElement); + ok(hr == S_OK, "ret %08x\n", hr ); + if(hr == S_OK) + { + IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pElement, NULL); + + hr = IXMLDOMElement_put_dataType(pElement, _bstr_("bin.base64") ); + ok(hr == S_OK, "ret %08x\n", hr ); + + IXMLDOMElement_Release(pElement); + } + + /* Check changing types */ + hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing_Change"), &pElement); + ok(hr == S_OK, "ret %08x\n", hr ); + if(hr == S_OK) + { + IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pElement, NULL); + + hr = IXMLDOMElement_put_dataType(pElement, _bstr_("DateTime.tz") ); + ok(hr == S_OK, "ret %08x\n", hr ); + + hr = IXMLDOMElement_put_dataType(pElement, _bstr_("string") ); + ok(hr == S_OK, "ret %08x\n", hr ); + + IXMLDOMElement_Release(pElement); + } + + IXMLDOMElement_Release(pRoot); + } + } + + IXMLDOMDocument_Release(doc); + + free_bstrs(); +} + START_TEST(domdoc) { HRESULT r; @@ -2367,6 +2721,7 @@ START_TEST(domdoc) test_XPath(); test_cloneNode(); test_xmlTypes(); + test_nodeTypeTests(); CoUninitialize(); }