msxml: node creation and insertion

Huw D M Davies h.davies1 at physics.ox.ac.uk
Wed Jan 11 09:07:47 CST 2006


	Huw Davies <huw at codeweavers.com>
	Implement createNode, appendChild and insertAfter
-- 
Huw Davies
huw at codeweavers.com
diff --git a/dlls/msxml3/domdoc.c b/dlls/msxml3/domdoc.c
index 7d9ad8a..98962ad 100644
--- a/dlls/msxml3/domdoc.c
+++ b/dlls/msxml3/domdoc.c
@@ -657,6 +657,14 @@ static HRESULT WINAPI domdoc_getElements
     return E_NOTIMPL;
 }
 
+static DOMNodeType get_node_type(VARIANT Type)
+{
+    if(V_VT(&Type) == VT_I4)
+        return V_I4(&Type);
+
+    FIXME("Unsupported variant type %x\n", V_VT(&Type));
+    return 0;
+}
 
 static HRESULT WINAPI domdoc_createNode(
     IXMLDOMDocument *iface,
@@ -665,10 +673,46 @@ static HRESULT WINAPI domdoc_createNode(
     BSTR namespaceURI,
     IXMLDOMNode** node )
 {
-    FIXME("\n");
-    return E_NOTIMPL;
-}
+    domdoc *This = impl_from_IXMLDOMDocument( iface );
+    DOMNodeType node_type;
+    xmlNodePtr xmlnode = NULL;
+    xmlChar *xml_name;
+    xmlDocPtr xmldoc;
+
+    TRACE("(%p)->(type,%s,%s,%p)\n", This, debugstr_w(name), debugstr_w(namespaceURI), node);
+
+    node_type = get_node_type(Type);
+    TRACE("node_type %d\n", node_type);
 
+    xml_name = xmlChar_from_wchar((WCHAR*)name);
+
+    if(!get_doc(This))
+    {
+        xmldoc = xmlNewDoc(NULL);
+        xmldoc->_private = 0;
+        attach_xmlnode(This->node, (xmlNodePtr) xmldoc);
+    }
+
+    switch(node_type)
+    {
+    case NODE_ELEMENT:
+        xmlnode = xmlNewDocNode(get_doc(This), NULL, xml_name, NULL);
+        *node = create_node(xmlnode);
+        TRACE("created %p\n", xmlnode);
+        break;
+
+    default:
+        FIXME("unhandled node type %d\n", node_type);
+        break;
+    }
+
+    HeapFree(GetProcessHeap(), 0, xml_name);
+
+    if(xmlnode && *node)
+        return S_OK;
+
+    return E_FAIL;
+}
 
 static HRESULT WINAPI domdoc_nodeFromID(
     IXMLDOMDocument *iface,
diff --git a/dlls/msxml3/node.c b/dlls/msxml3/node.c
index 704e92e..06f21ea 100644
--- a/dlls/msxml3/node.c
+++ b/dlls/msxml3/node.c
@@ -375,8 +375,54 @@ static HRESULT WINAPI xmlnode_insertBefo
     VARIANT refChild,
     IXMLDOMNode** outNewChild)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    xmlnode *This = impl_from_IXMLDOMNode( iface );
+    xmlNodePtr before_node, new_child_node;
+    IXMLDOMNode *before = NULL, *new;
+    HRESULT hr;
+
+    TRACE("(%p)->(%p,var,%p)\n",This,newChild,outNewChild);
+
+    switch(V_VT(&refChild))
+    {
+    case VT_EMPTY:
+    case VT_NULL:
+        break;
+
+    case VT_UNKNOWN:
+        hr = IUnknown_QueryInterface(V_UNKNOWN(&refChild), &IID_IXMLDOMNode, (LPVOID)&before);
+        if(FAILED(hr)) return hr;
+        break;
+
+    case VT_DISPATCH:
+        hr = IDispatch_QueryInterface(V_DISPATCH(&refChild), &IID_IXMLDOMNode, (LPVOID)&before);
+        if(FAILED(hr)) return hr;
+        break;
+
+    default:
+        FIXME("refChild var type %x\n", V_VT(&refChild));
+        return E_FAIL;
+    }
+
+    IXMLDOMNode_QueryInterface(newChild, &IID_IXMLDOMNode, (LPVOID)&new);
+    new_child_node = impl_from_IXMLDOMNode(new)->node;
+    TRACE("new_child_node %p This->node %p\n", new_child_node, This->node);
+
+    if(before)
+    {
+        before_node = impl_from_IXMLDOMNode(before)->node;
+        xmlAddPrevSibling(before_node, new_child_node);
+        IXMLDOMNode_Release(before);
+    }
+    else
+    {
+        xmlAddChild(This->node, new_child_node);
+    }
+
+    IXMLDOMNode_Release(new);
+    IXMLDOMNode_AddRef(newChild);
+    *outNewChild = newChild;
+    TRACE("ret S_OK\n");
+    return S_OK;
 }
 
 static HRESULT WINAPI xmlnode_replaceChild(
@@ -403,8 +449,12 @@ static HRESULT WINAPI xmlnode_appendChil
     IXMLDOMNode* newChild,
     IXMLDOMNode** outNewChild)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    xmlnode *This = impl_from_IXMLDOMNode( iface );
