xmllite/writer: Improve namespaces handling in WriteStartElement().
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
8eb054f328
commit
a86e2a4a3f
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue