[PATCH 2/3] xmllite/writer: Improve namespaces handling in WriteStartElement().
Nikolay Sivov
nsivov at codeweavers.com
Tue Sep 11 05:17:06 CDT 2018
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
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 9331899a19..87cdaabce1 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", "<prefix:local xmlns:prefix=\"uri\" />", "<prefix:local", S_OK, 1 },
- { NULL, "local", "uri", "<local xmlns=\"uri\" />", "<local", S_OK, 1 },
- { "", "local", "uri", "<local xmlns=\"uri\" />", "<local", S_OK, 1 },
- { "", "local", "uri", "<local xmlns=\"uri\" />", "<local", S_OK, 1 },
+ { "prefix", "local", "uri", "<prefix:local xmlns:prefix=\"uri\" />", "<prefix:local" },
+ { NULL, "local", "uri", "<local xmlns=\"uri\" />", "<local" },
+ { "", "local", "uri", "<local xmlns=\"uri\" />", "<local" },
+ { "", "local", "uri", "<local xmlns=\"uri\" />", "<local" },
{ "prefix", NULL, NULL, NULL, NULL, E_INVALIDARG },
{ NULL, NULL, "uri", NULL, NULL, E_INVALIDARG },
{ NULL, NULL, NULL, NULL, NULL, E_INVALIDARG },
- { NULL, "prefix:local", "uri", NULL, NULL, WC_E_NAMECHARACTER, 1, 1 },
- { "pre:fix", "local", "uri", NULL, NULL, WC_E_NAMECHARACTER, 1, 1 },
- { NULL, ":local", "uri", NULL, NULL, WC_E_NAMECHARACTER, 1, 1 },
- { ":", "local", "uri", NULL, NULL, WC_E_NAMECHARACTER, 1, 1 },
+ { NULL, "prefix:local", "uri", NULL, NULL, WC_E_NAMECHARACTER },
+ { "pre:fix", "local", "uri", NULL, NULL, WC_E_NAMECHARACTER },
+ { NULL, ":local", "uri", NULL, NULL, WC_E_NAMECHARACTER },
+ { ":", "local", "uri", NULL, NULL, WC_E_NAMECHARACTER },
{ NULL, "local", "http://www.w3.org/2000/xmlns/", NULL, NULL, WR_E_XMLNSPREFIXDECLARATION },
{ "prefix", "local", "http://www.w3.org/2000/xmlns/", NULL, NULL, WR_E_XMLNSURIDECLARATION },
};
- static const WCHAR valueW[] = {'v','a','l','u','e',0};
static const WCHAR aW[] = {'a',0};
- static const WCHAR bW[] = {'b',0};
IXmlWriter *writer;
IStream *stream;
unsigned int i;
@@ -882,12 +920,12 @@ static void test_WriteStartElement(void)
hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
- hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
+ hr = write_start_element(writer, NULL, "a", NULL);
ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
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_WriteStartDocument(writer, XmlStandalone_Yes);
@@ -914,33 +952,45 @@ static void test_WriteStartElement(void)
hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
- hr = IXmlWriter_WriteElementString(writer, NULL, bW, NULL, valueW);
+ hr = write_element_string(writer, NULL, "b", NULL, "value");
ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
stream = writer_set_output(writer);
- hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
- ok(hr == S_OK, "got 0x%08x\n", hr);
+ hr = write_start_element(writer, "prefix", "a", "uri");
+ ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
- hr = IXmlWriter_WriteElementString(writer, NULL, bW, NULL, valueW);
- ok(hr == S_OK, "got 0x%08x\n", hr);
+ hr = write_element_string(writer, NULL, "b", NULL, "value");
+ ok(hr == S_OK, "Failed to write element string, hr %#x.\n", hr);
- hr = IXmlWriter_WriteElementString(writer, NULL, bW, NULL, NULL);
- ok(hr == S_OK, "got 0x%08x\n", hr);
+ hr = write_element_string(writer, NULL, "c", NULL, NULL);
+ ok(hr == S_OK, "Failed to write element string, hr %#x.\n", hr);
+
+ hr = write_start_element(writer, NULL, "d", "uri");
+ ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
+
+ hr = write_start_element(writer, "", "e", "uri");
+ ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
+
+ hr = write_start_element(writer, "prefix2", "f", "uri");
+ ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
hr = IXmlWriter_Flush(writer);
ok(hr == S_OK, "got 0x%08x\n", hr);
CHECK_OUTPUT(stream,
- "<a><b>value</b><b />");
+ "<prefix:a xmlns:prefix=\"uri\">"
+ "<b>value</b>"
+ "<c />"
+ "<prefix:d>"
+ "<e xmlns=\"uri\">"
+ "<prefix2:f");
IStream_Release(stream);
/* WriteStartElement */
for (i = 0; i < ARRAY_SIZE(start_element_tests); ++i)
{
- WCHAR *prefixW, *localW, *uriW;
-
stream = writer_set_output(writer);
writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
@@ -948,12 +998,8 @@ static void test_WriteStartElement(void)
hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
ok(hr == S_OK, "Failed to start document, hr %#x.\n", hr);
- prefixW = strdupAtoW(start_element_tests[i].prefix);
- localW = strdupAtoW(start_element_tests[i].local);
- uriW = strdupAtoW(start_element_tests[i].uri);
-
- hr = IXmlWriter_WriteStartElement(writer, prefixW, localW, uriW);
- todo_wine_if(i >= 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 e8935cd508..31c11d9340 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;
--
2.18.0
More information about the wine-devel
mailing list