Skip to content
Snippets Groups Projects
manual.html 557 KiB
Newer Older
<p>It is possible to copy a subtree as a child of some node inside this subtree, i.e. <code>node.append_copy(node.parent().parent());</code>. This is a valid operation, and it results in a clone of the subtree in the state before cloning started, i.e. no infinite recursion takes place.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>This is an example with one possible implementation of include tags in XML (<a href="samples/include.cpp" class="bare">samples/include.cpp</a>). It illustrates node cloning and usage of other document modification functions:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-kt">bool</span> <span class="tok-nf">load_preprocess</span><span class="tok-p">(</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_document</span><span class="tok-o">&amp;</span> <span class="tok-n">doc</span><span class="tok-p">,</span> <span class="tok-k">const</span> <span class="tok-kt">char</span><span class="tok-o">*</span> <span class="tok-n">path</span><span class="tok-p">);</span>

<span class="tok-kt">bool</span> <span class="tok-nf">preprocess</span><span class="tok-p">(</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_node</span> <span class="tok-n">node</span><span class="tok-p">)</span>
<span class="tok-p">{</span>
    <span class="tok-k">for</span> <span class="tok-p">(</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_node</span> <span class="tok-n">child</span> <span class="tok-o">=</span> <span class="tok-n">node</span><span class="tok-p">.</span><span class="tok-n">first_child</span><span class="tok-p">();</span> <span class="tok-n">child</span><span class="tok-p">;</span> <span class="tok-p">)</span>
    <span class="tok-p">{</span>
        <span class="tok-k">if</span> <span class="tok-p">(</span><span class="tok-n">child</span><span class="tok-p">.</span><span class="tok-n">type</span><span class="tok-p">()</span> <span class="tok-o">==</span> <span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">node_pi</span> <span class="tok-o">&amp;&amp;</span> <span class="tok-n">strcmp</span><span class="tok-p">(</span><span class="tok-n">child</span><span class="tok-p">.</span><span class="tok-n">name</span><span class="tok-p">(),</span> <span class="tok-s">&quot;include&quot;</span><span class="tok-p">)</span> <span class="tok-o">==</span> <span class="tok-mi">0</span><span class="tok-p">)</span>
        <span class="tok-p">{</span>
            <span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_node</span> <span class="tok-n">include</span> <span class="tok-o">=</span> <span class="tok-n">child</span><span class="tok-p">;</span>

            <span class="tok-c1">// load new preprocessed document (note: ideally this should handle relative paths)</span>
            <span class="tok-k">const</span> <span class="tok-kt">char</span><span class="tok-o">*</span> <span class="tok-n">path</span> <span class="tok-o">=</span> <span class="tok-n">include</span><span class="tok-p">.</span><span class="tok-n">value</span><span class="tok-p">();</span>

            <span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_document</span> <span class="tok-n">doc</span><span class="tok-p">;</span>
            <span class="tok-k">if</span> <span class="tok-p">(</span><span class="tok-o">!</span><span class="tok-n">load_preprocess</span><span class="tok-p">(</span><span class="tok-n">doc</span><span class="tok-p">,</span> <span class="tok-n">path</span><span class="tok-p">))</span> <span class="tok-k">return</span> <span class="tok-nb">false</span><span class="tok-p">;</span>

            <span class="tok-c1">// insert the comment marker above include directive</span>
            <span class="tok-n">node</span><span class="tok-p">.</span><span class="tok-n">insert_child_before</span><span class="tok-p">(</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">node_comment</span><span class="tok-p">,</span> <span class="tok-n">include</span><span class="tok-p">).</span><span class="tok-n">set_value</span><span class="tok-p">(</span><span class="tok-n">path</span><span class="tok-p">);</span>

            <span class="tok-c1">// copy the document above the include directive (this retains the original order!)</span>
            <span class="tok-k">for</span> <span class="tok-p">(</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_node</span> <span class="tok-n">ic</span> <span class="tok-o">=</span> <span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">first_child</span><span class="tok-p">();</span> <span class="tok-n">ic</span><span class="tok-p">;</span> <span class="tok-n">ic</span> <span class="tok-o">=</span> <span class="tok-n">ic</span><span class="tok-p">.</span><span class="tok-n">next_sibling</span><span class="tok-p">())</span>
            <span class="tok-p">{</span>
                <span class="tok-n">node</span><span class="tok-p">.</span><span class="tok-n">insert_copy_before</span><span class="tok-p">(</span><span class="tok-n">ic</span><span class="tok-p">,</span> <span class="tok-n">include</span><span class="tok-p">);</span>
            <span class="tok-p">}</span>

            <span class="tok-c1">// remove the include node and move to the next child</span>
            <span class="tok-n">child</span> <span class="tok-o">=</span> <span class="tok-n">child</span><span class="tok-p">.</span><span class="tok-n">next_sibling</span><span class="tok-p">();</span>

            <span class="tok-n">node</span><span class="tok-p">.</span><span class="tok-n">remove_child</span><span class="tok-p">(</span><span class="tok-n">include</span><span class="tok-p">);</span>
        <span class="tok-p">}</span>
        <span class="tok-k">else</span>
        <span class="tok-p">{</span>
            <span class="tok-k">if</span> <span class="tok-p">(</span><span class="tok-o">!</span><span class="tok-n">preprocess</span><span class="tok-p">(</span><span class="tok-n">child</span><span class="tok-p">))</span> <span class="tok-k">return</span> <span class="tok-nb">false</span><span class="tok-p">;</span>

            <span class="tok-n">child</span> <span class="tok-o">=</span> <span class="tok-n">child</span><span class="tok-p">.</span><span class="tok-n">next_sibling</span><span class="tok-p">();</span>
        <span class="tok-p">}</span>
    <span class="tok-p">}</span>

    <span class="tok-k">return</span> <span class="tok-nb">true</span><span class="tok-p">;</span>
<span class="tok-p">}</span>

<span class="tok-kt">bool</span> <span class="tok-nf">load_preprocess</span><span class="tok-p">(</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_document</span><span class="tok-o">&amp;</span> <span class="tok-n">doc</span><span class="tok-p">,</span> <span class="tok-k">const</span> <span class="tok-kt">char</span><span class="tok-o">*</span> <span class="tok-n">path</span><span class="tok-p">)</span>
<span class="tok-p">{</span>
    <span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_parse_result</span> <span class="tok-n">result</span> <span class="tok-o">=</span> <span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">load_file</span><span class="tok-p">(</span><span class="tok-n">path</span><span class="tok-p">,</span> <span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">parse_default</span> <span class="tok-o">|</span> <span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">parse_pi</span><span class="tok-p">);</span> <span class="tok-c1">// for &lt;?include?&gt;</span>

    <span class="tok-k">return</span> <span class="tok-n">result</span> <span class="tok-o">?</span> <span class="tok-n">preprocess</span><span class="tok-p">(</span><span class="tok-n">doc</span><span class="tok-p">)</span> <span class="tok-o">:</span> <span class="tok-nb">false</span><span class="tok-p">;</span>
<span class="tok-p">}</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="modify.move"><a class="anchor" href="#modify.move"></a><a class="link" href="#modify.move">6.6. Moving nodes</a></h3>
<div class="paragraph">
<p><a id="xml_node::prepend_move"></a><a id="xml_node::append_move"></a><a id="xml_node::insert_move_after"></a><a id="xml_node::insert_move_before"></a>
Sometimes instead of cloning a node you need to move an existing node to a different position in a tree. This can be accomplished by copying the node and removing the original; however, this is expensive since it results in a lot of extra operations. For moving nodes within the same document tree, you can use of the following functions instead:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-n">xml_node</span> <span class="tok-n">xml_node</span><span class="tok-o">::</span><span class="tok-n">append_move</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">xml_node</span><span class="tok-o">&amp;</span> <span class="tok-n">moved</span><span class="tok-p">);</span>
<span class="tok-n">xml_node</span> <span class="tok-n">xml_node</span><span class="tok-o">::</span><span class="tok-n">prepend_move</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">xml_node</span><span class="tok-o">&amp;</span> <span class="tok-n">moved</span><span class="tok-p">);</span>
<span class="tok-n">xml_node</span> <span class="tok-n">xml_node</span><span class="tok-o">::</span><span class="tok-n">insert_move_after</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">xml_node</span><span class="tok-o">&amp;</span> <span class="tok-n">moved</span><span class="tok-p">,</span> <span class="tok-k">const</span> <span class="tok-n">xml_node</span><span class="tok-o">&amp;</span> <span class="tok-n">node</span><span class="tok-p">);</span>
<span class="tok-n">xml_node</span> <span class="tok-n">xml_node</span><span class="tok-o">::</span><span class="tok-n">insert_move_before</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">xml_node</span><span class="tok-o">&amp;</span> <span class="tok-n">moved</span><span class="tok-p">,</span> <span class="tok-k">const</span> <span class="tok-n">xml_node</span><span class="tok-o">&amp;</span> <span class="tok-n">node</span><span class="tok-p">);</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>These functions mirror the structure of <code>append_copy</code>, <code>prepend_copy</code>, <code>insert_copy_before</code> and <code>insert_copy_after</code> - they take the handle to the moved object and move it to the appropriate place with all attributes and/or child nodes. The functions return the handle to the resulting object (which is the same as the moved object), or null handle on failure.</p>
</div>
<div class="paragraph">
<p>The failure conditions resemble those of <code>append_child</code>, <code>insert_child_before</code> and related functions, <a href="#xml_node::append_child">consult their documentation for more information</a>. There are additional caveats specific to moving functions:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Moving null handles results in operation failure;</p>
</li>
<li>
<p>Moving is only possible for nodes that belong to the same document; attempting to move nodes between documents will fail.</p>
</li>
<li>
<p><code>insert_move_after</code> and <code>insert_move_before</code> functions fail if the moved node is the same as the <code>node</code> argument (this operation would be a no-op otherwise).</p>
</li>
<li>
<p>It is impossible to move a subtree to a child of some node inside this subtree, i.e. <code>node.append_move(node.parent().parent());</code> will fail.</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="modify.fragments"><a class="anchor" href="#modify.fragments"></a><a class="link" href="#modify.fragments">6.7. Assembling document from fragments</a></h3>
<div id="xml_node::append_buffer" class="paragraph">
<p>pugixml provides several ways to assemble an XML document from other XML documents. Assuming there is a set of document fragments, represented as in-memory buffers, the implementation choices are as follows:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Use a temporary document to parse the data from a string, then clone the nodes to a destination node. For example:</p>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-kt">bool</span> <span class="tok-nf">append_fragment</span><span class="tok-p">(</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_node</span> <span class="tok-n">target</span><span class="tok-p">,</span> <span class="tok-k">const</span> <span class="tok-kt">char</span><span class="tok-o">*</span> <span class="tok-n">buffer</span><span class="tok-p">,</span> <span class="tok-kt">size_t</span> <span class="tok-n">size</span><span class="tok-p">)</span>
<span class="tok-p">{</span>
    <span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_document</span> <span class="tok-n">doc</span><span class="tok-p">;</span>
    <span class="tok-k">if</span> <span class="tok-p">(</span><span class="tok-o">!</span><span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">load_buffer</span><span class="tok-p">(</span><span class="tok-n">buffer</span><span class="tok-p">,</span> <span class="tok-n">size</span><span class="tok-p">))</span> <span class="tok-k">return</span> <span class="tok-nb">false</span><span class="tok-p">;</span>

    <span class="tok-k">for</span> <span class="tok-p">(</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_node</span> <span class="tok-n">child</span> <span class="tok-o">=</span> <span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">first_child</span><span class="tok-p">();</span> <span class="tok-n">child</span><span class="tok-p">;</span> <span class="tok-n">child</span> <span class="tok-o">=</span> <span class="tok-n">child</span><span class="tok-p">.</span><span class="tok-n">next_sibling</span><span class="tok-p">())</span>
        <span class="tok-n">target</span><span class="tok-p">.</span><span class="tok-n">append_copy</span><span class="tok-p">(</span><span class="tok-n">child</span><span class="tok-p">);</span>
<span class="tok-p">}</span></code></pre>
</div>
</div>
</li>
<li>
<p>Cache the parsing step - instead of keeping in-memory buffers, keep document objects that already contain the parsed fragment:</p>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-kt">bool</span> <span class="tok-nf">append_fragment</span><span class="tok-p">(</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_node</span> <span class="tok-n">target</span><span class="tok-p">,</span> <span class="tok-k">const</span> <span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_document</span><span class="tok-o">&amp;</span> <span class="tok-n">cached_fragment</span><span class="tok-p">)</span>
<span class="tok-p">{</span>
    <span class="tok-k">for</span> <span class="tok-p">(</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_node</span> <span class="tok-n">child</span> <span class="tok-o">=</span> <span class="tok-n">cached_fragment</span><span class="tok-p">.</span><span class="tok-n">first_child</span><span class="tok-p">();</span> <span class="tok-n">child</span><span class="tok-p">;</span> <span class="tok-n">child</span> <span class="tok-o">=</span> <span class="tok-n">child</span><span class="tok-p">.</span><span class="tok-n">next_sibling</span><span class="tok-p">())</span>
        <span class="tok-n">target</span><span class="tok-p">.</span><span class="tok-n">append_copy</span><span class="tok-p">(</span><span class="tok-n">child</span><span class="tok-p">);</span>
<span class="tok-p">}</span></code></pre>
</div>
</div>
</li>
<li>
<p>Use <code>xml_node::append_buffer</code> directly:</p>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-n">xml_parse_result</span> <span class="tok-n">xml_node</span><span class="tok-o">::</span><span class="tok-n">append_buffer</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-kt">void</span><span class="tok-o">*</span> <span class="tok-n">contents</span><span class="tok-p">,</span> <span class="tok-kt">size_t</span> <span class="tok-n">size</span><span class="tok-p">,</span> <span class="tok-kt">unsigned</span> <span class="tok-kt">int</span> <span class="tok-n">options</span> <span class="tok-o">=</span> <span class="tok-n">parse_default</span><span class="tok-p">,</span> <span class="tok-n">xml_encoding</span> <span class="tok-n">encoding</span> <span class="tok-o">=</span> <span class="tok-n">encoding_auto</span><span class="tok-p">);</span></code></pre>
</div>
</div>
</li>
</ul>
</div>
<div class="paragraph">
<p>The first method is more convenient, but slower than the other two. The relative performance of <code>append_copy</code> and <code>append_buffer</code> depends on the buffer format - usually <code>append_buffer</code> is faster if the buffer is in native encoding (UTF-8 or wchar_t, depending on <code>PUGIXML_WCHAR_MODE</code>). At the same time it might be less efficient in terms of memory usage - the implementation makes a copy of the provided buffer, and the copy has the same lifetime as the document - the memory used by that copy will be reclaimed after the document is destroyed, but no sooner. Even deleting all nodes in the document, including the appended ones, won&#8217;t reclaim the memory.</p>
</div>
<div class="paragraph">
<p><code>append_buffer</code> behaves in the same way as <a href="#xml_document::load_buffer">xml_document::load_buffer</a> - the input buffer is a byte buffer, with size in bytes; the buffer is not modified and can be freed after the function returns.</p>
</div>
<div id="status_append_invalid_root" class="paragraph">
<p>Since <code>append_buffer</code> needs to append child nodes to the current node, it only works if the current node is either document or element node. Calling <code>append_buffer</code> on a node with any other type results in an error with <code>status_append_invalid_root</code> status.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="saving"><a class="anchor" href="#saving"></a><a class="link" href="#saving">7. Saving document</a></h2>
<div class="sectionbody">
<div class="paragraph">
<p>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 <a href="#saving.options">Output options</a>), and also perform necessary encoding conversions (see <a href="#saving.encoding">Encodings</a>). This section documents the relevant functionality.</p>
</div>
<div class="paragraph">
<p>Before writing to the destination the node/attribute data is properly formatted according to the node type; all special XML symbols, such as <code>&lt;</code> and <code>&amp;</code>, are properly escaped (unless <a href="#format_no_escapes">format_no_escapes</a> flag is set). In order to guard against forgotten node/attribute names, empty node/attribute names are printed as <code>":anonymous"</code>. For well-formed output, make sure all node and attribute names are set to meaningful values.</p>
</div>
<div class="paragraph">
<p>CDATA sections with values that contain <code>"]]&gt;"</code> are split into several sections as follows: section with value <code>"pre]]&gt;post"</code> is written as <code>&lt;![CDATA[pre]]]]&gt;&lt;![CDATA[&gt;post]]&gt;</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 way to escape CDATA contents.</p>
</div>
<div class="sect2">
<h3 id="saving.file"><a class="anchor" href="#saving.file"></a><a class="link" href="#saving.file">7.1. Saving document to a file</a></h3>
<div class="paragraph">
<p><a id="xml_document::save_file"></a><a id="xml_document::save_file_wide"></a>
If you want to save the whole document to a file, you can use one of the following functions:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-kt">bool</span> <span class="tok-n">xml_document</span><span class="tok-o">::</span><span class="tok-n">save_file</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-kt">char</span><span class="tok-o">*</span> <span class="tok-n">path</span><span class="tok-p">,</span> <span class="tok-k">const</span> <span class="tok-n">char_t</span><span class="tok-o">*</span> <span class="tok-n">indent</span> <span class="tok-o">=</span> <span class="tok-s">&quot;</span><span class="tok-se">\t</span><span class="tok-s">&quot;</span><span class="tok-p">,</span> <span class="tok-kt">unsigned</span> <span class="tok-kt">int</span> <span class="tok-n">flags</span> <span class="tok-o">=</span> <span class="tok-n">format_default</span><span class="tok-p">,</span> <span class="tok-n">xml_encoding</span> <span class="tok-n">encoding</span> <span class="tok-o">=</span> <span class="tok-n">encoding_auto</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span>
<span class="tok-kt">bool</span> <span class="tok-n">xml_document</span><span class="tok-o">::</span><span class="tok-n">save_file</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-kt">wchar_t</span><span class="tok-o">*</span> <span class="tok-n">path</span><span class="tok-p">,</span> <span class="tok-k">const</span> <span class="tok-n">char_t</span><span class="tok-o">*</span> <span class="tok-n">indent</span> <span class="tok-o">=</span> <span class="tok-s">&quot;</span><span class="tok-se">\t</span><span class="tok-s">&quot;</span><span class="tok-p">,</span> <span class="tok-kt">unsigned</span> <span class="tok-kt">int</span> <span class="tok-n">flags</span> <span class="tok-o">=</span> <span class="tok-n">format_default</span><span class="tok-p">,</span> <span class="tok-n">xml_encoding</span> <span class="tok-n">encoding</span> <span class="tok-o">=</span> <span class="tok-n">encoding_auto</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>These functions accept file path as its first argument, and also three optional arguments, which specify indentation and other output options (see <a href="#saving.options">Output options</a>) and output data encoding (see <a href="#saving.encoding">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 the target system, it should have the exact case if the target file system is case-sensitive, etc.</p>
</div>
<div class="paragraph">
<p>File path is passed to the system file opening function as is in case of the first function (which accepts <code>const char* path</code>); the second function either uses a special file opening function if it is provided by the runtime library or converts the path to UTF-8 and uses the system file opening function.</p>
</div>
<div id="xml_writer_file" class="paragraph">
<p><code>save_file</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 <code>false</code>. Calling <code>save_file</code> is equivalent to creating an <code>xml_writer_file</code> object with <code>FILE*</code> handle as the only constructor argument and then calling <code>save</code>; see <a href="#saving.writer">Saving document via writer interface</a> for writer interface details.</p>
</div>
<div class="paragraph">
<p>This is a simple example of saving XML document to file (<a href="samples/save_file.cpp" class="bare">samples/save_file.cpp</a>):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-c1">// save document to file</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o">&lt;&lt;</span> <span class="tok-s">&quot;Saving result: &quot;</span> <span class="tok-o">&lt;&lt;</span> <span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">save_file</span><span class="tok-p">(</span><span class="tok-s">&quot;save_file_output.xml&quot;</span><span class="tok-p">)</span> <span class="tok-o">&lt;&lt;</span> <span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="saving.stream"><a class="anchor" href="#saving.stream"></a><a class="link" href="#saving.stream">7.2. Saving document to C&#43;&#43; IOstreams</a></h3>
<div id="xml_document::save_stream" class="paragraph">
<p>To enhance interoperability pugixml provides functions for saving document to any object which implements C&#43;&#43; <code>std::ostream</code> interface. This allows you to save documents to any standard C&#43;&#43; 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 <code>std::cout</code> stream as saving target. There are two functions, one works with narrow character streams, another handles wide character ones:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-kt">void</span> <span class="tok-n">xml_document</span><span class="tok-o">::</span><span class="tok-n">save</span><span class="tok-p">(</span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">ostream</span><span class="tok-o">&amp;</span> <span class="tok-n">stream</span><span class="tok-p">,</span> <span class="tok-k">const</span> <span class="tok-n">char_t</span><span class="tok-o">*</span> <span class="tok-n">indent</span> <span class="tok-o">=</span> <span class="tok-s">&quot;</span><span class="tok-se">\t</span><span class="tok-s">&quot;</span><span class="tok-p">,</span> <span class="tok-kt">unsigned</span> <span class="tok-kt">int</span> <span class="tok-n">flags</span> <span class="tok-o">=</span> <span class="tok-n">format_default</span><span class="tok-p">,</span> <span class="tok-n">xml_encoding</span> <span class="tok-n">encoding</span> <span class="tok-o">=</span> <span class="tok-n">encoding_auto</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span>
<span class="tok-kt">void</span> <span class="tok-n">xml_document</span><span class="tok-o">::</span><span class="tok-n">save</span><span class="tok-p">(</span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">wostream</span><span class="tok-o">&amp;</span> <span class="tok-n">stream</span><span class="tok-p">,</span> <span class="tok-k">const</span> <span class="tok-n">char_t</span><span class="tok-o">*</span> <span class="tok-n">indent</span> <span class="tok-o">=</span> <span class="tok-s">&quot;</span><span class="tok-se">\t</span><span class="tok-s">&quot;</span><span class="tok-p">,</span> <span class="tok-kt">unsigned</span> <span class="tok-kt">int</span> <span class="tok-n">flags</span> <span class="tok-o">=</span> <span class="tok-n">format_default</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><code>save</code> with <code>std::ostream</code> argument saves the document to the stream in the same way as <code>save_file</code> (i.e. with requested header and with encoding conversions). On the other hand, <code>save</code> with <code>std::wstream</code> argument saves the document to the wide stream with <a href="#encoding_wchar">encoding_wchar</a> encoding.  Because of this, using <code>save</code> with wide character streams requires careful (usually platform-specific) stream setup (i.e. using the <code>imbue</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>
</div>
<div id="xml_writer_stream" class="paragraph">
<p>Calling <code>save</code> with stream target is equivalent to creating an <code>xml_writer_stream</code> object with stream as the only constructor argument and then calling <code>save</code>; see <a href="#saving.writer">Saving document via writer interface</a> for writer interface details.</p>
</div>
<div class="paragraph">
<p>This is a simple example of saving XML document to standard output (<a href="samples/save_stream.cpp" class="bare">samples/save_stream.cpp</a>):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-c1">// save document to standard output</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o">&lt;&lt;</span> <span class="tok-s">&quot;Document:</span><span class="tok-se">\n</span><span class="tok-s">&quot;</span><span class="tok-p">;</span>
<span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">save</span><span class="tok-p">(</span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-p">);</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="saving.writer"><a class="anchor" href="#saving.writer"></a><a class="link" href="#saving.writer">7.3. Saving document via writer interface</a></h3>
<div class="paragraph">
<p><a id="xml_document::save"></a><a id="xml_writer"></a><a id="xml_writer::write"></a>
All of the above saving functions are implemented in terms of writer interface. This is a simple interface with a single function, which is called several times during output process with chunks of document data as input:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-k">class</span> <span class="tok-nc">xml_writer</span>
<span class="tok-p">{</span>
<span class="tok-k">public</span><span class="tok-o">:</span>
    <span class="tok-k">virtual</span> <span class="tok-kt">void</span> <span class="tok-n">write</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-kt">void</span><span class="tok-o">*</span> <span class="tok-n">data</span><span class="tok-p">,</span> <span class="tok-kt">size_t</span> <span class="tok-n">size</span><span class="tok-p">)</span> <span class="tok-o">=</span> <span class="tok-mi">0</span><span class="tok-p">;</span>
<span class="tok-p">};</span>

