From 65e90b2d7a86383243e380b2658fad26dce370f0 Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Wed, 8 Apr 2015 21:44:16 -0700 Subject: docs: Add docs folder from master --- docs/samples/character.xml | 8 +++ docs/samples/custom_memory_management.cpp | 27 +++++++ docs/samples/include.cpp | 64 +++++++++++++++++ docs/samples/load_error_handling.cpp | 33 +++++++++ docs/samples/load_file.cpp | 16 +++++ docs/samples/load_memory.cpp | 66 +++++++++++++++++ docs/samples/load_options.cpp | 30 ++++++++ docs/samples/load_stream.cpp | 97 +++++++++++++++++++++++++ docs/samples/modify_add.cpp | 29 ++++++++ docs/samples/modify_base.cpp | 43 +++++++++++ docs/samples/modify_remove.cpp | 27 +++++++ docs/samples/save_custom_writer.cpp | 116 ++++++++++++++++++++++++++++++ docs/samples/save_declaration.cpp | 27 +++++++ docs/samples/save_file.cpp | 17 +++++ docs/samples/save_options.cpp | 48 +++++++++++++ docs/samples/save_stream.cpp | 18 +++++ docs/samples/save_subtree.cpp | 26 +++++++ docs/samples/text.cpp | 35 +++++++++ docs/samples/transitions.xml | 7 ++ docs/samples/traverse_base.cpp | 51 +++++++++++++ docs/samples/traverse_iter.cpp | 27 +++++++ docs/samples/traverse_predicate.cpp | 48 +++++++++++++ docs/samples/traverse_rangefor.cpp | 32 +++++++++ docs/samples/traverse_walker.cpp | 35 +++++++++ docs/samples/tree.xml | 12 ++++ docs/samples/weekly-shift_jis.xml | 78 ++++++++++++++++++++ docs/samples/weekly-utf-16.xml | Bin 0 -> 3186 bytes docs/samples/weekly-utf-8.xml | 78 ++++++++++++++++++++ docs/samples/xgconsole.xml | 12 ++++ docs/samples/xpath_error.cpp | 43 +++++++++++ docs/samples/xpath_query.cpp | 36 ++++++++++ docs/samples/xpath_select.cpp | 28 ++++++++ docs/samples/xpath_variables.cpp | 38 ++++++++++ 33 files changed, 1252 insertions(+) create mode 100644 docs/samples/character.xml create mode 100644 docs/samples/custom_memory_management.cpp create mode 100644 docs/samples/include.cpp create mode 100644 docs/samples/load_error_handling.cpp create mode 100644 docs/samples/load_file.cpp create mode 100644 docs/samples/load_memory.cpp create mode 100644 docs/samples/load_options.cpp create mode 100644 docs/samples/load_stream.cpp create mode 100644 docs/samples/modify_add.cpp create mode 100644 docs/samples/modify_base.cpp create mode 100644 docs/samples/modify_remove.cpp create mode 100644 docs/samples/save_custom_writer.cpp create mode 100644 docs/samples/save_declaration.cpp create mode 100644 docs/samples/save_file.cpp create mode 100644 docs/samples/save_options.cpp create mode 100644 docs/samples/save_stream.cpp create mode 100644 docs/samples/save_subtree.cpp create mode 100644 docs/samples/text.cpp create mode 100644 docs/samples/transitions.xml create mode 100644 docs/samples/traverse_base.cpp create mode 100644 docs/samples/traverse_iter.cpp create mode 100644 docs/samples/traverse_predicate.cpp create mode 100644 docs/samples/traverse_rangefor.cpp create mode 100644 docs/samples/traverse_walker.cpp create mode 100644 docs/samples/tree.xml create mode 100644 docs/samples/weekly-shift_jis.xml create mode 100644 docs/samples/weekly-utf-16.xml create mode 100644 docs/samples/weekly-utf-8.xml create mode 100644 docs/samples/xgconsole.xml create mode 100644 docs/samples/xpath_error.cpp create mode 100644 docs/samples/xpath_query.cpp create mode 100644 docs/samples/xpath_select.cpp create mode 100644 docs/samples/xpath_variables.cpp (limited to 'docs/samples') 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 @@ + + + + + + + + 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 + +// tag::decl[] +void* custom_allocate(size_t size) +{ + return new (std::nothrow) char[size]; +} + +void custom_deallocate(void* ptr) +{ + delete[] static_cast(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(""); +} + +// 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 +#include + +// 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 + + 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 + +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("text"); + check_xml("text"); + check_xml("text"); + check_xml("<#tag />"); +} + +// 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 + +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 +#include + +int main() +{ +// tag::decl[] + const char source[] = "0 0 1 1"; + 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(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("0 0 1 1"); + // 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 + +int main() +{ + pugi::xml_document doc; + +// tag::code[] + const char* source = "<"; + + // Parsing with default options; note that comment node is not added to the tree, and entity reference < 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; < 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 < 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 +#include +#include + +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 + +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 +#include + +int main() +{ + pugi::xml_document doc; + if (!doc.load_string("text", 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 + +int main() +{ + pugi::xml_document doc; + if (!doc.load_string("Simple 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 +#include +#include + +// 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(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("hey"); + + // 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 + +int main() +{ + // tag::code[] + // get a test document + pugi::xml_document doc; + doc.load_string("hey"); + + // 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"; + + // + // + // hey + // + 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 + +int main() +{ + // get a test document + pugi::xml_document doc; + doc.load_string("hey"); + + // 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 + +int main() +{ + // tag::code[] + // get a test document + pugi::xml_document doc; + doc.load_string("hey"); + + // default options; prints + // + // + // hey + // + doc.save(std::cout); + std::cout << std::endl; + + // default options with custom indentation string; prints + // + // + // --hey + // + doc.save(std::cout, "--"); + std::cout << std::endl; + + // default options without indentation; prints + // + // + // hey + // + 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 + // hey + doc.save(std::cout, "\t", pugi::format_raw); + std::cout << std::endl << std::endl; + + // raw output without declaration; prints + // hey + 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 + +int main() +{ + // get a test document + pugi::xml_document doc; + doc.load_string("hey"); + + // 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 + +int main() +{ + // tag::code[] + // get a test document + pugi::xml_document doc; + doc.load_string("hey"); + + // print document to standard output (prints hey) + doc.save(std::cout, "", pugi::format_raw); + std::cout << std::endl; + + // print document to standard output as a regular node (prints hey) + doc.print(std::cout, "", pugi::format_raw); + std::cout << std::endl; + + // print a subtree to standard output (prints hey) + 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 + +int main() +{ + pugi::xml_document doc; + + // get a test document + doc.load_string("test1.1yes"); + + 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 @@ + + + + + + + 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 +#include + +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 + +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 +#include + +// 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 + +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 + +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 @@ + + + + some text + + some more text + + + + + + 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 @@ + + + +<週報> + <年月週> + <年度>1997 + <月度>1 + <週>1 + + + <氏名> + <氏>山田 + <名>太郎 + + + <業務報告リスト> + <業務報告> + <業務名>XMLエディターの作成 + <業務コード>X3355-23 + <工数管理> + <見積もり工数>1600 + <実績工数>320 + <当月見積もり工数>160 + <当月実績工数>24 + + <予定項目リスト> + <予定項目> +

