Signed-off-by: Daniel Lehman dlehman25@gmail.com --- dlls/msxml3/attribute.c | 9 ++++++++- dlls/msxml3/element.c | 2 +- dlls/msxml3/msxml_private.h | 2 +- dlls/msxml3/node.c | 2 +- 4 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/dlls/msxml3/attribute.c b/dlls/msxml3/attribute.c index 637615b341..8eb2695128 100644 --- a/dlls/msxml3/attribute.c +++ b/dlls/msxml3/attribute.c @@ -50,6 +50,7 @@ typedef struct _domattr xmlnode node; IXMLDOMAttribute IXMLDOMAttribute_iface; LONG ref; + BOOL floating; } domattr;
static const tid_t domattr_se_tids[] = { @@ -116,6 +117,11 @@ static ULONG WINAPI domattr_Release( if ( ref == 0 ) { destroy_xmlnode(&This->node); + if ( This->floating ) + { + xmlFreeNs( This->node.node->ns ); + xmlFreeNode( This->node.node ); + } heap_free( This ); }
@@ -709,7 +715,7 @@ static dispex_static_data_t domattr_dispex = { domattr_iface_tids };
-IUnknown* create_attribute( xmlNodePtr attribute ) +IUnknown* create_attribute( xmlNodePtr attribute, BOOL floating ) { domattr *This;
@@ -719,6 +725,7 @@ IUnknown* create_attribute( xmlNodePtr attribute )
This->IXMLDOMAttribute_iface.lpVtbl = &domattr_vtbl; This->ref = 1; + This->floating = floating;
init_xmlnode(&This->node, attribute, (IXMLDOMNode*)&This->IXMLDOMAttribute_iface, &domattr_dispex);
diff --git a/dlls/msxml3/element.c b/dlls/msxml3/element.c index 6e00aa0116..4faeed400c 100644 --- a/dlls/msxml3/element.c +++ b/dlls/msxml3/element.c @@ -1398,7 +1398,7 @@ static HRESULT WINAPI domelem_getAttributeNode(
if (attr) { - IUnknown *unk = create_attribute((xmlNodePtr)attr); + IUnknown *unk = create_attribute((xmlNodePtr)attr, FALSE); hr = IUnknown_QueryInterface(unk, &IID_IXMLDOMAttribute, (void**)attributeNode); IUnknown_Release(unk); } diff --git a/dlls/msxml3/msxml_private.h b/dlls/msxml3/msxml_private.h index 94ef66b23d..abc6ab3465 100644 --- a/dlls/msxml3/msxml_private.h +++ b/dlls/msxml3/msxml_private.h @@ -252,7 +252,7 @@ extern IUnknown *create_domdoc( xmlNodePtr ) DECLSPEC_HIDDEN; extern IUnknown *create_xmldoc( void ) DECLSPEC_HIDDEN; extern IXMLDOMNode *create_node( xmlNodePtr ) DECLSPEC_HIDDEN; extern IUnknown *create_element( xmlNodePtr ) DECLSPEC_HIDDEN; -extern IUnknown *create_attribute( xmlNodePtr ) DECLSPEC_HIDDEN; +extern IUnknown *create_attribute( xmlNodePtr, BOOL ) DECLSPEC_HIDDEN; extern IUnknown *create_text( xmlNodePtr ) DECLSPEC_HIDDEN; extern IUnknown *create_pi( xmlNodePtr ) DECLSPEC_HIDDEN; extern IUnknown *create_comment( xmlNodePtr ) DECLSPEC_HIDDEN; diff --git a/dlls/msxml3/node.c b/dlls/msxml3/node.c index bcb4181374..fc18935b69 100644 --- a/dlls/msxml3/node.c +++ b/dlls/msxml3/node.c @@ -2271,7 +2271,7 @@ IXMLDOMNode *create_node( xmlNodePtr node ) pUnk = create_element( node ); break; case XML_ATTRIBUTE_NODE: - pUnk = create_attribute( node ); + pUnk = create_attribute( node, FALSE ); break; case XML_TEXT_NODE: pUnk = create_text( node );
Signed-off-by: Daniel Lehman dlehman25@gmail.com --- v3: LPVOID -> void* --- dlls/msxml3/element.c | 68 +++++++++++++++++++++++++++++--------- dlls/msxml3/tests/domdoc.c | 2 +- 2 files changed, 53 insertions(+), 17 deletions(-)
diff --git a/dlls/msxml3/element.c b/dlls/msxml3/element.c index 4faeed400c..0ff26e4fb7 100644 --- a/dlls/msxml3/element.c +++ b/dlls/msxml3/element.c @@ -1754,8 +1754,11 @@ static HRESULT domelem_remove_named_item(xmlNodePtr node, BSTR name, IXMLDOMNode
static HRESULT domelem_get_item(const xmlNodePtr node, LONG index, IXMLDOMNode **item) { + xmlNsPtr ns, xmlns; xmlAttrPtr curr; LONG attrIndex; + IUnknown *unk; + HRESULT hr;
TRACE("(%p)->(%d %p)\n", node, index, item);
@@ -1764,42 +1767,75 @@ static HRESULT domelem_get_item(const xmlNodePtr node, LONG index, IXMLDOMNode * if (index < 0) return S_FALSE;
+ attrIndex = 0; curr = node->properties; - - for (attrIndex = 0; attrIndex < index; attrIndex++) { - if (curr->next == NULL) - return S_FALSE; - else + if (curr) { + for (; attrIndex < index && curr->next != NULL; attrIndex++) curr = curr->next; + + if (attrIndex == index) { + *item = create_node( (xmlNodePtr) curr ); + return S_OK; + } }
- *item = create_node( (xmlNodePtr) curr ); + if (!node->nsDef) + return S_FALSE;
- return S_OK; + attrIndex++; + ns = node->nsDef; + for (; attrIndex < index && ns->next != NULL; attrIndex++) + ns = ns->next; + + if (attrIndex < index) + return S_FALSE; + + xmlns = xmlNewNs(NULL, BAD_CAST "http://www.w3.org/2000/xmlns/", BAD_CAST "xmlns"); + if (!xmlns) + return E_OUTOFMEMORY; + + curr = xmlNewNsProp(NULL, xmlns, ns->prefix, ns->href); + if (!curr) { + xmlFreeNs(xmlns); + return E_OUTOFMEMORY; + } + curr->doc = node->doc; + + unk = create_attribute((xmlNodePtr)curr, TRUE); + if (!unk) { + xmlFreeNs(xmlns); + xmlFreeProp(curr); + return E_OUTOFMEMORY; + } + + hr = IUnknown_QueryInterface(unk, &IID_IXMLDOMNode, (void**)item); + IUnknown_Release(unk); + + return hr; }
static HRESULT domelem_get_length(const xmlNodePtr node, LONG *length) { - xmlAttrPtr first; xmlAttrPtr curr; LONG attrCount; + xmlNsPtr ns;
TRACE("(%p)->(%p)\n", node, length);
if( !length ) return E_INVALIDARG;
- first = node->properties; - if (first == NULL) { - *length = 0; - return S_OK; + attrCount = 0; + curr = node->properties; + while (curr) { + attrCount++; + curr = curr->next; }
- curr = first; - attrCount = 1; - while (curr->next) { + ns = node->nsDef; + while (ns) { attrCount++; - curr = curr->next; + ns = ns->next; } *length = attrCount;
diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c index 0977e09a8c..8c977401ad 100644 --- a/dlls/msxml3/tests/domdoc.c +++ b/dlls/msxml3/tests/domdoc.c @@ -12891,7 +12891,7 @@ static void test_namespaces_as_attributes(void) len = -1; hr = IXMLDOMNamedNodeMap_get_length(map, &len); ok(SUCCEEDED(hr), "Failed to get map length, hr %#x.\n", hr); - todo_wine ok(len == 3, "got %d\n", len); + ok(len == 3, "got %d\n", len);
for (i = 0; i < len; i++) {
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Daniel Lehman dlehman25@gmail.com --- v3: comments in tests --- dlls/msxml3/tests/domdoc.c | 175 +++++++++++++++++++++++-------------- 1 file changed, 110 insertions(+), 65 deletions(-)
diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c index 8c977401ad..62f2e8ce45 100644 --- a/dlls/msxml3/tests/domdoc.c +++ b/dlls/msxml3/tests/domdoc.c @@ -12850,15 +12850,50 @@ static const namespace_as_attribute_t namespace_as_attribute_test_data[] = { static void test_namespaces_as_attributes(void) { const namespace_as_attribute_t *entry = namespace_as_attribute_test_data; - static const char ns_as_attr_doc[] = { - "<?xml version=\"1.0\"?>" - "<a ns:b="b attr" d="d attr" xmlns:ns="nshref" />" + struct test { + const char *xml; + int explen; + const char *names[3]; + const char *prefixes[3]; + const char *basenames[3]; + const char *uris[3]; + const char *texts[3]; }; - static const char *names[] = { "ns:b", "d", "xmlns:ns" }; - static const char *prefixes[] = { "ns", NULL, "xmlns" }; - static const char *basenames[] = { "b", "d", "ns" }; - static const char *uris[] = { "nshref", NULL, "" }; - static const char *texts[] = { "b attr", "d attr", "nshref" }; + static const struct test tests[] = { + { + "<a ns:b="b attr" d="d attr" xmlns:ns="nshref" />", 3, + { "ns:b", "d", "xmlns:ns" }, /* nodeName */ + { "ns", NULL, "xmlns" }, /* prefix */ + { "b", "d", "ns" }, /* baseName */ + { "nshref", NULL, "" }, /* namespaceURI */ + { "b attr", "d attr", "nshref" }, /* text */ + }, + /* property only */ + { + "<a d="d attr" />", 1, + { "d" }, /* nodeName */ + { NULL }, /* prefix */ + { "d" }, /* baseName */ + { NULL }, /* namespaceURI */ + { "d attr" }, /* text */ + }, + /* namespace only */ + { + "<a xmlns:ns="nshref" />", 1, + { "xmlns:ns" }, /* nodeName */ + { "xmlns" }, /* prefix */ + { "ns" }, /* baseName */ + { "" }, /* namespaceURI */ + { "nshref" }, /* text */ + }, + /* no properties or namespaces */ + { + "<a />", 0, + }, + + { NULL } + }; + const struct test *test; IXMLDOMNamedNodeMap *map; IXMLDOMNode *node, *item; IXMLDOMDocument *doc; @@ -12875,81 +12910,91 @@ static void test_namespaces_as_attributes(void) continue; }
- hr = CoCreateInstance(entry->guid, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument2, (void **)&doc); - ok(SUCCEEDED(hr), "Failed to create document %s, hr %#x.\n", wine_dbgstr_guid(entry->guid), hr); + test = tests; + while (test->xml) { + hr = CoCreateInstance(entry->guid, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument2, (void **)&doc); + ok(SUCCEEDED(hr), "Failed to create document %s, hr %#x.\n", wine_dbgstr_guid(entry->guid), hr);
- hr = IXMLDOMDocument_loadXML(doc, _bstr_(ns_as_attr_doc), &b); - ok(hr == S_OK, "Failed to load xml, hr %#x.\n", hr); + hr = IXMLDOMDocument_loadXML(doc, _bstr_(test->xml), &b); + ok(hr == S_OK, "Failed to load xml, hr %#x.\n", hr);
- node = NULL; - hr = IXMLDOMDocument_selectSingleNode(doc, _bstr_("a"), &node); - ok(SUCCEEDED(hr), "Failed to select a node, hr %#x.\n", hr); + node = NULL; + hr = IXMLDOMDocument_selectSingleNode(doc, _bstr_("a"), &node); + ok(SUCCEEDED(hr), "Failed to select a node, hr %#x.\n", hr);
- hr = IXMLDOMNode_get_attributes(node, &map); - ok(SUCCEEDED(hr), "Failed to get attributes, hr %#x.\n", hr); + hr = IXMLDOMNode_get_attributes(node, &map); + ok(SUCCEEDED(hr), "Failed to get attributes, hr %#x.\n", hr);
- len = -1; - hr = IXMLDOMNamedNodeMap_get_length(map, &len); - ok(SUCCEEDED(hr), "Failed to get map length, hr %#x.\n", hr); - ok(len == 3, "got %d\n", len); + len = -1; + hr = IXMLDOMNamedNodeMap_get_length(map, &len); + ok(SUCCEEDED(hr), "Failed to get map length, hr %#x.\n", hr); + ok(len == test->explen, "got %d\n", len);
- for (i = 0; i < len; i++) - { item = NULL; - hr = IXMLDOMNamedNodeMap_get_item(map, i, &item); - ok(SUCCEEDED(hr), "Failed to get item, hr %#x.\n", hr); - - str = NULL; - hr = IXMLDOMNode_get_nodeName(item, &str); - ok(SUCCEEDED(hr), "Failed to get node name, hr %#x.\n", hr); - ok(!lstrcmpW(str, _bstr_(names[i])), "got %s\n", wine_dbgstr_w(str)); - SysFreeString(str); + hr = IXMLDOMNamedNodeMap_get_item(map, test->explen+1, &item); + ok(hr == S_FALSE, "Failed to get item, hr %#x.\n", hr); + ok(!item, "Item should be NULL\n");
- str = NULL; - hr = IXMLDOMNode_get_prefix(item, &str); - if (prefixes[i]) + for (i = 0; i < len; i++) { - ok(hr == S_OK, "Failed to get node name, hr %#x.\n", hr); - ok(!lstrcmpW(str, _bstr_(prefixes[i])), "got %s\n", wine_dbgstr_w(str)); + item = NULL; + hr = IXMLDOMNamedNodeMap_get_item(map, i, &item); + ok(SUCCEEDED(hr), "Failed to get item, hr %#x.\n", hr); + + str = NULL; + hr = IXMLDOMNode_get_nodeName(item, &str); + ok(SUCCEEDED(hr), "Failed to get node name, hr %#x.\n", hr); + ok(!lstrcmpW(str, _bstr_(test->names[i])), "got %s\n", wine_dbgstr_w(str)); SysFreeString(str); - } - else - ok(hr == S_FALSE, "Failed to get node name, hr %#x.\n", hr);
- str = NULL; - hr = IXMLDOMNode_get_baseName(item, &str); - ok(SUCCEEDED(hr), "Failed to get base name, hr %#x.\n", hr); - ok(!lstrcmpW(str, _bstr_(basenames[i])), "got %s\n", wine_dbgstr_w(str)); - SysFreeString(str); + str = NULL; + hr = IXMLDOMNode_get_prefix(item, &str); + if (test->prefixes[i]) + { + ok(hr == S_OK, "Failed to get node name, hr %#x.\n", hr); + ok(!lstrcmpW(str, _bstr_(test->prefixes[i])), "got %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + } + else + ok(hr == S_FALSE, "Failed to get node name, hr %#x.\n", hr);
- str = NULL; - hr = IXMLDOMNode_get_namespaceURI(item, &str); - if (uris[i]) - { - ok(hr == S_OK, "Failed to get node name, hr %#x.\n", hr); - if (prefixes[i] && !strcmp(prefixes[i], "xmlns")) - todo_wine_if(entry->todo) - ok(!lstrcmpW(str, _bstr_(entry->xmlns_uri)), "got %s\n", wine_dbgstr_w(str)); + str = NULL; + hr = IXMLDOMNode_get_baseName(item, &str); + ok(SUCCEEDED(hr), "Failed to get base name, hr %#x.\n", hr); + ok(!lstrcmpW(str, _bstr_(test->basenames[i])), "got %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + str = NULL; + hr = IXMLDOMNode_get_namespaceURI(item, &str); + if (test->uris[i]) + { + ok(hr == S_OK, "Failed to get node name, hr %#x.\n", hr); + if (test->prefixes[i] && !strcmp(test->prefixes[i], "xmlns")) + todo_wine_if(entry->todo) + ok(!lstrcmpW(str, _bstr_(entry->xmlns_uri)), "got %s\n", wine_dbgstr_w(str)); + else + ok(!lstrcmpW(str, _bstr_(test->uris[i])), "got %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + } else - ok(!lstrcmpW(str, _bstr_(uris[i])), "got %s\n", wine_dbgstr_w(str)); + ok(hr == S_FALSE, "Failed to get node name, hr %#x.\n", hr); + + str = NULL; + hr = IXMLDOMNode_get_text(item, &str); + ok(SUCCEEDED(hr), "Failed to get node text, hr %#x.\n", hr); + ok(!lstrcmpW(str, _bstr_(test->texts[i])), "got %s\n", wine_dbgstr_w(str)); SysFreeString(str); + + IXMLDOMNode_Release(item); } - else - ok(hr == S_FALSE, "Failed to get node name, hr %#x.\n", hr);
- str = NULL; - hr = IXMLDOMNode_get_text(item, &str); - ok(SUCCEEDED(hr), "Failed to get node text, hr %#x.\n", hr); - ok(!lstrcmpW(str, _bstr_(texts[i])), "got %s\n", wine_dbgstr_w(str)); - SysFreeString(str); + IXMLDOMNamedNodeMap_Release(map); + IXMLDOMNode_Release(node); + IXMLDOMDocument_Release(doc);
- IXMLDOMNode_Release(item); + test++; }
- IXMLDOMNamedNodeMap_Release(map); - IXMLDOMNode_Release(node); - IXMLDOMDocument_Release(doc); - entry++; } free_bstrs();
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Daniel Lehman dlehman25@gmail.com --- dlls/msxml3/attribute.c | 9 ++++++++- dlls/msxml3/domdoc.c | 5 +++++ dlls/msxml3/msxml_private.h | 1 + dlls/msxml3/tests/domdoc.c | 14 ++++++-------- 4 files changed, 20 insertions(+), 9 deletions(-)
diff --git a/dlls/msxml3/attribute.c b/dlls/msxml3/attribute.c index 8eb2695128..c303969bc3 100644 --- a/dlls/msxml3/attribute.c +++ b/dlls/msxml3/attribute.c @@ -549,6 +549,8 @@ static HRESULT WINAPI domattr_get_namespaceURI( IXMLDOMAttribute *iface, BSTR* p) { + static const WCHAR w3xmlns[] = { 'h','t','t','p',':','/','/', 'w','w','w','.','w','3','.', + 'o','r','g','/','2','0','0','0','/','x','m','l','n','s','/',0 }; domattr *This = impl_from_IXMLDOMAttribute( iface ); xmlNsPtr ns = This->node.node->ns;
@@ -565,7 +567,12 @@ static HRESULT WINAPI domattr_get_namespaceURI( if (xmlStrEqual(This->node.node->name, xmlns)) *p = bstr_from_xmlChar(xmlns); else if (xmlStrEqual(ns->prefix, xmlns)) - *p = SysAllocStringLen(NULL, 0); + { + if (xmldoc_version(This->node.node->doc) == MSXML6) + *p = SysAllocString(w3xmlns); + else + *p = SysAllocStringLen(NULL, 0); + } else if (ns->href) *p = bstr_from_xmlChar(ns->href); } diff --git a/dlls/msxml3/domdoc.c b/dlls/msxml3/domdoc.c index 0b917c1302..445caaee69 100644 --- a/dlls/msxml3/domdoc.c +++ b/dlls/msxml3/domdoc.c @@ -396,6 +396,11 @@ xmlNodePtr xmldoc_unlink_xmldecl(xmlDocPtr doc) return node; }
+MSXML_VERSION xmldoc_version(xmlDocPtr doc) +{ + return properties_from_xmlDocPtr(doc)->version; +} + BOOL is_preserving_whitespace(xmlNodePtr node) { domdoc_properties* properties = NULL; diff --git a/dlls/msxml3/msxml_private.h b/dlls/msxml3/msxml_private.h index abc6ab3465..08f944ab1b 100644 --- a/dlls/msxml3/msxml_private.h +++ b/dlls/msxml3/msxml_private.h @@ -284,6 +284,7 @@ extern HRESULT xmldoc_add_orphan( xmlDocPtr doc, xmlNodePtr node ) DECLSPEC_HIDD extern HRESULT xmldoc_remove_orphan( xmlDocPtr doc, xmlNodePtr node ) DECLSPEC_HIDDEN; extern void xmldoc_link_xmldecl(xmlDocPtr doc, xmlNodePtr node) DECLSPEC_HIDDEN; extern xmlNodePtr xmldoc_unlink_xmldecl(xmlDocPtr doc) DECLSPEC_HIDDEN; +extern MSXML_VERSION xmldoc_version( xmlDocPtr doc ) DECLSPEC_HIDDEN;
extern HRESULT XMLElement_create( xmlNodePtr node, LPVOID *ppObj, BOOL own ) DECLSPEC_HIDDEN;
diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c index 62f2e8ce45..22d9c46871 100644 --- a/dlls/msxml3/tests/domdoc.c +++ b/dlls/msxml3/tests/domdoc.c @@ -12834,16 +12834,15 @@ typedef struct _namespace_as_attribute_t { const GUID *guid; const char *clsid; const char *xmlns_uri; - BOOL todo; } namespace_as_attribute_t;
static const namespace_as_attribute_t namespace_as_attribute_test_data[] = { - { &CLSID_DOMDocument, "CLSID_DOMDocument", "", FALSE }, - { &CLSID_DOMDocument2, "CLSID_DOMDocument2", "", FALSE }, - { &CLSID_DOMDocument26, "CLSID_DOMDocument26", "", FALSE }, - { &CLSID_DOMDocument30, "CLSID_DOMDocument30", "", FALSE }, - { &CLSID_DOMDocument40, "CLSID_DOMDocument40", "", FALSE }, - { &CLSID_DOMDocument60, "CLSID_DOMDocument60", "http://www.w3.org/2000/xmlns/", TRUE }, + { &CLSID_DOMDocument, "CLSID_DOMDocument", "" }, + { &CLSID_DOMDocument2, "CLSID_DOMDocument2", "" }, + { &CLSID_DOMDocument26, "CLSID_DOMDocument26", "" }, + { &CLSID_DOMDocument30, "CLSID_DOMDocument30", "" }, + { &CLSID_DOMDocument40, "CLSID_DOMDocument40", "" }, + { &CLSID_DOMDocument60, "CLSID_DOMDocument60", "http://www.w3.org/2000/xmlns/" }, { 0 } };
@@ -12970,7 +12969,6 @@ static void test_namespaces_as_attributes(void) { ok(hr == S_OK, "Failed to get node name, hr %#x.\n", hr); if (test->prefixes[i] && !strcmp(test->prefixes[i], "xmlns")) - todo_wine_if(entry->todo) ok(!lstrcmpW(str, _bstr_(entry->xmlns_uri)), "got %s\n", wine_dbgstr_w(str)); else ok(!lstrcmpW(str, _bstr_(test->uris[i])), "got %s\n", wine_dbgstr_w(str));
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com