From a86e2a4a3f52708edb2996a5e9319b1e1e563b80 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Tue, 11 Sep 2018 13:17:06 +0300 Subject: [PATCH] xmllite/writer: Improve namespaces handling in WriteStartElement(). Signed-off-by: Nikolay Sivov Signed-off-by: Alexandre Julliard --- dlls/xmllite/tests/writer.c | 156 ++++++++++++++++++------------------ dlls/xmllite/writer.c | 48 +++++++---- 2 files changed, 112 insertions(+), 92 deletions(-) diff --git a/dlls/xmllite/tests/writer.c b/dlls/xmllite/tests/writer.c index 9331899a198..87cdaabce15 100644 --- a/dlls/xmllite/tests/writer.c +++ b/dlls/xmllite/tests/writer.c @@ -841,6 +841,46 @@ static void test_bom(void) IXmlWriter_Release(writer); } +static HRESULT write_start_element(IXmlWriter *writer, const char *prefix, const char *local, + const char *uri) +{ + WCHAR *prefixW, *localW, *uriW; + HRESULT hr; + + prefixW = strdupAtoW(prefix); + localW = strdupAtoW(local); + uriW = strdupAtoW(uri); + + hr = IXmlWriter_WriteStartElement(writer, prefixW, localW, uriW); + + heap_free(prefixW); + heap_free(localW); + heap_free(uriW); + + return hr; +} + +static HRESULT write_element_string(IXmlWriter *writer, const char *prefix, const char *local, + const char *uri, const char *value) +{ + WCHAR *prefixW, *localW, *uriW, *valueW; + HRESULT hr; + + prefixW = strdupAtoW(prefix); + localW = strdupAtoW(local); + uriW = strdupAtoW(uri); + valueW = strdupAtoW(value); + + hr = IXmlWriter_WriteElementString(writer, prefixW, localW, uriW, valueW); + + heap_free(prefixW); + heap_free(localW); + heap_free(uriW); + heap_free(valueW); + + return hr; +} + static void test_WriteStartElement(void) { static const struct @@ -856,24 +896,22 @@ static void test_WriteStartElement(void) } start_element_tests[] = { - { "prefix", "local", "uri", "", "", "", "", "", "", "", "", "value"); + "" + "value" + "" + "" + "" + "= 11) + hr = write_start_element(writer, start_element_tests[i].prefix, start_element_tests[i].local, + start_element_tests[i].uri); ok(hr == start_element_tests[i].hr, "%u: unexpected hr %#x.\n", i, hr); if (SUCCEEDED(start_element_tests[i].hr)) @@ -972,56 +1018,12 @@ static void test_WriteStartElement(void) check_output(stream, start_element_tests[i].output, start_element_tests[i].todo, __LINE__); } - heap_free(prefixW); - heap_free(localW); - heap_free(uriW); - IStream_Release(stream); } IXmlWriter_Release(writer); } -static HRESULT write_element_string(IXmlWriter *writer, const char *prefix, const char *local, - const char *uri, const char *value) -{ - WCHAR *prefixW, *localW, *uriW, *valueW; - HRESULT hr; - - prefixW = strdupAtoW(prefix); - localW = strdupAtoW(local); - uriW = strdupAtoW(uri); - valueW = strdupAtoW(value); - - hr = IXmlWriter_WriteElementString(writer, prefixW, localW, uriW, valueW); - - heap_free(prefixW); - heap_free(localW); - heap_free(uriW); - heap_free(valueW); - - return hr; -} - -static HRESULT write_start_element(IXmlWriter *writer, const char *prefix, const char *local, - const char *uri) -{ - WCHAR *prefixW, *localW, *uriW; - HRESULT hr; - - prefixW = strdupAtoW(prefix); - localW = strdupAtoW(local); - uriW = strdupAtoW(uri); - - hr = IXmlWriter_WriteStartElement(writer, prefixW, localW, uriW); - - heap_free(prefixW); - heap_free(localW); - heap_free(uriW); - - return hr; -} - static void test_WriteElementString(void) { static const struct @@ -1164,10 +1166,8 @@ static void test_WriteElementString(void) IXmlWriter_Release(writer); } -static void test_writeendelement(void) +static void test_WriteEndElement(void) { - static const WCHAR aW[] = {'a',0}; - static const WCHAR bW[] = {'b',0}; IXmlWriter *writer; IStream *stream; HRESULT hr; @@ -1177,10 +1177,10 @@ static void test_writeendelement(void) stream = writer_set_output(writer); - hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL); + hr = write_start_element(writer, NULL, "a", NULL); ok(hr == S_OK, "got 0x%08x\n", hr); - hr = IXmlWriter_WriteStartElement(writer, NULL, bW, NULL); + hr = write_start_element(writer, NULL, "b", NULL); ok(hr == S_OK, "got 0x%08x\n", hr); hr = IXmlWriter_WriteEndElement(writer); @@ -1892,7 +1892,7 @@ START_TEST(writer) test_writestartdocument(); test_WriteStartElement(); test_WriteElementString(); - test_writeendelement(); + test_WriteEndElement(); test_flush(); test_omitxmldeclaration(); test_bom(); diff --git a/dlls/xmllite/writer.c b/dlls/xmllite/writer.c index e8935cd5086..31c11d93404 100644 --- a/dlls/xmllite/writer.c +++ b/dlls/xmllite/writer.c @@ -497,15 +497,9 @@ static HRESULT write_xmldecl(xmlwriter *writer, XmlStandalone standalone) return S_OK; } -static HRESULT writer_close_starttag(xmlwriter *writer) +static void writer_output_ns(xmlwriter *writer, struct element *element) { - struct element *element; struct ns *ns; - HRESULT hr; - - if (!writer->starttagopen) return S_OK; - - element = LIST_ENTRY(list_head(&writer->elements), struct element, entry); LIST_FOR_EACH_ENTRY(ns, &element->ns, struct ns, entry) { @@ -513,7 +507,15 @@ static HRESULT writer_close_starttag(xmlwriter *writer) write_output_buffer(writer->output, eqW, ARRAY_SIZE(eqW)); write_output_buffer_quoted(writer->output, ns->uri, -1); } +} +static HRESULT writer_close_starttag(xmlwriter *writer) +{ + HRESULT hr; + + if (!writer->starttagopen) return S_OK; + + writer_output_ns(writer, LIST_ENTRY(list_head(&writer->elements), struct element, entry)); hr = write_output_buffer(writer->output, gtW, ARRAY_SIZE(gtW)); writer->starttagopen = FALSE; return hr; @@ -967,6 +969,8 @@ static struct ns *writer_find_ns(xmlwriter *writer, const WCHAR *prefix, const W } else if (!strcmpW(uri, ns->uri)) { + if (prefix && !*prefix) + return NULL; if (!prefix || !strcmpW(prefix, ns->prefix)) return ns; } @@ -1114,11 +1118,13 @@ static HRESULT WINAPI xmlwriter_WriteEndElement(IXmlWriter *iface) if (This->starttagopen) { + writer_output_ns(This, element); write_output_buffer(This->output, closetagW, ARRAY_SIZE(closetagW)); This->starttagopen = FALSE; } - else { - /* write full end tag */ + else + { + /* Write full end tag. */ write_node_indent(This); write_output_buffer(This->output, closeelementW, ARRAY_SIZE(closeelementW)); write_output_buffer(This->output, element->qname, element->len); @@ -1402,6 +1408,7 @@ static HRESULT WINAPI xmlwriter_WriteStartElement(IXmlWriter *iface, LPCWSTR pre xmlwriter *This = impl_from_IXmlWriter(iface); int prefix_len, local_len; struct element *element; + struct ns *ns; HRESULT hr; TRACE("(%p)->(%s %s %s)\n", This, wine_dbgstr_w(prefix), wine_dbgstr_w(local_name), wine_dbgstr_w(uri)); @@ -1417,6 +1424,9 @@ static HRESULT WINAPI xmlwriter_WriteStartElement(IXmlWriter *iface, LPCWSTR pre return MX_E_ENCODING; case XmlWriterState_DocClosed: return WR_E_INVALIDACTION; + case XmlWriterState_ElemStarted: + writer_close_starttag(This); + break; default: ; } @@ -1428,9 +1438,16 @@ static HRESULT WINAPI xmlwriter_WriteStartElement(IXmlWriter *iface, LPCWSTR pre if (FAILED(hr = is_valid_ncname(local_name, &local_len))) return hr; - /* close pending element */ - if (This->starttagopen) - write_output_buffer(This->output, gtW, ARRAY_SIZE(gtW)); + if (uri && !strcmpW(uri, xmlnsuriW)) + { + if (!prefix) + return WR_E_XMLNSPREFIXDECLARATION; + + if (!is_empty_string(prefix)) + return WR_E_XMLNSURIDECLARATION; + } + + ns = writer_find_ns(This, prefix, uri); element = alloc_element(This, prefix, local_name); if (!element) @@ -1444,11 +1461,14 @@ static HRESULT WINAPI xmlwriter_WriteStartElement(IXmlWriter *iface, LPCWSTR pre writer_push_element(This, element); - if (prefix_len && uri) + if (!ns && uri) writer_push_ns(This, prefix, prefix_len, uri); write_output_buffer(This->output, ltW, ARRAY_SIZE(ltW)); - write_output_qname(This->output, prefix, prefix_len, local_name, local_len); + if (ns) + write_output_qname(This->output, ns->prefix, ns->prefix_len, local_name, local_len); + else + write_output_qname(This->output, prefix, prefix_len, local_name, local_len); writer_inc_indent(This); return S_OK;