Nikolay Sivov : xmllite/writer: Fix formatted output with interleaving text nodes.

Alexandre Julliard julliard at winehq.org
Fri Sep 14 14:20:59 CDT 2018


Module: wine
Branch: master
Commit: ef7b911a620d13cd5b921a35feeb86927d4933d3
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=ef7b911a620d13cd5b921a35feeb86927d4933d3

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Fri Sep 14 13:06:47 2018 +0300

xmllite/writer: Fix formatted output with interleaving text nodes.

Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/xmllite/tests/writer.c | 87 +++++++++++++++++++++++++++++++++++++++++++++
 dlls/xmllite/writer.c       | 24 ++++++++-----
 2 files changed, 103 insertions(+), 8 deletions(-)

diff --git a/dlls/xmllite/tests/writer.c b/dlls/xmllite/tests/writer.c
index 42b534f..7f731be 100644
--- a/dlls/xmllite/tests/writer.c
+++ b/dlls/xmllite/tests/writer.c
@@ -1981,6 +1981,93 @@ static void test_WriteString(void)
         "  <b>text</b>\r\n"
         "</a>");
 
+    IStream_Release(stream);
+
+    stream = writer_set_output(writer);
+
+    hr = write_start_element(writer, NULL, "a", NULL);
+    ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
+
+    hr = write_start_element(writer, NULL, "b", NULL);
+    ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
+
+    hr = IXmlWriter_WriteEndElement(writer);
+    ok(hr == S_OK, "Failed to end element, hr %#x.\n", hr);
+
+    hr = IXmlWriter_Flush(writer);
+    ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
+
+    CHECK_OUTPUT(stream,
+        "<a>\r\n"
+        "  <b />");
+
+    hr = write_start_element(writer, NULL, "c", NULL);
+    ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
+
+    hr = write_attribute_string(writer, NULL, "attr", NULL, "value");
+    ok(hr == S_OK, "Failed to write attribute string, hr %#x.\n", hr);
+
+    hr = IXmlWriter_Flush(writer);
+    ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
+
+    CHECK_OUTPUT(stream,
+        "<a>\r\n"
+        "  <b />\r\n"
+        "  <c attr=\"value\"");
+
+    hr = write_string(writer, "text");
+    ok(hr == S_OK, "Failed to write a string, hr %#x.\n", hr);
+
+    hr = IXmlWriter_Flush(writer);
+    ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
+
+    CHECK_OUTPUT(stream,
+        "<a>\r\n"
+        "  <b />\r\n"
+        "  <c attr=\"value\">text");
+
+    hr = IXmlWriter_WriteEndElement(writer);
+    ok(hr == S_OK, "Failed to end element, hr %#x.\n", hr);
+
+    hr = IXmlWriter_Flush(writer);
+    ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
+
+    CHECK_OUTPUT(stream,
+        "<a>\r\n"
+        "  <b />\r\n"
+        "  <c attr=\"value\">text</c>");
+
+    hr = write_start_element(writer, NULL, "d", NULL);
+    ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
+
+    hr = write_string(writer, "");
+    ok(hr == S_OK, "Failed to write a string, hr %#x.\n", hr);
+
+    hr = IXmlWriter_WriteEndElement(writer);
+    ok(hr == S_OK, "Failed to end element, hr %#x.\n", hr);
+
+    hr = IXmlWriter_Flush(writer);
+    ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
+
+    CHECK_OUTPUT(stream,
+        "<a>\r\n"
+        "  <b />\r\n"
+        "  <c attr=\"value\">text</c>\r\n"
+        "  <d></d>");
+
+    hr = IXmlWriter_WriteEndElement(writer);
+    ok(hr == S_OK, "Failed to end element, hr %#x.\n", hr);
+
+    hr = IXmlWriter_Flush(writer);
+    ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
+
+    CHECK_OUTPUT(stream,
+        "<a>\r\n"
+        "  <b />\r\n"
+        "  <c attr=\"value\">text</c>\r\n"
+        "  <d></d>\r\n"
+        "</a>");
+
     IXmlWriter_Release(writer);
     IStream_Release(stream);
 }
