Nikolay Sivov : msxml3: Unlink node first before adding it as a child.

Alexandre Julliard julliard at winehq.org
Mon Mar 14 14:29:34 CDT 2011


Module: wine
Branch: master
Commit: c48b7566bd1296dba3b17e1d30c5e8b29275cd86
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=c48b7566bd1296dba3b17e1d30c5e8b29275cd86

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Sun Mar 13 01:57:36 2011 +0300

msxml3: Unlink node first before adding it as a child.

---

 dlls/msxml3/node.c         |    2 +
 dlls/msxml3/tests/domdoc.c |  156 ++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 146 insertions(+), 12 deletions(-)

diff --git a/dlls/msxml3/node.c b/dlls/msxml3/node.c
index a492759..db3153d 100644
--- a/dlls/msxml3/node.c
+++ b/dlls/msxml3/node.c
@@ -354,6 +354,8 @@ HRESULT node_insert_before(xmlnode *This, IXMLDOMNode *new_child, const VARIANT
         }
         doc = node_obj->node->doc;
         xmldoc_add_ref(This->node->doc);
+        /* xmlAddChild doesn't unlink node from previous parent */
+        xmlUnlinkNode(node_obj->node);
         xmlAddChild(This->node, node_obj->node);
         xmldoc_release(doc);
         node_obj->parent = This->iface;
diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c
index 370c56e..f49b5c9 100644
--- a/dlls/msxml3/tests/domdoc.c
+++ b/dlls/msxml3/tests/domdoc.c
@@ -4,6 +4,7 @@
  * Copyright 2005 Mike McCormack for CodeWeavers
  * Copyright 2007-2008 Alistair Leslie-Hughes
  * Copyright 2010 Adam Martinson for CodeWeavers
+ * Copyright 2010-2011 Nikolay Sivov for CodeWeavers
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -180,6 +181,21 @@ static void _expect_ref(IUnknown* obj, ULONG ref, int line)
     ok_(__FILE__,line)(rc-1 == ref, "expected refcount %d, got %d\n", ref, rc-1);
 }
 
+#define EXPECT_LIST_LEN(list,len) _expect_list_len(list, len, __LINE__)
+static void _expect_list_len(IXMLDOMNodeList *list, LONG len, int line)
+{
+    LONG length;
+    HRESULT hr;
+
+    length = 0;
+    hr = IXMLDOMNodeList_get_length(list, &length);
+    ok_(__FILE__,line)(hr == S_OK, "got 0x%08x\n", hr);
+    ok_(__FILE__,line)(length == len, "got %d, expected %d\n", length, len);
+}
+
+#define EXPECT_HR(hr,hr_exp) \
+    ok(hr == hr_exp, "got 0x%08x, expected 0x%08x\n", hr, hr_exp)
+
 static const WCHAR szEmpty[] = { 0 };
 static const WCHAR szIncomplete[] = {
     '<','?','x','m','l',' ',
@@ -3985,32 +4001,46 @@ static void test_XPath(void)
     VARIANT var;
     VARIANT_BOOL b;
     IXMLDOMDocument2 *doc;
+    IXMLDOMDocument *doc2;
     IXMLDOMNode *rootNode;
     IXMLDOMNode *elem1Node;
     IXMLDOMNode *node;
     IXMLDOMNodeList *list;
+    IXMLDOMElement *elem;
+    IXMLDOMAttribute *attr;
+    HRESULT hr;
+    BSTR str;
 
     doc = create_document(&IID_IXMLDOMDocument2);
     if (!doc) return;
 
-    ole_check(IXMLDOMDocument_loadXML(doc, _bstr_(szExampleXML), &b));
+    ole_check(IXMLDOMDocument2_loadXML(doc, _bstr_(szExampleXML), &b));
     ok(b == VARIANT_TRUE, "failed to load XML string\n");
 
     /* switch to XPath */
     ole_check(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionLanguage"), _variantbstr_("XPath")));
 
     /* some simple queries*/
-    ole_check(IXMLDOMDocument_selectNodes(doc, _bstr_("root"), &list));
-    ole_check(IXMLDOMNodeList_get_item(list, 0, &rootNode));
-    ole_check(IXMLDOMNodeList_reset(list));
+    EXPECT_REF(doc, 1);
+    hr = IXMLDOMDocument2_selectNodes(doc, _bstr_("root"), &list);
+    EXPECT_HR(hr, S_OK);
+    EXPECT_REF(doc, 1);
+    EXPECT_LIST_LEN(list, 1);
+
+    EXPECT_REF(list, 1);
+    hr = IXMLDOMNodeList_get_item(list, 0, &rootNode);
+    EXPECT_HR(hr, S_OK);
+    EXPECT_REF(list, 1);
+    EXPECT_REF(rootNode, 1);
+
+    hr = IXMLDOMNodeList_reset(list);
+    EXPECT_HR(hr, S_OK);
     expect_list_and_release(list, "E2.D1");
-    if (rootNode == NULL)
-        return;
 
-    ole_check(IXMLDOMDocument_selectNodes(doc, _bstr_("root//c"), &list));
+    ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//c"), &list));
     expect_list_and_release(list, "E3.E1.E2.D1 E3.E2.E2.D1");
 
-    ole_check(IXMLDOMDocument_selectNodes(doc, _bstr_("//c[@type]"), &list));
+    ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("//c[@type]"), &list));
     expect_list_and_release(list, "E3.E2.E2.D1");
 
     ole_check(IXMLDOMNode_selectNodes(rootNode, _bstr_("elem"), &list));
