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 inline mxwriter
*impl_from_IMXWriter(IMXWriter
*iface
)
184 return CONTAINING_RECORD(iface
, mxwriter
, IMXWriter_iface
);
187 static inline mxwriter
*impl_from_ISAXContentHandler(ISAXContentHandler
*iface
)
189 return CONTAINING_RECORD(iface
, mxwriter
, ISAXContentHandler_iface
);
192 static HRESULT WINAPI
mxwriter_QueryInterface(IMXWriter
*iface
, REFIID riid
, void **obj
)
194 mxwriter
*This
= impl_from_IMXWriter( iface
);
196 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
198 if ( IsEqualGUID( riid
, &IID_IMXWriter
) ||
199 IsEqualGUID( riid
, &IID_IDispatch
) ||
200 IsEqualGUID( riid
, &IID_IUnknown
) )
202 *obj
= &This
->IMXWriter_iface
;
204 else if ( IsEqualGUID( riid
, &IID_ISAXContentHandler
) )
206 *obj
= &This
->ISAXContentHandler_iface
;
210 ERR("interface %s not implemented\n", debugstr_guid(riid
));
212 return E_NOINTERFACE
;
215 IMXWriter_AddRef(iface
);
219 static ULONG WINAPI
mxwriter_AddRef(IMXWriter
*iface
)
221 mxwriter
*This
= impl_from_IMXWriter( iface
);
222 LONG ref
= InterlockedIncrement(&This
->ref
);
224 TRACE("(%p)->(%d)\n", This
, ref
);
229 static ULONG WINAPI
mxwriter_Release(IMXWriter
*iface
)
231 mxwriter
*This
= impl_from_IMXWriter( iface
);
232 ULONG ref
= InterlockedDecrement(&This
->ref
);
234 TRACE("(%p)->(%d)\n", This
, ref
);
238 /* Windows flushes the buffer when the interface is destroyed. */
239 flush_output_buffer(This
);
241 if (This
->dest
) IStream_Release(This
->dest
);
242 SysFreeString(This
->version
);
244 xmlOutputBufferClose(This
->buffer
);
245 SysFreeString(This
->element
);
252 static HRESULT WINAPI
mxwriter_GetTypeInfoCount(IMXWriter
*iface
, UINT
* pctinfo
)
254 mxwriter
*This
= impl_from_IMXWriter( iface
);
256 TRACE("(%p)->(%p)\n", This
, pctinfo
);
263 static HRESULT WINAPI
mxwriter_GetTypeInfo(
265 UINT iTInfo
, LCID lcid
,
266 ITypeInfo
** ppTInfo
)
268 mxwriter
*This
= impl_from_IMXWriter( iface
);
270 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
272 return get_typeinfo(IMXWriter_tid
, ppTInfo
);
275 static HRESULT WINAPI
mxwriter_GetIDsOfNames(
277 REFIID riid
, LPOLESTR
* rgszNames
,
278 UINT cNames
, LCID lcid
, DISPID
* rgDispId
)
280 mxwriter
*This
= impl_from_IMXWriter( iface
);
284 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
,
287 if(!rgszNames
|| cNames
== 0 || !rgDispId
)
290 hr
= get_typeinfo(IMXWriter_tid
, &typeinfo
);
293 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
294 ITypeInfo_Release(typeinfo
);
300 static HRESULT WINAPI
mxwriter_Invoke(
302 DISPID dispIdMember
, REFIID riid
, LCID lcid
,
303 WORD wFlags
, DISPPARAMS
* pDispParams
, VARIANT
* pVarResult
,
304 EXCEPINFO
* pExcepInfo
, UINT
* puArgErr
)
306 mxwriter
*This
= impl_from_IMXWriter( iface
);
310 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
311 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
313 hr
= get_typeinfo(IMXWriter_tid
, &typeinfo
);
316 hr
= ITypeInfo_Invoke(typeinfo
, &This
->IMXWriter_iface
, dispIdMember
, wFlags
,
317 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
318 ITypeInfo_Release(typeinfo
);
324 static HRESULT WINAPI
mxwriter_put_output(IMXWriter
*iface
, VARIANT dest
)
326 mxwriter
*This
= impl_from_IMXWriter( iface
);
329 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&dest
));
331 hr
= flush_output_buffer(This
);
339 if (This
->dest
) IStream_Release(This
->dest
);
342 /* We need to reset the output buffer to UTF-16, since the only way
343 * the content of the mxwriter can be accessed now is through a BSTR.
345 This
->encoding
= xmlParseCharEncoding("UTF-16");
346 reset_output_buffer(This
);
353 hr
= IUnknown_QueryInterface(V_UNKNOWN(&dest
), &IID_IStream
, (void**)&stream
);
356 /* Recreate the output buffer to make sure it's using the correct encoding. */
357 reset_output_buffer(This
);
359 if (This
->dest
) IStream_Release(This
->dest
);
364 FIXME("unhandled interface type for VT_UNKNOWN destination\n");
368 FIXME("unhandled destination type %s\n", debugstr_variant(&dest
));
375 static HRESULT WINAPI
mxwriter_get_output(IMXWriter
*iface
, VARIANT
*dest
)
377 mxwriter
*This
= impl_from_IMXWriter( iface
);
379 TRACE("(%p)->(%p)\n", This
, dest
);
383 HRESULT hr
= flush_output_buffer(This
);
387 /* TODO: Windows always seems to re-encode the XML to UTF-16 (this includes
388 * updating the XML decl so it says "UTF-16" instead of "UTF-8"). We don't
389 * support this yet...
391 if (This
->encoding
== XML_CHAR_ENCODING_UTF8
) {
392 FIXME("XML re-encoding not supported yet\n");
396 V_VT(dest
) = VT_BSTR
;
397 V_BSTR(dest
) = SysAllocStringLen((const WCHAR
*)This
->buffer
->conv
->content
,
398 This
->buffer
->conv
->use
/sizeof(WCHAR
));
403 FIXME("not implemented when stream is set up\n");
408 static HRESULT WINAPI
mxwriter_put_encoding(IMXWriter
*iface
, BSTR encoding
)
410 mxwriter
*This
= impl_from_IMXWriter( iface
);
412 TRACE("(%p)->(%s)\n", This
, debugstr_w(encoding
));
414 /* FIXME: filter all supported encodings */
415 if (!strcmpW(encoding
, utf16W
) || !strcmpW(encoding
, utf8W
))
420 hr
= flush_output_buffer(This
);
424 enc
= heap_strdupWtoA(encoding
);
426 return E_OUTOFMEMORY
;
428 This
->encoding
= xmlParseCharEncoding(enc
);
431 reset_output_buffer(This
);
436 FIXME("unsupported encoding %s\n", debugstr_w(encoding
));
441 static HRESULT WINAPI
mxwriter_get_encoding(IMXWriter
*iface
, BSTR
*encoding
)
443 mxwriter
*This
= impl_from_IMXWriter( iface
);
445 TRACE("(%p)->(%p)\n", This
, encoding
);
447 if (!encoding
) return E_POINTER
;
449 return bstr_from_xmlCharEncoding(This
->encoding
, encoding
);
452 static HRESULT WINAPI
mxwriter_put_byteOrderMark(IMXWriter
*iface
, VARIANT_BOOL value
)
454 mxwriter
*This
= impl_from_IMXWriter( iface
);
456 TRACE("(%p)->(%d)\n", This
, value
);
457 This
->props
[MXWriter_BOM
] = value
;
458 This
->prop_changed
= TRUE
;
463 static HRESULT WINAPI
mxwriter_get_byteOrderMark(IMXWriter
*iface
, VARIANT_BOOL
*value
)
465 mxwriter
*This
= impl_from_IMXWriter( iface
);
467 TRACE("(%p)->(%p)\n", This
, value
);
469 if (!value
) return E_POINTER
;
471 *value
= This
->props
[MXWriter_BOM
];
476 static HRESULT WINAPI
mxwriter_put_indent(IMXWriter
*iface
, VARIANT_BOOL value
)
478 mxwriter
*This
= impl_from_IMXWriter( iface
);
480 TRACE("(%p)->(%d)\n", This
, value
);
481 This
->props
[MXWriter_Indent
] = value
;
482 This
->prop_changed
= TRUE
;
487 static HRESULT WINAPI
mxwriter_get_indent(IMXWriter
*iface
, VARIANT_BOOL
*value
)
489 mxwriter
*This
= impl_from_IMXWriter( iface
);
491 TRACE("(%p)->(%p)\n", This
, value
);
493 if (!value
) return E_POINTER
;
495 *value
= This
->props
[MXWriter_Indent
];
500 static HRESULT WINAPI
mxwriter_put_standalone(IMXWriter
*iface
, VARIANT_BOOL value
)
502 mxwriter
*This
= impl_from_IMXWriter( iface
);
504 TRACE("(%p)->(%d)\n", This
, value
);
505 This
->props
[MXWriter_Standalone
] = value
;
506 This
->prop_changed
= TRUE
;
511 static HRESULT WINAPI
mxwriter_get_standalone(IMXWriter
*iface
, VARIANT_BOOL
*value
)
513 mxwriter
*This
= impl_from_IMXWriter( iface
);
515 TRACE("(%p)->(%p)\n", This
, value
);
517 if (!value
) return E_POINTER
;
519 *value
= This
->props
[MXWriter_Standalone
];
524 static HRESULT WINAPI
mxwriter_put_omitXMLDeclaration(IMXWriter
*iface
, VARIANT_BOOL value
)
526 mxwriter
*This
= impl_from_IMXWriter( iface
);
528 TRACE("(%p)->(%d)\n", This
, value
);
529 This
->props
[MXWriter_OmitXmlDecl
] = value
;
530 This
->prop_changed
= TRUE
;
535 static HRESULT WINAPI
mxwriter_get_omitXMLDeclaration(IMXWriter
*iface
, VARIANT_BOOL
*value
)
537 mxwriter
*This
= impl_from_IMXWriter( iface
);
539 TRACE("(%p)->(%p)\n", This
, value
);
541 if (!value
) return E_POINTER
;
543 *value
= This
->props
[MXWriter_OmitXmlDecl
];
548 static HRESULT WINAPI
mxwriter_put_version(IMXWriter
*iface
, BSTR version
)
550 mxwriter
*This
= impl_from_IMXWriter( iface
);
552 TRACE("(%p)->(%s)\n", This
, debugstr_w(version
));
554 if (!version
) return E_INVALIDARG
;
556 SysFreeString(This
->version
);
557 This
->version
= SysAllocString(version
);
562 static HRESULT WINAPI
mxwriter_get_version(IMXWriter
*iface
, BSTR
*version
)
564 mxwriter
*This
= impl_from_IMXWriter( iface
);
566 TRACE("(%p)->(%p)\n", This
, version
);
568 if (!version
) return E_POINTER
;
570 return return_bstr(This
->version
, version
);
573 static HRESULT WINAPI
mxwriter_put_disableOutputEscaping(IMXWriter
*iface
, VARIANT_BOOL value
)
575 mxwriter
*This
= impl_from_IMXWriter( iface
);
577 TRACE("(%p)->(%d)\n", This
, value
);
578 This
->props
[MXWriter_DisableEscaping
] = value
;
579 This
->prop_changed
= TRUE
;
584 static HRESULT WINAPI
mxwriter_get_disableOutputEscaping(IMXWriter
*iface
, VARIANT_BOOL
*value
)
586 mxwriter
*This
= impl_from_IMXWriter( iface
);
588 TRACE("(%p)->(%p)\n", This
, value
);
590 if (!value
) return E_POINTER
;
592 *value
= This
->props
[MXWriter_DisableEscaping
];
597 static HRESULT WINAPI
mxwriter_flush(IMXWriter
*iface
)
599 mxwriter
*This
= impl_from_IMXWriter( iface
);
600 TRACE("(%p)\n", This
);
601 return flush_output_buffer(This
);
604 static const struct IMXWriterVtbl mxwriter_vtbl
=
606 mxwriter_QueryInterface
,
609 mxwriter_GetTypeInfoCount
,
610 mxwriter_GetTypeInfo
,
611 mxwriter_GetIDsOfNames
,
615 mxwriter_put_encoding
,
616 mxwriter_get_encoding
,
617 mxwriter_put_byteOrderMark
,
618 mxwriter_get_byteOrderMark
,
621 mxwriter_put_standalone
,
622 mxwriter_get_standalone
,
623 mxwriter_put_omitXMLDeclaration
,
624 mxwriter_get_omitXMLDeclaration
,
625 mxwriter_put_version
,
626 mxwriter_get_version
,
627 mxwriter_put_disableOutputEscaping
,
628 mxwriter_get_disableOutputEscaping
,
632 /*** ISAXContentHandler ***/
633 static HRESULT WINAPI
mxwriter_saxcontent_QueryInterface(
634 ISAXContentHandler
*iface
,
638 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
639 return IMXWriter_QueryInterface(&This
->IMXWriter_iface
, riid
, obj
);
642 static ULONG WINAPI
mxwriter_saxcontent_AddRef(ISAXContentHandler
*iface
)
644 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
645 return IMXWriter_AddRef(&This
->IMXWriter_iface
);
648 static ULONG WINAPI
mxwriter_saxcontent_Release(ISAXContentHandler
*iface
)
650 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
651 return IMXWriter_Release(&This
->IMXWriter_iface
);
654 static HRESULT WINAPI
mxwriter_saxcontent_putDocumentLocator(
655 ISAXContentHandler
*iface
,
656 ISAXLocator
*locator
)
658 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
659 FIXME("(%p)->(%p)\n", This
, locator
);
663 static HRESULT WINAPI
mxwriter_saxcontent_startDocument(ISAXContentHandler
*iface
)
665 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
668 TRACE("(%p)\n", This
);
670 /* If properties have been changed since the last "endDocument" call
671 * we need to reset the output buffer. If we don't the output buffer
672 * could end up with multiple XML documents in it, plus this seems to
673 * be how Windows works.
675 if (This
->prop_changed
) {
676 reset_output_buffer(This
);
677 This
->prop_changed
= FALSE
;
680 if (This
->props
[MXWriter_OmitXmlDecl
] == VARIANT_TRUE
) return S_OK
;
683 xmlOutputBufferWriteString(This
->buffer
, "<?xml version=\"");
684 s
= xmlchar_from_wchar(This
->version
);
685 xmlOutputBufferWriteString(This
->buffer
, (char*)s
);
687 xmlOutputBufferWriteString(This
->buffer
, "\"");
690 xmlOutputBufferWriteString(This
->buffer
, " encoding=\"");
691 xmlOutputBufferWriteString(This
->buffer
, xmlGetCharEncodingName(This
->encoding
));
692 xmlOutputBufferWriteString(This
->buffer
, "\"");
695 xmlOutputBufferWriteString(This
->buffer
, " standalone=\"");
696 if (This
->props
[MXWriter_Standalone
] == VARIANT_TRUE
)
697 xmlOutputBufferWriteString(This
->buffer
, "yes\"?>");
699 xmlOutputBufferWriteString(This
->buffer
, "no\"?>");
701 xmlOutputBufferWriteString(This
->buffer
, crlfA
);
703 if (This
->dest
&& This
->encoding
== XML_CHAR_ENCODING_UTF16LE
) {
704 static const CHAR utf16BOM
[] = {0xff,0xfe};
706 if (This
->props
[MXWriter_BOM
] == VARIANT_TRUE
)
707 /* Windows passes a NULL pointer as the pcbWritten parameter and
708 * ignores any error codes returned from this Write call.
710 IStream_Write(This
->dest
, utf16BOM
, sizeof(utf16BOM
), NULL
);
716 static HRESULT WINAPI
mxwriter_saxcontent_endDocument(ISAXContentHandler
*iface
)
718 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
719 TRACE("(%p)\n", This
);
720 This
->prop_changed
= FALSE
;
721 return flush_output_buffer(This
);
724 static HRESULT WINAPI
mxwriter_saxcontent_startPrefixMapping(
725 ISAXContentHandler
*iface
,
731 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
732 FIXME("(%p)->(%s %s)\n", This
, debugstr_wn(prefix
, nprefix
), debugstr_wn(uri
, nuri
));
736 static HRESULT WINAPI
mxwriter_saxcontent_endPrefixMapping(
737 ISAXContentHandler
*iface
,
741 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
742 FIXME("(%p)->(%s)\n", This
, debugstr_wn(prefix
, nprefix
));
746 static HRESULT WINAPI
mxwriter_saxcontent_startElement(
747 ISAXContentHandler
*iface
,
748 const WCHAR
*namespaceUri
,
750 const WCHAR
*local_name
,
754 ISAXAttributes
*attr
)
756 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
759 TRACE("(%p)->(%s %s %s %p)\n", This
, debugstr_wn(namespaceUri
, nnamespaceUri
),
760 debugstr_wn(local_name
, nlocal_name
), debugstr_wn(QName
, nQName
), attr
);
762 if ((!namespaceUri
|| !local_name
|| !QName
) && This
->class_version
!= MSXML6
)
765 close_element_starttag(This
);
766 set_element_name(This
, QName
? QName
: emptyW
,
769 xmlOutputBufferWriteString(This
->buffer
, "<");
770 s
= xmlchar_from_wcharn(QName
, nQName
);
771 xmlOutputBufferWriteString(This
->buffer
, (char*)s
);
780 hr
= ISAXAttributes_getLength(attr
, &length
);
781 if (FAILED(hr
)) return hr
;
783 for (i
= 0; i
< length
; i
++)
788 hr
= ISAXAttributes_getQName(attr
, i
, &str
, &len
);
789 if (FAILED(hr
)) return hr
;
791 /* space separator in front of every attribute */
792 xmlOutputBufferWriteString(This
->buffer
, " ");
794 s
= xmlchar_from_wcharn(str
, len
);
795 xmlOutputBufferWriteString(This
->buffer
, (char*)s
);
798 xmlOutputBufferWriteString(This
->buffer
, "=\"");
801 hr
= ISAXAttributes_getValue(attr
, i
, &str
, &len
);
802 if (FAILED(hr
)) return hr
;
804 s
= xmlchar_from_wcharn(str
, len
);
805 xmlOutputBufferWriteString(This
->buffer
, (char*)s
);
808 xmlOutputBufferWriteString(This
->buffer
, "\"");
815 static HRESULT WINAPI
mxwriter_saxcontent_endElement(
816 ISAXContentHandler
*iface
,
817 const WCHAR
*namespaceUri
,
819 const WCHAR
* local_name
,
824 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
827 TRACE("(%p)->(%s %s %s)\n", This
, debugstr_wn(namespaceUri
, nnamespaceUri
),
828 debugstr_wn(local_name
, nlocal_name
), debugstr_wn(QName
, nQName
));
830 if ((!namespaceUri
|| !local_name
|| !QName
) && This
->class_version
!= MSXML6
)
833 s
= xmlchar_from_wchar(QName
);
835 if (This
->element
&& QName
&& !strcmpW(This
->element
, QName
))
837 xmlOutputBufferWriteString(This
->buffer
, "/>");
841 xmlOutputBufferWriteString(This
->buffer
, "</");
842 xmlOutputBufferWriteString(This
->buffer
, (char*)s
);
843 xmlOutputBufferWriteString(This
->buffer
, ">");
847 set_element_name(This
, NULL
, 0);
852 static HRESULT WINAPI
mxwriter_saxcontent_characters(
853 ISAXContentHandler
*iface
,
857 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
859 TRACE("(%p)->(%s:%d)\n", This
, debugstr_wn(chars
, nchars
), nchars
);
861 if (!chars
) return E_INVALIDARG
;
863 close_element_starttag(This
);
864 set_element_name(This
, NULL
, 0);
868 xmlChar
*s
= xmlchar_from_wcharn(chars
, nchars
);
869 xmlOutputBufferWriteString(This
->buffer
, (char*)s
);
876 static HRESULT WINAPI
mxwriter_saxcontent_ignorableWhitespace(
877 ISAXContentHandler
*iface
,
881 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
882 FIXME("(%p)->(%s)\n", This
, debugstr_wn(chars
, nchars
));
886 static HRESULT WINAPI
mxwriter_saxcontent_processingInstruction(
887 ISAXContentHandler
*iface
,
893 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
894 FIXME("(%p)->(%s %s)\n", This
, debugstr_wn(target
, ntarget
), debugstr_wn(data
, ndata
));
898 static HRESULT WINAPI
mxwriter_saxcontent_skippedEntity(
899 ISAXContentHandler
*iface
,
903 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
904 FIXME("(%p)->(%s)\n", This
, debugstr_wn(name
, nname
));
908 static const struct ISAXContentHandlerVtbl mxwriter_saxcontent_vtbl
=
910 mxwriter_saxcontent_QueryInterface
,
911 mxwriter_saxcontent_AddRef
,
912 mxwriter_saxcontent_Release
,
913 mxwriter_saxcontent_putDocumentLocator
,
914 mxwriter_saxcontent_startDocument
,
915 mxwriter_saxcontent_endDocument
,
916 mxwriter_saxcontent_startPrefixMapping
,
917 mxwriter_saxcontent_endPrefixMapping
,
918 mxwriter_saxcontent_startElement
,
919 mxwriter_saxcontent_endElement
,
920 mxwriter_saxcontent_characters
,
921 mxwriter_saxcontent_ignorableWhitespace
,
922 mxwriter_saxcontent_processingInstruction
,
923 mxwriter_saxcontent_skippedEntity
926 HRESULT
MXWriter_create(MSXML_VERSION version
, IUnknown
*pUnkOuter
, void **ppObj
)
928 static const WCHAR version10W
[] = {'1','.','0',0};
931 TRACE("(%p,%p)\n", pUnkOuter
, ppObj
);
933 if (pUnkOuter
) FIXME("support aggregation, outer\n");
935 This
= heap_alloc( sizeof (*This
) );
937 return E_OUTOFMEMORY
;
939 This
->IMXWriter_iface
.lpVtbl
= &mxwriter_vtbl
;
940 This
->ISAXContentHandler_iface
.lpVtbl
= &mxwriter_saxcontent_vtbl
;
942 This
->class_version
= version
;
944 This
->props
[MXWriter_BOM
] = VARIANT_TRUE
;
945 This
->props
[MXWriter_DisableEscaping
] = VARIANT_FALSE
;
946 This
->props
[MXWriter_Indent
] = VARIANT_FALSE
;
947 This
->props
[MXWriter_OmitXmlDecl
] = VARIANT_FALSE
;
948 This
->props
[MXWriter_Standalone
] = VARIANT_FALSE
;
949 This
->prop_changed
= FALSE
;
950 This
->encoding
= xmlParseCharEncoding("UTF-16");
951 This
->version
= SysAllocString(version10W
);
953 This
->element
= NULL
;
956 This
->dest_written
= 0;
958 This
->buffer
= xmlAllocOutputBuffer(xmlGetCharEncodingHandler(This
->encoding
));
960 *ppObj
= &This
->IMXWriter_iface
;
962 TRACE("returning iface %p\n", *ppObj
);
969 HRESULT
MXWriter_create(MSXML_VERSION version
, IUnknown
*pUnkOuter
, void **obj
)
971 MESSAGE("This program tried to use a MXXMLWriter object, but\n"
972 "libxml2 support was not present at compile time.\n");
976 #endif /* HAVE_LIBXML2 */