From bc2448afbb294aa4e195b62504e405b80713d634 Mon Sep 17 00:00:00 2001 From: tobias Date: Fri, 21 Jan 2022 15:06:27 +0100 Subject: [PATCH 01/12] Add support for Visual Studio 2022 with Platform Toolset v143. --- scripts/nuget/pugixml.nuspec | 2 +- scripts/nuget_build.ps1 | 6 +- scripts/pugixml_vs2022.vcxproj | 172 +++++++++++++++++++++++++ scripts/pugixml_vs2022_static.vcxproj | 176 ++++++++++++++++++++++++++ 4 files changed, 354 insertions(+), 2 deletions(-) create mode 100644 scripts/pugixml_vs2022.vcxproj create mode 100644 scripts/pugixml_vs2022_static.vcxproj diff --git a/scripts/nuget/pugixml.nuspec b/scripts/nuget/pugixml.nuspec index d76b34c..2b383a1 100644 --- a/scripts/nuget/pugixml.nuspec +++ b/scripts/nuget/pugixml.nuspec @@ -11,7 +11,7 @@ https://pugixml.org/ pugixml is a C++ XML processing library, which consists of a DOM-like interface with rich traversal/modification capabilities, an extremely fast XML parser which constructs the DOM tree from an XML file/buffer, and an XPath 1.0 implementation for complex data-driven tree queries. Full Unicode support is also available, with Unicode interface variants and conversions between different Unicode encodings (which happen automatically during parsing/saving). pugixml is used by a lot of projects, both open-source and proprietary, for performance and easy-to-use interface. -This package contains builds for VS2013, VS2015, VS2017 and VS2019, for both statically linked and DLL CRT; you can switch the CRT linkage in Project -> Properties -> Referenced Packages -> pugixml. +This package contains builds for VS2013, VS2015, VS2017, VS2019 and VS2022, for both statically linked and DLL CRT; you can switch the CRT linkage in Project -> Properties -> Referenced Packages -> pugixml. Light-weight, simple and fast XML parser for C++ with XPath support https://pugixml.org/docs/manual.html#changes Copyright (c) 2006-2020 Arseny Kapoulkine diff --git a/scripts/nuget_build.ps1 b/scripts/nuget_build.ps1 index 7368f3b..30cbebe 100644 --- a/scripts/nuget_build.ps1 +++ b/scripts/nuget_build.ps1 @@ -35,7 +35,11 @@ Force-Copy "../src/pugiconfig.hpp" "nuget/build/native/include/pugiconfig.hpp" Force-Copy "../src/pugixml.hpp" "nuget/build/native/include/pugixml.hpp" Force-Copy "../src/pugixml.cpp" "nuget/build/native/include/pugixml.cpp" -if ($args[0] -eq 2019){ +if ($args[0] -eq 2022){ + Build-Version "vs2022" "v143" "dynamic" + Build-Version "vs2022" "v143" "static" + +} elseif ($args[0] -eq 2019){ Build-Version "vs2019" "v142" "dynamic" Build-Version "vs2019" "v142" "static" diff --git a/scripts/pugixml_vs2022.vcxproj b/scripts/pugixml_vs2022.vcxproj new file mode 100644 index 0000000..a10dafe --- /dev/null +++ b/scripts/pugixml_vs2022.vcxproj @@ -0,0 +1,172 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {07CF01C0-B887-499D-AD9C-799CB6A9FE64} + Win32Proj + pugixml + 10.0 + + + + StaticLibrary + true + v143 + Unicode + + + StaticLibrary + false + v143 + false + Unicode + + + StaticLibrary + true + v143 + Unicode + + + StaticLibrary + false + v143 + false + Unicode + + + + + + + + + + + + + + + + + + + + + vs2019\$(Platform)_$(Configuration)\ + vs2019\$(Platform)_$(Configuration)\ + pugixml + + + vs2019\$(Platform)_$(Configuration)\ + vs2019\$(Platform)_$(Configuration)\ + pugixml + + + vs2019\$(Platform)_$(Configuration)\ + vs2019\$(Platform)_$(Configuration)\ + pugixml + + + vs2019\$(Platform)_$(Configuration)\ + vs2019\$(Platform)_$(Configuration)\ + pugixml + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + $(IntDir)$(TargetName).pdb + OldStyle + false + + + Windows + true + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + $(IntDir)$(TargetName).pdb + OldStyle + false + + + Windows + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + $(IntDir)$(TargetName).pdb + OldStyle + + + Windows + true + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + $(IntDir)$(TargetName).pdb + OldStyle + + + Windows + true + true + true + + + + + + + + + + + + + diff --git a/scripts/pugixml_vs2022_static.vcxproj b/scripts/pugixml_vs2022_static.vcxproj new file mode 100644 index 0000000..96920a3 --- /dev/null +++ b/scripts/pugixml_vs2022_static.vcxproj @@ -0,0 +1,176 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {07CF01C0-B887-499D-AD9C-799CB6A9FE64} + Win32Proj + pugixml + 10.0 + + + + StaticLibrary + true + v143 + Unicode + + + StaticLibrary + false + v143 + false + Unicode + + + StaticLibrary + true + v143 + Unicode + + + StaticLibrary + false + v143 + false + Unicode + + + + + + + + + + + + + + + + + + + + + vs2019\$(Platform)_$(Configuration)Static\ + vs2019\$(Platform)_$(Configuration)Static\ + pugixml + + + vs2019\$(Platform)_$(Configuration)Static\ + vs2019\$(Platform)_$(Configuration)Static\ + pugixml + + + vs2019\$(Platform)_$(Configuration)Static\ + vs2019\$(Platform)_$(Configuration)Static\ + pugixml + + + vs2019\$(Platform)_$(Configuration)Static\ + vs2019\$(Platform)_$(Configuration)Static\ + pugixml + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + $(IntDir)$(TargetName).pdb + OldStyle + false + MultiThreadedDebug + + + Windows + true + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + $(IntDir)$(TargetName).pdb + OldStyle + false + MultiThreadedDebug + + + Windows + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + $(IntDir)$(TargetName).pdb + OldStyle + MultiThreaded + + + Windows + true + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + $(IntDir)$(TargetName).pdb + OldStyle + MultiThreaded + + + Windows + true + true + true + + + + + + + + + + + + + From 16a4f382ac5bcebf2a55a1a5df316861df750de8 Mon Sep 17 00:00:00 2001 From: tobias Date: Fri, 21 Jan 2022 15:30:45 +0100 Subject: [PATCH 02/12] Add missing appveyor test config for Visual Studio 2022. --- tests/autotest-appveyor.ps1 | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/autotest-appveyor.ps1 b/tests/autotest-appveyor.ps1 index dfed8c5..24736ef 100644 --- a/tests/autotest-appveyor.ps1 +++ b/tests/autotest-appveyor.ps1 @@ -18,15 +18,18 @@ foreach ($vs in $args) { Write-Output "# Setting up VS$vs $arch" - if ($vs -eq 15) - { + if ($vs -eq 15) { $vsdevcmdarch = if ($arch -eq "x64") { "amd64" } else { "x86" } Invoke-CmdScript "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\Tools\VsDevCmd.bat" "-arch=$vsdevcmdarch" } - elseif ($vs -eq 19){ + elseif ($vs -eq 19) { $vsdevcmdarch = if ($arch -eq "x64") { "amd64" } else { "x86" } Invoke-CmdScript "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\Tools\VsDevCmd.bat" "-arch=$vsdevcmdarch" } + elseif ($vs -eq 22) { + $vsdevcmdarch = if ($arch -eq "x64") { "amd64" } else { "x86" } + Invoke-CmdScript "C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\Tools\VsDevCmd.bat" "-arch=$vsdevcmdarch" + } else { Invoke-CmdScript "C:\Program Files (x86)\Microsoft Visual Studio $vs.0\VC\vcvarsall.bat" $arch From bd90579718cb66ea78e6770b6ddb1a20c609548a Mon Sep 17 00:00:00 2001 From: tobias Date: Fri, 21 Jan 2022 15:44:39 +0100 Subject: [PATCH 03/12] Add missing build script and test script entries for appveyor. --- appveyor.yml | 3 +++ 1 file changed, 3 insertions(+) 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" } From 64de196ba9f250d734625b4ca3a6c2afd19ba2b6 Mon Sep 17 00:00:00 2001 From: tobias Date: Fri, 21 Jan 2022 15:56:25 +0100 Subject: [PATCH 04/12] Fix path. --- scripts/pugixml_vs2022.vcxproj | 16 ++++++++-------- scripts/pugixml_vs2022_static.vcxproj | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/scripts/pugixml_vs2022.vcxproj b/scripts/pugixml_vs2022.vcxproj index a10dafe..efb1350 100644 --- a/scripts/pugixml_vs2022.vcxproj +++ b/scripts/pugixml_vs2022.vcxproj @@ -70,23 +70,23 @@ - vs2019\$(Platform)_$(Configuration)\ - vs2019\$(Platform)_$(Configuration)\ + vs2022\$(Platform)_$(Configuration)\ + vs2022\$(Platform)_$(Configuration)\ pugixml - vs2019\$(Platform)_$(Configuration)\ - vs2019\$(Platform)_$(Configuration)\ + vs2022\$(Platform)_$(Configuration)\ + vs2022\$(Platform)_$(Configuration)\ pugixml - vs2019\$(Platform)_$(Configuration)\ - vs2019\$(Platform)_$(Configuration)\ + vs2022\$(Platform)_$(Configuration)\ + vs2022\$(Platform)_$(Configuration)\ pugixml - vs2019\$(Platform)_$(Configuration)\ - vs2019\$(Platform)_$(Configuration)\ + vs2022\$(Platform)_$(Configuration)\ + vs2022\$(Platform)_$(Configuration)\ pugixml diff --git a/scripts/pugixml_vs2022_static.vcxproj b/scripts/pugixml_vs2022_static.vcxproj index 96920a3..065a9dc 100644 --- a/scripts/pugixml_vs2022_static.vcxproj +++ b/scripts/pugixml_vs2022_static.vcxproj @@ -70,23 +70,23 @@ - vs2019\$(Platform)_$(Configuration)Static\ - vs2019\$(Platform)_$(Configuration)Static\ + vs2022\$(Platform)_$(Configuration)Static\ + vs2022\$(Platform)_$(Configuration)Static\ pugixml - vs2019\$(Platform)_$(Configuration)Static\ - vs2019\$(Platform)_$(Configuration)Static\ + vs2022\$(Platform)_$(Configuration)Static\ + vs2022\$(Platform)_$(Configuration)Static\ pugixml - vs2019\$(Platform)_$(Configuration)Static\ - vs2019\$(Platform)_$(Configuration)Static\ + vs2022\$(Platform)_$(Configuration)Static\ + vs2022\$(Platform)_$(Configuration)Static\ pugixml - vs2019\$(Platform)_$(Configuration)Static\ - vs2019\$(Platform)_$(Configuration)Static\ + vs2022\$(Platform)_$(Configuration)Static\ + vs2022\$(Platform)_$(Configuration)Static\ pugixml From 428606b3c105921bd59237a572edbd00a04ee406 Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Sun, 6 Feb 2022 09:13:33 -0800 Subject: [PATCH 05/12] Create SECURITY.md Fixes #475 --- SECURITY.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 SECURITY.md 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). From 9ba92a7fa779aa1389b95d703b4c01122379994c Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Tue, 8 Feb 2022 19:15:40 -0800 Subject: [PATCH 06/12] Restore compatibility with WinCE WinCE lacks most recent CRT additions to MSVC; we used to explicitly disable specific sections of code, but it's more comprehensive to just specify that the CRT is from MSVC7 instead of MSVC8. Fixes #401 --- src/pugixml.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/pugixml.cpp b/src/pugixml.cpp index 2b365d9..398f94a 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -132,8 +132,10 @@ using std::memset; #endif // In some environments MSVC is a compiler but the CRT lacks certain MSVC-specific features -#if defined(_MSC_VER) && !defined(__S3E__) +#if defined(_MSC_VER) && !defined(__S3E__) && !defined(_WIN32_WCE) # define PUGI__MSVC_CRT_VERSION _MSC_VER +#elif defined(_WIN32_WCE) +# define PUGI__MSVC_CRT_VERSION 1310 // MSVC7.1 #endif // Not all platforms have snprintf; we define a wrapper that uses snprintf if possible. This only works with buffers with a known size. @@ -4733,7 +4735,7 @@ PUGI__NS_BEGIN // we need to get length of entire file to load it in memory; the only (relatively) sane way to do it is via seek/tell trick PUGI__FN xml_parse_status get_file_size(FILE* file, size_t& out_result) { - #if defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400 && !defined(_WIN32_WCE) + #if defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400 // there are 64-bit versions of fseek/ftell, let's use them typedef __int64 length_type; @@ -8270,7 +8272,7 @@ PUGI__NS_BEGIN } // gets mantissa digits in the form of 0.xxxxx with 0. implied and the exponent -#if defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400 && !defined(_WIN32_WCE) +#if defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400 PUGI__FN void convert_number_to_mantissa_exponent(double value, char (&buffer)[32], char** out_mantissa, int* out_exponent) { // get base values From c9e219c17bd5a3cd465726058c322f40dccca77b Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Tue, 8 Feb 2022 19:56:41 -0800 Subject: [PATCH 07/12] Update version to 1.12 --- CMakeLists.txt | 4 ++-- readme.txt | 2 +- scripts/nuget/pugixml.nuspec | 2 +- scripts/pugixml.podspec | 2 +- scripts/pugixml_dll.rc | 4 ++-- src/pugiconfig.hpp | 2 +- src/pugixml.cpp | 2 +- src/pugixml.hpp | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) 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/readme.txt b/readme.txt index bfb1875..5deba96 100644 --- a/readme.txt +++ b/readme.txt @@ -1,4 +1,4 @@ -pugixml 1.11 - an XML processing library +pugixml 1.12 - an XML processing library Copyright (C) 2006-2020, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) Report bugs and download new versions at https://pugixml.org/ diff --git a/scripts/nuget/pugixml.nuspec b/scripts/nuget/pugixml.nuspec index 2b383a1..2bb43bb 100644 --- a/scripts/nuget/pugixml.nuspec +++ b/scripts/nuget/pugixml.nuspec @@ -2,7 +2,7 @@ pugixml - 1.11.0-appveyor + 1.12.0-appveyor pugixml Arseny Kapoulkine Arseny Kapoulkine diff --git a/scripts/pugixml.podspec b/scripts/pugixml.podspec index 1ba5798..520dc9e 100644 --- a/scripts/pugixml.podspec +++ b/scripts/pugixml.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "pugixml" - s.version = "1.11" + s.version = "1.12" s.summary = "C++ XML parser library." s.homepage = "https://pugixml.org" s.license = "MIT" diff --git a/scripts/pugixml_dll.rc b/scripts/pugixml_dll.rc index 968254b..4e8d85a 100644 --- a/scripts/pugixml_dll.rc +++ b/scripts/pugixml_dll.rc @@ -1,9 +1,9 @@ #include #define PUGIXML_VERSION_MAJOR 1 -#define PUGIXML_VERSION_MINOR 11 +#define PUGIXML_VERSION_MINOR 12 #define PUGIXML_VERSION_PATCH 0 -#define PUGIXML_VERSION_NUMBER "1.11.0\0" +#define PUGIXML_VERSION_NUMBER "1.12.0\0" #if defined(GCC_WINDRES) || defined(__MINGW32__) || defined(__CYGWIN__) VS_VERSION_INFO VERSIONINFO diff --git a/src/pugiconfig.hpp b/src/pugiconfig.hpp index 405a66b..14ee864 100644 --- a/src/pugiconfig.hpp +++ b/src/pugiconfig.hpp @@ -1,5 +1,5 @@ /** - * pugixml parser - version 1.11 + * pugixml parser - version 1.12 * -------------------------------------------------------- * Copyright (C) 2006-2020, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) * Report bugs and download new versions at https://pugixml.org/ diff --git a/src/pugixml.cpp b/src/pugixml.cpp index 398f94a..be3908a 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -1,5 +1,5 @@ /** - * pugixml parser - version 1.11 + * pugixml parser - version 1.12 * -------------------------------------------------------- * Copyright (C) 2006-2020, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) * Report bugs and download new versions at https://pugixml.org/ diff --git a/src/pugixml.hpp b/src/pugixml.hpp index ed234fb..25268da 100644 --- a/src/pugixml.hpp +++ b/src/pugixml.hpp @@ -1,5 +1,5 @@ /** - * pugixml parser - version 1.11 + * pugixml parser - version 1.12 * -------------------------------------------------------- * Copyright (C) 2006-2020, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) * Report bugs and download new versions at https://pugixml.org/ From 25c4fb74a8808822bc822027bc20ae4410be2f7d Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Tue, 8 Feb 2022 19:58:58 -0800 Subject: [PATCH 08/12] Update copyright year to 2022 --- LICENSE.md | 2 +- docs/manual.adoc | 4 ++-- docs/quickstart.adoc | 4 ++-- readme.txt | 4 ++-- scripts/nuget/pugixml.nuspec | 2 +- scripts/pugixml_dll.rc | 2 +- src/pugiconfig.hpp | 4 ++-- src/pugixml.cpp | 4 ++-- src/pugixml.hpp | 4 ++-- 9 files changed, 15 insertions(+), 15 deletions(-) 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/docs/manual.adoc b/docs/manual.adoc index 0262047..443b605 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]] diff --git a/docs/quickstart.adoc b/docs/quickstart.adoc index ee15665..d9fb69e 100644 --- a/docs/quickstart.adoc +++ b/docs/quickstart.adoc @@ -255,7 +255,7 @@ If filing an issue is not possible due to privacy or other concerns, you can con 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 @@ -283,5 +283,5 @@ 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. .... diff --git a/readme.txt b/readme.txt index 5deba96..747fc0b 100644 --- a/readme.txt +++ b/readme.txt @@ -1,6 +1,6 @@ pugixml 1.12 - an XML processing library -Copyright (C) 2006-2020, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) +Copyright (C) 2006-2022, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) Report bugs and download new versions at https://pugixml.org/ This is the distribution of pugixml, which is a C++ XML processing library, @@ -26,7 +26,7 @@ The distribution contains the following folders: This library is distributed under the MIT License: -Copyright (c) 2006-2019 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/scripts/nuget/pugixml.nuspec b/scripts/nuget/pugixml.nuspec index 2bb43bb..36d833f 100644 --- a/scripts/nuget/pugixml.nuspec +++ b/scripts/nuget/pugixml.nuspec @@ -14,7 +14,7 @@ pugixml is used by a lot of projects, both open-source and proprietary, for perf This package contains builds for VS2013, VS2015, VS2017, VS2019 and VS2022, for both statically linked and DLL CRT; you can switch the CRT linkage in Project -> Properties -> Referenced Packages -> pugixml. Light-weight, simple and fast XML parser for C++ with XPath support https://pugixml.org/docs/manual.html#changes - Copyright (c) 2006-2020 Arseny Kapoulkine + Copyright (c) 2006-2022 Arseny Kapoulkine native nativepackage diff --git a/scripts/pugixml_dll.rc b/scripts/pugixml_dll.rc index 4e8d85a..72c68d0 100644 --- a/scripts/pugixml_dll.rc +++ b/scripts/pugixml_dll.rc @@ -31,7 +31,7 @@ BEGIN VALUE "FileDescription", "pugixml library\0" VALUE "FileVersion", PUGIXML_VERSION_NUMBER VALUE "InternalName", "pugixml.dll\0" - VALUE "LegalCopyright", "Copyright (C) 2006-2020, by Arseny Kapoulkine\0" + VALUE "LegalCopyright", "Copyright (C) 2006-2022, by Arseny Kapoulkine\0" VALUE "OriginalFilename", "pugixml.dll\0" VALUE "ProductName", "pugixml\0" VALUE "ProductVersion", PUGIXML_VERSION_NUMBER diff --git a/src/pugiconfig.hpp b/src/pugiconfig.hpp index 14ee864..0713b0e 100644 --- a/src/pugiconfig.hpp +++ b/src/pugiconfig.hpp @@ -1,7 +1,7 @@ /** * pugixml parser - version 1.12 * -------------------------------------------------------- - * Copyright (C) 2006-2020, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) + * Copyright (C) 2006-2022, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) * Report bugs and download new versions at https://pugixml.org/ * * This library is distributed under the MIT License. See notice at the end @@ -52,7 +52,7 @@ #endif /** - * 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/src/pugixml.cpp b/src/pugixml.cpp index be3908a..60b55da 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -1,7 +1,7 @@ /** * pugixml parser - version 1.12 * -------------------------------------------------------- - * Copyright (C) 2006-2020, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) + * Copyright (C) 2006-2022, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) * Report bugs and download new versions at https://pugixml.org/ * * This library is distributed under the MIT License. See notice at the end @@ -13004,7 +13004,7 @@ namespace pugi #endif /** - * 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/src/pugixml.hpp b/src/pugixml.hpp index 25268da..5a8496d 100644 --- a/src/pugixml.hpp +++ b/src/pugixml.hpp @@ -1,7 +1,7 @@ /** * pugixml parser - version 1.12 * -------------------------------------------------------- - * Copyright (C) 2006-2020, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) + * Copyright (C) 2006-2022, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) * Report bugs and download new versions at https://pugixml.org/ * * This library is distributed under the MIT License. See notice at the end @@ -1476,7 +1476,7 @@ namespace std #endif /** - * 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 From eb918f20789d2c266bea1c509f5fbe96b5a9689d Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Tue, 8 Feb 2022 19:59:44 -0800 Subject: [PATCH 09/12] docs: Update manual with 1.12 changelog --- docs/manual.adoc | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/docs/manual.adoc b/docs/manual.adoc index 443b605..ac51535 100644 --- a/docs/manual.adoc +++ b/docs/manual.adoc @@ -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^ From 314baf6605143f1e837209008f490e8559529e1c Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Tue, 8 Feb 2022 20:09:10 -0800 Subject: [PATCH 10/12] docs: Regenerate HTML documentation --- docs/manual.html | 2290 ++++++++++++++++++++++-------------------- docs/quickstart.html | 545 +++++----- 2 files changed, 1444 insertions(+), 1391 deletions(-) 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 @@ - + -pugixml 1.11 manual +pugixml 1.12 manual + @@ -686,9 +758,9 @@ pugixml is Copyright (C) 2006-2020 Arseny Kapoulkine.

