Hans Leidekker : webservices: Add support for namespace attributes in the writer.

Alexandre Julliard julliard at wine.codeweavers.com
Tue Feb 23 11:24:21 CST 2016


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

Author: Hans Leidekker <hans at codeweavers.com>
Date:   Tue Feb 23 13:11:50 2016 +0100

webservices: Add support for namespace attributes in the writer.

Signed-off-by: Hans Leidekker <hans at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/webservices/writer.c | 119 ++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 99 insertions(+), 20 deletions(-)

diff --git a/dlls/webservices/writer.c b/dlls/webservices/writer.c
index 88dab77..2ea3486 100644
--- a/dlls/webservices/writer.c
+++ b/dlls/webservices/writer.c
@@ -485,7 +485,6 @@ static HRESULT write_attribute( struct writer *writer, WS_XML_ATTRIBUTE *attr )
     if (text) write_bytes( writer, text->value.bytes, text->value.length );
     write_char( writer, quote );
 
-    /* FIXME: ignoring namespace */
     return S_OK;
 }
 
@@ -503,21 +502,42 @@ static HRESULT set_current_namespace( struct writer *writer, const WS_XML_STRING
     return S_OK;
 }
 
+static HRESULT write_namespace_attribute( struct writer *writer, WS_XML_ATTRIBUTE *attr )
+{
+    unsigned char quote = attr->singleQuote ? '\'' : '"';
+    ULONG size;
+    HRESULT hr;
+
+    /* ' xmlns:prefix="namespace"' */
+
+    size = attr->ns->length + 9 /* ' xmlns=""' */;
+    if (attr->prefix) size += attr->prefix->length + 1 /* ':' */;
+    if ((hr = write_grow_buffer( writer, size )) != S_OK) return hr;
+
+    write_bytes( writer, (const BYTE *)" xmlns", 6 );
+    if (attr->prefix)
+    {
+        write_char( writer, ':' );
+        write_bytes( writer, attr->prefix->bytes, attr->prefix->length );
+    }
+    write_char( writer, '=' );
+    write_char( writer, quote );
+    write_bytes( writer, attr->ns->bytes, attr->ns->length );
+    write_char( writer, quote );
+
+    return S_OK;
+}
+
 static HRESULT write_startelement( struct writer *writer )
 {
     WS_XML_ELEMENT_NODE *elem = &writer->current->hdr;
     ULONG size, i;
     HRESULT hr;
 
-    /* '<prefix:localname prefix:attr="value"... xmlns:prefix="ns"' */
+    /* '<prefix:localname prefix:attr="value"... xmlns:prefix="ns"'... */
 
     size = elem->localName->length + 1 /* '<' */;
     if (elem->prefix) size += elem->prefix->length + 1 /* ':' */;
-    if (elem->ns->length && !is_current_namespace( writer, elem->ns ))
-    {
-        size += strlen(" xmlns") + elem->ns->length + 3 /* '=""' */;
-        if (elem->prefix) size += elem->prefix->length + 1 /* ':' */;
-    }
     if ((hr = write_grow_buffer( writer, size )) != S_OK) return hr;
 
     write_char( writer, '<' );
@@ -529,23 +549,20 @@ static HRESULT write_startelement( struct writer *writer )
     write_bytes( writer, elem->localName->bytes, elem->localName->length );
     for (i = 0; i < elem->attributeCount; i++)
     {
+        if (elem->attributes[i]->isXmlNs) continue;
         if ((hr = write_attribute( writer, elem->attributes[i] )) != S_OK) return hr;
     }
-    if (elem->ns->length && !is_current_namespace( writer, elem->ns ))
+    for (i = 0; i < elem->attributeCount; i++)
     {
-        if ((hr = set_current_namespace( writer, elem->ns )) != S_OK) return hr;
-
-        write_bytes( writer, (const BYTE *)" xmlns", 6 );
-        if (elem->prefix)
-        {
-            write_char( writer, ':' );
-            write_bytes( writer, elem->prefix->bytes, elem->prefix->length );
-        }
-        write_char( writer, '=' );
-        write_char( writer, '"' );
-        write_bytes( writer, elem->ns->bytes, elem->ns->length );
-        write_char( writer, '"' );
+        if (!elem->attributes[i]->isXmlNs || !elem->attributes[i]->prefix) continue;
+        if ((hr = write_namespace_attribute( writer, elem->attributes[i] )) != S_OK) return hr;
+    }
+    for (i = 0; i < elem->attributeCount; i++)
+    {
+        if (!elem->attributes[i]->isXmlNs || elem->attributes[i]->prefix) continue;
+        if ((hr = write_namespace_attribute( writer, elem->attributes[i] )) != S_OK) return hr;
     }
+
     return S_OK;
 }
 
