[PATCH 2/3] msxml3: Copy namespaces as attributes.

Daniel Lehman dlehman25 at gmail.com
Sun Aug 26 11:27:22 CDT 2018


Signed-off-by: Daniel Lehman <dlehman25 at gmail.com>
---
 dlls/msxml3/nodemap.c      | 123 ++++++++++++++++++++++++++++++++++++-
 dlls/msxml3/tests/domdoc.c |   2 +-
 2 files changed, 122 insertions(+), 3 deletions(-)

diff --git a/dlls/msxml3/nodemap.c b/dlls/msxml3/nodemap.c
index a9fef4769d..b35fd34103 100644
--- a/dlls/msxml3/nodemap.c
+++ b/dlls/msxml3/nodemap.c
@@ -39,6 +39,7 @@
 #include "msxml_private.h"
 
 #include "wine/debug.h"
+#include "wine/list.h"
 
 #ifdef HAVE_LIBXML2
 
@@ -54,10 +55,17 @@ typedef struct
     xmlNodePtr node;
     LONG iterator;
     IEnumVARIANT *enumvariant;
+    struct list nsattrs;
 
     const struct nodemap_funcs *funcs;
 } xmlnodemap;
 
+typedef struct
+{
+    struct list entry;
+    xmlAttrPtr  attr;
+} nsattr_entry;
+
 static HRESULT nodemap_get_item(IUnknown *iface, LONG index, VARIANT *item)
 {
     V_VT(item) = VT_DISPATCH;
@@ -140,9 +148,20 @@ static ULONG WINAPI xmlnodemap_Release(
     TRACE("(%p)->(%d)\n", This, ref);
     if ( ref == 0 )
     {
+        nsattr_entry *nsattr;
+        struct list *head;
+
         xmlnode_release( This->node );
         xmldoc_release( This->node->doc );
         if (This->enumvariant) IEnumVARIANT_Release(This->enumvariant);
+        while ((head = list_head( &This->nsattrs )))
+        {
+            list_remove( head );
+            nsattr = LIST_ENTRY( head, nsattr_entry, entry );
+            xmlFreeNs( nsattr->attr->ns );
+            xmlFreeProp( nsattr->attr );
+            heap_free( nsattr );
+        }
         heap_free( This );
     }
 
@@ -224,16 +243,102 @@ static HRESULT WINAPI xmlnodemap_removeNamedItem(
     return This->funcs->remove_named_item(This->node, name, namedItem);
 }
 
+static HRESULT copy_ns_as_attrs(xmlnodemap *This)
+{
+    xmlNsPtr ns;
+    xmlNsPtr cur;
+    xmlAttrPtr prop;
+    nsattr_entry *entry;
+
+    cur = This->node->nsDef;
+    while (cur)
+    {
+        entry = heap_alloc(sizeof(*entry));
+        if (!entry)
+            return E_OUTOFMEMORY;
+
+        ns = xmlNewNs(NULL, BAD_CAST "http://www.w3.org/2000/xmlns/", BAD_CAST "xmlns");
+        if (!ns)
+        {
+            heap_free(entry);
+            return E_OUTOFMEMORY;
+        }
+
+        prop = xmlNewNsProp(NULL, ns, cur->prefix, cur->href);
+        if (!prop)
+        {
+            xmlFreeNs(ns);
+            heap_free(entry);
+            return E_OUTOFMEMORY;
+        }
+
+        prop->doc = This->node->doc;
+        entry->attr = prop;
+        list_add_tail(&This->nsattrs, &entry->entry);
+
+        cur = cur->next;
+    }
+
+    return S_OK;
+}
+
 static HRESULT WINAPI xmlnodemap_get_item(
     IXMLDOMNamedNodeMap *iface,
     LONG index,
     IXMLDOMNode** item)
 {
+    HRESULT hr;
+    xmlAttrPtr cur;
+    struct list *ptr;
+    nsattr_entry *nsattr;
     xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
 
     TRACE("(%p)->(%d %p)\n", This, index, item);
 
-    return This->funcs->get_item(This->node, index, item);
+    hr = This->funcs->get_item(This->node, index, item);
+    if (hr != S_FALSE)
+        return hr;
+
+    ptr = list_head(&This->nsattrs);
+    if (!ptr)
+    {
+        if (!This->node->nsDef)
+            return S_FALSE;
+
+        if (This->node->nsDef)
+        {
+            hr = copy_ns_as_attrs(This);
+            if (FAILED(hr))
+                return hr;
+        }
+
+        ptr = list_head(&This->nsattrs);
+        if (!ptr)
+            return FALSE;
+    }
+
+    if (This->node->properties)
+    {
+        --index;
+        cur = This->node->properties;
+        while (cur->next)
+        {
+            --index;
+            cur = cur->next;
+        }
+    }
+
+    if (index < 0)
+        return S_FALSE;
+
+    while (index--)
+        ptr = list_next(ptr, ptr);
+
+    nsattr = LIST_ENTRY(ptr, nsattr_entry, entry);
+    cur = nsattr->attr;
+    *item = create_node((xmlNodePtr) cur);
+
+    return S_OK;
 }
 
 static HRESULT WINAPI xmlnodemap_get_length(
@@ -241,10 +346,23 @@ static HRESULT WINAPI xmlnodemap_get_length(
     LONG *length)
 {
     xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
+    xmlNsPtr cur;
+    HRESULT hr;
 
     TRACE("(%p)->(%p)\n", This, length);
 
-    return This->funcs->get_length(This->node, length);
+    hr = This->funcs->get_length(This->node, length);
+    if (FAILED(hr))
+        return hr;
+
+    cur = This->node->nsDef;
+    while (cur)
+    {
+        ++*length;
+        cur = cur->next;
+    }
+
+    return S_OK;
 }
 
 static HRESULT WINAPI xmlnodemap_getQualifiedItem(
@@ -447,6 +565,7 @@ IXMLDOMNamedNodeMap *create_nodemap(xmlNodePtr node, const struct nodemap_funcs
     This->ref = 1;
     This->iterator = 0;
     This->enumvariant = NULL;
+    list_init(&This->nsattrs);
     This->funcs = funcs;
 
     init_dispex(&This->dispex, (IUnknown*)&This->IXMLDOMNamedNodeMap_iface, &xmlnodemap_dispex);
diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c
index ffb9e1462d..667feaa244 100644
--- a/dlls/msxml3/tests/domdoc.c
+++ b/dlls/msxml3/tests/domdoc.c
@@ -12894,7 +12894,7 @@ void test_namespaces_as_attributes(void)
         len = -1;
         hr = IXMLDOMNamedNodeMap_get_length(map, &len);
         EXPECT_HR(hr, S_OK);
-        todo_wine ok(len == 3, "got %d\n", len);
+        ok(len == 3, "got %d\n", len);
 
         for (i = 0; i < len; i++)
         {
-- 
2.17.1




More information about the wine-devel mailing list