You can download the latest source distribution as an archive:

-

pugixml-1.11.zip (Windows line endings) +

pugixml-1.12.zip (Windows line endings) / -pugixml-1.11.tar.gz (Unix line endings)

+pugixml-1.12.tar.gz (Unix line endings)

The distribution contains library source, documentation (the manual you’re reading now and the quick start guide) and some code examples. After downloading the distribution, install pugixml by extracting all files from the compressed archive.

@@ -709,7 +781,7 @@ pugixml is Copyright (C) 2006-2020 Arseny Kapoulkine.
git clone https://github.com/zeux/pugixml
 cd pugixml
-git checkout v1.11
+git checkout v1.12
@@ -726,7 +798,7 @@ git checkout v1.11
-
svn checkout https://github.com/zeux/pugixml/tags/v1.11 pugixml
+
svn checkout https://github.com/zeux/pugixml/tags/v1.12 pugixml
@@ -774,7 +846,7 @@ git checkout v1.11
-
pugixml.cpp(3477) : fatal error C1010: unexpected end of file while looking for precompiled header. Did you forget to add '#include "stdafx.h"' to your source?
+
pugixml.cpp(3477) : fatal error C1010: unexpected end of file while looking for precompiled header. Did you forget to add '#include "stdafx.h"' to your source?
@@ -871,9 +943,9 @@ git checkout v1.11
#ifdef _DLL
-    #define PUGIXML_API __declspec(dllexport)
+    #define PUGIXML_API __declspec(dllexport)
 #else
