Often after creating a new document or loading the existing one and processing
it, it is necessary to save the result back to file. Also it is occasionally
useful to output the whole document or a subtree to some stream; use cases
include debug printing, serialization via network or other text-oriented medium,
etc. pugixml provides several functions to output any subtree of the document
to a file, stream or another generic transport interface; these functions allow
to customize the output format (see <aclass="xref"href="saving.html#manual.saving.options"title="Output options"> Output options</a>), and also perform
necessary encoding conversions (see <aclass="xref"href="saving.html#manual.saving.encoding"title="Encodings"> Encodings</a>). This section documents
the relevant functionality.
</p>
<p>
The node/attribute data is written to the destination properly formatted according
to the node type; all special XML symbols, such as < and &, are properly
escaped. In order to guard against forgotten node/attribute names, empty node/attribute
names are printed as <codeclass="computeroutput"><spanclass="string">":anonymous"</span></code>.
For proper output, make sure all node and attribute names are set to meaningful
CDATA sections with values that contain <codeclass="computeroutput"><spanclass="string">"]]>"</span></code>
are split into several sections as follows: section with value <codeclass="computeroutput"><spanclass="string">"pre]]>post"</span></code> is written as <codeclass="computeroutput"><spanclass="special"><![</span><spanclass="identifier">CDATA</span><spanclass="special">[</span><spanclass="identifier">pre</span><spanclass="special">]]]]><![</span><spanclass="identifier">CDATA</span><spanclass="special">[></span><spanclass="identifier">post</span><spanclass="special">]]></span></code>.
While this alters the structure of the document (if you load the document after
saving it, there will be two CDATA sections instead of one), this is the only
arguments, which specify indentation and other output options (see <aclass="xref"href="saving.html#manual.saving.options"title="Output options"> Output options</a>)
and output data encoding (see <aclass="xref"href="saving.html#manual.saving.encoding"title="Encodings"> Encodings</a>). The path has the target
operating system format, so it can be a relative or absolute one, it should
have the delimiters of target system, it should have the exact case if target
<codeclass="computeroutput"><spanclass="identifier">save_file</span></code> opens the target
file for writing, outputs the requested header (by default a document declaration
is output, unless the document already has one), and then saves the document
contents. If the file could not be opened, the function returns <codeclass="computeroutput"><spanclass="keyword">false</span></code>. Calling <codeclass="computeroutput"><spanclass="identifier">save_file</span></code>
is equivalent to creating an <codeclass="computeroutput"><spanclass="identifier">xml_writer_file</span></code>
object with <codeclass="computeroutput"><spanclass="identifier">FILE</span><spanclass="special">*</span></code>
handle as the only constructor argument and then calling <codeclass="computeroutput"><spanclass="identifier">save</span></code>;
see <aclass="xref"href="saving.html#manual.saving.writer"title="Saving document via writer interface"> Saving document via writer interface</a> for writer interface details.
</p>
<p>
This is a simple example of saving XML document to file (<ahref="../samples/save_file.cpp"target="_top">samples/save_file.cpp</a>):
</p>
<p>
</p>
<preclass="programlisting"><spanclass="comment">// save document to file
<aname="manual.saving.stream"></a><aclass="link"href="saving.html#manual.saving.stream"title="Saving document to C++ IOstreams"> Saving document to C++ IOstreams</a>
</h3></div></div></div>
<aname="xml_document::save_stream"></a><p>
For additional interoperability pugixml provides functions for saving document
to any object which implements C++ std::ostream interface. This allows you
to save documents to any standard C++ stream (i.e. file stream) or any third-party
compliant implementation (i.e. Boost Iostreams). Most notably, this allows
for easy debug output, since you can use <codeclass="computeroutput"><spanclass="identifier">std</span><spanclass="special">::</span><spanclass="identifier">cout</span></code>
stream as saving target. There are two functions, one works with narrow character
<codeclass="computeroutput"><spanclass="identifier">save</span></code> with <codeclass="computeroutput"><spanclass="identifier">std</span><spanclass="special">::</span><spanclass="identifier">ostream</span></code>
argument saves the document to the stream in the same way as <codeclass="computeroutput"><spanclass="identifier">save_file</span></code> (i.e. with requested header and
with encoding conversions). On the other hand, <codeclass="computeroutput"><spanclass="identifier">save</span></code>
with <codeclass="computeroutput"><spanclass="identifier">std</span><spanclass="special">::</span><spanclass="identifier">wstream</span></code> argument saves the document to
the wide stream with <codeclass="computeroutput"><spanclass="identifier">encoding_wchar</span></code>
encoding. Because of this, using <codeclass="computeroutput"><spanclass="identifier">save</span></code>
with wide character streams requires careful (usually platform-specific)
stream setup (i.e. using the <codeclass="computeroutput"><spanclass="identifier">imbue</span></code>
function). Generally use of wide streams is discouraged, however it provides
you with the ability to save documents to non-Unicode encodings, i.e. you
can save Shift-JIS encoded data if you set the correct locale.
</p>
<aname="xml_writer_stream"></a><p>
Calling <codeclass="computeroutput"><spanclass="identifier">save</span></code> with stream
target is equivalent to creating an <codeclass="computeroutput"><spanclass="identifier">xml_writer_stream</span></code>
object with stream as the only constructor argument and then calling <codeclass="computeroutput"><spanclass="identifier">save</span></code>; see <aclass="xref"href="saving.html#manual.saving.writer"title="Saving document via writer interface"> Saving document via writer interface</a> for writer
interface details.
</p>
<p>
This is a simple example of saving XML document to standard output (<ahref="../samples/save_stream.cpp"target="_top">samples/save_stream.cpp</a>):
</p>
<p>
</p>
<preclass="programlisting"><spanclass="comment">// save document to standard output
<aname="manual.saving.writer"></a><aclass="link"href="saving.html#manual.saving.writer"title="Saving document via writer interface"> Saving document via writer interface</a>
function is called with a buffer as an input, where <codeclass="computeroutput"><spanclass="identifier">data</span></code>
points to buffer start, and <codeclass="computeroutput"><spanclass="identifier">size</span></code>
is equal to the buffer size in bytes. <codeclass="computeroutput"><spanclass="identifier">write</span></code>
implementation must write the buffer to the transport; it can not save the
passed buffer pointer, as the buffer contents will change after <codeclass="computeroutput"><spanclass="identifier">write</span></code> returns. The buffer contains the
chunk of document data in the desired encoding.
</p>
<p>
<codeclass="computeroutput"><spanclass="identifier">write</span></code> function is called
with relatively large blocks (size is usually several kilobytes, except for
the first block with BOM, which is output only if <codeclass="computeroutput"><spanclass="identifier">format_write_bom</span></code>
is set, and last block, which may be small), so there is often no need for
additional buffering in the implementation.
</p>
<p>
This is a simple example of custom writer for saving document data to STL
These functions have the same arguments with the same meaning as the corresponding
<codeclass="computeroutput"><spanclass="identifier">xml_document</span><spanclass="special">::</span><spanclass="identifier">save</span></code> functions, and allow you to save the
subtree to either a C++ IOstream or to any object that implements <codeclass="computeroutput"><spanclass="identifier">xml_writer</span></code> interface.
</p>
<p>
Saving a subtree differs from saving the whole document: the process behaves
as if <codeclass="computeroutput"><spanclass="identifier">format_write_bom</span></code> is
off, and <codeclass="computeroutput"><spanclass="identifier">format_no_declaration</span></code>
is on, even if actual values of the flags are different. This means that
BOM is not written to the destination, and document declaration is only written
if it is the node itself or is one of node's children. Note that this also
holds if you're saving a document; this example (<ahref="../samples/save_subtree.cpp"target="_top">samples/save_subtree.cpp</a>)
illustrates the difference:
</p>
<p>
</p>
<preclass="programlisting"><spanclass="comment">// get a test document
<spanclass="comment">// print document to standard output (prints <?xml version="1.0"?><foo bar="baz"><call>hey</call></foo>)
You should use the usual bitwise arithmetics to manipulate the bitmask:
to enable a flag, use <codeclass="computeroutput"><spanclass="identifier">mask</span><spanclass="special">|</span><spanclass="identifier">flag</span></code>;
to disable a flag, use <codeclass="computeroutput"><spanclass="identifier">mask</span><spanclass="special">&</span><spanclass="special">~</span><spanclass="identifier">flag</span></code>.
to disable default node declaration output. By default, if the document
is saved via <codeclass="computeroutput"><spanclass="identifier">save</span></code> or
<codeclass="computeroutput"><spanclass="identifier">save_file</span></code> function, and
it does not have any document declaration, a default declaration is output
before the document contents. Enabling this flag disables this declaration.
This flag has no effect in <codeclass="computeroutput"><spanclass="identifier">xml_node</span><spanclass="special">::</span><spanclass="identifier">print</span></code>
functions: they never output the default declaration. This flag is <spanclass="bold"><strong>off</strong></span> by default. <br><br>
</li>
<liclass="listitem">
<aname="format_write_bom"></a><codeclass="literal">format_write_bom</code> allows to enable
Byte Order Mark (BOM) output. By default, no BOM is output, so in case
of non UTF-8 encodings the resulting document's encoding may not be recognized
by some parsers and text editors, if they do not implement sophisticated
encoding detection. Enabling this flag adds an encoding-specific BOM
to the output. This flag has no effect in <codeclass="computeroutput"><spanclass="identifier">xml_node</span><spanclass="special">::</span><spanclass="identifier">print</span></code>
functions: they never output the BOM. This flag is <spanclass="bold"><strong>off</strong></span>
by default.
</li>
</ul></div>
<p>
Additionally, there is one predefined option mask:
<aname="format_default"></a><codeclass="literal">format_default</code> is the default set of
flags, i.e. it has all options set to their default values. It sets formatted
output with indentation, without BOM and with default node declaration,
if necessary.
</li></ul></div>
<p>
This is an example that shows the outputs of different output options (<ahref="../samples/save_options.cpp"target="_top">samples/save_options.cpp</a>):
</p>
<p>
</p>
<preclass="programlisting"><spanclass="comment">// get a test document
</span><spanclass="identifier">doc</span><spanclass="special">.</span><spanclass="identifier">save</span><spanclass="special">(</span><spanclass="identifier">std</span><spanclass="special">::</span><spanclass="identifier">cout</span><spanclass="special">,</span><spanclass="string">"\t"</span><spanclass="special">,</span><spanclass="identifier">pugi</span><spanclass="special">::</span><spanclass="identifier">format_default</span><spanclass="special">&</span><spanclass="special">~</span><spanclass="identifier">pugi</span><spanclass="special">::</span><spanclass="identifier">format_indent</span><spanclass="special">);</span><spanclass="comment">// can also pass "" instead of indentation string for the same effect