<span class="tok-kt">void</span> <span class="tok-n">xml_document</span><span class="tok-o">::</span><span class="tok-n">save</span><span class="tok-p">(</span><span class="tok-n">xml_writer</span><span class="tok-o">&amp;</span> <span class="tok-n">writer</span><span class="tok-p">,</span> <span class="tok-k">const</span> <span class="tok-n">char_t</span><span class="tok-o">*</span> <span class="tok-n">indent</span> <span class="tok-o">=</span> <span class="tok-s">&quot;</span><span class="tok-se">\t</span><span class="tok-s">&quot;</span><span class="tok-p">,</span> <span class="tok-kt">unsigned</span> <span class="tok-kt">int</span> <span class="tok-n">flags</span> <span class="tok-o">=</span> <span class="tok-n">format_default</span><span class="tok-p">,</span> <span class="tok-n">xml_encoding</span> <span class="tok-n">encoding</span> <span class="tok-o">=</span> <span class="tok-n">encoding_auto</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>In order to output the document via some custom transport, for example sockets, you should create an object which implements <code>xml_writer</code> interface and pass it to <code>save</code> function. <code>xml_writer::write</code> function is called with a buffer as an input, where <code>data</code> points to buffer start, and <code>size</code> is equal to the buffer size in bytes. <code>write</code> implementation must write the buffer to the transport; it can not save the passed buffer pointer, as the buffer contents will change after <code>write</code> returns. The buffer contains the chunk of document data in the desired encoding.</p>
</div>
<div class="paragraph">
<p><code>write</code> function is called with relatively large blocks (size is usually several kilobytes, except for the last block that may be small), so there is often no need for additional buffering in the implementation.</p>
</div>
<div class="paragraph">
<p>This is a simple example of custom writer for saving document data to STL string (<a href="samples/save_custom_writer.cpp" class="bare">samples/save_custom_writer.cpp</a>); read the sample code for more complex examples:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-k">struct</span> <span class="tok-nl">xml_string_writer</span><span class="tok-p">:</span> <span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_writer</span>
<span class="tok-p">{</span>
    <span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">string</span> <span class="tok-n">result</span><span class="tok-p">;</span>

    <span class="tok-k">virtual</span> <span class="tok-kt">void</span> <span class="tok-nf">write</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-kt">void</span><span class="tok-o">*</span> <span class="tok-n">data</span><span class="tok-p">,</span> <span class="tok-kt">size_t</span> <span class="tok-n">size</span><span class="tok-p">)</span>
    <span class="tok-p">{</span>
        <span class="tok-n">result</span><span class="tok-p">.</span><span class="tok-n">append</span><span class="tok-p">(</span><span class="tok-k">static_cast</span><span class="tok-o">&lt;</span><span class="tok-k">const</span> <span class="tok-kt">char</span><span class="tok-o">*&gt;</span><span class="tok-p">(</span><span class="tok-n">data</span><span class="tok-p">),</span> <span class="tok-n">size</span><span class="tok-p">);</span>
    <span class="tok-p">}</span>
<span class="tok-p">};</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="saving.subtree"><a class="anchor" href="#saving.subtree"></a><a class="link" href="#saving.subtree">7.4. Saving a single subtree</a></h3>
<div class="paragraph">
<p><a id="xml_node::print"></a><a id="xml_node::print_stream"></a>
While the previously described functions save the whole document to the destination, it is easy to save a single subtree. The following functions are provided:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-kt">void</span> <span class="tok-n">xml_node</span><span class="tok-o">::</span><span class="tok-n">print</span><span class="tok-p">(</span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">ostream</span><span class="tok-o">&amp;</span> <span class="tok-n">os</span><span class="tok-p">,</span> <span class="tok-k">const</span> <span class="tok-n">char_t</span><span class="tok-o">*</span> <span class="tok-n">indent</span> <span class="tok-o">=</span> <span class="tok-s">&quot;</span><span class="tok-se">\t</span><span class="tok-s">&quot;</span><span class="tok-p">,</span> <span class="tok-kt">unsigned</span> <span class="tok-kt">int</span> <span class="tok-n">flags</span> <span class="tok-o">=</span> <span class="tok-n">format_default</span><span class="tok-p">,</span> <span class="tok-n">xml_encoding</span> <span class="tok-n">encoding</span> <span class="tok-o">=</span> <span class="tok-n">encoding_auto</span><span class="tok-p">,</span> <span class="tok-kt">unsigned</span> <span class="tok-kt">int</span> <span class="tok-n">depth</span> <span class="tok-o">=</span> <span class="tok-mi">0</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span>
<span class="tok-kt">void</span> <span class="tok-n">xml_node</span><span class="tok-o">::</span><span class="tok-n">print</span><span class="tok-p">(</span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">wostream</span><span class="tok-o">&amp;</span> <span class="tok-n">os</span><span class="tok-p">,</span> <span class="tok-k">const</span> <span class="tok-n">char_t</span><span class="tok-o">*</span> <span class="tok-n">indent</span> <span class="tok-o">=</span> <span class="tok-s">&quot;</span><span class="tok-se">\t</span><span class="tok-s">&quot;</span><span class="tok-p">,</span> <span class="tok-kt">unsigned</span> <span class="tok-kt">int</span> <span class="tok-n">flags</span> <span class="tok-o">=</span> <span class="tok-n">format_default</span><span class="tok-p">,</span> <span class="tok-kt">unsigned</span> <span class="tok-kt">int</span> <span class="tok-n">depth</span> <span class="tok-o">=</span> <span class="tok-mi">0</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span>
<span class="tok-kt">void</span> <span class="tok-n">xml_node</span><span class="tok-o">::</span><span class="tok-n">print</span><span class="tok-p">(</span><span class="tok-n">xml_writer</span><span class="tok-o">&amp;</span> <span class="tok-n">writer</span><span class="tok-p">,</span> <span class="tok-k">const</span> <span class="tok-n">char_t</span><span class="tok-o">*</span> <span class="tok-n">indent</span> <span class="tok-o">=</span> <span class="tok-s">&quot;</span><span class="tok-se">\t</span><span class="tok-s">&quot;</span><span class="tok-p">,</span> <span class="tok-kt">unsigned</span> <span class="tok-kt">int</span> <span class="tok-n">flags</span> <span class="tok-o">=</span> <span class="tok-n">format_default</span><span class="tok-p">,</span> <span class="tok-n">xml_encoding</span> <span class="tok-n">encoding</span> <span class="tok-o">=</span> <span class="tok-n">encoding_auto</span><span class="tok-p">,</span> <span class="tok-kt">unsigned</span> <span class="tok-kt">int</span> <span class="tok-n">depth</span> <span class="tok-o">=</span> <span class="tok-mi">0</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>These functions have the same arguments with the same meaning as the corresponding <code>xml_document::save</code> functions, and allow you to save the subtree to either a C&#43;&#43; IOstream or to any object that implements <code>xml_writer</code> interface.</p>
</div>
<div class="paragraph">
<p>Saving a subtree differs from saving the whole document: the process behaves as if <a href="#format_write_bom">format_write_bom</a> is off, and <a href="#format_no_declaration">format_no_declaration</a> 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&#8217;s children. Note that this also holds if you&#8217;re saving a document; this example (<a href="samples/save_subtree.cpp" class="bare">samples/save_subtree.cpp</a>) illustrates the difference:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-c1">// get a test document</span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_document</span> <span class="tok-n">doc</span><span class="tok-p">;</span>
<span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">load_string</span><span class="tok-p">(</span><span class="tok-s">&quot;&lt;foo bar=&#39;baz&#39;&gt;&lt;call&gt;hey&lt;/call&gt;&lt;/foo&gt;&quot;</span><span class="tok-p">);</span>

<span class="tok-c1">// print document to standard output (prints &lt;?xml version=&quot;1.0&quot;?&gt;&lt;foo bar=&quot;baz&quot;&gt;&lt;call&gt;hey&lt;/call&gt;&lt;/foo&gt;)</span>
<span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">save</span><span class="tok-p">(</span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-p">,</span> <span class="tok-s">&quot;&quot;</span><span class="tok-p">,</span> <span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">format_raw</span><span class="tok-p">);</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o">&lt;&lt;</span> <span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span>

<span class="tok-c1">// print document to standard output as a regular node (prints &lt;foo bar=&quot;baz&quot;&gt;&lt;call&gt;hey&lt;/call&gt;&lt;/foo&gt;)</span>
<span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">print</span><span class="tok-p">(</span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-p">,</span> <span class="tok-s">&quot;&quot;</span><span class="tok-p">,</span> <span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">format_raw</span><span class="tok-p">);</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o">&lt;&lt;</span> <span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span>

<span class="tok-c1">// print a subtree to standard output (prints &lt;call&gt;hey&lt;/call&gt;)</span>
<span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">child</span><span class="tok-p">(</span><span class="tok-s">&quot;foo&quot;</span><span class="tok-p">).</span><span class="tok-n">child</span><span class="tok-p">(</span><span class="tok-s">&quot;call&quot;</span><span class="tok-p">).</span><span class="tok-n">print</span><span class="tok-p">(</span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-p">,</span> <span class="tok-s">&quot;&quot;</span><span class="tok-p">,</span> <span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">format_raw</span><span class="tok-p">);</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o">&lt;&lt;</span> <span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="saving.options"><a class="anchor" href="#saving.options"></a><a class="link" href="#saving.options">7.5. Output options</a></h3>
<div class="paragraph">
<p>All saving functions accept the optional parameter <code>flags</code>. This is a bitmask that customizes the output format; you can select the way the document nodes are printed and select the needed additional information that is output before the document contents.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
You should use the usual bitwise arithmetics to manipulate the bitmask: to enable a flag, use <code>mask | flag</code>; to disable a flag, use <code>mask &amp; ~flag</code>.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>These flags control the resulting tree contents:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a id="format_indent"></a><code>format_indent</code> determines if all nodes should be indented with the indentation string (this is an additional parameter for all saving functions, and is <code>"\t"</code> by default). If this flag is on, the indentation string is printed several times before every node, where the amount of indentation depends on the node&#8217;s depth relative to the output subtree. This flag has no effect if <a href="#format_raw">format_raw</a> is enabled. This flag is <strong>on</strong> by default.</p>
</li>
<li>
<p><a id="format_indent_attributes"></a><code>format_indent_attributes</code> determines if all attributes should be printed on a new line, indented with the indentation string according to the attribute&#8217;s depth. This flag implies <a href="#format_indent">format_indent</a>. This flag has no effect if <a href="#format_raw">format_raw</a> is enabled. This flag is <strong>off</strong> by default.</p>
</li>
<li>
<p><a id="format_raw"></a><code>format_raw</code> switches between formatted and raw output. If this flag is on, the nodes are not indented in any way, and also no newlines that are not part of document text are printed. Raw mode can be used for serialization where the result is not intended to be read by humans; also it can be useful if the document was parsed with <a href="#parse_ws_pcdata">parse_ws_pcdata</a> flag, to preserve the original document formatting as much as possible. This flag is <strong>off</strong> by default.</p>
</li>
<li>
<p><a id="format_no_escapes"></a><code>format_no_escapes</code> disables output escaping for attribute values and PCDATA contents. If this flag is off, special symbols (<code>"</code>, <code>&amp;</code>, <code>&lt;</code>, <code>&gt;</code>) and all non-printable characters (those with codepoint values less than 32) are converted to XML escape sequences (i.e. <code>&amp;amp;</code>) during output. If this flag is on, no text processing is performed; therefore, output XML can be malformed if output contents contains invalid symbols (i.e. having a stray <code>&lt;</code> in the PCDATA will make the output malformed). This flag is <strong>off</strong> by default.</p>
</li>
<li>
<p><a id="format_no_empty_element_tags"></a><code>format_no_empty_element_tags</code> determines if start/end tags should be output instead of empty element tags for empty elements (that is, elements with no children). This flag is <strong>off</strong> by default.</p>
</li>
<li>
<p><a id="format_skip_control_chars"></a><code>format_skip_control_chars</code> enables skipping characters belonging to range [0; 32) instead of "&amp;#xNN;" encoding. This flag is <strong>off</strong> by default.</p>
</li>
<p><a id="format_attribute_single_quote"></a><code>format_attribute_single_quote</code> enables using single quotes <code>'</code> instead of double quotes <code>"</code> for enclosing attribute values. This flag is <strong>off</strong> by default.</p>
</ul>
</div>
<div class="paragraph">
<p>These flags control the additional output information:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a id="format_no_declaration"></a><code>format_no_declaration</code> disables default node declaration output. By default, if the document is saved via <code>save</code> or <code>save_file</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 <code>xml_node::print</code> functions: they never output the default declaration. This flag is <strong>off</strong> by default.</p>
</li>
<li>
<p><a id="format_write_bom"></a><code>format_write_bom</code> enables Byte Order Mark (BOM) output. By default, no BOM is output, so in case of non UTF-8 encodings the resulting document&#8217;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 <code>xml_node::print</code> functions: they never output the BOM. This flag is <strong>off</strong> by default.</p>
</li>
<li>
<p><a id="format_save_file_text"></a><code>format_save_file_text</code> changes the file mode when using <code>save_file</code> function. By default, file is opened in binary mode, which means that the output file will
contain platform-independent newline <code>\n</code> (ASCII 10). If this flag is on, file is opened in text mode, which on some systems changes the newline format (i.e. on Windows you can use this flag to output XML documents with <code>\r\n</code> (ASCII 13 10) newlines. This flag is <strong>off</strong> by default.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Additionally, there is one predefined option mask:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a id="format_default"></a><code>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.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>This is an example that shows the outputs of different output options (<a href="samples/save_options.cpp" class="bare">samples/save_options.cpp</a>):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-c1">// get a test document</span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_document</span> <span class="tok-n">doc</span><span class="tok-p">;</span>
<span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">load_string</span><span class="tok-p">(</span><span class="tok-s">&quot;&lt;foo bar=&#39;baz&#39;&gt;&lt;call&gt;hey&lt;/call&gt;&lt;/foo&gt;&quot;</span><span class="tok-p">);</span>

<span class="tok-c1">// default options; prints</span>
<span class="tok-c1">// &lt;?xml version=&quot;1.0&quot;?&gt;</span>
<span class="tok-c1">// &lt;foo bar=&quot;baz&quot;&gt;</span>
<span class="tok-c1">//         &lt;call&gt;hey&lt;/call&gt;</span>
<span class="tok-c1">// &lt;/foo&gt;</span>
<span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">save</span><span class="tok-p">(</span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-p">);</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o">&lt;&lt;</span> <span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span>

<span class="tok-c1">// default options with custom indentation string; prints</span>
<span class="tok-c1">// &lt;?xml version=&quot;1.0&quot;?&gt;</span>
<span class="tok-c1">// &lt;foo bar=&quot;baz&quot;&gt;</span>
<span class="tok-c1">// --&lt;call&gt;hey&lt;/call&gt;</span>
<span class="tok-c1">// &lt;/foo&gt;</span>
<span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">save</span><span class="tok-p">(</span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-p">,</span> <span class="tok-s">&quot;--&quot;</span><span class="tok-p">);</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o">&lt;&lt;</span> <span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span>

<span class="tok-c1">// default options without indentation; prints</span>
<span class="tok-c1">// &lt;?xml version=&quot;1.0&quot;?&gt;</span>
<span class="tok-c1">// &lt;foo bar=&quot;baz&quot;&gt;</span>
<span class="tok-c1">// &lt;call&gt;hey&lt;/call&gt;</span>
<span class="tok-c1">// &lt;/foo&gt;</span>
<span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">save</span><span class="tok-p">(</span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-p">,</span> <span class="tok-s">&quot;</span><span class="tok-se">\t</span><span class="tok-s">&quot;</span><span class="tok-p">,</span> <span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">format_default</span> <span class="tok-o">&amp;</span> <span class="tok-o">~</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">format_indent</span><span class="tok-p">);</span> <span class="tok-c1">// can also pass &quot;&quot; instead of indentation string for the same effect</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o">&lt;&lt;</span> <span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span>

<span class="tok-c1">// raw output; prints</span>
<span class="tok-c1">// &lt;?xml version=&quot;1.0&quot;?&gt;&lt;foo bar=&quot;baz&quot;&gt;&lt;call&gt;hey&lt;/call&gt;&lt;/foo&gt;</span>
<span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">save</span><span class="tok-p">(</span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-p">,</span> <span class="tok-s">&quot;</span><span class="tok-se">\t</span><span class="tok-s">&quot;</span><span class="tok-p">,</span> <span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">format_raw</span><span class="tok-p">);</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o">&lt;&lt;</span> <span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span> <span class="tok-o">&lt;&lt;</span> <span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span>

<span class="tok-c1">// raw output without declaration; prints</span>
<span class="tok-c1">// &lt;foo bar=&quot;baz&quot;&gt;&lt;call&gt;hey&lt;/call&gt;&lt;/foo&gt;</span>
<span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">save</span><span class="tok-p">(</span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-p">,</span> <span class="tok-s">&quot;</span><span class="tok-se">\t</span><span class="tok-s">&quot;</span><span class="tok-p">,</span> <span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">format_raw</span> <span class="tok-o">|</span> <span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">format_no_declaration</span><span class="tok-p">);</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o">&lt;&lt;</span> <span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="saving.encoding"><a class="anchor" href="#saving.encoding"></a><a class="link" href="#saving.encoding">7.6. Encodings</a></h3>
<div class="paragraph">
<p>pugixml supports all popular Unicode encodings (UTF-8, UTF-16 (big and little endian), UTF-32 (big and little endian); UCS-2 is naturally supported since it&#8217;s a strict subset of UTF-16) and handles all encoding conversions during output. The output encoding is set via the <code>encoding</code> parameter of saving functions, which is of type <code>xml_encoding</code>. The possible values for the encoding are documented in <a href="#loading.encoding">Encodings</a>; the only flag that has a different meaning is <code>encoding_auto</code>.</p>
</div>
<div class="paragraph">
<p>While all other flags set the exact encoding, <code>encoding_auto</code> is meant for automatic encoding detection. The automatic detection does not make sense for output encoding, since there is usually nothing to infer the actual encoding from, so here <code>encoding_auto</code> means UTF-8 encoding, which is the most popular encoding for XML data storage. This is also the default value of output encoding; specify another value if you do not want UTF-8 encoded output.</p>
</div>
<div class="paragraph">
<p>Also note that wide stream saving functions do not have <code>encoding</code> argument and always assume <a href="#encoding_wchar">encoding_wchar</a> encoding.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
The current behavior for Unicode conversion is to skip all invalid UTF sequences during conversion. This behavior should not be relied upon; if your node/attribute names do not contain any valid UTF sequences, they may be output as if they are empty, which will result in malformed XML document.
</td>
</tr>
</table>
</div>
</div>
<div class="sect2">
<h3 id="saving.declaration"><a class="anchor" href="#saving.declaration"></a><a class="link" href="#saving.declaration">7.7. Customizing document declaration</a></h3>
<div class="paragraph">
<p>When you are saving the document using <code>xml_document::save()</code> or <code>xml_document::save_file()</code>, a default XML document declaration is output, if <code>format_no_declaration</code> is not specified and if the document does not have a declaration node. However, the default declaration is not customizable. If you want to customize the declaration output, you need to create the declaration node yourself.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
By default the declaration node is not added to the document during parsing. If you just need to preserve the original declaration node, you have to add the flag <a href="#parse_declaration">parse_declaration</a> to the parsing flags; the resulting document will contain the original declaration node, which will be output during saving.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Declaration node is a node with type <a href="#node_declaration">node_declaration</a>; it behaves like an element node in that it has attributes with values (but it does not have child nodes). Therefore setting custom version, encoding or standalone declaration involves adding attributes and setting attribute values.</p>
</div>
<div class="paragraph">
<p>This is an example that shows how to create a custom declaration node (<a href="samples/save_declaration.cpp" class="bare">samples/save_declaration.cpp</a>):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-c1">// get a test document</span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_document</span> <span class="tok-n">doc</span><span class="tok-p">;</span>
<span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">load_string</span><span class="tok-p">(</span><span class="tok-s">&quot;&lt;foo bar=&#39;baz&#39;&gt;&lt;call&gt;hey&lt;/call&gt;&lt;/foo&gt;&quot;</span><span class="tok-p">);</span>

<span class="tok-c1">// add a custom declaration node</span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_node</span> <span class="tok-n">decl</span> <span class="tok-o">=</span> <span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">prepend_child</span><span class="tok-p">(</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">node_declaration</span><span class="tok-p">);</span>
<span class="tok-n">decl</span><span class="tok-p">.</span><span class="tok-n">append_attribute</span><span class="tok-p">(</span><span class="tok-s">&quot;version&quot;</span><span class="tok-p">)</span> <span class="tok-o">=</span> <span class="tok-s">&quot;1.0&quot;</span><span class="tok-p">;</span>
<span class="tok-n">decl</span><span class="tok-p">.</span><span class="tok-n">append_attribute</span><span class="tok-p">(</span><span class="tok-s">&quot;encoding&quot;</span><span class="tok-p">)</span> <span class="tok-o">=</span> <span class="tok-s">&quot;UTF-8&quot;</span><span class="tok-p">;</span>
<span class="tok-n">decl</span><span class="tok-p">.</span><span class="tok-n">append_attribute</span><span class="tok-p">(</span><span class="tok-s">&quot;standalone&quot;</span><span class="tok-p">)</span> <span class="tok-o">=</span> <span class="tok-s">&quot;no&quot;</span><span class="tok-p">;</span>

<span class="tok-c1">// &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;</span>
<span class="tok-c1">// &lt;foo bar=&quot;baz&quot;&gt;</span>
<span class="tok-c1">//         &lt;call&gt;hey&lt;/call&gt;</span>
<span class="tok-c1">// &lt;/foo&gt;</span>
<span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">save</span><span class="tok-p">(</span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-p">);</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o">&lt;&lt;</span> <span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span></code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="xpath"><a class="anchor" href="#xpath"></a><a class="link" href="#xpath">8. XPath</a></h2>
<div class="sectionbody">
<div class="paragraph">
<p>If the task at hand is to select a subset of document nodes that match some criteria, it is possible to code a function using the existing traversal functionality for any practical criteria. However, often either a data-driven approach is desirable, in case the criteria are not predefined and come from a file, or it is inconvenient to use traversal interfaces and a higher-level DSL is required. There is a standard language for XML processing, XPath, that can be useful for these cases. pugixml implements an almost complete subset of XPath 1.0. Because of differences in document object model and some performance implications, there are minor violations of the official specifications, which can be found in <a href="#xpath.w3c">Conformance to W3C specification</a>. The rest of this section describes the interface for XPath functionality. Please note that if you wish to learn to use XPath language, you have to look for other tutorials or manuals; for example, you can read <a href="http://www.w3schools.com/xpath/">W3Schools XPath tutorial</a>, <a href="http://www.tizag.com/xmlTutorial/xpathtutorial.php">XPath tutorial at tizag.com</a>, and <a href="http://www.w3.org/TR/xpath/">the XPath 1.0 specification</a>.</p>
</div>
<div class="sect2">
<h3 id="xpath.types"><a class="anchor" href="#xpath.types"></a><a class="link" href="#xpath.types">8.1. XPath types</a></h3>
<div class="paragraph">
<p><a id="xpath_value_type"></a><a id="xpath_type_number"></a><a id="xpath_type_string"></a><a id="xpath_type_boolean"></a><a id="xpath_type_node_set"></a><a id="xpath_type_none"></a>
Each XPath expression can have one of the following types: boolean, number, string or node set. Boolean type corresponds to <code>bool</code> type, number type corresponds to <code>double</code> type, string type corresponds to either <code>std::string</code> or <code>std::wstring</code>, depending on whether <a href="#dom.unicode">wide character interface is enabled</a>, and node set corresponds to <a href="#xpath_node_set">xpath_node_set</a> type. There is an enumeration, <code>xpath_value_type</code>, which can take the values <code>xpath_type_boolean</code>, <code>xpath_type_number</code>, <code>xpath_type_string</code> or <code>xpath_type_node_set</code>, accordingly.</p>
</div>
<div class="paragraph">
<p><a id="xpath_node"></a><a id="xpath_node::node"></a><a id="xpath_node::attribute"></a><a id="xpath_node::parent"></a>
Because an XPath node can be either a node or an attribute, there is a special type, <code>xpath_node</code>, which is a discriminated union of these types. A value of this type contains two node handles, one of <code>xml_node</code> type, and another one of <code>xml_attribute</code> type; at most one of them can be non-null. The accessors to get these handles are available:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-n">xml_node</span> <span class="tok-n">xpath_node</span><span class="tok-o">::</span><span class="tok-n">node</span><span class="tok-p">()</span> <span class="tok-k">const</span><span class="tok-p">;</span>
<span class="tok-n">xml_attribute</span> <span class="tok-n">xpath_node</span><span class="tok-o">::</span><span class="tok-n">attribute</span><span class="tok-p">()</span> <span class="tok-k">const</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>XPath nodes can be null, in which case both accessors return null handles.</p>
</div>
<div class="paragraph">
<p>Note that as per XPath specification, each XPath node has a parent, which can be retrieved via this function:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-n">xml_node</span> <span class="tok-n">xpath_node</span><span class="tok-o">::</span><span class="tok-n">parent</span><span class="tok-p">()</span> <span class="tok-k">const</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><code>parent</code> function returns the node&#8217;s parent if the XPath node corresponds to <code>xml_node</code> handle (equivalent to <code>node().parent()</code>), or the node to which the attribute belongs to, if the XPath node corresponds to <code>xml_attribute</code> handle. For null nodes, <code>parent</code> returns null handle.</p>
</div>
<div class="paragraph">
<p><a id="xpath_node::unspecified_bool_type"></a><a id="xpath_node::comparison"></a>
Like node and attribute handles, XPath node handles can be implicitly cast to boolean-like object to check if it is a null node, and also can be compared for equality with each other.</p>
</div>
<div id="xpath_node::ctor" class="paragraph">
<p>You can also create XPath nodes with one of the three constructors: the default constructor, the constructor that takes node argument, and the constructor that takes attribute and node arguments (in which case the attribute must belong to the attribute list of the node). The constructor from <code>xml_node</code> is implicit, so you can usually pass <code>xml_node</code> to functions that expect <code>xpath_node</code>. Apart from that you usually don&#8217;t need to create your own XPath node objects, since they are returned to you via selection functions.</p>
</div>
<div id="xpath_node_set" class="paragraph">
<p>XPath expressions operate not on single nodes, but instead on node sets. A node set is a collection of nodes, which can be optionally ordered in either a forward document order or a reverse one. Document order is defined in XPath specification; an XPath node is before another node in document order if it appears before it in XML representation of the corresponding document.</p>
</div>
<div class="paragraph">
<p><a id="xpath_node_set::const_iterator"></a><a id="xpath_node_set::begin"></a><a id="xpath_node_set::end"></a>
Node sets are represented by <code>xpath_node_set</code> object, which has an interface that resembles one of sequential random-access containers. It has an iterator type along with usual begin/past-the-end iterator accessors:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-k">typedef</span> <span class="tok-k">const</span> <span class="tok-n">xpath_node</span><span class="tok-o">*</span> <span class="tok-n">xpath_node_set</span><span class="tok-o">::</span><span class="tok-n">const_iterator</span><span class="tok-p">;</span>
<span class="tok-n">const_iterator</span> <span class="tok-n">xpath_node_set</span><span class="tok-o">::</span><span class="tok-n">begin</span><span class="tok-p">()</span> <span class="tok-k">const</span><span class="tok-p">;</span>
<span class="tok-n">const_iterator</span> <span class="tok-n">xpath_node_set</span><span class="tok-o">::</span><span class="tok-n">end</span><span class="tok-p">()</span> <span class="tok-k">const</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><a id="xpath_node_set::index"></a><a id="xpath_node_set::size"></a><a id="xpath_node_set::empty"></a>
And it also can be iterated via indices, just like <code>std::vector</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-k">const</span> <span class="tok-n">xpath_node</span><span class="tok-o">&amp;</span> <span class="tok-n">xpath_node_set</span><span class="tok-o">::</span><span class="tok-k">operator</span><span class="tok-p">[](</span><span class="tok-kt">size_t</span> <span class="tok-n">index</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span>
<span class="tok-kt">size_t</span> <span class="tok-n">xpath_node_set</span><span class="tok-o">::</span><span class="tok-n">size</span><span class="tok-p">()</span> <span class="tok-k">const</span><span class="tok-p">;</span>
<span class="tok-kt">bool</span> <span class="tok-n">xpath_node_set</span><span class="tok-o">::</span><span class="tok-n">empty</span><span class="tok-p">()</span> <span class="tok-k">const</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>All of the above operations have the same semantics as that of <code>std::vector</code>: the iterators are random-access, all of the above operations are constant time, and accessing the element at index that is greater or equal than the set size results in undefined behavior. You can use both iterator-based and index-based access for iteration, however the iterator-based one can be faster.</p>
</div>
<div class="paragraph">
<p><a id="xpath_node_set::type"></a><a id="xpath_node_set::type_unsorted"></a><a id="xpath_node_set::type_sorted"></a><a id="xpath_node_set::type_sorted_reverse"></a><a id="xpath_node_set::sort"></a>
The order of iteration depends on the order of nodes inside the set; the order can be queried via the following function:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-k">enum</span> <span class="tok-n">xpath_node_set</span><span class="tok-o">::</span><span class="tok-n">type_t</span> <span class="tok-p">{</span><span class="tok-n">type_unsorted</span><span class="tok-p">,</span> <span class="tok-n">type_sorted</span><span class="tok-p">,</span> <span class="tok-n">type_sorted_reverse</span><span class="tok-p">};</span>
<span class="tok-n">type_t</span> <span class="tok-n">xpath_node_set</span><span class="tok-o">::</span><span class="tok-n">type</span><span class="tok-p">()</span> <span class="tok-k">const</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><code>type</code> function returns the current order of nodes; <code>type_sorted</code> means that the nodes are in forward document order, <code>type_sorted_reverse</code> means that the nodes are in reverse document order, and <code>type_unsorted</code> means that neither order is guaranteed (nodes can accidentally be in a sorted order even if <code>type()</code> returns <code>type_unsorted</code>). If you require a specific order of iteration, you can change it via <code>sort</code> function:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-kt">void</span> <span class="tok-n">xpath_node_set</span><span class="tok-o">::</span><span class="tok-n">sort</span><span class="tok-p">(</span><span class="tok-kt">bool</span> <span class="tok-n">reverse</span> <span class="tok-o">=</span> <span class="tok-nb">false</span><span class="tok-p">);</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Calling <code>sort</code> sorts the nodes in either forward or reverse document order, depending on the argument; after this call <code>type()</code> will return <code>type_sorted</code> or <code>type_sorted_reverse</code>.</p>
</div>
<div id="xpath_node_set::first" class="paragraph">
<p>Often the actual iteration is not needed; instead, only the first element in document order is required. For this, a special accessor is provided:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-n">xpath_node</span> <span class="tok-n">xpath_node_set</span><span class="tok-o">::</span><span class="tok-n">first</span><span class="tok-p">()</span> <span class="tok-k">const</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>This function returns the first node in forward document order from the set, or null node if the set is empty. Note that while the result of the node does not depend on the order of nodes in the set (i.e. on the result of <code>type()</code>), the complexity does - if the set is sorted, the complexity is constant, otherwise it is linear in the number of elements or worse.</p>
</div>
<div id="xpath_node_set::ctor" class="paragraph">
<p>While in the majority of cases the node set is returned by XPath functions, sometimes there is a need to manually construct a node set. For such cases, a constructor is provided which takes an iterator range (<code>const_iterator</code> is a typedef for <code>const xpath_node*</code>), and an optional type:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-n">xpath_node_set</span><span class="tok-o">::</span><span class="tok-n">xpath_node_set</span><span class="tok-p">(</span><span class="tok-n">const_iterator</span> <span class="tok-n">begin</span><span class="tok-p">,</span> <span class="tok-n">const_iterator</span> <span class="tok-n">end</span><span class="tok-p">,</span> <span class="tok-n">type_t</span> <span class="tok-n">type</span> <span class="tok-o">=</span> <span class="tok-n">type_unsorted</span><span class="tok-p">);</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>The constructor copies the specified range and sets the specified type. The objects in the range are not checked in any way; you&#8217;ll have to ensure that the range contains no duplicates, and that the objects are sorted according to the <code>type</code> parameter. Otherwise XPath operations with this set may produce unexpected results.</p>
</div>
</div>
<div class="sect2">
<h3 id="xpath.select"><a class="anchor" href="#xpath.select"></a><a class="link" href="#xpath.select">8.2. Selecting nodes via XPath expression</a></h3>
<div class="paragraph">
<p><a id="xml_node::select_node"></a><a id="xml_node::select_nodes"></a>
If you want to select nodes that match some XPath expression, you can do it with the following functions:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-n">xpath_node</span> <span class="tok-n">xml_node</span><span class="tok-o">::</span><span class="tok-n">select_node</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">char_t</span><span class="tok-o">*</span> <span class="tok-n">query</span><span class="tok-p">,</span> <span class="tok-n">xpath_variable_set</span><span class="tok-o">*</span> <span class="tok-n">variables</span> <span class="tok-o">=</span> <span class="tok-mi">0</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span>
<span class="tok-n">xpath_node_set</span> <span class="tok-n">xml_node</span><span class="tok-o">::</span><span class="tok-n">select_nodes</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">char_t</span><span class="tok-o">*</span> <span class="tok-n">query</span><span class="tok-p">,</span> <span class="tok-n">xpath_variable_set</span><span class="tok-o">*</span> <span class="tok-n">variables</span> <span class="tok-o">=</span> <span class="tok-mi">0</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><code>select_nodes</code> function compiles the expression and then executes it with the node as a context node, and returns the resulting node set. <code>select_node</code> returns only the first node in document order from the result, and is equivalent to calling <code>select_nodes(query).first()</code>. If the XPath expression does not match anything, or the node handle is null, <code>select_nodes</code> returns an empty set, and <code>select_node</code> returns null XPath node.</p>
</div>
<div class="paragraph">
<p>If exception handling is not disabled, both functions throw <a href="#xpath_exception">xpath_exception</a> if the query can not be compiled or if it returns a value with type other than node set; see <a href="#xpath.errors">Error handling</a> for details.</p>
</div>
<div class="paragraph">
<p><a id="xml_node::select_node_precomp"></a><a id="xml_node::select_nodes_precomp"></a>
While compiling expressions is fast, the compilation time can introduce a significant overhead if the same expression is used many times on small subtrees. If you&#8217;re doing many similar queries, consider compiling them into query objects (see <a href="#xpath.query">Using query objects</a> for further reference). Once you get a compiled query object, you can pass it to select functions instead of an expression string:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-n">xpath_node</span> <span class="tok-n">xml_node</span><span class="tok-o">::</span><span class="tok-n">select_node</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">xpath_query</span><span class="tok-o">&amp;</span> <span class="tok-n">query</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span>
<span class="tok-n">xpath_node_set</span> <span class="tok-n">xml_node</span><span class="tok-o">::</span><span class="tok-n">select_nodes</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">xpath_query</span><span class="tok-o">&amp;</span> <span class="tok-n">query</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>If exception handling is not disabled, both functions throw <a href="#xpath_exception">xpath_exception</a> if the query returns a value with type other than node set.</p>
</div>
<div class="paragraph">
<p>This is an example of selecting nodes using XPath expressions (<a href="samples/xpath_select.cpp" class="bare">samples/xpath_select.cpp</a>):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_node_set</span> <span class="tok-n">tools</span> <span class="tok-o">=</span> <span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">select_nodes</span><span class="tok-p">(</span><span class="tok-s">&quot;/Profile/Tools/Tool[@AllowRemote=&#39;true&#39; and @DeriveCaptionFrom=&#39;lastparam&#39;]&quot;</span><span class="tok-p">);</span>

<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o">&lt;&lt;</span> <span class="tok-s">&quot;Tools:</span><span class="tok-se">\n</span><span class="tok-s">&quot;</span><span class="tok-p">;</span>

<span class="tok-k">for</span> <span class="tok-p">(</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_node_set</span><span class="tok-o">::</span><span class="tok-n">const_iterator</span> <span class="tok-n">it</span> <span class="tok-o">=</span> <span class="tok-n">tools</span><span class="tok-p">.</span><span class="tok-n">begin</span><span class="tok-p">();</span> <span class="tok-n">it</span> <span class="tok-o">!=</span> <span class="tok-n">tools</span><span class="tok-p">.</span><span class="tok-n">end</span><span class="tok-p">();</span> <span class="tok-o">++</span><span class="tok-n">it</span><span class="tok-p">)</span>
<span class="tok-p">{</span>
    <span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_node</span> <span class="tok-n">node</span> <span class="tok-o">=</span> <span class="tok-o">*</span><span class="tok-n">it</span><span class="tok-p">;</span>
    <span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o">&lt;&lt;</span> <span class="tok-n">node</span><span class="tok-p">.</span><span class="tok-n">node</span><span class="tok-p">().</span><span class="tok-n">attribute</span><span class="tok-p">(</span><span class="tok-s">&quot;Filename&quot;</span><span class="tok-p">).</span><span class="tok-n">value</span><span class="tok-p">()</span> <span class="tok-o">&lt;&lt;</span> <span class="tok-s">&quot;</span><span class="tok-se">\n</span><span class="tok-s">&quot;</span><span class="tok-p">;</span>
<span class="tok-p">}</span>

<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_node</span> <span class="tok-n">build_tool</span> <span class="tok-o">=</span> <span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">select_node</span><span class="tok-p">(</span><span class="tok-s">&quot;//Tool[contains(Description, &#39;build system&#39;)]&quot;</span><span class="tok-p">);</span>

<span class="tok-k">if</span> <span class="tok-p">(</span><span class="tok-n">build_tool</span><span class="tok-p">)</span>
    <span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o">&lt;&lt;</span> <span class="tok-s">&quot;Build tool: &quot;</span> <span class="tok-o">&lt;&lt;</span> <span class="tok-n">build_tool</span><span class="tok-p">.</span><span class="tok-n">node</span><span class="tok-p">().</span><span class="tok-n">attribute</span><span class="tok-p">(</span><span class="tok-s">&quot;Filename&quot;</span><span class="tok-p">).</span><span class="tok-n">value</span><span class="tok-p">()</span> <span class="tok-o">&lt;&lt;</span> <span class="tok-s">&quot;</span><span class="tok-se">\n</span><span class="tok-s">&quot;</span><span class="tok-p">;</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="xpath.query"><a class="anchor" href="#xpath.query"></a><a class="link" href="#xpath.query">8.3. Using query objects</a></h3>
<div id="xpath_query" class="paragraph">
<p>When you call <code>select_nodes</code> with an expression string as an argument, a query object is created behind the scenes. A query object represents a compiled XPath expression. Query objects can be needed in the following circumstances:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>You can precompile expressions to query objects to save compilation time if it becomes an issue;</p>
</li>
<li>
<p>You can use query objects to evaluate XPath expressions which result in booleans, numbers or strings;</p>
</li>
<li>
<p>You can get the type of expression value via query object.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Query objects correspond to <code>xpath_query</code> type. They are immutable and non-copyable: they are bound to the expression at creation time and can not be cloned. If you want to put query objects in a container, either allocate them on heap via <code>new</code> operator and store pointers to <code>xpath_query</code> in the container, or use a C11 compiler (query objects are movable in C11).</p>
</div>
<div id="xpath_query::ctor" class="paragraph">
<p>You can create a query object with the constructor that takes XPath expression as an argument:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-k">explicit</span> <span class="tok-n">xpath_query</span><span class="tok-o">::</span><span class="tok-n">xpath_query</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">char_t</span><span class="tok-o">*</span> <span class="tok-n">query</span><span class="tok-p">,</span> <span class="tok-n">xpath_variable_set</span><span class="tok-o">*</span> <span class="tok-n">variables</span> <span class="tok-o">=</span> <span class="tok-mi">0</span><span class="tok-p">);</span></code></pre>
</div>
</div>
<div id="xpath_query::return_type" class="paragraph">
<p>The expression is compiled and the compiled representation is stored in the new query object. If compilation fails, <a href="#xpath_exception">xpath_exception</a> is thrown if exception handling is not disabled (see <a href="#xpath.errors">Error handling</a> for details). After the query is created, you can query the type of the evaluation result using the following function:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-n">xpath_value_type</span> <span class="tok-n">xpath_query</span><span class="tok-o">::</span><span class="tok-n">return_type</span><span class="tok-p">()</span> <span class="tok-k">const</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><a id="xpath_query::evaluate_boolean"></a><a id="xpath_query::evaluate_number"></a><a id="xpath_query::evaluate_string"></a><a id="xpath_query::evaluate_node_set"></a><a id="xpath_query::evaluate_node"></a>
You can evaluate the query using one of the following functions:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-kt">bool</span> <span class="tok-n">xpath_query</span><span class="tok-o">::</span><span class="tok-n">evaluate_boolean</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">xpath_node</span><span class="tok-o">&amp;</span> <span class="tok-n">n</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span>
<span class="tok-kt">double</span> <span class="tok-n">xpath_query</span><span class="tok-o">::</span><span class="tok-n">evaluate_number</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">xpath_node</span><span class="tok-o">&amp;</span> <span class="tok-n">n</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span>
<span class="tok-n">string_t</span> <span class="tok-n">xpath_query</span><span class="tok-o">::</span><span class="tok-n">evaluate_string</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">xpath_node</span><span class="tok-o">&amp;</span> <span class="tok-n">n</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span>
<span class="tok-n">xpath_node_set</span> <span class="tok-n">xpath_query</span><span class="tok-o">::</span><span class="tok-n">evaluate_node_set</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">xpath_node</span><span class="tok-o">&amp;</span> <span class="tok-n">n</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span>
<span class="tok-n">xpath_node</span> <span class="tok-n">xpath_query</span><span class="tok-o">::</span><span class="tok-n">evaluate_node</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">xpath_node</span><span class="tok-o">&amp;</span> <span class="tok-n">n</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>All functions take the context node as an argument, compute the expression and return the result, converted to the requested type. According to XPath specification, value of any type can be converted to boolean, number or string value, but no type other than node set can be converted to node set. Because of this, <code>evaluate_boolean</code>, <code>evaluate_number</code> and <code>evaluate_string</code> always return a result, but <code>evaluate_node_set</code> and <code>evaluate_node</code> result in an error if the return type is not node set (see <a href="#xpath.errors">Error handling</a>).</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
Calling <code>node.select_nodes("query")</code> is equivalent to calling <code>xpath_query("query").evaluate_node_set(node)</code>. Calling <code>node.select_node("query")</code> is equivalent to calling <code>xpath_query("query").evaluate_node(node)</code>.
</td>
</tr>
</table>
</div>
<div id="xpath_query::evaluate_string_buffer" class="paragraph">
<p>Note that <code>evaluate_string</code> function returns the STL string; as such, it&#8217;s not available in <a href="#PUGIXML_NO_STL">PUGIXML_NO_STL</a> mode and also usually allocates memory. There is another string evaluation function:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-kt">size_t</span> <span class="tok-n">xpath_query</span><span class="tok-o">::</span><span class="tok-n">evaluate_string</span><span class="tok-p">(</span><span class="tok-n">char_t</span><span class="tok-o">*</span> <span class="tok-n">buffer</span><span class="tok-p">,</span> <span class="tok-kt">size_t</span> <span class="tok-n">capacity</span><span class="tok-p">,</span> <span class="tok-k">const</span> <span class="tok-n">xpath_node</span><span class="tok-o">&amp;</span> <span class="tok-n">n</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>This function evaluates the string, and then writes the result to <code>buffer</code> (but at most <code>capacity</code> characters); then it returns the full size of the result in characters, including the terminating zero. If <code>capacity</code> is not 0, the resulting buffer is always zero-terminated. You can use this function as follows:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>First call the function with <code>buffer = 0</code> and <code>capacity = 0</code>; then allocate the returned amount of characters, and call the function again, passing the allocated storage and the amount of characters;</p>
</li>
<li>
<p>First call the function with small buffer and buffer capacity; then, if the result is larger than the capacity, the output has been trimmed, so allocate a larger buffer and call the function again.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>This is an example of using query objects (<a href="samples/xpath_query.cpp" class="bare">samples/xpath_query.cpp</a>):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-c1">// Select nodes via compiled query</span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_query</span> <span class="tok-n">query_remote_tools</span><span class="tok-p">(</span><span class="tok-s">&quot;/Profile/Tools/Tool[@AllowRemote=&#39;true&#39;]&quot;</span><span class="tok-p">);</span>

