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

This commit is contained in:
Nikolay Sivov 2011-03-13 01:57:36 +03:00 committed by Alexandre Julliard
parent 81f2a237f3
commit c48b7566bd
2 changed files with 147 additions and 13 deletions

View File

@ -354,6 +354,8 @@ HRESULT node_insert_before(xmlnode *This, IXMLDOMNode *new_child, const VARIANT
} }
doc = node_obj->node->doc; doc = node_obj->node->doc;
xmldoc_add_ref(This->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); xmlAddChild(This->node, node_obj->node);
xmldoc_release(doc); xmldoc_release(doc);
node_obj->parent = This->iface; node_obj->parent = This->iface;

View File

@ -4,6 +4,7 @@
* Copyright 2005 Mike McCormack for CodeWeavers * Copyright 2005 Mike McCormack for CodeWeavers
* Copyright 2007-2008 Alistair Leslie-Hughes * Copyright 2007-2008 Alistair Leslie-Hughes
* Copyright 2010 Adam Martinson for CodeWeavers * Copyright 2010 Adam Martinson for CodeWeavers
* Copyright 2010-2011 Nikolay Sivov for CodeWeavers
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * 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); 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 szEmpty[] = { 0 };
static const WCHAR szIncomplete[] = { static const WCHAR szIncomplete[] = {
'<','?','x','m','l',' ', '<','?','x','m','l',' ',
@ -3985,32 +4001,46 @@ static void test_XPath(void)
VARIANT var; VARIANT var;
VARIANT_BOOL b; VARIANT_BOOL b;
IXMLDOMDocument2 *doc; IXMLDOMDocument2 *doc;
IXMLDOMDocument *doc2;
IXMLDOMNode *rootNode; IXMLDOMNode *rootNode;
IXMLDOMNode *elem1Node; IXMLDOMNode *elem1Node;
IXMLDOMNode *node; IXMLDOMNode *node;
IXMLDOMNodeList *list; IXMLDOMNodeList *list;
IXMLDOMElement *elem;
IXMLDOMAttribute *attr;
HRESULT hr;
BSTR str;
doc = create_document(&IID_IXMLDOMDocument2); doc = create_document(&IID_IXMLDOMDocument2);
if (!doc) return; 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"); ok(b == VARIANT_TRUE, "failed to load XML string\n");
/* switch to XPath */ /* switch to XPath */
ole_check(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionLanguage"), _variantbstr_("XPath"))); ole_check(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionLanguage"), _variantbstr_("XPath")));
/* some simple queries*/ /* some simple queries*/
ole_check(IXMLDOMDocument_selectNodes(doc, _bstr_("root"), &list)); EXPECT_REF(doc, 1);
ole_check(IXMLDOMNodeList_get_item(list, 0, &rootNode)); hr = IXMLDOMDocument2_selectNodes(doc, _bstr_("root"), &list);
ole_check(IXMLDOMNodeList_reset(list)); EXPECT_HR(hr, S_OK);
expect_list_and_release(list, "E2.D1"); EXPECT_REF(doc, 1);
if (rootNode == NULL) EXPECT_LIST_LEN(list, 1);
return;
ole_check(IXMLDOMDocument_selectNodes(doc, _bstr_("root//c"), &list)); 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");
ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//c"), &list));
expect_list_and_release(list, "E3.E1.E2.D1 E3.E2.E2.D1"); 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"); expect_list_and_release(list, "E3.E2.E2.D1");
ole_check(IXMLDOMNode_selectNodes(rootNode, _bstr_("elem"), &list)); ole_check(IXMLDOMNode_selectNodes(rootNode, _bstr_("elem"), &list));
@ -4054,7 +4084,7 @@ static void test_XPath(void)
expect_list_and_release(list, ""); expect_list_and_release(list, "");
/* foo undeclared in document node */ /* 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 */ /* undeclared in <root> node */
ole_expect(IXMLDOMNode_selectNodes(rootNode, _bstr_(".//foo:c"), &list), E_FAIL); ole_expect(IXMLDOMNode_selectNodes(rootNode, _bstr_(".//foo:c"), &list), E_FAIL);
/* undeclared in <elem> node */ /* undeclared in <elem> node */
@ -4068,7 +4098,7 @@ static void test_XPath(void)
_variantbstr_("xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'"))); _variantbstr_("xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'")));
/* now the namespace can be used */ /* 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"); expect_list_and_release(list, "E3.E3.E2.D1 E3.E4.E2.D1");
ole_check(IXMLDOMNode_selectNodes(rootNode, _bstr_(".//test:c"), &list)); ole_check(IXMLDOMNode_selectNodes(rootNode, _bstr_(".//test:c"), &list));
expect_list_and_release(list, "E3.E3.E2.D1 E3.E4.E2.D1"); 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"), ole_expect(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionNamespaces"),
_variantbstr_("xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29' xmlns:foo=###")), E_FAIL); _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); VariantInit(&var);
ole_check(IXMLDOMDocument2_getProperty(doc, _bstr_("SelectionNamespaces"), &var)); ole_check(IXMLDOMDocument2_getProperty(doc, _bstr_("SelectionNamespaces"), &var));
@ -4096,7 +4126,109 @@ static void test_XPath(void)
IXMLDOMNode_Release(rootNode); IXMLDOMNode_Release(rootNode);
IXMLDOMNode_Release(elem1Node); 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(); free_bstrs();
} }