summaryrefslogtreecommitdiff
path: root/docs/samples
diff options
context:
space:
mode:
authorArseny Kapoulkine <arseny.kapoulkine@gmail.com>2015-04-08 21:44:16 -0700
committerArseny Kapoulkine <arseny.kapoulkine@gmail.com>2015-04-08 21:44:16 -0700
commit65e90b2d7a86383243e380b2658fad26dce370f0 (patch)
tree95f418c94216831b595a98f2e56768a6bdcbdab9 /docs/samples
parent084ecd454a06d6da0304d0b7ccde8e8917b1ea26 (diff)
docs: Add docs folder from master
Diffstat (limited to 'docs/samples')
-rw-r--r--docs/samples/character.xml8
-rw-r--r--docs/samples/custom_memory_management.cpp27
-rw-r--r--docs/samples/include.cpp64
-rw-r--r--docs/samples/load_error_handling.cpp33
-rw-r--r--docs/samples/load_file.cpp16
-rw-r--r--docs/samples/load_memory.cpp66
-rw-r--r--docs/samples/load_options.cpp30
-rw-r--r--docs/samples/load_stream.cpp97
-rw-r--r--docs/samples/modify_add.cpp29
-rw-r--r--docs/samples/modify_base.cpp43
-rw-r--r--docs/samples/modify_remove.cpp27
-rw-r--r--docs/samples/save_custom_writer.cpp116
-rw-r--r--docs/samples/save_declaration.cpp27
-rw-r--r--docs/samples/save_file.cpp17
-rw-r--r--docs/samples/save_options.cpp48
-rw-r--r--docs/samples/save_stream.cpp18
-rw-r--r--docs/samples/save_subtree.cpp26
-rw-r--r--docs/samples/text.cpp35
-rw-r--r--docs/samples/transitions.xml7
-rw-r--r--docs/samples/traverse_base.cpp51
-rw-r--r--docs/samples/traverse_iter.cpp27
-rw-r--r--docs/samples/traverse_predicate.cpp48
-rw-r--r--docs/samples/traverse_rangefor.cpp32
-rw-r--r--docs/samples/traverse_walker.cpp35
-rw-r--r--docs/samples/tree.xml12
-rw-r--r--docs/samples/weekly-shift_jis.xml78
-rw-r--r--docs/samples/weekly-utf-16.xmlbin0 -> 3186 bytes
-rw-r--r--docs/samples/weekly-utf-8.xml78
-rw-r--r--docs/samples/xgconsole.xml12
-rw-r--r--docs/samples/xpath_error.cpp43
-rw-r--r--docs/samples/xpath_query.cpp36
-rw-r--r--docs/samples/xpath_select.cpp28
-rw-r--r--docs/samples/xpath_variables.cpp38
33 files changed, 1252 insertions, 0 deletions
diff --git a/docs/samples/character.xml b/docs/samples/character.xml
new file mode 100644
index 0000000..078e0bf
--- /dev/null
+++ b/docs/samples/character.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<network>
+ <animation clip="idle" flags="loop" />
+ <animation clip="run" flags="loop" />
+ <animation clip="attack" />
+
+ <?include transitions.xml?>
+</network>
diff --git a/docs/samples/custom_memory_management.cpp b/docs/samples/custom_memory_management.cpp
new file mode 100644
index 0000000..2cb5520
--- /dev/null
+++ b/docs/samples/custom_memory_management.cpp
@@ -0,0 +1,27 @@
+#include "pugixml.hpp"
+
+#include <new>
+
+// tag::decl[]
+void* custom_allocate(size_t size)
+{
+ return new (std::nothrow) char[size];
+}
+
+void custom_deallocate(void* ptr)
+{
+ delete[] static_cast<char*>(ptr);
+}
+// end::decl[]
+
+int main()
+{
+// tag::call[]
+ pugi::set_memory_management_functions(custom_allocate, custom_deallocate);
+// end::call[]
+
+ pugi::xml_document doc;
+ doc.load_string("<node/>");
+}
+
+// vim:et
diff --git a/docs/samples/include.cpp b/docs/samples/include.cpp
new file mode 100644
index 0000000..39830c5
--- /dev/null
+++ b/docs/samples/include.cpp
@@ -0,0 +1,64 @@
+#include "pugixml.hpp"
+
+#include <string.h>
+#include <iostream>
+
+// tag::code[]
+bool load_preprocess(pugi::xml_document& doc, const char* path);
+
+bool preprocess(pugi::xml_node node)
+{
+ for (pugi::xml_node child = node.first_child(); child; )
+ {
+ if (child.type() == pugi::node_pi && strcmp(child.name(), "include") == 0)
+ {
+ pugi::xml_node include = child;
+
+ // load new preprocessed document (note: ideally this should handle relative paths)
+ const char* path = include.value();
+
+ pugi::xml_document doc;
+ if (!load_preprocess(doc, path)) return false;
+
+ // insert the comment marker above include directive
+ node.insert_child_before(pugi::node_comment, include).set_value(path);
+
+ // copy the document above the include directive (this retains the original order!)
+ for (pugi::xml_node ic = doc.first_child(); ic; ic = ic.next_sibling())
+ {
+ node.insert_copy_before(ic, include);
+ }
+
+ // remove the include node and move to the next child
+ child = child.next_sibling();
+
+ node.remove_child(include);
+ }
+ else
+ {
+ if (!preprocess(child)) return false;
+
+ child = child.next_sibling();
+ }
+ }
+
+ return true;
+}
+
+bool load_preprocess(pugi::xml_document& doc, const char* path)
+{
+ pugi::xml_parse_result result = doc.load_file(path, pugi::parse_default | pugi::parse_pi); // for <?include?>
+
+ return result ? preprocess(doc) : false;
+}
+// end::code[]
+
+int main()
+{
+ pugi::xml_document doc;
+ if (!load_preprocess(doc, "character.xml")) return -1;
+
+ doc.print(std::cout);
+}
+
+// vim:et
diff --git a/docs/samples/load_error_handling.cpp b/docs/samples/load_error_handling.cpp
new file mode 100644
index 0000000..d1e5a49
--- /dev/null
+++ b/docs/samples/load_error_handling.cpp
@@ -0,0 +1,33 @@
+#include "pugixml.hpp"
+
+#include <iostream>
+
+void check_xml(const char* source)
+{
+// tag::code[]
+ pugi::xml_document doc;
+ pugi::xml_parse_result result = doc.load_string(source);
+
+ if (result)
+ {
+ std::cout << "XML [" << source << "] parsed without errors, attr value: [" << doc.child("node").attribute("attr").value() << "]\n\n";
+ }
+ else
+ {
+ std::cout << "XML [" << source << "] parsed with errors, attr value: [" << doc.child("node").attribute("attr").value() << "]\n";
+ std::cout << "Error description: " << result.description() << "\n";
+ std::cout << "Error offset: " << result.offset << " (error at [..." << (source + result.offset) << "]\n\n";
+ }
+// end::code[]
+}
+
+int main()
+{
+ check_xml("<node attr='value'><child>text</child></node>");
+ check_xml("<node attr='value'><child>text</chil></node>");
+ check_xml("<node attr='value'><child>text</child>");
+ check_xml("<node attr='value\"><child>text</child></node>");
+ check_xml("<node attr='value'><#tag /></node>");
+}
+
+// vim:et
diff --git a/docs/samples/load_file.cpp b/docs/samples/load_file.cpp
new file mode 100644
index 0000000..8b2191b
--- /dev/null
+++ b/docs/samples/load_file.cpp
@@ -0,0 +1,16 @@
+#include "pugixml.hpp"
+
+#include <iostream>
+
+int main()
+{
+// tag::code[]
+ pugi::xml_document doc;
+
+ pugi::xml_parse_result result = doc.load_file("tree.xml");
+
+ std::cout << "Load result: " << result.description() << ", mesh name: " << doc.child("mesh").attribute("name").value() << std::endl;
+// end::code[]
+}
+
+// vim:et
diff --git a/docs/samples/load_memory.cpp b/docs/samples/load_memory.cpp
new file mode 100644
index 0000000..80bba3c
--- /dev/null
+++ b/docs/samples/load_memory.cpp
@@ -0,0 +1,66 @@
+#include "pugixml.hpp"
+
+#include <iostream>
+#include <cstring>
+
+int main()
+{
+// tag::decl[]
+ const char source[] = "<mesh name='sphere'><bounds>0 0 1 1</bounds></mesh>";
+ size_t size = sizeof(source);
+// end::decl[]
+
+ pugi::xml_document doc;
+
+ {
+ // tag::load_buffer[]
+ // You can use load_buffer to load document from immutable memory block:
+ pugi::xml_parse_result result = doc.load_buffer(source, size);
+ // end::load_buffer[]
+
+ std::cout << "Load result: " << result.description() << ", mesh name: " << doc.child("mesh").attribute("name").value() << std::endl;
+ }
+
+ {
+ // tag::load_buffer_inplace_begin[]
+ // You can use load_buffer_inplace to load document from mutable memory block; the block's lifetime must exceed that of document
+ char* buffer = new char[size];
+ memcpy(buffer, source, size);
+
+ // The block can be allocated by any method; the block is modified during parsing
+ pugi::xml_parse_result result = doc.load_buffer_inplace(buffer, size);
+ // end::load_buffer_inplace_begin[]
+
+ std::cout << "Load result: " << result.description() << ", mesh name: " << doc.child("mesh").attribute("name").value() << std::endl;
+
+ // tag::load_buffer_inplace_end[]
+ // You have to destroy the block yourself after the document is no longer used
+ delete[] buffer;
+ // end::load_buffer_inplace_end[]
+ }
+
+ {
+ // tag::load_buffer_inplace_own[]
+ // You can use load_buffer_inplace_own to load document from mutable memory block and to pass the ownership of this block
+ // The block has to be allocated via pugixml allocation function - using i.e. operator new here is incorrect
+ char* buffer = static_cast<char*>(pugi::get_memory_allocation_function()(size));
+ memcpy(buffer, source, size);
+
+ // The block will be deleted by the document
+ pugi::xml_parse_result result = doc.load_buffer_inplace_own(buffer, size);
+ // end::load_buffer_inplace_own[]
+
+ std::cout << "Load result: " << result.description() << ", mesh name: " << doc.child("mesh").attribute("name").value() << std::endl;
+ }
+
+ {
+ // tag::load_string[]
+ // You can use load to load document from null-terminated strings, for example literals:
+ pugi::xml_parse_result result = doc.load_string("<mesh name='sphere'><bounds>0 0 1 1</bounds></mesh>");
+ // end::load_string[]
+
+ std::cout << "Load result: " << result.description() << ", mesh name: " << doc.child("mesh").attribute("name").value() << std::endl;
+ }
+}
+
+// vim:et
diff --git a/docs/samples/load_options.cpp b/docs/samples/load_options.cpp
new file mode 100644
index 0000000..b7b0a6b
--- /dev/null
+++ b/docs/samples/load_options.cpp
@@ -0,0 +1,30 @@
+#include "pugixml.hpp"
+
+#include <iostream>
+
+int main()
+{
+ pugi::xml_document doc;
+
+// tag::code[]
+ const char* source = "<!--comment--><node>&lt;</node>";
+
+ // Parsing with default options; note that comment node is not added to the tree, and entity reference &lt; is expanded
+ doc.load_string(source);
+ std::cout << "First node value: [" << doc.first_child().value() << "], node child value: [" << doc.child_value("node") << "]\n";
+
+ // Parsing with additional parse_comments option; comment node is now added to the tree
+ doc.load_string(source, pugi::parse_default | pugi::parse_comments);
+ std::cout << "First node value: [" << doc.first_child().value() << "], node child value: [" << doc.child_value("node") << "]\n";
+
+ // Parsing with additional parse_comments option and without the (default) parse_escapes option; &lt; is not expanded
+ doc.load_string(source, (pugi::parse_default | pugi::parse_comments) & ~pugi::parse_escapes);
+ std::cout << "First node value: [" << doc.first_child().value() << "], node child value: [" << doc.child_value("node") << "]\n";
+
+ // Parsing with minimal option mask; comment node is not added to the tree, and &lt; is not expanded
+ doc.load_string(source, pugi::parse_minimal);
+ std::cout << "First node value: [" << doc.first_child().value() << "], node child value: [" << doc.child_value("node") << "]\n";
+// end::code[]
+}
+
+// vim:et
diff --git a/docs/samples/load_stream.cpp b/docs/samples/load_stream.cpp
new file mode 100644
index 0000000..f982a83
--- /dev/null
+++ b/docs/samples/load_stream.cpp
@@ -0,0 +1,97 @@
+#include "pugixml.hpp"
+
+#include <fstream>
+#include <iomanip>
+#include <iostream>
+
+void print_doc(const char* message, const pugi::xml_document& doc, const pugi::xml_parse_result& result)
+{
+ std::cout
+ << message
+ << "\t: load result '" << result.description() << "'"
+ << ", first character of root name: U+" << std::hex << std::uppercase << std::setw(4) << std::setfill('0') << pugi::as_wide(doc.first_child().name())[0]
+ << ", year: " << doc.first_child().first_child().first_child().child_value()
+ << std::endl;
+}
+
+bool try_imbue(std::wistream& stream, const char* name)
+{
+ try
+ {
+ stream.imbue(std::locale(name));
+
+ return true;
+ }
+ catch (const std::exception&)
+ {
+ return false;
+ }
+}
+
+int main()
+{
+ pugi::xml_document doc;
+
+ {
+ // tag::code[]
+ std::ifstream stream("weekly-utf-8.xml");
+ pugi::xml_parse_result result = doc.load(stream);
+ // end::code[]
+
+ // first character of root name: U+9031, year: 1997
+ print_doc("UTF8 file from narrow stream", doc, result);
+ }
+
+ {
+ std::ifstream stream("weekly-utf-16.xml");
+ pugi::xml_parse_result result = doc.load(stream);
+
+ // first character of root name: U+9031, year: 1997
+ print_doc("UTF16 file from narrow stream", doc, result);
+ }
+
+ {
+ // Since wide streams are treated as UTF-16/32 ones, you can't load the UTF-8 file from a wide stream
+ // directly if you have localized characters; you'll have to provide a UTF8 locale (there is no
+ // standard one; you can use utf8_codecvt_facet from Boost or codecvt_utf8 from C++0x)
+ std::wifstream stream("weekly-utf-8.xml");
+
+ if (try_imbue(stream, "en_US.UTF-8")) // try Linux encoding
+ {
+ pugi::xml_parse_result result = doc.load(stream);
+
+ // first character of root name: U+00E9, year: 1997
+ print_doc("UTF8 file from wide stream", doc, result);
+ }
+ else
+ {
+ std::cout << "UTF-8 locale is not available\n";
+ }
+ }
+
+ {
+ // Since wide streams are treated as UTF-16/32 ones, you can't load the UTF-16 file from a wide stream without
+ // using custom codecvt; you can use codecvt_utf16 from C++0x
+ }
+
+ {
+ // Since encoding names are non-standard, you can't load the Shift-JIS (or any other non-ASCII) file
+ // from a wide stream portably
+ std::wifstream stream("weekly-shift_jis.xml");
+
+ if (try_imbue(stream, ".932") || // try Microsoft encoding
+ try_imbue(stream, "ja_JP.SJIS")) // try Linux encoding; run "localedef -i ja_JP -c -f SHIFT_JIS /usr/lib/locale/ja_JP.SJIS" to get it
+ {
+ pugi::xml_parse_result result = doc.load(stream);
+
+ // first character of root name: U+9031, year: 1997
+ print_doc("Shift-JIS file from wide stream", doc, result);
+ }
+ else
+ {
+ std::cout << "Shift-JIS locale is not available\n";
+ }
+ }
+}
+
+// vim:et
diff --git a/docs/samples/modify_add.cpp b/docs/samples/modify_add.cpp
new file mode 100644
index 0000000..a2ddd31
--- /dev/null
+++ b/docs/samples/modify_add.cpp
@@ -0,0 +1,29 @@
+#include "pugixml.hpp"
+
+#include <iostream>
+
+int main()
+{
+ pugi::xml_document doc;
+
+ // tag::code[]
+ // add node with some name
+ pugi::xml_node node = doc.append_child("node");
+
+ // add description node with text child
+ pugi::xml_node descr = node.append_child("description");
+ descr.append_child(pugi::node_pcdata).set_value("Simple node");
+
+ // add param node before the description
+ pugi::xml_node param = node.insert_child_before("param", descr);
+
+ // add attributes to param node
+ param.append_attribute("name") = "version";
+ param.append_attribute("value") = 1.1;
+ param.insert_attribute_after("type", param.attribute("name")) = "float";
+ // end::code[]
+
+ doc.print(std::cout);
+}
+
+// vim:et
diff --git a/docs/samples/modify_base.cpp b/docs/samples/modify_base.cpp
new file mode 100644
index 0000000..7c4819b
--- /dev/null
+++ b/docs/samples/modify_base.cpp
@@ -0,0 +1,43 @@
+#include "pugixml.hpp"
+
+#include <string.h>
+#include <iostream>
+
+int main()
+{
+ pugi::xml_document doc;
+ if (!doc.load_string("<node id='123'>text</node><!-- comment -->", pugi::parse_default | pugi::parse_comments)) return -1;
+
+ // tag::node[]
+ pugi::xml_node node = doc.child("node");
+
+ // change node name
+ std::cout << node.set_name("notnode");
+ std::cout << ", new node name: " << node.name() << std::endl;
+
+ // change comment text
+ std::cout << doc.last_child().set_value("useless comment");
+ std::cout << ", new comment text: " << doc.last_child().value() << std::endl;
+
+ // we can't change value of the element or name of the comment
+ std::cout << node.set_value("1") << ", " << doc.last_child().set_name("2") << std::endl;
+ // end::node[]
+
+ // tag::attr[]
+ pugi::xml_attribute attr = node.attribute("id");
+
+ // change attribute name/value
+ std::cout << attr.set_name("key") << ", " << attr.set_value("345");
+ std::cout << ", new attribute: " << attr.name() << "=" << attr.value() << std::endl;
+
+ // we can use numbers or booleans
+ attr.set_value(1.234);
+ std::cout << "new attribute value: " << attr.value() << std::endl;
+
+ // we can also use assignment operators for more concise code
+ attr = true;
+ std::cout << "final attribute value: " << attr.value() << std::endl;
+ // end::attr[]
+}
+
+// vim:et
diff --git a/docs/samples/modify_remove.cpp b/docs/samples/modify_remove.cpp
new file mode 100644
index 0000000..d54c0d8
--- /dev/null
+++ b/docs/samples/modify_remove.cpp
@@ -0,0 +1,27 @@
+#include "pugixml.hpp"
+
+#include <iostream>
+
+int main()
+{
+ pugi::xml_document doc;
+ if (!doc.load_string("<node><description>Simple node</description><param name='id' value='123'/></node>")) return -1;
+
+ // tag::code[]
+ // remove description node with the whole subtree
+ pugi::xml_node node = doc.child("node");
+ node.remove_child("description");
+
+ // remove id attribute
+ pugi::xml_node param = node.child("param");
+ param.remove_attribute("value");
+
+ // we can also remove nodes/attributes by handles
+ pugi::xml_attribute id = param.attribute("name");
+ param.remove_attribute(id);
+ // end::code[]
+
+ doc.print(std::cout);
+}
+
+// vim:et
diff --git a/docs/samples/save_custom_writer.cpp b/docs/samples/save_custom_writer.cpp
new file mode 100644
index 0000000..e777a32
--- /dev/null
+++ b/docs/samples/save_custom_writer.cpp
@@ -0,0 +1,116 @@
+#include "pugixml.hpp"
+
+#include <string>
+#include <iostream>
+#include <cstring>
+
+// tag::code[]
+struct xml_string_writer: pugi::xml_writer
+{
+ std::string result;
+
+ virtual void write(const void* data, size_t size)
+ {
+ result.append(static_cast<const char*>(data), size);
+ }
+};
+// end::code[]
+
+struct xml_memory_writer: pugi::xml_writer
+{
+ char* buffer;
+ size_t capacity;
+
+ size_t result;
+
+ xml_memory_writer(): buffer(0), capacity(0), result(0)
+ {
+ }
+
+ xml_memory_writer(char* buffer, size_t capacity): buffer(buffer), capacity(capacity), result(0)
+ {
+ }
+
+ size_t written_size() const
+ {
+ return result < capacity ? result : capacity;
+ }
+
+ virtual void write(const void* data, size_t size)
+ {
+ if (result < capacity)
+ {
+ size_t chunk = (capacity - result < size) ? capacity - result : size;
+
+ memcpy(buffer + result, data, chunk);
+ }
+
+ result += size;
+ }
+};
+
+std::string node_to_string(pugi::xml_node node)
+{
+ xml_string_writer writer;
+ node.print(writer);
+
+ return writer.result;
+}
+
+char* node_to_buffer(pugi::xml_node node, char* buffer, size_t size)
+{
+ if (size == 0) return buffer;
+
+ // leave one character for null terminator
+ xml_memory_writer writer(buffer, size - 1);
+ node.print(writer);
+
+ // null terminate
+ buffer[writer.written_size()] = 0;
+
+ return buffer;
+}
+
+char* node_to_buffer_heap(pugi::xml_node node)
+{
+ // first pass: get required memory size
+ xml_memory_writer counter;
+ node.print(counter);
+
+ // allocate necessary size (+1 for null termination)
+ char* buffer = new char[counter.result + 1];
+
+ // second pass: actual printing
+ xml_memory_writer writer(buffer, counter.result);
+ node.print(writer);
+
+ // null terminate
+ buffer[writer.written_size()] = 0;
+
+ return buffer;
+}
+
+int main()
+{
+ // get a test document
+ pugi::xml_document doc;
+ doc.load_string("<foo bar='baz'>hey</foo>");
+
+ // get contents as std::string (single pass)
+ std::cout << "contents: [" << node_to_string(doc) << "]\n";
+
+ // get contents into fixed-size buffer (single pass)
+ char large_buf[128];
+ std::cout << "contents: [" << node_to_buffer(doc, large_buf, sizeof(large_buf)) << "]\n";
+
+ // get contents into fixed-size buffer (single pass, shows truncating behavior)
+ char small_buf[22];
+ std::cout << "contents: [" << node_to_buffer(doc, small_buf, sizeof(small_buf)) << "]\n";
+
+ // get contents into heap-allocated buffer (two passes)
+ char* heap_buf = node_to_buffer_heap(doc);
+ std::cout << "contents: [" << heap_buf << "]\n";
+ delete[] heap_buf;
+}
+
+// vim:et
diff --git a/docs/samples/save_declaration.cpp b/docs/samples/save_declaration.cpp
new file mode 100644
index 0000000..7ca1e07
--- /dev/null
+++ b/docs/samples/save_declaration.cpp
@@ -0,0 +1,27 @@
+#include "pugixml.hpp"
+
+#include <iostream>
+
+int main()
+{
+ // tag::code[]
+ // get a test document
+ pugi::xml_document doc;
+ doc.load_string("<foo bar='baz'><call>hey</call></foo>");
+
+ // add a custom declaration node
+ pugi::xml_node decl = doc.prepend_child(pugi::node_declaration);
+ decl.append_attribute("version") = "1.0";
+ decl.append_attribute("encoding") = "UTF-8";
+ decl.append_attribute("standalone") = "no";
+
+ // <?xml version="1.0" encoding="UTF-8" standalone="no"?>
+ // <foo bar="baz">
+ // <call>hey</call>
+ // </foo>
+ doc.save(std::cout);
+ std::cout << std::endl;
+ // end::code[]
+}
+
+// vim:et
diff --git a/docs/samples/save_file.cpp b/docs/samples/save_file.cpp
new file mode 100644
index 0000000..10c6104
--- /dev/null
+++ b/docs/samples/save_file.cpp
@@ -0,0 +1,17 @@
+#include "pugixml.hpp"
+
+#include <iostream>
+
+int main()
+{
+ // get a test document
+ pugi::xml_document doc;
+ doc.load_string("<foo bar='baz'>hey</foo>");
+
+ // tag::code[]
+ // save document to file
+ std::cout << "Saving result: " << doc.save_file("save_file_output.xml") << std::endl;
+ // end::code[]
+}
+
+// vim:et
diff --git a/docs/samples/save_options.cpp b/docs/samples/save_options.cpp
new file mode 100644
index 0000000..e196946
--- /dev/null
+++ b/docs/samples/save_options.cpp
@@ -0,0 +1,48 @@
+#include "pugixml.hpp"
+
+#include <iostream>
+
+int main()
+{
+ // tag::code[]
+ // get a test document
+ pugi::xml_document doc;
+ doc.load_string("<foo bar='baz'><call>hey</call></foo>");
+
+ // default options; prints
+ // <?xml version="1.0"?>
+ // <foo bar="baz">
+ // <call>hey</call>
+ // </foo>
+ doc.save(std::cout);
+ std::cout << std::endl;
+
+ // default options with custom indentation string; prints
+ // <?xml version="1.0"?>
+ // <foo bar="baz">
+ // --<call>hey</call>
+ // </foo>
+ doc.save(std::cout, "--");
+ std::cout << std::endl;
+
+ // default options without indentation; prints
+ // <?xml version="1.0"?>
+ // <foo bar="baz">
+ // <call>hey</call>
+ // </foo>
+ doc.save(std::cout, "\t", pugi::format_default & ~pugi::format_indent); // can also pass "" instead of indentation string for the same effect
+ std::cout << std::endl;
+
+ // raw output; prints
+ // <?xml version="1.0"?><foo bar="baz"><call>hey</call></foo>
+ doc.save(std::cout, "\t", pugi::format_raw);
+ std::cout << std::endl << std::endl;
+
+ // raw output without declaration; prints
+ // <foo bar="baz"><call>hey</call></foo>
+ doc.save(std::cout, "\t", pugi::format_raw | pugi::format_no_declaration);
+ std::cout << std::endl;
+ // end::code[]
+}
+
+// vim:et
diff --git a/docs/samples/save_stream.cpp b/docs/samples/save_stream.cpp
new file mode 100644
index 0000000..84a33bf
--- /dev/null
+++ b/docs/samples/save_stream.cpp
@@ -0,0 +1,18 @@
+#include "pugixml.hpp"
+
+#include <iostream>
+
+int main()
+{
+ // get a test document
+ pugi::xml_document doc;
+ doc.load_string("<foo bar='baz'><call>hey</call></foo>");
+
+ // tag::code[]
+ // save document to standard output
+ std::cout << "Document:\n";
+ doc.save(std::cout);
+ // end::code[]
+}
+
+// vim:et
diff --git a/docs/samples/save_subtree.cpp b/docs/samples/save_subtree.cpp
new file mode 100644
index 0000000..5ae4830
--- /dev/null
+++ b/docs/samples/save_subtree.cpp
@@ -0,0 +1,26 @@
+#include "pugixml.hpp"
+
+#include <iostream>
+
+int main()
+{
+ // tag::code[]
+ // get a test document
+ pugi::xml_document doc;
+ doc.load_string("<foo bar='baz'><call>hey</call></foo>");
+
+ // print document to standard output (prints <?xml version="1.0"?><foo bar="baz"><call>hey</call></foo>)
+ doc.save(std::cout, "", pugi::format_raw);
+ std::cout << std::endl;
+
+ // print document to standard output as a regular node (prints <foo bar="baz"><call>hey</call></foo>)
+ doc.print(std::cout, "", pugi::format_raw);
+ std::cout << std::endl;
+
+ // print a subtree to standard output (prints <call>hey</call>)
+ doc.child("foo").child("call").print(std::cout, "", pugi::format_raw);
+ std::cout << std::endl;
+ // end::code[]
+}
+
+// vim:et
diff --git a/docs/samples/text.cpp b/docs/samples/text.cpp
new file mode 100644
index 0000000..0b4bae6
--- /dev/null
+++ b/docs/samples/text.cpp
@@ -0,0 +1,35 @@
+#include "pugixml.hpp"
+
+#include <iostream>
+
+int main()
+{
+ pugi::xml_document doc;
+
+ // get a test document
+ doc.load_string("<project><name>test</name><version>1.1</version><public>yes</public></project>");
+
+ pugi::xml_node project = doc.child("project");
+
+ // tag::access[]
+ std::cout << "Project name: " << project.child("name").text().get() << std::endl;
+ std::cout << "Project version: " << project.child("version").text().as_double() << std::endl;
+ std::cout << "Project visibility: " << (project.child("public").text().as_bool(/* def= */ true) ? "public" : "private") << std::endl;
+ std::cout << "Project description: " << project.child("description").text().get() << std::endl;
+ // end::access[]
+
+ std::cout << std::endl;
+
+ // tag::modify[]
+ // change project version
+ project.child("version").text() = 1.2;
+
+ // add description element and set the contents
+ // note that we do not have to explicitly add the node_pcdata child
+ project.append_child("description").text().set("a test project");
+ // end::modify[]
+
+ doc.save(std::cout);
+}
+
+// vim:et
diff --git a/docs/samples/transitions.xml b/docs/samples/transitions.xml
new file mode 100644
index 0000000..a195ef8
--- /dev/null
+++ b/docs/samples/transitions.xml
@@ -0,0 +1,7 @@
+<transition source="idle" target="run">
+ <event name="key_up|key_shift" />
+</transition>
+<transition source="run" target="attack">
+ <event name="key_ctrl" />
+ <condition expr="weapon != null" />
+</transition>
diff --git a/docs/samples/traverse_base.cpp b/docs/samples/traverse_base.cpp
new file mode 100644
index 0000000..3ee7fe4
--- /dev/null
+++ b/docs/samples/traverse_base.cpp
@@ -0,0 +1,51 @@
+#include "pugixml.hpp"
+
+#include <string.h>
+#include <iostream>
+
+int main()
+{
+ pugi::xml_document doc;
+ if (!doc.load_file("xgconsole.xml")) return -1;
+
+ pugi::xml_node tools = doc.child("Profile").child("Tools");
+
+ // tag::basic[]
+ for (pugi::xml_node tool = tools.first_child(); tool; tool = tool.next_sibling())
+ {
+ std::cout << "Tool:";
+
+ for (pugi::xml_attribute attr = tool.first_attribute(); attr; attr = attr.next_attribute())
+ {
+ std::cout << " " << attr.name() << "=" << attr.value();
+ }
+
+ std::cout << std::endl;
+ }
+ // end::basic[]
+
+ std::cout << std::endl;
+
+ // tag::data[]
+ for (pugi::xml_node tool = tools.child("Tool"); tool; tool = tool.next_sibling("Tool"))
+ {
+ std::cout << "Tool " << tool.attribute("Filename").value();
+ std::cout << ": AllowRemote " << tool.attribute("AllowRemote").as_bool();
+ std::cout << ", Timeout " << tool.attribute("Timeout").as_int();
+ std::cout << ", Description '" << tool.child_value("Description") << "'\n";
+ }
+ // end::data[]
+
+ std::cout << std::endl;
+
+ // tag::contents[]
+ std::cout << "Tool for *.dae generation: " << tools.find_child_by_attribute("Tool", "OutputFileMasks", "*.dae").attribute("Filename").value() << "\n";
+
+ for (pugi::xml_node tool = tools.child("Tool"); tool; tool = tool.next_sibling("Tool"))
+ {
+ std::cout << "Tool " << tool.attribute("Filename").value() << "\n";
+ }
+ // end::contents[]
+}
+
+// vim:et
diff --git a/docs/samples/traverse_iter.cpp b/docs/samples/traverse_iter.cpp
new file mode 100644
index 0000000..77bcf35
--- /dev/null
+++ b/docs/samples/traverse_iter.cpp
@@ -0,0 +1,27 @@
+#include "pugixml.hpp"
+
+#include <iostream>
+
+int main()
+{
+ pugi::xml_document doc;
+ if (!doc.load_file("xgconsole.xml")) return -1;
+
+ pugi::xml_node tools = doc.child("Profile").child("Tools");
+
+ // tag::code[]
+ for (pugi::xml_node_iterator it = tools.begin(); it != tools.end(); ++it)
+ {
+ std::cout << "Tool:";
+
+ for (pugi::xml_attribute_iterator ait = it->attributes_begin(); ait != it->attributes_end(); ++ait)
+ {
+ std::cout << " " << ait->name() << "=" << ait->value();
+ }
+
+ std::cout << std::endl;
+ }
+ // end::code[]
+}
+
+// vim:et
diff --git a/docs/samples/traverse_predicate.cpp b/docs/samples/traverse_predicate.cpp
new file mode 100644
index 0000000..40e1718
--- /dev/null
+++ b/docs/samples/traverse_predicate.cpp
@@ -0,0 +1,48 @@
+#include "pugixml.hpp"
+
+#include <string.h>
+#include <iostream>
+
+// tag::decl[]
+bool small_timeout(pugi::xml_node node)
+{
+ return node.attribute("Timeout").as_int() < 20;
+}
+
+struct allow_remote_predicate
+{
+ bool operator()(pugi::xml_attribute attr) const
+ {
+ return strcmp(attr.name(), "AllowRemote") == 0;
+ }
+
+ bool operator()(pugi::xml_node node) const
+ {
+ return node.attribute("AllowRemote").as_bool();
+ }
+};
+// end::decl[]
+
+int main()
+{
+ pugi::xml_document doc;
+ if (!doc.load_file("xgconsole.xml")) return -1;
+
+ pugi::xml_node tools = doc.child("Profile").child("Tools");
+
+ // tag::find[]
+ // Find child via predicate (looks for direct children only)
+ std::cout << tools.find_child(allow_remote_predicate()).attribute("Filename").value() << std::endl;
+
+ // Find node via predicate (looks for all descendants in depth-first order)
+ std::cout << doc.find_node(allow_remote_predicate()).attribute("Filename").value() << std::endl;
+
+ // Find attribute via predicate
+ std::cout << tools.last_child().find_attribute(allow_remote_predicate()).value() << std::endl;
+
+ // We can use simple functions instead of function objects
+ std::cout << tools.find_child(small_timeout).attribute("Filename").value() << std::endl;
+ // end::find[]
+}
+
+// vim:et
diff --git a/docs/samples/traverse_rangefor.cpp b/docs/samples/traverse_rangefor.cpp
new file mode 100644
index 0000000..8d9d7d5
--- /dev/null
+++ b/docs/samples/traverse_rangefor.cpp
@@ -0,0 +1,32 @@
+#include "pugixml.hpp"
+
+#include <iostream>
+
+int main()
+{
+ pugi::xml_document doc;
+ if (!doc.load_file("xgconsole.xml")) return -1;
+
+ pugi::xml_node tools = doc.child("Profile").child("Tools");
+
+ // tag::code[]
+ for (pugi::xml_node tool: tools.children("Tool"))
+ {
+ std::cout << "Tool:";
+
+ for (pugi::xml_attribute attr: tool.attributes())
+ {
+ std::cout << " " << attr.name() << "=" << attr.value();
+ }
+
+ for (pugi::xml_node child: tool.children())
+ {
+ std::cout << ", child " << child.name();
+ }
+
+ std::cout << std::endl;
+ }
+ // end::code[]
+}
+
+// vim:et
diff --git a/docs/samples/traverse_walker.cpp b/docs/samples/traverse_walker.cpp
new file mode 100644
index 0000000..2f4b11b
--- /dev/null
+++ b/docs/samples/traverse_walker.cpp
@@ -0,0 +1,35 @@
+#include "pugixml.hpp"
+
+#include <iostream>
+
+const char* node_types[] =
+{
+ "null", "document", "element", "pcdata", "cdata", "comment", "pi", "declaration"
+};
+
+// tag::impl[]
+struct simple_walker: pugi::xml_tree_walker
+{
+ virtual bool for_each(pugi::xml_node& node)
+ {
+ for (int i = 0; i < depth(); ++i) std::cout << " "; // indentation
+
+ std::cout << node_types[node.type()] << ": name='" << node.name() << "', value='" << node.value() << "'\n";
+
+ return true; // continue traversal
+ }
+};
+// end::impl[]
+
+int main()
+{
+ pugi::xml_document doc;
+ if (!doc.load_file("tree.xml")) return -1;
+
+ // tag::traverse[]
+ simple_walker walker;
+ doc.traverse(walker);
+ // end::traverse[]
+}
+
+// vim:et
diff --git a/docs/samples/tree.xml b/docs/samples/tree.xml
new file mode 100644
index 0000000..b33267a
--- /dev/null
+++ b/docs/samples/tree.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<mesh name="mesh_root">
+ <!-- here is a mesh node -->
+ some text
+ <![CDATA[someothertext]]>
+ some more text
+ <node attr1="value1" attr2="value2" />
+ <node attr1="value2">
+ <innernode/>
+ </node>
+</mesh>
+<?include somedata?>
diff --git a/docs/samples/weekly-shift_jis.xml b/docs/samples/weekly-shift_jis.xml
new file mode 100644
index 0000000..097e374
--- /dev/null
+++ b/docs/samples/weekly-shift_jis.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="Shift_JIS"?>
+<!DOCTYPE 週報 SYSTEM "weekly-shift_jis.dtd">
+<!-- 週報サンプル -->
+<週報>
+ <年月週>
+ <年度>1997</年度>
+ <月度>1</月度>
+ <週>1</週>
+ </年月週>
+
+ <氏名>
+ <氏>山田</氏>
+ <名>太郎</名>
+ </氏名>
+
+ <業務報告リスト>
+ <業務報告>
+ <業務名>XMLエディターの作成</業務名>
+ <業務コード>X3355-23</業務コード>
+ <工数管理>
+ <見積もり工数>1600</見積もり工数>
+ <実績工数>320</実績工数>
+ <当月見積もり工数>160</当月見積もり工数>
+ <当月実績工数>24</当月実績工数>
+ </工数管理>
+ <予定項目リスト>
+ <予定項目>
+ <P>XMLエディターの基本仕様の作成</P>
+ </予定項目>
+ </予定項目リスト>
+ <実施事項リスト>
+ <実施事項>
+ <P>XMLエディターの基本仕様の作成</P>
+ </実施事項>
+ <実施事項>
+ <P>競合他社製品の機能調査</P>
+ </実施事項>
+ </実施事項リスト>
+ <上長への要請事項リスト>
+ <上長への要請事項>
+ <P>特になし</P>
+ </上長への要請事項>
+ </上長への要請事項リスト>
+ <問題点対策>
+ <P>XMLとは何かわからない。</P>
+ </問題点対策>
+ </業務報告>
+
+ <業務報告>
+ <業務名>検索エンジンの開発</業務名>
+ <業務コード>S8821-76</業務コード>
+ <工数管理>
+ <見積もり工数>120</見積もり工数>
+ <実績工数>6</実績工数>
+ <当月見積もり工数>32</当月見積もり工数>
+ <当月実績工数>2</当月実績工数>
+ </工数管理>
+ <予定項目リスト>
+ <予定項目>
+ <P><A href="http://www.goo.ne.jp">goo</A>の機能を調べてみる</P>
+ </予定項目>
+ </予定項目リスト>
+ <実施事項リスト>
+ <実施事項>
+ <P>更に、どういう検索エンジンがあるか調査する</P>
+ </実施事項>
+ </実施事項リスト>
+ <上長への要請事項リスト>
+ <上長への要請事項>
+ <P>開発をするのはめんどうなので、Yahoo!を買収して下さい。</P>
+ </上長への要請事項>
+ </上長への要請事項リスト>
+ <問題点対策>
+ <P>検索エンジンで車を走らせることができない。(要調査)</P>
+ </問題点対策>
+ </業務報告>
+ </業務報告リスト>
+</週報>
diff --git a/docs/samples/weekly-utf-16.xml b/docs/samples/weekly-utf-16.xml
new file mode 100644
index 0000000..6c8622a
--- /dev/null
+++ b/docs/samples/weekly-utf-16.xml
Binary files differ
diff --git a/docs/samples/weekly-utf-8.xml b/docs/samples/weekly-utf-8.xml
new file mode 100644
index 0000000..d55474e
--- /dev/null
+++ b/docs/samples/weekly-utf-8.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0"?>
+<!DOCTYPE 騾ア蝣ア SYSTEM "weekly-utf-8.dtd">
+<!-- 騾ア蝣ア繧オ繝ウ繝励Ν -->
+<騾ア蝣ア>
+ <蟷エ譛磯ア>
+ <蟷エ蠎ヲ>1997</蟷エ蠎ヲ>
+ <譛亥コヲ>1</譛亥コヲ>
+ <騾ア>1</騾ア>
+ </蟷エ譛磯ア>
+
+ <豌丞錐>
+ <豌>螻ア逕ー</豌>
+ <蜷>螟ェ驛</蜷>
+ </豌丞錐>
+
+ <讌ュ蜍吝ア蜻翫Μ繧ケ繝>
+ <讌ュ蜍吝ア蜻>
+ <讌ュ蜍吝錐>XML繧ィ繝繧」繧ソ繝シ縺ョ菴懈</讌ュ蜍吝錐>
+ <讌ュ蜍吶さ繝シ繝>X3355-23</讌ュ蜍吶さ繝シ繝>
+ <蟾・謨ー邂。逅>
+ <隕狗ゥ阪b繧雁キ・謨ー>1600</隕狗ゥ阪b繧雁キ・謨ー>
+ <螳溽クセ蟾・謨ー>320</螳溽クセ蟾・謨ー>
+ <蠖捺怦隕狗ゥ阪b繧雁キ・謨ー>160</蠖捺怦隕狗ゥ阪b繧雁キ・謨ー>
+ <蠖捺怦螳溽クセ蟾・謨ー>24</蠖捺怦螳溽クセ蟾・謨ー>
+ </蟾・謨ー邂。逅>
+ <莠亥ョ夐逶ョ繝ェ繧ケ繝>
+ <莠亥ョ夐逶ョ>
+ <P>XML繧ィ繝繧」繧ソ繝シ縺ョ蝓コ譛ャ莉墓ァ倥ョ菴懈</P>
+ </莠亥ョ夐逶ョ>
+ </莠亥ョ夐逶ョ繝ェ繧ケ繝>
+ <螳滓命莠矩繝ェ繧ケ繝>
+ <螳滓命莠矩>
+ <P>XML繧ィ繝繧」繧ソ繝シ縺ョ蝓コ譛ャ莉墓ァ倥ョ菴懈</P>
+ </螳滓命莠矩>
+ <螳滓命莠矩>
+ <P>遶カ蜷井サ也、セ陬ス蜩√ョ讖溯ス隱ソ譟サ</P>
+ </螳滓命莠矩>
+ </螳滓命莠矩繝ェ繧ケ繝>
+ <荳企聞縺ク縺ョ隕∬ォ倶コ矩繝ェ繧ケ繝>
+ <荳企聞縺ク縺ョ隕∬ォ倶コ矩>
+ <P>迚ケ縺ォ縺ェ縺</P>
+ </荳企聞縺ク縺ョ隕∬ォ倶コ矩>
+ </荳企聞縺ク縺ョ隕∬ォ倶コ矩繝ェ繧ケ繝>
+ <蝠城。檎せ蟇セ遲>
+ <P>XML縺ィ縺ッ菴輔°繧上°繧峨↑縺縲</P>
+ </蝠城。檎せ蟇セ遲>
+ </讌ュ蜍吝ア蜻>
+
+ <讌ュ蜍吝ア蜻>
+ <讌ュ蜍吝錐>讀懃エ「繧ィ繝ウ繧ク繝ウ縺ョ髢狗匱</讌ュ蜍吝錐>
+ <讌ュ蜍吶さ繝シ繝>S8821-76</讌ュ蜍吶さ繝シ繝>
+ <蟾・謨ー邂。逅>
+ <隕狗ゥ阪b繧雁キ・謨ー>120</隕狗ゥ阪b繧雁キ・謨ー>
+ <螳溽クセ蟾・謨ー>6</螳溽クセ蟾・謨ー>
+ <蠖捺怦隕狗ゥ阪b繧雁キ・謨ー>32</蠖捺怦隕狗ゥ阪b繧雁キ・謨ー>
+ <蠖捺怦螳溽クセ蟾・謨ー>2</蠖捺怦螳溽クセ蟾・謨ー>
+ </蟾・謨ー邂。逅>
+ <莠亥ョ夐逶ョ繝ェ繧ケ繝>
+ <莠亥ョ夐逶ョ>
+ <P><A href="http://www.goo.ne.jp">goo</A>縺ョ讖溯ス繧定ェソ縺ケ縺ヲ縺ソ繧</P>
+ </莠亥ョ夐逶ョ>
+ </莠亥ョ夐逶ョ繝ェ繧ケ繝>
+ <螳滓命莠矩繝ェ繧ケ繝>
+ <螳滓命莠矩>
+ <P>譖エ縺ォ縲√←縺縺縺讀懃エ「繧ィ繝ウ繧ク繝ウ縺後≠繧九°隱ソ譟サ縺吶k</P>
+ </螳滓命莠矩>
+ </螳滓命莠矩繝ェ繧ケ繝>
+ <荳企聞縺ク縺ョ隕∬ォ倶コ矩繝ェ繧ケ繝>
+ <荳企聞縺ク縺ョ隕∬ォ倶コ矩>
+ <P>髢狗匱繧偵☆繧九ョ縺ッ繧√s縺ゥ縺縺ェ縺ョ縺ァ縲〆ahoo!繧定イキ蜿弱@縺ヲ荳九&縺縲</P>
+ </荳企聞縺ク縺ョ隕∬ォ倶コ矩>
+ </荳企聞縺ク縺ョ隕∬ォ倶コ矩繝ェ繧ケ繝>
+ <蝠城。檎せ蟇セ遲>
+ <P>讀懃エ「繧ィ繝ウ繧ク繝ウ縺ァ霆翫r襍ー繧峨○繧九%縺ィ縺後〒縺阪↑縺縲ゑシ郁ヲ∬ェソ譟サシ</P>
+ </蝠城。檎せ蟇セ遲>
+ </讌ュ蜍吝ア蜻>
+ </讌ュ蜍吝ア蜻翫Μ繧ケ繝>
+</騾ア蝣ア>
diff --git a/docs/samples/xgconsole.xml b/docs/samples/xgconsole.xml
new file mode 100644
index 0000000..b2bf5a2
--- /dev/null
+++ b/docs/samples/xgconsole.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
+<Profile FormatVersion="1">
+ <Tools>
+ <Tool Filename="jam" AllowIntercept="true">
+ <Description>Jamplus build system</Description>
+ </Tool>
+ <Tool Filename="mayabatch.exe" AllowRemote="true" OutputFileMasks="*.dae" DeriveCaptionFrom="lastparam" Timeout="40" />
+ <Tool Filename="meshbuilder_*.exe" AllowRemote="false" OutputFileMasks="*.mesh" DeriveCaptionFrom="lastparam" Timeout="10" />
+ <Tool Filename="texbuilder_*.exe" AllowRemote="true" OutputFileMasks="*.tex" DeriveCaptionFrom="lastparam" />
+ <Tool Filename="shaderbuilder_*.exe" AllowRemote="true" DeriveCaptionFrom="lastparam" />
+ </Tools>
+</Profile>
diff --git a/docs/samples/xpath_error.cpp b/docs/samples/xpath_error.cpp
new file mode 100644
index 0000000..b6dc424
--- /dev/null
+++ b/docs/samples/xpath_error.cpp
@@ -0,0 +1,43 @@
+#include "pugixml.hpp"
+
+#include <iostream>
+
+int main()
+{
+ pugi::xml_document doc;
+ if (!doc.load_file("xgconsole.xml")) return -1;
+
+// tag::code[]
+ // Exception is thrown for incorrect query syntax
+ try
+ {
+ doc.select_nodes("//nodes[#true()]");
+ }
+ catch (const pugi::xpath_exception& e)
+ {
+ std::cout << "Select failed: " << e.what() << std::endl;
+ }
+
+ // Exception is thrown for incorrect query semantics
+ try
+ {
+ doc.select_nodes("(123)/next");
+ }
+ catch (const pugi::xpath_exception& e)
+ {
+ std::cout << "Select failed: " << e.what() << std::endl;
+ }
+
+ // Exception is thrown for query with incorrect return type
+ try
+ {
+ doc.select_nodes("123");
+ }
+ catch (const pugi::xpath_exception& e)
+ {
+ std::cout << "Select failed: " << e.what() << std::endl;
+ }
+// end::code[]
+}
+
+// vim:et
diff --git a/docs/samples/xpath_query.cpp b/docs/samples/xpath_query.cpp
new file mode 100644
index 0000000..857c04c
--- /dev/null
+++ b/docs/samples/xpath_query.cpp
@@ -0,0 +1,36 @@
+#include "pugixml.hpp"
+
+#include <iostream>
+#include <string>
+
+int main()
+{
+ pugi::xml_document doc;
+ if (!doc.load_file("xgconsole.xml")) return -1;
+
+// tag::code[]
+ // Select nodes via compiled query
+ pugi::xpath_query query_remote_tools("/Profile/Tools/Tool[@AllowRemote='true']");
+
+ pugi::xpath_node_set tools = query_remote_tools.evaluate_node_set(doc);
+ std::cout << "Remote tool: ";
+ tools[2].node().print(std::cout);
+
+ // Evaluate numbers via compiled query
+ pugi::xpath_query query_timeouts("sum(//Tool/@Timeout)");
+ std::cout << query_timeouts.evaluate_number(doc) << std::endl;
+
+ // Evaluate strings via compiled query for different context nodes
+ pugi::xpath_query query_name_valid("string-length(substring-before(@Filename, '_')) > 0 and @OutputFileMasks");
+ pugi::xpath_query query_name("concat(substring-before(@Filename, '_'), ' produces ', @OutputFileMasks)");
+
+ for (pugi::xml_node tool = doc.first_element_by_path("Profile/Tools/Tool"); tool; tool = tool.next_sibling())
+ {
+ std::string s = query_name.evaluate_string(tool);
+
+ if (query_name_valid.evaluate_boolean(tool)) std::cout << s << std::endl;
+ }
+// end::code[]
+}
+
+// vim:et
diff --git a/docs/samples/xpath_select.cpp b/docs/samples/xpath_select.cpp
new file mode 100644
index 0000000..f6067a3
--- /dev/null
+++ b/docs/samples/xpath_select.cpp
@@ -0,0 +1,28 @@
+#include "pugixml.hpp"
+
+#include <iostream>
+
+int main()
+{
+ pugi::xml_document doc;
+ if (!doc.load_file("xgconsole.xml")) return -1;
+
+// tag::code[]
+ pugi::xpath_node_set tools = doc.select_nodes("/Profile/Tools/Tool[@AllowRemote='true' and @DeriveCaptionFrom='lastparam']");
+
+ std::cout << "Tools:\n";
+
+ for (pugi::xpath_node_set::const_iterator it = tools.begin(); it != tools.end(); ++it)
+ {
+ pugi::xpath_node node = *it;
+ std::cout << node.node().attribute("Filename").value() << "\n";
+ }
+
+ pugi::xpath_node build_tool = doc.select_node("//Tool[contains(Description, 'build system')]");
+
+ if (build_tool)
+ std::cout << "Build tool: " << build_tool.node().attribute("Filename").value() << "\n";
+// end::code[]
+}
+
+// vim:et
diff --git a/docs/samples/xpath_variables.cpp b/docs/samples/xpath_variables.cpp
new file mode 100644
index 0000000..5affaef
--- /dev/null
+++ b/docs/samples/xpath_variables.cpp
@@ -0,0 +1,38 @@
+#include "pugixml.hpp"
+
+#include <iostream>
+#include <string>
+
+int main()
+{
+ pugi::xml_document doc;
+ if (!doc.load_file("xgconsole.xml")) return -1;
+
+// tag::code[]
+ // Select nodes via compiled query
+ pugi::xpath_variable_set vars;
+ vars.add("remote", pugi::xpath_type_boolean);
+
+ pugi::xpath_query query_remote_tools("/Profile/Tools/Tool[@AllowRemote = string($remote)]", &vars);
+
+ vars.set("remote", true);
+ pugi::xpath_node_set tools_remote = query_remote_tools.evaluate_node_set(doc);
+
+ vars.set("remote", false);
+ pugi::xpath_node_set tools_local = query_remote_tools.evaluate_node_set(doc);
+
+ std::cout << "Remote tool: ";
+ tools_remote[2].node().print(std::cout);
+
+ std::cout << "Local tool: ";
+ tools_local[0].node().print(std::cout);
+
+ // You can pass the context directly to select_nodes/select_node
+ pugi::xpath_node_set tools_local_imm = doc.select_nodes("/Profile/Tools/Tool[@AllowRemote = string($remote)]", &vars);
+
+ std::cout << "Local tool imm: ";
+ tools_local_imm[0].node().print(std::cout);
+// end::code[]
+}
+
+// vim:et