<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_node_set</span> <span class="tok-n">tools</span> <span class="tok-o">=</span> <span class="tok-n">query_remote_tools</span><span class="tok-p">.</span><span class="tok-n">evaluate_node_set</span><span class="tok-p">(</span><span class="tok-n">doc</span><span class="tok-p">);</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o">&lt;&lt;</span> <span class="tok-s">&quot;Remote tool: &quot;</span><span class="tok-p">;</span>
<span class="tok-n">tools</span><span class="tok-p">[</span><span class="tok-mi">2</span><span class="tok-p">].</span><span class="tok-n">node</span><span class="tok-p">().</span><span class="tok-n">print</span><span class="tok-p">(</span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-p">);</span>

<span class="tok-c1">// Evaluate numbers via compiled query</span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_query</span> <span class="tok-n">query_timeouts</span><span class="tok-p">(</span><span class="tok-s">&quot;sum(//Tool/@Timeout)&quot;</span><span class="tok-p">);</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o">&lt;&lt;</span> <span class="tok-n">query_timeouts</span><span class="tok-p">.</span><span class="tok-n">evaluate_number</span><span class="tok-p">(</span><span class="tok-n">doc</span><span class="tok-p">)</span> <span class="tok-o">&lt;&lt;</span> <span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span>

<span class="tok-c1">// Evaluate strings via compiled query for different context nodes</span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_query</span> <span class="tok-n">query_name_valid</span><span class="tok-p">(</span><span class="tok-s">&quot;string-length(substring-before(@Filename, &#39;_&#39;)) &gt; 0 and @OutputFileMasks&quot;</span><span class="tok-p">);</span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_query</span> <span class="tok-n">query_name</span><span class="tok-p">(</span><span class="tok-s">&quot;concat(substring-before(@Filename, &#39;_&#39;), &#39; produces &#39;, @OutputFileMasks)&quot;</span><span class="tok-p">);</span>

<span class="tok-k">for</span> <span class="tok-p">(</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_node</span> <span class="tok-n">tool</span> <span class="tok-o">=</span> <span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">first_element_by_path</span><span class="tok-p">(</span><span class="tok-s">&quot;Profile/Tools/Tool&quot;</span><span class="tok-p">);</span> <span class="tok-n">tool</span><span class="tok-p">;</span> <span class="tok-n">tool</span> <span class="tok-o">=</span> <span class="tok-n">tool</span><span class="tok-p">.</span><span class="tok-n">next_sibling</span><span class="tok-p">())</span>
<span class="tok-p">{</span>
    <span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">string</span> <span class="tok-n">s</span> <span class="tok-o">=</span> <span class="tok-n">query_name</span><span class="tok-p">.</span><span class="tok-n">evaluate_string</span><span class="tok-p">(</span><span class="tok-n">tool</span><span class="tok-p">);</span>

    <span class="tok-k">if</span> <span class="tok-p">(</span><span class="tok-n">query_name_valid</span><span class="tok-p">.</span><span class="tok-n">evaluate_boolean</span><span class="tok-p">(</span><span class="tok-n">tool</span><span class="tok-p">))</span> <span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o">&lt;&lt;</span> <span class="tok-n">s</span> <span class="tok-o">&lt;&lt;</span> <span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span>
<span class="tok-p">}</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="xpath.variables"><a class="anchor" href="#xpath.variables"></a><a class="link" href="#xpath.variables">8.4. Using variables</a></h3>
<div class="paragraph">
<p>XPath queries may contain references to variables; this is useful if you want to use queries that depend on some dynamic parameter without manually preparing the complete query string, or if you want to reuse the same query object for similar queries.</p>
</div>
<div class="paragraph">
<p>Variable references have the form <code>$name</code>; in order to use them, you have to provide a variable set, which includes all variables present in the query with correct types. This set is passed to <code>xpath_query</code> constructor or to <code>select_nodes</code>/<code>select_node</code> functions:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-k">explicit</span> <span class="tok-n">xpath_query</span><span class="tok-o">::</span><span class="tok-n">xpath_query</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">char_t</span><span class="tok-o">*</span> <span class="tok-n">query</span><span class="tok-p">,</span> <span class="tok-n">xpath_variable_set</span><span class="tok-o">*</span> <span class="tok-n">variables</span> <span class="tok-o">=</span> <span class="tok-mi">0</span><span class="tok-p">);</span>
<span class="tok-n">xpath_node</span> <span class="tok-n">xml_node</span><span class="tok-o">::</span><span class="tok-n">select_node</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">char_t</span><span class="tok-o">*</span> <span class="tok-n">query</span><span class="tok-p">,</span> <span class="tok-n">xpath_variable_set</span><span class="tok-o">*</span> <span class="tok-n">variables</span> <span class="tok-o">=</span> <span class="tok-mi">0</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span>
<span class="tok-n">xpath_node_set</span> <span class="tok-n">xml_node</span><span class="tok-o">::</span><span class="tok-n">select_nodes</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">char_t</span><span class="tok-o">*</span> <span class="tok-n">query</span><span class="tok-p">,</span> <span class="tok-n">xpath_variable_set</span><span class="tok-o">*</span> <span class="tok-n">variables</span> <span class="tok-o">=</span> <span class="tok-mi">0</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>If you&#8217;re using query objects, you can change the variable values before <code>evaluate</code>/<code>select</code> calls to change the query behavior.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
The variable set pointer is stored in the query object; you have to ensure that the lifetime of the set exceeds that of query object.
</td>
</tr>
</table>
</div>
<div id="xpath_variable_set" class="paragraph">
<p>Variable sets correspond to <code>xpath_variable_set</code> type, which is essentially a variable container.</p>
</div>
<div id="xpath_variable_set::add" class="paragraph">
<p>You can add new variables with the following function:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-n">xpath_variable</span><span class="tok-o">*</span> <span class="tok-n">xpath_variable_set</span><span class="tok-o">::</span><span class="tok-n">add</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">char_t</span><span class="tok-o">*</span> <span class="tok-n">name</span><span class="tok-p">,</span> <span class="tok-n">xpath_value_type</span> <span class="tok-n">type</span><span class="tok-p">);</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>The function tries to add a new variable with the specified name and type; if the variable with such name does not exist in the set, the function adds a new variable and returns the variable handle; if there is already a variable with the specified name, the function returns the variable handle if variable has the specified type. Otherwise the function returns null pointer; it also returns null pointer on allocation failure.</p>
</div>
<div class="paragraph">
<p>New variables are assigned the default value which depends on the type: <code>0</code> for numbers, <code>false</code> for booleans, empty string for strings and empty set for node sets.</p>
</div>
<div id="xpath_variable_set::get" class="paragraph">
<p>You can get the existing variables with the following functions:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-n">xpath_variable</span><span class="tok-o">*</span> <span class="tok-n">xpath_variable_set</span><span class="tok-o">::</span><span class="tok-n">get</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">char_t</span><span class="tok-o">*</span> <span class="tok-n">name</span><span class="tok-p">);</span>
<span class="tok-k">const</span> <span class="tok-n">xpath_variable</span><span class="tok-o">*</span> <span class="tok-n">xpath_variable_set</span><span class="tok-o">::</span><span class="tok-n">get</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">char_t</span><span class="tok-o">*</span> <span class="tok-n">name</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>The functions return the variable handle, or null pointer if the variable with the specified name is not found.</p>
</div>
<div id="xpath_variable_set::set" class="paragraph">
<p>Additionally, there are the helper functions for setting the variable value by name; they try to add the variable with the corresponding type, if it does not exist, and to set the value. If the variable with the same name but with different type is already present, they return <code>false</code>; they also return <code>false</code> on allocation failure. Note that these functions do not perform any type conversions.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-kt">bool</span> <span class="tok-n">xpath_variable_set</span><span class="tok-o">::</span><span class="tok-n">set</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">char_t</span><span class="tok-o">*</span> <span class="tok-n">name</span><span class="tok-p">,</span> <span class="tok-kt">bool</span> <span class="tok-n">value</span><span class="tok-p">);</span>
<span class="tok-kt">bool</span> <span class="tok-n">xpath_variable_set</span><span class="tok-o">::</span><span class="tok-n">set</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">char_t</span><span class="tok-o">*</span> <span class="tok-n">name</span><span class="tok-p">,</span> <span class="tok-kt">double</span> <span class="tok-n">value</span><span class="tok-p">);</span>
<span class="tok-kt">bool</span> <span class="tok-n">xpath_variable_set</span><span class="tok-o">::</span><span class="tok-n">set</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">char_t</span><span class="tok-o">*</span> <span class="tok-n">name</span><span class="tok-p">,</span> <span class="tok-k">const</span> <span class="tok-n">char_t</span><span class="tok-o">*</span> <span class="tok-n">value</span><span class="tok-p">);</span>
<span class="tok-kt">bool</span> <span class="tok-n">xpath_variable_set</span><span class="tok-o">::</span><span class="tok-n">set</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">char_t</span><span class="tok-o">*</span> <span class="tok-n">name</span><span class="tok-p">,</span> <span class="tok-k">const</span> <span class="tok-n">xpath_node_set</span><span class="tok-o">&amp;</span> <span class="tok-n">value</span><span class="tok-p">);</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>The variable values are copied to the internal variable storage, so you can modify or destroy them after the functions return.</p>
</div>
<div id="xpath_variable" class="paragraph">
<p>If setting variables by name is not efficient enough, or if you have to inspect variable information or get variable values, you can use variable handles. A variable corresponds to the <code>xpath_variable</code> type, and a variable handle is simply a pointer to <code>xpath_variable</code>.</p>
</div>
<div class="paragraph">
<p><a id="xpath_variable::type"></a><a id="xpath_variable::name"></a>
In order to get variable information, you can use one of the following functions:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-k">const</span> <span class="tok-n">char_t</span><span class="tok-o">*</span> <span class="tok-n">xpath_variable</span><span class="tok-o">::</span><span class="tok-n">name</span><span class="tok-p">()</span> <span class="tok-k">const</span><span class="tok-p">;</span>
<span class="tok-n">xpath_value_type</span> <span class="tok-n">xpath_variable</span><span class="tok-o">::</span><span class="tok-n">type</span><span class="tok-p">()</span> <span class="tok-k">const</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Note that each variable has a distinct type which is specified upon variable creation and can not be changed later.</p>
</div>
<div class="paragraph">
<p><a id="xpath_variable::get_boolean"></a><a id="xpath_variable::get_number"></a><a id="xpath_variable::get_string"></a><a id="xpath_variable::get_node_set"></a>
In order to get variable value, you should use one of the following functions, depending on the variable type:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-kt">bool</span> <span class="tok-n">xpath_variable</span><span class="tok-o">::</span><span class="tok-n">get_boolean</span><span class="tok-p">()</span> <span class="tok-k">const</span><span class="tok-p">;</span>
<span class="tok-kt">double</span> <span class="tok-n">xpath_variable</span><span class="tok-o">::</span><span class="tok-n">get_number</span><span class="tok-p">()</span> <span class="tok-k">const</span><span class="tok-p">;</span>
<span class="tok-k">const</span> <span class="tok-n">char_t</span><span class="tok-o">*</span> <span class="tok-n">xpath_variable</span><span class="tok-o">::</span><span class="tok-n">get_string</span><span class="tok-p">()</span> <span class="tok-k">const</span><span class="tok-p">;</span>
<span class="tok-k">const</span> <span class="tok-n">xpath_node_set</span><span class="tok-o">&amp;</span> <span class="tok-n">xpath_variable</span><span class="tok-o">::</span><span class="tok-n">get_node_set</span><span class="tok-p">()</span> <span class="tok-k">const</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>These functions return the value of the variable. Note that no type conversions are performed; if the type mismatch occurs, a dummy value is returned (<code>false</code> for booleans, <code>NaN</code> for numbers, empty string for strings and empty set for node sets).</p>
</div>
<div id="xpath_variable::set" class="paragraph">
<p>In order to set variable value, you should use one of the following functions, depending on the variable type:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-kt">bool</span> <span class="tok-n">xpath_variable</span><span class="tok-o">::</span><span class="tok-n">set</span><span class="tok-p">(</span><span class="tok-kt">bool</span> <span class="tok-n">value</span><span class="tok-p">);</span>
<span class="tok-kt">bool</span> <span class="tok-n">xpath_variable</span><span class="tok-o">::</span><span class="tok-n">set</span><span class="tok-p">(</span><span class="tok-kt">double</span> <span class="tok-n">value</span><span class="tok-p">);</span>
<span class="tok-kt">bool</span> <span class="tok-n">xpath_variable</span><span class="tok-o">::</span><span class="tok-n">set</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">char_t</span><span class="tok-o">*</span> <span class="tok-n">value</span><span class="tok-p">);</span>
<span class="tok-kt">bool</span> <span class="tok-n">xpath_variable</span><span class="tok-o">::</span><span class="tok-n">set</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">xpath_node_set</span><span class="tok-o">&amp;</span> <span class="tok-n">value</span><span class="tok-p">);</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>These functions modify the variable value. Note that no type conversions are performed; if the type mismatch occurs, the functions return <code>false</code>; they also return <code>false</code> on allocation failure. The variable values are copied to the internal variable storage, so you can modify or destroy them after the functions return.</p>
</div>
<div class="paragraph">
<p>This is an example of using variables in XPath queries (<a href="samples/xpath_variables.cpp" class="bare">samples/xpath_variables.cpp</a>):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-c1">// Select nodes via compiled query</span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_variable_set</span> <span class="tok-n">vars</span><span class="tok-p">;</span>
<span class="tok-n">vars</span><span class="tok-p">.</span><span class="tok-n">add</span><span class="tok-p">(</span><span class="tok-s">&quot;remote&quot;</span><span class="tok-p">,</span> <span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_type_boolean</span><span class="tok-p">);</span>