@@ -4054,7 +4084,7 @@ static void test_XPath(void)
     expect_list_and_release(list, "");
 
     /* foo undeclared in document node */
-    ole_expect(IXMLDOMDocument_selectNodes(doc, _bstr_("root//foo:c"), &list), E_FAIL);
+    ole_expect(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//foo:c"), &list), E_FAIL);
     /* undeclared in <root> node */
     ole_expect(IXMLDOMNode_selectNodes(rootNode, _bstr_(".//foo:c"), &list), E_FAIL);
     /* undeclared in <elem> node */
@@ -4068,7 +4098,7 @@ static void test_XPath(void)
         _variantbstr_("xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'")));
 
     /* now the namespace can be used */
-    ole_check(IXMLDOMDocument_selectNodes(doc, _bstr_("root//test:c"), &list));
+    ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//test:c"), &list));
     expect_list_and_release(list, "E3.E3.E2.D1 E3.E4.E2.D1");
     ole_check(IXMLDOMNode_selectNodes(rootNode, _bstr_(".//test:c"), &list));
     expect_list_and_release(list, "E3.E3.E2.D1 E3.E4.E2.D1");
@@ -4081,7 +4111,7 @@ static void test_XPath(void)
     ole_expect(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionNamespaces"),
         _variantbstr_("xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29' xmlns:foo=###")), E_FAIL);
 
