[PATCH V3 2/2] msxml3: Implement SAXContentHandler methods for DOMDocument mxwriter output.
Jefferson Carpenter
jeffersoncarpenter2 at gmail.com
Fri Jan 22 20:33:43 CST 2021
From b9c54a002b1500e28ae8af0e7936889f2b9d978b Mon Sep 17 00:00:00 2001
From: Jefferson Carpenter <jeffersoncarpenter2 at gmail.com>
Date: Sat, 23 Jan 2021 03:46:31 +0000
Subject: [PATCH 2/2] msxml3: Implement SAXContentHandler methods for
DOMDocument mxwriter output.
Changes from last version:
Added FIXME and return E_NOTIMPL statements to the SAX handler methods
I did NOT implement: in particular, LexicalHandler, DeclHandler, and
DTDHandler, as well as IXMWriter::get_output. This way mxwriter will
not fail silently when those methods are called and the output is a
DOMDocument.
Signed-off-by: Jefferson Carpenter <jeffersoncarpenter2 at gmail.com>
---
dlls/msxml3/mxwriter.c | 765 +++++++++++++++++++++++++---------
dlls/msxml3/tests/saxreader.c | 62 +--
2 files changed, 591 insertions(+), 236 deletions(-)
diff --git a/dlls/msxml3/mxwriter.c b/dlls/msxml3/mxwriter.c
index 029e9aac0d0..0a979fbe89a 100644
--- a/dlls/msxml3/mxwriter.c
+++ b/dlls/msxml3/mxwriter.c
@@ -142,6 +142,13 @@ typedef enum
EscapeText
} escape_mode;
+typedef enum
+{
+ OutputIStream,
+ OutputString,
+ OutputDOMDocument,
+} output_type;
+
typedef struct
{
struct list entry;
@@ -193,7 +200,11 @@ typedef struct
we don't have to close */
BSTR element;
+ IXMLDOMNode *cur_node; /* current node for DOMDocument destination */
+
+ output_type output_ty;
IStream *dest;
+ IXMLDOMDocument *dest_doc;
output_buffer buffer;
} mxwriter;
@@ -715,6 +726,32 @@ static HRESULT writer_get_property(const mxwriter *writer, mxwriter_prop propert
return S_OK;
}
+static void push_cur_node(mxwriter *writer, IXMLDOMNode *node)
+{
+ if (writer->cur_node) {
+ IXMLDOMNode_Release(writer->cur_node);
+ }
+
+ IXMLDOMNode_AddRef(node);
+ writer->cur_node = node;
+}
+
+static HRESULT pop_cur_node(mxwriter *writer)
+{
+ HRESULT hr;
+ IXMLDOMNode *parent_node = NULL;
+
+ if (!writer->cur_node) return E_INVALIDARG;
+
+ hr = IXMLDOMNode_get_parentNode(writer->cur_node, &parent_node);
+ if (FAILED(hr)) return hr;
+
+ IXMLDOMNode_Release(writer->cur_node);
+ writer->cur_node = parent_node;
+
+ return S_OK;
+}
+
static inline mxwriter *impl_from_IMXWriter(IMXWriter *iface)
{
return CONTAINING_RECORD(iface, mxwriter, IMXWriter_iface);
@@ -863,6 +900,9 @@ static ULONG WINAPI mxwriter_Release(IMXWriter *iface)
free_output_buffer(&This->buffer);
if (This->dest) IStream_Release(This->dest);
+ while (!FAILED(pop_cur_node(This)));
+ if (This->dest_doc) IXMLDOMDocument_Release(This->dest_doc);
+
SysFreeString(This->version);
SysFreeString(This->encoding);
@@ -926,8 +966,14 @@ static HRESULT WINAPI mxwriter_put_output(IMXWriter *iface, VARIANT dest)
case VT_EMPTY:
{
if (This->dest) IStream_Release(This->dest);
+ while (!FAILED(pop_cur_node(This)));
+ if (This->dest_doc) IXMLDOMDocument_Release(This->dest_doc);
+
This->dest = NULL;
+ This->dest_doc = NULL;
+
reset_output_buffer(This);
+ This->output_ty = OutputString;
break;
}
case VT_UNKNOWN:
@@ -941,13 +987,41 @@ static HRESULT WINAPI mxwriter_put_output(IMXWriter *iface, VARIANT dest)
reset_output_buffer(This);
if (This->dest) IStream_Release(This->dest);
+ while (!FAILED(pop_cur_node(This)));
+ if (This->dest_doc) IXMLDOMDocument_Release(This->dest_doc);
+
This->dest = stream;
+ This->dest_doc = NULL;
+ This->output_ty = OutputIStream;
break;
}
FIXME("unhandled interface type for VT_UNKNOWN destination\n");
return E_NOTIMPL;
}
+ case VT_DISPATCH:
+ {
+ IXMLDOMDocument *document;
+
+ hr = IDispatch_QueryInterface(V_DISPATCH(&dest), &IID_IXMLDOMDocument, (void**)&document);
+ if (hr == S_OK) {
+ /* Reset output buffer to initial state. */
+ reset_output_buffer(This);
+
+ if (This->dest) IStream_Release(This->dest);
+ while (!FAILED(pop_cur_node(This)));
+ if (This->dest_doc) IXMLDOMDocument_Release(This->dest_doc);
+
+ This->dest = NULL;
+ This->dest_doc = document;
+ push_cur_node(This, (IXMLDOMNode*)document);
+ This->output_ty = OutputDOMDocument;
+ break;
+ }
+
+ FIXME("unhandled interface type for VT_DISPATCH destination\n");
+ return E_NOTIMPL;
+ }
default:
FIXME("unhandled destination type %s\n", debugstr_variant(&dest));
return E_NOTIMPL;
@@ -971,6 +1045,11 @@ static HRESULT WINAPI mxwriter_get_output(IMXWriter *iface, VARIANT *dest)
V_UNKNOWN(dest) = (IUnknown*)This->dest;
IStream_AddRef(This->dest);
}
+ else if (This->dest_doc)
+ {
+ FIXME("(%p)->(%p)\n", This, dest);
+ return E_NOTIMPL;
+ }
else
{
encoded_buffer *buff;
@@ -1223,28 +1302,36 @@ static HRESULT WINAPI SAXContentHandler_startDocument(ISAXContentHandler *iface)
TRACE("(%p)\n", This);
- /* If properties have been changed since the last "endDocument" call
- * we need to reset the output buffer. If we don't the output buffer
- * could end up with multiple XML documents in it, plus this seems to
- * be how Windows works.
- */
- if (This->prop_changed) {
- reset_output_buffer(This);
- This->prop_changed = FALSE;
- }
+ switch (This->output_ty)
+ {
+ case OutputIStream:
+ case OutputString:
+ /* If properties have been changed since the last "endDocument" call
+ * we need to reset the output buffer. If we don't the output buffer
+ * could end up with multiple XML documents in it, plus this seems to
+ * be how Windows works.
+ */
+ if (This->prop_changed) {
+ reset_output_buffer(This);
+ This->prop_changed = FALSE;
+ }
- if (This->props[MXWriter_OmitXmlDecl] == VARIANT_TRUE) return S_OK;
+ if (This->props[MXWriter_OmitXmlDecl] == VARIANT_TRUE) return S_OK;
- write_prolog_buffer(This);
+ write_prolog_buffer(This);
- if (This->dest && This->xml_enc == XmlEncoding_UTF16) {
- static const char utf16BOM[] = {0xff,0xfe};
+ if (This->dest && This->xml_enc == XmlEncoding_UTF16) {
+ static const char utf16BOM[] = {0xff,0xfe};
- if (This->props[MXWriter_BOM] == VARIANT_TRUE)
- /* Windows passes a NULL pointer as the pcbWritten parameter and
- * ignores any error codes returned from this Write call.
- */
- IStream_Write(This->dest, utf16BOM, sizeof(utf16BOM), NULL);
+ if (This->props[MXWriter_BOM] == VARIANT_TRUE)
+ /* Windows passes a NULL pointer as the pcbWritten parameter and
+ * ignores any error codes returned from this Write call.
+ */
+ IStream_Write(This->dest, utf16BOM, sizeof(utf16BOM), NULL);
+ }
+ break;
+ case OutputDOMDocument:
+ break;
}
return S_OK;
@@ -1254,7 +1341,15 @@ static HRESULT WINAPI SAXContentHandler_endDocument(ISAXContentHandler *iface)
{
mxwriter *This = impl_from_ISAXContentHandler( iface );
TRACE("(%p)\n", This);
- This->prop_changed = FALSE;
+ switch (This->output_ty)
+ {
+ case OutputIStream:
+ case OutputString:
+ This->prop_changed = FALSE;
+ break;
+ case OutputDOMDocument:
+ break;
+ }
return flush_output_buffer(This);
}
@@ -1333,32 +1428,96 @@ static HRESULT WINAPI SAXContentHandler_startElement(
(nQName == -1 && This->class_version == MSXML6))
return E_INVALIDARG;
- mxwriter_write_starttag(This, QName, nQName);
+ switch (This->output_ty) {
+ case OutputIStream:
+ case OutputString:
+ mxwriter_write_starttag(This, QName, nQName);
- if (attr)
- {
- int length, i, escape;
- HRESULT hr;
+ if (attr)
+ {
+ int length, i, escape;
+ HRESULT hr;
- hr = ISAXAttributes_getLength(attr, &length);
- if (FAILED(hr)) return hr;
+ hr = ISAXAttributes_getLength(attr, &length);
+ if (FAILED(hr)) return hr;
- escape = This->props[MXWriter_DisableEscaping] == VARIANT_FALSE ||
+ escape = This->props[MXWriter_DisableEscaping] == VARIANT_FALSE ||
(This->class_version == MSXML4 || This->class_version == MSXML6);
- for (i = 0; i < length; i++)
- {
- int qname_len = 0, value_len = 0;
- const WCHAR *qname, *value;
+ for (i = 0; i < length; i++)
+ {
+ int qname_len = 0, value_len = 0;
+ const WCHAR *qname, *value;
- hr = ISAXAttributes_getQName(attr, i, &qname, &qname_len);
- if (FAILED(hr)) return hr;
+ hr = ISAXAttributes_getQName(attr, i, &qname, &qname_len);
+ if (FAILED(hr)) return hr;
+
+ hr = ISAXAttributes_getValue(attr, i, &value, &value_len);
+ if (FAILED(hr)) return hr;
+
+ mxwriter_write_attribute(This, qname, qname_len, value, value_len, escape);
+ }
+ }
+ break;
+ case OutputDOMDocument:
+ {
+ HRESULT hr = S_OK;
+ IXMLDOMElement *element = NULL;
+ BSTR tag_name = NULL;
+
+ tag_name = SysAllocStringLen(QName, nQName);
+ if (!tag_name) {
+ hr = E_OUTOFMEMORY;
+ goto done;
+ }
- hr = ISAXAttributes_getValue(attr, i, &value, &value_len);
+ hr = IXMLDOMDocument_createElement(This->dest_doc, tag_name, &element);
+ if (FAILED(hr)) goto done;
+
+ if (attr) {
+ int length, i;
+ BSTR attribute_name = NULL;
+ VARIANT attribute_value;
+
+ hr = ISAXAttributes_getLength(attr, &length);
if (FAILED(hr)) return hr;
- mxwriter_write_attribute(This, qname, qname_len, value, value_len, escape);
+ for (i = 0; i < length; i++)
+ {
+ int qname_len = 0, value_len = 0;
+ const WCHAR *qname, *value;
+
+ hr = ISAXAttributes_getQName(attr, i, &qname, &qname_len);
+ if (FAILED(hr)) return hr;
+
+ hr = ISAXAttributes_getValue(attr, i, &value, &value_len);
+ if (FAILED(hr)) return hr;
+
+ attribute_name = SysAllocStringLen(qname, qname_len);
+ if (!attribute_name) goto done;
+
+ V_VT(&attribute_value) = VT_BSTR;
+ V_BSTR(&attribute_value) = SysAllocStringLen(value, value_len);
+ if (!V_BSTR(&attribute_value)) goto done;
+
+ IXMLDOMElement_setAttribute(element, attribute_name, attribute_value);
+
+ SysFreeString(V_BSTR(&attribute_value));
+ SysFreeString(attribute_name);
+ }
}
+
+ hr = IXMLDOMNode_appendChild(This->cur_node, (IXMLDOMNode*)element, NULL);
+ if (FAILED(hr)) goto done;
+
+ push_cur_node(This, (IXMLDOMNode*)element);
+
+ done:
+ if (element) IXMLDOMElement_Release(element);
+ if (tag_name) SysFreeString(tag_name);
+
+ return hr;
+ }
}
return S_OK;
@@ -1382,25 +1541,34 @@ static HRESULT WINAPI SAXContentHandler_endElement(
(nQName == -1 && This->class_version == MSXML6))
return E_INVALIDARG;
- writer_dec_indent(This);
-
- if (This->element)
+ switch (This->output_ty)
{
- static const WCHAR closeW[] = {'/','>'};
- write_output_buffer(This, closeW, 2);
- }
- else
- {
- static const WCHAR closetagW[] = {'<','/'};
- static const WCHAR gtW[] = {'>'};
+ case OutputIStream:
+ case OutputString:
+ writer_dec_indent(This);
- write_node_indent(This);
- write_output_buffer(This, closetagW, 2);
- write_output_buffer(This, QName, nQName);
- write_output_buffer(This, gtW, 1);
- }
+ if (This->element)
+ {
+ static const WCHAR closeW[] = {'/','>'};
+ write_output_buffer(This, closeW, 2);
+ }
+ else
+ {
+ static const WCHAR closetagW[] = {'<','/'};
+ static const WCHAR gtW[] = {'>'};
- set_element_name(This, NULL, 0);
+ write_node_indent(This);
+ write_output_buffer(This, closetagW, 2);
+ write_output_buffer(This, QName, nQName);
+ write_output_buffer(This, gtW, 1);
+ }
+
+ set_element_name(This, NULL, 0);
+ break;
+ case OutputDOMDocument:
+ pop_cur_node(This);
+ break;
+ }
return S_OK;
}
@@ -1416,25 +1584,54 @@ static HRESULT WINAPI SAXContentHandler_characters(
if (!chars) return E_INVALIDARG;
- close_element_starttag(This);
- set_element_name(This, NULL, 0);
+ switch (This->output_ty) {
+ case OutputIStream:
+ case OutputString:
+ close_element_starttag(This);
+ set_element_name(This, NULL, 0);
- if (!This->cdata)
- This->text = TRUE;
+ if (!This->cdata)
+ This->text = TRUE;
- if (nchars)
- {
- if (This->cdata || This->props[MXWriter_DisableEscaping] == VARIANT_TRUE)
- write_output_buffer(This, chars, nchars);
- else
+ if (nchars)
{
- int len = nchars;
- WCHAR *escaped;
+ if (This->cdata || This->props[MXWriter_DisableEscaping] == VARIANT_TRUE)
+ write_output_buffer(This, chars, nchars);
+ else
+ {
+ int len = nchars;
+ WCHAR *escaped;
- escaped = get_escaped_string(chars, EscapeText, &len);
- write_output_buffer(This, escaped, len);
- heap_free(escaped);
+ escaped = get_escaped_string(chars, EscapeText, &len);
+ write_output_buffer(This, escaped, len);
+ heap_free(escaped);
+ }
+ }
+ break;
+ case OutputDOMDocument:
+ {
+ HRESULT hr = S_OK;
+ IXMLDOMText *text_node = NULL;
+ BSTR text = NULL;
+
+ text = SysAllocStringLen(chars, nchars);
+ if (!text) {
+ hr = E_OUTOFMEMORY;
+ goto done;
}
+
+ hr = IXMLDOMDocument_createTextNode(This->dest_doc, text, &text_node);
+ if (FAILED(hr)) goto done;
+
+ hr = IXMLDOMNode_appendChild(This->cur_node, (IXMLDOMNode*)text_node, NULL);
+ if (FAILED(hr)) goto done;
+
+ done:
+ if (text_node) IXMLDOMText_Release(text_node);
+ if (text) SysFreeString(text);
+
+ return hr;
+ }
}
return S_OK;
@@ -1451,7 +1648,15 @@ static HRESULT WINAPI SAXContentHandler_ignorableWhitespace(
if (!chars) return E_INVALIDARG;
- write_output_buffer(This, chars, nchars);
+ switch (This->output_ty)
+ {
+ case OutputIStream:
+ case OutputString:
+ write_output_buffer(This, chars, nchars);
+ break;
+ case OutputDOMDocument:
+ break;
+ }
return S_OK;
}
@@ -1471,20 +1676,71 @@ static HRESULT WINAPI SAXContentHandler_processingInstruction(
if (!target) return E_INVALIDARG;
- write_node_indent(This);
- write_output_buffer(This, openpiW, ARRAY_SIZE(openpiW));
+ switch (This->output_ty) {
+ case OutputIStream:
+ case OutputString:
+ write_node_indent(This);
+ write_output_buffer(This, openpiW, ARRAY_SIZE(openpiW));
+
+ if (*target)
+ write_output_buffer(This, target, ntarget);
- if (*target)
- write_output_buffer(This, target, ntarget);
+ if (data && *data && ndata)
+ {
+ write_output_buffer(This, spaceW, 1);
+ write_output_buffer(This, data, ndata);
+ }
- if (data && *data && ndata)
+ write_output_buffer(This, closepiW, ARRAY_SIZE(closepiW));
+ This->newline = TRUE;
+ break;
+ case OutputDOMDocument:
{
- write_output_buffer(This, spaceW, 1);
- write_output_buffer(This, data, ndata);
- }
+ HRESULT hr = S_OK;
+ IXMLDOMNode *first_child = NULL;
+ IXMLDOMProcessingInstruction *processing_instruction = NULL;
+ VARIANT ref_node;
+ BSTR target_bstr = NULL;
+ BSTR data_bstr = NULL;
+
+ target_bstr = SysAllocStringLen(target, ntarget);
+ if (!target_bstr) {
+ hr = E_OUTOFMEMORY;
+ goto done;
+ }
+
+ data_bstr = SysAllocStringLen(data, ndata);
+ if (!data_bstr) {
+ hr = E_OUTOFMEMORY;
+ goto done;
+ }
+
+ hr = IXMLDOMDocument_createProcessingInstruction(
+ This->dest_doc, target_bstr, data_bstr, &processing_instruction
+ );
+ if (FAILED(hr)) goto done;
- write_output_buffer(This, closepiW, ARRAY_SIZE(closepiW));
- This->newline = TRUE;
+ hr = IXMLDOMDocument_get_firstChild(This->dest_doc, &first_child);
+ if (FAILED(hr)) goto done;
+
+ V_VT(&ref_node) = VT_UNKNOWN;
+ V_UNKNOWN(&ref_node) = (IUnknown*)first_child;
+
+ hr = IXMLDOMDocument_insertBefore(
+ This->dest_doc, (IXMLDOMNode*)processing_instruction, ref_node, NULL
+ );
+ if (FAILED(hr)) goto done;
+
+ done:
+ if (first_child) IXMLDOMNode_Release(first_child);
+ if (processing_instruction)
+ IXMLDOMProcessingInstruction_Release(processing_instruction);
+ if (data_bstr) SysFreeString(data_bstr);
+ if (target_bstr) SysFreeString(target_bstr);
+
+ return hr;
+ }
+ }
return S_OK;
}
@@ -1551,38 +1807,48 @@ static HRESULT WINAPI SAXLexicalHandler_startDTD(ISAXLexicalHandler *iface,
if (!name) return E_INVALIDARG;
- write_output_buffer(This, doctypeW, ARRAY_SIZE(doctypeW));
+ switch (This->output_ty) {
+ case OutputIStream:
+ case OutputString:
+ write_output_buffer(This, doctypeW, ARRAY_SIZE(doctypeW));
- if (*name)
- {
- write_output_buffer(This, name, name_len);
- write_output_buffer(This, spaceW, 1);
- }
+ if (*name)
+ {
+ write_output_buffer(This, name, name_len);
+ write_output_buffer(This, spaceW, 1);
+ }
- if (publicId)
- {
- write_output_buffer(This, publicW, ARRAY_SIZE(publicW));
- write_output_buffer_quoted(This, publicId, publicId_len);
+ if (publicId)
+ {
+ write_output_buffer(This, publicW, ARRAY_SIZE(publicW));
+ write_output_buffer_quoted(This, publicId, publicId_len);
- if (!systemId) return E_INVALIDARG;
+ if (!systemId) return E_INVALIDARG;
- if (*publicId)
- write_output_buffer(This, spaceW, 1);
+ if (*publicId)
+ write_output_buffer(This, spaceW, 1);
- write_output_buffer_quoted(This, systemId, systemId_len);
+ write_output_buffer_quoted(This, systemId, systemId_len);
- if (*systemId)
- write_output_buffer(This, spaceW, 1);
- }
- else if (systemId)
- {
- write_output_buffer(This, systemW, ARRAY_SIZE(systemW));
- write_output_buffer_quoted(This, systemId, systemId_len);
- if (*systemId)
- write_output_buffer(This, spaceW, 1);
- }
+ if (*systemId)
+ write_output_buffer(This, spaceW, 1);
+ }
+ else if (systemId)
+ {
+ write_output_buffer(This, systemW, ARRAY_SIZE(systemW));
+ write_output_buffer_quoted(This, systemId, systemId_len);
+ if (*systemId)
+ write_output_buffer(This, spaceW, 1);
+ }
- write_output_buffer(This, openintW, ARRAY_SIZE(openintW));
+ write_output_buffer(This, openintW, ARRAY_SIZE(openintW));
+ break;
+ case OutputDOMDocument:
+ FIXME("(%p)->(%s, %s, %s)\n", This, debugstr_wn(name, name_len),
+ debugstr_wn(publicId, publicId_len),
+ debugstr_wn(systemId, systemId_len));
+ return E_NOTIMPL;
+ }
return S_OK;
}
@@ -1594,7 +1860,15 @@ static HRESULT WINAPI SAXLexicalHandler_endDTD(ISAXLexicalHandler *iface)
TRACE("(%p)\n", This);
- write_output_buffer(This, closedtdW, ARRAY_SIZE(closedtdW));
+ switch (This->output_ty) {
+ case OutputIStream:
+ case OutputString:
+ write_output_buffer(This, closedtdW, ARRAY_SIZE(closedtdW));
+ break;
+ case OutputDOMDocument:
+ FIXME("(%p)\n", This);
+ return E_NOTIMPL;
+ }
return S_OK;
}
@@ -1620,9 +1894,17 @@ static HRESULT WINAPI SAXLexicalHandler_startCDATA(ISAXLexicalHandler *iface)
TRACE("(%p)\n", This);
- write_node_indent(This);
- write_output_buffer(This, scdataW, ARRAY_SIZE(scdataW));
- This->cdata = TRUE;
+ switch (This->output_ty) {
+ case OutputIStream:
+ case OutputString:
+ write_node_indent(This);
+ write_output_buffer(This, scdataW, ARRAY_SIZE(scdataW));
+ This->cdata = TRUE;
+ break;
+ case OutputDOMDocument:
+ FIXME("(%p)\n", This);
+ return E_NOTIMPL;
+ }
return S_OK;
}
@@ -1634,8 +1916,16 @@ static HRESULT WINAPI SAXLexicalHandler_endCDATA(ISAXLexicalHandler *iface)
TRACE("(%p)\n", This);
- write_output_buffer(This, ecdataW, ARRAY_SIZE(ecdataW));
- This->cdata = FALSE;
+ switch (This->output_ty) {
+ case OutputIStream:
+ case OutputString:
+ write_output_buffer(This, ecdataW, ARRAY_SIZE(ecdataW));
+ This->cdata = FALSE;
+ break;
+ case OutputDOMDocument:
+ FIXME("(%p)\n", This);
+ return E_NOTIMPL;
+ }
return S_OK;
}
@@ -1650,13 +1940,21 @@ static HRESULT WINAPI SAXLexicalHandler_comment(ISAXLexicalHandler *iface, const
if (!chars) return E_INVALIDARG;
- close_element_starttag(This);
- write_node_indent(This);
+ switch (This->output_ty) {
+ case OutputIStream:
+ case OutputString:
+ close_element_starttag(This);
+ write_node_indent(This);
- write_output_buffer(This, copenW, ARRAY_SIZE(copenW));
- if (nchars)
- write_output_buffer(This, chars, nchars);
- write_output_buffer(This, ccloseW, ARRAY_SIZE(ccloseW));
+ write_output_buffer(This, copenW, ARRAY_SIZE(copenW));
+ if (nchars)
+ write_output_buffer(This, chars, nchars);
+ write_output_buffer(This, ccloseW, ARRAY_SIZE(ccloseW));
+ break;
+ case OutputDOMDocument:
+ FIXME("(%p)->(%s)\n", This, debugstr_wn(chars, nchars));
+ return E_NOTIMPL;
+ }
return S_OK;
}
@@ -1706,14 +2004,22 @@ static HRESULT WINAPI SAXDeclHandler_elementDecl(ISAXDeclHandler *iface,
if (!name || !model) return E_INVALIDARG;
- write_output_buffer(This, elementW, ARRAY_SIZE(elementW));
- if (n_name) {
- write_output_buffer(This, name, n_name);
- write_output_buffer(This, spaceW, ARRAY_SIZE(spaceW));
+ switch (This->output_ty) {
+ case OutputIStream:
+ case OutputString:
+ write_output_buffer(This, elementW, ARRAY_SIZE(elementW));
+ if (n_name) {
+ write_output_buffer(This, name, n_name);
+ write_output_buffer(This, spaceW, ARRAY_SIZE(spaceW));
+ }
+ if (n_model)
+ write_output_buffer(This, model, n_model);
+ write_output_buffer(This, closetagW, ARRAY_SIZE(closetagW));
+ break;
+ case OutputDOMDocument:
+ FIXME("(%p)->(%s, %s)\n", This, debugstr_wn(name, n_name), debugstr_wn(model, n_model));
+ return E_NOTIMPL;
}
- if (n_model)
- write_output_buffer(This, model, n_model);
- write_output_buffer(This, closetagW, ARRAY_SIZE(closetagW));
return S_OK;
}
@@ -1731,31 +2037,41 @@ static HRESULT WINAPI SAXDeclHandler_attributeDecl(ISAXDeclHandler *iface,
debugstr_wn(attr, n_attr), n_attr, debugstr_wn(type, n_type), n_type, debugstr_wn(Default, n_default), n_default,
debugstr_wn(value, n_value), n_value);
- write_output_buffer(This, attlistW, ARRAY_SIZE(attlistW));
- if (n_element) {
- write_output_buffer(This, element, n_element);
- write_output_buffer(This, spaceW, ARRAY_SIZE(spaceW));
- }
+ switch (This->output_ty) {
+ case OutputIStream:
+ case OutputString:
+ write_output_buffer(This, attlistW, ARRAY_SIZE(attlistW));
+ if (n_element) {
+ write_output_buffer(This, element, n_element);
+ write_output_buffer(This, spaceW, ARRAY_SIZE(spaceW));
+ }
- if (n_attr) {
- write_output_buffer(This, attr, n_attr);
- write_output_buffer(This, spaceW, ARRAY_SIZE(spaceW));
- }
+ if (n_attr) {
+ write_output_buffer(This, attr, n_attr);
+ write_output_buffer(This, spaceW, ARRAY_SIZE(spaceW));
+ }
- if (n_type) {
- write_output_buffer(This, type, n_type);
- write_output_buffer(This, spaceW, ARRAY_SIZE(spaceW));
- }
+ if (n_type) {
+ write_output_buffer(This, type, n_type);
+ write_output_buffer(This, spaceW, ARRAY_SIZE(spaceW));
+ }
- if (n_default) {
- write_output_buffer(This, Default, n_default);
- write_output_buffer(This, spaceW, ARRAY_SIZE(spaceW));
- }
+ if (n_default) {
+ write_output_buffer(This, Default, n_default);
+ write_output_buffer(This, spaceW, ARRAY_SIZE(spaceW));
+ }
- if (n_value)
- write_output_buffer_quoted(This, value, n_value);
+ if (n_value)
+ write_output_buffer_quoted(This, value, n_value);
- write_output_buffer(This, closetagW, ARRAY_SIZE(closetagW));
+ write_output_buffer(This, closetagW, ARRAY_SIZE(closetagW));
+ break;
+ case OutputDOMDocument:
+ FIXME("(%p)->(%s:%d %s:%d %s:%d %s:%d %s:%d)\n", This, debugstr_wn(element, n_element), n_element,
+ debugstr_wn(attr, n_attr), n_attr, debugstr_wn(type, n_type), n_type, debugstr_wn(Default, n_default), n_default,
+ debugstr_wn(value, n_value), n_value);
+ return E_NOTIMPL;
+ }
return S_OK;
}
@@ -1770,16 +2086,25 @@ static HRESULT WINAPI SAXDeclHandler_internalEntityDecl(ISAXDeclHandler *iface,
if (!name || !value) return E_INVALIDARG;
- write_output_buffer(This, entityW, ARRAY_SIZE(entityW));
- if (n_name) {
- write_output_buffer(This, name, n_name);
- write_output_buffer(This, spaceW, ARRAY_SIZE(spaceW));
- }
+ switch (This->output_ty) {
+ case OutputIStream:
+ case OutputString:
+ write_output_buffer(This, entityW, ARRAY_SIZE(entityW));
+ if (n_name) {
+ write_output_buffer(This, name, n_name);
+ write_output_buffer(This, spaceW, ARRAY_SIZE(spaceW));
+ }
- if (n_value)
- write_output_buffer_quoted(This, value, n_value);
+ if (n_value)
+ write_output_buffer_quoted(This, value, n_value);
- write_output_buffer(This, closetagW, ARRAY_SIZE(closetagW));
+ write_output_buffer(This, closetagW, ARRAY_SIZE(closetagW));
+ break;
+ case OutputDOMDocument:
+ FIXME("(%p)->(%s:%d %s:%d)\n", This, debugstr_wn(name, n_name), n_name,
+ debugstr_wn(value, n_value), n_value);
+ return E_NOTIMPL;
+ }
return S_OK;
}
@@ -1795,26 +2120,35 @@ static HRESULT WINAPI SAXDeclHandler_externalEntityDecl(ISAXDeclHandler *iface,
if (!name || !systemId) return E_INVALIDARG;
- write_output_buffer(This, entityW, ARRAY_SIZE(entityW));
- if (n_name) {
- write_output_buffer(This, name, n_name);
- write_output_buffer(This, spaceW, ARRAY_SIZE(spaceW));
- }
+ switch (This->output_ty) {
+ case OutputIStream:
+ case OutputString:
+ write_output_buffer(This, entityW, ARRAY_SIZE(entityW));
+ if (n_name) {
+ write_output_buffer(This, name, n_name);
+ write_output_buffer(This, spaceW, ARRAY_SIZE(spaceW));
+ }
- if (publicId)
- {
- write_output_buffer(This, publicW, ARRAY_SIZE(publicW));
- write_output_buffer_quoted(This, publicId, n_publicId);
- write_output_buffer(This, spaceW, ARRAY_SIZE(spaceW));
- write_output_buffer_quoted(This, systemId, n_systemId);
- }
- else
- {
- write_output_buffer(This, systemW, ARRAY_SIZE(systemW));
- write_output_buffer_quoted(This, systemId, n_systemId);
- }
+ if (publicId)
+ {
+ write_output_buffer(This, publicW, ARRAY_SIZE(publicW));
+ write_output_buffer_quoted(This, publicId, n_publicId);
+ write_output_buffer(This, spaceW, ARRAY_SIZE(spaceW));
+ write_output_buffer_quoted(This, systemId, n_systemId);
+ }
+ else
+ {
+ write_output_buffer(This, systemW, ARRAY_SIZE(systemW));
+ write_output_buffer_quoted(This, systemId, n_systemId);
+ }
- write_output_buffer(This, closetagW, ARRAY_SIZE(closetagW));
+ write_output_buffer(This, closetagW, ARRAY_SIZE(closetagW));
+ break;
+ case OutputDOMDocument:
+ FIXME("(%p)->(%s:%d %s:%d %s:%d)\n", This, debugstr_wn(name, n_name), n_name,
+ debugstr_wn(publicId, n_publicId), n_publicId, debugstr_wn(systemId, n_systemId), n_systemId);
+ return E_NOTIMPL;
+ }
return S_OK;
}
@@ -2172,37 +2506,46 @@ static HRESULT WINAPI VBSAXContentHandler_startElement(IVBSAXContentHandler *ifa
TRACE("(%s %s %s)\n", debugstr_w(*namespaceURI), debugstr_w(*localName), debugstr_w(*QName));
- mxwriter_write_starttag(This, *QName, SysStringLen(*QName));
+ switch (This->output_ty) {
+ case OutputIStream:
+ case OutputString:
+ mxwriter_write_starttag(This, *QName, SysStringLen(*QName));
- if (attrs)
- {
- int length, i, escape;
- HRESULT hr;
+ if (attrs)
+ {
+ int length, i, escape;
+ HRESULT hr;
- hr = IVBSAXAttributes_get_length(attrs, &length);
- if (FAILED(hr)) return hr;
+ hr = IVBSAXAttributes_get_length(attrs, &length);
+ if (FAILED(hr)) return hr;
- escape = This->props[MXWriter_DisableEscaping] == VARIANT_FALSE ||
+ escape = This->props[MXWriter_DisableEscaping] == VARIANT_FALSE ||
(This->class_version == MSXML4 || This->class_version == MSXML6);
- for (i = 0; i < length; i++)
- {
- BSTR qname, value;
+ for (i = 0; i < length; i++)
+ {
+ BSTR qname, value;
- hr = IVBSAXAttributes_getQName(attrs, i, &qname);
- if (FAILED(hr)) return hr;
+ hr = IVBSAXAttributes_getQName(attrs, i, &qname);
+ if (FAILED(hr)) return hr;
- hr = IVBSAXAttributes_getValue(attrs, i, &value);
- if (FAILED(hr))
- {
+ hr = IVBSAXAttributes_getValue(attrs, i, &value);
+ if (FAILED(hr))
+ {
+ SysFreeString(qname);
+ return hr;
+ }
+
+ mxwriter_write_attribute(This, qname, SysStringLen(qname), value, SysStringLen(value), escape);
SysFreeString(qname);
- return hr;
+ SysFreeString(value);
}
-
- mxwriter_write_attribute(This, qname, SysStringLen(qname), value, SysStringLen(value), escape);
- SysFreeString(qname);
- SysFreeString(value);
}
+ break;
+ case OutputDOMDocument:
+ FIXME("(%p)->(%s %s %s)\n", This, debugstr_w(*namespaceURI),
+ debugstr_w(*localName), debugstr_w(*QName));
+ return E_NOTIMPL;
}
return S_OK;
@@ -2326,30 +2669,39 @@ static HRESULT WINAPI SAXDTDHandler_notationDecl(ISAXDTDHandler *iface,
if (!name || !n_name)
return E_INVALIDARG;
- write_output_buffer(This, notationW, ARRAY_SIZE(notationW));
- write_output_buffer(This, name, n_name);
+ switch (This->output_ty) {
+ case OutputIStream:
+ case OutputString:
+ write_output_buffer(This, notationW, ARRAY_SIZE(notationW));
+ write_output_buffer(This, name, n_name);
- if (!publicid && !systemid)
- return E_INVALIDARG;
+ if (!publicid && !systemid)
+ return E_INVALIDARG;
- write_output_buffer(This, spaceW, ARRAY_SIZE(spaceW));
- if (publicid)
- {
- write_output_buffer(This, publicW, ARRAY_SIZE(publicW));
- write_output_buffer_quoted(This, publicid, n_publicid);
- if (systemid)
+ write_output_buffer(This, spaceW, ARRAY_SIZE(spaceW));
+ if (publicid)
{
- write_output_buffer(This, spaceW, ARRAY_SIZE(spaceW));
+ write_output_buffer(This, publicW, ARRAY_SIZE(publicW));
+ write_output_buffer_quoted(This, publicid, n_publicid);
+ if (systemid)
+ {
+ write_output_buffer(This, spaceW, ARRAY_SIZE(spaceW));
+ write_output_buffer_quoted(This, systemid, n_systemid);
+ }
+ }
+ else
+ {
+ write_output_buffer(This, systemW, ARRAY_SIZE(systemW));
write_output_buffer_quoted(This, systemid, n_systemid);
}
- }
- else
- {
- write_output_buffer(This, systemW, ARRAY_SIZE(systemW));
- write_output_buffer_quoted(This, systemid, n_systemid);
- }
- write_output_buffer(This, closetagW, ARRAY_SIZE(closetagW));
+ write_output_buffer(This, closetagW, ARRAY_SIZE(closetagW));
+ break;
+ case OutputDOMDocument:
+ TRACE("(%p)->(%s:%d, %s:%d, %s:%d)\n", This, debugstr_wn(name, n_name), n_name,
+ debugstr_wn(publicid, n_publicid), n_publicid, debugstr_wn(systemid, n_systemid), n_systemid);
+ return E_NOTIMPL;
+ }
return S_OK;
}
@@ -2651,7 +3003,10 @@ HRESULT MXWriter_create(MSXML_VERSION version, void **ppObj)
This->text = FALSE;
This->newline = FALSE;
+ This->output_ty = OutputString;
This->dest = NULL;
+ This->dest_doc = NULL;
+ This->cur_node = NULL;
hr = init_output_buffer(This->xml_enc, &This->buffer);
if (hr != S_OK) {
diff --git a/dlls/msxml3/tests/saxreader.c b/dlls/msxml3/tests/saxreader.c
index 70556f94615..dc9347eff8e 100644
--- a/dlls/msxml3/tests/saxreader.c
+++ b/dlls/msxml3/tests/saxreader.c
@@ -4405,7 +4405,7 @@ static void test_mxwriter_domdoc(void)
V_DISPATCH(&dest) = dispatch;
hr = IMXWriter_put_output(writer, dest);
- todo_wine EXPECT_HR(hr, S_OK);
+ EXPECT_HR(hr, S_OK);
/* Provide writer with events */
@@ -4474,90 +4474,90 @@ static void test_mxwriter_domdoc(void)
/* Assert that it created the correct document */
hr = IXMLDOMDocument3_get_documentElement(domdoc, &root);
- todo_wine EXPECT_HR(hr, S_OK);
+ EXPECT_HR(hr, S_OK);
ok(root != NULL, "root == NULL\n");
if (!root) return;
/* <BankAccount> */
hr = IXMLDOMElement_get_nodeName(root, &str);
- todo_wine EXPECT_HR(hr, S_OK);
- todo_wine ok(!lstrcmpW(L"BankAccount", str), "got %s\n", wine_dbgstr_w(str));
+ EXPECT_HR(hr, S_OK);
+ ok(!lstrcmpW(L"BankAccount", str), "got %s\n", wine_dbgstr_w(str));
SysFreeString(str);
hr = IXMLDOMElement_get_childNodes(root, &node_list);
- todo_wine EXPECT_HR(hr, S_OK);
+ EXPECT_HR(hr, S_OK);
hr = IXMLDOMNodeList_get_length(node_list, &list_length);
- todo_wine EXPECT_HR(hr, S_OK);
- todo_wine ok(2 == list_length, "list length %i, expected 1\n", list_length);
+ EXPECT_HR(hr, S_OK);
+ ok(2 == list_length, "list length %i, expected 1\n", list_length);
/* <Number */
hr = IXMLDOMNodeList_get_item(node_list, 0, &node);
- todo_wine EXPECT_HR(hr, S_OK);
+ EXPECT_HR(hr, S_OK);
hr = IXMLDOMNode_get_nodeName(node, &str);
- todo_wine EXPECT_HR(hr, S_OK);
- todo_wine ok(!lstrcmpW(L"Number", str), "got %s\n", wine_dbgstr_w(str));
+ EXPECT_HR(hr, S_OK);
+ ok(!lstrcmpW(L"Number", str), "got %s\n", wine_dbgstr_w(str));
SysFreeString(str);
hr = IXMLDOMNode_get_attributes(node, &attribute_map);
- todo_wine EXPECT_HR(hr, S_OK);
+ EXPECT_HR(hr, S_OK);
hr = IXMLDOMNamedNodeMap_get_length(attribute_map, &list_length);
- todo_wine EXPECT_HR(hr, S_OK);
- todo_wine ok(2 == list_length, "attributes length %i, expected 2\n", list_length);
+ EXPECT_HR(hr, S_OK);
+ ok(2 == list_length, "attributes length %i, expected 2\n", list_length);
/* bank="World Bank" */
hr = IXMLDOMNamedNodeMap_get_item(attribute_map, 0, &attribute_node);
- todo_wine EXPECT_HR(hr, S_OK);
+ EXPECT_HR(hr, S_OK);
hr = IXMLDOMNode_get_nodeName(attribute_node, &str);
- todo_wine EXPECT_HR(hr, S_OK);
- todo_wine ok(!lstrcmpW(L"bank", str), "got %s\n", wine_dbgstr_w(str));
+ EXPECT_HR(hr, S_OK);
+ ok(!lstrcmpW(L"bank", str), "got %s\n", wine_dbgstr_w(str));
SysFreeString(str);
hr = IXMLDOMNode_get_text(attribute_node, &str);
- todo_wine EXPECT_HR(hr, S_OK);
- todo_wine ok(!lstrcmpW(L"World Bank", str), "got %s\n", wine_dbgstr_w(str));
+ EXPECT_HR(hr, S_OK);
+ ok(!lstrcmpW(L"World Bank", str), "got %s\n", wine_dbgstr_w(str));
SysFreeString(str);
IXMLDOMNode_Release(attribute_node);
/* branch="Japan" */
hr = IXMLDOMNamedNodeMap_get_item(attribute_map, 1, &attribute_node);
- todo_wine EXPECT_HR(hr, S_OK);
+ EXPECT_HR(hr, S_OK);
hr = IXMLDOMNode_get_nodeName(attribute_node, &str);
- todo_wine EXPECT_HR(hr, S_OK);
- todo_wine ok(!lstrcmpW(L"branch", str), "got %s\n", wine_dbgstr_w(str));
+ EXPECT_HR(hr, S_OK);
+ ok(!lstrcmpW(L"branch", str), "got %s\n", wine_dbgstr_w(str));
SysFreeString(str);
hr = IXMLDOMNode_get_text(attribute_node, &str);
- todo_wine EXPECT_HR(hr, S_OK);
- todo_wine ok(!lstrcmpW(L"Japan", str), "got %s\n", wine_dbgstr_w(str));
+ EXPECT_HR(hr, S_OK);
+ ok(!lstrcmpW(L"Japan", str), "got %s\n", wine_dbgstr_w(str));
SysFreeString(str);
IXMLDOMNode_Release(attribute_node);
IXMLDOMNamedNodeMap_Release(attribute_map);
/* >12345</Number> */
hr = IXMLDOMNode_get_text(node, &str);
- todo_wine EXPECT_HR(hr, S_OK);
- todo_wine ok(!lstrcmpW(L"12345", str), "got %s\n", wine_dbgstr_w(str));
+ EXPECT_HR(hr, S_OK);
+ ok(!lstrcmpW(L"12345", str), "got %s\n", wine_dbgstr_w(str));
SysFreeString(str);
IXMLDOMNode_Release(node);
/* <Name>Captain Ahab</Name></BankAccount> */
hr = IXMLDOMNodeList_get_item(node_list, 1, &node);
- todo_wine EXPECT_HR(hr, S_OK);
+ EXPECT_HR(hr, S_OK);
hr = IXMLDOMNode_get_nodeName(node, &str);
- todo_wine EXPECT_HR(hr, S_OK);
- todo_wine ok(!lstrcmpW(L"Name", str), "got %s\n", wine_dbgstr_w(str));
+ EXPECT_HR(hr, S_OK);
+ ok(!lstrcmpW(L"Name", str), "got %s\n", wine_dbgstr_w(str));
SysFreeString(str);
hr = IXMLDOMNode_get_text(node, &str);
- todo_wine EXPECT_HR(hr, S_OK);
- todo_wine ok(!lstrcmpW(L"Captain Ahab", str), "got %s\n", wine_dbgstr_w(str));
+ EXPECT_HR(hr, S_OK);
+ ok(!lstrcmpW(L"Captain Ahab", str), "got %s\n", wine_dbgstr_w(str));
SysFreeString(str);
IXMLDOMNode_Release(node);
IXMLDOMNodeList_Release(node_list);
@@ -4565,7 +4565,7 @@ static void test_mxwriter_domdoc(void)
/* finally test doc output */
hr = IXMLDOMDocument3_get_xml(domdoc, &str);
- todo_wine EXPECT_HR(hr, S_OK);
+ EXPECT_HR(hr, S_OK);
todo_wine ok(
!lstrcmpW(
L"<?targ type=\"test sheet\" test=\"something\"?>\r\n"
--
2.26.2
More information about the wine-devel
mailing list