<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_query</span> <span class="tok-n">query_remote_tools</span><span class="tok-p">(</span><span class="tok-s">&quot;/Profile/Tools/Tool[@AllowRemote = string($remote)]&quot;</span><span class="tok-p">,</span> <span class="tok-o">&amp;</span><span class="tok-n">vars</span><span class="tok-p">);</span>

<span class="tok-n">vars</span><span class="tok-p">.</span><span class="tok-n">set</span><span class="tok-p">(</span><span class="tok-s">&quot;remote&quot;</span><span class="tok-p">,</span> <span class="tok-nb">true</span><span class="tok-p">);</span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_node_set</span> <span class="tok-n">tools_remote</span> <span class="tok-o">=</span> <span class="tok-n">query_remote_tools</span><span class="tok-p">.</span><span class="tok-n">evaluate_node_set</span><span class="tok-p">(</span><span class="tok-n">doc</span><span class="tok-p">);</span>

<span class="tok-n">vars</span><span class="tok-p">.</span><span class="tok-n">set</span><span class="tok-p">(</span><span class="tok-s">&quot;remote&quot;</span><span class="tok-p">,</span> <span class="tok-nb">false</span><span class="tok-p">);</span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_node_set</span> <span class="tok-n">tools_local</span> <span class="tok-o">=</span> <span class="tok-n">query_remote_tools</span><span class="tok-p">.</span><span class="tok-n">evaluate_node_set</span><span class="tok-p">(</span><span class="tok-n">doc</span><span class="tok-p">);</span>

