Nikolay Sivov : msxml3: Store namespace info for created attribute, fix returned properties.

Alexandre Julliard julliard at winehq.org
Sat Jul 27 13:23:35 CDT 2013


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

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Fri Jul 26 08:44:57 2013 +0400

msxml3: Store namespace info for created attribute, fix returned properties.

---

 dlls/msxml3/attribute.c    |   45 ++++++++++++++++++++-
 dlls/msxml3/domdoc.c       |   23 +++++++++--
 dlls/msxml3/tests/domdoc.c |   94 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 156 insertions(+), 6 deletions(-)

diff --git a/dlls/msxml3/attribute.c b/dlls/msxml3/attribute.c
index 70dee2a..bb0655c 100644
--- a/dlls/msxml3/attribute.c
+++ b/dlls/msxml3/attribute.c
@@ -43,6 +43,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(msxml);
 
 #ifdef HAVE_LIBXML2
 
+static const xmlChar xmlns[] = "xmlns";
+
 typedef struct _domattr
 {
     xmlnode node;
@@ -542,8 +544,29 @@ static HRESULT WINAPI domattr_get_namespaceURI(
     BSTR* p)
 {
     domattr *This = impl_from_IXMLDOMAttribute( iface );
+    xmlNsPtr ns = This->node.node->ns;
+
     TRACE("(%p)->(%p)\n", This, p);
-    return node_get_namespaceURI(&This->node, p);
+
+    if (!p)
+        return E_INVALIDARG;
+
+    *p = NULL;
+
+    if (ns)
+    {
+        /* special case for default namespace definition */
+        if (xmlStrEqual(This->node.node->name, xmlns))
+            *p = bstr_from_xmlChar(xmlns);
+        else if (xmlStrEqual(ns->prefix, xmlns))
+            *p = SysAllocStringLen(NULL, 0);
+        else if (ns->href)
+            *p = bstr_from_xmlChar(ns->href);
+    }
+
+    TRACE("uri: %s\n", debugstr_w(*p));
+
+    return *p ? S_OK : S_FALSE;
 }
 
 static HRESULT WINAPI domattr_get_prefix(
@@ -551,8 +574,26 @@ static HRESULT WINAPI domattr_get_prefix(
     BSTR* prefix)
 {
     domattr *This = impl_from_IXMLDOMAttribute( iface );
+    xmlNsPtr ns = This->node.node->ns;
+
     TRACE("(%p)->(%p)\n", This, prefix);
-    return node_get_prefix( &This->node, prefix );
+
+    if (!prefix) return E_INVALIDARG;
+
+    *prefix = NULL;
+
+    if (ns)
+    {
+        /* special case for default namespace definition */
+        if (xmlStrEqual(This->node.node->name, xmlns))
+            *prefix = bstr_from_xmlChar(xmlns);
+        else if (ns->prefix)
+            *prefix = bstr_from_xmlChar(ns->prefix);
+    }
+
+    TRACE("prefix: %s\n", debugstr_w(*prefix));
+
+    return *prefix ? S_OK : S_FALSE;
 }
 
 static HRESULT WINAPI domattr_get_baseName(
diff --git a/dlls/msxml3/domdoc.c b/dlls/msxml3/domdoc.c
index 7eae2d4..a96b5c7 100644
--- a/dlls/msxml3/domdoc.c
+++ b/dlls/msxml3/domdoc.c
@@ -1934,9 +1934,6 @@ static HRESULT WINAPI domdoc_createNode(
     hr = get_node_type(Type, &node_type);
     if(FAILED(hr)) return hr;
 
-    if(namespaceURI && namespaceURI[0] && node_type != NODE_ELEMENT)
-        FIXME("nodes with namespaces currently not supported.\n");
-
     TRACE("node_type %d\n", node_type);
 
     /* exit earlier for types that need name */
@@ -1979,8 +1976,26 @@ static HRESULT WINAPI domdoc_createNode(
         break;
     }
     case NODE_ATTRIBUTE:
-        xmlnode = (xmlNodePtr)xmlNewDocProp(get_doc(This), xml_name, NULL);
+    {
+        xmlChar *local, *prefix;
+
+        local = xmlSplitQName2(xml_name, &prefix);
+
+        xmlnode = (xmlNodePtr)xmlNewDocProp(get_doc(This), local ? local : xml_name, NULL);
+
+        if (local || (href && *href))
+        {
+            /* we need a floating namespace here, it can't be created linked to attribute from
+               a start */
+            xmlNsPtr ns = xmlNewNs(NULL, href, prefix);
+            xmlSetNs(xmlnode, ns);
+        }
+
+        xmlFree(local);
+        xmlFree(prefix);
+
         break;
+    }
     case NODE_TEXT:
         xmlnode = (xmlNodePtr)xmlNewDocText(get_doc(This), NULL);
         break;
diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c
index 5f1b5c3..a32eda8 100644
--- a/dlls/msxml3/tests/domdoc.c
+++ b/dlls/msxml3/tests/domdoc.c
@@ -11590,6 +11590,99 @@ static void test_xsltext(void)
     free_bstrs();
 }
 
+struct attrtest_t {
+    const char *name;
+    const char *uri;
+    const char *prefix;
+    const char *href;
+};
+
+static struct attrtest_t attrtests[] = {
+    { "xmlns", "http://www.w3.org/2000/xmlns/", "xmlns", "xmlns" },
+    { "xmlns", "nondefaulturi", "xmlns", "xmlns" },
+    { "c", "http://www.w3.org/2000/xmlns/", NULL, "http://www.w3.org/2000/xmlns/" },
+    { "c", "nsref1", NULL, "nsref1" },
+    { "ns:c", "nsref1", "ns", "nsref1" },
+    { "xmlns:c", "http://www.w3.org/2000/xmlns/", "xmlns", "" },
+    { "xmlns:c", "nondefaulturi", "xmlns", "" },
+    { 0 }
+};
+
+static void test_create_attribute(void)
+{
+    struct attrtest_t *ptr = attrtests;
+    IXMLDOMElement *el;
+    IXMLDOMDocument *doc;
+    IXMLDOMNode *node, *node2;
+    VARIANT var;
+    HRESULT hr;
+    int i = 0;
+    BSTR str;
+
+    doc = create_document(&IID_IXMLDOMDocument);
+
+    while (ptr->name)
+    {
+        V_VT(&var) = VT_I1;
+        V_I1(&var) = NODE_ATTRIBUTE;
+        hr = IXMLDOMDocument_createNode(doc, var, _bstr_(ptr->name), _bstr_(ptr->uri), &node);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+
+        str = NULL;
+        hr = IXMLDOMNode_get_prefix(node, &str);
+        if (ptr->prefix)
+        {
+            ok(hr == S_OK, "%d: got 0x%08x\n", i, hr);
+            ok(!lstrcmpW(str, _bstr_(ptr->prefix)), "%d: got prefix %s, expected %s\n", i, wine_dbgstr_w(str), ptr->prefix);
+        }
+        else
+        {
+            ok(hr == S_FALSE, "%d: got 0x%08x\n", i, hr);
+            ok(str == NULL, "%d: got prefix %s\n", i, wine_dbgstr_w(str));
+        }
+
+        str = NULL;
+        hr = IXMLDOMNode_get_namespaceURI(node, &str);
+        ok(hr == S_OK, "%d: got 0x%08x\n", i, hr);
+        ok(!lstrcmpW(str, _bstr_(ptr->href)), "%d: got uri %s, expected %s\n", i, wine_dbgstr_w(str), ptr->href);
+        SysFreeString(str);
+
+        IXMLDOMNode_Release(node);
+        free_bstrs();
+
+        i++;
+        ptr++;
+    }
+
+    V_VT(&var) = VT_I1;
+    V_I1(&var) = NODE_ELEMENT;
+    hr = IXMLDOMDocument_createNode(doc, var, _bstr_("e"), NULL, &node2);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    hr = IXMLDOMNode_QueryInterface(node2, &IID_IXMLDOMElement, (void**)&el);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    IXMLDOMNode_Release(node2);
+
+    V_VT(&var) = VT_I1;
+    V_I1(&var) = NODE_ATTRIBUTE;
+    hr = IXMLDOMDocument_createNode(doc, var, _bstr_("xmlns:a"), _bstr_("http://www.w3.org/2000/xmlns/"), &node);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    hr = IXMLDOMElement_setAttributeNode(el, (IXMLDOMAttribute*)node, NULL);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    /* for some reason default namespace uri is not reported */
+    hr = IXMLDOMNode_get_namespaceURI(node, &str);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(!lstrcmpW(str, _bstr_("")), "got uri %s\n", wine_dbgstr_w(str));
+    SysFreeString(str);
+
+    IXMLDOMNode_Release(node);
+    IXMLDOMElement_Release(el);
+    IXMLDOMDocument_Release(doc);
+    free_bstrs();
+}
+
 START_TEST(domdoc)
 {
     IXMLDOMDocument *doc;
@@ -11644,6 +11737,7 @@ START_TEST(domdoc)
     test_setAttributeNode();
     test_put_dataType();
     test_createNode();
+    test_create_attribute();
     test_get_prefix();
     test_default_properties();
     test_selectSingleNode();




More information about the wine-cvs mailing list