-    ole_expect(IXMLDOMDocument_selectNodes(doc, _bstr_("root//foo:c"), &list), E_FAIL);
+    ole_expect(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//foo:c"), &list), E_FAIL);
 
     VariantInit(&var);
     ole_check(IXMLDOMDocument2_getProperty(doc, _bstr_("SelectionNamespaces"), &var));
@@ -4096,7 +4126,109 @@ static void test_XPath(void)
 
     IXMLDOMNode_Release(rootNode);
     IXMLDOMNode_Release(elem1Node);
-    IXMLDOMDocument_Release(doc);
+
+    /* alter document with already built list */
+    hr = IXMLDOMDocument2_selectNodes(doc, _bstr_("root"), &list);
+    EXPECT_HR(hr, S_OK);
+    EXPECT_LIST_LEN(list, 1);
+
+    hr = IXMLDOMDocument2_get_lastChild(doc, &rootNode);
+    EXPECT_HR(hr, S_OK);
+    EXPECT_REF(rootNode, 1);
+    EXPECT_REF(doc, 1);
+
+    hr = IXMLDOMDocument2_removeChild(doc, rootNode, NULL);
+    EXPECT_HR(hr, S_OK);
+    IXMLDOMNode_Release(rootNode);
+
+    EXPECT_LIST_LEN(list, 1);
+
+    hr = IXMLDOMNodeList_get_item(list, 0, &rootNode);
+    EXPECT_HR(hr, S_OK);
+    EXPECT_REF(rootNode, 1);
+
+    IXMLDOMNodeList_Release(list);
+
+    hr = IXMLDOMNode_get_nodeName(rootNode, &str);
+    EXPECT_HR(hr, S_OK);
+    ok(!lstrcmpW(str, _bstr_("root")), "got %s\n", wine_dbgstr_w(str));
+    SysFreeString(str);
+    IXMLDOMNode_Release(rootNode);
+
+    /* alter node from list and get it another time */
+    hr = IXMLDOMDocument2_loadXML(doc, _bstr_(szExampleXML), &b);
+    EXPECT_HR(hr, S_OK);
+    ok(b == VARIANT_TRUE, "failed to load XML string\n");
+
+    hr = IXMLDOMDocument2_selectNodes(doc, _bstr_("root"), &list);
+    EXPECT_HR(hr, S_OK);
+    EXPECT_LIST_LEN(list, 1);
+
+    hr = IXMLDOMNodeList_get_item(list, 0, &rootNode);
+    EXPECT_HR(hr, S_OK);
+
+    hr = IXMLDOMNode_QueryInterface(rootNode, &IID_IXMLDOMElement, (void**)&elem);
+    EXPECT_HR(hr, S_OK);
+
+    V_VT(&var) = VT_I2;
+    V_I2(&var) = 1;
+    hr = IXMLDOMElement_setAttribute(elem, _bstr_("attrtest"), var);
+    EXPECT_HR(hr, S_OK);
+    IXMLDOMElement_Release(elem);
+    IXMLDOMNode_Release(rootNode);
+
+    /* now check attribute to be present */
+    hr = IXMLDOMNodeList_get_item(list, 0, &rootNode);
+    EXPECT_HR(hr, S_OK);
+
+    hr = IXMLDOMNode_QueryInterface(rootNode, &IID_IXMLDOMElement, (void**)&elem);
+    EXPECT_HR(hr, S_OK);
+
+    hr = IXMLDOMElement_getAttributeNode(elem, _bstr_("attrtest"), &attr);
+    EXPECT_HR(hr, S_OK);
+    IXMLDOMAttribute_Release(attr);
+
+    IXMLDOMElement_Release(elem);
+    IXMLDOMNode_Release(rootNode);
+
+    /* and now check for attribute in original document */
+    hr = IXMLDOMDocument_get_documentElement(doc, &elem);
+    EXPECT_HR(hr, S_OK);
+
+    hr = IXMLDOMElement_getAttributeNode(elem, _bstr_("attrtest"), &attr);
+    EXPECT_HR(hr, S_OK);
+    IXMLDOMAttribute_Release(attr);
+
+    IXMLDOMElement_Release(elem);
+
+    /* attach node from list to another document */
+    doc2 = create_document(&IID_IXMLDOMDocument);
+
+    hr = IXMLDOMDocument2_loadXML(doc, _bstr_(szExampleXML), &b);
+    EXPECT_HR(hr, S_OK);
+    ok(b == VARIANT_TRUE, "failed to load XML string\n");
+
+    hr = IXMLDOMDocument2_selectNodes(doc, _bstr_("root"), &list);
+    EXPECT_HR(hr, S_OK);
+    EXPECT_LIST_LEN(list, 1);
+
+    hr = IXMLDOMNodeList_get_item(list, 0, &rootNode);
+    EXPECT_HR(hr, S_OK);
+    EXPECT_REF(rootNode, 1);
+
+    hr = IXMLDOMDocument_appendChild(doc2, rootNode, NULL);
+    EXPECT_HR(hr, S_OK);
+    EXPECT_REF(rootNode, 1);
+    EXPECT_REF(doc2, 1);
+    EXPECT_REF(list, 1);
+
+    EXPECT_LIST_LEN(list, 1);
+
+    IXMLDOMNode_Release(rootNode);
+    IXMLDOMNodeList_Release(list);
+    IXMLDOMDocument_Release(doc2);
+
+    IXMLDOMDocument2_Release(doc);
     free_bstrs();
 }
 




More information about the wine-cvs mailing list