From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/xmllite/tests/writer.c | 144 ++++++++++++++++++++++++++++++++++++ dlls/xmllite/writer.c | 33 +++++---- 2 files changed, 162 insertions(+), 15 deletions(-)
diff --git a/dlls/xmllite/tests/writer.c b/dlls/xmllite/tests/writer.c index ceadb4c937e..25dc9e3b8c1 100644 --- a/dlls/xmllite/tests/writer.c +++ b/dlls/xmllite/tests/writer.c @@ -2414,6 +2414,149 @@ static void test_WriteNode(void) IXmlWriter_Release(writer); }
+static void test_WriteNodeShallow(void) +{ + static const struct + { + const char *input; + const char *output; + XmlNodeType node_type; + } + write_node_tests[] = + { + { "<r><!-- comment --></r>", "<w><!-- comment -->", XmlNodeType_Comment }, + { "<r>text</r>", "<w>text", XmlNodeType_Text }, + { "<r> </r>", "<w> ", XmlNodeType_Whitespace }, + { "<r><![CDATA[ cdata ]]></r>", "<w><![CDATA[ cdata ]]>", XmlNodeType_CDATA }, + { "<r><?pi pidata ?></r>", "<w><?pi pidata ?>", XmlNodeType_ProcessingInstruction }, + { "<r><e1><e2 attr1='a'/></e1></r>", "<w><e1", XmlNodeType_Element }, + { "<r><e1/></r>", "<w><e1 />", XmlNodeType_Element }, + { "<r><e1 attr1='a'/></r>", "<w><e1 attr1="a" />", XmlNodeType_Element }, + { "<r><e1 attr1='a'></e1></r>", "<w><e1 attr1="a"", XmlNodeType_Element }, + { "<r></r>", "<w></w>", XmlNodeType_EndElement }, + }; + XmlNodeType node_type; + IXmlWriter *writer; + IXmlReader *reader; + IStream *stream; + unsigned int i; + HRESULT hr; + + hr = CreateXmlWriter(&IID_IXmlWriter, (void **)&writer, NULL); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + for (i = 0; i < ARRAY_SIZE(write_node_tests); ++i) + { + winetest_push_context("Test %s", debugstr_a(write_node_tests[i].input)); + + stream = writer_set_output(writer); + reader_set_input(reader, write_node_tests[i].input); + + /* Skip top level element. */ + hr = IXmlReader_Read(reader, &node_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = IXmlReader_Read(reader, &node_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(node_type == write_node_tests[i].node_type, "Unexpected node type %d.\n", node_type); + + /* Always write a root node to give a valid context for following nodes. */ + hr = IXmlWriter_WriteStartElement(writer, NULL, L"w", NULL); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IXmlWriter_WriteNodeShallow(writer, reader, FALSE); + ok(hr == S_OK, "Failed to write a node, hr %#lx.\n", hr); + + hr = IXmlReader_GetNodeType(reader, &node_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(node_type == write_node_tests[i].node_type, "Unexpected node type on return %d.\n", node_type); + + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr); + + CHECK_OUTPUT(stream, write_node_tests[i].output); + + IStream_Release(stream); + + winetest_pop_context(); + } + + /* Current node is an attribute. */ + reader_set_input(reader, "<a attr='b' ></a>"); + hr = IXmlReader_Read(reader, &node_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(node_type == XmlNodeType_Element, "Unexpected node type on return %d.\n", node_type); + hr = IXmlReader_MoveToFirstAttribute(reader); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + stream = writer_set_output(writer); + hr = IXmlWriter_WriteNodeShallow(writer, reader, FALSE); + ok(hr == S_OK, "Failed to write a node, hr %#lx.\n", hr); + hr = IXmlReader_GetNodeType(reader, &node_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(node_type == XmlNodeType_Attribute, "Unexpected node type on return %d.\n", node_type); + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr); + CHECK_OUTPUT(stream, ""); + IStream_Release(stream); + + /* Xml declaration node. */ + reader_set_input(reader, "<?xml version=\"1.0\" ?><a/>"); + hr = IXmlReader_Read(reader, &node_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(node_type == XmlNodeType_XmlDeclaration, "Unexpected node type on return %d.\n", node_type); + + stream = writer_set_output(writer); + hr = IXmlWriter_WriteNodeShallow(writer, reader, FALSE); + ok(hr == S_OK, "Failed to write a node, hr %#lx.\n", hr); + hr = IXmlReader_GetNodeType(reader, &node_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(node_type == XmlNodeType_Attribute, "Unexpected node type on return %d.\n", node_type); + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr); + CHECK_OUTPUT(stream, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); + IStream_Release(stream); + + /* With standalone attribute. */ + reader_set_input(reader, "<?xml version=\"1.0\" standalone=\'yes\'?><a/>"); + hr = IXmlReader_Read(reader, &node_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(node_type == XmlNodeType_XmlDeclaration, "Unexpected node type on return %d.\n", node_type); + + stream = writer_set_output(writer); + hr = IXmlWriter_WriteNodeShallow(writer, reader, FALSE); + ok(hr == S_OK, "Failed to write a node, hr %#lx.\n", hr); + hr = IXmlReader_GetNodeType(reader, &node_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(node_type == XmlNodeType_Attribute, "Unexpected node type on return %d.\n", node_type); + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr); + CHECK_OUTPUT(stream, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"); + IStream_Release(stream); + + /* Initial state. */ + reader_set_input(reader, "<?xml version=\"1.0\" ?><a><b/></a>"); + hr = IXmlReader_GetNodeType(reader, &node_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(node_type == XmlNodeType_None, "Unexpected node type on return %d.\n", node_type); + stream = writer_set_output(writer); + hr = IXmlWriter_WriteNodeShallow(writer, reader, FALSE); + ok(hr == S_OK, "Failed to write a node, hr %#lx.\n", hr); + node_type = XmlNodeType_Element; + hr = IXmlReader_GetNodeType(reader, &node_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(node_type == XmlNodeType_None, "Unexpected node type on return %d.\n", node_type); + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr); + CHECK_OUTPUT(stream, ""); + IStream_Release(stream); + + IXmlReader_Release(reader); + IXmlWriter_Release(writer); +} + START_TEST(writer) { test_writer_create(); @@ -2440,4 +2583,5 @@ START_TEST(writer) test_WriteProcessingInstruction(); test_WriteAttributes(); test_WriteNode(); + test_WriteNodeShallow(); } diff --git a/dlls/xmllite/writer.c b/dlls/xmllite/writer.c index 423cf9670d8..fb2784ab439 100644 --- a/dlls/xmllite/writer.c +++ b/dlls/xmllite/writer.c @@ -1502,7 +1502,7 @@ static HRESULT WINAPI xmlwriter_WriteNmToken(IXmlWriter *iface, LPCWSTR pwszNmTo return E_NOTIMPL; }
-static HRESULT writer_write_node(IXmlWriter *writer, IXmlReader *reader, BOOL write_default_attributes) +static HRESULT writer_write_node(IXmlWriter *writer, IXmlReader *reader, BOOL shallow, BOOL write_default_attributes) { XmlStandalone standalone = XmlStandalone_Omit; const WCHAR *name, *value, *prefix, *uri; @@ -1515,9 +1515,10 @@ static HRESULT writer_write_node(IXmlWriter *writer, IXmlReader *reader, BOOL wr switch (node_type) { case XmlNodeType_None: + if (shallow) return S_OK; while ((hr = IXmlReader_Read(reader, NULL)) == S_OK) { - if (FAILED(hr = writer_write_node(writer, reader, write_default_attributes))) return hr; + if (FAILED(hr = writer_write_node(writer, reader, FALSE, write_default_attributes))) return hr; } break; case XmlNodeType_Element: @@ -1532,11 +1533,12 @@ static HRESULT writer_write_node(IXmlWriter *writer, IXmlReader *reader, BOOL wr } else { + if (shallow) return S_OK; if (FAILED(hr = IXmlReader_MoveToElement(reader))) return hr; if (FAILED(hr = IXmlReader_GetDepth(reader, &start_depth))) return hr; while ((hr = IXmlReader_Read(reader, &node_type)) == S_OK) { - if (FAILED(hr = writer_write_node(writer, reader, write_default_attributes))) return hr; + if (FAILED(hr = writer_write_node(writer, reader, FALSE, write_default_attributes))) return hr; if (FAILED(hr = IXmlReader_MoveToElement(reader))) return hr;
depth = 0; @@ -1572,13 +1574,17 @@ static HRESULT writer_write_node(IXmlWriter *writer, IXmlReader *reader, BOOL wr hr = IXmlWriter_WriteFullEndElement(writer); break; case XmlNodeType_XmlDeclaration: - if (FAILED(hr = IXmlReader_MoveToAttributeByName(reader, L"standalone", NULL))) return hr; - if (hr == S_OK) + while ((hr = IXmlReader_MoveToNextAttribute(reader)) == S_OK) { - if (FAILED(hr = IXmlReader_GetValue(reader, &value, NULL))) return hr; - standalone = !wcscmp(value, L"yes") ? XmlStandalone_Yes : XmlStandalone_No; + if (FAILED(hr = IXmlReader_GetLocalName(reader, &name, NULL))) return hr; + if (!wcscmp(name, L"standalone")) + { + if (FAILED(hr = IXmlReader_GetValue(reader, &value, NULL))) return hr; + standalone = !wcscmp(value, L"yes") ? XmlStandalone_Yes : XmlStandalone_No; + } } - hr = IXmlWriter_WriteStartDocument(writer, standalone); + if (SUCCEEDED(hr)) + hr = IXmlWriter_WriteStartDocument(writer, standalone); break; default: WARN("Unknown node type %d.\n", node_type); @@ -1594,20 +1600,17 @@ static HRESULT WINAPI xmlwriter_WriteNode(IXmlWriter *iface, IXmlReader *reader,
TRACE("%p, %p, %d.\n", iface, reader, write_default_attributes);
- if (SUCCEEDED(hr = writer_write_node(iface, reader, write_default_attributes))) + if (SUCCEEDED(hr = writer_write_node(iface, reader, FALSE, write_default_attributes))) hr = IXmlReader_Read(reader, NULL);
return hr; }
-static HRESULT WINAPI xmlwriter_WriteNodeShallow(IXmlWriter *iface, IXmlReader *pReader, - BOOL fWriteDefaultAttributes) +static HRESULT WINAPI xmlwriter_WriteNodeShallow(IXmlWriter *iface, IXmlReader *reader, BOOL write_default_attributes) { - xmlwriter *This = impl_from_IXmlWriter(iface); - - FIXME("%p %p %d\n", This, pReader, fWriteDefaultAttributes); + TRACE("%p, %p, %d.\n", iface, reader, write_default_attributes);
- return E_NOTIMPL; + return writer_write_node(iface, reader, TRUE, write_default_attributes); }
static HRESULT WINAPI xmlwriter_WriteProcessingInstruction(IXmlWriter *iface, LPCWSTR name,