diff --git a/CMakeLists.txt b/CMakeLists.txt
index cdb8c21..17f67d1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.4)
-project(pugixml VERSION 1.11 LANGUAGES CXX)
+project(pugixml VERSION 1.12 LANGUAGES CXX)
include(CMakePackageConfigHelpers)
include(CMakeDependentOption)
@@ -33,7 +33,7 @@ option(BUILD_SHARED_LIBS "Build shared instead of static library" OFF)
cmake_dependent_option(PUGIXML_BUILD_SHARED_AND_STATIC_LIBS
"Build both shared and static libraries" OFF
"BUILD_SHARED_LIBS" OFF)
-
+
# Expose options from the pugiconfig.hpp
option(PUGIXML_WCHAR_MODE "Enable wchar_t mode" OFF)
option(PUGIXML_COMPACT "Enable compact mode" OFF)
diff --git a/LICENSE.md b/LICENSE.md
index 2503b81..63042bd 100644
--- a/LICENSE.md
+++ b/LICENSE.md
@@ -1,6 +1,6 @@
MIT License
-Copyright (c) 2006-2020 Arseny Kapoulkine
+Copyright (c) 2006-2022 Arseny Kapoulkine
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 0000000..ae94871
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,9 @@
+# Security Policy
+
+## Supported Versions
+
+Please verify that the vulnerabilities reported can be reproduced on the [latest released version](https://github.com/zeux/pugixml/releases).
+
+## Reporting a Vulnerability
+
+Vulnerabilities can be reported via e-mail to the [project maintainer](https://github.com/zeux).
diff --git a/appveyor.yml b/appveyor.yml
index 2a596b6..2f2c0e6 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,4 +1,5 @@
image:
+ - Visual Studio 2022
- Visual Studio 2019
- Visual Studio 2017
- Visual Studio 2015
@@ -10,11 +11,13 @@ build_script:
- ps: if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2015") { .\scripts\nuget_build.ps1 2015}
- ps: if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2017") { .\scripts\nuget_build.ps1 2017}
- ps: if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2019") { .\scripts\nuget_build.ps1 2019}
+ - ps: if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2022") { .\scripts\nuget_build.ps1 2022}
test_script:
- ps: if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2015") { .\tests\autotest-appveyor.ps1 9 10 11 12 14 }
- ps: if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2017") { .\tests\autotest-appveyor.ps1 15 }
- ps: if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2019") { .\tests\autotest-appveyor.ps1 19 }
+ - ps: if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2022") { .\tests\autotest-appveyor.ps1 22 }
- ps: if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2015") { & C:\cygwin\bin\bash.exe -c "PATH=/usr/bin:/usr/local/bin:$PATH; make config=coverage test && bash <(curl -s https://codecov.io/bash) -f pugixml.cpp.gcov 2>&1" }
- ps: if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2015") { & C:\cygwin\bin\bash.exe -c "PATH=/usr/bin:/usr/local/bin:$PATH; make config=coverage defines=PUGIXML_WCHAR_MODE test && bash <(curl -s https://codecov.io/bash) -f pugixml.cpp.gcov 2>&1" }
diff --git a/docs/manual.adoc b/docs/manual.adoc
index 0262047..ac51535 100644
--- a/docs/manual.adoc
+++ b/docs/manual.adoc
@@ -46,7 +46,7 @@ Thanks to *Vyacheslav Egorov* for documentation proofreading and fuzz testing.
The pugixml library is distributed under the MIT license:
....
-Copyright (c) 2006-2020 Arseny Kapoulkine
+Copyright (c) 2006-2022 Arseny Kapoulkine
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
@@ -74,7 +74,7 @@ This means that you can freely use pugixml in your applications, both open-sourc
....
This software is based on pugixml library (https://pugixml.org).
-pugixml is Copyright (C) 2006-2020 Arseny Kapoulkine.
+pugixml is Copyright (C) 2006-2022 Arseny Kapoulkine.
....
[[install]]
@@ -2138,6 +2138,27 @@ Because of the differences in document object models, performance considerations
:!numbered:
+[[v1.12]]
+=== v1.12 ^2022-02-09^
+
+Maintenance release. Changes:
+
+* Bug fixes:
+ . Fix a bug in xml_document move construction when the source of the move is empty
+ . Fix const-correctness issues with iterator objects to support C++20 ranges
+
+* XPath improvements:
+ . Improved detection of overly complex queries that may result in stack overflow during parsing
+
+* Compatibility improvements:
+ . Fix Cygwin support for DLL builds
+ . Fix Windows CE support
+ . Add NuGet builds and project files for VS2022
+
+* Build system changes
+ . All CMake options now have the prefix `PUGIXML_`. This may require changing dependent build configurations.
+ . Many build settings are now exposed via CMake settings, most notably `PUGIXML_COMPACT` and `PUGIXML_WCHAR_MODE` can be set without changing `pugiconfig.hpp`
+
[[v1.11]]
=== v1.11 ^2020-11-26^
diff --git a/docs/manual.html b/docs/manual.html
index 0cec877..6457a9a 100644
--- a/docs/manual.html
+++ b/docs/manual.html
@@ -4,26 +4,24 @@
-
+
-
load_buffer
-
const char* source = "<!--comment--><node><</node>";
+const char* source = "<!--comment--><node><</node>";
// 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";
+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";
+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";
+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";
+doc.load_string(source, pugi::parse_minimal);
+std::cout << "First node value: [" << doc.first_child().value() << "], node child value: [" << doc.child_value("node") << "]\n";
@@ -1930,16 +2002,16 @@ The internal representation of the document is a tree, where each node has a lis
-
xml_node xml_node::parent() const;
-xml_node xml_node::first_child() const;
-xml_node xml_node::last_child() const;
-xml_node xml_node::next_sibling() const;
-xml_node xml_node::previous_sibling() const;
+xml_node xml_node::parent() const;
+xml_node xml_node::first_child() const;
+xml_node xml_node::last_child() const;
+xml_node xml_node::next_sibling() const;
+xml_node xml_node::previous_sibling() const;
-xml_attribute xml_node::first_attribute() const;
-xml_attribute xml_node::last_attribute() const;
-xml_attribute xml_attribute::next_attribute() const;
-xml_attribute xml_attribute::previous_attribute() const;
+xml_attribute xml_node::first_attribute() const;
+xml_attribute xml_node::last_attribute() const;
+xml_attribute xml_attribute::next_attribute() const;
+xml_attribute xml_attribute::previous_attribute() const;
@@ -1965,17 +2037,17 @@ Because of memory consumption reasons, attributes do not have a link to their pa
-
for (pugi::xml_node tool = tools.first_child(); tool; tool = tool.next_sibling())
-{
- std::cout << "Tool:";
+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();
- }
+ for (pugi::xml_attribute attr = tool.first_attribute(); attr; attr = attr.next_attribute())
+ {
+ std::cout << " " << attr.name() << "=" << attr.value();
+ }
- std::cout << std::endl;
-}
+ std::cout << std::endl;
+}
@@ -1987,8 +2059,8 @@ Apart from structural information (parent, child nodes, attributes), nodes can h
-
const char_t* xml_node::name() const;
-const char_t* xml_node::value() const;
+
const char_t* xml_node::name() const;
+const char_t* xml_node::value() const;
@@ -1999,9 +2071,9 @@ Apart from structural information (parent, child nodes, attributes), nodes can h
-
const char_t* xml_node::child_value() const;
-const char_t* xml_node::child_value(const char_t* name) const;
-xml_text xml_node::text() const;
+
const char_t* xml_node::child_value() const;
+const char_t* xml_node::child_value(const char_t* name) const;
+xml_text xml_node::text() const;
@@ -2022,8 +2094,8 @@ All attributes have name and value, both of which are strings (value may be empt
-
const char_t* xml_attribute::name() const;
-const char_t* xml_attribute::value() const;
+
const char_t* xml_attribute::name() const;
+const char_t* xml_attribute::value() const;
@@ -2034,7 +2106,7 @@ All attributes have name and value, both of which are strings (value may be empt
-
const char_t* xml_attribute::as_string(const char_t* def = "") const;
+
const char_t* xml_attribute::as_string(const char_t* def = "") const;
@@ -2046,13 +2118,13 @@ In many cases attribute values have types that are not strings - i.e. an attribu
-
int xml_attribute::as_int(int def = 0) const;
-unsigned int xml_attribute::as_uint(unsigned int def = 0) const;
-double xml_attribute::as_double(double def = 0) const;
-float xml_attribute::as_float(float def = 0) const;
-bool xml_attribute::as_bool(bool def = false) const;
-long long xml_attribute::as_llong(long long def = 0) const;
-unsigned long long xml_attribute::as_ullong(unsigned long long def = 0) const;
+
int xml_attribute::as_int(int def = 0) const;
+unsigned int xml_attribute::as_uint(unsigned int def = 0) const;
+double xml_attribute::as_double(double def = 0) const;
+float xml_attribute::as_float(float def = 0) const;
+bool xml_attribute::as_bool(bool def = false) const;
+long long xml_attribute::as_llong(long long def = 0) const;
+unsigned long long xml_attribute::as_ullong(unsigned long long def = 0) const;
@@ -2093,13 +2165,13 @@ Number conversion functions depend on current C locale as set with setloca
-
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";
-}
+
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";
+}
@@ -2111,10 +2183,10 @@ Since a lot of document traversal consists of finding the node/attribute with th
-
xml_node xml_node::child(const char_t* name) const;
-xml_attribute xml_node::attribute(const char_t* name) const;
-xml_node xml_node::next_sibling(const char_t* name) const;
-xml_node xml_node::previous_sibling(const char_t* name) const;
+
xml_node xml_node::child(const char_t* name) const;
+xml_attribute xml_node::attribute(const char_t* name) const;
+xml_node xml_node::next_sibling(const char_t* name) const;
+xml_node xml_node::previous_sibling(const char_t* name) const;
@@ -2125,7 +2197,7 @@ Since a lot of document traversal consists of finding the node/attribute with th
-
for (pugi::xml_node tool = tools.child("Tool"); tool; tool = tool.next_sibling("Tool"))
+
for (pugi::xml_node tool = tools.child("Tool"); tool; tool = tool.next_sibling("Tool"))
@@ -2133,8 +2205,8 @@ Since a lot of document traversal consists of finding the node/attribute with th
-
xml_node xml_node::find_child_by_attribute(const char_t* name, const char_t* attr_name, const char_t* attr_value) const;
-xml_node xml_node::find_child_by_attribute(const char_t* attr_name, const char_t* attr_value) const;
+
xml_node xml_node::find_child_by_attribute(const char_t* name, const char_t* attr_name, const char_t* attr_value) const;
+xml_node xml_node::find_child_by_attribute(const char_t* attr_name, const char_t* attr_value) const;
@@ -2148,12 +2220,12 @@ Since a lot of document traversal consists of finding the node/attribute with th
-
std::cout << "Tool for *.dae generation: " << tools.find_child_by_attribute("Tool", "OutputFileMasks", "*.dae").attribute("Filename").value() << "\n";
+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";
-}
+for (pugi::xml_node tool = tools.child("Tool"); tool; tool = tool.next_sibling("Tool"))
+{
+ std::cout << "Tool " << tool.attribute("Filename").value() << "\n";
+}
@@ -2165,9 +2237,9 @@ If your C++ compiler supports range-based for-loop (this is a C++
-
implementation-defined-type xml_node::children() const;
-implementation-defined-type xml_node::children(const char_t* name) const;
-implementation-defined-type xml_node::attributes() const;
+
implementation-defined-type xml_node::children() const;
+implementation-defined-type xml_node::children(const char_t* name) const;
+implementation-defined-type xml_node::attributes() const;
@@ -2178,22 +2250,22 @@ If your C++ compiler supports range-based for-loop (this is a C++
-
for (pugi::xml_node tool: tools.children("Tool"))
-{
- std::cout << "Tool:";
+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_attribute attr: tool.attributes())
+ {
+ std::cout << " " << attr.name() << "=" << attr.value();
+ }
- for (pugi::xml_node child: tool.children())
- {
- std::cout << ", child " << child.name();
- }
+ for (pugi::xml_node child: tool.children())
+ {
+ std::cout << ", child " << child.name();
+ }
- std::cout << std::endl;
-}
+ std::cout << std::endl;
+}
@@ -2201,7 +2273,7 @@ If your C++ compiler supports range-based for-loop (this is a C++
-
for (pugi::xml_node child: tool)
+
for (pugi::xml_node child: tool)
@@ -2213,16 +2285,16 @@ Child node lists and attribute lists are simply double-linked lists; while you c
-
class xml_node_iterator;
-class xml_attribute_iterator;
+class xml_node_iterator;
+class xml_attribute_iterator;
-typedef xml_node_iterator xml_node::iterator;
-iterator xml_node::begin() const;
-iterator xml_node::end() const;
+typedef xml_node_iterator xml_node::iterator;
+iterator xml_node::begin() const;
+iterator xml_node::end() const;
-typedef xml_attribute_iterator xml_node::attribute_iterator;
-attribute_iterator xml_node::attributes_begin() const;
-attribute_iterator xml_node::attributes_end() const;
+typedef xml_attribute_iterator xml_node::attribute_iterator;
+attribute_iterator xml_node::attributes_begin() const;
+attribute_iterator xml_node::attributes_end() const;
@@ -2239,17 +2311,17 @@ Child node lists and attribute lists are simply double-linked lists; while you c
-
for (pugi::xml_node_iterator it = tools.begin(); it != tools.end(); ++it)
-{
- std::cout << "Tool:";
+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();
- }
+ for (pugi::xml_attribute_iterator ait = it->attributes_begin(); ait != it->attributes_end(); ++ait)
+ {
+ std::cout << " " << ait->name() << "=" << ait->value();
+ }
- std::cout << std::endl;
-}
+ std::cout << std::endl;
+}
@@ -2272,17 +2344,17 @@ Node and attribute iterators are somewhere in the middle between const and non-c
-
class xml_tree_walker
-{
-public:
- virtual bool begin(xml_node& node);
- virtual bool for_each(xml_node& node) = 0;
- virtual bool end(xml_node& node);
+class xml_tree_walker
+{
+public:
+ virtual bool begin(xml_node& node);
+ virtual bool for_each(xml_node& node) = 0;
+ virtual bool end(xml_node& node);
- int depth() const;
-};
+ int depth() const;
+};
-bool xml_node::traverse(xml_tree_walker& walker);
+bool xml_node::traverse(xml_tree_walker& walker);
@@ -2313,23 +2385,23 @@ The traversal is launched by calling traverse function on traversal
-
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
+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";
+ std::cout << node_types[node.type()] << ": name='" << node.name() << "', value='" << node.value() << "'\n";
- return true; // continue traversal
- }
-};
+ return true; // continue traversal
+ }
+};
-
simple_walker walker;
-doc.traverse(walker);
+
simple_walker walker;
+doc.traverse(walker);
@@ -2341,9 +2413,9 @@ While there are existing functions for getting a node/attribute with known conte
-
template <typename Predicate> xml_attribute xml_node::find_attribute(Predicate pred) const;
-template <typename Predicate> xml_node xml_node::find_child(Predicate pred) const;
-template <typename Predicate> xml_node xml_node::find_node(Predicate pred) const;
+
template <typename Predicate> xml_attribute xml_node::find_attribute(Predicate pred) const;
+template <typename Predicate> xml_node xml_node::find_child(Predicate pred) const;
+template <typename Predicate> xml_node xml_node::find_node(Predicate pred) const;
@@ -2363,38 +2435,38 @@ While there are existing functions for getting a node/attribute with known conte
-
bool small_timeout(pugi::xml_node node)
-{
- return node.attribute("Timeout").as_int() < 20;
-}
+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;
- }
+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();
- }
-};
+ bool operator()(pugi::xml_node node) const
+ {
+ return node.attribute("AllowRemote").as_bool();
+ }
+};
// Find child via predicate (looks for direct children only)
-std::cout << tools.find_child(allow_remote_predicate()).attribute("Filename").value() << std::endl;
+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;
+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;
+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;
+
std::cout << tools.find_child(small_timeout).attribute("Filename").value() << std::endl;
@@ -2408,7 +2480,7 @@ While there are existing functions for getting a node/attribute with known conte
-
xml_text xml_node::text() const;
+
xml_text xml_node::text() const;
@@ -2420,7 +2492,7 @@ You can check if the text object is bound to a valid PCDATA/CDATA node by using
-
bool xml_text::empty() const;
+
bool xml_text::empty() const;
@@ -2428,7 +2500,7 @@ You can check if the text object is bound to a valid PCDATA/CDATA node by using
-
const char_t* xml_text::get() const;
+
const char_t* xml_text::get() const;
@@ -2440,14 +2512,14 @@ If you need a non-empty string if the text object is empty, or if the text conte
-
const char_t* xml_text::as_string(const char_t* def = "") const;
-int xml_text::as_int(int def = 0) const;
-unsigned int xml_text::as_uint(unsigned int def = 0) const;
-double xml_text::as_double(double def = 0) const;
-float xml_text::as_float(float def = 0) const;
-bool xml_text::as_bool(bool def = false) const;
-long long xml_text::as_llong(long long def = 0) const;
-unsigned long long xml_text::as_ullong(unsigned long long def = 0) const;
+
const char_t* xml_text::as_string(const char_t* def = "") const;
+int xml_text::as_int(int def = 0) const;
+unsigned int xml_text::as_uint(unsigned int def = 0) const;
+double xml_text::as_double(double def = 0) const;
+float xml_text::as_float(float def = 0) const;
+bool xml_text::as_bool(bool def = false) const;
+long long xml_text::as_llong(long long def = 0) const;
+unsigned long long xml_text::as_ullong(unsigned long long def = 0) const;
@@ -2458,7 +2530,7 @@ If you need a non-empty string if the text object is empty, or if the text conte
-
xml_node xml_text::data() const;
+
xml_node xml_text::data() const;
@@ -2469,10 +2541,10 @@ If you need a non-empty string if the text object is empty, or if the text conte
-
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;
+
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;
@@ -2483,7 +2555,7 @@ If you need a non-empty string if the text object is empty, or if the text conte
-
xml_node xml_node::root() const;
+
xml_node xml_node::root() const;
@@ -2495,8 +2567,8 @@ While pugixml supports complex XPath expressions, sometimes a simple path handli
-
string_t xml_node::path(char_t delimiter = '/') const;
-xml_node xml_node::first_element_by_path(const char_t* path, char_t delimiter = '/') const;
+
string_t xml_node::path(char_t delimiter = '/') const;
+xml_node xml_node::first_element_by_path(const char_t* path, char_t delimiter = '/') const;
@@ -2522,7 +2594,7 @@ While pugixml supports complex XPath expressions, sometimes a simple path handli
-
ptrdiff_t xml_node::offset_debug() const;
+
ptrdiff_t xml_node::offset_debug() const;
@@ -2548,8 +2620,8 @@ As discussed before, nodes can have name and value, both of which are strings. D
-
bool xml_node::set_name(const char_t* rhs);
-bool xml_node::set_value(const char_t* rhs);
+
bool xml_node::set_name(const char_t* rhs);
+bool xml_node::set_value(const char_t* rhs);
@@ -2560,18 +2632,18 @@ As discussed before, nodes can have name and value, both of which are strings. D
-
pugi::xml_node node = doc.child("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;
+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;
+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;
+std::cout << node.set_value("1") << ", " << doc.last_child().set_name("2") << std::endl;
@@ -2583,8 +2655,8 @@ All attributes have name and value, both of which are strings (value may be empt
-
bool xml_attribute::set_name(const char_t* rhs);
-bool xml_attribute::set_value(const char_t* rhs);
+
bool xml_attribute::set_name(const char_t* rhs);
+bool xml_attribute::set_value(const char_t* rhs);
@@ -2595,17 +2667,17 @@ All attributes have name and value, both of which are strings (value may be empt
-
bool xml_attribute::set_value(int rhs);
-bool xml_attribute::set_value(unsigned int rhs);
-bool xml_attribute::set_value(long rhs);
-bool xml_attribute::set_value(unsigned long rhs);
-bool xml_attribute::set_value(double rhs);
-bool xml_attribute::set_value(double rhs, int precision);
-bool xml_attribute::set_value(float rhs);
-bool xml_attribute::set_value(float rhs, int precision);
-bool xml_attribute::set_value(bool rhs);
-bool xml_attribute::set_value(long long rhs);
-bool xml_attribute::set_value(unsigned long long rhs);
+
bool xml_attribute::set_value(int rhs);
+bool xml_attribute::set_value(unsigned int rhs);
+bool xml_attribute::set_value(long rhs);
+bool xml_attribute::set_value(unsigned long rhs);
+bool xml_attribute::set_value(double rhs);
+bool xml_attribute::set_value(double rhs, int precision);
+bool xml_attribute::set_value(float rhs);
+bool xml_attribute::set_value(float rhs, int precision);
+bool xml_attribute::set_value(bool rhs);
+bool xml_attribute::set_value(long long rhs);
+bool xml_attribute::set_value(unsigned long long rhs);
@@ -2640,16 +2712,16 @@ Number conversion functions depend on current C locale as set with setloca
-
xml_attribute& xml_attribute::operator=(const char_t* rhs);
-xml_attribute& xml_attribute::operator=(int rhs);
-xml_attribute& xml_attribute::operator=(unsigned int rhs);
-xml_attribute& xml_attribute::operator=(long rhs);
-xml_attribute& xml_attribute::operator=(unsigned long rhs);
-xml_attribute& xml_attribute::operator=(double rhs);
-xml_attribute& xml_attribute::operator=(float rhs);
-xml_attribute& xml_attribute::operator=(bool rhs);
-xml_attribute& xml_attribute::operator=(long long rhs);
-xml_attribute& xml_attribute::operator=(unsigned long long rhs);
+
xml_attribute& xml_attribute::operator=(const char_t* rhs);
+xml_attribute& xml_attribute::operator=(int rhs);
+xml_attribute& xml_attribute::operator=(unsigned int rhs);
+xml_attribute& xml_attribute::operator=(long rhs);
+xml_attribute& xml_attribute::operator=(unsigned long rhs);
+xml_attribute& xml_attribute::operator=(double rhs);
+xml_attribute& xml_attribute::operator=(float rhs);
+xml_attribute& xml_attribute::operator=(bool rhs);
+xml_attribute& xml_attribute::operator=(long long rhs);
+xml_attribute& xml_attribute::operator=(unsigned long long rhs);
@@ -2660,19 +2732,19 @@ Number conversion functions depend on current C locale as set with setloca
-
pugi::xml_attribute attr = node.attribute("id");
+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;
+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;
+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;
+attr = true;
+std::cout << "final attribute value: " << attr.value() << std::endl;
@@ -2684,20 +2756,20 @@ Nodes and attributes do not exist without a document tree, so you can’t cr
-
xml_attribute xml_node::append_attribute(const char_t* name);
-xml_attribute xml_node::prepend_attribute(const char_t* name);
-xml_attribute xml_node::insert_attribute_after(const char_t* name, const xml_attribute& attr);
-xml_attribute xml_node::insert_attribute_before(const char_t* name, const xml_attribute& attr);
+xml_attribute xml_node::append_attribute(const char_t* name);
+xml_attribute xml_node::prepend_attribute(const char_t* name);
+xml_attribute xml_node::insert_attribute_after(const char_t* name, const xml_attribute& attr);
+xml_attribute xml_node::insert_attribute_before(const char_t* name, const xml_attribute& attr);
-xml_node xml_node::append_child(xml_node_type type = node_element);
-xml_node xml_node::prepend_child(xml_node_type type = node_element);
-xml_node xml_node::insert_child_after(xml_node_type type, const xml_node& node);
-xml_node xml_node::insert_child_before(xml_node_type type, const xml_node& node);
+xml_node xml_node::append_child(xml_node_type type = node_element);
+xml_node xml_node::prepend_child(xml_node_type type = node_element);
+xml_node xml_node::insert_child_after(xml_node_type type, const xml_node& node);
+xml_node xml_node::insert_child_before(xml_node_type type, const xml_node& node);
-xml_node xml_node::append_child(const char_t* name);
-xml_node xml_node::prepend_child(const char_t* name);
-xml_node xml_node::insert_child_after(const char_t* name, const xml_node& node);
-xml_node xml_node::insert_child_before(const char_t* name, const xml_node& node);
+xml_node xml_node::append_child(const char_t* name);
+xml_node xml_node::prepend_child(const char_t* name);
+xml_node xml_node::insert_child_after(const char_t* name, const xml_node& node);
+xml_node xml_node::insert_child_before(const char_t* name, const xml_node& node);
@@ -2755,19 +2827,19 @@ Nodes and attributes do not exist without a document tree, so you can’t cr
// add node with some name
-pugi::xml_node node = doc.append_child("node");
+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");
+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);
+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";
+
param.append_attribute("name") = "version";
+
param.append_attribute("value") = 1.1;
+
param.insert_attribute_after("type", param.attribute("name")) = "float";
@@ -2779,10 +2851,10 @@ If you do not want your document to contain some node or attribute, you can remo
-
bool xml_node::remove_attribute(const xml_attribute& a);
-bool xml_node::remove_attributes();
-bool xml_node::remove_child(const xml_node& n);
-bool xml_node::remove_children();
+
bool xml_node::remove_attribute(const xml_attribute& a);
+bool xml_node::remove_attributes();
+bool xml_node::remove_child(const xml_node& n);
+bool xml_node::remove_children();
@@ -2809,8 +2881,8 @@ If you do not want your document to contain some node or attribute, you can remo
-
bool xml_node::remove_attribute(const char_t* name);
-bool xml_node::remove_child(const char_t* name);
+
bool xml_node::remove_attribute(const char_t* name);
+bool xml_node::remove_child(const char_t* name);
@@ -2822,16 +2894,16 @@ If you do not want your document to contain some node or attribute, you can remo
// remove description node with the whole subtree
-pugi::xml_node node = doc.child("node");
-node.remove_child("description");
+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");
+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);
+
pugi::xml_attribute id = param.attribute("name");
+
param.remove_attribute(id);
@@ -2845,7 +2917,7 @@ If you do not want your document to contain some node or attribute, you can remo
-
bool xml_text::set(const char_t* rhs);
+
bool xml_text::set(const char_t* rhs);
@@ -2856,17 +2928,17 @@ If you do not want your document to contain some node or attribute, you can remo
-
bool xml_text::set(int rhs);
-bool xml_text::set(unsigned int rhs);
-bool xml_text::set(long rhs);
-bool xml_text::set(unsigned long rhs);
-bool xml_text::set(double rhs);
-bool xml_text::set(double rhs, int precision);
-bool xml_text::set(float rhs);
-bool xml_text::set(float rhs, int precision);
-bool xml_text::set(bool rhs);
-bool xml_text::set(long long rhs);
-bool xml_text::set(unsigned long long rhs);
+
bool xml_text::set(int rhs);
+bool xml_text::set(unsigned int rhs);
+bool xml_text::set(long rhs);
+bool xml_text::set(unsigned long rhs);
+bool xml_text::set(double rhs);
+bool xml_text::set(double rhs, int precision);
+bool xml_text::set(float rhs);
+bool xml_text::set(float rhs, int precision);
+bool xml_text::set(bool rhs);
+bool xml_text::set(long long rhs);
+bool xml_text::set(unsigned long long rhs);
@@ -2877,16 +2949,16 @@ If you do not want your document to contain some node or attribute, you can remo
-
xml_text& xml_text::operator=(const char_t* rhs);
-xml_text& xml_text::operator=(int rhs);
-xml_text& xml_text::operator=(unsigned int rhs);
-xml_text& xml_text::operator=(long rhs);
-xml_text& xml_text::operator=(unsigned long rhs);
-xml_text& xml_text::operator=(double rhs);
-xml_text& xml_text::operator=(float rhs);
-xml_text& xml_text::operator=(bool rhs);
-xml_text& xml_text::operator=(long long rhs);
-xml_text& xml_text::operator=(unsigned long long rhs);
+
xml_text& xml_text::operator=(const char_t* rhs);
+xml_text& xml_text::operator=(int rhs);
+xml_text& xml_text::operator=(unsigned int rhs);
+xml_text& xml_text::operator=(long rhs);
+xml_text& xml_text::operator=(unsigned long rhs);
+xml_text& xml_text::operator=(double rhs);
+xml_text& xml_text::operator=(float rhs);
+xml_text& xml_text::operator=(bool rhs);
+xml_text& xml_text::operator=(long long rhs);
+xml_text& xml_text::operator=(unsigned long long rhs);
@@ -2898,11 +2970,11 @@ If you do not want your document to contain some node or attribute, you can remo
// change project version
-project.child("version").text() = 1.2;
+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");
+
project.append_child("description").text().set("a test project");
@@ -2914,15 +2986,15 @@ With the help of previously described functions, it is possible to create trees
-
xml_attribute xml_node::append_copy(const xml_attribute& proto);
-xml_attribute xml_node::prepend_copy(const xml_attribute& proto);
-xml_attribute xml_node::insert_copy_after(const xml_attribute& proto, const xml_attribute& attr);
-xml_attribute xml_node::insert_copy_before(const xml_attribute& proto, const xml_attribute& attr);
+xml_attribute xml_node::append_copy(const xml_attribute& proto);
+xml_attribute xml_node::prepend_copy(const xml_attribute& proto);
+xml_attribute xml_node::insert_copy_after(const xml_attribute& proto, const xml_attribute& attr);
+xml_attribute xml_node::insert_copy_before(const xml_attribute& proto, const xml_attribute& attr);
-xml_node xml_node::append_copy(const xml_node& proto);
-xml_node xml_node::prepend_copy(const xml_node& proto);
-xml_node xml_node::insert_copy_after(const xml_node& proto, const xml_node& node);
-xml_node xml_node::insert_copy_before(const xml_node& proto, const xml_node& node);
+xml_node xml_node::append_copy(const xml_node& proto);
+xml_node xml_node::prepend_copy(const xml_node& proto);
+xml_node xml_node::insert_copy_after(const xml_node& proto, const xml_node& node);
+xml_node xml_node::insert_copy_before(const xml_node& proto, const xml_node& node);
@@ -2952,53 +3024,53 @@ With the help of previously described functions, it is possible to create trees
-
bool load_preprocess(pugi::xml_document& doc, const char* path);
+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;
+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();
+ // 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;
+ 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);
+ // 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);
- }
+ // 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();
+ // remove the include node and move to the next child
+ child = child.next_sibling();
- node.remove_child(include);
- }
- else
- {
- if (!preprocess(child)) return false;
+ node.remove_child(include);
+ }
+ else
+ {
+ if (!preprocess(child)) return false;
- child = child.next_sibling();
- }
- }
+ child = child.next_sibling();
+ }
+ }
- return true;
-}
+ 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?>
+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;
-}
+ return result ? preprocess(doc) : false;
+}
@@ -3010,10 +3082,10 @@ Sometimes instead of cloning a node you need to move an existing node to a diffe
-
xml_node xml_node::append_move(const xml_node& moved);
-xml_node xml_node::prepend_move(const xml_node& moved);
-xml_node xml_node::insert_move_after(const xml_node& moved, const xml_node& node);
-xml_node xml_node::insert_move_before(const xml_node& moved, const xml_node& node);
+
xml_node xml_node::append_move(const xml_node& moved);
+xml_node xml_node::prepend_move(const xml_node& moved);
+xml_node xml_node::insert_move_after(const xml_node& moved, const xml_node& node);
+xml_node xml_node::insert_move_before(const xml_node& moved, const xml_node& node);
@@ -3050,14 +3122,14 @@ Sometimes instead of cloning a node you need to move an existing node to a diffe
Use a temporary document to parse the data from a string, then clone the nodes to a destination node. For example:
-
bool append_fragment(pugi::xml_node target, const char* buffer, size_t size)
-{
- pugi::xml_document doc;
- if (!doc.load_buffer(buffer, size)) return false;
+bool append_fragment(pugi::xml_node target, const char* buffer, size_t size)
+{
+ pugi::xml_document doc;
+ if (!doc.load_buffer(buffer, size)) return false;
- for (pugi::xml_node child = doc.first_child(); child; child = child.next_sibling())
- target.append_copy(child);
-}
+ for (pugi::xml_node child = doc.first_child(); child; child = child.next_sibling())
+ target.append_copy(child);
+}
@@ -3065,11 +3137,11 @@ Sometimes instead of cloning a node you need to move an existing node to a diffe
Cache the parsing step - instead of keeping in-memory buffers, keep document objects that already contain the parsed fragment:
-
bool append_fragment(pugi::xml_node target, const pugi::xml_document& cached_fragment)
-{
- for (pugi::xml_node child = cached_fragment.first_child(); child; child = child.next_sibling())
- target.append_copy(child);
-}
+
bool append_fragment(pugi::xml_node target, const pugi::xml_document& cached_fragment)
+{
+ for (pugi::xml_node child = cached_fragment.first_child(); child; child = child.next_sibling())
+ target.append_copy(child);
+}
@@ -3077,7 +3149,7 @@ Sometimes instead of cloning a node you need to move an existing node to a diffe
Use xml_node::append_buffer directly:
-
xml_parse_result xml_node::append_buffer(const void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
+
xml_parse_result xml_node::append_buffer(const void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
@@ -3115,8 +3187,8 @@ If you want to save the whole document to a file, you can use one of the followi
-
bool xml_document::save_file(const char* path, const char_t* indent = "\t", unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const;
-bool xml_document::save_file(const wchar_t* path, const char_t* indent = "\t", unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const;
+
bool xml_document::save_file(const char* path, const char_t* indent = "\t", unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const;
+bool xml_document::save_file(const wchar_t* path, const char_t* indent = "\t", unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const;
@@ -3134,7 +3206,7 @@ If you want to save the whole document to a file, you can use one of the followi
// save document to file
-std::cout << "Saving result: " << doc.save_file("save_file_output.xml") << std::endl;
+
std::cout << "Saving result: " << doc.save_file("save_file_output.xml") << std::endl;
@@ -3145,8 +3217,8 @@ If you want to save the whole document to a file, you can use one of the followi
-
void xml_document::save(std::ostream& stream, const char_t* indent = "\t", unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const;
-void xml_document::save(std::wostream& stream, const char_t* indent = "\t", unsigned int flags = format_default) const;
+
void xml_document::save(std::ostream& stream, const char_t* indent = "\t", unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const;
+void xml_document::save(std::wostream& stream, const char_t* indent = "\t", unsigned int flags = format_default) const;
@@ -3161,8 +3233,8 @@ If you want to save the whole document to a file, you can use one of the followi
// save document to standard output
-std::cout << "Document:\n";
-doc.save(std::cout);
+
std::cout << "Document:\n";
+
doc.save(std::cout);
@@ -3174,13 +3246,13 @@ All of the above saving functions are implemented in terms of writer interface.
-
class xml_writer
-{
-public:
- virtual void write(const void* data, size_t size) = 0;
-};
+class xml_writer
+{
+public:
+ virtual void write(const void* data, size_t size) = 0;
+};
-void xml_document::save(xml_writer& writer, const char_t* indent = "\t", unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const;
+void xml_document::save(xml_writer& writer, const char_t* indent = "\t", unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const;
@@ -3194,15 +3266,15 @@ All of the above saving functions are implemented in terms of writer interface.
-
struct xml_string_writer: pugi::xml_writer
-{
- std::string result;
+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);
- }
-};
+ virtual void write(const void* data, size_t size)
+ {
+ result.append(static_cast<const char*>(data), size);
+ }
+};
@@ -3214,9 +3286,9 @@ While the previously described functions save the whole document to the destinat
-
void xml_node::print(std::ostream& os, const char_t* indent = "\t", unsigned int flags = format_default, xml_encoding encoding = encoding_auto, unsigned int depth = 0) const;
-void xml_node::print(std::wostream& os, const char_t* indent = "\t", unsigned int flags = format_default, unsigned int depth = 0) const;
-void xml_node::print(xml_writer& writer, const char_t* indent = "\t", unsigned int flags = format_default, xml_encoding encoding = encoding_auto, unsigned int depth = 0) const;
+
void xml_node::print(std::ostream& os, const char_t* indent = "\t", unsigned int flags = format_default, xml_encoding encoding = encoding_auto, unsigned int depth = 0) const;
+void xml_node::print(std::wostream& os, const char_t* indent = "\t", unsigned int flags = format_default, unsigned int depth = 0) const;
+void xml_node::print(xml_writer& writer, const char_t* indent = "\t", unsigned int flags = format_default, xml_encoding encoding = encoding_auto, unsigned int depth = 0) const;
@@ -3228,20 +3300,20 @@ While the previously described functions save the whole document to the destinat
// get a test document
-pugi::xml_document doc;
-doc.load_string("<foo bar='baz'><call>hey</call></foo>");
+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;
+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;
+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;
+
doc.child("foo").child("call").print(std::cout, "", pugi::format_raw);
+
std::cout << std::endl;
@@ -3323,42 +3395,42 @@ contain platform-independent newline \n (ASCII 10). If this flag is
// get a test document
-pugi::xml_document doc;
-doc.load_string("<foo bar='baz'><call>hey</call></foo>");
+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;
+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;
+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;
+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;
+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;
+
doc.save(std::cout, "\t", pugi::format_raw | pugi::format_no_declaration);
+
std::cout << std::endl;
@@ -3412,21 +3484,21 @@ By default the declaration node is not added to the document during parsing. If
// get a test document
-pugi::xml_document doc;
-doc.load_string("<foo bar='baz'><call>hey</call></foo>");
+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";
+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;
+
doc.save(std::cout);
+
std::cout << std::endl;
@@ -3450,8 +3522,8 @@ Because an XPath node can be either a node or an attribute, there is a special t
-
xml_node xpath_node::node() const;
-xml_attribute xpath_node::attribute() const;
+
xml_node xpath_node::node() const;
+xml_attribute xpath_node::attribute() const;
@@ -3462,7 +3534,7 @@ Because an XPath node can be either a node or an attribute, there is a special t
-
xml_node xpath_node::parent() const;
+
xml_node xpath_node::parent() const;
@@ -3484,9 +3556,9 @@ Node sets are represented by xpath_node_set object, which has an in
-
typedef const xpath_node* xpath_node_set::const_iterator;
-const_iterator xpath_node_set::begin() const;
-const_iterator xpath_node_set::end() const;
+
typedef const xpath_node* xpath_node_set::const_iterator;
+const_iterator xpath_node_set::begin() const;
+const_iterator xpath_node_set::end() const;
@@ -3495,9 +3567,9 @@ And it also can be iterated via indices, just like std::vector:
-
const xpath_node& xpath_node_set::operator[](size_t index) const;
-size_t xpath_node_set::size() const;
-bool xpath_node_set::empty() const;
+
const xpath_node& xpath_node_set::operator[](size_t index) const;
+size_t xpath_node_set::size() const;
+bool xpath_node_set::empty() const;
@@ -3509,8 +3581,8 @@ The order of iteration depends on the order of nodes inside the set; the order c
-
enum xpath_node_set::type_t {type_unsorted, type_sorted, type_sorted_reverse};
-type_t xpath_node_set::type() const;
+
enum xpath_node_set::type_t {type_unsorted, type_sorted, type_sorted_reverse};
+type_t xpath_node_set::type() const;
@@ -3518,7 +3590,7 @@ The order of iteration depends on the order of nodes inside the set; the order c
-
void xpath_node_set::sort(bool reverse = false);
+
void xpath_node_set::sort(bool reverse = false);
@@ -3529,7 +3601,7 @@ The order of iteration depends on the order of nodes inside the set; the order c
-
xpath_node xpath_node_set::first() const;
+
xpath_node xpath_node_set::first() const;
@@ -3540,7 +3612,7 @@ The order of iteration depends on the order of nodes inside the set; the order c
-
xpath_node_set::xpath_node_set(const_iterator begin, const_iterator end, type_t type = type_unsorted);
+
xpath_node_set::xpath_node_set(const_iterator begin, const_iterator end, type_t type = type_unsorted);
@@ -3555,8 +3627,8 @@ If you want to select nodes that match some XPath expression, you can do it with
-
xpath_node xml_node::select_node(const char_t* query, xpath_variable_set* variables = 0) const;
-xpath_node_set xml_node::select_nodes(const char_t* query, xpath_variable_set* variables = 0) const;
+
xpath_node xml_node::select_node(const char_t* query, xpath_variable_set* variables = 0) const;
+xpath_node_set xml_node::select_nodes(const char_t* query, xpath_variable_set* variables = 0) const;
@@ -3571,8 +3643,8 @@ While compiling expressions is fast, the compilation time can introduce a signif
-
xpath_node xml_node::select_node(const xpath_query& query) const;
-xpath_node_set xml_node::select_nodes(const xpath_query& query) const;
+
xpath_node xml_node::select_node(const xpath_query& query) const;
+xpath_node_set xml_node::select_nodes(const xpath_query& query) const;
@@ -3583,20 +3655,20 @@ While compiling expressions is fast, the compilation time can introduce a signif
-
pugi::xpath_node_set tools = doc.select_nodes("/Profile/Tools/Tool[@AllowRemote='true' and @DeriveCaptionFrom='lastparam']");
+pugi::xpath_node_set tools = doc.select_nodes("/Profile/Tools/Tool[@AllowRemote='true' and @DeriveCaptionFrom='lastparam']");
-std::cout << "Tools:\n";
+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";
-}
+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')]");
+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";
+if (build_tool)
+ std::cout << "Build tool: " << build_tool.node().attribute("Filename").value() << "\n";
@@ -3626,7 +3698,7 @@ While compiling expressions is fast, the compilation time can introduce a signif
-
explicit xpath_query::xpath_query(const char_t* query, xpath_variable_set* variables = 0);
+
explicit xpath_query::xpath_query(const char_t* query, xpath_variable_set* variables = 0);
@@ -3634,7 +3706,7 @@ While compiling expressions is fast, the compilation time can introduce a signif
-
xpath_value_type xpath_query::return_type() const;
+
xpath_value_type xpath_query::return_type() const;
@@ -3643,11 +3715,11 @@ You can evaluate the query using one of the following functions:
-
bool xpath_query::evaluate_boolean(const xpath_node& n) const;
-double xpath_query::evaluate_number(const xpath_node& n) const;
-string_t xpath_query::evaluate_string(const xpath_node& n) const;
-xpath_node_set xpath_query::evaluate_node_set(const xpath_node& n) const;
-xpath_node xpath_query::evaluate_node(const xpath_node& n) const;
+
bool xpath_query::evaluate_boolean(const xpath_node& n) const;
+double xpath_query::evaluate_number(const xpath_node& n) const;
+string_t xpath_query::evaluate_string(const xpath_node& n) const;
+xpath_node_set xpath_query::evaluate_node_set(const xpath_node& n) const;
+xpath_node xpath_query::evaluate_node(const xpath_node& n) const;
@@ -3670,7 +3742,7 @@ Calling node.select_nodes("query") is equivalent to calling x
-
size_t xpath_query::evaluate_string(char_t* buffer, size_t capacity, const xpath_node& n) const;
+
size_t xpath_query::evaluate_string(char_t* buffer, size_t capacity, const xpath_node& n) const;
@@ -3692,26 +3764,26 @@ Calling
node.select_nodes("query") is equivalent to calling
x
// Select nodes via compiled query
-pugi::xpath_query query_remote_tools("/Profile/Tools/Tool[@AllowRemote='true']");
+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);
+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;
+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)");
+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);
+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;
-}
+
if (query_name_valid.evaluate_boolean(tool)) std::cout << s << std::endl;
+
}
@@ -3725,9 +3797,9 @@ Calling node.select_nodes("query") is equivalent to calling x
-
explicit xpath_query::xpath_query(const char_t* query, xpath_variable_set* variables = 0);
-xpath_node xml_node::select_node(const char_t* query, xpath_variable_set* variables = 0) const;
-xpath_node_set xml_node::select_nodes(const char_t* query, xpath_variable_set* variables = 0) const;
+
explicit xpath_query::xpath_query(const char_t* query, xpath_variable_set* variables = 0);
+xpath_node xml_node::select_node(const char_t* query, xpath_variable_set* variables = 0) const;
+xpath_node_set xml_node::select_nodes(const char_t* query, xpath_variable_set* variables = 0) const;
@@ -3753,7 +3825,7 @@ The variable set pointer is stored in the query object; you have to ensure that
-
xpath_variable* xpath_variable_set::add(const char_t* name, xpath_value_type type);
+
xpath_variable* xpath_variable_set::add(const char_t* name, xpath_value_type type);
@@ -3767,8 +3839,8 @@ The variable set pointer is stored in the query object; you have to ensure that
-
xpath_variable* xpath_variable_set::get(const char_t* name);
-const xpath_variable* xpath_variable_set::get(const char_t* name) const;
+
xpath_variable* xpath_variable_set::get(const char_t* name);
+const xpath_variable* xpath_variable_set::get(const char_t* name) const;
@@ -3779,10 +3851,10 @@ The variable set pointer is stored in the query object; you have to ensure that
-
bool xpath_variable_set::set(const char_t* name, bool value);
-bool xpath_variable_set::set(const char_t* name, double value);
-bool xpath_variable_set::set(const char_t* name, const char_t* value);
-bool xpath_variable_set::set(const char_t* name, const xpath_node_set& value);
+
bool xpath_variable_set::set(const char_t* name, bool value);
+bool xpath_variable_set::set(const char_t* name, double value);
+bool xpath_variable_set::set(const char_t* name, const char_t* value);
+bool xpath_variable_set::set(const char_t* name, const xpath_node_set& value);
@@ -3797,8 +3869,8 @@ In order to get variable information, you can use one of the following functions
-
const char_t* xpath_variable::name() const;
-xpath_value_type xpath_variable::type() const;
+
const char_t* xpath_variable::name() const;
+xpath_value_type xpath_variable::type() const;
@@ -3810,10 +3882,10 @@ In order to get variable value, you should use one of the following functions, d
-
bool xpath_variable::get_boolean() const;
-double xpath_variable::get_number() const;
-const char_t* xpath_variable::get_string() const;
-const xpath_node_set& xpath_variable::get_node_set() const;
+
bool xpath_variable::get_boolean() const;
+double xpath_variable::get_number() const;
+const char_t* xpath_variable::get_string() const;
+const xpath_node_set& xpath_variable::get_node_set() const;
@@ -3824,10 +3896,10 @@ In order to get variable value, you should use one of the following functions, d
-
bool xpath_variable::set(bool value);
-bool xpath_variable::set(double value);
-bool xpath_variable::set(const char_t* value);
-bool xpath_variable::set(const xpath_node_set& value);
+
bool xpath_variable::set(bool value);
+bool xpath_variable::set(double value);
+bool xpath_variable::set(const char_t* value);
+bool xpath_variable::set(const xpath_node_set& value);
@@ -3839,28 +3911,28 @@ In order to get variable value, you should use one of the following functions, d
// Select nodes via compiled query
-pugi::xpath_variable_set vars;
-vars.add("remote", pugi::xpath_type_boolean);
+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);
+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", 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);
+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 << "Remote tool: ";
+tools_remote[2].node().print(std::cout);
-std::cout << "Local tool: ";
-tools_local[0].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);
+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);
+
std::cout << "Local tool imm: ";
+
tools_local_imm[0].node().print(std::cout);
@@ -3875,8 +3947,8 @@ By default, XPath functions throw xpath_exception object in case of
-
virtual const char* xpath_exception::what() const throw();
-const xpath_parse_result& xpath_exception::result() const;
+
virtual const char* xpath_exception::what() const throw();
+const xpath_parse_result& xpath_exception::result() const;
@@ -3885,7 +3957,7 @@ If exceptions are disabled, then in the event of parsing failure the query is in
-
const xpath_parse_result& xpath_query::result() const;
+
const xpath_parse_result& xpath_query::result() const;
@@ -3896,14 +3968,14 @@ If exceptions are disabled, then in the event of parsing failure the query is in
-
struct xpath_parse_result
-{
- const char* error;
- ptrdiff_t offset;
+struct xpath_parse_result
+{
+ const char* error;
+ ptrdiff_t offset;
- operator bool() const;
- const char* description() const;
-};
+ operator bool() const;
+ const char* description() const;
+};
@@ -3924,34 +3996,34 @@ If exceptions are disabled, then in the event of parsing failure the query is in
// 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;
-}
+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;
-}
+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;
-}
+
try
+
{
+
doc.select_nodes("123");
+
}
+
catch (const pugi::xpath_exception& e)
+
{
+
std::cout << "Select failed: " << e.what() << std::endl;
+
}
@@ -3986,6 +4058,68 @@ If exceptions are disabled, then in the event of parsing failure the query is in
+
+
+
Maintenance release. Changes:
+
+
+
+
Maintenance release. Changes:
@@ -5393,10 +5527,10 @@ If exceptions are disabled, then in the event of parsing failure the query is in
@@ -5404,54 +5538,54 @@ If exceptions are disabled, then in the event of parsing failure the query is in
@@ -5460,36 +5594,36 @@ If exceptions are disabled, then in the event of parsing failure the query is in
@@ -5497,352 +5631,352 @@ If exceptions are disabled, then in the event of parsing failure the query is in
-
class xml_attribute
- xml_attribute();
-
- bool empty() const;
- operator unspecified_bool_type() const;
-
- bool operator==(const xml_attribute& r) const;
- bool operator!=(const xml_attribute& r) const;
- bool operator<(const xml_attribute& r) const;
- bool operator>(const xml_attribute& r) const;
- bool operator<=(const xml_attribute& r) const;
- bool operator>=(const xml_attribute& r) const;
-
- size_t hash_value() const;
-
- xml_attribute next_attribute() const;
- xml_attribute previous_attribute() const;
-
- const char_t* name() const;
- const char_t* value() const;
-
- const char_t* as_string(const char_t* def = "") const;
- int as_int(int def = 0) const;
- unsigned int as_uint(unsigned int def = 0) const;
- double as_double(double def = 0) const;
- float as_float(float def = 0) const;
- bool as_bool(bool def = false) const;
- long long as_llong(long long def = 0) const;
- unsigned long long as_ullong(unsigned long long def = 0) const;
-
- bool set_name(const char_t* rhs);
- bool set_value(const char_t* rhs);
- bool set_value(int rhs);
- bool set_value(unsigned int rhs);
- bool set_value(long rhs);
- bool set_value(unsigned long rhs);
- bool set_value(double rhs);
- bool set_value(float rhs);
- bool set_value(bool rhs);
- bool set_value(long long rhs);
- bool set_value(unsigned long long rhs);
-
- xml_attribute& operator=(const char_t* rhs);
- xml_attribute& operator=(int rhs);
- xml_attribute& operator=(unsigned int rhs);
- xml_attribute& operator=(long rhs);
- xml_attribute& operator=(unsigned long rhs);
- xml_attribute& operator=(double rhs);
- xml_attribute& operator=(float rhs);
- xml_attribute& operator=(bool rhs);
- xml_attribute& operator=(long long rhs);
- xml_attribute& operator=(unsnigned long long rhs);
-
-class xml_node
- xml_node();
-
- bool empty() const;
- operator unspecified_bool_type() const;
-
- bool operator==(const xml_node& r) const;
- bool operator!=(const xml_node& r) const;
- bool operator<(const xml_node& r) const;
- bool operator>(const xml_node& r) const;
- bool operator<=(const xml_node& r) const;
- bool operator>=(const xml_node& r) const;
-
- size_t hash_value() const;
-
- xml_node_type type() const;
-
- const char_t* name() const;
- const char_t* value() const;
-
- xml_node parent() const;
- xml_node first_child() const;
- xml_node last_child() const;
- xml_node next_sibling() const;
- xml_node previous_sibling() const;
-
- xml_attribute first_attribute() const;
- xml_attribute last_attribute() const;
-
- implementation-defined-type children() const;
- implementation-defined-type children(const char_t* name) const;
- implementation-defined-type attributes() const;
-
- xml_node child(const char_t* name) const;
- xml_attribute attribute(const char_t* name) const;
- xml_node next_sibling(const char_t* name) const;
- xml_node previous_sibling(const char_t* name) const;
- xml_node find_child_by_attribute(const char_t* name, const char_t* attr_name, const char_t* attr_value) const;
- xml_node find_child_by_attribute(const char_t* attr_name, const char_t* attr_value) const;
-
- const char_t* child_value() const;
- const char_t* child_value(const char_t* name) const;
- xml_text text() const;
-
- typedef xml_node_iterator iterator;
- iterator begin() const;
- iterator end() const;
-
- typedef xml_attribute_iterator attribute_iterator;
- attribute_iterator attributes_begin() const;
- attribute_iterator attributes_end() const;
-
- bool traverse(xml_tree_walker& walker);
-
- template <typename Predicate> xml_attribute find_attribute(Predicate pred) const;
- template <typename Predicate> xml_node find_child(Predicate pred) const;
- template <typename Predicate> xml_node find_node(Predicate pred) const;
-
- string_t path(char_t delimiter = '/') const;
- xml_node xml_node::first_element_by_path(const char_t* path, char_t delimiter = '/') const;
- xml_node root() const;
- ptrdiff_t offset_debug() const;
-
- bool set_name(const char_t* rhs);
- bool set_value(const char_t* rhs);
-
- xml_attribute append_attribute(const char_t* name);
- xml_attribute prepend_attribute(const char_t* name);
- xml_attribute insert_attribute_after(const char_t* name, const xml_attribute& attr);
- xml_attribute insert_attribute_before(const char_t* name, const xml_attribute& attr);
-
- xml_node append_child(xml_node_type type = node_element);
- xml_node prepend_child(xml_node_type type = node_element);
- xml_node insert_child_after(xml_node_type type, const xml_node& node);
- xml_node insert_child_before(xml_node_type type, const xml_node& node);
-
- xml_node append_child(const char_t* name);
- xml_node prepend_child(const char_t* name);
- xml_node insert_child_after(const char_t* name, const xml_node& node);
- xml_node insert_child_before(const char_t* name, const xml_node& node);
-
- xml_attribute append_copy(const xml_attribute& proto);
- xml_attribute prepend_copy(const xml_attribute& proto);
- xml_attribute insert_copy_after(const xml_attribute& proto, const xml_attribute& attr);
- xml_attribute insert_copy_before(const xml_attribute& proto, const xml_attribute& attr);
-
- xml_node append_copy(const xml_node& proto);
- xml_node prepend_copy(const xml_node& proto);
- xml_node insert_copy_after(const xml_node& proto, const xml_node& node);
- xml_node insert_copy_before(const xml_node& proto, const xml_node& node);
-
- xml_node append_move(const xml_node& moved);
- xml_node prepend_move(const xml_node& moved);
- xml_node insert_move_after(const xml_node& moved, const xml_node& node);
- xml_node insert_move_before(const xml_node& moved, const xml_node& node);
-
- bool remove_attribute(const xml_attribute& a);
- bool remove_attribute(const char_t* name);
- bool remove_attributes();
- bool remove_child(const xml_node& n);
- bool remove_child(const char_t* name);
- bool remove_children();
-
- xml_parse_result append_buffer(const void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
-
- void print(xml_writer& writer, const char_t* indent = "\t", unsigned int flags = format_default, xml_encoding encoding = encoding_auto, unsigned int depth = 0) const;
- void print(std::ostream& os, const char_t* indent = "\t", unsigned int flags = format_default, xml_encoding encoding = encoding_auto, unsigned int depth = 0) const;
- void print(std::wostream& os, const char_t* indent = "\t", unsigned int flags = format_default, unsigned int depth = 0) const;
-
- xpath_node select_node(const char_t* query, xpath_variable_set* variables = 0) const;
- xpath_node select_node(const xpath_query& query) const;
- xpath_node_set select_nodes(const char_t* query, xpath_variable_set* variables = 0) const;
- xpath_node_set select_nodes(const xpath_query& query) const;
-
-class xml_document
- xml_document();
- ~xml_document();
-
- void reset();
- void reset(const xml_document& proto);
-
- xml_parse_result load(std::istream& stream, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
- xml_parse_result load(std::wistream& stream, unsigned int options = parse_default);
-
- xml_parse_result load_string(const char_t* contents, unsigned int options = parse_default);
-
- xml_parse_result load_file(const char* path, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
- xml_parse_result load_file(const wchar_t* path, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
-
- xml_parse_result load_buffer(const void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
- xml_parse_result load_buffer_inplace(void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
- xml_parse_result load_buffer_inplace_own(void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
+class xml_attribute
+ xml_attribute();
+
+ bool empty() const;
+ operator unspecified_bool_type() const;
+
+ bool operator==(const xml_attribute& r) const;
+ bool operator!=(const xml_attribute& r) const;
+ bool operator<(const xml_attribute& r) const;
+ bool operator>(const xml_attribute& r) const;
+ bool operator<=(const xml_attribute& r) const;
+ bool operator>=(const xml_attribute& r) const;
+
+ size_t hash_value() const;
+
+ xml_attribute next_attribute() const;
+ xml_attribute previous_attribute() const;
+
+ const char_t* name() const;
+ const char_t* value() const;
+
+ const char_t* as_string(const char_t* def = "") const;
+ int as_int(int def = 0) const;
+ unsigned int as_uint(unsigned int def = 0) const;
+ double as_double(double def = 0) const;
+ float as_float(float def = 0) const;
+ bool as_bool(bool def = false) const;
+ long long as_llong(long long def = 0) const;
+ unsigned long long as_ullong(unsigned long long def = 0) const;
+
+ bool set_name(const char_t* rhs);
+ bool set_value(const char_t* rhs);
+ bool set_value(int rhs);
+ bool set_value(unsigned int rhs);
+ bool set_value(long rhs);
+ bool set_value(unsigned long rhs);
+ bool set_value(double rhs);
+ bool set_value(float rhs);
+ bool set_value(bool rhs);
+ bool set_value(long long rhs);
+ bool set_value(unsigned long long rhs);
+
+ xml_attribute& operator=(const char_t* rhs);
+ xml_attribute& operator=(int rhs);
+ xml_attribute& operator=(unsigned int rhs);
+ xml_attribute& operator=(long rhs);
+ xml_attribute& operator=(unsigned long rhs);
+ xml_attribute& operator=(double rhs);
+ xml_attribute& operator=(float rhs);
+ xml_attribute& operator=(bool rhs);
+ xml_attribute& operator=(long long rhs);
+ xml_attribute& operator=(unsnigned long long rhs);
+
+class xml_node
+ xml_node();
+
+ bool empty() const;
+ operator unspecified_bool_type() const;
+
+ bool operator==(const xml_node& r) const;
+ bool operator!=(const xml_node& r) const;
+ bool operator<(const xml_node& r) const;
+ bool operator>(const xml_node& r) const;
+ bool operator<=(const xml_node& r) const;
+ bool operator>=(const xml_node& r) const;
+
+ size_t hash_value() const;
+
+ xml_node_type type() const;
+
+ const char_t* name() const;
+ const char_t* value() const;
+
+ xml_node parent() const;
+ xml_node first_child() const;
+ xml_node last_child() const;
+ xml_node next_sibling() const;
+ xml_node previous_sibling() const;
+
+ xml_attribute first_attribute() const;
+ xml_attribute last_attribute() const;
+
+ implementation-defined-type children() const;
+ implementation-defined-type children(const char_t* name) const;
+ implementation-defined-type attributes() const;
+
+ xml_node child(const char_t* name) const;
+ xml_attribute attribute(const char_t* name) const;
+ xml_node next_sibling(const char_t* name) const;
+ xml_node previous_sibling(const char_t* name) const;
+ xml_node find_child_by_attribute(const char_t* name, const char_t* attr_name, const char_t* attr_value) const;
+ xml_node find_child_by_attribute(const char_t* attr_name, const char_t* attr_value) const;
+
+ const char_t* child_value() const;
+ const char_t* child_value(const char_t* name) const;
+ xml_text text() const;
+
+ typedef xml_node_iterator iterator;
+ iterator begin() const;
+ iterator end() const;
+
+ typedef xml_attribute_iterator attribute_iterator;
+ attribute_iterator attributes_begin() const;
+ attribute_iterator attributes_end() const;
+
+ bool traverse(xml_tree_walker& walker);
+
+ template <typename Predicate> xml_attribute find_attribute(Predicate pred) const;
+ template <typename Predicate> xml_node find_child(Predicate pred) const;
+ template <typename Predicate> xml_node find_node(Predicate pred) const;
+
+ string_t path(char_t delimiter = '/') const;
+ xml_node xml_node::first_element_by_path(const char_t* path, char_t delimiter = '/') const;
+ xml_node root() const;
+ ptrdiff_t offset_debug() const;
+
+ bool set_name(const char_t* rhs);
+ bool set_value(const char_t* rhs);
+
+ xml_attribute append_attribute(const char_t* name);
+ xml_attribute prepend_attribute(const char_t* name);
+ xml_attribute insert_attribute_after(const char_t* name, const xml_attribute& attr);
+ xml_attribute insert_attribute_before(const char_t* name, const xml_attribute& attr);
+
+ xml_node append_child(xml_node_type type = node_element);
+ xml_node prepend_child(xml_node_type type = node_element);
+ xml_node insert_child_after(xml_node_type type, const xml_node& node);
+ xml_node insert_child_before(xml_node_type type, const xml_node& node);
+
+ xml_node append_child(const char_t* name);
+ xml_node prepend_child(const char_t* name);
+ xml_node insert_child_after(const char_t* name, const xml_node& node);
+ xml_node insert_child_before(const char_t* name, const xml_node& node);
+
+ xml_attribute append_copy(const xml_attribute& proto);
+ xml_attribute prepend_copy(const xml_attribute& proto);
+ xml_attribute insert_copy_after(const xml_attribute& proto, const xml_attribute& attr);
+ xml_attribute insert_copy_before(const xml_attribute& proto, const xml_attribute& attr);
+
+ xml_node append_copy(const xml_node& proto);
+ xml_node prepend_copy(const xml_node& proto);
+ xml_node insert_copy_after(const xml_node& proto, const xml_node& node);
+ xml_node insert_copy_before(const xml_node& proto, const xml_node& node);
+
+ xml_node append_move(const xml_node& moved);
+ xml_node prepend_move(const xml_node& moved);
+ xml_node insert_move_after(const xml_node& moved, const xml_node& node);
+ xml_node insert_move_before(const xml_node& moved, const xml_node& node);
+
+ bool remove_attribute(const xml_attribute& a);
+ bool remove_attribute(const char_t* name);
+ bool remove_attributes();
+ bool remove_child(const xml_node& n);
+ bool remove_child(const char_t* name);
+ bool remove_children();
+
+ xml_parse_result append_buffer(const void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
+
+ void print(xml_writer& writer, const char_t* indent = "\t", unsigned int flags = format_default, xml_encoding encoding = encoding_auto, unsigned int depth = 0) const;
+ void print(std::ostream& os, const char_t* indent = "\t", unsigned int flags = format_default, xml_encoding encoding = encoding_auto, unsigned int depth = 0) const;
+ void print(std::wostream& os, const char_t* indent = "\t", unsigned int flags = format_default, unsigned int depth = 0) const;
+
+ xpath_node select_node(const char_t* query, xpath_variable_set* variables = 0) const;
+ xpath_node select_node(const xpath_query& query) const;
+ xpath_node_set select_nodes(const char_t* query, xpath_variable_set* variables = 0) const;
+ xpath_node_set select_nodes(const xpath_query& query) const;
+
+class xml_document
+ xml_document();
+ ~xml_document();
+
+ void reset();
+ void reset(const xml_document& proto);
+
+ xml_parse_result load(std::istream& stream, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
+ xml_parse_result load(std::wistream& stream, unsigned int options = parse_default);
+
+ xml_parse_result load_string(const char_t* contents, unsigned int options = parse_default);
+
+ xml_parse_result load_file(const char* path, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
+ xml_parse_result load_file(const wchar_t* path, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
+
+ xml_parse_result load_buffer(const void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
+ xml_parse_result load_buffer_inplace(void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
+ xml_parse_result load_buffer_inplace_own(void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
- bool save_file(const char* path, const char_t* indent = "\t", unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const;
- bool save_file(const wchar_t* path, const char_t* indent = "\t", unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const;
+ bool save_file(const char* path, const char_t* indent = "\t", unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const;
+ bool save_file(const wchar_t* path, const char_t* indent = "\t", unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const;
- void save(std::ostream& stream, const char_t* indent = "\t", unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const;
- void save(std::wostream& stream, const char_t* indent = "\t", unsigned int flags = format_default) const;
+ void save(std::ostream& stream, const char_t* indent = "\t", unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const;
+ void save(std::wostream& stream, const char_t* indent = "\t", unsigned int flags = format_default) const;
- void save(xml_writer& writer, const char_t* indent = "\t", unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const;
+ void save(xml_writer& writer, const char_t* indent = "\t", unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const;
- xml_node document_element() const;
+ xml_node document_element() const;
-struct xml_parse_result
- xml_parse_status status;
- ptrdiff_t offset;
- xml_encoding encoding;
+struct xml_parse_result
+ xml_parse_status status;
+ ptrdiff_t offset;
+ xml_encoding encoding;
- operator bool() const;
- const char* description() const;
+ operator bool() const;
+ const char* description() const;
-class xml_node_iterator
-class xml_attribute_iterator
+class xml_node_iterator
+class xml_attribute_iterator
-class xml_tree_walker
- virtual bool begin(xml_node& node);
- virtual bool for_each(xml_node& node) = 0;
- virtual bool end(xml_node& node);
+class xml_tree_walker
+ virtual bool begin(xml_node& node);
+ virtual bool for_each(xml_node& node) = 0;
+ virtual bool end(xml_node& node);
- int depth() const;
+ int depth() const;
-class xml_text
- bool empty() const;
- operator xml_text::unspecified_bool_type() const;
+class xml_text
+ bool empty() const;
+ operator xml_text::unspecified_bool_type() const;
- const char_t* xml_text::get() const;
+ const char_t* xml_text::get() const;
- const char_t* as_string(const char_t* def = "") const;
- int as_int(int def = 0) const;
- unsigned int as_uint(unsigned int def = 0) const;
- double as_double(double def = 0) const;
- float as_float(float def = 0) const;
- bool as_bool(bool def = false) const;
- long long as_llong(long long def = 0) const;
- unsigned long long as_ullong(unsigned long long def = 0) const;
+ const char_t* as_string(const char_t* def = "") const;
+ int as_int(int def = 0) const;
+ unsigned int as_uint(unsigned int def = 0) const;
+ double as_double(double def = 0) const;
+ float as_float(float def = 0) const;
+ bool as_bool(bool def = false) const;
+ long long as_llong(long long def = 0) const;
+ unsigned long long as_ullong(unsigned long long def = 0) const;
- bool set(const char_t* rhs);
+ bool set(const char_t* rhs);
- bool set(int rhs);
- bool set(unsigned int rhs);
- bool set(long rhs);
- bool set(unsigned long rhs);
- bool set(double rhs);
- bool set(float rhs);
- bool set(bool rhs);
- bool set(long long rhs);
- bool set(unsigned long long rhs);
+ bool set(int rhs);
+ bool set(unsigned int rhs);
+ bool set(long rhs);
+ bool set(unsigned long rhs);
+ bool set(double rhs);
+ bool set(float rhs);
+ bool set(bool rhs);
+ bool set(long long rhs);
+ bool set(unsigned long long rhs);
- xml_text& operator=(const char_t* rhs);
- xml_text& operator=(int rhs);
- xml_text& operator=(unsigned int rhs);
- xml_text& operator=(long rhs);
- xml_text& operator=(unsigned long rhs);
- xml_text& operator=(double rhs);
- xml_text& operator=(float rhs);
- xml_text& operator=(bool rhs);
- xml_text& operator=(long long rhs);
- xml_text& operator=(unsigned long long rhs);
+ xml_text& operator=(const char_t* rhs);
+ xml_text& operator=(int rhs);
+ xml_text& operator=(unsigned int rhs);
+ xml_text& operator=(long rhs);
+ xml_text& operator=(unsigned long rhs);
+ xml_text& operator=(double rhs);
+ xml_text& operator=(float rhs);
+ xml_text& operator=(bool rhs);
+ xml_text& operator=(long long rhs);
+ xml_text& operator=(unsigned long long rhs);
- xml_node data() const;
+ xml_node data() const;
-class xml_writer
- virtual void write(const void* data, size_t size) = 0;
+class xml_writer
+ virtual void write(const void* data, size_t size) = 0;
-class xml_writer_file: public xml_writer
- xml_writer_file(void* file);
+class xml_writer_file: public xml_writer
+ xml_writer_file(void* file);
-class xml_writer_stream: public xml_writer
- xml_writer_stream(std::ostream& stream);
- xml_writer_stream(std::wostream& stream);
+class xml_writer_stream: public xml_writer
+ xml_writer_stream(std::ostream& stream);
+ xml_writer_stream(std::wostream& stream);
-struct xpath_parse_result
- const char* error;
- ptrdiff_t offset;
+struct xpath_parse_result
+ const char* error;
+ ptrdiff_t offset;
- operator bool() const;
- const char* description() const;
+ operator bool() const;
+ const char* description() const;
-class xpath_query
- explicit xpath_query(const char_t* query, xpath_variable_set* variables = 0);
+class xpath_query
+ explicit xpath_query(const char_t* query, xpath_variable_set* variables = 0);
- bool evaluate_boolean(const xpath_node& n) const;
- double evaluate_number(const xpath_node& n) const;
- string_t evaluate_string(const xpath_node& n) const;
- size_t evaluate_string(char_t* buffer, size_t capacity, const xpath_node& n) const;
- xpath_node_set evaluate_node_set(const xpath_node& n) const;
- xpath_node evaluate_node(const xpath_node& n) const;
+ bool evaluate_boolean(const xpath_node& n) const;
+ double evaluate_number(const xpath_node& n) const;
+ string_t evaluate_string(const xpath_node& n) const;
+ size_t evaluate_string(char_t* buffer, size_t capacity, const xpath_node& n) const;
+ xpath_node_set evaluate_node_set(const xpath_node& n) const;
+ xpath_node evaluate_node(const xpath_node& n) const;
- xpath_value_type return_type() const;
+ xpath_value_type return_type() const;
- const xpath_parse_result& result() const;
- operator unspecified_bool_type() const;
+ const xpath_parse_result& result() const;
+ operator unspecified_bool_type() const;
-class xpath_exception: public std::exception
- virtual const char* what() const throw();
+class xpath_exception: public std::exception
+ virtual const char* what() const throw();
- const xpath_parse_result& result() const;
+ const xpath_parse_result& result() const;
-class xpath_node
- xpath_node();
- xpath_node(const xml_node& node);
- xpath_node(const xml_attribute& attribute, const xml_node& parent);
+class xpath_node
+ xpath_node();
+ xpath_node(const xml_node& node);
+ xpath_node(const xml_attribute& attribute, const xml_node& parent);
- xml_node node() const;
- xml_attribute attribute() const;
- xml_node parent() const;
+ xml_node node() const;
+ xml_attribute attribute() const;
+ xml_node parent() const;
- operator unspecified_bool_type() const;
- bool operator==(const xpath_node& n) const;
- bool operator!=(const xpath_node& n) const;
+ operator unspecified_bool_type() const;
+ bool operator==(const xpath_node& n) const;
+ bool operator!=(const xpath_node& n) const;
-class xpath_node_set
- xpath_node_set();
- xpath_node_set(const_iterator begin, const_iterator end, type_t type = type_unsorted);
-
- typedef const xpath_node* const_iterator;
- const_iterator begin() const;
- const_iterator end() const;
+class xpath_node_set
+ xpath_node_set();
+ xpath_node_set(const_iterator begin, const_iterator end, type_t type = type_unsorted);
+
+ typedef const xpath_node* const_iterator;
+ const_iterator begin() const;
+ const_iterator end() const;
- const xpath_node& operator[](size_t index) const;
- size_t size() const;
- bool empty() const;
-
- xpath_node first() const;
-
- enum type_t {type_unsorted, type_sorted, type_sorted_reverse};
- type_t type() const;
- void sort(bool reverse = false);
-
-class xpath_variable
- const char_t* name() const;
- xpath_value_type type() const;
-
- bool get_boolean() const;
- double get_number() const;
- const char_t* get_string() const;
- const xpath_node_set& get_node_set() const;
-
- bool set(bool value);
- bool set(double value);
- bool set(const char_t* value);
- bool set(const xpath_node_set& value);
+ const xpath_node& operator[](size_t index) const;
+ size_t size() const;
+ bool empty() const;
+
+ xpath_node first() const;
+
+ enum type_t {type_unsorted, type_sorted, type_sorted_reverse};
+ type_t type() const;
+ void sort(bool reverse = false);
+
+class xpath_variable
+ const char_t* name() const;
+ xpath_value_type type() const;
+
+ bool get_boolean() const;
+ double get_number() const;
+ const char_t* get_string() const;
+ const xpath_node_set& get_node_set() const;
+
+ bool set(bool value);
+ bool set(double value);
+ bool set(const char_t* value);
+ bool set(const xpath_node_set& value);
-class xpath_variable_set
- xpath_variable* add(const char_t* name, xpath_value_type type);
+class xpath_variable_set
+ xpath_variable* add(const char_t* name, xpath_value_type type);
- bool set(const char_t* name, bool value);
- bool set(const char_t* name, double value);
- bool set(const char_t* name, const char_t* value);
- bool set(const char_t* name, const xpath_node_set& value);
+ bool set(const char_t* name, bool value);
+ bool set(const char_t* name, double value);
+ bool set(const char_t* name, const char_t* value);
+ bool set(const char_t* name, const xpath_node_set& value);
- xpath_variable* get(const char_t* name);
- const xpath_variable* get(const char_t* name) const;
+ xpath_variable* get(const char_t* name);
+ const xpath_variable* get(const char_t* name) const;
@@ -5850,13 +5984,13 @@ If exceptions are disabled, then in the event of parsing failure the query is in
@@ -5871,84 +6005,8 @@ If exceptions are disabled, then in the event of parsing failure the query is in
-