Commit e77d3f59 authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

xmllite/writer: Add initial implementation of WriteNode().

parent 22c9af71
......@@ -2259,6 +2259,155 @@ static void test_WriteAttributes(void)
IXmlReader_Release(reader);
}
static void test_WriteNode(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><e2 attr1=\"a\" /></e1>", XmlNodeType_Element },
{ "<r><e1/></r>", "<w><e1 />", XmlNodeType_Element },
{ "<r></r>", "<w></w>", XmlNodeType_EndElement },
};
XmlNodeType node_type;
IXmlWriter *writer;
IXmlReader *reader;
const WCHAR *name;
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_WriteNode(writer, reader, FALSE);
ok(SUCCEEDED(hr), "Failed to write a node, hr %#lx.\n", hr);
if (hr == S_OK)
{
hr = IXmlReader_GetNodeType(reader, &node_type);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
ok(node_type == XmlNodeType_EndElement, "Unexpected node type on return %d.\n", node_type);
hr = IXmlReader_GetLocalName(reader, &name, NULL);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
ok(!wcscmp(name, L"r"), "Unexpected node name %s.\n", debugstr_w(name));
}
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_WriteNode(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_EndElement, "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_WriteNode(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_Element, "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_WriteNode(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_Element, "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_WriteNode(writer, reader, FALSE);
ok(hr == S_FALSE, "Failed to write a node, hr %#lx.\n", hr);
node_type = XmlNodeType_Element;
hr = IXmlReader_GetNodeType(reader, &node_type);
todo_wine
ok(hr == S_FALSE, "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, "<?xml version=\"1.0\" encoding=\"UTF-8\"?><a><b /></a>");
IStream_Release(stream);
IXmlReader_Release(reader);
IXmlWriter_Release(writer);
}
START_TEST(writer)
{
test_writer_create();
......@@ -2284,4 +2433,5 @@ START_TEST(writer)
test_WriteWhitespace();
test_WriteProcessingInstruction();
test_WriteAttributes();
test_WriteNode();
}
......@@ -1502,14 +1502,102 @@ static HRESULT WINAPI xmlwriter_WriteNmToken(IXmlWriter *iface, LPCWSTR pwszNmTo
return E_NOTIMPL;
}
static HRESULT WINAPI xmlwriter_WriteNode(IXmlWriter *iface, IXmlReader *pReader,
BOOL fWriteDefaultAttributes)
static HRESULT writer_write_node(IXmlWriter *writer, IXmlReader *reader, BOOL write_default_attributes)
{
xmlwriter *This = impl_from_IXmlWriter(iface);
XmlStandalone standalone = XmlStandalone_Omit;
const WCHAR *name, *value, *prefix, *uri;
unsigned int start_depth = 0, depth;
XmlNodeType node_type;
HRESULT hr;
FIXME("%p %p %d\n", This, pReader, fWriteDefaultAttributes);
if (FAILED(hr = IXmlReader_GetNodeType(reader, &node_type))) return hr;
return E_NOTIMPL;
switch (node_type)
{
case XmlNodeType_None:
while ((hr = IXmlReader_Read(reader, NULL)) == S_OK)
{
if (FAILED(hr = writer_write_node(writer, reader, write_default_attributes))) return hr;
}
break;
case XmlNodeType_Element:
if (FAILED(hr = IXmlReader_GetPrefix(reader, &prefix, NULL))) return hr;
if (FAILED(hr = IXmlReader_GetLocalName(reader, &name, NULL))) return hr;
if (FAILED(hr = IXmlReader_GetNamespaceUri(reader, &uri, NULL))) return hr;
if (FAILED(hr = IXmlWriter_WriteStartElement(writer, prefix, name, uri))) return hr;
if (FAILED(hr = IXmlWriter_WriteAttributes(writer, reader, write_default_attributes))) return hr;
if (IXmlReader_IsEmptyElement(reader))
{
hr = IXmlWriter_WriteEndElement(writer);
}
else
{
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 = IXmlReader_MoveToElement(reader))) return hr;
depth = 0;
if (FAILED(hr = IXmlReader_GetDepth(reader, &depth))) return hr;
if (node_type == XmlNodeType_EndElement && (start_depth == depth - 1)) break;
}
}
break;
case XmlNodeType_Attribute:
break;
case XmlNodeType_Text:
if (FAILED(hr = IXmlReader_GetValue(reader, &value, NULL))) return hr;
hr = IXmlWriter_WriteRaw(writer, value);
break;
case XmlNodeType_CDATA:
if (FAILED(hr = IXmlReader_GetValue(reader, &value, NULL))) return hr;
hr = IXmlWriter_WriteCData(writer, value);
break;
case XmlNodeType_ProcessingInstruction:
if (FAILED(hr = IXmlReader_GetLocalName(reader, &name, NULL))) return hr;
if (FAILED(hr = IXmlReader_GetValue(reader, &value, NULL))) return hr;
hr = IXmlWriter_WriteProcessingInstruction(writer, name, value);
break;
case XmlNodeType_Comment:
if (FAILED(hr = IXmlReader_GetValue(reader, &value, NULL))) return hr;
hr = IXmlWriter_WriteComment(writer, value);
break;
case XmlNodeType_Whitespace:
if (FAILED(hr = IXmlReader_GetValue(reader, &value, NULL))) return hr;
hr = IXmlWriter_WriteWhitespace(writer, value);
break;
case XmlNodeType_EndElement:
hr = IXmlWriter_WriteFullEndElement(writer);
break;
case XmlNodeType_XmlDeclaration:
if (FAILED(hr = IXmlReader_MoveToAttributeByName(reader, L"standalone", NULL))) return hr;
if (hr == S_OK)
{
if (FAILED(hr = IXmlReader_GetValue(reader, &value, NULL))) return hr;
standalone = !wcscmp(value, L"yes") ? XmlStandalone_Yes : XmlStandalone_No;
}
hr = IXmlWriter_WriteStartDocument(writer, standalone);
break;
default:
WARN("Unknown node type %d.\n", node_type);
return E_UNEXPECTED;
}
return hr;
}
static HRESULT WINAPI xmlwriter_WriteNode(IXmlWriter *iface, IXmlReader *reader, BOOL write_default_attributes)
{
HRESULT hr;
TRACE("%p, %p, %d.\n", iface, reader, write_default_attributes);
if (SUCCEEDED(hr = writer_write_node(iface, reader, write_default_attributes)))
hr = IXmlReader_Read(reader, NULL);
return hr;
}
static HRESULT WINAPI xmlwriter_WriteNodeShallow(IXmlWriter *iface, IXmlReader *pReader,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment