2 * MXWriter implementation
4 * Copyright 2011 Nikolay Sivov for CodeWeavers
5 * Copyright 2011 Thomas Mullaly
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 # include <libxml/parser.h>
36 #include "wine/debug.h"
38 #include "msxml_private.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(msxml
);
44 static const WCHAR utf16W
[] = {'U','T','F','-','1','6',0};
45 static const WCHAR utf8W
[] = {'U','T','F','-','8',0};
47 static const char crlfA
[] = "\r\n";
48 static const WCHAR emptyW
[] = {0};
53 MXWriter_DisableEscaping
,
60 typedef struct _mxwriter
62 IMXWriter IMXWriter_iface
;
63 ISAXContentHandler ISAXContentHandler_iface
;
66 MSXML_VERSION class_version
;
68 VARIANT_BOOL props
[MXWriter_LastProp
];
70 xmlCharEncoding encoding
;
73 /* contains a pending (or not closed yet) element name or NULL if
74 we don't have to close */
80 xmlOutputBufferPtr buffer
;
83 static HRESULT
bstr_from_xmlCharEncoding(xmlCharEncoding enc
, BSTR
*encoding
)
85 const char *encodingA
;
87 if (enc
!= XML_CHAR_ENCODING_UTF16LE
&& enc
!= XML_CHAR_ENCODING_UTF8
) {
88 FIXME("Unsupported xmlCharEncoding: %d\n", enc
);
93 encodingA
= xmlGetCharEncodingName(enc
);
95 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, encodingA
, -1, NULL
, 0);
96 *encoding
= SysAllocStringLen(NULL
, len
-1);
98 MultiByteToWideChar( CP_ACP
, 0, encodingA
, -1, *encoding
, len
);
100 *encoding
= SysAllocStringLen(NULL
, 0);
102 return *encoding
? S_OK
: E_OUTOFMEMORY
;
105 /* Attempts to the write data from the mxwriter's buffer to
106 * the destination stream (if there is one).
108 static HRESULT
write_data_to_stream(mxwriter
*This
)
112 xmlBufferPtr buffer
= NULL
;
117 /* The xmlOutputBuffer doesn't copy its contents from its 'buffer' to the
118 * 'conv' buffer when UTF8 encoding is used.
120 if (This
->encoding
== XML_CHAR_ENCODING_UTF8
)
121 buffer
= This
->buffer
->buffer
;
123 buffer
= This
->buffer
->conv
;
125 if (This
->dest_written
> buffer
->use
) {
126 ERR("Failed sanity check! Not sure what to do... (%d > %d)\n", This
->dest_written
, buffer
->use
);
128 } else if (This
->dest_written
== buffer
->use
&& This
->encoding
!= XML_CHAR_ENCODING_UTF8
)
129 /* Windows seems to make an empty write call when the encoding is UTF-8 and
130 * all the data has been written to the stream. It doesn't seem make this call
131 * for any other encodings.
135 /* Write the current content from the output buffer into 'dest'.
136 * TODO: Check what Windows does if the IStream doesn't write all of
137 * the data we give it at once.
139 hres
= IStream_Write(This
->dest
, buffer
->content
+This
->dest_written
,
140 buffer
->use
-This
->dest_written
, &written
);
142 WARN("Failed to write data to IStream (%08x)\n", hres
);
146 This
->dest_written
+= written
;
150 /* Newly added element start tag left unclosed cause for empty elements
151 we have to close it differently. */
152 static void close_element_starttag(const mxwriter
*This
)
154 if (!This
->element
) return;
155 xmlOutputBufferWriteString(This
->buffer
, ">");
158 static void set_element_name(mxwriter
*This
, const WCHAR
*name
, int len
)
160 SysFreeString(This
->element
);
161 This
->element
= name
? SysAllocStringLen(name
, len
) : NULL
;
164 static inline HRESULT
flush_output_buffer(mxwriter
*This
)
166 close_element_starttag(This
);
167 set_element_name(This
, NULL
, 0);
168 xmlOutputBufferFlush(This
->buffer
);
169 return write_data_to_stream(This
);
172 /* Resets the mxwriter's output buffer by closing it, then creating a new
173 * output buffer using the given encoding.
175 static inline void reset_output_buffer(mxwriter
*This
)
177 xmlOutputBufferClose(This
->buffer
);
178 This
->buffer
= xmlAllocOutputBuffer(xmlGetCharEncodingHandler(This
->encoding
));
179 This
->dest_written
= 0;
182 static HRESULT
writer_set_property(mxwriter
*writer
, MXWRITER_PROPS property
, VARIANT_BOOL value
)
184 writer
->props
[property
] = value
;
185 writer
->prop_changed
= TRUE
;
189 static HRESULT
writer_get_property(const mxwriter
*writer
, MXWRITER_PROPS property
, VARIANT_BOOL
*value
)
191 if (!value
) return E_POINTER
;
192 *value
= writer
->props
[property
];
196 static inline mxwriter
*impl_from_IMXWriter(IMXWriter
*iface
)
198 return CONTAINING_RECORD(iface
, mxwriter
, IMXWriter_iface
);
201 static inline mxwriter
*impl_from_ISAXContentHandler(ISAXContentHandler
*iface
)
203 return CONTAINING_RECORD(iface
, mxwriter
, ISAXContentHandler_iface
);
206 static HRESULT WINAPI
mxwriter_QueryInterface(IMXWriter
*iface
, REFIID riid
, void **obj
)
208 mxwriter
*This
= impl_from_IMXWriter( iface
);
210 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
212 if ( IsEqualGUID( riid
, &IID_IMXWriter
) ||
213 IsEqualGUID( riid
, &IID_IDispatch
) ||
214 IsEqualGUID( riid
, &IID_IUnknown
) )
216 *obj
= &This
->IMXWriter_iface
;
218 else if ( IsEqualGUID( riid
, &IID_ISAXContentHandler
) )
220 *obj
= &This
->ISAXContentHandler_iface
;
224 ERR("interface %s not implemented\n", debugstr_guid(riid
));
226 return E_NOINTERFACE
;
229 IMXWriter_AddRef(iface
);
233 static ULONG WINAPI
mxwriter_AddRef(IMXWriter
*iface
)
235 mxwriter
*This
= impl_from_IMXWriter( iface
);
236 LONG ref
= InterlockedIncrement(&This
->ref
);
238 TRACE("(%p)->(%d)\n", This
, ref
);
243 static ULONG WINAPI
mxwriter_Release(IMXWriter
*iface
)
245 mxwriter
*This
= impl_from_IMXWriter( iface
);
246 ULONG ref
= InterlockedDecrement(&This
->ref
);
248 TRACE("(%p)->(%d)\n", This
, ref
);
252 /* Windows flushes the buffer when the interface is destroyed. */
253 flush_output_buffer(This
);
255 if (This
->dest
) IStream_Release(This
->dest
);
256 SysFreeString(This
->version
);
258 xmlOutputBufferClose(This
->buffer
);
259 SysFreeString(This
->element
);
266 static HRESULT WINAPI
mxwriter_GetTypeInfoCount(IMXWriter
*iface
, UINT
* pctinfo
)
268 mxwriter
*This
= impl_from_IMXWriter( iface
);
270 TRACE("(%p)->(%p)\n", This
, pctinfo
);
277 static HRESULT WINAPI
mxwriter_GetTypeInfo(
279 UINT iTInfo
, LCID lcid
,
280 ITypeInfo
** ppTInfo
)
282 mxwriter
*This
= impl_from_IMXWriter( iface
);
284 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
286 return get_typeinfo(IMXWriter_tid
, ppTInfo
);
289 static HRESULT WINAPI
mxwriter_GetIDsOfNames(
291 REFIID riid
, LPOLESTR
* rgszNames
,
292 UINT cNames
, LCID lcid
, DISPID
* rgDispId
)
294 mxwriter
*This
= impl_from_IMXWriter( iface
);
298 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
,
301 if(!rgszNames
|| cNames
== 0 || !rgDispId
)
304 hr
= get_typeinfo(IMXWriter_tid
, &typeinfo
);
307 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
308 ITypeInfo_Release(typeinfo
);
314 static HRESULT WINAPI
mxwriter_Invoke(
316 DISPID dispIdMember
, REFIID riid
, LCID lcid
,
317 WORD wFlags
, DISPPARAMS
* pDispParams
, VARIANT
* pVarResult
,
318 EXCEPINFO
* pExcepInfo
, UINT
* puArgErr
)
320 mxwriter
*This
= impl_from_IMXWriter( iface
);
324 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
325 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
327 hr
= get_typeinfo(IMXWriter_tid
, &typeinfo
);
330 hr
= ITypeInfo_Invoke(typeinfo
, &This
->IMXWriter_iface
, dispIdMember
, wFlags
,
331 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
332 ITypeInfo_Release(typeinfo
);
338 static HRESULT WINAPI
mxwriter_put_output(IMXWriter
*iface
, VARIANT dest
)
340 mxwriter
*This
= impl_from_IMXWriter( iface
);
343 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&dest
));
345 hr
= flush_output_buffer(This
);
353 if (This
->dest
) IStream_Release(This
->dest
);
356 /* We need to reset the output buffer to UTF-16, since the only way
357 * the content of the mxwriter can be accessed now is through a BSTR.
359 This
->encoding
= xmlParseCharEncoding("UTF-16");
360 reset_output_buffer(This
);
367 hr
= IUnknown_QueryInterface(V_UNKNOWN(&dest
), &IID_IStream
, (void**)&stream
);
370 /* Recreate the output buffer to make sure it's using the correct encoding. */
371 reset_output_buffer(This
);
373 if (This
->dest
) IStream_Release(This
->dest
);
378 FIXME("unhandled interface type for VT_UNKNOWN destination\n");
382 FIXME("unhandled destination type %s\n", debugstr_variant(&dest
));
389 static HRESULT WINAPI
mxwriter_get_output(IMXWriter
*iface
, VARIANT
*dest
)
391 mxwriter
*This
= impl_from_IMXWriter( iface
);
393 TRACE("(%p)->(%p)\n", This
, dest
);
397 HRESULT hr
= flush_output_buffer(This
);
401 /* TODO: Windows always seems to re-encode the XML to UTF-16 (this includes
402 * updating the XML decl so it says "UTF-16" instead of "UTF-8"). We don't
403 * support this yet...
405 if (This
->encoding
== XML_CHAR_ENCODING_UTF8
) {
406 FIXME("XML re-encoding not supported yet\n");
410 V_VT(dest
) = VT_BSTR
;
411 V_BSTR(dest
) = SysAllocStringLen((const WCHAR
*)This
->buffer
->conv
->content
,
412 This
->buffer
->conv
->use
/sizeof(WCHAR
));
417 FIXME("not implemented when stream is set up\n");
422 static HRESULT WINAPI
mxwriter_put_encoding(IMXWriter
*iface
, BSTR encoding
)
424 mxwriter
*This
= impl_from_IMXWriter( iface
);
426 TRACE("(%p)->(%s)\n", This
, debugstr_w(encoding
));
428 /* FIXME: filter all supported encodings */
429 if (!strcmpW(encoding
, utf16W
) || !strcmpW(encoding
, utf8W
))
434 hr
= flush_output_buffer(This
);
438 enc
= heap_strdupWtoA(encoding
);
440 return E_OUTOFMEMORY
;
442 This
->encoding
= xmlParseCharEncoding(enc
);
445 reset_output_buffer(This
);
450 FIXME("unsupported encoding %s\n", debugstr_w(encoding
));
455 static HRESULT WINAPI
mxwriter_get_encoding(IMXWriter
*iface
, BSTR
*encoding
)
457 mxwriter
*This
= impl_from_IMXWriter( iface
);
459 TRACE("(%p)->(%p)\n", This
, encoding
);
461 if (!encoding
) return E_POINTER
;
463 return bstr_from_xmlCharEncoding(This
->encoding
, encoding
);
466 static HRESULT WINAPI
mxwriter_put_byteOrderMark(IMXWriter
*iface
, VARIANT_BOOL value
)
468 mxwriter
*This
= impl_from_IMXWriter( iface
);
470 TRACE("(%p)->(%d)\n", This
, value
);
471 return writer_set_property(This
, MXWriter_BOM
, value
);
474 static HRESULT WINAPI
mxwriter_get_byteOrderMark(IMXWriter
*iface
, VARIANT_BOOL
*value
)
476 mxwriter
*This
= impl_from_IMXWriter( iface
);
478 TRACE("(%p)->(%p)\n", This
, value
);
479 return writer_get_property(This
, MXWriter_BOM
, value
);
482 static HRESULT WINAPI
mxwriter_put_indent(IMXWriter
*iface
, VARIANT_BOOL value
)
484 mxwriter
*This
= impl_from_IMXWriter( iface
);
486 TRACE("(%p)->(%d)\n", This
, value
);
487 return writer_set_property(This
, MXWriter_Indent
, value
);
490 static HRESULT WINAPI
mxwriter_get_indent(IMXWriter
*iface
, VARIANT_BOOL
*value
)
492 mxwriter
*This
= impl_from_IMXWriter( iface
);
494 TRACE("(%p)->(%p)\n", This
, value
);
495 return writer_get_property(This
, MXWriter_Indent
, value
);
498 static HRESULT WINAPI
mxwriter_put_standalone(IMXWriter
*iface
, VARIANT_BOOL value
)
500 mxwriter
*This
= impl_from_IMXWriter( iface
);
502 TRACE("(%p)->(%d)\n", This
, value
);
503 return writer_set_property(This
, MXWriter_Standalone
, value
);
506 static HRESULT WINAPI
mxwriter_get_standalone(IMXWriter
*iface
, VARIANT_BOOL
*value
)
508 mxwriter
*This
= impl_from_IMXWriter( iface
);
510 TRACE("(%p)->(%p)\n", This
, value
);
511 return writer_get_property(This
, MXWriter_Standalone
, value
);
514 static HRESULT WINAPI
mxwriter_put_omitXMLDeclaration(IMXWriter
*iface
, VARIANT_BOOL value
)
516 mxwriter
*This
= impl_from_IMXWriter( iface
);
518 TRACE("(%p)->(%d)\n", This
, value
);
519 return writer_set_property(This
, MXWriter_OmitXmlDecl
, value
);
522 static HRESULT WINAPI
mxwriter_get_omitXMLDeclaration(IMXWriter
*iface
, VARIANT_BOOL
*value
)
524 mxwriter
*This
= impl_from_IMXWriter( iface
);
526 TRACE("(%p)->(%p)\n", This
, value
);
527 return writer_get_property(This
, MXWriter_OmitXmlDecl
, value
);
530 static HRESULT WINAPI
mxwriter_put_version(IMXWriter
*iface
, BSTR version
)
532 mxwriter
*This
= impl_from_IMXWriter( iface
);
534 TRACE("(%p)->(%s)\n", This
, debugstr_w(version
));
536 if (!version
) return E_INVALIDARG
;
538 SysFreeString(This
->version
);
539 This
->version
= SysAllocString(version
);
544 static HRESULT WINAPI
mxwriter_get_version(IMXWriter
*iface
, BSTR
*version
)
546 mxwriter
*This
= impl_from_IMXWriter( iface
);
548 TRACE("(%p)->(%p)\n", This
, version
);
550 if (!version
) return E_POINTER
;
552 return return_bstr(This
->version
, version
);
555 static HRESULT WINAPI
mxwriter_put_disableOutputEscaping(IMXWriter
*iface
, VARIANT_BOOL value
)
557 mxwriter
*This
= impl_from_IMXWriter( iface
);
559 TRACE("(%p)->(%d)\n", This
, value
);
560 return writer_set_property(This
, MXWriter_DisableEscaping
, value
);
563 static HRESULT WINAPI
mxwriter_get_disableOutputEscaping(IMXWriter
*iface
, VARIANT_BOOL
*value
)
565 mxwriter
*This
= impl_from_IMXWriter( iface
);
567 TRACE("(%p)->(%p)\n", This
, value
);
568 return writer_get_property(This
, MXWriter_DisableEscaping
, value
);
571 static HRESULT WINAPI
mxwriter_flush(IMXWriter
*iface
)
573 mxwriter
*This
= impl_from_IMXWriter( iface
);
574 TRACE("(%p)\n", This
);
575 return flush_output_buffer(This
);
578 static const struct IMXWriterVtbl mxwriter_vtbl
=
580 mxwriter_QueryInterface
,
583 mxwriter_GetTypeInfoCount
,
584 mxwriter_GetTypeInfo
,
585 mxwriter_GetIDsOfNames
,
589 mxwriter_put_encoding
,
590 mxwriter_get_encoding
,
591 mxwriter_put_byteOrderMark
,
592 mxwriter_get_byteOrderMark
,
595 mxwriter_put_standalone
,
596 mxwriter_get_standalone
,
597 mxwriter_put_omitXMLDeclaration
,
598 mxwriter_get_omitXMLDeclaration
,
599 mxwriter_put_version
,
600 mxwriter_get_version
,
601 mxwriter_put_disableOutputEscaping
,
602 mxwriter_get_disableOutputEscaping
,
606 /*** ISAXContentHandler ***/
607 static HRESULT WINAPI
mxwriter_saxcontent_QueryInterface(
608 ISAXContentHandler
*iface
,
612 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
613 return IMXWriter_QueryInterface(&This
->IMXWriter_iface
, riid
, obj
);
616 static ULONG WINAPI
mxwriter_saxcontent_AddRef(ISAXContentHandler
*iface
)
618 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
619 return IMXWriter_AddRef(&This
->IMXWriter_iface
);
622 static ULONG WINAPI
mxwriter_saxcontent_Release(ISAXContentHandler
*iface
)
624 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
625 return IMXWriter_Release(&This
->IMXWriter_iface
);
628 static HRESULT WINAPI
mxwriter_saxcontent_putDocumentLocator(
629 ISAXContentHandler
*iface
,
630 ISAXLocator
*locator
)
632 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
633 FIXME("(%p)->(%p)\n", This
, locator
);
637 static HRESULT WINAPI
mxwriter_saxcontent_startDocument(ISAXContentHandler
*iface
)
639 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
642 TRACE("(%p)\n", This
);
644 /* If properties have been changed since the last "endDocument" call
645 * we need to reset the output buffer. If we don't the output buffer
646 * could end up with multiple XML documents in it, plus this seems to
647 * be how Windows works.
649 if (This
->prop_changed
) {
650 reset_output_buffer(This
);
651 This
->prop_changed
= FALSE
;
654 if (This
->props
[MXWriter_OmitXmlDecl
] == VARIANT_TRUE
) return S_OK
;
657 xmlOutputBufferWriteString(This
->buffer
, "<?xml version=\"");
658 s
= xmlchar_from_wchar(This
->version
);
659 xmlOutputBufferWriteString(This
->buffer
, (char*)s
);
661 xmlOutputBufferWriteString(This
->buffer
, "\"");
664 xmlOutputBufferWriteString(This
->buffer
, " encoding=\"");
665 xmlOutputBufferWriteString(This
->buffer
, xmlGetCharEncodingName(This
->encoding
));
666 xmlOutputBufferWriteString(This
->buffer
, "\"");
669 xmlOutputBufferWriteString(This
->buffer
, " standalone=\"");
670 if (This
->props
[MXWriter_Standalone
] == VARIANT_TRUE
)
671 xmlOutputBufferWriteString(This
->buffer
, "yes\"?>");
673 xmlOutputBufferWriteString(This
->buffer
, "no\"?>");
675 xmlOutputBufferWriteString(This
->buffer
, crlfA
);
677 if (This
->dest
&& This
->encoding
== XML_CHAR_ENCODING_UTF16LE
) {
678 static const CHAR utf16BOM
[] = {0xff,0xfe};
680 if (This
->props
[MXWriter_BOM
] == VARIANT_TRUE
)
681 /* Windows passes a NULL pointer as the pcbWritten parameter and
682 * ignores any error codes returned from this Write call.
684 IStream_Write(This
->dest
, utf16BOM
, sizeof(utf16BOM
), NULL
);
690 static HRESULT WINAPI
mxwriter_saxcontent_endDocument(ISAXContentHandler
*iface
)
692 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
693 TRACE("(%p)\n", This
);
694 This
->prop_changed
= FALSE
;
695 return flush_output_buffer(This
);
698 static HRESULT WINAPI
mxwriter_saxcontent_startPrefixMapping(
699 ISAXContentHandler
*iface
,
705 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
706 FIXME("(%p)->(%s %s)\n", This
, debugstr_wn(prefix
, nprefix
), debugstr_wn(uri
, nuri
));
710 static HRESULT WINAPI
mxwriter_saxcontent_endPrefixMapping(
711 ISAXContentHandler
*iface
,
715 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
716 FIXME("(%p)->(%s)\n", This
, debugstr_wn(prefix
, nprefix
));
720 static HRESULT WINAPI
mxwriter_saxcontent_startElement(
721 ISAXContentHandler
*iface
,
722 const WCHAR
*namespaceUri
,
724 const WCHAR
*local_name
,
728 ISAXAttributes
*attr
)
730 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
733 TRACE("(%p)->(%s %s %s %p)\n", This
, debugstr_wn(namespaceUri
, nnamespaceUri
),
734 debugstr_wn(local_name
, nlocal_name
), debugstr_wn(QName
, nQName
), attr
);
736 if ((!namespaceUri
|| !local_name
|| !QName
) && This
->class_version
!= MSXML6
)
739 close_element_starttag(This
);
740 set_element_name(This
, QName
? QName
: emptyW
,
743 xmlOutputBufferWriteString(This
->buffer
, "<");
744 s
= xmlchar_from_wcharn(QName
, nQName
);
745 xmlOutputBufferWriteString(This
->buffer
, (char*)s
);
754 hr
= ISAXAttributes_getLength(attr
, &length
);
755 if (FAILED(hr
)) return hr
;
757 for (i
= 0; i
< length
; i
++)
762 hr
= ISAXAttributes_getQName(attr
, i
, &str
, &len
);
763 if (FAILED(hr
)) return hr
;
765 /* space separator in front of every attribute */
766 xmlOutputBufferWriteString(This
->buffer
, " ");
768 s
= xmlchar_from_wcharn(str
, len
);
769 xmlOutputBufferWriteString(This
->buffer
, (char*)s
);
772 xmlOutputBufferWriteString(This
->buffer
, "=\"");
775 hr
= ISAXAttributes_getValue(attr
, i
, &str
, &len
);
776 if (FAILED(hr
)) return hr
;
778 s
= xmlchar_from_wcharn(str
, len
);
779 xmlOutputBufferWriteString(This
->buffer
, (char*)s
);
782 xmlOutputBufferWriteString(This
->buffer
, "\"");
789 static HRESULT WINAPI
mxwriter_saxcontent_endElement(
790 ISAXContentHandler
*iface
,
791 const WCHAR
*namespaceUri
,
793 const WCHAR
* local_name
,
798 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
800 TRACE("(%p)->(%s:%d %s:%d %s:%d)\n", This
, debugstr_wn(namespaceUri
, nnamespaceUri
), nnamespaceUri
,
801 debugstr_wn(local_name
, nlocal_name
), nlocal_name
, debugstr_wn(QName
, nQName
), nQName
);
803 if ((!namespaceUri
|| !local_name
|| !QName
) && This
->class_version
!= MSXML6
)
806 if (This
->element
&& QName
&& !strncmpW(This
->element
, QName
, nQName
))
808 xmlOutputBufferWriteString(This
->buffer
, "/>");
812 xmlChar
*s
= xmlchar_from_wcharn(QName
, nQName
);
814 xmlOutputBufferWriteString(This
->buffer
, "</");
815 xmlOutputBufferWriteString(This
->buffer
, (char*)s
);
816 xmlOutputBufferWriteString(This
->buffer
, ">");
821 set_element_name(This
, NULL
, 0);
826 static HRESULT WINAPI
mxwriter_saxcontent_characters(
827 ISAXContentHandler
*iface
,
831 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
833 TRACE("(%p)->(%s:%d)\n", This
, debugstr_wn(chars
, nchars
), nchars
);
835 if (!chars
) return E_INVALIDARG
;
837 close_element_starttag(This
);
838 set_element_name(This
, NULL
, 0);
842 xmlChar
*s
= xmlchar_from_wcharn(chars
, nchars
);
843 xmlOutputBufferWriteString(This
->buffer
, (char*)s
);
850 static HRESULT WINAPI
mxwriter_saxcontent_ignorableWhitespace(
851 ISAXContentHandler
*iface
,
855 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
856 FIXME("(%p)->(%s)\n", This
, debugstr_wn(chars
, nchars
));
860 static HRESULT WINAPI
mxwriter_saxcontent_processingInstruction(
861 ISAXContentHandler
*iface
,
867 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
868 FIXME("(%p)->(%s %s)\n", This
, debugstr_wn(target
, ntarget
), debugstr_wn(data
, ndata
));
872 static HRESULT WINAPI
mxwriter_saxcontent_skippedEntity(
873 ISAXContentHandler
*iface
,
877 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
878 FIXME("(%p)->(%s)\n", This
, debugstr_wn(name
, nname
));
882 static const struct ISAXContentHandlerVtbl mxwriter_saxcontent_vtbl
=
884 mxwriter_saxcontent_QueryInterface
,
885 mxwriter_saxcontent_AddRef
,
886 mxwriter_saxcontent_Release
,
887 mxwriter_saxcontent_putDocumentLocator
,
888 mxwriter_saxcontent_startDocument
,
889 mxwriter_saxcontent_endDocument
,
890 mxwriter_saxcontent_startPrefixMapping
,
891 mxwriter_saxcontent_endPrefixMapping
,
892 mxwriter_saxcontent_startElement
,
893 mxwriter_saxcontent_endElement
,
894 mxwriter_saxcontent_characters
,
895 mxwriter_saxcontent_ignorableWhitespace
,
896 mxwriter_saxcontent_processingInstruction
,
897 mxwriter_saxcontent_skippedEntity
900 HRESULT
MXWriter_create(MSXML_VERSION version
, IUnknown
*pUnkOuter
, void **ppObj
)
902 static const WCHAR version10W
[] = {'1','.','0',0};
905 TRACE("(%p,%p)\n", pUnkOuter
, ppObj
);
907 if (pUnkOuter
) FIXME("support aggregation, outer\n");
909 This
= heap_alloc( sizeof (*This
) );
911 return E_OUTOFMEMORY
;
913 This
->IMXWriter_iface
.lpVtbl
= &mxwriter_vtbl
;
914 This
->ISAXContentHandler_iface
.lpVtbl
= &mxwriter_saxcontent_vtbl
;
916 This
->class_version
= version
;
918 This
->props
[MXWriter_BOM
] = VARIANT_TRUE
;
919 This
->props
[MXWriter_DisableEscaping
] = VARIANT_FALSE
;
920 This
->props
[MXWriter_Indent
] = VARIANT_FALSE
;
921 This
->props
[MXWriter_OmitXmlDecl
] = VARIANT_FALSE
;
922 This
->props
[MXWriter_Standalone
] = VARIANT_FALSE
;
923 This
->prop_changed
= FALSE
;
924 This
->encoding
= xmlParseCharEncoding("UTF-16");
925 This
->version
= SysAllocString(version10W
);
927 This
->element
= NULL
;
930 This
->dest_written
= 0;
932 This
->buffer
= xmlAllocOutputBuffer(xmlGetCharEncodingHandler(This
->encoding
));
934 *ppObj
= &This
->IMXWriter_iface
;
936 TRACE("returning iface %p\n", *ppObj
);
943 HRESULT
MXWriter_create(MSXML_VERSION version
, IUnknown
*pUnkOuter
, void **obj
)
945 MESSAGE("This program tried to use a MXXMLWriter object, but\n"
946 "libxml2 support was not present at compile time.\n");
950 #endif /* HAVE_LIBXML2 */