@@ -576,9 +593,70 @@ static HRESULT write_endelement( struct writer *writer )
     return S_OK;
 }
 
+static HRESULT write_add_namespace_attribute( struct writer *writer, const WS_XML_STRING *prefix,
+                                              const WS_XML_STRING *ns, BOOL single )
+{
+    WS_XML_ATTRIBUTE *attr;
+    WS_XML_ELEMENT_NODE *elem = &writer->current->hdr;
+    HRESULT hr;
+
+    if (!(attr = heap_alloc_zero( sizeof(*attr) ))) return E_OUTOFMEMORY;
+
+    attr->singleQuote = !!single;
+    attr->isXmlNs = 1;
+    if (prefix && !(attr->prefix = alloc_xml_string( prefix->bytes, prefix->length )))
+    {
+        free_attribute( attr );
+        return E_OUTOFMEMORY;
+    }
+    if (!(attr->ns = alloc_xml_string( ns->bytes, ns->length )))
+    {
+        free_attribute( attr );
+        return E_OUTOFMEMORY;
+    }
+    if ((hr = append_attribute( elem, attr )) != S_OK)
+    {
+        free_attribute( attr );
+        return hr;
+    }
+    return S_OK;
+}
+
+static const WS_XML_ATTRIBUTE *find_namespace_attribute( const WS_XML_ELEMENT_NODE *elem,
+                                                         const WS_XML_STRING *prefix,
+                                                         const WS_XML_STRING *ns )
+{
+    ULONG i;
+    for (i = 0; i < elem->attributeCount; i++)
+    {
+        if (!elem->attributes[i]->isXmlNs) continue;
+        if (WsXmlStringEquals( elem->attributes[i]->prefix, prefix, NULL ) == S_OK &&
+            WsXmlStringEquals( elem->attributes[i]->ns, ns, NULL ) == S_OK)
+        {
+            return elem->attributes[i];
+        }
+    }
+    return NULL;
+}
+
+static HRESULT write_set_element_namespace( struct writer *writer )
+{
+    WS_XML_ELEMENT_NODE *elem = &writer->current->hdr;
+    HRESULT hr;
+
+    if (!elem->ns->length || is_current_namespace( writer, elem->ns ) ||
+        find_namespace_attribute( elem, elem->prefix, elem->ns )) return S_OK;
+
+    if ((hr = write_add_namespace_attribute( writer, elem->prefix, elem->ns, FALSE )) != S_OK)
+        return hr;
+
+    return set_current_namespace( writer, elem->ns );
+}
+
 static HRESULT write_endstartelement( struct writer *writer )
 {
     HRESULT hr;
+    if ((hr = write_set_element_namespace( writer )) != S_OK) return hr;
     if ((hr = write_startelement( writer )) != S_OK) return hr;
     if ((hr = write_grow_buffer( writer, 1 )) != S_OK) return hr;
     write_char( writer, '>' );
@@ -609,6 +687,7 @@ static HRESULT write_close_element( struct writer *writer )
     if (writer->state == WRITER_STATE_STARTELEMENT)
     {
         /* '/>' */
+        if ((hr = write_set_element_namespace( writer )) != S_OK) return hr;
         if ((hr = write_startelement( writer )) != S_OK) return hr;
         if ((hr = write_grow_buffer( writer, 2 )) != S_OK) return hr;
         write_char( writer, '/' );




More information about the wine-cvs mailing list