XMLエディターの基本仕様の作成

+ + + <実施事項リスト> + <実施事項> +

XMLエディターの基本仕様の作成

+ + <実施事項> +

競合他社製品の機能調査

+ + + <上長への要請事項リスト> + <上長への要請事項> +

特になし

+ + + <問題点対策> +

XMLとは何かわからない。

+ + + + <業務報告> + <業務名>検索エンジンの開発 + <業務コード>S8821-76 + <工数管理> + <見積もり工数>120 + <実績工数>6 + <当月見積もり工数>32 + <当月実績工数>2 + + <予定項目リスト> + <予定項目> +

gooの機能を調べてみる

+ + + <実施事項リスト> + <実施事項> +

更に、どういう検索エンジンがあるか調査する

+ + + <上長への要請事項リスト> + <上長への要請事項> +

開発をするのはめんどうなので、Yahoo!を買収して下さい。

+ + + <問題点対策> +

検索エンジンで車を走らせることができない。(要調査)

+ + + + diff --git a/docs/samples/weekly-utf-16.xml b/docs/samples/weekly-utf-16.xml new file mode 100644 index 0000000..6c8622a Binary files /dev/null and b/docs/samples/weekly-utf-16.xml 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 @@ + + + +<騾ア蝣ア> + <蟷エ譛磯ア> + <蟷エ蠎ヲ>1997 + <譛亥コヲ>1 + <騾ア>1 + + + <豌丞錐> + <豌>螻ア逕ー + <蜷>螟ェ驛 + + + <讌ュ蜍吝ア蜻翫Μ繧ケ繝> + <讌ュ蜍吝ア蜻> + <讌ュ蜍吝錐>XML繧ィ繝繧」繧ソ繝シ縺ョ菴懈 + <讌ュ蜍吶さ繝シ繝>X3355-23 + <蟾・謨ー邂。逅> + <隕狗ゥ阪b繧雁キ・謨ー>1600 + <螳溽クセ蟾・謨ー>320 + <蠖捺怦隕狗ゥ阪b繧雁キ・謨ー>160 + <蠖捺怦螳溽クセ蟾・謨ー>24 + + <莠亥ョ夐逶ョ繝ェ繧ケ繝> + <莠亥ョ夐逶ョ> +