diff --git a/dlls/xmllite/writer.c b/dlls/xmllite/writer.c
index 94e1f2f..f0eac77 100644
--- a/dlls/xmllite/writer.c
+++ b/dlls/xmllite/writer.c
@@ -118,6 +118,7 @@ typedef struct _xmlwriter
     struct list elements;
     DWORD bomwritten : 1;
     DWORD starttagopen : 1;
+    DWORD textnode : 1;
 } xmlwriter;
 
 static inline xmlwriter *impl_from_IXmlWriter(IXmlWriter *iface)
@@ -626,8 +627,11 @@ static void write_node_indent(xmlwriter *writer)
     static const WCHAR crlfW[] = {'\r','\n'};
     unsigned int indent_level = writer->indent_level;
 
-    if (!writer->indent)
+    if (!writer->indent || writer->textnode)
+    {
+        writer->textnode = 0;
         return;
+    }
 
     /* Do state check to prevent newline inserted after BOM. It is assumed that
        state does not change between writing BOM and inserting indentation. */
@@ -635,6 +639,8 @@ static void write_node_indent(xmlwriter *writer)
         write_output_buffer(writer->output, crlfW, ARRAY_SIZE(crlfW));
     while (indent_level--)
         write_output_buffer(writer->output, dblspaceW, ARRAY_SIZE(dblspaceW));
+
+    writer->textnode = 0;
 }
 
 static HRESULT WINAPI xmlwriter_QueryInterface(IXmlWriter *iface, REFIID riid, void **ppvObject)
@@ -704,6 +710,7 @@ static HRESULT WINAPI xmlwriter_SetOutput(IXmlWriter *iface, IUnknown *output)
         IUnknown_Release(&This->output->IXmlWriterOutput_iface);
         This->output = NULL;
         This->bomwritten = 0;
+        This->textnode = 0;
         This->indent_level = 0;
         writer_free_element_stack(This);
     }
@@ -1281,7 +1288,10 @@ static HRESULT WINAPI xmlwriter_WriteFullEndElement(IXmlWriter *iface)
 
     /* don't force full end tag to the next line */
     if (This->state == XmlWriterState_ElemStarted)
+    {
         This->state = XmlWriterState_Content;
+        This->textnode = 0;
+    }
     else
         write_node_indent(This);
 
@@ -1623,6 +1633,7 @@ static HRESULT WINAPI xmlwriter_WriteString(IXmlWriter *iface, const WCHAR *stri
         ;
     }
 
+    This->textnode = 1;
     write_escaped_string(This, string);
     return S_OK;
 }
@@ -1761,21 +1772,18 @@ HRESULT WINAPI CreateXmlWriter(REFIID riid, void **obj, IMalloc *imalloc)
         writer = IMalloc_Alloc(imalloc, sizeof(*writer));
     else
         writer = heap_alloc(sizeof(*writer));
-    if(!writer) return E_OUTOFMEMORY;
+    if (!writer)
+        return E_OUTOFMEMORY;
+
+    memset(writer, 0, sizeof(*writer));
 
     writer->IXmlWriter_iface.lpVtbl = &xmlwriter_vtbl;
     writer->ref = 1;
     writer->imalloc = imalloc;
     if (imalloc) IMalloc_AddRef(imalloc);
-    writer->output = NULL;
-    writer->indent_level = 0;
-    writer->indent = FALSE;
     writer->bom = TRUE;
-    writer->omitxmldecl = FALSE;
     writer->conformance = XmlConformanceLevel_Document;
     writer->state = XmlWriterState_Initial;
-    writer->bomwritten = 0;
-    writer->starttagopen = 0;
     list_init(&writer->elements);
 
     hr = IXmlWriter_QueryInterface(&writer->IXmlWriter_iface, riid, obj);




More information about the wine-cvs mailing list