+    VARIANT var;
+
+    TRACE("(%p)->(%p,%p)\n", This, newChild, outNewChild);
+    VariantInit(&var);
+    return IXMLDOMNode_insertBefore(iface, newChild, var, outNewChild);
 }
 
 static HRESULT WINAPI xmlnode_hasChildNodes(
diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c
index 49c303b..74b96ec 100644
--- a/dlls/msxml3/tests/domdoc.c
+++ b/dlls/msxml3/tests/domdoc.c
@@ -598,6 +598,75 @@ static void test_refs(void)
 
 }
 
+static void test_create(void)
+{
+    HRESULT r;
+    VARIANT var;
+    BSTR str;
+    IXMLDOMDocument *doc;
+    IXMLDOMNode *root, *node, *child;
+    IUnknown *unk;
+    LONG ref;
+
+    r = CoCreateInstance( &CLSID_DOMDocument, NULL, 
+        CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (LPVOID*)&doc );
+    if( r != S_OK )
+        return;
+
+    V_VT(&var) = VT_I4;
+    V_I4(&var) = NODE_ELEMENT;
+    str = SysAllocString( szlc );
+    r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
+    ok( r == S_OK, "returns %08lx\n", r );
+    r = IXMLDOMDocument_appendChild( doc, node, &root );
+    ok( r == S_OK, "returns %08lx\n", r );
+    ok( node == root, "%p %p\n", node, root );
+
+    ref = IXMLDOMNode_AddRef( node );
+    ok(ref == 3, "ref %ld\n", ref);
+    IXMLDOMNode_Release( node );
+
+    ref = IXMLDOMNode_Release( node );
+    ok(ref == 1, "ref %ld\n", ref);
+    SysFreeString( str );
+
+    V_VT(&var) = VT_I4;
+    V_I4(&var) = NODE_ELEMENT;
+    str = SysAllocString( szbs );
+    r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
+    ok( r == S_OK, "returns %08lx\n", r );
+
+    ref = IXMLDOMNode_AddRef( node );
+    ok(ref == 2, "ref = %ld\n", ref);
+    IXMLDOMNode_Release( node );
+
+    r = IXMLDOMNode_QueryInterface( node, &IID_IUnknown, (LPVOID*)&unk );
+    ok( r == S_OK, "returns %08lx\n", r );
+
+    ref = IXMLDOMNode_AddRef( unk );
+    ok(ref == 3, "ref = %ld\n", ref);
+    IXMLDOMNode_Release( unk );
+
+    V_VT(&var) = VT_EMPTY;
+    r = IXMLDOMNode_insertBefore( root, (IXMLDOMNode*)unk, var, &child );
+    ok( r == S_OK, "returns %08lx\n", r );
+    ok( unk == (IUnknown*)child, "%p %p\n", unk, child );
+    IXMLDOMNode_Release( child );
+    IUnknown_Release( unk );
+
+
+    V_VT(&var) = VT_NULL;
+    V_DISPATCH(&var) = (IDispatch*)node;
+    r = IXMLDOMNode_insertBefore( root, node, var, &child );
+    ok( r == S_OK, "returns %08lx\n", r );
+    ok( node == child, "%p %p\n", node, child );
+    IXMLDOMNode_Release( child );
+    IXMLDOMNode_Release( node );
+    IXMLDOMNode_Release( root );
+    IXMLDOMDocument_Release( doc );
+}
+
+
 START_TEST(domdoc)
 {
     HRESULT r;
@@ -608,6 +677,7 @@ START_TEST(domdoc)
     test_domdoc();
     test_domnode();
     test_refs();
+    test_create();
 
     CoUninitialize();
 }



More information about the wine-patches mailing list