XML繧ィ繝繧」繧ソ繝シ縺ョ蝓コ譛ャ莉墓ァ倥ョ菴懈

+ + + <螳滓命莠矩繝ェ繧ケ繝> + <螳滓命莠矩> +

XML繧ィ繝繧」繧ソ繝シ縺ョ蝓コ譛ャ莉墓ァ倥ョ菴懈

+ + <螳滓命莠矩> +

遶カ蜷井サ也、セ陬ス蜩√ョ讖溯ス隱ソ譟サ

+ + + <荳企聞縺ク縺ョ隕∬ォ倶コ矩繝ェ繧ケ繝> + <荳企聞縺ク縺ョ隕∬ォ倶コ矩> +

迚ケ縺ォ縺ェ縺

+ + + <蝠城。檎せ蟇セ遲> +

XML縺ィ縺ッ菴輔°繧上°繧峨↑縺縲

+ + + + <讌ュ蜍吝ア蜻> + <讌ュ蜍吝錐>讀懃エ「繧ィ繝ウ繧ク繝ウ縺ョ髢狗匱 + <讌ュ蜍吶さ繝シ繝>S8821-76 + <蟾・謨ー邂。逅> + <隕狗ゥ阪b繧雁キ・謨ー>120 + <螳溽クセ蟾・謨ー>6 + <蠖捺怦隕狗ゥ阪b繧雁キ・謨ー>32 + <蠖捺怦螳溽クセ蟾・謨ー>2 + + <莠亥ョ夐逶ョ繝ェ繧ケ繝> + <莠亥ョ夐逶ョ> +

goo縺ョ讖溯ス繧定ェソ縺ケ縺ヲ縺ソ繧

+ + + <螳滓命莠矩繝ェ繧ケ繝> + <螳滓命莠矩> +

譖エ縺ォ縲√←縺縺縺讀懃エ「繧ィ繝ウ繧ク繝ウ縺後≠繧九°隱ソ譟サ縺吶k

+ + + <荳企聞縺ク縺ョ隕∬ォ倶コ矩繝ェ繧ケ繝> + <荳企聞縺ク縺ョ隕∬ォ倶コ矩> +

髢狗匱繧偵☆繧九ョ縺ッ繧√s縺ゥ縺縺ェ縺ョ縺ァ縲〆ahoo!繧定イキ蜿弱@縺ヲ荳九&縺縲

+ + + <蝠城。檎せ蟇セ遲> +

讀懃エ「繧ィ繝ウ繧ク繝ウ縺ァ霆翫r襍ー繧峨○繧九%縺ィ縺後〒縺阪↑縺縲ゑシ郁ヲ∬ェソ譟サシ

+ + + + 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 @@ + + + + + Jamplus build system + + + + + + + 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 + +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 +#include + +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 + +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 +#include + +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 -- cgit v1.2.3