<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o">&lt;&lt;</span> <span class="tok-s">&quot;Remote tool: &quot;</span><span class="tok-p">;</span>
<span class="tok-n">tools_remote</span><span class="tok-p">[</span><span class="tok-mi">2</span><span class="tok-p">].</span><span class="tok-n">node</span><span class="tok-p">().</span><span class="tok-n">print</span><span class="tok-p">(</span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-p">);</span>

<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o">&lt;&lt;</span> <span class="tok-s">&quot;Local tool: &quot;</span><span class="tok-p">;</span>
<span class="tok-n">tools_local</span><span class="tok-p">[</span><span class="tok-mi">0</span><span class="tok-p">].</span><span class="tok-n">node</span><span class="tok-p">().</span><span class="tok-n">print</span><span class="tok-p">(</span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-p">);</span>

<span class="tok-c1">// You can pass the context directly to select_nodes/select_node</span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_node_set</span> <span class="tok-n">tools_local_imm</span> <span class="tok-o">=</span> <span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">select_nodes</span><span class="tok-p">(</span><span class="tok-s">&quot;/Profile/Tools/Tool[@AllowRemote = string($remote)]&quot;</span><span class="tok-p">,</span> <span class="tok-o">&amp;</span><span class="tok-n">vars</span><span class="tok-p">);</span>

<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o">&lt;&lt;</span> <span class="tok-s">&quot;Local tool imm: &quot;</span><span class="tok-p">;</span>
<span class="tok-n">tools_local_imm</span><span class="tok-p">[</span><span class="tok-mi">0</span><span class="tok-p">].</span><span class="tok-n">node</span><span class="tok-p">().</span><span class="tok-n">print</span><span class="tok-p">(</span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-p">);</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="xpath.errors"><a class="anchor" href="#xpath.errors"></a><a class="link" href="#xpath.errors">8.5. Error handling</a></h3>
<div class="paragraph">
<p>There are two different mechanisms for error handling in XPath implementation; the mechanism used depends on whether exception support is disabled (this is controlled with <a href="#PUGIXML_NO_EXCEPTIONS">PUGIXML_NO_EXCEPTIONS</a> define).</p>
</div>
<div class="paragraph">
<p><a id="xpath_exception"></a><a id="xpath_exception::result"></a><a id="xpath_exception::what"></a>
By default, XPath functions throw <code>xpath_exception</code> object in case of errors; additionally, in the event any memory allocation fails, an <code>std::bad_alloc</code> exception is thrown. Also <code>xpath_exception</code> is thrown if the query is evaluated to a node set, but the return type is not node set. If the query constructor succeeds (i.e. no exception is thrown), the query object is valid. Otherwise you can get the error details via one of the following functions:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-k">virtual</span> <span class="tok-k">const</span> <span class="tok-kt">char</span><span class="tok-o">*</span> <span class="tok-n">xpath_exception</span><span class="tok-o">::</span><span class="tok-n">what</span><span class="tok-p">()</span> <span class="tok-k">const</span> <span class="tok-k">throw</span><span class="tok-p">();</span>
<span class="tok-k">const</span> <span class="tok-n">xpath_parse_result</span><span class="tok-o">&amp;</span> <span class="tok-n">xpath_exception</span><span class="tok-o">::</span><span class="tok-n">result</span><span class="tok-p">()</span> <span class="tok-k">const</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><a id="xpath_query::unspecified_bool_type"></a><a id="xpath_query::result"></a>
If exceptions are disabled, then in the event of parsing failure the query is initialized to invalid state; you can test if the query object is valid by using it in a boolean expression: <code>if (query) { &#8230;&#8203; }</code>. Additionally, you can get parsing result via the result() accessor:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-k">const</span> <span class="tok-n">xpath_parse_result</span><span class="tok-o">&amp;</span> <span class="tok-n">xpath_query</span><span class="tok-o">::</span><span class="tok-n">result</span><span class="tok-p">()</span> <span class="tok-k">const</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Without exceptions, evaluating invalid query results in <code>false</code>, empty string, <code>NaN</code> or an empty node set, depending on the type; evaluating a query as a node set results in an empty node set if the return type is not node set.</p>
</div>
<div id="xpath_parse_result" class="paragraph">
<p>The information about parsing result is returned via <code>xpath_parse_result</code> object. It contains parsing status and the offset of last successfully parsed character from the beginning of the source stream:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-k">struct</span> <span class="tok-n">xpath_parse_result</span>
<span class="tok-p">{</span>
    <span class="tok-k">const</span> <span class="tok-kt">char</span><span class="tok-o">*</span> <span class="tok-n">error</span><span class="tok-p">;</span>
    <span class="tok-kt">ptrdiff_t</span> <span class="tok-n">offset</span><span class="tok-p">;</span>

    <span class="tok-k">operator</span> <span class="tok-nf">bool</span><span class="tok-p">()</span> <span class="tok-k">const</span><span class="tok-p">;</span>
    <span class="tok-k">const</span> <span class="tok-kt">char</span><span class="tok-o">*</span> <span class="tok-nf">description</span><span class="tok-p">()</span> <span class="tok-k">const</span><span class="tok-p">;</span>
<span class="tok-p">};</span></code></pre>
</div>
</div>
<div id="xpath_parse_result::error" class="paragraph">
<p>Parsing result is represented as the error message; it is either a null pointer, in case there is no error, or the error message in the form of ASCII zero-terminated string.</p>
</div>
<div id="xpath_parse_result::description" class="paragraph">
<p><code>description()</code> member function can be used to get the error message; it never returns the null pointer, so you can safely use <code>description()</code> even if query parsing succeeded. Note that <code>description()</code> returns a <code>char</code> string even in <code>PUGIXML_WCHAR_MODE</code>; you&#8217;ll have to call <a href="#as_wide">as_wide</a> to get the <code>wchar_t</code> string.</p>
</div>
<div id="xpath_parse_result::offset" class="paragraph">
<p>In addition to the error message, parsing result has an <code>offset</code> member, which contains the offset of last successfully parsed character. This offset is in units of <a href="#char_t">pugi::char_t</a> (bytes for character mode, wide characters for wide character mode).</p>
</div>
<div id="xpath_parse_result::bool" class="paragraph">
<p>Parsing result object can be implicitly converted to <code>bool</code> like this: <code>if (result) { &#8230;&#8203; } else { &#8230;&#8203; }</code>.</p>
</div>
<div class="paragraph">
<p>This is an example of XPath error handling (<a href="samples/xpath_error.cpp" class="bare">samples/xpath_error.cpp</a>):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-c1">// Exception is thrown for incorrect query syntax</span>
<span class="tok-k">try</span>
<span class="tok-p">{</span>
    <span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">select_nodes</span><span class="tok-p">(</span><span class="tok-s">&quot;//nodes[#true()]&quot;</span><span class="tok-p">);</span>
<span class="tok-p">}</span>
<span class="tok-k">catch</span> <span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_exception</span><span class="tok-o">&amp;</span> <span class="tok-n">e</span><span class="tok-p">)</span>
<span class="tok-p">{</span>
    <span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o">&lt;&lt;</span> <span class="tok-s">&quot;Select failed: &quot;</span> <span class="tok-o">&lt;&lt;</span> <span class="tok-n">e</span><span class="tok-p">.</span><span class="tok-n">what</span><span class="tok-p">()</span> <span class="tok-o">&lt;&lt;</span> <span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span>
<span class="tok-p">}</span>

<span class="tok-c1">// Exception is thrown for incorrect query semantics</span>
<span class="tok-k">try</span>
<span class="tok-p">{</span>
    <span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">select_nodes</span><span class="tok-p">(</span><span class="tok-s">&quot;(123)/next&quot;</span><span class="tok-p">);</span>
<span class="tok-p">}</span>
<span class="tok-k">catch</span> <span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_exception</span><span class="tok-o">&amp;</span> <span class="tok-n">e</span><span class="tok-p">)</span>
<span class="tok-p">{</span>
    <span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o">&lt;&lt;</span> <span class="tok-s">&quot;Select failed: &quot;</span> <span class="tok-o">&lt;&lt;</span> <span class="tok-n">e</span><span class="tok-p">.</span><span class="tok-n">what</span><span class="tok-p">()</span> <span class="tok-o">&lt;&lt;</span> <span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span>
<span class="tok-p">}</span>