-    #define PUGIXML_API __declspec(dllimport)
+    #define PUGIXML_API __declspec(dllimport)
 #endif
@@ -908,7 +980,7 @@ can include pugixml.cpp in your project (see B
#ifndef _DEBUG
-    #define PUGIXML_HEADER_ONLY
+    #define PUGIXML_HEADER_ONLY
 #endif
@@ -999,7 +1071,7 @@ In that example PUGIXML_API is inconsistent between several source

Element/tag node (node_element) - this is the most common type of node, which represents XML elements. Element nodes have a name, a collection of attributes and a collection of child nodes (both of which may be empty). The attribute is a simple name/value pair. The example XML representation of element nodes is as follows:

-
<node attr="value"><child/></node>
+
<node attr="value"><child/></node>
@@ -1010,7 +1082,7 @@ In that example PUGIXML_API is inconsistent between several source

Plain character data nodes (node_pcdata) represent plain text in XML. PCDATA nodes have a value, but do not have a name or children/attributes. Note that plain character data is not a part of the element node but instead has its own node; an element node can have several child PCDATA nodes. The example XML representation of text nodes is as follows:

-
<node> text1 <child/> text2 </node>
+
<node> text1 <child/> text2 </node>
@@ -1021,7 +1093,7 @@ In that example PUGIXML_API is inconsistent between several source

Character data nodes (node_cdata) represent text in XML that is quoted in a special way. CDATA nodes do not differ from PCDATA nodes except in XML representation - the above text example looks like this with CDATA:

-
<node> <![CDATA[text1]]> <child/> <![CDATA[text2]]> </node>
+
<node> <![CDATA[text1]]> <child/> <![CDATA[text2]]> </node>
@@ -1032,7 +1104,7 @@ In that example PUGIXML_API is inconsistent between several source

Comment nodes (node_comment) represent comments in XML. Comment nodes have a value, but do not have a name or children/attributes. The example XML representation of a comment node is as follows:

-
<!-- comment text -->
+
<!-- comment text -->
@@ -1043,7 +1115,7 @@ In that example PUGIXML_API is inconsistent between several source

Processing instruction node (node_pi) represent processing instructions (PI) in XML. PI nodes have a name and an optional value, but do not have children/attributes. The example XML representation of a PI node is as follows:

-
<?name value?>
+
<?name value?>
@@ -1054,7 +1126,7 @@ In that example PUGIXML_API is inconsistent between several source

Declaration node (node_declaration) represents document declarations in XML. Declaration nodes have a name ("xml") and an optional collection of attributes, but do not have value or children. There can be only one declaration node in a document; moreover, it should be the topmost node (its parent should be the document). The example XML representation of a declaration node is as follows:

-
<?xml version="1.0"?>
+
<?xml version="1.0"?>
@@ -1065,7 +1137,7 @@ In that example PUGIXML_API is inconsistent between several source

Document type declaration node (node_doctype) represents document type declarations in XML. Document type declaration nodes have a value, which corresponds to the entire document type contents; no additional nodes are created for inner elements like <!ENTITY>. There can be only one document type declaration node in a document; moreover, it should be the topmost node (its parent should be the document). The example XML representation of a document type declaration node is as follows:

-
<!DOCTYPE greeting [ <!ELEMENT greeting (#PCDATA)> ]>
+
<!DOCTYPE greeting [ <!ELEMENT greeting (#PCDATA)> ]>
@@ -1174,8 +1246,8 @@ Finally handles can be implicitly cast to boolean-like objects, so that you can
-
bool xml_attribute::empty() const;
-bool xml_node::empty() const;
+
bool xml_attribute::empty() const;
+bool xml_node::empty() const;
@@ -1204,8 +1276,8 @@ If the size of wchar_t is 2, pugixml assumes UTF-16 encoding instea
-
const char* xml_node::name() const;
-bool xml_node::set_name(const char* value);
+
const char* xml_node::name() const;
+bool xml_node::set_name(const char* value);
@@ -1213,8 +1285,8 @@ If the size of wchar_t is 2, pugixml assumes UTF-16 encoding instea
-
const wchar_t* xml_node::name() const;
-bool xml_node::set_name(const wchar_t* value);
+
const wchar_t* xml_node::name() const;
+bool xml_node::set_name(const wchar_t* value);
@@ -1230,8 +1302,8 @@ There are cases when you’ll have to convert string data between UTF-8 and
-
std::string as_utf8(const wchar_t* str);
-std::wstring as_wide(const char* str);
+
std::string as_utf8(const wchar_t* str);
+std::wstring as_wide(const char* str);
@@ -1239,8 +1311,8 @@ There are cases when you’ll have to convert string data between UTF-8 and
-
std::string as_utf8(const std::wstring& str);
-std::wstring as_wide(const std::string& str);
+
std::string as_utf8(const std::wstring& str);
+std::wstring as_wide(const std::string& str);
@@ -1317,8 +1389,8 @@ All memory for tree structure, tree data and XPath objects is allocated via glob
-
typedef void* (*allocation_function)(size_t size);
-typedef void (*deallocation_function)(void* ptr);
+
typedef void* (*allocation_function)(size_t size);
+typedef void (*deallocation_function)(void* ptr);
@@ -1327,9 +1399,9 @@ You can use the following accessor functions to change or get current memory man
-
void set_memory_management_functions(allocation_function allocate, deallocation_function deallocate);
-allocation_function get_memory_allocation_function();
-deallocation_function get_memory_deallocation_function();
+
void set_memory_management_functions(allocation_function allocate, deallocation_function deallocate);
+allocation_function get_memory_allocation_function();
+deallocation_function get_memory_deallocation_function();
@@ -1343,20 +1415,20 @@ You can use the following accessor functions to change or get current memory man
-
void* custom_allocate(size_t size)
-{
-    return new (std::nothrow) char[size];
-}
+
void* custom_allocate(size_t size)
+{
+    return new (std::nothrow) char[size];
+}
 
-void custom_deallocate(void* ptr)
-{
-    delete[] static_cast<char*>(ptr);
-}
+void custom_deallocate(void* ptr) +{ + delete[] static_cast<char*>(ptr); +}
-
pugi::set_memory_management_functions(custom_allocate, custom_deallocate);
+
pugi::set_memory_management_functions(custom_allocate, custom_deallocate);
@@ -1432,8 +1504,8 @@ The most common source of XML data is files; pugixml provides dedicated function
-
xml_parse_result xml_document::load_file(const char* path, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
-xml_parse_result xml_document::load_file(const wchar_t* path, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
+
xml_parse_result xml_document::load_file(const char* path, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
+xml_parse_result xml_document::load_file(const wchar_t* path, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
@@ -1450,11 +1522,11 @@ The most common source of XML data is files; pugixml provides dedicated function
-
pugi::xml_document doc;
+
pugi::xml_document doc;
 
-pugi::xml_parse_result result = doc.load_file("tree.xml");
+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;
+std::cout << "Load result: " << result.description() << ", mesh name: " << doc.child("mesh").attribute("name").value() << std::endl;
@@ -1466,9 +1538,9 @@ Sometimes XML data should be loaded from some other source than a file, i.e. HTT
-
xml_parse_result xml_document::load_buffer(const void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
-xml_parse_result xml_document::load_buffer_inplace(void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
-xml_parse_result xml_document::load_buffer_inplace_own(void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
+
xml_parse_result xml_document::load_buffer(const void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
+xml_parse_result xml_document::load_buffer_inplace(void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
+xml_parse_result xml_document::load_buffer_inplace_own(void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
@@ -1485,7 +1557,7 @@ Sometimes XML data should be loaded from some other source than a file, i.e. HTT
-
xml_parse_result xml_document::load_string(const char_t* contents, unsigned int options = parse_default);
+
xml_parse_result xml_document::load_string(const char_t* contents, unsigned int options = parse_default);
@@ -1496,44 +1568,44 @@ Sometimes XML data should be loaded from some other source than a file, i.e. HTT
-
const char source[] = "<mesh name='sphere'><bounds>0 0 1 1</bounds></mesh>";
-size_t size = sizeof(source);
+
const char source[] = "<mesh name='sphere'><bounds>0 0 1 1</bounds></mesh>";
+size_t size = sizeof(source);
// You can use load_buffer to load document from immutable memory block:
-pugi::xml_parse_result result = doc.load_buffer(source, size);
+pugi::xml_parse_result result = doc.load_buffer(source, size);
// 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);
+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);
+pugi::xml_parse_result result = doc.load_buffer_inplace(buffer, size);
 
 // You have to destroy the block yourself after the document is no longer used
-delete[] buffer;
+delete[] buffer;
// You can use load_buffer_inplace_own to load document from mutable memory block and to pass the ownership of this block
 // The block has to be allocated via pugixml allocation function - using i.e. operator new here is incorrect
-char* buffer = static_cast<char*>(pugi::get_memory_allocation_function()(size));
-memcpy(buffer, source, size);
+char* buffer = static_cast<char*>(pugi::get_memory_allocation_function()(size));
+memcpy(buffer, source, size);
 
 // The block will be deleted by the document
-pugi::xml_parse_result result = doc.load_buffer_inplace_own(buffer, size);
+pugi::xml_parse_result result = doc.load_buffer_inplace_own(buffer, size);
// You can use load to load document from null-terminated strings, for example literals:
-pugi::xml_parse_result result = doc.load_string("<mesh name='sphere'><bounds>0 0 1 1</bounds></mesh>");
+pugi::xml_parse_result result = doc.load_string("<mesh name='sphere'><bounds>0 0 1 1</bounds></mesh>");
@@ -1544,8 +1616,8 @@ Sometimes XML data should be loaded from some other source than a file, i.e. HTT
-
xml_parse_result xml_document::load(std::istream& stream, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
-xml_parse_result xml_document::load(std::wistream& stream, unsigned int options = parse_default);
+
xml_parse_result xml_document::load(std::istream& stream, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
+xml_parse_result xml_document::load(std::wistream& stream, unsigned int options = parse_default);
@@ -1559,8 +1631,8 @@ Sometimes XML data should be loaded from some other source than a file, i.e. HTT
-
std::ifstream stream("weekly-utf-8.xml");
-pugi::xml_parse_result result = doc.load(stream);
+
std::ifstream stream("weekly-utf-8.xml");
+pugi::xml_parse_result result = doc.load(stream);
@@ -1571,15 +1643,15 @@ Sometimes XML data should be loaded from some other source than a file, i.e. HTT
-
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; +};
@@ -1661,19 +1733,19 @@ Offset is calculated in the XML buffer in native encoding; if encoding conversio
-
pugi::xml_document doc;
-pugi::xml_parse_result result = doc.load_string(source);
+
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";
-}
+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"; +}
@@ -1796,23 +1868,23 @@ Using in-place parsing (load_buffer
-
const char* source = "<!--comment--><node>&lt;</node>";
+
const char* source = "<!--comment--><node>&lt;</node>";
 
 // Parsing with default options; note that comment node is not added to the tree, and entity reference &lt; is expanded
-doc.load_string(source);
-std::cout << "First node value: [" << doc.first_child().value() << "], node child value: [" << doc.child_value("node") << "]\n";
+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; &lt; is not expanded
-doc.load_string(source, (pugi::parse_default | pugi::parse_comments) & ~pugi::parse_escapes);
-std::cout << "First node value: [" << doc.first_child().value() << "], node child value: [" << doc.child_value("node") << "]\n";
+doc.load_string(source, (pugi::parse_default | pugi::parse_comments) & ~pugi::parse_escapes);
+std::cout << "First node value: [" << doc.first_child().value() << "], node child value: [" << doc.child_value("node") << "]\n";
 
 // Parsing with minimal option mask; comment node is not added to the tree, and &lt; is not expanded
-doc.load_string(source, pugi::parse_minimal);
-std::cout << "First node value: [" << doc.first_child().value() << "], node child value: [" << doc.child_value("node") << "]\n";
+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

9. Changelog

+

v1.12 2022-02-09

+
+

Maintenance release. Changes:

+
+
+
    +
  • +

    Bug fixes:

    +
    +
      +
    1. +

      Fix a bug in xml_document move construction when the source of the move is empty

      +
    2. +
    3. +

      Fix const-correctness issues with iterator objects to support C++20 ranges

      +
    4. +
    +
    +
  • +
  • +

    XPath improvements:

    +
    +
      +
    1. +

      Improved detection of overly complex queries that may result in stack overflow during parsing

      +
    2. +
    +
    +
  • +
  • +

    Compatibility improvements:

    +
    +
      +
    1. +

      Fix Cygwin support for DLL builds

      +
    2. +
    3. +

      Fix Windows CE support

      +
    4. +
    5. +

      Add NuGet builds and project files for VS2022

      +
    6. +
    +
    +
  • +
  • +

    Build system changes

    +
    +
      +
    1. +

      All CMake options now have the prefix PUGIXML_. This may require changing dependent build configurations.

      +
    2. +
    3. +

      Many build settings are now exposed via CMake settings, most notably PUGIXML_COMPACT and PUGIXML_WCHAR_MODE can be set without changing pugiconfig.hpp

      +
    4. +
    +
    +
  • +
+
+
+

v1.11 2020-11-26

Maintenance release. Changes:

@@ -5393,10 +5527,10 @@ If exceptions are disabled, then in the event of parsing failure the query is in

10.2. Types

-
typedef configuration-defined-type char_t;
-typedef configuration-defined-type string_t;
-typedef void* (*allocation_function)(size_t size);
-typedef void (*deallocation_function)(void* ptr);
+
typedef configuration-defined-type char_t;
+typedef configuration-defined-type string_t;
+typedef void* (*allocation_function)(size_t size);
+typedef void (*deallocation_function)(void* ptr);
@@ -5404,54 +5538,54 @@ If exceptions are disabled, then in the event of parsing failure the query is in

10.3. Enumerations

-
enum xml_node_type
-    node_null
-    node_document
-    node_element
-    node_pcdata
-    node_cdata
-    node_comment
-    node_pi
-    node_declaration
-    node_doctype
+
enum xml_node_type
+    node_null
+    node_document
+    node_element
+    node_pcdata
+    node_cdata
+    node_comment
+    node_pi
+    node_declaration
+    node_doctype
 
-enum xml_parse_status
-    status_ok
-    status_file_not_found
-    status_io_error
-    status_out_of_memory
-    status_internal_error
-    status_unrecognized_tag
-    status_bad_pi
-    status_bad_comment
-    status_bad_cdata
-    status_bad_doctype
-    status_bad_pcdata
-    status_bad_start_element
-    status_bad_attribute
-    status_bad_end_element
-    status_end_element_mismatch
-    status_append_invalid_root
-    status_no_document_element
+enum xml_parse_status
+    status_ok
+    status_file_not_found
+    status_io_error
+    status_out_of_memory
+    status_internal_error
+    status_unrecognized_tag
+    status_bad_pi
+    status_bad_comment
+    status_bad_cdata
+    status_bad_doctype
+    status_bad_pcdata
+    status_bad_start_element
+    status_bad_attribute
+    status_bad_end_element
+    status_end_element_mismatch
+    status_append_invalid_root
+    status_no_document_element
 
-enum xml_encoding
-    encoding_auto
-    encoding_utf8
-    encoding_utf16_le
-    encoding_utf16_be
-    encoding_utf16
-    encoding_utf32_le
-    encoding_utf32_be
-    encoding_utf32
-    encoding_wchar
-    encoding_latin1
+enum xml_encoding
+    encoding_auto
+    encoding_utf8
+    encoding_utf16_le
+    encoding_utf16_be
+    encoding_utf16
+    encoding_utf32_le
+    encoding_utf32_be
+    encoding_utf32
+    encoding_wchar
+    encoding_latin1
 
-enum xpath_value_type
-    xpath_type_none
-    xpath_type_node_set
-    xpath_type_number
-    xpath_type_string
-    xpath_type_boolean
+enum xpath_value_type + xpath_type_none + xpath_type_node_set + xpath_type_number + xpath_type_string + xpath_type_boolean
@@ -5460,36 +5594,36 @@ If exceptions are disabled, then in the event of parsing failure the query is in
// Formatting options bit flags:
-const unsigned int format_attribute_single_quote
-const unsigned int format_default
-const unsigned int format_indent
-const unsigned int format_indent_attributes
-const unsigned int format_no_declaration
-const unsigned int format_no_empty_element_tags
-const unsigned int format_no_escapes
-const unsigned int format_raw
-const unsigned int format_save_file_text
-const unsigned int format_skip_control_chars
-const unsigned int format_write_bom
+const unsigned int format_attribute_single_quote
+const unsigned int format_default
+const unsigned int format_indent
+const unsigned int format_indent_attributes
+const unsigned int format_no_declaration
+const unsigned int format_no_empty_element_tags
+const unsigned int format_no_escapes
+const unsigned int format_raw
+const unsigned int format_save_file_text
+const unsigned int format_skip_control_chars
+const unsigned int format_write_bom
 
 // Parsing options bit flags:
-const unsigned int parse_cdata
-const unsigned int parse_comments
-const unsigned int parse_declaration
-const unsigned int parse_default
-const unsigned int parse_doctype
-const unsigned int parse_eol
-const unsigned int parse_escapes
-const unsigned int parse_fragment
-const unsigned int parse_full
-const unsigned int parse_minimal
-const unsigned int parse_pi
-const unsigned int parse_trim_pcdata
-const unsigned int parse_ws_pcdata
-const unsigned int parse_ws_pcdata_single
-const unsigned int parse_embed_pcdata
-const unsigned int parse_wconv_attribute
-const unsigned int parse_wnorm_attribute
+const unsigned int parse_cdata +const unsigned int parse_comments +const unsigned int parse_declaration +const unsigned int parse_default +const unsigned int parse_doctype +const unsigned int parse_eol +const unsigned int parse_escapes +const unsigned int parse_fragment +const unsigned int parse_full +const unsigned int parse_minimal +const unsigned int parse_pi +const unsigned int parse_trim_pcdata +const unsigned int parse_ws_pcdata +const unsigned int parse_ws_pcdata_single +const unsigned int parse_embed_pcdata +const unsigned int parse_wconv_attribute +const unsigned int parse_wnorm_attribute
@@ -5497,352 +5631,352 @@ If exceptions are disabled, then in the event of parsing failure the query is in

10.5. Classes

-
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

10.6. Functions

-
std::string as_utf8(const wchar_t* str);
-std::string as_utf8(const std::wstring& str);
-std::wstring as_wide(const char* str);
-std::wstring as_wide(const std::string& str);
-void set_memory_management_functions(allocation_function allocate, deallocation_function deallocate);
-allocation_function get_memory_allocation_function();
-deallocation_function get_memory_deallocation_function();
+
std::string as_utf8(const wchar_t* str);
+std::string as_utf8(const std::wstring& str);
+std::wstring as_wide(const char* str);
+std::wstring as_wide(const std::string& str);
+void set_memory_management_functions(allocation_function allocate, deallocation_function deallocate);
+allocation_function get_memory_allocation_function();
+deallocation_function get_memory_deallocation_function();
@@ -5871,84 +6005,8 @@ If exceptions are disabled, then in the event of parsing failure the query is in - \ No newline at end of file diff --git a/docs/quickstart.html b/docs/quickstart.html index 6eac2c7..2c8a1ab 100644 --- a/docs/quickstart.html +++ b/docs/quickstart.html @@ -4,26 +4,24 @@ - + -pugixml 1.11 quick start guide +pugixml 1.12 quick start guide + @@ -677,13 +748,13 @@ All pugixml classes and functions are located in pugi namespace; yo
-
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";
+}
@@ -691,12 +762,12 @@ All pugixml classes and functions are located in pugi namespace; yo
-
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"; +}
@@ -707,17 +778,17 @@ All pugixml classes and functions are located in pugi namespace; yo
-
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; +}
@@ -728,22 +799,22 @@ All pugixml classes and functions are located in pugi namespace; yo
-
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; +}
@@ -754,23 +825,23 @@ All pugixml classes and functions are located in pugi namespace; yo
-
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);
@@ -778,20 +849,20 @@ All pugixml classes and functions are located in pugi namespace; yo
-
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";
@@ -822,35 +893,35 @@ XPath functions throw xpath_exception objects on error; the sample
-
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;
-
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;
@@ -874,19 +945,19 @@ XPath functions throw xpath_exception objects on error; the sample
// 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";
@@ -898,16 +969,16 @@ XPath functions throw xpath_exception objects on error; the sample
// 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);
@@ -927,7 +998,7 @@ XPath functions throw xpath_exception objects on error; the sample
// 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;
@@ -939,8 +1010,8 @@ XPath functions throw xpath_exception objects on error; the sample
// save document to standard output
-std::cout << "Document:\n";
-doc.save(std::cout);
+std::cout << "Document:\n"; +doc.save(std::cout);
@@ -951,15 +1022,15 @@ XPath functions throw xpath_exception objects on error; the sample
-
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); + } +};
@@ -986,7 +1057,7 @@ XPath functions throw xpath_exception objects on error; the sample
-
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
@@ -1016,7 +1087,7 @@ OTHER DEALINGS IN THE SOFTWARE.
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.
@@ -1030,84 +1101,8 @@ pugixml is Copyright (C) 2006-2020 Arseny Kapoulkine.
- \ No newline at end of file From dd50fa5b45ab8d58d6c27566c2eaf04a8b7e5841 Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Thu, 10 Feb 2022 08:36:19 -0800 Subject: [PATCH 11/12] Fix PUGIXML_VERSION macro Also make sure the line shows up in grep when using the current version number. Fixes #478. --- src/pugixml.hpp | 4 ++-- tests/test_version.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pugixml.hpp b/src/pugixml.hpp index 5a8496d..579f143 100644 --- a/src/pugixml.hpp +++ b/src/pugixml.hpp @@ -11,10 +11,10 @@ * Copyright (C) 2003, by Kristen Wegner (kristen@tima.net) */ -#ifndef PUGIXML_VERSION // Define version macro; evaluates to major * 1000 + minor * 10 + patch so that it's safe to use in less-than comparisons // Note: pugixml used major * 100 + minor * 10 + patch format up until 1.9 (which had version identifier 190); starting from pugixml 1.10, the minor version number is two digits -# define PUGIXML_VERSION 1110 +#ifndef PUGIXML_VERSION +# define PUGIXML_VERSION 1120 // 1.12 #endif // Include user configuration file (this can define various configuration macros) diff --git a/tests/test_version.cpp b/tests/test_version.cpp index 11f8a7f..a19b59b 100644 --- a/tests/test_version.cpp +++ b/tests/test_version.cpp @@ -1,5 +1,5 @@ #include "../src/pugixml.hpp" -#if PUGIXML_VERSION != 1110 +#if PUGIXML_VERSION != 1120 #error Unexpected pugixml version #endif From c60ca94cdd836aac8bcee93b01f541bab24de7a5 Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Tue, 15 Feb 2022 20:23:05 -0800 Subject: [PATCH 12/12] tests: Fix MSVC 2022 build Instead of trying to detect if we can safely use random shuffle simply reimplement it ourselves. The quality of the RNG is not essential for these tests. --- tests/test_xpath.cpp | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/tests/test_xpath.cpp b/tests/test_xpath.cpp index b057c57..0fbe392 100644 --- a/tests/test_xpath.cpp +++ b/tests/test_xpath.cpp @@ -10,14 +10,6 @@ #include #include -// std::random_shuffle is deprecated in c++14, is removed in c++17. -#if defined(__cplusplus) && (__cplusplus >= 201402L) -# include -# define PUGIXML_SHUFFLE(rng) std::shuffle(rng.begin(), rng.end(), std::default_random_engine{std::random_device{}()}) -#else -# define PUGIXML_SHUFFLE(rng) std::random_shuffle(rng.begin(), rng.end()) -#endif - using namespace pugi; static void load_document_copy(xml_document& doc, const char_t* text) @@ -28,6 +20,22 @@ static void load_document_copy(xml_document& doc, const char_t* text) doc.append_copy(source.first_child()); } +template +static void random_shuffle(std::vector& v) +{ + size_t rng = 2147483647; + + for (size_t i = v.size() - 1; i > 0; --i) + { + // Fisher-Yates shuffle + size_t j = rng % (i + 1); + std::swap(v[j], v[i]); + + // LCG RNG, constants from Numerical Recipes + rng = rng * 1664525 + 1013904223; + } +} + TEST(xpath_allocator_many_pages) { std::basic_string query = STR("0"); @@ -163,7 +171,7 @@ TEST(xpath_sort_random_medium) xpath_node_set ns = doc.select_nodes(STR("//node() | //@*")); std::vector nsv(ns.begin(), ns.end()); - PUGIXML_SHUFFLE(nsv); + random_shuffle(nsv); xpath_node_set copy(&nsv[0], &nsv[0] + nsv.size()); copy.sort(); @@ -192,7 +200,7 @@ TEST(xpath_sort_random_large) xpath_node_set ns = doc.select_nodes(STR("//node() | //@*")); std::vector nsv(ns.begin(), ns.end()); - PUGIXML_SHUFFLE(nsv); + random_shuffle(nsv); xpath_node_set copy(&nsv[0], &nsv[0] + nsv.size()); copy.sort();