Dmitry Timoshkov : msxml3: Implement ::get_attributes() for "xml" processing instruction node.

Alexandre Julliard julliard at winehq.org
Mon May 31 15:58:36 CDT 2021


Module: wine
Branch: master
Commit: 769aac0021c23754c46dd9cceaf52a42df77f04d
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=769aac0021c23754c46dd9cceaf52a42df77f04d

Author: Dmitry Timoshkov <dmitry at baikal.ru>
Date:   Fri May 28 13:38:32 2021 +0300

msxml3: Implement ::get_attributes() for "xml" processing instruction node.

Signed-off-by: Dmitry Timoshkov <dmitry at baikal.ru>
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/msxml3/pi.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 143 insertions(+), 1 deletion(-)

diff --git a/dlls/msxml3/pi.c b/dlls/msxml3/pi.c
index cea95708087..f37f3c01630 100644
--- a/dlls/msxml3/pi.c
+++ b/dlls/msxml3/pi.c
@@ -34,6 +34,7 @@
 #include "ole2.h"
 #include "msxml6.h"
 
+#include "xmlparser.h"
 #include "msxml_private.h"
 
 #include "wine/debug.h"
@@ -287,6 +288,138 @@ static HRESULT WINAPI dom_pi_get_nextSibling(
     return node_get_next_sibling(&This->node, domNode);
 }
 
+static HRESULT xml_get_value(xmlChar **p, xmlChar **value)
+{
+    xmlChar *v;
+    int len;
+
+    while (isspace(**p)) *p += 1;
+    if (**p != '=') return XML_E_MISSINGEQUALS;
+    *p += 1;
+
+    while (isspace(**p)) *p += 1;
+    if (**p != '"') return XML_E_MISSINGQUOTE;
+    *p += 1;
+
+    v = *p;
+    while (**p && **p != '"') *p += 1;
+    if (!**p) return XML_E_EXPECTINGCLOSEQUOTE;
+    len = *p - v;
+    if (!len) return XML_E_MISSINGNAME;
+    *p += 1;
+
+    *value = heap_alloc(len + 1);
+    if (!*value) return E_OUTOFMEMORY;
+    memcpy(*value, v, len);
+    *(*value + len) = 0;
+
+    return S_OK;
+}
+
+static void set_prop(xmlNodePtr node, xmlAttrPtr attr)
+{
+    xmlAttrPtr prop;
+
+    if (!node->properties)
+    {
+        node->properties = attr;
+        return;
+    }
+
+    prop = node->properties;
+    while (prop->next) prop = prop->next;
+
+    prop->next = attr;
+}
+
+static HRESULT parse_xml_decl(xmlNodePtr node)
+{
+    xmlChar *version, *encoding, *standalone, *p;
+    xmlAttrPtr attr;
+    HRESULT hr = S_OK;
+
+    if (!node->content) return S_OK;
+
+    version = encoding = standalone = NULL;
+
+    p = node->content;
+
+    while (*p)
+    {
+        while (isspace(*p)) p++;
+        if (!*p) break;
+
+        if (!strncmp((const char *)p, "version", 7))
+        {
+            p += 7;
+            if ((hr = xml_get_value(&p, &version)) != S_OK) goto fail;
+        }
+        else if (!strncmp((const char *)p, "encoding", 8))
+        {
+            p += 8;
+            if ((hr = xml_get_value(&p, &encoding)) != S_OK) goto fail;
+        }
+        else if (!strncmp((const char *)p, "standalone", 10))
+        {
+            p += 10;
+            if ((hr = xml_get_value(&p, &standalone)) != S_OK) goto fail;
+        }
+        else
+        {
+            FIXME("unexpected XML attribute %s\n", debugstr_a((const char *)p));
+            hr = XML_E_UNEXPECTED_ATTRIBUTE;
+            goto fail;
+        }
+    }
+
+    /* xmlSetProp/xmlSetNsProp accept only nodes of type XML_ELEMENT_NODE,
+     * so we have to create and assign attributes to a node by hand.
+     */
+
+    if (version)
+    {
+        attr = xmlSetNsProp(NULL, NULL, (const xmlChar *)"version", version);
+        if (attr)
+        {
+            attr->doc = node->doc;
+            set_prop(node, attr);
+        }
+        else hr = E_OUTOFMEMORY;
+    }
+    if (encoding)
+    {
+        attr = xmlSetNsProp(NULL, NULL, (const xmlChar *)"encoding", encoding);
+        if (attr)
+        {
+            attr->doc = node->doc;
+            set_prop(node, attr);
+        }
+        else hr = E_OUTOFMEMORY;
+    }
+    if (standalone)
+    {
+        attr = xmlSetNsProp(NULL, NULL, (const xmlChar *)"standalone", standalone);
+        if (attr)
+        {
+            attr->doc = node->doc;
+            set_prop(node, attr);
+        }
+        else hr = E_OUTOFMEMORY;
+    }
+
+fail:
+    if (hr != S_OK)
+    {
+        xmlFreePropList(node->properties);
+        node->properties = NULL;
+    }
+
+    heap_free(version);
+    heap_free(encoding);
+    heap_free(standalone);
+    return hr;
+}
+
 static HRESULT WINAPI dom_pi_get_attributes(
     IXMLDOMProcessingInstruction *iface,
     IXMLDOMNamedNodeMap** map)
@@ -307,7 +440,16 @@ static HRESULT WINAPI dom_pi_get_attributes(
 
     if (!strcmpW(name, xmlW))
     {
-        FIXME("created dummy map for <?xml ?>\n");
+        if (!This->node.node->properties)
+        {
+            hr = parse_xml_decl(This->node.node);
+            if (hr != S_OK)
+            {
+                SysFreeString(name);
+                return S_FALSE;
+            }
+        }
+
         *map = create_nodemap(This->node.node, &dom_pi_attr_map);
         SysFreeString(name);
         return S_OK;




More information about the wine-cvs mailing list