232 Commits
Author SHA1 Message Date
Kirill Str 27b68329de Clarify operator precedence in declaration check (#731)
This makes existing precedence more explicit via grouping, with no behavior/codegen changes.
2026-06-16 11:09:44 -07:00
Arseny Kapoulkine c8033ce9d0 scripts: Remove VS2013/2015 libraries from NuGet builds
Our NuGet package no longer supports VS versions before 2017, so these
are purely redundant; they are also being build on the VS2017 agent, so
it's reliant on having the requisite build tools installed and I'm
concerned a future agent configuration change may silently break this.
2026-06-15 13:38:00 -07:00
Arseny Kapoulkine 974e736f2d Update library version to 1.16 and update docs 2026-06-15 12:18:26 -07:00
Arseny Kapoulkine f5dbff784c Fix bundle identifiers for Apple framework builds to be reverse-dot
This was changed to a URL but it does not appear that bundle identifiers
permit URLs, and in either case this is certainly not idiomatic. The
1.15 value for this was com.zeux.pugixml which is a little strange
because zeux.com is not affiliated with pugixml; change this to
com.github.zeux.pugixml which seems more correct.
2026-06-15 10:41:21 -07:00
Arseny Kapoulkine 77c1bb62e7 Merge pull request #730 from zeux/ensure
Add xml_node::ensure_attribute and xml_node::ensure_child
2026-06-15 10:16:16 -07:00
Arseny Kapoulkine c971615200 docs: Add documentation for ensure_attribute/node
Also add these to the changelog for 1.16 as it's right around the
corner and the changelog has already been written.
2026-06-14 22:16:47 -07:00
Arseny Kapoulkine 09721beb80 tests: Add tests for xml_node::ensure_child/attribute
These include both raw string and string view variants.
2026-06-14 22:16:47 -07:00
Arseny Kapoulkine 7bdf94b22e Add xml_node::ensure_attribute and xml_node::ensure_child
These are equivalent to a named lookup (attribute/child) followed by
appending the attribute/child if an existing one is not found. The
implementation is trivial but this is fairly commonplace in code that
modifies an existing DOM.
2026-06-14 22:16:47 -07:00
Arseny Kapoulkine c5d771df8b docs: Add release notes for 1.16
Planned release is June 16th; note the version numbers have not been
updated yet.
2026-06-13 17:59:06 -07:00
Arseny Kapoulkine 3a8e1dc59e Revert "cmake: add option to enable std::string_view (#708)"
This reverts commit 504c90b2e9.
2026-06-13 15:03:52 -07:00
nolangeandArseny Kapoulkine 504c90b2e9 cmake: add option to enable std::string_view (#708)
There was no way to build without STL (more like without iostream),
but keeping std::string_view.

Co-authored-by: Arseny Kapoulkine <arseny.kapoulkine@gmail.com>
2026-06-13 10:39:26 -07:00
Arseny Kapoulkine 71418cc5c9 Fix xml_parse_result::encoding for empty document load
The new early-out for size==0 has a subtly different behavior from the
main path: encoding is left at auto instead of being set to the inferred
encoding (which is always UTF-8 for empty inputs).

In general, xml_parse_result::encoding is a bit inconsistent for error
returns: the parse() path sets it including errors, but other paths
don't. That said, this is somewhat defensible since there's some difference
between not having parsed anything and having parsed something.

In any case, before the early out, fragment parse of an empty document
would return UTF-8 encoding, so this change restores the behavior and
adds a test for it.
2026-06-13 09:02:40 -07:00
Arseny Kapoulkine 29b39bed6f docs: Update documentation with fresh links for install/portability
- Subversion clones were discontinued by GitHub in 2024
- Some of the packaged links were dead; fix that and add vcpkg/conan
- Update compiler and standard version wording
2026-06-12 14:25:06 -07:00
Arseny Kapoulkine 485f64d425 docs: Assorted documentation fixes
This mostly fixes a few typos and inconsistent references throughout the
documentation; a few function names were misspelled too. And API
reference had a few instances of redundant symbol qualification and
missing functions.

Amusingly, quickstart still referred to VS 2012 as "VS 11 Beta" which...
dates it.
2026-06-12 14:09:49 -07:00
Arseny Kapoulkine 5a18bbcd11 Clean up invalid or incoherent comments
Most importantly, header documentation for parse_merge_pcdata was
difficult to follow, so as a drive-by this fixes a few other clarity
issues with various comments.

Also add an assertion to min_element as our implementation does not work
correctly on empty ranges (which isn't a problem because it's never
called on empty ranges).
2026-06-12 13:56:50 -07:00
Arseny Kapoulkine 088551d068 Switch AppVeyor to a sparse build matrix (#729)
AppVeyor is dramatically slower than GHA, and after recent VS2026
addition it is approaching 30 minutes of build time. It tests multiple
configurations per VS version, many VS versions, and the builds are all
sequential due to free tier limitations.

This is becoming unsustainable and the cross-configuration/version build
problems are quite rare; additionally we do already test all of this for
the latest VS version on GHA.

So it is time to dramatically reorganize the build configuration by
making the matrix sparse: for each VS version we now only test *one*
manual cl run with an interleaving of architecture and configuration
selection, so that we hit every combination of arch-defines, and the
combinations are somewhat creatively chosen to still exercise commonly
seen configurations.
2026-06-12 10:27:49 -07:00
Arseny Kapoulkine 5a1c8f297a Update AppVeyor configuration for VS2026 (#718)
- Add VS2026 builds to Appveyor configuration
- Remove VS2013/VS2015 from Appveyor NuGet packages

VS2013/2015 are out of support according to
https://learn.microsoft.com/en-us/visualstudio/releases/2026/servicing-vs

Note that for now we still build and test pugixml itself for the older
VS versions; the removals here only apply to the NuGet package.
2026-06-12 08:19:57 -07:00
Arseny Kapoulkine 95ae857450 tests: Add another test for loading sysfs file for coverage
sysfs files have size reported as a page size, but the actual contents
tends to be short; this triggers the IO error in our file read path that
is otherwise very difficult to exercise as it's usually hit on genuine
IO errors.

On earlier kernels or Linux containers with partially mounted sysfs this
should just report file_not_found instead.
2026-06-03 16:04:13 -07:00
Arseny Kapoulkine 890fc20ea5 tests: Add more coverage tests for edge cases in the implementation
These cover a few extra error returns in the XPath query parser and an
edge case in the sort where one half is empty.

These are a little sensitive to the specific placement of nodes and AST
structure; they should hold regardless but may need to be adjusted to
keep coverage if the implementation changes.
2026-06-03 12:13:19 -07:00
Arseny Kapoulkine 3ebcd3e680 tests: Fix file level EOL
Fixes warnings on some compilers.
2026-06-03 10:34:00 -07:00
Arseny Kapoulkine 00577a903a Streamline dead code after recent optimizations
In attribute step_push, nodetest_name branch is now dead: it is
completely subsumed by the fast path for attribute/name axis. step_push
is called in three places; one has a fast path for nodetest_name, and
the other two only invoke nodetest_node case.

The assertion in get_mutable_buffer can't be hit reliably because of a
variety of zero checks along the call paths. It seems fully dead, but in
either case this should be a top-level function assertion as it results
in a stronger guarantee that includes mutable case too.
2026-06-03 10:08:36 -07:00
Arseny Kapoulkine 15a9ee72b5 tests: Add a test for late empty buffer handling
Normally empty inputs are now rejected early before we get further into
the parsing flow, but if the input becomes empty during internal size
adjustments (when the input is a one-byte buffer and pugixml is built
with PUGIXML_WCHAR_MODE and the input is marked as wchar-encoded), the
processing happens later.

The results should match whatever happens for empty inputs: ok if
fragment parsing is enabled, error otherwise.
2026-06-03 09:56:02 -07:00
Arseny Kapoulkine bfe4bb6b7f tests: Add extra coverage for some new functionality
- Whitespace/+ skipping in float parsing which is critical for PCDATA
- Optimized relational comparisons for attributes

Also add text.as_bool tests for the extra branch checks.
2026-06-02 09:43:19 -07:00
Arseny Kapoulkine b343fa9547 Merge pull request #727 from zeux/xpath-opt2
XPath: Accelerate child::name and attribute::name traversals
Optimize strequal by checking the first character inline
2026-06-02 08:10:57 -07:00
Arseny Kapoulkine 9426bd2ae3 XPath: Extract string_value implementation for elements (#728)
This is just extracting the existing code into a separate function and
converting it to work with xml_node_struct*; this streamlines the
codegen by removing a few redundant checks, and might make it easier to
optimize in the future.
2026-06-01 10:13:21 -07:00
Arseny Kapoulkine 4a0eda5395 Merge pull request #726 from zeux/xpath-opt
XPath: Optimize attribute selection via specialized node
2026-06-01 10:05:47 -07:00
Arseny Kapoulkine 6795caa34c XPath: Accelerate child::name and attribute::name traversals
Currently we use a general structure where step_fill calls step_push for
every node/attribute, and step_push does the relevant test. This is
necessary because both axis and test can be mixed arbitrarily, but this
results in extra overhead: step_push may not be inlined, and it has a
switch dispatch that we have to go through on every iteration.

Since child/attribute and name node test are by far the most prevalent
in real queries, we can add a fast-path that removes the switch dispatch
and directly traverses the children while checking their names; this,
then, is similar to existing loops that find children/attributes and
runs faster than our general dispatch.

Note that for attributes, axis_attribute/nodetest_name always has
once=true by construction.
2026-06-01 08:37:22 -07:00
Arseny Kapoulkine 02d1011bd4 Optimize strequal by checking the first character inline
While strcmp implementations are typically heavily optimized, invoking
strcmp has a cost, and some implementations (like glibc) use long prefix
matching via vectorized instructions. This is nice and optimal when the
strings do match, but in our case we often use strequal to skip
nodes/attributes by name.

Checking just the first character is safe, and while it's not always
profitable it often speeds up traversal appreciably, whether done via
XPath or via pugixml APIs. In typical loops that call strequal, this
adds a couple instructions for every successful match that terminates
the traversal, but often allows to skip strcmp calls for unsuccessful
matches so it's usually a net win.
2026-06-01 08:28:38 -07:00
Arseny Kapoulkine de31023032 XPath: Use direct attribute evaluation in relational comparisons
For @attr <rel> threshold comparisons, we currently evaluate @attr as a
node set; the previous optimization for ast_opt_select_attribute allowed
us to mostly skip these evaluations when the evaluation is done as a
string/number/boolean, but comparisons are generic and have complex
semantics: @attr <rel> threshold means "is there any object in the @attr
set that matches <rel> threshold".

For ast_opt_select_attribute though, we know the @attr set is either
empty or has the @attr attribute, so we can use the same shortcut and
evaluate the comparison directly.

While a similar case potentially exists for equality comparisons, they
are type-generic and this short cut is a little more tedious;
additionally, the common case there is probably @attr='value'/$value,
which is already fully specialized via ast_opt_compare_attribute.
2026-05-30 12:28:37 -07:00
Arseny Kapoulkine 6ee0d9645b XPath: Optimize attribute selection via specialized node
We already specialize attribute value comparison which allows to cut
short a lot of node set manipulation as well as a generic equality
comparison, but this only works for @attr='value' expressions.

When @attr is present in other cases, we can still get some extra
mileage by skipping node set manipulation if attribute is evaluated as a
non-nodeset. Additionally, the is_xpath_attribute check can be skipped
since the node test can be restricted ahead of time.

This also allows us to simplify matching for opt_compare_attribute, as
we would already have matched the attribute selection node beforehand.
2026-05-30 10:51:20 -07:00
Arseny Kapoulkine b6ee7a39be Merge pull request #725 from zeux/gcc16-warnfix
Work around GCC16 Wuninitialized occurence in xml_document::_move
2026-05-29 09:56:33 -07:00
Arseny Kapoulkine 0632188425 Merge pull request #717 from zeux/vs2026
Add VS2026 projects
2026-05-17 22:28:17 -07:00
Arseny Kapoulkine eeedba928a scripts: Add VS2026 packaging support for NuGet
Also update package description with the new versions.
2026-05-16 19:15:11 -07:00
Arseny Kapoulkine d7096f53e8 scripts: Add VS2026 projects
These were copied from VS2022 and upgraded to the new toolchain.
2026-05-16 19:12:43 -07:00
Arseny Kapoulkine 532c028fb4 Fix an edge case when copying xpath_variable_set
If the set that's being copied contains an unassigned string variable,
its value is NULL and attempting to set it asserts. Because the target
variable is freshly allocated, the copy is safe to skip in this case.
2026-05-16 09:29:41 -07:00
Arseny Kapoulkine c1faf38e62 docs: Assorted manual updates
- Fix "undefined" wording for conversions. The behavior is well
  specified for integer conversions and depends on CRT/STL for floats.
- Add mention of PUGIXML_CHARCONV_FLOAT to locale specific caution.
- We only use the long long type now and don't need CRT support.
- Expand the note on xpath_variable_set lifetime: assigning to the query
  is similar to destroying the query in this case
- Fix 1.15 release date year
2026-05-16 09:10:35 -07:00
Arseny Kapoulkine 1960dbc881 Merge pull request #716 from zeux/charconv-ci
Improve and test std::charconv integration
2026-05-16 08:45:36 -07:00
Arseny Kapoulkine 3a9e532a9f Add PUGIXML_CHARCONV_FLOAT to the build matrix
Since charconv requires C++17, we carve out cxxstd= make builds into a
separate job.

Also this requires Xcode 26 and GHA is on Xcode 16 so we'll need to wait
to enable this on macOS.
2026-05-15 14:11:30 -07:00
Arseny Kapoulkine aedf4dfed3 Improve std::charconv integration
- Handle to_chars error code; on error, result.ptr points to buffer end,
  so previously we'd return uninitialized stack data
- Explicitly do *not* handle from_chars error code; we need this to
  handle underflow/overflow on nice STL implementations
- Don't use std::begin/end as it may not have been included transitively

See https://isocpp.org/files/papers/P4168R0.html for underflow/overflow
details.
2026-05-15 14:11:30 -07:00
Arseny Kapoulkine 9de90bcb15 docs: Regenerate HTML manual after std::charconv change 2026-05-15 13:37:07 -07:00
nolangeandArseny Kapoulkine d69172513e Add a define to use charconv for float parsing/printing (#710)
When PUGIXML_CHARCONV_FLOAT is defined, we use std::charconv
instead of sprintf/strtod. This avoids using functions that pull in printf or locale,
and can result in smaller binaries and locale-independent behavior.

Note that this is not enabled in PUGIXML_WCHAR_MODE as charconv
only supports narrow characters.

Co-authored-by: Arseny Kapoulkine <arseny.kapoulkine@gmail.com>
2026-05-15 13:19:31 -07:00
Arseny Kapoulkine 86de7ff5a0 xml_node::first_element_by_path does not permit delimiter=0
This is an obviously-invalid situation, but to appease various forms of
static analysis we're going to assert that it is in fact invalid.

Closes #714
Closes #715
2026-05-15 12:15:45 -07:00
Arseny Kapoulkine 0595296e91 docs: Clarify xml_writer_stream usage with wide character streams
When using wide character streams, encoding_wchar should be specified
explicitly as the writer will expect wide inputs.

Fixes #713.
2026-05-15 00:38:30 -07:00
Arseny Kapoulkine 8b863f56ad Guard against integer overflow when attempting to load large files (#712)
This fixes two classes of possible integer overflows on 32-bit systems:

- Loading a large stream/file could sometimes result in integer overflow
  when computing the allocation size; the subsequent read/copy would
  attempt to fill ~4 GB of space and crash

- Loading a large (1+ GB) UTF8 document in PUGIXML_WCHAR_MODE would
  result in an integer overflow during wchar_t allocation; the
  subsequent decoding would attempt to fill ~4 GB of space and crash

In either case, we detect this early and return status_out_of_memory.
2026-05-14 07:50:31 -07:00
nolange 05fc589176 tests: Check PUGIXML_NO_STL after including config (#711)
The tests would not build before if PUGIXML_NO_STL was defined via `pugiconfig.hpp`.
2026-05-12 14:46:29 -07:00
Arseny Kapoulkine 6e1e723009 Treat nodes with a single PCDATA child as empty during output (#707)
When a node only has a single child with PCDATA set to empty, we no
longer output a separate start and end element tag, unless flag
format_no_empty_element_tags is used.

This makes the output shorter in some cases and is better for
roundtripping: as we never create empty PCDATA nodes during parsing,
saving this document and loading it again would result in no children.
With this, save(doc) matches save(load(save(doc))).
2026-05-11 10:10:22 -07:00
Sean McBride 9c1b438fe1 Fixed Clang -Wextra-semi-stmt warnings (#706)
Use do-while(0) idiom in several macros to enforce need for trailing semi-colon.
2026-04-23 15:30:51 -07:00
Arseny Kapoulkine e56134e6dd Silence Wsign-conversion under clang as it's enabled in Wconversion (#704)
This is not a problem for GCC which doesn't enable sign-conversion
warnings as part of Wconversion, but it's a problem for clang. These
warnings are noisy and do not mask any real bugs, so it's cleaner to
silence the warning.
2026-04-14 07:24:02 -07:00
Arseny Kapoulkine 058733a4bd tests: Add a test for stackless remove_child
This would have previously failed in some configurations due to a
recursive implementation.
2026-04-14 07:23:36 -07:00
Arseny Kapoulkine ec81c66a09 Use stackless traversal for tree destruction to avoid stack overflow
For very deep trees that can be parsed using our stackless parser,
attempts to remove the relevant nodes may cause a stack overflow due to
deep recursion.

Instead, use a stackless traversal; this is a little different from
other traversals we already have in the library, as it needs to process
each node *after* the entire subtree to avoid accessing destroyed
memory.

This is part of a new destroy_tree function; destroy_node now only
destroys the node's attributes/name/value.
2026-04-14 07:23:36 -07:00
Arseny Kapoulkine 5c52ce0319 Add PUGIXML_INSTALL_SOURCE CMake option to install pugixml.cpp (#705)
This is necessary for header-only builds to work together with
installation and might be useful elsewhere.
2026-04-14 07:22:58 -07:00
Arseny Kapoulkine 59ec7856c0 Use GCC attribute aligned(1) for utfN_decoder::type (#703)
This makes sure that the input memory can be unaligned; in
convert_buffer paths, we don't have a guarantee that the input data is
aligned to be able to read uint16/32. On some platforms like ARMv6/7
this might cause alignment faults depending on the compiler codegen.
2026-04-14 07:22:32 -07:00
Alexander RyabykinandArseny Kapoulkine 59f944c467 Add inline variable support (external linkage for const vars) (#581)
Co-authored-by: Arseny Kapoulkine <arseny.kapoulkine@gmail.com>
2026-04-13 08:54:55 -07:00
Arseny Kapoulkine 3070fb6320 Merge pull request #697 from jgressma/fixes-for-bcc
Fixes for Embacadero's XE5 compiler
2026-03-16 10:39:18 -07:00
Jean Gressmann aa50e2914a Build fix attemp 2026-03-16 07:29:57 +01:00
Jean Gressmann 984551e432 Fixes for Embacadero's XE5 compiler 2026-03-16 07:14:12 +01:00
Arseny Kapoulkine 710052066c Update copyright year to 2026 2026-01-02 09:58:14 -08:00
Arseny Kapoulkine 61c944895e docs: Fix typo in comment
The remove_attribute call removes 'value' attribute; 'id' attribute is
removed later in the sample.

Fixes #684.
2025-09-01 14:45:30 -07:00
Arseny Kapoulkine e86ffc5b47 Merge pull request #683 from sankhesh/global_ctor
Remove global constructor from pugixml
2025-08-25 17:48:12 -07:00
Sankhesh Jhaveri 706982acd6 Remove global constructor from pugixml
This avoids any consumers of pugixml from seeing an unwanted global.
2025-08-25 17:05:12 -04:00
Arseny Kapoulkine 5a1892b321 Fix minor stylistic/"analysis" nits
- Explicitly ignore strcpy_insitu return value in node_copy_string; if it
fails, we must be out of memory and we leave the relevant destination
fields empty, similarly to other OOMs during copying

- Use the same code for eval_number of string/node set; these are slightly
different semantically, as eval_string is an implicit conversion, but the
code ends up the same.

Closes #674, #675.
2025-05-15 12:13:30 +03:00
Thrita c4cca93ad1 PUGIXML_BUILD_APPLE_FRAMEWORK now includes framework headers (#655) 2025-05-07 22:11:31 +03:00
Arseny Kapoulkine b0801735cd Merge pull request #672 from mosfet80/patch-1
Update build.yml to fix node deprecation warnings
2025-04-24 08:07:32 -07:00
mosfet80 390515a31b Update build.yml
Update default runtime to node20 (fix node deprecation warning)
2025-04-24 09:54:53 +02:00
Arseny Kapoulkine 657c33ae34 XPath: Silence static analysis false positive
klockworks reports that var->name() may be NULL; it can never be NULL
for a valid variable, but this check costs us nothing to add so we might
as well add it.
2025-04-17 10:48:19 -07:00
Arseny Kapoulkine 3cdb7f4ae2 Coverity Scan fixes and adjustments
- In remove_duplicates, `sizeof(void**)` was used improperly for
  allocation and memsetting instead of `void*`; these are equivalent but
  the extra pointer is redundant.

- Remove `var_deref_model` silencing annotation, as it is now redundant
  due to changes in 709ba74b24
2025-04-17 10:39:52 -07:00
Arseny Kapoulkine caade5a28a Merge pull request #665 from bilbothebaggins/master
#659 License Info Cleanup
2025-03-03 11:19:30 -08:00
Arseny Kapoulkine 7144cc453d Adjust comment structure slightly 2025-03-03 11:07:08 -08:00
bilbothebaggins 11090789b4 #659 License Info Cleanup
Added SPDX Headers; moved pugxml Public Domain reference to README.md
2025-03-02 10:39:08 +01:00
Arseny Kapoulkine 066b6583a4 Merge pull request #664 from zeux/emptybuf
Early out in load_buffer for empty inputs to avoid allocations
2025-02-19 09:33:22 -08:00
Arseny Kapoulkine 709ba74b24 Early out in load_buffer for empty inputs to avoid allocations
Previously, calling xml_document::load_string on an empty buffer
resulted in a single byte allocation for the buffer copy; this
allocation was redundant as no data was parsed, so we now add the same
early-out that already exists in xml_parser::parse to load_buffer_impl.
2025-02-19 08:19:28 -08:00
Arseny Kapoulkine a340834408 Update upload-artifact to v4 to fix build due to deprecation 2025-02-16 08:24:54 -08:00
Arseny Kapoulkine 8f17faf1ca Merge pull request #663 from luzpaz/typo
docs: fix typo
2025-02-16 08:20:28 -08:00
Luz Paz 762abf1c57 docs: fix typo
Found via `codespell -q 3 -D ../dictionary.txt -L parametere,thirdparty`
2025-02-16 09:08:02 -05:00
Arseny Kapoulkine a305d01bc8 Merge pull request #662 from e-kwsm/virtual
style: remove redundant 'virtual' for the 'override'-specified functions
2025-01-26 13:41:23 -08:00
Eisuke Kawashima 081e8a3227 style: remove redundant 'virtual' for the 'override'-specified functions 2025-01-25 11:06:11 +09:00
Arseny Kapoulkine 9d7fcbf741 docs: Update quickstart guide after version update 2025-01-10 11:22:25 -08:00
Arseny Kapoulkine ee86beb30e scripts: Remove -appveyor version prefix from NuGet packages
This was originally intended as a safety measure to avoid mixing
packages built via AppVeyor vs packages built via other means, but this
just creates friction because of the need to edit the version field
before publishing the package.
2025-01-10 10:15:31 -08:00
Arseny Kapoulkine e7ed748b02 Update library version to 1.15 and update docs 2025-01-10 08:48:52 -08:00
Arseny Kapoulkine b299231ff7 Update copyright year to 2025 2025-01-10 07:31:00 -08:00
Treata 06318b084a Add support for Apple framework builds (#653)
Add CMake option PUGIXML_BUILD_APPLE_FRAMEWORKS to build PugiXML as Apple Frameworks.

This is needed to be able to create iOS-derived compatible app bundles which need to embed PugiXML as framework, as using dylibs is prohibited by Apple.
2025-01-02 11:11:51 -08:00
Arseny Kapoulkine 4bc14418d1 Merge pull request #650 from hughsie/hughsie/sbom
Add a SBOM template in CycloneDX format
2024-11-29 08:04:18 -08:00
Richard Hughes 752afbf4df Add a SBOM template in CycloneDX format
Improve supply chain security by including a SBOM file with substituted values.

This will be used to construct a composite platform SBOM.

Signed-off-by: Richard Hughes <richard@hughsie.com>
2024-11-26 18:07:45 +00:00
Arseny Kapoulkine 8c3038f9c8 Update CMake version to 3.5...3.30
This should retain compatibility with earlier version of CMake and suppress
the deprecation warning for quite some time.
2024-11-17 08:25:06 +09:00
Arseny Kapoulkine f1f532acfc docs: Reword last bullet point of thread safety guarantees
This was worded somewhat confusingly; we should be explicit that it's
okay to access multiple documents concurrently as long as access to each
one is serialized.
2024-11-05 07:43:54 -08:00
Arseny Kapoulkine 3480faa837 Merge pull request #642 from zeux/string-view-def
Auto-detect std::string_view support by default
2024-11-04 10:20:38 -08:00
Arseny Kapoulkine 0f22f71f60 CMake now uses C++17 if supported by the compiler
We only set this when C++ version or requirement flag is not overridden
externally to be able to rely on CMake automatically downgrading the
standard version when the compiler doesn't support it.

CXX_STANDARD 17 also requires CMake 3.8 or later; on earlier versions we
use the old behavior and set C++11.
2024-10-30 14:18:39 -07:00
Arseny Kapoulkine 781e2dbe5d Merge pull request #643 from zeux/cmake-test
Enhance CMake testing in CI
2024-10-30 14:10:26 -07:00
Arseny Kapoulkine f1f1b4e0dd Add basic CMake testing to AppVeyor
To reduce build time impact we just do a quick smoke test (configure &
build).
2024-10-30 13:27:13 -07:00
Arseny Kapoulkine 25b508056c Add unix-cmake test to GHA
To not inflate the build matrix too much, just use the default settings;
we mostly need this to test the CMake flow, not to test the actual code.
2024-10-30 13:02:56 -07:00
Arseny Kapoulkine ae163d5f06 Enable C++17 support in VS2019 and VS2022 projects
This enables std::string_view support for NuGet builds
2024-10-30 11:46:36 -07:00
Arseny Kapoulkine af6cbeb170 Enable C++17 standard in AppVeyor tests
To avoid increasing the build matrix we enable this unconditionally for
VS2019 and VS2022 to be able to test std::string_view. Note that we
already test VS2022 without this flag on GHA so this should catch any
regressions.
2024-10-30 11:25:17 -07:00
Arseny Kapoulkine d5f14adb3c docs: Update documentation to address PUGIXML_HAS_STRING_VIEW changes
The PUGIXML_STRING_VIEW define is no longer necessary but
_HAS_STRING_VIEW can be enabled manually if the compiler supports it
without advertising C++17 support.
2024-10-30 10:36:36 -07:00
Arseny Kapoulkine ca4f7cfecc Auto-detect std::string_view support by default
Instead of opting in std::string_view support via PUGIXML_STRING_VIEW
define, always enable it when C++17 is supported; this still requires
enabling C++17 support in the compiler, which this change doesn't
attempt to do yet.
2024-10-30 10:31:49 -07:00
dantargz 4d0043fb6c Update VERSION in Makefile and add documentation for string_view_t (#641)
We now document PUGIXML_HAS_STRING_VIEW and PUGIXML_STRING_VIEW (the latter will be removed in the future) configuration as well as string_view_t type and overloads.

Makefile also had to be fixed to recognize the version properly after pugixml.hpp changes.
2024-10-28 08:06:42 -07:00
Arseny Kapoulkine 2729d80c94 Makefile now defaults to cxxstd=any (#639)
This means that by default we inherit the default language version
supported by the compiler; this will help with string_view testing
in the future as it will "just work" out of the box once the define is
set.

This should also automatically enable CI coverage for string_view; C++11
is still explicitly tested in CI via cxxstd=c++11.
2024-10-28 08:05:36 -07:00
Arseny Kapoulkine 23e617b158 Warn if PUGIXML_STRING_VIEW is set without CMAKE_CXX_STANDARD (#638)
Even if the compiler supports C++17, we define CMAKE_CXX_STANDARD as 11
by default which implicitly disables string_view support; for now warn
in this case.
2024-10-26 10:20:06 -07:00
dantargz 13beda24b8 Add remaining std::string_view overloads (#636)
Add remaining overloads and supporting unit tests. This concludes the initial phase of std::string_view support; for now the support is still opt-in via PUGIXML_STRING_VIEW define, but that will become unnecessary (enabled-by-default) in a future version.
2024-10-24 14:10:09 -07:00
Arseny Kapoulkine 7e702740ff Merge pull request #623 from r-barnes/master
throw() -> noexcept
2024-10-22 18:59:45 -07:00
Arseny Kapoulkine d713fd2315 Define PUGIXML_NOEXCEPT as throw()
This is necessary to avoid gcc warnings for exception::what()
2024-10-22 13:36:47 -07:00
dantargz a0db6e2185 Initial support for std::string_view (#633)
When PUGIXML_STRING_VIEW define is set and C++17 is available, add std::string_view support to a few functions. In the future, string view support will be enabled without the need for an extra define, but for now the support is opt-in to reduce compatibility risks.

PR is based on initial contribution by @brandl-muc.
2024-10-22 13:31:54 -07:00
Arseny Kapoulkine 3b17184379 docs: Work around asciidoc bug with TOC numbering
For some reason using a code import right before a header breaks
numbering on that header; fix by moving the import above text.
2024-09-12 09:49:35 -07:00
Richard Barnes 6247ece208 throw() -> noexcept 2024-07-16 06:48:23 -07:00
Arseny Kapoulkine 30cc354fe3 Merge pull request #621 from aral-matrix/master
xmldocument::save: use encoding interpreted by get_write_encoding in buffered_writer constructor
2024-07-08 09:35:57 -07:00
aral-matrix 2039e448cf use encoding interpreted by get_write_encoding in buffered_writer constructor 2024-07-07 11:19:52 +02:00
Arseny Kapoulkine 2d42114ed1 Merge pull request #620 from zeux/nostl-warnfix
Work around 'unreferenced function' warnings in NO_STL builds
2024-07-06 08:55:52 -07:00
Arseny Kapoulkine c691c6b401 Work around 'unreferenced function' warnings in NO_STL builds
Normally, as_utf8_begin et al are used in STL functions but when STL is
disabled, these are only used if the target platform lacks first class
support for wchar_t FILE* APIs. With some warning levels we consequently
can get warnings about these functions not being referenced.

Not defining these in the first place is difficult because of the
complexity of the selection logic for open_file_wide so for now just
mark these as unused. The strange (void)& syntax is needed for MSVC to
not trigger another warning...

The workaround is narrowly scoped to avoid unforeseen compatibility issues.

Fixes #619.
2024-07-05 15:43:55 -07:00
Arseny Kapoulkine ac0ef854e0 Clarify comments for xml_*::empty()
"empty" can be mistaken for "has no children" in case of xml_node in
particular; we now use both empty and null in the comment in hopes that
it may help.
2024-05-28 20:39:08 -07:00
Arseny Kapoulkine 7c66cf7b06 docs: Add C++20 ranges documentation
This doesn't require any implementation changes, as the existing support
for C++11 ranged for loops automatically makes nodes and node/attribute
range objects work as C++20 ranges.

Fixes #613.
2024-05-19 13:24:34 -07:00
Arseny Kapoulkine f1d8c51ec8 Merge pull request #611 from kmilos/patch-1
Relative and absolute paths for a relocatable pkgconf file
2024-03-23 09:44:03 -07:00
Miloš Komarčević 08e38a4c14 Relative and absolute paths for a relocatable pkgconf file 2024-03-22 14:05:43 +01:00
Miloš Komarčević 6ab3fa418b Update pugixml.pc.in 2024-03-22 14:00:34 +01:00
Arseny Kapoulkine b2b4664030 docs: Adjust docs wrt parse_merge_pcdata x parse_embed_pcdata
parse_merge_pcdata expects to find node_pcdata nodes which aren't
present when parse_embed_pcdata is active. For now we mention this in
the documentation; changing this is possible in the future, but carries
a small performance penalty so it requires a specific use case.

Fixes #600
2024-01-26 09:23:26 -08:00
Arseny Kapoulkine 3cc2daf449 Update year to 2024 everywhere
... except .html files that will be regenerated later.
2024-01-26 09:18:48 -08:00
Arseny Kapoulkine 96aebcb8ae Merge pull request #604 from zeux/ndk-warnfix
Fix -Wshorten-64-to-32 warning on Android NDK when targeting x86
2023-12-23 10:48:31 -08:00
Arseny Kapoulkine 86591a97c3 Extract length validation and conversion function into a templated function
Since there's no reasonable way for us to figure out what the type of
stat::st_size is on Android NDK without resorting to C++11 auto /
non-standard decltype extensions, we're going to resort to a templated
function that can deduce the length type. The rest of the validation and
conversion logic is preserved as is.
2023-12-23 09:30:57 -08:00
Arseny Kapoulkine 8fef4591be Fix -Wshorten-64-to-32 warning on Android NDK when targeting x86
stat.h defines struct stat to use long long on Android NDK when
targeting x86; off_t however is defined as long, which is 32-bit (unlike
other Unix-like platforms). This results in a narrowing conversion which
produces a warning, and can also result in silently reading a prefix of
a huge file instead of a clean "out of memory" error.

There's no way for us to preserve the type exactly but always widening
to long long should be safe; get_file_size will proceed to check if
length actually fits into size_t which is what we ultimately need, and
that overflow check will fail on files that are >4 GB in size.
2023-12-20 11:19:42 -08:00
Arseny Kapoulkine cf466ce2a2 Merge pull request #595 from zeux/stl-defarg
Use cleaner references to STL classes
2023-11-16 12:42:22 -08:00
Arseny Kapoulkine 499750ad95 Merge pull request #596 from zeux/appvmp
AppVeyor build optimizations
2023-11-16 12:32:28 -08:00
Arseny Kapoulkine cd420ab193 Use make -j2 for mingw builds on AppVeyor 2023-11-16 12:12:56 -08:00
Arseny Kapoulkine d99aa003ba Restrict AppVeyor builds to master branch
This avoids duplicate builds on PRs submitted from a branch in the same
repository.
2023-11-16 12:09:18 -08:00
Arseny Kapoulkine 1e3d6f15f5 tests: Add /MP to AppVeyor builds to try to reduce build time 2023-11-16 11:27:40 -08:00
Arseny Kapoulkine 2e8a2a4e1c tests: Work around -Wself-move in new gcc
We do want to test self-move; fortunately, hiding the object reference
behind a separate pointer variable silences the warning.
2023-11-16 10:54:53 -08:00
Arseny Kapoulkine 0bd2848f33 Use cleaner references to STL classes
The explicit specification of default template arguments is repetitive
and dates back to the versions of pugixml that tried to forward-declare
all STL classes manually, which ran into issues with default arguments
in some STL versions.

We've since abandoned this idea and use <string>/<iosfwd> includes, as
such it should be fine to rely on default arguments.

Note: while we could use std::wstring, this had compatibility issues
with some very early versions of Android SDK. Out of abundance of
caution, we keep basic_i/ostream and basic_string in tact. We could use
std::string but we might need to replace these in char8 mode if that
ever gets merged.
2023-11-16 10:51:20 -08:00
Arseny Kapoulkine 43d7d568a7 Merge pull request #594 from SoapGentoo/Wuseless-cast
Fix `-Wuseless-cast`
2023-11-14 07:13:09 -08:00
David Seifert 44236fef2c Fix -Wuseless-cast 2023-11-13 20:53:44 -08:00
Arseny Kapoulkine 6909df2478 Merge pull request #590 from zeux/sanfuzz
Update config=sanitize and fuzz targets
2023-10-22 11:18:08 -07:00
Arseny Kapoulkine b15bc6bf1f Update config=sanitize and fuzz targets
We used to need to silence float-divide-by-zero and float-cast-overflow
sanitizers since clang used a finite valid floating point value range.
Fortunately, since clang-9 UBSAN properly handles various primitive
operations per IEEE-754 so we no longer need this workaround.

Also use fork=16 mode for fuzz targets to make it easier to run fuzzing
locally.
2023-10-22 10:07:52 -07:00
Arseny Kapoulkine 33f709379a Merge pull request #551 from silvergasp/master
fuzzer: excersizes query code on xml doc
2023-10-21 12:29:22 -07:00
Arseny Kapoulkine 4d42ba7a60 Update fuzz_xpath.cpp
Remove unused variables
2023-10-21 11:20:03 -07:00
Arseny Kapoulkine d75a081aa3 Update fuzz_xpath.cpp
Fix code style, no exceptions, other tweaks.
2023-10-21 11:11:11 -07:00
Arseny Kapoulkine 1ade1d4bea Merge pull request #586 from PhilipBotha/fix/nullptr_const_zero
Replaced 0 with PUGIXML_NULL when a nullptr would have been needed.
2023-10-19 19:21:08 -07:00
Arseny Kapoulkine 94b19a3c45 Fix indentation changes 2023-10-15 19:25:56 -07:00
Arseny Kapoulkine 76dec417a6 Silence -Wzero-as-null-pointer-constant for clang
clang does not handle NULL the same way as gcc, so for now we silence
the warning.
2023-10-15 19:19:36 -07:00
Arseny Kapoulkine 6699559320 Replace 0 with NULL for some MSVC-specific code 2023-10-15 19:17:37 -07:00
Arseny Kapoulkine dab3a2f858 Replace 0 with NULL for compact and wchar mode specific code 2023-10-15 19:13:34 -07:00
Arseny Kapoulkine 60d9656cb7 Replace PUGIXML_NULL with NULL and fix a couple extra stragglers 2023-10-15 19:10:34 -07:00
Philip 08b966e24f Fixed zero as nullptr constant in macro.
Removed white space that was changed.
2023-10-14 09:06:20 +02:00
Arseny Kapoulkine 2e357d19a3 Merge pull request #585 from ilya-lavrenov/install-rules
Added cmake option to disable install rules
2023-10-13 20:14:59 -07:00
Philip Botha b138778fd9 Replaced 0 with PUGIXML_NULL when appropriate.
Added the suffix UZ to size_t.

Added fixed GCC warning about using const literal zero in place of nullptr (-Wzero-as-null-pointer-constant).
2023-10-12 15:49:18 +02:00
Ilya Lavrenov 3cfe51b72d Added cmake option to disable install rules 2023-10-12 02:15:05 +04:00
Arseny Kapoulkine ef856bf975 Merge pull request #584 from richardapeters/master
build: only include CTest when building the pugixml tests
2023-10-06 06:14:27 -07:00
Richard Peters efce4a8d7a Remove BUILD_TESTING as prerequisite for the PUGIXML_BUILD_TESTS; it was always set by including CTest, now CTest is conditionally included later on 2023-10-06 10:02:15 +02:00
Richard Peters a468d5c438 Only include CTest when building the pugixml tests 2023-10-06 09:51:29 +02:00
Arseny Kapoulkine db78afc2b7 Update version to 1.14 everywhere 2023-09-07 11:55:13 -07:00
Arseny Kapoulkine bd70bd7662 docs: Update release notes and regenerate HTML documentation
The large amount of changes seems to be due to asciidoctor now omitting
empty spans in formatted code.
2023-09-07 11:52:15 -07:00
Arseny Kapoulkine 1a9a41b0f4 Update copyright year (2022 => 2023) 2023-09-06 20:39:25 -07:00
Arseny Kapoulkine 1118066f0b Merge pull request #576 from vineethkuttan/Merge-pcdata-#546
Implement parse_merge_pcdata
2023-09-06 08:01:56 -07:00
Arseny Kapoulkine ff56985924 Rename merged to merged_pcdata for clarity. 2023-09-06 07:54:14 -07:00
Arseny Kapoulkine 30adb1713b Use memmove instead of strcat
strcat does not allow overlapping ranges; we didn't have a test for this
but now we do.

As an added bonus, this also means we only compute the length of each
fragment once now.
2023-09-05 22:43:55 -07:00
Arseny Kapoulkine 58616a29aa Avoid store-load penalty on cursor->parent
This reclaims the performance lost in PCDATA reorganization and gains a
little more on top of that.
2023-09-05 22:23:31 -07:00
Arseny Kapoulkine dfb2b7f7b4 Cache ~last position of merged PCDATA
This allows us to fix the quadratic complexity of parse_merge_pcdata.
After parsing the first PCDATA we need to advance by its length; we
still compute the length of each fragment twice with this approach, but
it's constant time.
2023-09-05 21:34:02 -07:00
Arseny Kapoulkine efb76c1128 docs: Update external XPath links
Both w3schools tutorial and the W3C spec have changed their URLs; I
don't think we actually need the second tutorial so we can simply drop
that one.
2023-08-28 21:26:09 -07:00
Arseny Kapoulkine bf42c4c568 Reorder set_value/set size_t overloads and change sz to size
This makes the source order and naming match documentation.
2023-08-26 08:41:37 -07:00
Arseny Kapoulkine 5a33d2b1d7 docs: Add forgotten set_name overloads to API reference 2023-08-26 08:38:42 -07:00
Arseny Kapoulkine e9d17a045e Streamline conditions with else if 2023-08-26 08:35:40 -07:00
Arseny Kapoulkine 08a5048f15 Merge pull request #537 from stefanroellin/size-t-overloads
Add overloads with size_t type argument
2023-08-26 08:27:34 -07:00
Stefan Roellin f4d4316eba Add overloads with size_t type argument
* bool xml_attribute::set_name(const char_t* rhs, size_t sz)
* bool xml_node::set_name(const char_t* rhs, size_t sz)
2023-08-26 11:30:49 +02:00
Arseny Kapoulkine 6749789ec4 Fix interaction between parse_merge_pcdata and append_buffer
strconcat in the parsing loop only works if we know the source string
comes from the same buffer that we're parsing. This is somewhat
cumbersome to establish during parsing and it requires extra tracking
data, so we just disable this combination as it's unlikely to be
actually useful - usually append_buffer would be called on a possibly
empty collection of elements, not on something with PCDATA.
2023-08-25 19:32:42 -07:00
Arseny Kapoulkine f31ad2c1ab tests: Add more tests for parse_merge_pcdata
Add tests for double escape and a test for interaction with
parse_ws_pcdata flags; this behavior might change but we should pin the
current result.

Also slightly clean up the previously added test.
2023-08-25 19:20:23 -07:00
Arseny Kapoulkine 37ba937e05 Fix code style and simplify conditions
prev_sibling_c is never NULL so it should be safe to check first_child
instead, which ensures we may the minumum cost when the feature isn't
enabled.
2023-08-25 18:57:06 -07:00
Arseny Kapoulkine 0189471a3a docs: Fix up grammar 2023-08-25 18:48:32 -07:00
Arseny Kapoulkine c72a210ff7 tests: Add more tests for empty text setup
Here we also test what happens when text gets assigned to an empty
string after initially being non-empty, to make sure this is not
different from the initial state.
2023-08-25 18:15:36 -07:00
Vineeth 3ad133a2ad Review Changes
i)Indentation added
ii)Optimal parsing ensured
2023-08-23 08:12:57 +05:30
vineeth-11316 a28252205a Final Commit 2023-08-20 10:21:26 +05:30
vineeth-11316 068aa22b1a documentation Change 2023-08-19 09:54:01 +05:30
vineeth-11316 e15adbe704 Intial Commit for merge_pcdata 2023-08-19 09:17:54 +05:30
Arseny Kapoulkine 980cf57ff4 XPath: Account for non-English locales during number->string conversion
We use a special number formatting routine to generate the XPath
REC-compliant number representation; it relies on being able to get a
decimal representation of the source number, which we use sprintf for as
a fallback.

This is fairly insensitive to current locale, except for an assertion
that validates the decimal point as a precaution, and this check
triggers when the locale decimal point is not a dot.

Ideally we'd use a locale-insensitive routine here. On some systems we
have ecvt_r (similarly to MSVC's ecvt_s), but it's deprecated so
adopting it might be fraught with peril.

For now let's simply adjust the assertion to account for locales with
comma as a separator. This is probably not fully comprehensive but
probably gets us from a 90% solution to a 99% solution...

Fixes #574.
2023-07-27 09:24:10 -07:00
Arseny Kapoulkine 187cf6b5a5 Merge pull request #573 from asmaloney/min-cmake-version
{cmake} Fix deprecation warning by updating min version to 3.5
2023-07-19 21:30:01 -07:00
Andy Maloney b047f46e2c {cmake} Fix deprecation warning by updating min version to 3.5
With CMake 3.27, we get a deprecation warning:

"Compatibility with CMake < 3.5 will be removed from a future version of CMake.
Update the VERSION argument <min> value or use a ...<max> suffix to tell
CMake that the project does not need compatibility with older versions."

Bump min version to 3.5 to remove warning.
2023-07-19 09:20:14 -04:00
Arseny Kapoulkine f75dc6dd10 Merge pull request #566 from ArchXUser/master
Fix compilation errors on old GCC (2.95.3, 3.3.5)
2023-05-10 19:55:43 -07:00
Sergey Abramov 1e9636303e Fix compilation errors on old GCC (2.95.3, 3.3.5) 2023-05-11 09:04:22 +07:00
Arseny Kapoulkine 80a531ee1d Merge pull request #563 from zeux/cmake-oof
build: Fix CMake PUGIXML_STATIC_CRT behavior
2023-04-22 08:01:01 -07:00
Arseny Kapoulkine 8d18de8f46 Merge pull request #550 from asmaloney/fix-weak-vtable-warning
Fix weak vtable warning regarding xml_writer
2023-04-21 15:59:19 -07:00
Andy Maloney 058fc601a1 Fix weak vtable warning regarding xml_writer
Using Apple clang (clang-1400.0.29.202) with `-Wweak-vtables` would produce the following warning:

'xml_writer' has no out-of-line virtual method definitions; its vtable will be emitted in every translation unit [-Wweak-vtables]
2023-04-21 17:23:38 -04:00
Arseny Kapoulkine 750e20323b build: Fix CMake PUGIXML_STATIC_CRT behavior
Implementation of PUGIXML_STATIC_CRT for newer CMake versions (3.15+)
depend on MSVC_RUNTIME_LIBRARY, but this only works if the policy
is defined *before* the project.
2023-04-21 13:24:59 -07:00
Arseny Kapoulkine f4b89469b3 Merge pull request #561 from zeux/file-size
Fix get_file_size behavior inconsistency for folders
2023-04-21 12:52:17 -07:00
Arseny Kapoulkine a13b5cc08d Use stricter subset for now to avoid compat issues with Unix-like platforms 2023-04-15 13:41:15 -07:00
Arseny Kapoulkine d3199a0c39 Fix get_file_size behavior inconsistency for folders
Different OSes have different behavior when trying to fopen/fseek/ftell
a folder. On Linux, some systems return 0 size, some systems return an
error, and some systems return LONG_MAX. LONG_MAX is particularly
problematic because that causes spurious OOMs under address sanitizer.

Using fstat manually cleans this up, however it introduces a new
dependency on platform specific headers that we didn't have before, and
also has unclear behavior on 64-bit systems wrt 32-bit sizes which will
need to be tested further as I'm not certain if the behavior needs to be
special-cased only for MSVC/MinGW, which are currently not handled by
this path (unless MinGW defines __unix__...)
2023-04-15 12:48:59 -07:00
Arseny Kapoulkine e383ce5d82 docs: Update HTML documentation 2023-03-19 15:41:31 -07:00
Arseny Kapoulkine 02930331f8 docs: Add a note to parse_fragment documentation
Fixes #554
2023-03-19 15:41:12 -07:00
Arseny Kapoulkine a469fa2cfc Add assertion about header-dest relation to strcpy_insitu
May improve static analysis behavior for #555.
2023-03-19 14:57:10 -07:00
Arseny Kapoulkine 544b0a49eb Merge pull request #559 from SoapGentoo/fix-Wreserved-macro-identifier
Fix `-Wreserved-macro-identifier`
2023-03-19 10:37:20 -07:00
David Seifert 36aa487e9c Fix -Wreserved-macro-identifier
* https://eel.is/c++draft/lex.name#3.1
  "Each identifier that contains a double underscore __ [...] is reserved to the implementation for any use."
2023-03-19 17:10:53 +01:00
Arseny Kapoulkine 8a679cfe78 Merge pull request #557 from jiangqucheng/master
#556 fix makefile err in some env
2023-03-16 19:03:14 -07:00
jiangqucheng ddd3cfa4bf #556 fix makefile err in some env 2023-03-16 05:05:16 +00:00
Nathaniel Brough 9d8d193288 tests: excersizes query code on xml doc 2023-03-09 17:46:23 -08:00
Arseny Kapoulkine c2c61a5905 Add a cautionary comment to xml_node::children(name)
Fixes #538
2023-01-23 09:37:11 -08:00
Arseny Kapoulkine 95683943bb Merge pull request #533 from DavidKorczynski/cifuzz-int
Add Github CIFuzz action
2022-11-21 11:15:36 +01:00
David Korczynski 7e8a42ee31 CI: decrease fuzzing time from 300s to 30s
Signed-off-by: David Korczynski <david@adalogics.com>
2022-11-20 14:42:49 -08:00
David Korczynski 5cfa7f90f1 Add Github CIFuzz action
Signed-off-by: David Korczynski <david@adalogics.com>
2022-11-18 15:40:54 -08:00
Arseny Kapoulkine 1dc3266fff docs: Add missing documentation for xml_node::attribute with hint
The feature was added in 2015 but somehow was never documented.
2022-11-08 16:49:34 -08:00
Arseny Kapoulkine cb217f5a85 Merge pull request #530 from zeux/snprintf
Fix Xcode 14 sprintf deprecation warning
2022-11-06 15:09:53 -08:00
Arseny Kapoulkine e11e0c965f Fix comment typo. 2022-11-06 13:47:53 -08:00
Arseny Kapoulkine b6b747244e Adjust the workaround for -pedantic mode and fix tests 2022-11-06 10:21:35 -08:00
Arseny Kapoulkine 8be081fbbe Fix Xcode 14 sprintf deprecation warning
We use snprintf when stdc is set to C++11, however in C++98 mode we can't use variadic macros,
and Xcode 14 complains about the use of sprintf.

It should be safe however to use variadic macros on any remotely recent version of clang on Apple,
unless -pedantic is defined which warns against the use of variadic macros in C++98 mode...

This change fixes the problem for the builds that don't specify -pedantic, which is a problem for
another day.
2022-11-06 10:16:21 -08:00
Arseny Kapoulkine a0e0643363 Merge pull request #526 from zeux/newver
Prepare for 1.13 release
2022-10-28 16:53:25 -07:00
Arseny Kapoulkine 3bd1f452b5 Fix version check in test 2022-10-20 20:23:26 -07:00
Arseny Kapoulkine c5b288d91a Update HTML documentation 2022-10-20 20:20:45 -07:00
Arseny Kapoulkine 0ef3da1e6e Update release notes and manual for 1.13
This includes a previously unnoticed link fix for xml_text::set
2022-10-20 20:18:08 -07:00
Arseny Kapoulkine 76dcd89427 Update version number in preparation for 1.13 2022-10-20 20:08:52 -07:00
Arseny Kapoulkine 43ef7e25d9 Merge pull request #525 from bruxisma/master
Fix exported symbols under clang-cl (Closes #503)
2022-10-20 19:49:48 -07:00
Izzy Muerte ab8af53059 Fix exported symbols under clang-cl (Closes #503)
This also turns the define for PUGIXML_API into an `$<IF:>`, instead of an
`$<IF:>` with an empty true condition. If this is inadequate, I will
undo it, and place them on separate lines as they were before, but will
most likely use an inverse `$<NOT:>` instead of an `$<IF:>`.
2022-10-20 13:35:49 -07:00
Arseny Kapoulkine 86c9105154 Merge pull request #523 from zeux/ferrh
Fix error handling in xml_document::save_file
2022-10-09 09:08:50 -07:00
Arseny Kapoulkine 444963e269 Fix error handling in xml_document::save_file
There were two conditions under which xml_document::save_file could
previously return true even though the saving failed:

- The last write to the file was buffered in stdio buffer, and it's that
  last write that would fail due to lack of disk space
- The data has been written correctly but fclose failed to update file
  metadata, which can result in truncated size / missing inode updates.

This change fixes both by adjusting save_file to fflush before the check,
and also checking fclose results. Note that while fflush here is
technically redundant, because it's implied by fclose, we must check
ferror explicitly anyway, and so it feels a little cleaner to do most of
the error handling in save_file_impl, so that the changes of fclose()
failing are very slim.

Of course, neither change guarantees that the contents of the file are
going to be safe on disk following a power failure.
2022-10-07 22:13:04 -07:00
Arseny Kapoulkine 0cb4f02579 Final tweaks after #522
This cleans up xml_attribute::set_value to be uniform wrt
xml_node::set_value and xml_text::set_value - for now we duplicate the
body since the logic is trivial and this keeps debug performance
excellent.
2022-10-07 21:46:27 -07:00
Arseny Kapoulkine c342266fae Merge pull request #522 from Ferenc-/followup-on-pr-490
Followup on pr 490
2022-10-07 21:42:41 -07:00
Ferenc Géczi 39e169285c Add test for xml_attribute::set_value with size argument 2022-09-29 00:00:00 +00:00
Ferenc Géczi 1905284494 Add test for xml_node::set_value with size argument 2022-09-29 00:00:00 +00:00
Ferenc Géczi d359402311 Add xml_text::set test with size set to substring 2022-09-29 00:00:00 +00:00
Ferenc Géczi 09e7cc9b1c Add test for xml_text::set with size argument 2022-09-29 00:00:00 +00:00
Ferenc Géczi f327371219 Add overloads with size_t type argument
* xml_node::set_value(const char_t* rhs, size_t sz)
* xml_text::set(const char_t* rhs, size_t sz)

Signed-off-by: Ferenc Géczi <ferenc.gm@gmail.com>
2022-09-29 18:26:05 +00:00
Arseny Kapoulkine bcf483c3b7 Merge pull request #492 from KDAB/fix-default-visibility
Correctly set default visibility on non-windows compilers
2022-09-27 12:53:06 -07:00
Milian Wolff 173a263490 Correctly set default visibility on non-windows compilers
This fixes compilation of pugixml with -fvisibility=hidden. Without
this patch, one would get lots of unresolved symbols when consuming
pugixml as a shared library.
2022-09-25 11:37:48 +02:00
Arseny Kapoulkine 521b2cd854 Add issue templates to try to route questions to Discussions 2022-09-02 21:42:25 -07:00
Arseny Kapoulkine 27bc68ab45 Merge pull request #506 from brandl-muc/nullptr_for_msvc
Enable usage of nullptr for MSVC 16 and newer (MSVS 2010)
2022-08-04 08:46:13 -07:00
Matthäus Brandl f7de324855 Enable usage of nullptr for MSVC 16 and newer (MSVS 2010) 2022-08-04 16:59:37 +02:00
Arseny Kapoulkine 3b5c1fb022 tests: Fix MSVC 2005 build
... I forgot we still support platforms without C99, 23 years later.
2022-07-21 21:17:17 -07:00
Arseny Kapoulkine ab8453c572 tests: Use snprintf instead of sprintf
sprintf now results in a deprecation warning in Xcode 14 beta.
2022-07-21 20:51:26 -07:00
Arseny Kapoulkine 2639dfd053 Merge pull request #477 from zeux/compactopt
Optimize compact mode
2022-05-31 20:00:01 -05:00
Arseny Kapoulkine 0401559dde Merge pull request #498 from zeux/fix-oom-safer
Fix memory leak during OOM in convert_buffer
2022-05-16 20:50:07 -07:00
Arseny Kapoulkine 832a4f4914 Use more idiomatic code in this codebase 2022-05-16 19:14:29 -07:00
Arseny Kapoulkine 33a75c734b Fix memory leak during OOM in convert_buffer
This is the same fix as #497, but we're using auto_deleter instead
because if allocation function throws, we can't rely on an explicit call
to deallocate.

Comes along with two tests that validate the behavior.
2022-05-16 19:12:52 -07:00
Arseny Kapoulkine ec851bb18d Merge pull request #497 from TodorHryn/master
Fix memory leak
2022-05-16 19:05:29 -07:00
TodorHryn 6fbf32140b Fix memory leak 2022-05-16 13:21:20 +03:00
Viktor Govako effc46f0ed Added bool set_value(const char_t* rhs, size_t sz). 2022-04-13 12:25:01 +03:00
Arseny Kapoulkine 363ebdde91 Merge pull request #482 from zeux/fix-msvc-test
tests: Fix MSVC 2022 build
2022-02-15 21:12:03 -08:00
Arseny Kapoulkine c60ca94cdd 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.
2022-02-15 20:23:05 -08:00
Arseny Kapoulkine dd50fa5b45 Fix PUGIXML_VERSION macro
Also make sure the line shows up in grep when using the current version
number.

Fixes #478.
2022-02-10 08:36:19 -08:00
Arseny Kapoulkine 2fa9158b4f Optimize compact mode: xml_text 2022-02-08 23:04:31 -08:00
Arseny Kapoulkine fad2d5e4ef Optimize compact mode: xml_attribute/xml_node implementation 2022-02-08 23:00:17 -08:00
Arseny Kapoulkine f388c465dd Optimize compact mode: reuse access in insert/remove 2022-02-08 22:44:31 -08:00
48 changed files with 5842 additions and 2845 deletions
+8
View File
@@ -0,0 +1,8 @@
---
name: Bug report
about: Create a report if you believe you've found a bug in this project; please use GitHub Discussions instead if you think the bug may be in your code.
title: ''
labels: bug
assignees: ''
---
+5
View File
@@ -0,0 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: Help and support
url: https://github.com/zeux/pugixml/discussions
about: Please use GitHub Discussions if you have questions or need help.
@@ -0,0 +1,8 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: enhancement
assignees: ''
---
+37 -5
View File
@@ -12,35 +12,60 @@ jobs:
matrix:
os: [ubuntu, macos]
compiler: [g++, clang++]
defines: [standard, PUGIXML_WCHAR_MODE, PUGIXML_COMPACT, PUGIXML_NO_EXCEPTIONS]
defines: [standard, PUGIXML_WCHAR_MODE, PUGIXML_COMPACT, PUGIXML_NO_EXCEPTIONS, PUGIXML_CHARCONV_FLOAT]
exclude:
- os: macos
compiler: g++
- os: macos
defines: PUGIXML_CHARCONV_FLOAT # std::charconv is not supported until Xcode 26
name: ${{matrix.os}} (${{matrix.compiler}}, ${{matrix.defines}})
runs-on: ${{matrix.os}}-latest
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v4
- name: make test
if: matrix.defines != 'PUGIXML_CHARCONV_FLOAT' # std::charconv requires C++17, tested below
run: |
export CXX=${{matrix.compiler}}
make test cxxstd=c++11 defines=${{matrix.defines}} config=release -j2
make test cxxstd=c++98 defines=${{matrix.defines}} config=debug -j2
make test cxxstd=c++17 defines=${{matrix.defines}} config=debug -j2
make test defines=${{matrix.defines}} config=sanitize -j2
- name: make test charconv
if: matrix.defines == 'PUGIXML_CHARCONV_FLOAT'
run: |
export CXX=${{matrix.compiler}}
make test cxxstd=c++17 defines=${{matrix.defines}} config=sanitize -j2
- name: make coverage
if: ${{!(matrix.os == 'ubuntu' && matrix.compiler == 'clang++')}} # linux/clang produces coverage info gcov can't parse
run: |
export CXX=${{matrix.compiler}}
make test defines=${{matrix.defines}} config=coverage -j2
make test cxxstd=c++17 defines=${{matrix.defines}} config=coverage -j2
bash <(curl -s https://codecov.io/bash) -f pugixml.cpp.gcov -X search -t ${{secrets.CODECOV_TOKEN}} -B ${{github.ref}}
unix-cmake:
strategy:
matrix:
os: [ubuntu, macos]
name: ${{matrix.os}} cmake
runs-on: ${{matrix.os}}-latest
steps:
- uses: actions/checkout@v4
- name: cmake configure
run: |
mkdir cmake && cd cmake
cmake .. -D PUGIXML_BUILD_TESTS=ON
- name: cmake test
run: |
make -C cmake -j2
windows:
runs-on: windows-latest
strategy:
matrix:
arch: [Win32, x64]
defines: [standard, PUGIXML_WCHAR_MODE, PUGIXML_COMPACT, PUGIXML_NO_EXCEPTIONS]
defines: [standard, PUGIXML_WCHAR_MODE, PUGIXML_COMPACT, PUGIXML_NO_EXCEPTIONS, PUGIXML_CHARCONV_FLOAT]
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v4
- name: cmake configure
run: cmake . -DPUGIXML_BUILD_TESTS=ON -D${{matrix.defines}}=ON -A ${{matrix.arch}}
- name: cmake test
@@ -50,3 +75,10 @@ jobs:
Debug/pugixml-check.exe
cmake --build . -- -property:Configuration=Release -verbosity:minimal
Release/pugixml-check.exe
- name: cmake configure (c++17)
run: cmake . -DPUGIXML_BUILD_TESTS=ON -DCMAKE_CXX_STANDARD=17 -D${{matrix.defines}}=ON -A ${{matrix.arch}}
- name: cmake test (c++17)
shell: bash # necessary for fail-fast
run: |
cmake --build . -- -property:Configuration=Debug -verbosity:minimal
Debug/pugixml-check.exe
+24
View File
@@ -0,0 +1,24 @@
name: CIFuzz
on: [pull_request]
jobs:
Fuzzing:
runs-on: ubuntu-latest
steps:
- name: Build Fuzzers
id: build
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
with:
oss-fuzz-project-name: 'pugixml'
dry-run: false
- name: Run Fuzzers
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
with:
oss-fuzz-project-name: 'pugixml'
fuzz-seconds: 30
dry-run: false
- name: Upload Crash
uses: actions/upload-artifact@v4
if: failure() && steps.build.outcome == 'success'
with:
name: artifacts
path: ./out/artifacts
+4 -1
View File
@@ -1,2 +1,5 @@
/build/
/build*/
/.vscode/
.DS_Store
+127 -55
View File
@@ -1,10 +1,15 @@
cmake_minimum_required(VERSION 3.4)
project(pugixml VERSION 1.12 LANGUAGES CXX)
cmake_minimum_required(VERSION 3.5...3.30)
# Policy configuration; this *MUST* be specified before project is defined
if(POLICY CMP0091)
cmake_policy(SET CMP0091 NEW) # Enables use of MSVC_RUNTIME_LIBRARY
endif()
project(pugixml VERSION 1.16 LANGUAGES CXX)
include(CMakePackageConfigHelpers)
include(CMakeDependentOption)
include(GNUInstallDirs)
include(CTest)
cmake_dependent_option(PUGIXML_USE_VERSIONED_LIBDIR
"Use a private subdirectory to install the headers and libraries" OFF
@@ -20,23 +25,37 @@ cmake_dependent_option(PUGIXML_STATIC_CRT
cmake_dependent_option(PUGIXML_BUILD_TESTS
"Build pugixml tests" OFF
"BUILD_TESTING;CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF)
"CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF)
# Custom build defines
set(PUGIXML_BUILD_DEFINES CACHE STRING "Build defines for custom options")
separate_arguments(PUGIXML_BUILD_DEFINES)
# Public headers
set(PUGIXML_HEADERS
${PROJECT_SOURCE_DIR}/src/pugiconfig.hpp
${PROJECT_SOURCE_DIR}/src/pugixml.hpp
)
set(PUGIXML_SOURCE ${PROJECT_SOURCE_DIR}/src/pugixml.cpp)
# Technically not needed for this file. This is builtin CMAKE global variable.
option(BUILD_SHARED_LIBS "Build shared instead of static library" OFF)
option(BUILD_SHARED_LIBS "Build shared instead of static library" OFF)
# Expose option to build PUGIXML as static as well when the global BUILD_SHARED_LIBS variable is set
cmake_dependent_option(PUGIXML_BUILD_SHARED_AND_STATIC_LIBS
"Build both shared and static libraries" OFF
"BUILD_SHARED_LIBS" OFF)
option(PUGIXML_INSTALL "Enable installation rules" ON)
cmake_dependent_option(PUGIXML_INSTALL_SOURCE
"Install pugixml.cpp alongside headers" OFF
"PUGIXML_INSTALL" OFF)
# Expose options from the pugiconfig.hpp
option(PUGIXML_WCHAR_MODE "Enable wchar_t mode" OFF)
option(PUGIXML_COMPACT "Enable compact mode" OFF)
option(PUGIXML_CHARCONV_FLOAT "Enable charconv number conversion" OFF)
# Advanced options from pugiconfig.hpp
option(PUGIXML_NO_XPATH "Disable XPath" OFF)
@@ -44,17 +63,18 @@ option(PUGIXML_NO_STL "Disable STL" OFF)
option(PUGIXML_NO_EXCEPTIONS "Disable Exceptions" OFF)
mark_as_advanced(PUGIXML_NO_XPATH PUGIXML_NO_STL PUGIXML_NO_EXCEPTIONS)
# Policy configuration
if(POLICY CMP0091)
cmake_policy(SET CMP0091 NEW) # Enables use of MSVC_RUNTIME_LIBRARY
if (APPLE)
option(PUGIXML_BUILD_APPLE_FRAMEWORK "Build as Apple Frameworks" OFF)
endif()
set(PUGIXML_PUBLIC_DEFINITIONS
$<$<BOOL:${PUGIXML_WCHAR_MODE}>:PUGIXML_WCHAR_MODE>
$<$<BOOL:${PUGIXML_COMPACT}>:PUGIXML_COMPACT>
$<$<BOOL:${PUGIXML_CHARCONV_FLOAT}>:PUGIXML_CHARCONV_FLOAT>
$<$<BOOL:${PUGIXML_NO_XPATH}>:PUGIXML_NO_XPATH>
$<$<BOOL:${PUGIXML_NO_STL}>:PUGIXML_NO_STL>
$<$<BOOL:${PUGIXML_NO_EXCEPTIONS}>:PUGIXML_NO_EXCEPTIONS>)
$<$<BOOL:${PUGIXML_NO_EXCEPTIONS}>:PUGIXML_NO_EXCEPTIONS>
)
# This is used to backport a CMake 3.15 feature, but is also forwards compatible
if (NOT DEFINED CMAKE_MSVC_RUNTIME_LIBRARY)
@@ -62,11 +82,13 @@ if (NOT DEFINED CMAKE_MSVC_RUNTIME_LIBRARY)
MultiThreaded$<$<CONFIG:Debug>:Debug>$<$<NOT:$<BOOL:${PUGIXML_STATIC_CRT}>>:DLL>)
endif()
if (NOT DEFINED CMAKE_CXX_STANDARD_REQUIRED)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
endif()
# Set the default C++ standard to C++17 if not set; CMake will automatically downgrade this if the compiler does not support it
# When CMAKE_CXX_STANDARD_REQUIRED is set, we fall back to C++11 to avoid breaking older compilers
if (NOT DEFINED CMAKE_CXX_STANDARD_REQUIRED AND NOT DEFINED CMAKE_CXX_STANDARD AND NOT CMAKE_VERSION VERSION_LESS 3.8)
if (NOT DEFINED CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED OFF)
elseif (NOT DEFINED CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 11)
endif()
@@ -98,9 +120,14 @@ set(libs)
if (BUILD_SHARED_LIBS)
add_library(pugixml-shared SHARED
${PROJECT_SOURCE_DIR}/scripts/pugixml_dll.rc
${PROJECT_SOURCE_DIR}/src/pugixml.cpp)
${PUGIXML_SOURCE}
${PUGIXML_HEADERS})
add_library(pugixml::shared ALIAS pugixml-shared)
list(APPEND libs pugixml-shared)
string(CONCAT pugixml.msvc $<OR:
$<STREQUAL:${CMAKE_CXX_COMPILER_FRONTEND_VARIANT},MSVC>,
$<CXX_COMPILER_ID:MSVC>
>)
set_property(TARGET pugixml-shared PROPERTY EXPORT_NAME shared)
target_include_directories(pugixml-shared
@@ -111,18 +138,24 @@ if (BUILD_SHARED_LIBS)
${PUGIXML_BUILD_DEFINES}
${PUGIXML_PUBLIC_DEFINITIONS}
PRIVATE
$<$<CXX_COMPILER_ID:MSVC>:PUGIXML_API=__declspec\(dllexport\)>)
PUGIXML_API=$<IF:${pugixml.msvc},__declspec\(dllexport\),__attribute__\(\(visibility\("default"\)\)\)>
)
target_compile_options(pugixml-shared
PRIVATE
${msvc-rt-mtd-shared}
${msvc-rt-mtd-static}
${msvc-rt-mt-shared}
${msvc-rt-mt-static})
target_compile_features(pugixml-shared
PRIVATE
$<$<BOOL:${PUGIXML_CHARCONV_FLOAT}>:cxx_std_17>
)
endif()
if (NOT BUILD_SHARED_LIBS OR PUGIXML_BUILD_SHARED_AND_STATIC_LIBS)
add_library(pugixml-static STATIC
${PROJECT_SOURCE_DIR}/src/pugixml.cpp)
${PUGIXML_SOURCE}
${PUGIXML_HEADERS})
add_library(pugixml::static ALIAS pugixml-static)
list(APPEND libs pugixml-static)
@@ -140,6 +173,10 @@ if (NOT BUILD_SHARED_LIBS OR PUGIXML_BUILD_SHARED_AND_STATIC_LIBS)
${msvc-rt-mtd-static}
${msvc-rt-mt-shared}
${msvc-rt-mt-static})
target_compile_features(pugixml-static
PRIVATE
$<$<BOOL:${PUGIXML_CHARCONV_FLOAT}>:cxx_std_17>
)
endif()
if (BUILD_SHARED_LIBS)
@@ -165,6 +202,23 @@ set_target_properties(${libs}
EXCLUDE_FROM_ALL OFF)
set(install-targets pugixml ${libs})
if (PUGIXML_BUILD_APPLE_FRAMEWORK)
set_target_properties(${libs} PROPERTIES
FRAMEWORK TRUE
FRAMEWORK_VERSION ${PROJECT_VERSION}
XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "com.github.zeux.pugixml"
XCODE_ATTRIBUTE_INSTALL_PATH "@rpath"
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY ""
XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO"
XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO"
PUBLIC_HEADER "${PUGIXML_HEADERS}"
MACOSX_FRAMEWORK_IDENTIFIER "com.github.zeux.pugixml"
MACOSX_FRAMEWORK_BUNDLE_VERSION ${PROJECT_VERSION}
MACOSX_FRAMEWORK_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}
MACOSX_RPATH TRUE
)
endif()
configure_package_config_file(
"${PROJECT_SOURCE_DIR}/scripts/pugixml-config.cmake.in"
"${PROJECT_BINARY_DIR}/pugixml-config.cmake"
@@ -186,54 +240,72 @@ if (PUGIXML_USE_POSTFIX)
endif()
endif()
# Handle both relative and absolute paths (e.g. NixOS) for a relocatable package
if(IS_ABSOLUTE "${CMAKE_INSTALL_INCLUDEDIR}")
set(PUGIXML_PC_INCLUDEDIR "${CMAKE_INSTALL_INCLUDEDIR}")
else()
set(PUGIXML_PC_INCLUDEDIR "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}")
endif()
if(IS_ABSOLUTE "${CMAKE_INSTALL_LIBDIR}")
set(PUGIXML_PC_LIBDIR "${CMAKE_INSTALL_LIBDIR}")
else()
set(PUGIXML_PC_LIBDIR "\${exec_prefix}/${CMAKE_INSTALL_LIBDIR}")
endif()
configure_file(scripts/pugixml.pc.in pugixml.pc @ONLY)
if (NOT DEFINED PUGIXML_RUNTIME_COMPONENT)
set(PUGIXML_RUNTIME_COMPONENT Runtime)
endif()
if (NOT DEFINED PUGIXML_LIBRARY_COMPONENT)
set(PUGIXML_LIBRARY_COMPONENT Library)
endif()
if (NOT DEFINED PUGIXML_DEVELOPMENT_COMPONENT)
set(PUGIXML_DEVELOPMENT_COMPONENT Development)
endif()
set(namelink-component)
if (NOT CMAKE_VERSION VERSION_LESS 3.12)
set(namelink-component NAMELINK_COMPONENT ${PUGIXML_DEVELOPMENT_COMPONENT})
endif()
install(TARGETS ${install-targets}
EXPORT pugixml-targets
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${PUGIXML_RUNTIME_COMPONENT}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT ${PUGIXML_LIBRARY_COMPONENT} ${namelink-component}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT ${PUGIXML_DEVELOPMENT_COMPONENT}
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}${versioned-dir})
install(EXPORT pugixml-targets
export(TARGETS ${install-targets}
NAMESPACE pugixml::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/pugixml COMPONENT ${PUGIXML_DEVELOPMENT_COMPONENT})
FILE pugixml-targets.cmake)
export(EXPORT pugixml-targets
NAMESPACE pugixml::)
if(PUGIXML_INSTALL)
if (NOT DEFINED PUGIXML_RUNTIME_COMPONENT)
set(PUGIXML_RUNTIME_COMPONENT Runtime)
endif()
install(FILES
"${PROJECT_BINARY_DIR}/pugixml-config-version.cmake"
"${PROJECT_BINARY_DIR}/pugixml-config.cmake"
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/pugixml COMPONENT ${PUGIXML_DEVELOPMENT_COMPONENT})
if (NOT DEFINED PUGIXML_LIBRARY_COMPONENT)
set(PUGIXML_LIBRARY_COMPONENT Library)
endif()
install(FILES ${PROJECT_BINARY_DIR}/pugixml.pc
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig COMPONENT ${PUGIXML_DEVELOPMENT_COMPONENT})
if (NOT DEFINED PUGIXML_DEVELOPMENT_COMPONENT)
set(PUGIXML_DEVELOPMENT_COMPONENT Development)
endif()
install(
FILES
"${PROJECT_SOURCE_DIR}/src/pugiconfig.hpp"
"${PROJECT_SOURCE_DIR}/src/pugixml.hpp"
DESTINATION
${CMAKE_INSTALL_INCLUDEDIR}${versioned-dir} COMPONENT ${PUGIXML_DEVELOPMENT_COMPONENT})
set(namelink-component)
if (NOT CMAKE_VERSION VERSION_LESS 3.12)
set(namelink-component NAMELINK_COMPONENT ${PUGIXML_DEVELOPMENT_COMPONENT})
endif()
install(TARGETS ${install-targets}
EXPORT pugixml-targets
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${PUGIXML_RUNTIME_COMPONENT}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT ${PUGIXML_LIBRARY_COMPONENT} ${namelink-component}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT ${PUGIXML_DEVELOPMENT_COMPONENT}
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}${versioned-dir}
FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT runtime OPTIONAL
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
install(EXPORT pugixml-targets
NAMESPACE pugixml::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/pugixml COMPONENT ${PUGIXML_DEVELOPMENT_COMPONENT})
install(FILES
"${PROJECT_BINARY_DIR}/pugixml-config-version.cmake"
"${PROJECT_BINARY_DIR}/pugixml-config.cmake"
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/pugixml COMPONENT ${PUGIXML_DEVELOPMENT_COMPONENT})
install(FILES ${PROJECT_BINARY_DIR}/pugixml.pc
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig COMPONENT ${PUGIXML_DEVELOPMENT_COMPONENT})
install(FILES ${PUGIXML_HEADERS}
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}${versioned-dir} COMPONENT ${PUGIXML_DEVELOPMENT_COMPONENT})
if (PUGIXML_INSTALL_SOURCE)
install(FILES ${PUGIXML_SOURCE}
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}${versioned-dir} COMPONENT ${PUGIXML_DEVELOPMENT_COMPONENT})
endif()
endif()
if (PUGIXML_BUILD_TESTS)
include(CTest)
set(fuzz-pattern "tests/fuzz_*.cpp")
set(test-pattern "tests/*.cpp")
if (CMAKE_VERSION VERSION_GREATER 3.11)
+1 -1
View File
@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2006-2022 Arseny Kapoulkine
Copyright (c) 2006-2026 Arseny Kapoulkine
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
+5 -6
View File
@@ -3,15 +3,14 @@ MAKEFLAGS+=-r
config=debug
defines=standard
cxxstd=c++11
# set cxxstd=any to disable use of -std=...
cxxstd=any
BUILD=build/make-$(CXX)-$(config)-$(defines)-$(cxxstd)
BUILD=build/make-$(firstword $(CXX))-$(config)-$(defines)-$(cxxstd)
SOURCES=src/pugixml.cpp $(filter-out tests/fuzz_%,$(wildcard tests/*.cpp))
EXECUTABLE=$(BUILD)/test
VERSION=$(shell sed -n 's/.*version \(.*\).*/\1/p' src/pugiconfig.hpp)
VERSION=$(shell sed -n 's/.*version \(.*\).*/\1/p; /version/q' src/pugiconfig.hpp)
RELEASE=$(filter-out scripts/archive.py docs/%.adoc,$(shell git ls-files docs scripts src CMakeLists.txt LICENSE.md readme.txt))
CXXFLAGS=-g -Wall -Wextra -Werror -pedantic -Wundef -Wshadow -Wcast-align -Wcast-qual -Wold-style-cast -Wdouble-promotion
@@ -27,7 +26,7 @@ ifeq ($(config),coverage)
endif
ifeq ($(config),sanitize)
CXXFLAGS+=-fsanitize=address,undefined -fno-sanitize=float-divide-by-zero,float-cast-overflow -fno-sanitize-recover=all
CXXFLAGS+=-fsanitize=address,undefined -fno-sanitize-recover=all
LDFLAGS+=-fsanitize=address,undefined
endif
@@ -66,7 +65,7 @@ endif
fuzz_%: $(BUILD)/fuzz_%
@mkdir -p build/$@
$< build/$@ tests/data_fuzz_$* -max_len=1024 -dict=tests/fuzz_$*.dict
$< build/$@ tests/data_fuzz_$* -max_len=1024 -dict=tests/fuzz_$*.dict -fork=16
clean:
rm -rf $(BUILD)
+9
View File
@@ -70,3 +70,12 @@ int main()
## License
This library is available to anybody free of charge, under the terms of MIT License (see LICENSE.md).
This work is based on the pugxml parser, which carried the following Public Domain dedication:
// Pug XML Parser - Version 1.0002
// --------------------------------------------------------
// Copyright (C) 2003, by Kristen Wegner (kristen@tima.net)
// Released into the Public Domain. Use at your own risk.
// See pugxml.xml for further information, history, etc.
// Contributions by Neville Franks (readonly@getsoft.com).
+33 -8
View File
@@ -1,4 +1,9 @@
branches:
only:
- master
image:
- Visual Studio 2026
- Visual Studio 2022
- Visual Studio 2019
- Visual Studio 2017
@@ -6,20 +11,40 @@ image:
version: "{branch}-{build}"
for:
- matrix:
only:
- image: Visual Studio 2026
install:
- pip install --upgrade cmake
build_script:
- ps: if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2013") { .\scripts\nuget_build.ps1 2013}
- 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}
- ps: if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2026") { .\scripts\nuget_build.ps1 2026}
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" }
- ps: if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2015") { .\tests\cmake-appveyor.ps1 9 2008 }
- ps: if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2015") { .\tests\cmake-appveyor.ps1 12 2013 }
- ps: if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2015") { .\tests\cmake-appveyor.ps1 14 2015 }
- ps: if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2017") { .\tests\cmake-appveyor.ps1 15 2017 }
- ps: if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2019") { .\tests\cmake-appveyor.ps1 16 2019 }
- ps: if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2022") { .\tests\cmake-appveyor.ps1 17 2022 }
- ps: if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2026") { .\tests\cmake-appveyor.ps1 18 2026 }
- ps: if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2015") { .\tests\autotest-appveyor.ps1 9 x86 standard }
- ps: if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2015") { .\tests\autotest-appveyor.ps1 10 x64 standard }
- ps: if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2015") { .\tests\autotest-appveyor.ps1 11 x86 PUGIXML_WCHAR_MODE }
- ps: if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2015") { .\tests\autotest-appveyor.ps1 12 x64 PUGIXML_COMPACT }
- ps: if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2015") { .\tests\autotest-appveyor.ps1 14 x64 standard }
- ps: if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2017") { .\tests\autotest-appveyor.ps1 15 x86 standard }
- ps: if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2019") { .\tests\autotest-appveyor.ps1 19 x86 PUGIXML_COMPACT }
- ps: if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2022") { .\tests\autotest-appveyor.ps1 22 x64 PUGIXML_WCHAR_MODE }
- ps: if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2026") { .\tests\autotest-appveyor.ps1 26 x64 standard }
- 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 -j2 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 -j2 config=coverage defines=PUGIXML_WCHAR_MODE test && bash <(curl -s https://codecov.io/bash) -f pugixml.cpp.gcov 2>&1" }
artifacts:
- path: .\scripts\*.nupkg
+266 -69
View File
@@ -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-2022 Arseny Kapoulkine
Copyright (c) 2006-2026 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-2022 Arseny Kapoulkine.
pugixml is Copyright (C) 2006-2026 Arseny Kapoulkine.
....
[[install]]
@@ -116,16 +116,6 @@ The repository contains library source, documentation, code examples and full un
Use `latest` tag if you want to automatically get new versions. Use other tags if you want to switch to new versions only explicitly. Also please note that the master branch contains the work-in-progress version of the code; while this means that you can get new features and bug fixes from master without waiting for a new release, this also means that occasionally the code can be broken in some configurations.
[[install.getting.subversion]]
==== Subversion repository
You can access the Git repository via Subversion using https://github.com/zeux/pugixml URL. For example, to checkout the current version, you can use this command:
[source,bash,subs="attributes"]
----
svn checkout https://github.com/zeux/pugixml/tags/v{version} pugixml
----
[[install.getting.packages]]
==== Packages
@@ -133,10 +123,11 @@ pugixml is available as a package via various package managers. Note that most p
Here's an incomplete list of pugixml packages in various systems:
* Linux (http://packages.ubuntu.com/search?keywords=pugixml[Ubuntu], https://tracker.debian.org/pkg/pugixml[Debian], https://apps.fedoraproject.org/packages/pugixml[Fedora], https://aur.archlinux.org/packages/pugixml/[Arch Linux], other http://pkgs.org/search/pugixml[distributions])
* http://fbsdmon.org/ports/textproc/pugixml[FreeBSD]
* OSX, via http://brewformulas.org/Pugixml[Homebrew]
* Windows, via https://www.nuget.org/packages/pugixml/[NuGet]
* Linux (http://packages.ubuntu.com/search?keywords=pugixml[Ubuntu], https://tracker.debian.org/pkg/pugixml[Debian], https://packages.fedoraproject.org/pkgs/pugixml/pugixml[Fedora], https://archlinux.org/packages/extra/x86_64/pugixml/[Arch Linux], other https://pkgs.org/download/pugixml[distributions])
* https://www.freshports.org/textproc/pugixml[FreeBSD]
* OSX, via https://formulae.brew.sh/formula/pugixml[Homebrew]
* Windows, via https://www.nuget.org/packages/pugixml[NuGet]
* C{plus}{plus} package managers (https://vcpkg.io/en/package/pugixml[vcpkg], https://conan.io/center/recipes/pugixml[Conan])
[[install.building]]
=== Building pugixml
@@ -228,6 +219,8 @@ pugixml uses several defines to control the compilation process. There are two w
[[PUGIXML_WCHAR_MODE]]`PUGIXML_WCHAR_MODE` define toggles between UTF-8 style interface (the in-memory text encoding is assumed to be UTF-8, most functions use `char` as character type) and UTF-16/32 style interface (the in-memory text encoding is assumed to be UTF-16/32, depending on `wchar_t` size, most functions use `wchar_t` as character type). See <<dom.unicode>> for more details.
[[PUGIXML_CHARCONV_FLOAT]]`PUGIXML_CHARCONV_FLOAT` will use https://en.cppreference.com/cpp/header/charconv[<charconv>] for floating-point number formatting instead of `<stdio.h>` functions, which requires C++17 and UTF-8 interface. Note that the conversion will then ignore the locale and always act as if the default `C` locale is used.
[[PUGIXML_COMPACT]]`PUGIXML_COMPACT` define activates a different internal representation of document storage that is much more memory efficient for documents with a lot of markup (i.e. nodes and attributes), but is slightly slower to parse and access. For details see <<dom.memory.compact>>.
[[PUGIXML_NO_XPATH]]`PUGIXML_NO_XPATH` define disables XPath. Both XPath interfaces and XPath implementation are excluded from compilation. This option is provided in case you do not need XPath functionality and need to save code space.
@@ -244,16 +237,18 @@ NOTE: In that example `PUGIXML_API` is inconsistent between several source files
[[PUGIXML_HAS_LONG_LONG]]`PUGIXML_HAS_LONG_LONG` define enables support for `long long` type in pugixml. This define is automatically enabled if your platform is known to have `long long` support (i.e. has C{plus}{plus}11 support or uses a reasonably modern version of a known compiler); if pugixml does not recognize that your platform supports `long long` but in fact it does, you can enable the define manually.
[[PUGIXML_HAS_STRING_VIEW]]`PUGIXML_HAS_STRING_VIEW` define enables function overloads that accept `std::string_view` arguments. This define is automatically enabled if built targeting C{plus}{plus}17 or later; if pugixml does not recognize that your platform supports `std::string_view` but in fact it does, you can enable the define manually.
[[install.portability]]
=== Portability
pugixml is written in standard-compliant C{plus}{plus} with some compiler-specific workarounds where appropriate. pugixml is compatible with the C{plus}{plus}11 standard, but does not require C{plus}{plus}11 support. Each version is tested with a unit test suite with code coverage exceeding 99%.
pugixml is written in standard-compliant C{plus}{plus} with some compiler-specific workarounds where appropriate. pugixml can be compiled with any version of the C{plus}{plus} standard starting from C{plus}{plus}98; newer standards automatically enable additional functionality (move semantics and range-based for support in C{plus}{plus}11, `std::string_view` overloads in C{plus}{plus}17). Each version is tested with a unit test suite with code coverage exceeding 99%.
pugixml runs on a variety of desktop platforms (including Microsoft Windows, Linux, FreeBSD, Apple MacOSX and Sun Solaris), game consoles (inclusing Microsoft Xbox 360, Microsoft Xbox One, Nintendo Wii, Sony Playstation Portable and Sony Playstation 3) and mobile platforms (including Android, iOS, BlackBerry, Samsung bada and Microsoft Windows CE).
pugixml runs on a variety of desktop platforms (including Microsoft Windows, Linux, FreeBSD, Apple MacOSX and Sun Solaris), game consoles (including Microsoft Xbox 360, Microsoft Xbox One, Nintendo Wii, Sony Playstation Portable and Sony Playstation 3) and mobile platforms (including Android, iOS, BlackBerry, Samsung bada and Microsoft Windows CE).
pugixml supports various architectures, such as x86/x86-64, PowerPC, ARM, MIPS and SPARC. In general it should run on any architecture since it does not use architecture-specific code and does not rely on features such as unaligned memory access.
pugixml can be compiled using any C++ compiler; it was tested with all versions of Microsoft Visual C{plus}{plus} from 6.0 up to 2015, GCC from 3.4 up to 5.2, Clang from 3.2 up to 3.7, as well as a variety of other compilers (e.g. Borland C{plus}{plus}, Digital Mars C{plus}{plus}, Intel C{plus}{plus}, Metrowerks CodeWarrior and PathScale). The code is written to avoid compilation warnings even on reasonably high warning levels.
pugixml can be compiled using any C++ compiler; it was tested with all versions of Microsoft Visual C{plus}{plus} from 6.0 up to 2026, GCC from 3.4 up to 16, Clang from 3.2 up to 21, as well as a variety of other compilers (e.g. Borland C{plus}{plus}, Digital Mars C{plus}{plus}, Intel C{plus}{plus}, Metrowerks CodeWarrior and PathScale). The code is written to avoid compilation warnings even on reasonably high warning levels.
Note that some platforms may have very bare-bones support of C++; in some cases you'll have to use `PUGIXML_NO_STL` and/or `PUGIXML_NO_EXCEPTIONS` to compile without issues. This mostly applies to old game consoles and embedded systems.
@@ -270,7 +265,7 @@ The XML document is represented with a tree data structure. The root of the tree
[[xml_node_type]]
The tree nodes can be of one of the following types (which together form the enumeration `xml_node_type`):
* Document node ([[node_document]]`node_document`) - this is the root of the tree, which consists of several child nodes. This node corresponds to <<xml_document,xml_document>> class; note that <<xml_document,xml_document>> is a sub-class of <<xml_node,xml_node>>, so the entire node interface is also available. However, document node is special in several ways, which are covered below. There can be only one document node in the tree; document node does not have any XML representation. Document generally has one child element node (see [[xml_document::document_element]]`document_element()`), although documents parsed from XML fragments (see [[parse_fragment]]`parse_fragment`) can have more than one.
* Document node ([[node_document]]`node_document`) - this is the root of the tree, which consists of several child nodes. This node corresponds to <<xml_document,xml_document>> class; note that <<xml_document,xml_document>> is a sub-class of <<xml_node,xml_node>>, so the entire node interface is also available. However, document node is special in several ways, which are covered below. There can be only one document node in the tree; document node does not have any XML representation. Document generally has one child element node (see <<xml_document::document_element,document_element()>>), although documents parsed from XML fragments (see <<parse_fragment,parse_fragment>>) can have more than one.
* Element/tag node ([[node_element]]`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:
+
@@ -419,8 +414,8 @@ const wchar_t* xml_node::name() const;
bool xml_node::set_name(const wchar_t* value);
----
[[char_t]][[string_t]]
There is a special type, `pugi::char_t`, that is defined as the character type and depends on the library configuration; it will be also used in the documentation hereafter. There is also a type `pugi::string_t`, which is defined as the STL string of the character type; it corresponds to `std::string` in char mode and to `std::wstring` in wchar_t mode.
[[char_t]][[string_t]][[string_view_t]]
There is a special type, `pugi::char_t`, that is defined as the character type and depends on the library configuration; it will be also used in the documentation hereafter. There is also a type `pugi::string_t`, which is defined as the STL string of the character type; it corresponds to `std::string` in char mode and to `std::wstring` in wchar_t mode. Similarly, `string_view_t` is defined to be `std::basic_string_view<char_t>`. Overloads for `string_view_t` are only available when building for C++17 or later (see `PUGIXML_HAS_STRING_VIEW`).
In addition to the interface, the internal implementation changes to store XML data as `pugi::char_t`; this means that these two modes have different memory usage characteristics - generally UTF-8 mode is more memory and performance efficient, especially if `sizeof(wchar_t)` is 4. The conversion to `pugi::char_t` upon document loading and from `pugi::char_t` upon document saving happen automatically, which also carries minor performance penalty. The general advice however is to select the character mode based on usage scenario, i.e. if UTF-8 is inconvenient to process and most of your XML data is non-ASCII, wchar_t mode is probably a better choice.
@@ -459,9 +454,9 @@ Almost all functions in pugixml have the following thread-safety guarantees:
* it is safe to call free (non-member) functions from multiple threads
* it is safe to perform concurrent read-only accesses to the same tree (all constant member functions do not modify the tree)
* it is safe to perform concurrent read/write accesses, if there is only one read or write access to the single tree at a time
* it is safe to perform concurrent read/write accesses on multiple trees, as long as each tree is only accessed from a single thread at a time
Concurrent modification and traversing of a single tree requires synchronization, for example via reader-writer lock. Modification includes altering document structure and altering individual node/attribute data, i.e. changing names/values.
Concurrent read/write access to a single tree requires synchronization, for example via a reader-writer lock. Modification includes altering document structure and altering individual node/attribute data, i.e. changing names/values.
The only exception is <<set_memory_management_functions,set_memory_management_functions>>; it modifies global variables and as such is not thread-safe. Its usage policy has more restrictions, see <<dom.memory.custom>>.
@@ -483,7 +478,7 @@ pugixml requests the memory needed for document storage in big chunks, and alloc
==== Custom memory allocation/deallocation functions
[[allocation_function]][[deallocation_function]]
All memory for tree structure, tree data and XPath objects is allocated via globally specified functions, which default to malloc/free. You can set your own allocation functions with set_memory_management function. The function interfaces are the same as that of malloc/free:
All memory for tree structure, tree data and XPath objects is allocated via globally specified functions, which default to malloc/free. You can set your own allocation functions with `set_memory_management_functions` function. The function interfaces are the same as that of malloc/free:
[source]
----
@@ -538,7 +533,7 @@ Constructing a document object using the default constructor does not result in
When the document is loaded from file/buffer, unless an inplace loading function is used (see <<loading.memory>>), a complete copy of character stream is made; all names/values of nodes and attributes are allocated in this buffer. This buffer is allocated via a single large allocation and is only freed when document memory is reclaimed (i.e. if the <<xml_document,xml_document>> object is destroyed or if another document is loaded in the same object). Also when loading from file or stream, an additional large allocation may be performed if encoding conversion is required; a temporary buffer is allocated, and it is freed before load function returns.
All additional memory, such as memory for document structure (node/attribute objects) and memory for node/attribute names/values is allocated in pages on the order of 32 Kb; actual objects are allocated inside the pages using a memory management scheme optimized for fast allocation/deallocation of many small objects. Because of the scheme specifics, the pages are only destroyed if all objects inside them are destroyed; also, generally destroying an object does not mean that subsequent object creation will reuse the same memory. This means that it is possible to devise a usage scheme which will lead to higher memory usage than expected; one example is adding a lot of nodes, and them removing all even numbered ones; not a single page is reclaimed in the process. However this is an example specifically crafted to produce unsatisfying behavior; in all practical usage scenarios the memory consumption is less than that of a general-purpose allocator because allocation meta-data is very small in size.
All additional memory, such as memory for document structure (node/attribute objects) and memory for node/attribute names/values is allocated in pages on the order of 32 Kb; actual objects are allocated inside the pages using a memory management scheme optimized for fast allocation/deallocation of many small objects. Because of the scheme specifics, the pages are only destroyed if all objects inside them are destroyed; also, generally destroying an object does not mean that subsequent object creation will reuse the same memory. This means that it is possible to devise a usage scheme which will lead to higher memory usage than expected; one example is adding a lot of nodes, and then removing all even numbered ones; not a single page is reclaimed in the process. However this is an example specifically crafted to produce unsatisfying behavior; in all practical usage scenarios the memory consumption is less than that of a general-purpose allocator because allocation meta-data is very small in size.
[[dom.memory.compact]]
==== Compact mode
@@ -651,7 +646,7 @@ xml_parse_result xml_document::load(std::wistream& stream, unsigned int options
`load` with `std::istream` argument loads the document from stream from the current read position to the end, treating the stream contents as a byte stream of the specified encoding (with encoding autodetection as necessary). Thus calling `xml_document::load` on an opened `std::ifstream` object is equivalent to calling `xml_document::load_file`.
`load` with `std::wstream` argument treats the stream contents as a wide character stream (encoding is always <<encoding_wchar,encoding_wchar>>). Because of this, using `load` with wide character streams requires careful (usually platform-specific) stream setup (i.e. using the `imbue` function). Generally use of wide streams is discouraged, however it provides you the ability to load documents from non-Unicode encodings, i.e. you can load Shift-JIS encoded data if you set the correct locale.
`load` with `std::wistream` argument treats the stream contents as a wide character stream (encoding is always <<encoding_wchar,encoding_wchar>>). Because of this, using `load` with wide character streams requires careful (usually platform-specific) stream setup (i.e. using the `imbue` function). Generally use of wide streams is discouraged, however it provides you the ability to load documents from non-Unicode encodings, i.e. you can load Shift-JIS encoded data if you set the correct locale.
This is a simple example of loading XML document from file using streams (link:samples/load_stream.cpp[]); read the sample code for more complex examples involving wide streams and locales:
@@ -685,7 +680,7 @@ Parsing status is represented as the `xml_parse_status` enumeration and can be o
* [[status_ok]]`status_ok` means that no error was encountered during parsing; the source stream represents the valid XML document which was fully parsed and converted to a tree.
* [[status_file_not_found]]`status_file_not_found` is only returned by `load_file` function and means that file could not be opened.
* [[status_io_error]]`status_io_error` is returned by `load_file` function and by `load` functions with `std::istream`/`std::wstream` arguments; it means that some I/O error has occurred during reading the file/stream.
* [[status_io_error]]`status_io_error` is returned by `load_file` function and by `load` functions with `std::istream`/`std::wistream` arguments; it means that some I/O error has occurred during reading the file/stream.
* [[status_out_of_memory]]`status_out_of_memory` means that there was not enough memory during some allocation; any allocation failure during parsing results in this error.
* [[status_internal_error]]`status_internal_error` means that something went horribly wrong; currently this error does not occur
@@ -746,10 +741,12 @@ These flags control the resulting tree contents:
* [[parse_ws_pcdata_single]]`parse_ws_pcdata_single` determines if whitespace-only PCDATA nodes that have no sibling nodes are to be put in DOM tree. In some cases application needs to parse the whitespace-only contents of nodes, i.e. `<node> </node>`, but is not interested in whitespace markup elsewhere. It is possible to use <<parse_ws_pcdata,parse_ws_pcdata>> flag in this case, but it results in excessive allocations and complicates document processing; this flag can be used to avoid that. As an example, after parsing XML string `<node> <a> </a> </node>` with `parse_ws_pcdata_single` flag set, `<node>` element will have one child `<a>`, and `<a>` element will have one child with type <<node_pcdata,node_pcdata>> and value `" "`. This flag has no effect if <<parse_ws_pcdata,parse_ws_pcdata>> is enabled. This flag is *off* by default.
* [[parse_embed_pcdata]]`parse_embed_pcdata` determines if PCDATA contents is to be saved as element values. Normally element nodes have names but not values; this flag forces the parser to store the contents as a value if PCDATA is the first child of the element node (otherwise PCDATA node is created as usual). This can significantly reduce the memory required for documents with many PCDATA nodes. To retrieve the data you can use `xml_node::value()` on the element nodes or any of the higher-level functions like `child_value` or `text`. This flag is *off* by default.
* [[parse_embed_pcdata]]`parse_embed_pcdata` determines if PCDATA contents is to be saved as element values. Normally element nodes have names but not values; this flag forces the parser to store the contents as a value if PCDATA is the first child of the element node (otherwise PCDATA node is created as usual). This can significantly reduce the memory required for documents with many PCDATA nodes. To retrieve the data you can use `xml_node::value()` on the element nodes or any of the higher-level functions like `child_value` or `text`.
Since this flag significantly changes the DOM structure it is only recommended for parsing documents with many PCDATA nodes in memory-constrained environments. This flag is *off* by default.
* [[parse_fragment]]`parse_fragment` determines if document should be treated as a fragment of a valid XML. Parsing document as a fragment leads to top-level PCDATA content (i.e. text that is not located inside a node) to be added to a tree, and additionally treats documents without element nodes as valid and permits multiple top-level element nodes. This flag is *off* by default.
* [[parse_merge_pcdata]]`parse_merge_pcdata` determines if PCDATA contents is to be merged with the previous PCDATA node when no intermediary nodes are present between them. If the PCDATA contains CDATA sections, PI nodes, or comments in between, and either of the flags <<parse_cdata,parse_cdata>>, <<parse_pi,parse_pi>>, <<parse_comments,parse_comments>> is not set, the contents of the PCDATA node will be merged with the previous one. This flag is *off* by default. Note that this flag is not compatible with `parse_embed_pcdata`.
* [[parse_fragment]]`parse_fragment` determines if document should be treated as a fragment of a valid XML. Parsing document as a fragment leads to top-level PCDATA content (i.e. text that is not located inside a node) to be added to a tree, and additionally treats documents without element nodes as valid and permits multiple top-level element nodes (currently multiple top-level element nodes are also permitted when the flag is off, but that behavior should not be relied on). This flag is *off* by default.
CAUTION: Using in-place parsing (<<xml_document::load_buffer_inplace,load_buffer_inplace>>) with `parse_fragment` flag may result in the loss of the last character of the buffer if it is a part of PCDATA. Since PCDATA values are null-terminated strings, the only way to resolve this is to provide a null-terminated buffer as an input to `load_buffer_inplace` - i.e. `doc.load_buffer_inplace("test\0", 5, pugi::parse_default | pugi::parse_fragment)`.
@@ -823,10 +820,10 @@ As for rejecting invalid XML documents, there are a number of incompatibilities
[[access]]
== Accessing document data
pugixml features an extensive interface for getting various types of data from the document and for traversing the document. This section provides documentation for all such functions that do not modify the tree except for XPath-related functions; see <<xpath>> for XPath reference. As discussed in <<dom.cpp>>, there are two types of handles to tree data - <<xml_node,xml_node>> and <<xml_attribute,xml_attribute>>. The handles have special null (empty) values which propagate through various functions and thus are useful for writing more concise code; see <<node_null,this description>> for details. The documentation in this section will explicitly state the results of all function in case of null inputs.
[import samples/traverse_base.cpp]
pugixml features an extensive interface for getting various types of data from the document and for traversing the document. This section provides documentation for all such functions that do not modify the tree except for XPath-related functions; see <<xpath>> for XPath reference. As discussed in <<dom.cpp>>, there are two types of handles to tree data - <<xml_node,xml_node>> and <<xml_attribute,xml_attribute>>. The handles have special null (empty) values which propagate through various functions and thus are useful for writing more concise code; see <<node_null,this description>> for details. The documentation in this section will explicitly state the results of all function in case of null inputs.
[[access.basic]]
=== Basic traversal functions
@@ -930,13 +927,13 @@ unsigned long long xml_attribute::as_ullong(unsigned long long def = 0) const;
`as_int`, `as_uint`, `as_llong`, `as_ullong`, `as_double` and `as_float` convert attribute values to numbers. If attribute handle is null `def` argument is returned (which is 0 by default). Otherwise, all leading whitespace characters are truncated, and the remaining string is parsed as an integer number in either decimal or hexadecimal form (applicable to `as_int`, `as_uint`, `as_llong` and `as_ullong`; hexadecimal format is used if the number has `0x` or `0X` prefix) or as a floating point number in either decimal or scientific form (`as_double` or `as_float`).
In case the input string contains a non-numeric character sequence or a number that is out of the target numeric range, the result is undefined.
For integer conversions, non-numeric character sequences return 0 and out of range values are clamped to the closest representable value; for floating-point conversions, the result depends on implementation (CRT or STL depending on whether `PUGIXML_CHARCONV_FLOAT` is used).
CAUTION: Number conversion functions depend on current C locale as set with `setlocale`, so may return unexpected results if the locale is different from `"C"`.
CAUTION: Floating-point conversion functions depend on the current C locale as set with `setlocale`, so may return unexpected results if the locale is different from `"C"`. This does not apply when pugixml is built with `PUGIXML_CHARCONV_FLOAT`.
`as_bool` converts attribute value to boolean as follows: if attribute handle is null, `def` argument is returned (which is `false` by default). If attribute value is empty, `false` is returned. Otherwise, `true` is returned if the first character is one of `'1', 't', 'T', 'y', 'Y'`. This means that strings like `"true"` and `"yes"` are recognized as `true`, while strings like `"false"` and `"no"` are recognized as `false`. For more complex matching you'll have to write your own function.
NOTE: `as_llong` and `as_ullong` are only available if your platform has reliable support for the `long long` type, including string conversions.
NOTE: `as_llong` and `as_ullong` are only available if your platform has support for the `long long` type.
[[code_traverse_base_data]]
This is an example of using these functions, along with node data retrieval ones (link:samples/traverse_base.cpp[]):
@@ -955,9 +952,13 @@ Since a lot of document traversal consists of finding the node/attribute with th
[source]
----
xml_node xml_node::child(const char_t* name) const;
xml_node xml_node::child(string_view_t name) const;
xml_attribute xml_node::attribute(const char_t* name) const;
xml_attribute xml_node::attribute(string_view_t name) const;
xml_node xml_node::next_sibling(const char_t* name) const;
xml_node xml_node::next_sibling(string_view_t name) const;
xml_node xml_node::previous_sibling(const char_t* name) const;
xml_node xml_node::previous_sibling(string_view_t name) const;
----
`child` and `attribute` return the first child/attribute with the specified name; `next_sibling` and `previous_sibling` return the first sibling in the corresponding direction with the specified name. All string comparisons are case-sensitive. In case the node handle is null or there is no node/attribute with the specified name, null handle is returned.
@@ -969,6 +970,29 @@ xml_node xml_node::previous_sibling(const char_t* name) const;
for (pugi::xml_node tool = tools.child("Tool"); tool; tool = tool.next_sibling("Tool"))
----
[[xml_node::attribute_hinted]]
`attribute` function needs to look for the target attribute by name. If a node has many attributes, finding each by name can be time consuming. If you have an idea of how attributes are ordered in the node, you can use a faster function:
[source]
----
xml_attribute xml_node::attribute(const char_t* name, xml_attribute& hint) const;
xml_attribute xml_node::attribute(string_view_t name, xml_attribute& hint) const;
----
The extra `hint` argument is used to guess where the attribute might be, and is updated to the location of the next attribute so that if you search for multiple attributes in the right order, the performance is maximized. Note that `hint` has to be either null or has to belong to the node, otherwise the behavior is undefined.
You can use this function as follows:
[source]
----
xml_attribute hint;
xml_attribute id = node.attribute("id", hint);
xml_attribute name = node.attribute("name", hint);
xml_attribute version = node.attribute("version", hint);
----
This code is correct regardless of the order of the attributes, but it's faster if `"id"`, `"name"` and `"version"` occur in that order.
[[xml_node::find_child_by_attribute]]
Occasionally the needed node is specified not by the unique name but instead by the value of some attribute; for example, it is common to have node collections with each node having a unique id: `<group><item id="1"/> <item id="2"/></group>`. There are two functions for finding child nodes based on the attribute values:
@@ -993,7 +1017,7 @@ include::samples/traverse_base.cpp[tags=contents]
=== Range-based for-loop support
[[xml_node::children]][[xml_node::attributes]]
If your C{plus}{plus} compiler supports range-based for-loop (this is a C{plus}{plus}11 feature, at the time of writing it's supported by Microsoft Visual Studio 2012+, GCC 4.6+ and Clang 3.0+), you can use it to enumerate nodes/attributes. Additional helpers are provided to support this; note that they are also compatible with http://www.boost.org/libs/foreach/[Boost Foreach], and possibly other pre-C{plus}{plus}11 foreach facilities.
If your C{plus}{plus} compiler supports range-based for-loop (this is a C{plus}{plus}11 feature, supported by Microsoft Visual Studio 2012+, GCC 4.6+ and Clang 3.0+), you can use it to enumerate nodes/attributes. Additional helpers are provided to support this; note that they are also compatible with http://www.boost.org/libs/foreach/[Boost Foreach], and possibly other pre-C{plus}{plus}11 foreach facilities.
[source,subs="+quotes"]
----
@@ -1015,7 +1039,19 @@ While using `children()` makes the intent of the code clear, note that each node
[source]
----
for (pugi::xml_node child: tool)
for (pugi::xml_node child: tool) ...
----
When using C{plus}{plus}20, you can also use nodes as well as objects returned by `children()` and `attributes()` functions as ranges:
[source]
----
auto tf =
tools.children("Tool")
| std::views::filter([](auto node) { return node.attribute("AllowRemote").as_bool(); })
| std::views::reverse;
for (pugi::xml_node tool: tf) ...
----
[[access.iterators]]
@@ -1238,12 +1274,12 @@ If the offset is not available (this happens if the node is null, was not origin
[[modify]]
== Modifying document data
[import samples/modify_base.cpp]
The document in pugixml is fully mutable: you can completely change the document structure and modify the data of nodes/attributes. This section provides documentation for the relevant functions. All functions take care of memory management and structural integrity themselves, so they always result in structurally valid tree - however, it is possible to create an invalid XML tree (for example, by adding two attributes with the same name or by setting attribute/node name to empty/invalid string). Tree modification is optimized for performance and for memory consumption, so if you have enough memory you can create documents from scratch with pugixml and later save them to file/stream instead of relying on error-prone manual text writing and without too much overhead.
All member functions that change node/attribute data or structure are non-constant and thus can not be called on constant handles. However, you can easily convert constant handle to non-constant one by simple assignment: `void foo(const pugi::xml_node& n) { pugi::xml_node nc = n; }`, so const-correctness here mainly provides additional documentation.
[import samples/modify_base.cpp]
[[modify.nodedata]]
=== Setting node data
@@ -1253,7 +1289,11 @@ As discussed before, nodes can have name and value, both of which are strings. D
[source]
----
bool xml_node::set_name(const char_t* rhs);
bool xml_node::set_name(const char_t* rhs, size_t sz);
bool xml_node::set_name(string_view_t rhs);
bool xml_node::set_value(const char_t* rhs);
bool xml_node::set_value(const char_t* rhs, size_t size);
bool xml_node::set_value(string_view_t rhs);
----
Both functions try to set the name/value to the specified string, and return the operation result. The operation fails if the node can not have name or value (for instance, when trying to call `set_name` on a <<node_pcdata,node_pcdata>> node), if the node handle is null, or if there is insufficient memory to handle the request. The provided string is copied into document managed memory and can be destroyed after the function returns (for example, you can safely pass stack-allocated buffers to these functions). The name/value content is not verified, so take care to use only valid XML names, or the document may become malformed.
@@ -1274,7 +1314,11 @@ All attributes have name and value, both of which are strings (value may be empt
[source]
----
bool xml_attribute::set_name(const char_t* rhs);
bool xml_attribute::set_name(const char_t* rhs, size_t sz);
bool xml_attribute::set_name(string_view_t rhs);
bool xml_attribute::set_value(const char_t* rhs);
bool xml_attribute::set_value(const char_t* rhs, size_t size);
bool xml_attribute::set_value(string_view_t rhs);
----
Both functions try to set the name/value to the specified string, and return the operation result. The operation fails if the attribute handle is null, or if there is insufficient memory to handle the request. The provided string is copied into document managed memory and can be destroyed after the function returns (for example, you can safely pass stack-allocated buffers to these functions). The name/value content is not verified, so take care to use only valid XML names, or the document may become malformed.
@@ -1298,9 +1342,9 @@ bool xml_attribute::set_value(unsigned long long rhs);
The above functions convert the argument to string and then call the base `set_value` function. Integers are converted to a decimal form, floating-point numbers are converted to either decimal or scientific form, depending on the number magnitude, boolean values are converted to either `"true"` or `"false"`.
CAUTION: Number conversion functions depend on current C locale as set with `setlocale`, so may generate unexpected results if the locale is different from `"C"`.
CAUTION: Floating-point conversion functions depend on the current C locale as set with `setlocale`, so may generate unexpected results if the locale is different from `"C"`. This does not apply when pugixml is built with `PUGIXML_CHARCONV_FLOAT`.
NOTE: `set_value` overloads with `long long` type are only available if your platform has reliable support for the type, including string conversions.
NOTE: `set_value` overloads with `long long` type are only available if your platform has support for the type.
[[xml_attribute::assign]]
@@ -1309,6 +1353,7 @@ For convenience, all `set_value` functions have the corresponding assignment ope
[source]
----
xml_attribute& xml_attribute::operator=(const char_t* rhs);
xml_attribute& xml_attribute::operator=(string_view_t rhs);
xml_attribute& xml_attribute::operator=(int rhs);
xml_attribute& xml_attribute::operator=(unsigned int rhs);
xml_attribute& xml_attribute::operator=(long rhs);
@@ -1332,15 +1377,19 @@ include::samples/modify_base.cpp[tags=attr]
[[modify.add]]
=== Adding nodes/attributes
[[xml_node::prepend_attribute]][[xml_node::append_attribute]][[xml_node::insert_attribute_after]][[xml_node::insert_attribute_before]][[xml_node::prepend_child]][[xml_node::append_child]][[xml_node::insert_child_after]][[xml_node::insert_child_before]]
[[xml_node::prepend_attribute]][[xml_node::append_attribute]][[xml_node::insert_attribute_after]][[xml_node::insert_attribute_before]][[xml_node::ensure_attribute]][[xml_node::prepend_child]][[xml_node::append_child]][[xml_node::insert_child_after]][[xml_node::insert_child_before]][[xml_node::ensure_child]]
Nodes and attributes do not exist without a document tree, so you can't create them without adding them to some document. A node or attribute can be created at the end of node/attribute list or before/after some other node:
[source]
----
xml_attribute xml_node::append_attribute(const char_t* name);
xml_attribute xml_node::append_attribute(string_view_t name);
xml_attribute xml_node::prepend_attribute(const char_t* name);
xml_attribute xml_node::prepend_attribute(string_view_t name);
xml_attribute xml_node::insert_attribute_after(const char_t* name, const xml_attribute& attr);
xml_attribute xml_node::insert_attribute_after(string_view_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::insert_attribute_before(string_view_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);
@@ -1348,28 +1397,37 @@ 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::append_child(string_view_t name);
xml_node xml_node::prepend_child(const char_t* name);
xml_node xml_node::prepend_child(string_view_t name);
xml_node xml_node::insert_child_after(const char_t* name, const xml_node& node);
xml_node xml_node::insert_child_after(string_view_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::insert_child_before(string_view_t name, const xml_node& node);
xml_attribute xml_node::ensure_attribute(const char_t* name);
xml_attribute xml_node::ensure_attribute(string_view_t name);
xml_node xml_node::ensure_child(const char_t* name);
xml_node xml_node::ensure_child(string_view_t name);
----
`append_attribute` and `append_child` create a new node/attribute at the end of the corresponding list of the node the method is called on; `prepend_attribute` and `prepend_child` create a new node/attribute at the beginning of the list; `insert_attribute_after`, `insert_attribute_before`, `insert_child_after` and `insert_attribute_before` add the node/attribute before or after the specified node/attribute.
`append_attribute` and `append_child` create a new node/attribute at the end of the corresponding list of the node the method is called on; `prepend_attribute` and `prepend_child` create a new node/attribute at the beginning of the list; `insert_attribute_after`, `insert_attribute_before`, `insert_child_after` and `insert_child_before` add the node/attribute before or after the specified node/attribute. `ensure_attribute` and `ensure_child` return the existing attribute/child with the specified name, appending a new one only if no such attribute/child exists; this makes it convenient to write code like `node.ensure_attribute("id") = 123;`.
Attribute functions create an attribute with the specified name; you can specify the empty name and change the name later if you want to. Node functions with the `type` argument create the node with the specified type; since node type can't be changed, you have to know the desired type beforehand. Also note that not all types can be added as children; see below for clarification. Node functions with the `name` argument create the element node (<<node_element,node_element>>) with the specified name.
All functions return the handle to the created object on success, and null handle on failure. There are several reasons for failure:
* Adding fails if the target node is null;
* Only <<node_element,node_element>> nodes can contain attributes, so attribute adding fails if node is not an element;
* Only <<node_element,node_element>> and <<node_declaration,node_declaration>> nodes can contain attributes, so attribute adding fails if node is not an element or a declaration;
* Only <<node_document,node_document>> and <<node_element,node_element>> nodes can contain children, so child node adding fails if the target node is not an element or a document;
* <<node_document,node_document>> and <<node_null,node_null>> nodes can not be inserted as children, so passing <<node_document,node_document>> or <<node_null,node_null>> value as `type` results in operation failure;
* <<node_declaration,node_declaration>> nodes can only be added as children of the document node; attempt to insert declaration node as a child of an element node fails;
* <<node_declaration,node_declaration>> and <<node_doctype,node_doctype>> nodes can only be added as children of the document node; attempt to insert them as children of an element node fails;
* Adding node/attribute results in memory allocation, which may fail;
* Insertion functions fail if the specified node or attribute is null or is not in the target node's children/attribute list.
Even if the operation fails, the document remains in consistent state, but the requested node/attribute is not added.
CAUTION: `attribute()` and `child()` functions do not add attributes or nodes to the tree, so code like `node.attribute("id") = 123;` will not do anything if `node` does not have an attribute with name `"id"`. Make sure you're operating with existing attributes/nodes by adding them if necessary.
CAUTION: `attribute()` and `child()` functions do not add attributes or nodes to the tree, so code like `node.attribute("id") = 123;` will not do anything if `node` does not have an attribute with name `"id"`. Make sure you're operating with existing attributes/nodes by adding them if necessary, or use `ensure_attribute`/`ensure_child`.
This is an example of adding new attributes/nodes to the document (link:samples/modify_add.cpp[]):
@@ -1405,7 +1463,9 @@ If you want to remove the attribute or child node by its name, two additional he
[source]
----
bool xml_node::remove_attribute(const char_t* name);
bool xml_node::remove_attribute(string_view_t name);
bool xml_node::remove_child(const char_t* name);
bool xml_node::remove_child(string_view_t name);
----
These functions look for the first attribute or child with the specified name, and then remove it, returning the result. If there is no attribute or child with such name, the function returns `false`; if there are two nodes with the given name, only the first node is deleted. If you want to delete all nodes with the specified name, you can use code like this: `while (node.remove_child("tool")) ;`.
@@ -1428,9 +1488,11 @@ Once you have an `xml_text` object, you can set the text contents using the foll
[source]
----
bool xml_text::set(const char_t* rhs);
bool xml_text::set(const char_t* rhs, size_t size);
bool xml_text::set(string_view_t rhs);
----
This function tries to set the contents to the specified string, and returns the operation result. The operation fails if the text object was retrieved from a node that can not have a value and is not an element node (i.e. it is a <<node_declaration,node_declaration>> node), if the text object is empty, or if there is insufficient memory to handle the request. The provided string is copied into document managed memory and can be destroyed after the function returns (for example, you can safely pass stack-allocated buffers to this function). Note that if the text object was retrieved from an element node, this function creates the PCDATA child node if necessary (i.e. if the element node does not have a PCDATA/CDATA child already).
This function tries to set the contents to the specified string, and returns the operation result. The operation fails if the text object was retrieved from a node that can not have a value and is not an element node (i.e. it is a <<node_declaration,node_declaration>> node), if the node handle is null, or if there is insufficient memory to handle the request. The provided string is copied into document managed memory and can be destroyed after the function returns (for example, you can safely pass stack-allocated buffers to this function). Note that if the text object was retrieved from an element node, this function creates the PCDATA child node if necessary (i.e. if the element node does not have a PCDATA/CDATA child already).
[[xml_text::set_value]]
In addition to a string function, several functions are provided for handling text with numbers and booleans as contents:
@@ -1459,6 +1521,7 @@ For convenience, all `set` functions have the corresponding assignment operators
[source]
----
xml_text& xml_text::operator=(const char_t* rhs);
xml_text& xml_text::operator=(string_view_t rhs);
xml_text& xml_text::operator=(int rhs);
xml_text& xml_text::operator=(unsigned int rhs);
xml_text& xml_text::operator=(long rhs);
@@ -1555,6 +1618,8 @@ bool append_fragment(pugi::xml_node target, const char* buffer, size_t size)
for (pugi::xml_node child = doc.first_child(); child; child = child.next_sibling())
target.append_copy(child);
return true;
}
----
@@ -1562,7 +1627,7 @@ bool append_fragment(pugi::xml_node target, const char* buffer, size_t size)
+
[source]
----
bool append_fragment(pugi::xml_node target, const pugi::xml_document& cached_fragment)
void 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);
@@ -1630,10 +1695,10 @@ void xml_document::save(std::ostream& stream, const char_t* indent = "\t", unsig
void xml_document::save(std::wostream& stream, const char_t* indent = "\t", unsigned int flags = format_default) const;
----
`save` with `std::ostream` argument saves the document to the stream in the same way as `save_file` (i.e. with requested header and with encoding conversions). On the other hand, `save` with `std::wstream` argument saves the document to the wide stream with <<encoding_wchar,encoding_wchar>> encoding. Because of this, using `save` with wide character streams requires careful (usually platform-specific) stream setup (i.e. using the `imbue` function). Generally use of wide streams is discouraged, however it provides you with the ability to save documents to non-Unicode encodings, i.e. you can save Shift-JIS encoded data if you set the correct locale.
`save` with `std::ostream` argument saves the document to the stream in the same way as `save_file` (i.e. with requested header and with encoding conversions). On the other hand, `save` with `std::wostream` argument saves the document to the wide stream with <<encoding_wchar,encoding_wchar>> encoding. Because of this, using `save` with wide character streams requires careful (usually platform-specific) stream setup (i.e. using the `imbue` function). Generally use of wide streams is discouraged, however it provides you with the ability to save documents to non-Unicode encodings, i.e. you can save Shift-JIS encoded data if you set the correct locale.
[[xml_writer_stream]]
Calling `save` with stream target is equivalent to creating an `xml_writer_stream` object with stream as the only constructor argument and then calling `save`; see <<saving.writer>> for writer interface details.
Calling `save` with stream target is equivalent to creating an `xml_writer_stream` object with stream as the only constructor argument and then calling `save`; see <<saving.writer>> for writer interface details. When using `xml_writer_stream` with wide-character streams, you must pass `encoding_wchar` explicitly, as the wide writer expects wide-character data.
This is a simple example of saving XML document to standard output (link:samples/save_stream.cpp[]):
@@ -1722,7 +1787,7 @@ These flags control the additional output information:
* [[format_write_bom]]`format_write_bom` enables Byte Order Mark (BOM) output. By default, no BOM is output, so in case of non UTF-8 encodings the resulting document's encoding may not be recognized by some parsers and text editors, if they do not implement sophisticated encoding detection. Enabling this flag adds an encoding-specific BOM to the output. This flag has no effect in `xml_node::print` functions: they never output the BOM. This flag is *off* by default.
* [[format_save_file_text]]`format_save_file_text` changes the file mode when using `save_file` function. By default, file is opened in binary mode, which means that the output file will
contain platform-independent newline `\n` (ASCII 10). If this flag is on, file is opened in text mode, which on some systems changes the newline format (i.e. on Windows you can use this flag to output XML documents with `\r\n` (ASCII 13 10) newlines. This flag is *off* by default.
contain platform-independent newline `\n` (ASCII 10). If this flag is on, file is opened in text mode, which on some systems changes the newline format (i.e. on Windows you can use this flag to output XML documents with `\r\n` (ASCII 13 10) newlines). This flag is *off* by default.
Additionally, there is one predefined option mask:
@@ -1765,7 +1830,7 @@ include::samples/save_declaration.cpp[tags=code]
[[xpath]]
== XPath
If the task at hand is to select a subset of document nodes that match some criteria, it is possible to code a function using the existing traversal functionality for any practical criteria. However, often either a data-driven approach is desirable, in case the criteria are not predefined and come from a file, or it is inconvenient to use traversal interfaces and a higher-level DSL is required. There is a standard language for XML processing, XPath, that can be useful for these cases. pugixml implements an almost complete subset of XPath 1.0. Because of differences in document object model and some performance implications, there are minor violations of the official specifications, which can be found in <<xpath.w3c>>. The rest of this section describes the interface for XPath functionality. Please note that if you wish to learn to use XPath language, you have to look for other tutorials or manuals; for example, you can read http://www.w3schools.com/xpath/[W3Schools XPath tutorial], http://www.tizag.com/xmlTutorial/xpathtutorial.php[XPath tutorial at tizag.com], and http://www.w3.org/TR/xpath/[the XPath 1.0 specification].
If the task at hand is to select a subset of document nodes that match some criteria, it is possible to code a function using the existing traversal functionality for any practical criteria. However, often either a data-driven approach is desirable, in case the criteria are not predefined and come from a file, or it is inconvenient to use traversal interfaces and a higher-level DSL is required. There is a standard language for XML processing, XPath, that can be useful for these cases. pugixml implements an almost complete subset of XPath 1.0. Because of differences in document object model and some performance implications, there are minor violations of the official specifications, which can be found in <<xpath.w3c>>. The rest of this section describes the interface for XPath functionality. Please note that if you wish to learn to use XPath language, you have to look for other tutorials or manuals; for example, you can read https://www.w3schools.com/xml/xpath_intro.asp[W3Schools XPath tutorial] or https://www.w3.org/TR/xpath-10/[the XPath 1.0 specification].
[[xpath.types]]
=== XPath types
@@ -1976,7 +2041,7 @@ xpath_node_set xml_node::select_nodes(const char_t* query, xpath_variable_set* v
If you're using query objects, you can change the variable values before `evaluate`/`select` calls to change the query behavior.
NOTE: The variable set pointer is stored in the query object; you have to ensure that the lifetime of the set exceeds that of query object.
NOTE: The variable set pointer is stored in the query object, along with pointers to the variables it references; you have to ensure that the lifetime of the set exceeds that of the query object, and that the set is not assigned to or moved into while the query is live.
[[xpath_variable_set]]
Variable sets correspond to `xpath_variable_set` type, which is essentially a variable container.
@@ -2070,11 +2135,11 @@ include::samples/xpath_variables.cpp[tags=code]
There are two different mechanisms for error handling in XPath implementation; the mechanism used depends on whether exception support is disabled (this is controlled with <<PUGIXML_NO_EXCEPTIONS,PUGIXML_NO_EXCEPTIONS>> define).
[[xpath_exception]][[xpath_exception::result]][[xpath_exception::what]]
By default, XPath functions throw `xpath_exception` object in case of errors; additionally, in the event any memory allocation fails, an `std::bad_alloc` exception is thrown. Also `xpath_exception` is thrown if the query is evaluated to a node set, but the return type is not node set. If the query constructor succeeds (i.e. no exception is thrown), the query object is valid. Otherwise you can get the error details via one of the following functions:
By default, XPath functions throw `xpath_exception` object in case of errors; additionally, in the event any memory allocation fails, an `std::bad_alloc` exception is thrown. Also `xpath_exception` is thrown if the query is evaluated as a node set, but the return type is not node set. If the query constructor succeeds (i.e. no exception is thrown), the query object is valid. Otherwise you can get the error details via one of the following functions:
[source]
----
virtual const char* xpath_exception::what() const throw();
virtual const char* xpath_exception::what() const noexcept;
const xpath_parse_result& xpath_exception::result() const;
----
@@ -2138,6 +2203,96 @@ Because of the differences in document object models, performance considerations
:!numbered:
[[v1.16]]
=== v1.16 ^2026-06-16^
Anniversary release (pugixml turns 20 this year!). Changes:
* Behavior changes:
. Elements that have a single empty PCDATA child are now printed as empty element tags (unless `format_no_empty_element_tags` is used)
* Improvements:
. `PUGIXML_CHARCONV_FLOAT` option can be enabled to switch floating point conversions to `<charconv>`; this requires C{plus}{plus}17, makes the conversions locale-independent and can improve performance
. Add `xml_node::ensure_child` and `xml_node::ensure_attribute` that return the child/attribute with the specified name, adding one if it does not exist
. Improve performance of searching for nodes and attributes by name
. Loading a document from an empty buffer no longer performs memory allocations
* XPath improvements:
. Improve performance of queries that evaluate or compare attribute values, like `@attr > 5`
. Improve performance of queries that select nodes and attributes by name
* Bug fixes:
. Fix stack overflow when removing subtrees with extremely deep nesting
. Fix integer overflows that could lead to crashes when loading very large (1+ GB) documents on 32-bit platforms in `PUGIXML_WCHAR_MODE`
. Fix null pointer dereference when copying `xpath_variable_set` objects that contain string variables with unassigned values
* CMake improvements:
. Apple frameworks built with `PUGIXML_BUILD_APPLE_FRAMEWORK` now include framework headers
. `PUGIXML_INSTALL_SOURCE` option can be used to install `pugixml.cpp` (useful for header-only mode)
* Compatibility improvements:
. Add project files and NuGet packages for Visual Studio 2026
. Fix compatibility with C{plus}{plus}20 modules when including `pugixml.hpp` in the global module fragment
. Fix clang/gcc warnings `-Wextra-semi-stmt`, `-Wsign-conversion`, `-Wuninitialized` (GCC16)
. Fix compilation for Embarcadero C{plus}{plus} XE5
. Work around several static analysis false positives
[[v1.15]]
=== v1.15 ^2025-01-10^
Maintenance release. Changes:
* Improvements:
. Many `xml_attribute::` and `xml_node::` functions now transparently support `std::string_view` and `std::string` when C++17 support is detected.
* CMake improvements:
. Improve `pkg-config` file generation for NixOS
. `PUGIXML_BUILD_APPLE_FRAMEWORK` CMake option can be used to build pugixml as `.xcframework`
. `PUGIXML_INSTALL` CMake option can be used to disable installation targets
* Compatibility improvements:
. Fix clang/gcc warnings `-Wzero-as-null-pointer-constant`, `-Wuseless-cast`, `-Wshorten-64-to-32`
. Fix unreferenced function warnings in `PUGIXML_NO_STL` configuration
. Fix CMake 3.31 deprecation warnings
. Stop using deprecated `throw()` when `noexcept` is available
[[v1.14]]
=== v1.14 ^2023-10-01^
Maintenance release. Changes:
* Improvements:
. `xml_attribute::set_name` and `xml_node::set_name` now have overloads that accept pointer to non-null-terminated string and size
. Implement `parse_merge_pcdata` parsing mode in which PCDATA contents is merged into a single node when original document had comments that were skipped during parsing
. `xml_document::load_file` now returns a more consistent error status when given a path to a folder
* Bug fixes:
. Fix assertion in XPath number->string conversion when using non-English locales
. Fix PUGIXML_STATIC_CRT CMake option to correctly select static CRT when using MSVC and recent CMake
* Compatibility improvements:
. Fix GCC 2.95/3.3 builds
. Fix CMake 3.27 deprecation warnings
. Fix XCode 14 sprintf deprecation warning when compiling in C++03 mode
. Fix clang/gcc warnings `-Wweak-vtables`, `-Wreserved-macro-identifier`
[[v1.13]]
=== v1.13 ^2022-11-01^
Maintenance release. Changes:
* Improvements:
. `xml_attribute::set_value`, `xml_node::set_value` and `xml_text::set` now have overloads that accept pointer to non-null-terminated string and size
. Improve performance of tree traversal when using compact mode (`PUGIXML_COMPACT`)
* Bug fixes:
. Fix error handling in `xml_document::save_file` that could result in the function succeeding while running out of disk space
. Fix memory leak during error handling of some out-of-memory conditions during `xml_document::load`
* Compatibility improvements:
. Fix exported symbols in CMake DLL builds when using CMake
. Fix exported symbols in CMake shared object builds when using -fvisibility=hidden
[[v1.12]]
=== v1.12 ^2022-02-09^
@@ -2655,6 +2810,7 @@ This is the reference for all macros, types, enumerations, classes and functions
#define +++<a href="#PUGIXML_MEMORY_XPATH_PAGE_SIZE">PUGIXML_MEMORY_XPATH_PAGE_SIZE</a>+++
#define +++<a href="#PUGIXML_HEADER_ONLY">PUGIXML_HEADER_ONLY</a>+++
#define +++<a href="#PUGIXML_HAS_LONG_LONG">PUGIXML_HAS_LONG_LONG</a>+++
#define +++<a href="#PUGIXML_HAS_STRING_VIEW">PUGIXML_HAS_STRING_VIEW</a>+++
----
[[apiref.types]]
@@ -2664,6 +2820,7 @@ This is the reference for all macros, types, enumerations, classes and functions
----
typedef configuration-defined-type +++<a href="#char_t">char_t</a>+++;
typedef configuration-defined-type +++<a href="#string_t">string_t</a>+++;
typedef configuration-defined-type +++<a href="#string_view_t">string_view_t</a>+++;
typedef void* (*+++<a href="#allocation_function">allocation_function</a>+++)(size_t size);
typedef void (*+++<a href="#deallocation_function">deallocation_function</a>+++)(void* ptr);
----
@@ -2757,6 +2914,7 @@ const unsigned int +++<a href="#parse_trim_pcdata">parse_trim_pcdata</a>+++
const unsigned int +++<a href="#parse_ws_pcdata">parse_ws_pcdata</a>+++
const unsigned int +++<a href="#parse_ws_pcdata_single">parse_ws_pcdata_single</a>+++
const unsigned int +++<a href="#parse_embed_pcdata">parse_embed_pcdata</a>+++
const unsigned int +++<a href="#parse_merge_pcdata">parse_merge_pcdata</a>+++
const unsigned int +++<a href="#parse_wconv_attribute">parse_wconv_attribute</a>+++
const unsigned int +++<a href="#parse_wnorm_attribute">parse_wnorm_attribute</a>+++
----
@@ -2797,18 +2955,25 @@ const unsigned int +++<a href="#parse_wnorm_attribute">parse_wnorm_attribute</a>
unsigned long long +++<a href="#xml_attribute::as_ullong">as_ullong</a>+++(unsigned long long def = 0) const;
bool +++<a href="#xml_attribute::set_name">set_name</a>+++(const char_t* rhs);
bool +++<a href="#xml_attribute::set_name">set_name</a>+++(const char_t* rhs, size_t size);
bool +++<a href="#xml_attribute::set_name">set_name</a>+++(string_view_t rhs);
bool +++<a href="#xml_attribute::set_value">set_value</a>+++(const char_t* rhs);
bool +++<a href="#xml_attribute::set_value">set_value</a>+++(const char_t* rhs, size_t size);
bool +++<a href="#xml_attribute::set_value">set_value</a>+++(string_view_t rhs);
bool +++<a href="#xml_attribute::set_value">set_value</a>+++(int rhs);
bool +++<a href="#xml_attribute::set_value">set_value</a>+++(unsigned int rhs);
bool +++<a href="#xml_attribute::set_value">set_value</a>+++(long rhs);
bool +++<a href="#xml_attribute::set_value">set_value</a>+++(unsigned long rhs);
bool +++<a href="#xml_attribute::set_value">set_value</a>+++(double rhs);
bool +++<a href="#xml_attribute::set_value">set_value</a>+++(double rhs, int precision);
bool +++<a href="#xml_attribute::set_value">set_value</a>+++(float rhs);
bool +++<a href="#xml_attribute::set_value">set_value</a>+++(float rhs, int precision);
bool +++<a href="#xml_attribute::set_value">set_value</a>+++(bool rhs);
bool +++<a href="#xml_attribute::set_value">set_value</a>+++(long long rhs);
bool +++<a href="#xml_attribute::set_value">set_value</a>+++(unsigned long long rhs);
xml_attribute& +++<a href="#xml_attribute::assign">operator=</a>+++(const char_t* rhs);
xml_attribute& +++<a href="#xml_attribute::assign">operator=</a>+++(string_view_t rhs);
xml_attribute& +++<a href="#xml_attribute::assign">operator=</a>+++(int rhs);
xml_attribute& +++<a href="#xml_attribute::assign">operator=</a>+++(unsigned int rhs);
xml_attribute& +++<a href="#xml_attribute::assign">operator=</a>+++(long rhs);
@@ -2817,7 +2982,7 @@ const unsigned int +++<a href="#parse_wnorm_attribute">parse_wnorm_attribute</a>
xml_attribute& +++<a href="#xml_attribute::assign">operator=</a>+++(float rhs);
xml_attribute& +++<a href="#xml_attribute::assign">operator=</a>+++(bool rhs);
xml_attribute& +++<a href="#xml_attribute::assign">operator=</a>+++(long long rhs);
xml_attribute& +++<a href="#xml_attribute::assign">operator=</a>+++(unsnigned long long rhs);
xml_attribute& +++<a href="#xml_attribute::assign">operator=</a>+++(unsigned long long rhs);
+++<span class="tok-k">class</span> <a href="#xml_node">xml_node</a>+++
+++<a href="#xml_node::ctor">xml_node</a>+++();
@@ -2853,9 +3018,17 @@ const unsigned int +++<a href="#parse_wnorm_attribute">parse_wnorm_attribute</a>
implementation-defined-type +++<a href="#xml_node::attributes">attributes</a>+++() const;
xml_node +++<a href="#xml_node::child">child</a>+++(const char_t* name) const;
xml_node +++<a href="#xml_node::child">child</a>+++(string_view_t name) const;
xml_attribute +++<a href="#xml_node::attribute">attribute</a>+++(const char_t* name) const;
xml_attribute +++<a href="#xml_node::attribute">attribute</a>+++(string_view_t name) const;
xml_node +++<a href="#xml_node::next_sibling_name">next_sibling</a>+++(const char_t* name) const;
xml_node +++<a href="#xml_node::next_sibling_name">next_sibling</a>+++(string_view_t name) const;
xml_node +++<a href="#xml_node::previous_sibling_name">previous_sibling</a>+++(const char_t* name) const;
xml_node +++<a href="#xml_node::previous_sibling_name">previous_sibling</a>+++(string_view_t name) const;
xml_attribute +++<a href="#xml_node::attribute_hinted">attribute</a>+++(const char_t* name, xml_attribute& hint) const;
xml_attribute +++<a href="#xml_node::attribute_hinted">attribute</a>+++(string_view_t name, xml_attribute& hint) const;
xml_node +++<a href="#xml_node::find_child_by_attribute">find_child_by_attribute</a>+++(const char_t* name, const char_t* attr_name, const char_t* attr_value) const;
xml_node +++<a href="#xml_node::find_child_by_attribute">find_child_by_attribute</a>+++(const char_t* attr_name, const char_t* attr_value) const;
@@ -2878,17 +3051,25 @@ const unsigned int +++<a href="#parse_wnorm_attribute">parse_wnorm_attribute</a>
template <typename Predicate> xml_node +++<a href="#xml_node::find_node">find_node</a>+++(Predicate pred) const;
string_t +++<a href="#xml_node::path">path</a>+++(char_t delimiter = '/') const;
xml_node +++<a href="#xml_node::first_element_by_path">xml_node::first_element_by_path</a>+++(const char_t* path, char_t delimiter = '/') const;
xml_node +++<a href="#xml_node::first_element_by_path">first_element_by_path</a>+++(const char_t* path, char_t delimiter = '/') const;
xml_node +++<a href="#xml_node::root">root</a>+++() const;
ptrdiff_t +++<a href="#xml_node::offset_debug">offset_debug</a>+++() const;
bool +++<a href="#xml_node::set_name">set_name</a>+++(const char_t* rhs);
bool +++<a href="#xml_node::set_name">set_name</a>+++(const char_t* rhs, size_t size);
bool +++<a href="#xml_node::set_name">set_name</a>+++(string_view_t rhs);
bool +++<a href="#xml_node::set_value">set_value</a>+++(const char_t* rhs);
bool +++<a href="#xml_node::set_value">set_value</a>+++(const char_t* rhs, size_t size);
bool +++<a href="#xml_node::set_value">set_value</a>+++(string_view_t rhs);
xml_attribute +++<a href="#xml_node::append_attribute">append_attribute</a>+++(const char_t* name);
xml_attribute +++<a href="#xml_node::append_attribute">append_attribute</a>+++(string_view_t name);
xml_attribute +++<a href="#xml_node::prepend_attribute">prepend_attribute</a>+++(const char_t* name);
xml_attribute +++<a href="#xml_node::prepend_attribute">prepend_attribute</a>+++(string_view_t name);
xml_attribute +++<a href="#xml_node::insert_attribute_after">insert_attribute_after</a>+++(const char_t* name, const xml_attribute& attr);
xml_attribute +++<a href="#xml_node::insert_attribute_after">insert_attribute_after</a>+++(string_view_t name, const xml_attribute& attr);
xml_attribute +++<a href="#xml_node::insert_attribute_before">insert_attribute_before</a>+++(const char_t* name, const xml_attribute& attr);
xml_attribute +++<a href="#xml_node::insert_attribute_before">insert_attribute_before</a>+++(string_view_t name, const xml_attribute& attr);
xml_node +++<a href="#xml_node::append_child">append_child</a>+++(xml_node_type type = node_element);
xml_node +++<a href="#xml_node::prepend_child">prepend_child</a>+++(xml_node_type type = node_element);
@@ -2896,9 +3077,18 @@ const unsigned int +++<a href="#parse_wnorm_attribute">parse_wnorm_attribute</a>
xml_node +++<a href="#xml_node::insert_child_before">insert_child_before</a>+++(xml_node_type type, const xml_node& node);
xml_node +++<a href="#xml_node::append_child">append_child</a>+++(const char_t* name);
xml_node +++<a href="#xml_node::append_child">append_child</a>+++(string_view_t name);
xml_node +++<a href="#xml_node::prepend_child">prepend_child</a>+++(const char_t* name);
xml_node +++<a href="#xml_node::prepend_child">prepend_child</a>+++(string_view_t name);
xml_node +++<a href="#xml_node::insert_child_after">insert_child_after</a>+++(const char_t* name, const xml_node& node);
xml_node +++<a href="#xml_node::insert_child_after">insert_child_after</a>+++(string_view_t name, const xml_node& node);
xml_node +++<a href="#xml_node::insert_child_before">insert_child_before</a>+++(const char_t* name, const xml_node& node);
xml_node +++<a href="#xml_node::insert_child_before">insert_child_before</a>+++(string_view_t name, const xml_node& node);
xml_attribute +++<a href="#xml_node::ensure_attribute">ensure_attribute</a>+++(const char_t* name);
xml_attribute +++<a href="#xml_node::ensure_attribute">ensure_attribute</a>+++(string_view_t name);
xml_node +++<a href="#xml_node::ensure_child">ensure_child</a>+++(const char_t* name);
xml_node +++<a href="#xml_node::ensure_child">ensure_child</a>+++(string_view_t name);
xml_attribute +++<a href="#xml_node::append_copy">append_copy</a>+++(const xml_attribute& proto);
xml_attribute +++<a href="#xml_node::prepend_copy">prepend_copy</a>+++(const xml_attribute& proto);
@@ -2917,9 +3107,11 @@ const unsigned int +++<a href="#parse_wnorm_attribute">parse_wnorm_attribute</a>
bool +++<a href="#xml_node::remove_attribute">remove_attribute</a>+++(const xml_attribute& a);
bool +++<a href="#xml_node::remove_attribute">remove_attribute</a>+++(const char_t* name);
bool +++<a href="#xml_node::remove_attribute">remove_attribute</a>+++(string_view_t name);
bool +++<a href="#xml_node::remove_attributes">remove_attributes</a>+++();
bool +++<a href="#xml_node::remove_child">remove_child</a>+++(const xml_node& n);
bool +++<a href="#xml_node::remove_child">remove_child</a>+++(const char_t* name);
bool +++<a href="#xml_node::remove_child">remove_child</a>+++(string_view_t name);
bool +++<a href="#xml_node::remove_children">remove_children</a>+++();
xml_parse_result +++<a href="#xml_node::append_buffer">append_buffer</a>+++(const void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
@@ -2982,9 +3174,9 @@ const unsigned int +++<a href="#parse_wnorm_attribute">parse_wnorm_attribute</a>
+++<span class="tok-k">class</span> <a href="#xml_text">xml_text</a>+++
bool +++<a href="#xml_text::empty">empty</a>+++() const;
operator +++<a href="#xml_text::unspecified_bool_type">xml_text::unspecified_bool_type</a>+++() const;
operator +++<a href="#xml_text::unspecified_bool_type">unspecified_bool_type</a>+++() const;
const char_t* +++<a href="#xml_text::get">xml_text::get</a>+++() const;
const char_t* +++<a href="#xml_text::get">get</a>+++() const;
const char_t* +++<a href="#xml_text::as_string">as_string</a>+++(const char_t* def = "") const;
int +++<a href="#xml_text::as_int">as_int</a>+++(int def = 0) const;
@@ -2996,18 +3188,23 @@ const unsigned int +++<a href="#parse_wnorm_attribute">parse_wnorm_attribute</a>
unsigned long long +++<a href="#xml_text::as_ullong">as_ullong</a>+++(unsigned long long def = 0) const;
bool +++<a href="#xml_text::set">set</a>+++(const char_t* rhs);
bool +++<a href="#xml_text::set">set</a>+++(const char_t* rhs, size_t size);
bool +++<a href="#xml_text::set">set</a>+++(string_view_t rhs);
bool +++<a href="#xml_text::set">set</a>+++(int rhs);
bool +++<a href="#xml_text::set">set</a>+++(unsigned int rhs);
bool +++<a href="#xml_text::set">set</a>+++(long rhs);
bool +++<a href="#xml_text::set">set</a>+++(unsigned long rhs);
bool +++<a href="#xml_text::set">set</a>+++(double rhs);
bool +++<a href="#xml_text::set">set</a>+++(float rhs);
bool +++<a href="#xml_text::set">set</a>+++(bool rhs);
bool +++<a href="#xml_text::set">set</a>+++(long long rhs);
bool +++<a href="#xml_text::set">set</a>+++(unsigned long long rhs);
bool +++<a href="#xml_text::set_value">set</a>+++(int rhs);
bool +++<a href="#xml_text::set_value">set</a>+++(unsigned int rhs);
bool +++<a href="#xml_text::set_value">set</a>+++(long rhs);
bool +++<a href="#xml_text::set_value">set</a>+++(unsigned long rhs);
bool +++<a href="#xml_text::set_value">set</a>+++(double rhs);
bool +++<a href="#xml_text::set_value">set</a>+++(double rhs, int precision);
bool +++<a href="#xml_text::set_value">set</a>+++(float rhs);
bool +++<a href="#xml_text::set_value">set</a>+++(float rhs, int precision);
bool +++<a href="#xml_text::set_value">set</a>+++(bool rhs);
bool +++<a href="#xml_text::set_value">set</a>+++(long long rhs);
bool +++<a href="#xml_text::set_value">set</a>+++(unsigned long long rhs);
xml_text& +++<a href="#xml_text::assign">operator=</a>+++(const char_t* rhs);
xml_text& +++<a href="#xml_text::assign">operator=</a>+++(string_view_t rhs);
xml_text& +++<a href="#xml_text::assign">operator=</a>+++(int rhs);
xml_text& +++<a href="#xml_text::assign">operator=</a>+++(unsigned int rhs);
xml_text& +++<a href="#xml_text::assign">operator=</a>+++(long rhs);
@@ -3053,7 +3250,7 @@ const unsigned int +++<a href="#parse_wnorm_attribute">parse_wnorm_attribute</a>
operator +++<a href="#xpath_query::unspecified_bool_type">unspecified_bool_type</a>+++() const;
+++<span class="tok-k">class</span> <a href="#xpath_exception">xpath_exception</a>+++: public std::exception
virtual const char* +++<a href="#xpath_exception::what">what</a>+++() const throw();
virtual const char* +++<a href="#xpath_exception::what">what</a>+++() const noexcept;
const xpath_parse_result& +++<a href="#xpath_exception::result">result</a>+++() const;
+1498 -1115
View File
File diff suppressed because it is too large Load Diff
+5 -5
View File
@@ -83,7 +83,7 @@ include::samples/load_error_handling.cpp[tags=code]
Sometimes XML data should be loaded from some other source than file, i.e. HTTP URL; also you may want to load XML data from file using non-standard functions, i.e. to use your virtual file system facilities or to load XML from gzip-compressed files. These scenarios either require loading document from memory, in which case you should prepare a contiguous memory block with all XML data and to pass it to one of buffer loading functions, or loading document from C{plus}{plus} IOstream, in which case you should provide an object which implements `std::istream` or `std::wistream` interface.
There are different functions for loading document from memory; they treat the passed buffer as either an immutable one (`load_buffer`), a mutable buffer which is owned by the caller (`load_buffer_inplace`), or a mutable buffer which ownership belongs to pugixml (`load_buffer_inplace_own`). There is also a simple helper function, `xml_document::load`, for cases when you want to load the XML document from null-terminated character string.
There are different functions for loading document from memory; they treat the passed buffer as either an immutable one (`load_buffer`), a mutable buffer which is owned by the caller (`load_buffer_inplace`), or a mutable buffer which ownership belongs to pugixml (`load_buffer_inplace_own`). There is also a simple helper function, `xml_document::load_string`, for cases when you want to load the XML document from null-terminated character string.
This is an example of loading XML document from memory using one of these functions (link:samples/load_memory.cpp[]); read the sample code for more examples:
@@ -139,7 +139,7 @@ Here is an example of using iterators for document traversal (link:samples/trave
include::samples/traverse_iter.cpp[tags=code]
----
If your C{plus}{plus} compiler supports range-based for-loop (this is a C{plus}{plus}11 feature, at the time of writing it's supported by Microsoft Visual Studio 11 Beta, GCC 4.6 and Clang 3.0), you can use it to enumerate nodes/attributes. Additional helpers are provided to support this; note that they are also compatible with http://www.boost.org/libs/foreach/[Boost Foreach], and possibly other pre-C{plus}{plus}11 foreach facilities.
If your C{plus}{plus} compiler supports range-based for-loop (this is a C{plus}{plus}11 feature, supported by Microsoft Visual Studio 2012+, GCC 4.6+ and Clang 3.0+), you can use it to enumerate nodes/attributes. Additional helpers are provided to support this; note that they are also compatible with http://www.boost.org/libs/foreach/[Boost Foreach], and possibly other pre-C{plus}{plus}11 foreach facilities.
Here is an example of using C{plus}{plus}11 range-based for loop for document traversal (link:samples/traverse_rangefor.cpp[]):
@@ -231,7 +231,7 @@ This is a simple example of saving XML document to standard output (link:samples
include::samples/save_stream.cpp[tags=code]
----
All of the above saving functions are implemented in terms of writer interface. This is a simple interface with a single function, which is called several times during output process with chunks of document data as input. In order to output the document via some custom transport, for example sockets, you should create an object which implements `xml_writer_file` interface and pass it to `xml_document::save` function.
All of the above saving functions are implemented in terms of writer interface. This is a simple interface with a single function, which is called several times during output process with chunks of document data as input. In order to output the document via some custom transport, for example sockets, you should create an object which implements `xml_writer` interface and pass it to `xml_document::save` function.
This is a simple example of custom writer for saving document data to STL string (link:samples/save_custom_writer.cpp[]); read the sample code for more complex examples:
@@ -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-2022 Arseny Kapoulkine
Copyright (c) 2006-2026 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-2022 Arseny Kapoulkine.
pugixml is Copyright (C) 2006-2026 Arseny Kapoulkine.
....
+170 -171
View File
@@ -4,9 +4,9 @@
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 2.0.17">
<meta name="generator" content="Asciidoctor 2.0.26">
<meta name="author" content="website, repository">
<title>pugixml 1.12 quick start guide</title>
<title>pugixml 1.16 quick start guide</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
<style>
/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
@@ -85,10 +85,10 @@ code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;
ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit}
ul.square{list-style-type:square}
ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc}
ul.square{list-style-type:square}
ul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
dl dt{margin-bottom:.3125em;font-weight:bold}
dl dd{margin-bottom:1.25em}
@@ -117,7 +117,6 @@ h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title str
:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
pre{color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;line-height:1.45;text-rendering:optimizeSpeed}
pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
pre>code{display:block}
pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
em em{font-style:normal}
strong strong{font-weight:400}
@@ -141,7 +140,7 @@ p a>code:hover{color:rgba(0,0,0,.9)}
#content::before{content:none}
#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}
#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}
#header .details span:first-child{margin-left:-.125em}
#header .details span.email a{color:rgba(0,0,0,.85)}
@@ -163,6 +162,7 @@ p a>code:hover{color:rgba(0,0,0,.9)}
#toctitle{color:#7a2518;font-size:1.2em}
@media screen and (min-width:768px){#toctitle{font-size:1.375em}
body.toc2{padding-left:15em;padding-right:0}
body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
#toc.toc2>ul{font-size:.9em;margin-bottom:0}
@@ -209,19 +209,17 @@ table.tableblock.fit-content>caption.title{white-space:nowrap;width:0}
.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}
.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}
.exampleblock>.content>:first-child{margin-top:0}
.exampleblock>.content>:last-child{margin-bottom:0}
.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}
.sidebarblock>:first-child{margin-top:0}
.sidebarblock>:last-child{margin-bottom:0}
.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}
.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}
@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}
@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}
.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^="highlight "]{background:#f7f7f8}
.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}
.listingblock>.content{position:relative}
.listingblock pre>code{display:block}
.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}
.listingblock:hover code[data-lang]::before{display:block}
.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}
@@ -331,7 +329,7 @@ a.image{text-decoration:none;display:inline-block}
a.image object{pointer-events:none}
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
sup.footnote a,sup.footnoteref a{text-decoration:none}
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
sup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
@@ -394,7 +392,7 @@ b.conum *{color:inherit!important}
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
p,blockquote,dt,td.content,span.alt,summary{font-size:1.0625rem}
p,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}
p{margin-bottom:1.25rem}
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}
@@ -439,78 +437,79 @@ body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-b
<style>
pre.pygments .hll { background-color: #ffffcc }
pre.pygments { background: #f8f8f8; }
pre.pygments .tok-c { color: #408080; font-style: italic } /* Comment */
pre.pygments .tok-err { border: 1px solid #FF0000 } /* Error */
pre.pygments .tok-c { color: #3D7B7B; font-style: italic } /* Comment */
pre.pygments .tok-err { border: 1px solid #F00 } /* Error */
pre.pygments .tok-k { color: #008000; font-weight: bold } /* Keyword */
pre.pygments .tok-o { color: #666666 } /* Operator */
pre.pygments .tok-ch { color: #408080; font-style: italic } /* Comment.Hashbang */
pre.pygments .tok-cm { color: #408080; font-style: italic } /* Comment.Multiline */
pre.pygments .tok-cp { color: #BC7A00 } /* Comment.Preproc */
pre.pygments .tok-cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */
pre.pygments .tok-c1 { color: #408080; font-style: italic } /* Comment.Single */
pre.pygments .tok-cs { color: #408080; font-style: italic } /* Comment.Special */
pre.pygments .tok-o { color: #666 } /* Operator */
pre.pygments .tok-ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */
pre.pygments .tok-cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */
pre.pygments .tok-cp { color: #9C6500 } /* Comment.Preproc */
pre.pygments .tok-cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */
pre.pygments .tok-c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */
pre.pygments .tok-cs { color: #3D7B7B; font-style: italic } /* Comment.Special */
pre.pygments .tok-gd { color: #A00000 } /* Generic.Deleted */
pre.pygments .tok-ge { font-style: italic } /* Generic.Emph */
pre.pygments .tok-gr { color: #FF0000 } /* Generic.Error */
pre.pygments .tok-ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
pre.pygments .tok-gr { color: #E40000 } /* Generic.Error */
pre.pygments .tok-gh { color: #000080; font-weight: bold } /* Generic.Heading */
pre.pygments .tok-gi { color: #00A000 } /* Generic.Inserted */
pre.pygments .tok-go { color: #888888 } /* Generic.Output */
pre.pygments .tok-gi { color: #008400 } /* Generic.Inserted */
pre.pygments .tok-go { color: #717171 } /* Generic.Output */
pre.pygments .tok-gp { color: #000080; font-weight: bold } /* Generic.Prompt */
pre.pygments .tok-gs { font-weight: bold } /* Generic.Strong */
pre.pygments .tok-gu { color: #800080; font-weight: bold } /* Generic.Subheading */
pre.pygments .tok-gt { color: #0044DD } /* Generic.Traceback */
pre.pygments .tok-gt { color: #04D } /* Generic.Traceback */
pre.pygments .tok-kc { color: #008000; font-weight: bold } /* Keyword.Constant */
pre.pygments .tok-kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
pre.pygments .tok-kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
pre.pygments .tok-kp { color: #008000 } /* Keyword.Pseudo */
pre.pygments .tok-kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
pre.pygments .tok-kt { color: #B00040 } /* Keyword.Type */
pre.pygments .tok-m { color: #666666 } /* Literal.Number */
pre.pygments .tok-m { color: #666 } /* Literal.Number */
pre.pygments .tok-s { color: #BA2121 } /* Literal.String */
pre.pygments .tok-na { color: #7D9029 } /* Name.Attribute */
pre.pygments .tok-na { color: #687822 } /* Name.Attribute */
pre.pygments .tok-nb { color: #008000 } /* Name.Builtin */
pre.pygments .tok-nc { color: #0000FF; font-weight: bold } /* Name.Class */
pre.pygments .tok-no { color: #880000 } /* Name.Constant */
pre.pygments .tok-nd { color: #AA22FF } /* Name.Decorator */
pre.pygments .tok-ni { color: #999999; font-weight: bold } /* Name.Entity */
pre.pygments .tok-ne { color: #D2413A; font-weight: bold } /* Name.Exception */
pre.pygments .tok-nf { color: #0000FF } /* Name.Function */
pre.pygments .tok-nl { color: #A0A000 } /* Name.Label */
pre.pygments .tok-nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
pre.pygments .tok-nc { color: #00F; font-weight: bold } /* Name.Class */
pre.pygments .tok-no { color: #800 } /* Name.Constant */
pre.pygments .tok-nd { color: #A2F } /* Name.Decorator */
pre.pygments .tok-ni { color: #717171; font-weight: bold } /* Name.Entity */
pre.pygments .tok-ne { color: #CB3F38; font-weight: bold } /* Name.Exception */
pre.pygments .tok-nf { color: #00F } /* Name.Function */
pre.pygments .tok-nl { color: #767600 } /* Name.Label */
pre.pygments .tok-nn { color: #00F; font-weight: bold } /* Name.Namespace */
pre.pygments .tok-nt { color: #008000; font-weight: bold } /* Name.Tag */
pre.pygments .tok-nv { color: #19177C } /* Name.Variable */
pre.pygments .tok-ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
pre.pygments .tok-w { color: #bbbbbb } /* Text.Whitespace */
pre.pygments .tok-mb { color: #666666 } /* Literal.Number.Bin */
pre.pygments .tok-mf { color: #666666 } /* Literal.Number.Float */
pre.pygments .tok-mh { color: #666666 } /* Literal.Number.Hex */
pre.pygments .tok-mi { color: #666666 } /* Literal.Number.Integer */
pre.pygments .tok-mo { color: #666666 } /* Literal.Number.Oct */
pre.pygments .tok-ow { color: #A2F; font-weight: bold } /* Operator.Word */
pre.pygments .tok-w { color: #BBB } /* Text.Whitespace */
pre.pygments .tok-mb { color: #666 } /* Literal.Number.Bin */
pre.pygments .tok-mf { color: #666 } /* Literal.Number.Float */
pre.pygments .tok-mh { color: #666 } /* Literal.Number.Hex */
pre.pygments .tok-mi { color: #666 } /* Literal.Number.Integer */
pre.pygments .tok-mo { color: #666 } /* Literal.Number.Oct */
pre.pygments .tok-sa { color: #BA2121 } /* Literal.String.Affix */
pre.pygments .tok-sb { color: #BA2121 } /* Literal.String.Backtick */
pre.pygments .tok-sc { color: #BA2121 } /* Literal.String.Char */
pre.pygments .tok-dl { color: #BA2121 } /* Literal.String.Delimiter */
pre.pygments .tok-sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
pre.pygments .tok-s2 { color: #BA2121 } /* Literal.String.Double */
pre.pygments .tok-se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
pre.pygments .tok-se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */
pre.pygments .tok-sh { color: #BA2121 } /* Literal.String.Heredoc */
pre.pygments .tok-si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
pre.pygments .tok-si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */
pre.pygments .tok-sx { color: #008000 } /* Literal.String.Other */
pre.pygments .tok-sr { color: #BB6688 } /* Literal.String.Regex */
pre.pygments .tok-sr { color: #A45A77 } /* Literal.String.Regex */
pre.pygments .tok-s1 { color: #BA2121 } /* Literal.String.Single */
pre.pygments .tok-ss { color: #19177C } /* Literal.String.Symbol */
pre.pygments .tok-bp { color: #008000 } /* Name.Builtin.Pseudo */
pre.pygments .tok-fm { color: #0000FF } /* Name.Function.Magic */
pre.pygments .tok-fm { color: #00F } /* Name.Function.Magic */
pre.pygments .tok-vc { color: #19177C } /* Name.Variable.Class */
pre.pygments .tok-vg { color: #19177C } /* Name.Variable.Global */
pre.pygments .tok-vi { color: #19177C } /* Name.Variable.Instance */
pre.pygments .tok-vm { color: #19177C } /* Name.Variable.Magic */
pre.pygments .tok-il { color: #666666 } /* Literal.Number.Integer.Long */
pre.pygments .tok-il { color: #666 } /* Literal.Number.Integer.Long */
</style>
</head>
<body class="article toc2 toc-right">
<div id="header">
<h1>pugixml 1.12 quick start guide</h1>
<h1>pugixml 1.16 quick start guide</h1>
<div class="details">
<span id="author" class="author">website</span><br>
<span id="email" class="email"><a href="https://pugixml.org" class="bare">https://pugixml.org</a></span><br>
@@ -566,9 +565,9 @@ No documentation is perfect; neither is this one. If you find errors or omission
<p>You can download the latest source distribution as an archive:</p>
</div>
<div class="paragraph">
<p><a href="https://github.com/zeux/pugixml/releases/download/v1.12/pugixml-1.12.zip">pugixml-1.12.zip</a> (Windows line endings)
<p><a href="https://github.com/zeux/pugixml/releases/download/v1.16/pugixml-1.16.zip">pugixml-1.16.zip</a> (Windows line endings)
/
<a href="https://github.com/zeux/pugixml/releases/download/v1.12/pugixml-1.12.tar.gz">pugixml-1.12.tar.gz</a> (Unix line endings)</p>
<a href="https://github.com/zeux/pugixml/releases/download/v1.16/pugixml-1.16.tar.gz">pugixml-1.16.tar.gz</a> (Unix line endings)</p>
</div>
<div class="paragraph">
<p>The distribution contains library source, documentation (the guide you&#8217;re reading now and the manual) and some code examples. After downloading the distribution, install pugixml by extracting all files from the compressed archive.</p>
@@ -652,11 +651,11 @@ All pugixml classes and functions are located in <code>pugi</code> namespace; yo
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_document</span><span class="tok-w"> </span><span class="tok-n">doc</span><span class="tok-p">;</span><span class="tok-w"></span>
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_document</span><span class="tok-w"> </span><span class="tok-n">doc</span><span class="tok-p">;</span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_parse_result</span><span class="tok-w"> </span><span class="tok-n">result</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">load_file</span><span class="tok-p">(</span><span class="tok-s">&quot;tree.xml&quot;</span><span class="tok-p">);</span><span class="tok-w"></span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_parse_result</span><span class="tok-w"> </span><span class="tok-n">result</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">load_file</span><span class="tok-p">(</span><span class="tok-s">&quot;tree.xml&quot;</span><span class="tok-p">);</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;Load result: &quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">result</span><span class="tok-p">.</span><span class="tok-n">description</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;, mesh name: &quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">child</span><span class="tok-p">(</span><span class="tok-s">&quot;mesh&quot;</span><span class="tok-p">).</span><span class="tok-n">attribute</span><span class="tok-p">(</span><span class="tok-s">&quot;name&quot;</span><span class="tok-p">).</span><span class="tok-n">value</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span><span class="tok-w"></span></code></pre>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;Load result: &quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">result</span><span class="tok-p">.</span><span class="tok-n">description</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;, mesh name: &quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">child</span><span class="tok-p">(</span><span class="tok-s">&quot;mesh&quot;</span><span class="tok-p">).</span><span class="tok-n">attribute</span><span class="tok-p">(</span><span class="tok-s">&quot;name&quot;</span><span class="tok-p">).</span><span class="tok-n">value</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
@@ -670,47 +669,47 @@ All pugixml classes and functions are located in <code>pugi</code> namespace; yo
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_document</span><span class="tok-w"> </span><span class="tok-n">doc</span><span class="tok-p">;</span><span class="tok-w"></span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_parse_result</span><span class="tok-w"> </span><span class="tok-n">result</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">load_string</span><span class="tok-p">(</span><span class="tok-n">source</span><span class="tok-p">);</span><span class="tok-w"></span>
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_document</span><span class="tok-w"> </span><span class="tok-n">doc</span><span class="tok-p">;</span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_parse_result</span><span class="tok-w"> </span><span class="tok-n">result</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">load_string</span><span class="tok-p">(</span><span class="tok-n">source</span><span class="tok-p">);</span>
<span class="tok-k">if</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-n">result</span><span class="tok-p">)</span><span class="tok-w"></span>
<span class="tok-p">{</span><span class="tok-w"></span>
<span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;XML [&quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">source</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;] parsed without errors, attr value: [&quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">child</span><span class="tok-p">(</span><span class="tok-s">&quot;node&quot;</span><span class="tok-p">).</span><span class="tok-n">attribute</span><span class="tok-p">(</span><span class="tok-s">&quot;attr&quot;</span><span class="tok-p">).</span><span class="tok-n">value</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;]</span><span class="tok-se">\n\n</span><span class="tok-s">&quot;</span><span class="tok-p">;</span><span class="tok-w"></span>
<span class="tok-p">}</span><span class="tok-w"></span>
<span class="tok-k">else</span><span class="tok-w"></span>
<span class="tok-p">{</span><span class="tok-w"></span>
<span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;XML [&quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">source</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;] parsed with errors, attr value: [&quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">child</span><span class="tok-p">(</span><span class="tok-s">&quot;node&quot;</span><span class="tok-p">).</span><span class="tok-n">attribute</span><span class="tok-p">(</span><span class="tok-s">&quot;attr&quot;</span><span class="tok-p">).</span><span class="tok-n">value</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;]</span><span class="tok-se">\n</span><span class="tok-s">&quot;</span><span class="tok-p">;</span><span class="tok-w"></span>
<span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;Error description: &quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">result</span><span class="tok-p">.</span><span class="tok-n">description</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;</span><span class="tok-se">\n</span><span class="tok-s">&quot;</span><span class="tok-p">;</span><span class="tok-w"></span>
<span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;Error offset: &quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">result</span><span class="tok-p">.</span><span class="tok-n">offset</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot; (error at [...&quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-n">source</span><span class="tok-w"> </span><span class="tok-o">+</span><span class="tok-w"> </span><span class="tok-n">result</span><span class="tok-p">.</span><span class="tok-n">offset</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;]</span><span class="tok-se">\n\n</span><span class="tok-s">&quot;</span><span class="tok-p">;</span><span class="tok-w"></span>
<span class="tok-p">}</span><span class="tok-w"></span></code></pre>
<span class="tok-k">if</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-n">result</span><span class="tok-p">)</span>
<span class="tok-p">{</span>
<span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;XML [&quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">source</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;] parsed without errors, attr value: [&quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">child</span><span class="tok-p">(</span><span class="tok-s">&quot;node&quot;</span><span class="tok-p">).</span><span class="tok-n">attribute</span><span class="tok-p">(</span><span class="tok-s">&quot;attr&quot;</span><span class="tok-p">).</span><span class="tok-n">value</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;]</span><span class="tok-se">\n\n</span><span class="tok-s">&quot;</span><span class="tok-p">;</span>
<span class="tok-p">}</span>
<span class="tok-k">else</span>
<span class="tok-p">{</span>
<span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;XML [&quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">source</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;] parsed with errors, attr value: [&quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">child</span><span class="tok-p">(</span><span class="tok-s">&quot;node&quot;</span><span class="tok-p">).</span><span class="tok-n">attribute</span><span class="tok-p">(</span><span class="tok-s">&quot;attr&quot;</span><span class="tok-p">).</span><span class="tok-n">value</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;]</span><span class="tok-se">\n</span><span class="tok-s">&quot;</span><span class="tok-p">;</span>
<span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;Error description: &quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">result</span><span class="tok-p">.</span><span class="tok-n">description</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;</span><span class="tok-se">\n</span><span class="tok-s">&quot;</span><span class="tok-p">;</span>
<span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;Error offset: &quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">result</span><span class="tok-p">.</span><span class="tok-n">offset</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot; (error at [...&quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-n">source</span><span class="tok-w"> </span><span class="tok-o">+</span><span class="tok-w"> </span><span class="tok-n">result</span><span class="tok-p">.</span><span class="tok-n">offset</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;]</span><span class="tok-se">\n\n</span><span class="tok-s">&quot;</span><span class="tok-p">;</span>
<span class="tok-p">}</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Sometimes XML data should be loaded from some other source than file, i.e. HTTP URL; also you may want to load XML data from file using non-standard functions, i.e. to use your virtual file system facilities or to load XML from gzip-compressed files. These scenarios either require loading document from memory, in which case you should prepare a contiguous memory block with all XML data and to pass it to one of buffer loading functions, or loading document from C&#43;&#43; IOstream, in which case you should provide an object which implements <code>std::istream</code> or <code>std::wistream</code> interface.</p>
</div>
<div class="paragraph">
<p>There are different functions for loading document from memory; they treat the passed buffer as either an immutable one (<code>load_buffer</code>), a mutable buffer which is owned by the caller (<code>load_buffer_inplace</code>), or a mutable buffer which ownership belongs to pugixml (<code>load_buffer_inplace_own</code>). There is also a simple helper function, <code>xml_document::load</code>, for cases when you want to load the XML document from null-terminated character string.</p>
<p>There are different functions for loading document from memory; they treat the passed buffer as either an immutable one (<code>load_buffer</code>), a mutable buffer which is owned by the caller (<code>load_buffer_inplace</code>), or a mutable buffer which ownership belongs to pugixml (<code>load_buffer_inplace_own</code>). There is also a simple helper function, <code>xml_document::load_string</code>, for cases when you want to load the XML document from null-terminated character string.</p>
</div>
<div class="paragraph">
<p>This is an example of loading XML document from memory using one of these functions (<a href="samples/load_memory.cpp" class="bare">samples/load_memory.cpp</a>); read the sample code for more examples:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-k">const</span><span class="tok-w"> </span><span class="tok-kt">char</span><span class="tok-w"> </span><span class="tok-n">source</span><span class="tok-p">[]</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-s">&quot;&lt;mesh name=&#39;sphere&#39;&gt;&lt;bounds&gt;0 0 1 1&lt;/bounds&gt;&lt;/mesh&gt;&quot;</span><span class="tok-p">;</span><span class="tok-w"></span>
<span class="tok-kt">size_t</span><span class="tok-w"> </span><span class="tok-n">size</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-k">sizeof</span><span class="tok-p">(</span><span class="tok-n">source</span><span class="tok-p">);</span><span class="tok-w"></span></code></pre>
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-k">const</span><span class="tok-w"> </span><span class="tok-kt">char</span><span class="tok-w"> </span><span class="tok-n">source</span><span class="tok-p">[]</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-s">&quot;&lt;mesh name=&#39;sphere&#39;&gt;&lt;bounds&gt;0 0 1 1&lt;/bounds&gt;&lt;/mesh&gt;&quot;</span><span class="tok-p">;</span>
<span class="tok-kt">size_t</span><span class="tok-w"> </span><span class="tok-n">size</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-k">sizeof</span><span class="tok-p">(</span><span class="tok-n">source</span><span class="tok-p">);</span></code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-c1">// You can use load_buffer_inplace to load document from mutable memory block; the block&#39;s lifetime must exceed that of document</span>
<span class="tok-kt">char</span><span class="tok-o">*</span><span class="tok-w"> </span><span class="tok-n">buffer</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-k">new</span><span class="tok-w"> </span><span class="tok-kt">char</span><span class="tok-p">[</span><span class="tok-n">size</span><span class="tok-p">];</span><span class="tok-w"></span>
<span class="tok-n">memcpy</span><span class="tok-p">(</span><span class="tok-n">buffer</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-n">source</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-n">size</span><span class="tok-p">);</span><span class="tok-w"></span>
<span class="tok-kt">char</span><span class="tok-o">*</span><span class="tok-w"> </span><span class="tok-n">buffer</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-k">new</span><span class="tok-w"> </span><span class="tok-kt">char</span><span class="tok-p">[</span><span class="tok-n">size</span><span class="tok-p">];</span>
<span class="tok-n">memcpy</span><span class="tok-p">(</span><span class="tok-n">buffer</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-n">source</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-n">size</span><span class="tok-p">);</span>
<span class="tok-c1">// The block can be allocated by any method; the block is modified during parsing</span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_parse_result</span><span class="tok-w"> </span><span class="tok-n">result</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">load_buffer_inplace</span><span class="tok-p">(</span><span class="tok-n">buffer</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-n">size</span><span class="tok-p">);</span><span class="tok-w"></span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_parse_result</span><span class="tok-w"> </span><span class="tok-n">result</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">load_buffer_inplace</span><span class="tok-p">(</span><span class="tok-n">buffer</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-n">size</span><span class="tok-p">);</span>
<span class="tok-c1">// You have to destroy the block yourself after the document is no longer used</span>
<span class="tok-k">delete</span><span class="tok-p">[]</span><span class="tok-w"> </span><span class="tok-n">buffer</span><span class="tok-p">;</span><span class="tok-w"></span></code></pre>
<span class="tok-k">delete</span><span class="tok-p">[]</span><span class="tok-w"> </span><span class="tok-n">buffer</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
@@ -718,8 +717,8 @@ All pugixml classes and functions are located in <code>pugi</code> namespace; yo
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">ifstream</span><span class="tok-w"> </span><span class="tok-nf">stream</span><span class="tok-p">(</span><span class="tok-s">&quot;weekly-utf-8.xml&quot;</span><span class="tok-p">);</span><span class="tok-w"></span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_parse_result</span><span class="tok-w"> </span><span class="tok-n">result</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">load</span><span class="tok-p">(</span><span class="tok-n">stream</span><span class="tok-p">);</span><span class="tok-w"></span></code></pre>
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">ifstream</span><span class="tok-w"> </span><span class="tok-n">stream</span><span class="tok-p">(</span><span class="tok-s">&quot;weekly-utf-8.xml&quot;</span><span class="tok-p">);</span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_parse_result</span><span class="tok-w"> </span><span class="tok-n">result</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">load</span><span class="tok-p">(</span><span class="tok-n">stream</span><span class="tok-p">);</span></code></pre>
</div>
</div>
</div>
@@ -748,13 +747,13 @@ All pugixml classes and functions are located in <code>pugi</code> namespace; yo
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-k">for</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_node</span><span class="tok-w"> </span><span class="tok-n">tool</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">tools</span><span class="tok-p">.</span><span class="tok-n">child</span><span class="tok-p">(</span><span class="tok-s">&quot;Tool&quot;</span><span class="tok-p">);</span><span class="tok-w"> </span><span class="tok-n">tool</span><span class="tok-p">;</span><span class="tok-w"> </span><span class="tok-n">tool</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">tool</span><span class="tok-p">.</span><span class="tok-n">next_sibling</span><span class="tok-p">(</span><span class="tok-s">&quot;Tool&quot;</span><span class="tok-p">))</span><span class="tok-w"></span>
<span class="tok-p">{</span><span class="tok-w"></span>
<span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;Tool &quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">tool</span><span class="tok-p">.</span><span class="tok-n">attribute</span><span class="tok-p">(</span><span class="tok-s">&quot;Filename&quot;</span><span class="tok-p">).</span><span class="tok-n">value</span><span class="tok-p">();</span><span class="tok-w"></span>
<span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;: AllowRemote &quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">tool</span><span class="tok-p">.</span><span class="tok-n">attribute</span><span class="tok-p">(</span><span class="tok-s">&quot;AllowRemote&quot;</span><span class="tok-p">).</span><span class="tok-n">as_bool</span><span class="tok-p">();</span><span class="tok-w"></span>
<span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;, Timeout &quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">tool</span><span class="tok-p">.</span><span class="tok-n">attribute</span><span class="tok-p">(</span><span class="tok-s">&quot;Timeout&quot;</span><span class="tok-p">).</span><span class="tok-n">as_int</span><span class="tok-p">();</span><span class="tok-w"></span>
<span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;, Description &#39;&quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">tool</span><span class="tok-p">.</span><span class="tok-n">child_value</span><span class="tok-p">(</span><span class="tok-s">&quot;Description&quot;</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;&#39;</span><span class="tok-se">\n</span><span class="tok-s">&quot;</span><span class="tok-p">;</span><span class="tok-w"></span>
<span class="tok-p">}</span><span class="tok-w"></span></code></pre>
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-k">for</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_node</span><span class="tok-w"> </span><span class="tok-n">tool</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">tools</span><span class="tok-p">.</span><span class="tok-n">child</span><span class="tok-p">(</span><span class="tok-s">&quot;Tool&quot;</span><span class="tok-p">);</span><span class="tok-w"> </span><span class="tok-n">tool</span><span class="tok-p">;</span><span class="tok-w"> </span><span class="tok-n">tool</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">tool</span><span class="tok-p">.</span><span class="tok-n">next_sibling</span><span class="tok-p">(</span><span class="tok-s">&quot;Tool&quot;</span><span class="tok-p">))</span>
<span class="tok-p">{</span>
<span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;Tool &quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">tool</span><span class="tok-p">.</span><span class="tok-n">attribute</span><span class="tok-p">(</span><span class="tok-s">&quot;Filename&quot;</span><span class="tok-p">).</span><span class="tok-n">value</span><span class="tok-p">();</span>
<span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;: AllowRemote &quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">tool</span><span class="tok-p">.</span><span class="tok-n">attribute</span><span class="tok-p">(</span><span class="tok-s">&quot;AllowRemote&quot;</span><span class="tok-p">).</span><span class="tok-n">as_bool</span><span class="tok-p">();</span>
<span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;, Timeout &quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">tool</span><span class="tok-p">.</span><span class="tok-n">attribute</span><span class="tok-p">(</span><span class="tok-s">&quot;Timeout&quot;</span><span class="tok-p">).</span><span class="tok-n">as_int</span><span class="tok-p">();</span>
<span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;, Description &#39;&quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">tool</span><span class="tok-p">.</span><span class="tok-n">child_value</span><span class="tok-p">(</span><span class="tok-s">&quot;Description&quot;</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;&#39;</span><span class="tok-se">\n</span><span class="tok-s">&quot;</span><span class="tok-p">;</span>
<span class="tok-p">}</span></code></pre>
</div>
</div>
<div class="paragraph">
@@ -762,12 +761,12 @@ All pugixml classes and functions are located in <code>pugi</code> namespace; yo
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;Tool for *.dae generation: &quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">tools</span><span class="tok-p">.</span><span class="tok-n">find_child_by_attribute</span><span class="tok-p">(</span><span class="tok-s">&quot;Tool&quot;</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-s">&quot;OutputFileMasks&quot;</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-s">&quot;*.dae&quot;</span><span class="tok-p">).</span><span class="tok-n">attribute</span><span class="tok-p">(</span><span class="tok-s">&quot;Filename&quot;</span><span class="tok-p">).</span><span class="tok-n">value</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;</span><span class="tok-se">\n</span><span class="tok-s">&quot;</span><span class="tok-p">;</span><span class="tok-w"></span>
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;Tool for *.dae generation: &quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">tools</span><span class="tok-p">.</span><span class="tok-n">find_child_by_attribute</span><span class="tok-p">(</span><span class="tok-s">&quot;Tool&quot;</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-s">&quot;OutputFileMasks&quot;</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-s">&quot;*.dae&quot;</span><span class="tok-p">).</span><span class="tok-n">attribute</span><span class="tok-p">(</span><span class="tok-s">&quot;Filename&quot;</span><span class="tok-p">).</span><span class="tok-n">value</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;</span><span class="tok-se">\n</span><span class="tok-s">&quot;</span><span class="tok-p">;</span>
<span class="tok-k">for</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_node</span><span class="tok-w"> </span><span class="tok-n">tool</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">tools</span><span class="tok-p">.</span><span class="tok-n">child</span><span class="tok-p">(</span><span class="tok-s">&quot;Tool&quot;</span><span class="tok-p">);</span><span class="tok-w"> </span><span class="tok-n">tool</span><span class="tok-p">;</span><span class="tok-w"> </span><span class="tok-n">tool</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">tool</span><span class="tok-p">.</span><span class="tok-n">next_sibling</span><span class="tok-p">(</span><span class="tok-s">&quot;Tool&quot;</span><span class="tok-p">))</span><span class="tok-w"></span>
<span class="tok-p">{</span><span class="tok-w"></span>
<span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;Tool &quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">tool</span><span class="tok-p">.</span><span class="tok-n">attribute</span><span class="tok-p">(</span><span class="tok-s">&quot;Filename&quot;</span><span class="tok-p">).</span><span class="tok-n">value</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;</span><span class="tok-se">\n</span><span class="tok-s">&quot;</span><span class="tok-p">;</span><span class="tok-w"></span>
<span class="tok-p">}</span><span class="tok-w"></span></code></pre>
<span class="tok-k">for</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_node</span><span class="tok-w"> </span><span class="tok-n">tool</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">tools</span><span class="tok-p">.</span><span class="tok-n">child</span><span class="tok-p">(</span><span class="tok-s">&quot;Tool&quot;</span><span class="tok-p">);</span><span class="tok-w"> </span><span class="tok-n">tool</span><span class="tok-p">;</span><span class="tok-w"> </span><span class="tok-n">tool</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">tool</span><span class="tok-p">.</span><span class="tok-n">next_sibling</span><span class="tok-p">(</span><span class="tok-s">&quot;Tool&quot;</span><span class="tok-p">))</span>
<span class="tok-p">{</span>
<span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;Tool &quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">tool</span><span class="tok-p">.</span><span class="tok-n">attribute</span><span class="tok-p">(</span><span class="tok-s">&quot;Filename&quot;</span><span class="tok-p">).</span><span class="tok-n">value</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;</span><span class="tok-se">\n</span><span class="tok-s">&quot;</span><span class="tok-p">;</span>
<span class="tok-p">}</span></code></pre>
</div>
</div>
<div class="paragraph">
@@ -778,43 +777,43 @@ All pugixml classes and functions are located in <code>pugi</code> namespace; yo
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-k">for</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_node_iterator</span><span class="tok-w"> </span><span class="tok-n">it</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">tools</span><span class="tok-p">.</span><span class="tok-n">begin</span><span class="tok-p">();</span><span class="tok-w"> </span><span class="tok-n">it</span><span class="tok-w"> </span><span class="tok-o">!=</span><span class="tok-w"> </span><span class="tok-n">tools</span><span class="tok-p">.</span><span class="tok-n">end</span><span class="tok-p">();</span><span class="tok-w"> </span><span class="tok-o">++</span><span class="tok-n">it</span><span class="tok-p">)</span><span class="tok-w"></span>
<span class="tok-p">{</span><span class="tok-w"></span>
<span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;Tool:&quot;</span><span class="tok-p">;</span><span class="tok-w"></span>
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-k">for</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_node_iterator</span><span class="tok-w"> </span><span class="tok-n">it</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">tools</span><span class="tok-p">.</span><span class="tok-n">begin</span><span class="tok-p">();</span><span class="tok-w"> </span><span class="tok-n">it</span><span class="tok-w"> </span><span class="tok-o">!=</span><span class="tok-w"> </span><span class="tok-n">tools</span><span class="tok-p">.</span><span class="tok-n">end</span><span class="tok-p">();</span><span class="tok-w"> </span><span class="tok-o">++</span><span class="tok-n">it</span><span class="tok-p">)</span>
<span class="tok-p">{</span>
<span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;Tool:&quot;</span><span class="tok-p">;</span>
<span class="tok-w"> </span><span class="tok-k">for</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_attribute_iterator</span><span class="tok-w"> </span><span class="tok-n">ait</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">it</span><span class="tok-o">-&gt;</span><span class="tok-n">attributes_begin</span><span class="tok-p">();</span><span class="tok-w"> </span><span class="tok-n">ait</span><span class="tok-w"> </span><span class="tok-o">!=</span><span class="tok-w"> </span><span class="tok-n">it</span><span class="tok-o">-&gt;</span><span class="tok-n">attributes_end</span><span class="tok-p">();</span><span class="tok-w"> </span><span class="tok-o">++</span><span class="tok-n">ait</span><span class="tok-p">)</span><span class="tok-w"></span>
<span class="tok-w"> </span><span class="tok-p">{</span><span class="tok-w"></span>
<span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot; &quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">ait</span><span class="tok-o">-&gt;</span><span class="tok-n">name</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;=&quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">ait</span><span class="tok-o">-&gt;</span><span class="tok-n">value</span><span class="tok-p">();</span><span class="tok-w"></span>
<span class="tok-w"> </span><span class="tok-p">}</span><span class="tok-w"></span>
<span class="tok-w"> </span><span class="tok-k">for</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_attribute_iterator</span><span class="tok-w"> </span><span class="tok-n">ait</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">it</span><span class="tok-o">-&gt;</span><span class="tok-n">attributes_begin</span><span class="tok-p">();</span><span class="tok-w"> </span><span class="tok-n">ait</span><span class="tok-w"> </span><span class="tok-o">!=</span><span class="tok-w"> </span><span class="tok-n">it</span><span class="tok-o">-&gt;</span><span class="tok-n">attributes_end</span><span class="tok-p">();</span><span class="tok-w"> </span><span class="tok-o">++</span><span class="tok-n">ait</span><span class="tok-p">)</span>
<span class="tok-w"> </span><span class="tok-p">{</span>
<span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot; &quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">ait</span><span class="tok-o">-&gt;</span><span class="tok-n">name</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;=&quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">ait</span><span class="tok-o">-&gt;</span><span class="tok-n">value</span><span class="tok-p">();</span>
<span class="tok-w"> </span><span class="tok-p">}</span>
<span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span><span class="tok-w"></span>
<span class="tok-p">}</span><span class="tok-w"></span></code></pre>
<span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span>
<span class="tok-p">}</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>If your C&#43;&#43; compiler supports range-based for-loop (this is a C&#43;&#43;11 feature, at the time of writing it&#8217;s supported by Microsoft Visual Studio 11 Beta, GCC 4.6 and Clang 3.0), you can use it to enumerate nodes/attributes. Additional helpers are provided to support this; note that they are also compatible with <a href="http://www.boost.org/libs/foreach/">Boost Foreach</a>, and possibly other pre-C&#43;&#43;11 foreach facilities.</p>
<p>If your C&#43;&#43; compiler supports range-based for-loop (this is a C&#43;&#43;11 feature, supported by Microsoft Visual Studio 2012+, GCC 4.6+ and Clang 3.0+), you can use it to enumerate nodes/attributes. Additional helpers are provided to support this; note that they are also compatible with <a href="http://www.boost.org/libs/foreach/">Boost Foreach</a>, and possibly other pre-C&#43;&#43;11 foreach facilities.</p>
</div>
<div class="paragraph">
<p>Here is an example of using C&#43;&#43;11 range-based for loop for document traversal (<a href="samples/traverse_rangefor.cpp" class="bare">samples/traverse_rangefor.cpp</a>):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-k">for</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_node</span><span class="tok-w"> </span><span class="tok-nl">tool</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-n">tools</span><span class="tok-p">.</span><span class="tok-n">children</span><span class="tok-p">(</span><span class="tok-s">&quot;Tool&quot;</span><span class="tok-p">))</span><span class="tok-w"></span>
<span class="tok-p">{</span><span class="tok-w"></span>
<span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;Tool:&quot;</span><span class="tok-p">;</span><span class="tok-w"></span>
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-k">for</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_node</span><span class="tok-w"> </span><span class="tok-n">tool</span><span class="tok-o">:</span><span class="tok-w"> </span><span class="tok-n">tools</span><span class="tok-p">.</span><span class="tok-n">children</span><span class="tok-p">(</span><span class="tok-s">&quot;Tool&quot;</span><span class="tok-p">))</span>
<span class="tok-p">{</span>
<span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;Tool:&quot;</span><span class="tok-p">;</span>
<span class="tok-w"> </span><span class="tok-k">for</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_attribute</span><span class="tok-w"> </span><span class="tok-nl">attr</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-n">tool</span><span class="tok-p">.</span><span class="tok-n">attributes</span><span class="tok-p">())</span><span class="tok-w"></span>
<span class="tok-w"> </span><span class="tok-p">{</span><span class="tok-w"></span>
<span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot; &quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">attr</span><span class="tok-p">.</span><span class="tok-n">name</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;=&quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">attr</span><span class="tok-p">.</span><span class="tok-n">value</span><span class="tok-p">();</span><span class="tok-w"></span>
<span class="tok-w"> </span><span class="tok-p">}</span><span class="tok-w"></span>
<span class="tok-w"> </span><span class="tok-k">for</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_attribute</span><span class="tok-w"> </span><span class="tok-n">attr</span><span class="tok-o">:</span><span class="tok-w"> </span><span class="tok-n">tool</span><span class="tok-p">.</span><span class="tok-n">attributes</span><span class="tok-p">())</span>
<span class="tok-w"> </span><span class="tok-p">{</span>
<span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot; &quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">attr</span><span class="tok-p">.</span><span class="tok-n">name</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;=&quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">attr</span><span class="tok-p">.</span><span class="tok-n">value</span><span class="tok-p">();</span>
<span class="tok-w"> </span><span class="tok-p">}</span>
<span class="tok-w"> </span><span class="tok-k">for</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_node</span><span class="tok-w"> </span><span class="tok-nl">child</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-n">tool</span><span class="tok-p">.</span><span class="tok-n">children</span><span class="tok-p">())</span><span class="tok-w"></span>
<span class="tok-w"> </span><span class="tok-p">{</span><span class="tok-w"></span>
<span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;, child &quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">child</span><span class="tok-p">.</span><span class="tok-n">name</span><span class="tok-p">();</span><span class="tok-w"></span>
<span class="tok-w"> </span><span class="tok-p">}</span><span class="tok-w"></span>
<span class="tok-w"> </span><span class="tok-k">for</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_node</span><span class="tok-w"> </span><span class="tok-n">child</span><span class="tok-o">:</span><span class="tok-w"> </span><span class="tok-n">tool</span><span class="tok-p">.</span><span class="tok-n">children</span><span class="tok-p">())</span>
<span class="tok-w"> </span><span class="tok-p">{</span>
<span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;, child &quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">child</span><span class="tok-p">.</span><span class="tok-n">name</span><span class="tok-p">();</span>
<span class="tok-w"> </span><span class="tok-p">}</span>
<span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span><span class="tok-w"></span>
<span class="tok-p">}</span><span class="tok-w"></span></code></pre>
<span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span>
<span class="tok-p">}</span></code></pre>
</div>
</div>
<div class="paragraph">
@@ -825,23 +824,23 @@ All pugixml classes and functions are located in <code>pugi</code> namespace; yo
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-k">struct</span> <span class="tok-nc">simple_walker</span><span class="tok-o">:</span><span class="tok-w"> </span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_tree_walker</span><span class="tok-w"></span>
<span class="tok-p">{</span><span class="tok-w"></span>
<span class="tok-w"> </span><span class="tok-k">virtual</span><span class="tok-w"> </span><span class="tok-kt">bool</span><span class="tok-w"> </span><span class="tok-nf">for_each</span><span class="tok-p">(</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_node</span><span class="tok-o">&amp;</span><span class="tok-w"> </span><span class="tok-n">node</span><span class="tok-p">)</span><span class="tok-w"></span>
<span class="tok-w"> </span><span class="tok-p">{</span><span class="tok-w"></span>
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-k">struct</span><span class="tok-w"> </span><span class="tok-nc">simple_walker</span><span class="tok-o">:</span><span class="tok-w"> </span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_tree_walker</span>
<span class="tok-p">{</span>
<span class="tok-w"> </span><span class="tok-k">virtual</span><span class="tok-w"> </span><span class="tok-kt">bool</span><span class="tok-w"> </span><span class="tok-nf">for_each</span><span class="tok-p">(</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_node</span><span class="tok-o">&amp;</span><span class="tok-w"> </span><span class="tok-n">node</span><span class="tok-p">)</span>
<span class="tok-w"> </span><span class="tok-p">{</span>
<span class="tok-w"> </span><span class="tok-k">for</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-kt">int</span><span class="tok-w"> </span><span class="tok-n">i</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-mi">0</span><span class="tok-p">;</span><span class="tok-w"> </span><span class="tok-n">i</span><span class="tok-w"> </span><span class="tok-o">&lt;</span><span class="tok-w"> </span><span class="tok-n">depth</span><span class="tok-p">();</span><span class="tok-w"> </span><span class="tok-o">++</span><span class="tok-n">i</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot; &quot;</span><span class="tok-p">;</span><span class="tok-w"> </span><span class="tok-c1">// indentation</span>
<span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">node_types</span><span class="tok-p">[</span><span class="tok-n">node</span><span class="tok-p">.</span><span class="tok-n">type</span><span class="tok-p">()]</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;: name=&#39;&quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">node</span><span class="tok-p">.</span><span class="tok-n">name</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;&#39;, value=&#39;&quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">node</span><span class="tok-p">.</span><span class="tok-n">value</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;&#39;</span><span class="tok-se">\n</span><span class="tok-s">&quot;</span><span class="tok-p">;</span><span class="tok-w"></span>
<span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">node_types</span><span class="tok-p">[</span><span class="tok-n">node</span><span class="tok-p">.</span><span class="tok-n">type</span><span class="tok-p">()]</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;: name=&#39;&quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">node</span><span class="tok-p">.</span><span class="tok-n">name</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;&#39;, value=&#39;&quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">node</span><span class="tok-p">.</span><span class="tok-n">value</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;&#39;</span><span class="tok-se">\n</span><span class="tok-s">&quot;</span><span class="tok-p">;</span>
<span class="tok-w"> </span><span class="tok-k">return</span><span class="tok-w"> </span><span class="tok-nb">true</span><span class="tok-p">;</span><span class="tok-w"> </span><span class="tok-c1">// continue traversal</span>
<span class="tok-w"> </span><span class="tok-p">}</span><span class="tok-w"></span>
<span class="tok-p">};</span><span class="tok-w"></span></code></pre>
<span class="tok-w"> </span><span class="tok-p">}</span>
<span class="tok-p">};</span></code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-n">simple_walker</span><span class="tok-w"> </span><span class="tok-n">walker</span><span class="tok-p">;</span><span class="tok-w"></span>
<span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">traverse</span><span class="tok-p">(</span><span class="tok-n">walker</span><span class="tok-p">);</span><span class="tok-w"></span></code></pre>
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-n">simple_walker</span><span class="tok-w"> </span><span class="tok-n">walker</span><span class="tok-p">;</span>
<span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">traverse</span><span class="tok-p">(</span><span class="tok-n">walker</span><span class="tok-p">);</span></code></pre>
</div>
</div>
<div class="paragraph">
@@ -849,20 +848,20 @@ All pugixml classes and functions are located in <code>pugi</code> namespace; yo
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_node_set</span><span class="tok-w"> </span><span class="tok-n">tools</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">select_nodes</span><span class="tok-p">(</span><span class="tok-s">&quot;/Profile/Tools/Tool[@AllowRemote=&#39;true&#39; and @DeriveCaptionFrom=&#39;lastparam&#39;]&quot;</span><span class="tok-p">);</span><span class="tok-w"></span>
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_node_set</span><span class="tok-w"> </span><span class="tok-n">tools</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">select_nodes</span><span class="tok-p">(</span><span class="tok-s">&quot;/Profile/Tools/Tool[@AllowRemote=&#39;true&#39; and @DeriveCaptionFrom=&#39;lastparam&#39;]&quot;</span><span class="tok-p">);</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;Tools:</span><span class="tok-se">\n</span><span class="tok-s">&quot;</span><span class="tok-p">;</span><span class="tok-w"></span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;Tools:</span><span class="tok-se">\n</span><span class="tok-s">&quot;</span><span class="tok-p">;</span>
<span class="tok-k">for</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_node_set</span><span class="tok-o">::</span><span class="tok-n">const_iterator</span><span class="tok-w"> </span><span class="tok-n">it</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">tools</span><span class="tok-p">.</span><span class="tok-n">begin</span><span class="tok-p">();</span><span class="tok-w"> </span><span class="tok-n">it</span><span class="tok-w"> </span><span class="tok-o">!=</span><span class="tok-w"> </span><span class="tok-n">tools</span><span class="tok-p">.</span><span class="tok-n">end</span><span class="tok-p">();</span><span class="tok-w"> </span><span class="tok-o">++</span><span class="tok-n">it</span><span class="tok-p">)</span><span class="tok-w"></span>
<span class="tok-p">{</span><span class="tok-w"></span>
<span class="tok-w"> </span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_node</span><span class="tok-w"> </span><span class="tok-n">node</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-o">*</span><span class="tok-n">it</span><span class="tok-p">;</span><span class="tok-w"></span>
<span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">node</span><span class="tok-p">.</span><span class="tok-n">node</span><span class="tok-p">().</span><span class="tok-n">attribute</span><span class="tok-p">(</span><span class="tok-s">&quot;Filename&quot;</span><span class="tok-p">).</span><span class="tok-n">value</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;</span><span class="tok-se">\n</span><span class="tok-s">&quot;</span><span class="tok-p">;</span><span class="tok-w"></span>
<span class="tok-p">}</span><span class="tok-w"></span>
<span class="tok-k">for</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_node_set</span><span class="tok-o">::</span><span class="tok-n">const_iterator</span><span class="tok-w"> </span><span class="tok-n">it</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">tools</span><span class="tok-p">.</span><span class="tok-n">begin</span><span class="tok-p">();</span><span class="tok-w"> </span><span class="tok-n">it</span><span class="tok-w"> </span><span class="tok-o">!=</span><span class="tok-w"> </span><span class="tok-n">tools</span><span class="tok-p">.</span><span class="tok-n">end</span><span class="tok-p">();</span><span class="tok-w"> </span><span class="tok-o">++</span><span class="tok-n">it</span><span class="tok-p">)</span>
<span class="tok-p">{</span>
<span class="tok-w"> </span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_node</span><span class="tok-w"> </span><span class="tok-n">node</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-o">*</span><span class="tok-n">it</span><span class="tok-p">;</span>
<span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">node</span><span class="tok-p">.</span><span class="tok-n">node</span><span class="tok-p">().</span><span class="tok-n">attribute</span><span class="tok-p">(</span><span class="tok-s">&quot;Filename&quot;</span><span class="tok-p">).</span><span class="tok-n">value</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;</span><span class="tok-se">\n</span><span class="tok-s">&quot;</span><span class="tok-p">;</span>
<span class="tok-p">}</span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_node</span><span class="tok-w"> </span><span class="tok-n">build_tool</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">select_node</span><span class="tok-p">(</span><span class="tok-s">&quot;//Tool[contains(Description, &#39;build system&#39;)]&quot;</span><span class="tok-p">);</span><span class="tok-w"></span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_node</span><span class="tok-w"> </span><span class="tok-n">build_tool</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">select_node</span><span class="tok-p">(</span><span class="tok-s">&quot;//Tool[contains(Description, &#39;build system&#39;)]&quot;</span><span class="tok-p">);</span>
<span class="tok-k">if</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-n">build_tool</span><span class="tok-p">)</span><span class="tok-w"></span>
<span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;Build tool: &quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">build_tool</span><span class="tok-p">.</span><span class="tok-n">node</span><span class="tok-p">().</span><span class="tok-n">attribute</span><span class="tok-p">(</span><span class="tok-s">&quot;Filename&quot;</span><span class="tok-p">).</span><span class="tok-n">value</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;</span><span class="tok-se">\n</span><span class="tok-s">&quot;</span><span class="tok-p">;</span><span class="tok-w"></span></code></pre>
<span class="tok-k">if</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-n">build_tool</span><span class="tok-p">)</span>
<span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;Build tool: &quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">build_tool</span><span class="tok-p">.</span><span class="tok-n">node</span><span class="tok-p">().</span><span class="tok-n">attribute</span><span class="tok-p">(</span><span class="tok-s">&quot;Filename&quot;</span><span class="tok-p">).</span><span class="tok-n">value</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;</span><span class="tok-se">\n</span><span class="tok-s">&quot;</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="admonitionblock caution">
@@ -893,35 +892,35 @@ XPath functions throw <code>xpath_exception</code> objects on error; the sample
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_node</span><span class="tok-w"> </span><span class="tok-n">node</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">child</span><span class="tok-p">(</span><span class="tok-s">&quot;node&quot;</span><span class="tok-p">);</span><span class="tok-w"></span>
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_node</span><span class="tok-w"> </span><span class="tok-n">node</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">child</span><span class="tok-p">(</span><span class="tok-s">&quot;node&quot;</span><span class="tok-p">);</span>
<span class="tok-c1">// change node name</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">node</span><span class="tok-p">.</span><span class="tok-n">set_name</span><span class="tok-p">(</span><span class="tok-s">&quot;notnode&quot;</span><span class="tok-p">);</span><span class="tok-w"></span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;, new node name: &quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">node</span><span class="tok-p">.</span><span class="tok-n">name</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span><span class="tok-w"></span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">node</span><span class="tok-p">.</span><span class="tok-n">set_name</span><span class="tok-p">(</span><span class="tok-s">&quot;notnode&quot;</span><span class="tok-p">);</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;, new node name: &quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">node</span><span class="tok-p">.</span><span class="tok-n">name</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span>
<span class="tok-c1">// change comment text</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">last_child</span><span class="tok-p">().</span><span class="tok-n">set_value</span><span class="tok-p">(</span><span class="tok-s">&quot;useless comment&quot;</span><span class="tok-p">);</span><span class="tok-w"></span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;, new comment text: &quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">last_child</span><span class="tok-p">().</span><span class="tok-n">value</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span><span class="tok-w"></span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">last_child</span><span class="tok-p">().</span><span class="tok-n">set_value</span><span class="tok-p">(</span><span class="tok-s">&quot;useless comment&quot;</span><span class="tok-p">);</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;, new comment text: &quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">last_child</span><span class="tok-p">().</span><span class="tok-n">value</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span>
<span class="tok-c1">// we can&#39;t change value of the element or name of the comment</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">node</span><span class="tok-p">.</span><span class="tok-n">set_value</span><span class="tok-p">(</span><span class="tok-s">&quot;1&quot;</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;, &quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">last_child</span><span class="tok-p">().</span><span class="tok-n">set_name</span><span class="tok-p">(</span><span class="tok-s">&quot;2&quot;</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span><span class="tok-w"></span></code></pre>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">node</span><span class="tok-p">.</span><span class="tok-n">set_value</span><span class="tok-p">(</span><span class="tok-s">&quot;1&quot;</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;, &quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">last_child</span><span class="tok-p">().</span><span class="tok-n">set_name</span><span class="tok-p">(</span><span class="tok-s">&quot;2&quot;</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_attribute</span><span class="tok-w"> </span><span class="tok-n">attr</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">node</span><span class="tok-p">.</span><span class="tok-n">attribute</span><span class="tok-p">(</span><span class="tok-s">&quot;id&quot;</span><span class="tok-p">);</span><span class="tok-w"></span>
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_attribute</span><span class="tok-w"> </span><span class="tok-n">attr</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">node</span><span class="tok-p">.</span><span class="tok-n">attribute</span><span class="tok-p">(</span><span class="tok-s">&quot;id&quot;</span><span class="tok-p">);</span>
<span class="tok-c1">// change attribute name/value</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">attr</span><span class="tok-p">.</span><span class="tok-n">set_name</span><span class="tok-p">(</span><span class="tok-s">&quot;key&quot;</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;, &quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">attr</span><span class="tok-p">.</span><span class="tok-n">set_value</span><span class="tok-p">(</span><span class="tok-s">&quot;345&quot;</span><span class="tok-p">);</span><span class="tok-w"></span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;, new attribute: &quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">attr</span><span class="tok-p">.</span><span class="tok-n">name</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;=&quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">attr</span><span class="tok-p">.</span><span class="tok-n">value</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span><span class="tok-w"></span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">attr</span><span class="tok-p">.</span><span class="tok-n">set_name</span><span class="tok-p">(</span><span class="tok-s">&quot;key&quot;</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;, &quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">attr</span><span class="tok-p">.</span><span class="tok-n">set_value</span><span class="tok-p">(</span><span class="tok-s">&quot;345&quot;</span><span class="tok-p">);</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;, new attribute: &quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">attr</span><span class="tok-p">.</span><span class="tok-n">name</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;=&quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">attr</span><span class="tok-p">.</span><span class="tok-n">value</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span>
<span class="tok-c1">// we can use numbers or booleans</span>
<span class="tok-n">attr</span><span class="tok-p">.</span><span class="tok-n">set_value</span><span class="tok-p">(</span><span class="tok-mf">1.234</span><span class="tok-p">);</span><span class="tok-w"></span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;new attribute value: &quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">attr</span><span class="tok-p">.</span><span class="tok-n">value</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span><span class="tok-w"></span>
<span class="tok-n">attr</span><span class="tok-p">.</span><span class="tok-n">set_value</span><span class="tok-p">(</span><span class="tok-mf">1.234</span><span class="tok-p">);</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;new attribute value: &quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">attr</span><span class="tok-p">.</span><span class="tok-n">value</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span>
<span class="tok-c1">// we can also use assignment operators for more concise code</span>
<span class="tok-n">attr</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-nb">true</span><span class="tok-p">;</span><span class="tok-w"></span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;final attribute value: &quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">attr</span><span class="tok-p">.</span><span class="tok-n">value</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span><span class="tok-w"></span></code></pre>
<span class="tok-n">attr</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-nb">true</span><span class="tok-p">;</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;final attribute value: &quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">attr</span><span class="tok-p">.</span><span class="tok-n">value</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
@@ -945,19 +944,19 @@ XPath functions throw <code>xpath_exception</code> objects on error; the sample
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-c1">// add node with some name</span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_node</span><span class="tok-w"> </span><span class="tok-n">node</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">append_child</span><span class="tok-p">(</span><span class="tok-s">&quot;node&quot;</span><span class="tok-p">);</span><span class="tok-w"></span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_node</span><span class="tok-w"> </span><span class="tok-n">node</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">append_child</span><span class="tok-p">(</span><span class="tok-s">&quot;node&quot;</span><span class="tok-p">);</span>
<span class="tok-c1">// add description node with text child</span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_node</span><span class="tok-w"> </span><span class="tok-n">descr</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">node</span><span class="tok-p">.</span><span class="tok-n">append_child</span><span class="tok-p">(</span><span class="tok-s">&quot;description&quot;</span><span class="tok-p">);</span><span class="tok-w"></span>
<span class="tok-n">descr</span><span class="tok-p">.</span><span class="tok-n">append_child</span><span class="tok-p">(</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">node_pcdata</span><span class="tok-p">).</span><span class="tok-n">set_value</span><span class="tok-p">(</span><span class="tok-s">&quot;Simple node&quot;</span><span class="tok-p">);</span><span class="tok-w"></span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_node</span><span class="tok-w"> </span><span class="tok-n">descr</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">node</span><span class="tok-p">.</span><span class="tok-n">append_child</span><span class="tok-p">(</span><span class="tok-s">&quot;description&quot;</span><span class="tok-p">);</span>
<span class="tok-n">descr</span><span class="tok-p">.</span><span class="tok-n">append_child</span><span class="tok-p">(</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">node_pcdata</span><span class="tok-p">).</span><span class="tok-n">set_value</span><span class="tok-p">(</span><span class="tok-s">&quot;Simple node&quot;</span><span class="tok-p">);</span>
<span class="tok-c1">// add param node before the description</span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_node</span><span class="tok-w"> </span><span class="tok-n">param</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">node</span><span class="tok-p">.</span><span class="tok-n">insert_child_before</span><span class="tok-p">(</span><span class="tok-s">&quot;param&quot;</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-n">descr</span><span class="tok-p">);</span><span class="tok-w"></span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_node</span><span class="tok-w"> </span><span class="tok-n">param</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">node</span><span class="tok-p">.</span><span class="tok-n">insert_child_before</span><span class="tok-p">(</span><span class="tok-s">&quot;param&quot;</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-n">descr</span><span class="tok-p">);</span>
<span class="tok-c1">// add attributes to param node</span>
<span class="tok-n">param</span><span class="tok-p">.</span><span class="tok-n">append_attribute</span><span class="tok-p">(</span><span class="tok-s">&quot;name&quot;</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-s">&quot;version&quot;</span><span class="tok-p">;</span><span class="tok-w"></span>
<span class="tok-n">param</span><span class="tok-p">.</span><span class="tok-n">append_attribute</span><span class="tok-p">(</span><span class="tok-s">&quot;value&quot;</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-mf">1.1</span><span class="tok-p">;</span><span class="tok-w"></span>
<span class="tok-n">param</span><span class="tok-p">.</span><span class="tok-n">insert_attribute_after</span><span class="tok-p">(</span><span class="tok-s">&quot;type&quot;</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-n">param</span><span class="tok-p">.</span><span class="tok-n">attribute</span><span class="tok-p">(</span><span class="tok-s">&quot;name&quot;</span><span class="tok-p">))</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-s">&quot;float&quot;</span><span class="tok-p">;</span><span class="tok-w"></span></code></pre>
<span class="tok-n">param</span><span class="tok-p">.</span><span class="tok-n">append_attribute</span><span class="tok-p">(</span><span class="tok-s">&quot;name&quot;</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-s">&quot;version&quot;</span><span class="tok-p">;</span>
<span class="tok-n">param</span><span class="tok-p">.</span><span class="tok-n">append_attribute</span><span class="tok-p">(</span><span class="tok-s">&quot;value&quot;</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-mf">1.1</span><span class="tok-p">;</span>
<span class="tok-n">param</span><span class="tok-p">.</span><span class="tok-n">insert_attribute_after</span><span class="tok-p">(</span><span class="tok-s">&quot;type&quot;</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-n">param</span><span class="tok-p">.</span><span class="tok-n">attribute</span><span class="tok-p">(</span><span class="tok-s">&quot;name&quot;</span><span class="tok-p">))</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-s">&quot;float&quot;</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
@@ -969,16 +968,16 @@ XPath functions throw <code>xpath_exception</code> objects on error; the sample
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-c1">// remove description node with the whole subtree</span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_node</span><span class="tok-w"> </span><span class="tok-n">node</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">child</span><span class="tok-p">(</span><span class="tok-s">&quot;node&quot;</span><span class="tok-p">);</span><span class="tok-w"></span>
<span class="tok-n">node</span><span class="tok-p">.</span><span class="tok-n">remove_child</span><span class="tok-p">(</span><span class="tok-s">&quot;description&quot;</span><span class="tok-p">);</span><span class="tok-w"></span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_node</span><span class="tok-w"> </span><span class="tok-n">node</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">child</span><span class="tok-p">(</span><span class="tok-s">&quot;node&quot;</span><span class="tok-p">);</span>
<span class="tok-n">node</span><span class="tok-p">.</span><span class="tok-n">remove_child</span><span class="tok-p">(</span><span class="tok-s">&quot;description&quot;</span><span class="tok-p">);</span>
<span class="tok-c1">// remove id attribute</span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_node</span><span class="tok-w"> </span><span class="tok-n">param</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">node</span><span class="tok-p">.</span><span class="tok-n">child</span><span class="tok-p">(</span><span class="tok-s">&quot;param&quot;</span><span class="tok-p">);</span><span class="tok-w"></span>
<span class="tok-n">param</span><span class="tok-p">.</span><span class="tok-n">remove_attribute</span><span class="tok-p">(</span><span class="tok-s">&quot;value&quot;</span><span class="tok-p">);</span><span class="tok-w"></span>
<span class="tok-c1">// remove value attribute</span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_node</span><span class="tok-w"> </span><span class="tok-n">param</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">node</span><span class="tok-p">.</span><span class="tok-n">child</span><span class="tok-p">(</span><span class="tok-s">&quot;param&quot;</span><span class="tok-p">);</span>
<span class="tok-n">param</span><span class="tok-p">.</span><span class="tok-n">remove_attribute</span><span class="tok-p">(</span><span class="tok-s">&quot;value&quot;</span><span class="tok-p">);</span>
<span class="tok-c1">// we can also remove nodes/attributes by handles</span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_attribute</span><span class="tok-w"> </span><span class="tok-n">id</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">param</span><span class="tok-p">.</span><span class="tok-n">attribute</span><span class="tok-p">(</span><span class="tok-s">&quot;name&quot;</span><span class="tok-p">);</span><span class="tok-w"></span>
<span class="tok-n">param</span><span class="tok-p">.</span><span class="tok-n">remove_attribute</span><span class="tok-p">(</span><span class="tok-n">id</span><span class="tok-p">);</span><span class="tok-w"></span></code></pre>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_attribute</span><span class="tok-w"> </span><span class="tok-n">id</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">param</span><span class="tok-p">.</span><span class="tok-n">attribute</span><span class="tok-p">(</span><span class="tok-s">&quot;name&quot;</span><span class="tok-p">);</span>
<span class="tok-n">param</span><span class="tok-p">.</span><span class="tok-n">remove_attribute</span><span class="tok-p">(</span><span class="tok-n">id</span><span class="tok-p">);</span></code></pre>
</div>
</div>
</div>
@@ -998,7 +997,7 @@ XPath functions throw <code>xpath_exception</code> objects on error; the sample
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-c1">// save document to file</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;Saving result: &quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">save_file</span><span class="tok-p">(</span><span class="tok-s">&quot;save_file_output.xml&quot;</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span><span class="tok-w"></span></code></pre>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;Saving result: &quot;</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">save_file</span><span class="tok-p">(</span><span class="tok-s">&quot;save_file_output.xml&quot;</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
@@ -1010,27 +1009,27 @@ XPath functions throw <code>xpath_exception</code> objects on error; the sample
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-c1">// save document to standard output</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;Document:</span><span class="tok-se">\n</span><span class="tok-s">&quot;</span><span class="tok-p">;</span><span class="tok-w"></span>
<span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">save</span><span class="tok-p">(</span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-p">);</span><span class="tok-w"></span></code></pre>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-w"> </span><span class="tok-o">&lt;&lt;</span><span class="tok-w"> </span><span class="tok-s">&quot;Document:</span><span class="tok-se">\n</span><span class="tok-s">&quot;</span><span class="tok-p">;</span>
<span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">save</span><span class="tok-p">(</span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-p">);</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>All of the above saving functions are implemented in terms of writer interface. This is a simple interface with a single function, which is called several times during output process with chunks of document data as input. In order to output the document via some custom transport, for example sockets, you should create an object which implements <code>xml_writer_file</code> interface and pass it to <code>xml_document::save</code> function.</p>
<p>All of the above saving functions are implemented in terms of writer interface. This is a simple interface with a single function, which is called several times during output process with chunks of document data as input. In order to output the document via some custom transport, for example sockets, you should create an object which implements <code>xml_writer</code> interface and pass it to <code>xml_document::save</code> function.</p>
</div>
<div class="paragraph">
<p>This is a simple example of custom writer for saving document data to STL string (<a href="samples/save_custom_writer.cpp" class="bare">samples/save_custom_writer.cpp</a>); read the sample code for more complex examples:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-k">struct</span> <span class="tok-nc">xml_string_writer</span><span class="tok-o">:</span><span class="tok-w"> </span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_writer</span><span class="tok-w"></span>
<span class="tok-p">{</span><span class="tok-w"></span>
<span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">string</span><span class="tok-w"> </span><span class="tok-n">result</span><span class="tok-p">;</span><span class="tok-w"></span>
<pre class="pygments highlight"><code data-lang="c++"><span></span><span class="tok-k">struct</span><span class="tok-w"> </span><span class="tok-nc">xml_string_writer</span><span class="tok-o">:</span><span class="tok-w"> </span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_writer</span>
<span class="tok-p">{</span>
<span class="tok-w"> </span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">string</span><span class="tok-w"> </span><span class="tok-n">result</span><span class="tok-p">;</span>
<span class="tok-w"> </span><span class="tok-k">virtual</span><span class="tok-w"> </span><span class="tok-kt">void</span><span class="tok-w"> </span><span class="tok-nf">write</span><span class="tok-p">(</span><span class="tok-k">const</span><span class="tok-w"> </span><span class="tok-kt">void</span><span class="tok-o">*</span><span class="tok-w"> </span><span class="tok-n">data</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-kt">size_t</span><span class="tok-w"> </span><span class="tok-n">size</span><span class="tok-p">)</span><span class="tok-w"></span>
<span class="tok-w"> </span><span class="tok-p">{</span><span class="tok-w"></span>
<span class="tok-w"> </span><span class="tok-n">result</span><span class="tok-p">.</span><span class="tok-n">append</span><span class="tok-p">(</span><span class="tok-k">static_cast</span><span class="tok-o">&lt;</span><span class="tok-k">const</span><span class="tok-w"> </span><span class="tok-kt">char</span><span class="tok-o">*&gt;</span><span class="tok-p">(</span><span class="tok-n">data</span><span class="tok-p">),</span><span class="tok-w"> </span><span class="tok-n">size</span><span class="tok-p">);</span><span class="tok-w"></span>
<span class="tok-w"> </span><span class="tok-p">}</span><span class="tok-w"></span>
<span class="tok-p">};</span><span class="tok-w"></span></code></pre>
<span class="tok-w"> </span><span class="tok-k">virtual</span><span class="tok-w"> </span><span class="tok-kt">void</span><span class="tok-w"> </span><span class="tok-nf">write</span><span class="tok-p">(</span><span class="tok-k">const</span><span class="tok-w"> </span><span class="tok-kt">void</span><span class="tok-o">*</span><span class="tok-w"> </span><span class="tok-n">data</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-kt">size_t</span><span class="tok-w"> </span><span class="tok-n">size</span><span class="tok-p">)</span>
<span class="tok-w"> </span><span class="tok-p">{</span>
<span class="tok-w"> </span><span class="tok-n">result</span><span class="tok-p">.</span><span class="tok-n">append</span><span class="tok-p">(</span><span class="tok-k">static_cast</span><span class="tok-o">&lt;</span><span class="tok-k">const</span><span class="tok-w"> </span><span class="tok-kt">char</span><span class="tok-o">*&gt;</span><span class="tok-p">(</span><span class="tok-n">data</span><span class="tok-p">),</span><span class="tok-w"> </span><span class="tok-n">size</span><span class="tok-p">);</span>
<span class="tok-w"> </span><span class="tok-p">}</span>
<span class="tok-p">};</span></code></pre>
</div>
</div>
<div class="paragraph">
@@ -1057,7 +1056,7 @@ XPath functions throw <code>xpath_exception</code> objects on error; the sample
</div>
<div class="literalblock">
<div class="content">
<pre>Copyright (c) 2006-2022 Arseny Kapoulkine
<pre>Copyright (c) 2006-2026 Arseny Kapoulkine
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
@@ -1087,7 +1086,7 @@ OTHER DEALINGS IN THE SOFTWARE.</pre>
<div class="literalblock">
<div class="content">
<pre>This software is based on pugixml library (https://pugixml.org).
pugixml is Copyright (C) 2006-2022 Arseny Kapoulkine.</pre>
pugixml is Copyright (C) 2006-2026 Arseny Kapoulkine.</pre>
</div>
</div>
</div>
@@ -1101,7 +1100,7 @@ pugixml is Copyright (C) 2006-2022 Arseny Kapoulkine.</pre>
</div>
<div id="footer">
<div id="footer-text">
Last updated 2022-02-08 19:57:47 -0800
Last updated 2026-06-12 14:06:53 -0700
</div>
</div>
</body>
+1 -1
View File
@@ -12,7 +12,7 @@ int main()
pugi::xml_node node = doc.child("node");
node.remove_child("description");
// remove id attribute
// remove value attribute
pugi::xml_node param = node.child("param");
param.remove_attribute("value");
+3 -3
View File
@@ -1,6 +1,6 @@
pugixml 1.12 - an XML processing library
pugixml 1.16 - an XML processing library
Copyright (C) 2006-2022, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
Copyright (C) 2006-2026, 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-2022 Arseny Kapoulkine
Copyright (c) 2006-2026 Arseny Kapoulkine
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
+3 -3
View File
@@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/10/nuspec.xsd">
<metadata>
<id>pugixml</id>
<version>1.12.0-appveyor</version>
<version>1.16.0</version>
<title>pugixml</title>
<authors>Arseny Kapoulkine</authors>
<owners>Arseny Kapoulkine</owners>
@@ -11,10 +11,10 @@
<projectUrl>https://pugixml.org/</projectUrl>
<description>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, VS2019 and VS2022, for both statically linked and DLL CRT; you can switch the CRT linkage in Project -> Properties -> Referenced Packages -> pugixml.</description>
This package contains builds for VS2017, VS2019, VS2022 and VS2026, for both statically linked and DLL CRT; you can switch the CRT linkage in Project -> Properties -> Referenced Packages -> pugixml.</description>
<summary>Light-weight, simple and fast XML parser for C++ with XPath support</summary>
<releaseNotes>https://pugixml.org/docs/manual.html#changes</releaseNotes>
<copyright>Copyright (c) 2006-2022 Arseny Kapoulkine</copyright>
<copyright>Copyright (c) 2006-2026 Arseny Kapoulkine</copyright>
<tags>native nativepackage</tags>
</metadata>
</package>
+7 -17
View File
@@ -35,7 +35,10 @@ 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 2022){
if ($args[0] -eq 2026){
Build-Version "vs2026" "v145" "dynamic"
Build-Version "vs2026" "v145" "static"
} elseif ($args[0] -eq 2022){
Build-Version "vs2022" "v143" "dynamic"
Build-Version "vs2022" "v143" "static"
@@ -47,22 +50,9 @@ if ($args[0] -eq 2022){
Build-Version "vs2017" "v141" "dynamic"
Build-Version "vs2017" "v141" "static"
Build-Version "vs2015" "v140" "dynamic"
Build-Version "vs2015" "v140" "static"
Build-Version "vs2013" "v120" "dynamic"
Build-Version "vs2013" "v120" "static"
} elseif($args[0] -eq 2015){
Build-Version "vs2015" "v140" "dynamic"
Build-Version "vs2015" "v140" "static"
Build-Version "vs2013" "v120" "dynamic"
Build-Version "vs2013" "v120" "static"
} elseif($args[0] -eq 2013){
Build-Version "vs2013" "v120" "dynamic"
Build-Version "vs2013" "v120" "static"
} else {
Write-Error "Unsupported Visual Studio version '$($args[0])'"
exit 1
}
Run-Command "nuget pack nuget"
+2 -2
View File
@@ -1,7 +1,7 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=${prefix}
includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@@INSTALL_SUFFIX@
libdir=@CMAKE_INSTALL_FULL_LIBDIR@@INSTALL_SUFFIX@
includedir=@PUGIXML_PC_INCLUDEDIR@
libdir=@PUGIXML_PC_LIBDIR@
Name: pugixml
Description: Light-weight, simple and fast XML parser for C++ with XPath support.
+1 -1
View File
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "pugixml"
s.version = "1.12"
s.version = "1.16"
s.summary = "C++ XML parser library."
s.homepage = "https://pugixml.org"
s.license = "MIT"
+3 -3
View File
@@ -1,9 +1,9 @@
#include <winver.h>
#define PUGIXML_VERSION_MAJOR 1
#define PUGIXML_VERSION_MINOR 12
#define PUGIXML_VERSION_MINOR 16
#define PUGIXML_VERSION_PATCH 0
#define PUGIXML_VERSION_NUMBER "1.12.0\0"
#define PUGIXML_VERSION_NUMBER "1.16.0\0"
#if defined(GCC_WINDRES) || defined(__MINGW32__) || defined(__CYGWIN__)
VS_VERSION_INFO VERSIONINFO
@@ -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-2022, by Arseny Kapoulkine\0"
VALUE "LegalCopyright", "Copyright (C) 2006-2026, by Arseny Kapoulkine\0"
VALUE "OriginalFilename", "pugixml.dll\0"
VALUE "ProductName", "pugixml\0"
VALUE "ProductVersion", PUGIXML_VERSION_NUMBER
+4
View File
@@ -99,6 +99,7 @@
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<MinimalRebuild>false</MinimalRebuild>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -115,6 +116,7 @@
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<MinimalRebuild>false</MinimalRebuild>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -132,6 +134,7 @@
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -151,6 +154,7 @@
<PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
+4
View File
@@ -100,6 +100,7 @@
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<MinimalRebuild>false</MinimalRebuild>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -117,6 +118,7 @@
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<MinimalRebuild>false</MinimalRebuild>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -135,6 +137,7 @@
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -155,6 +158,7 @@
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
+4
View File
@@ -99,6 +99,7 @@
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<MinimalRebuild>false</MinimalRebuild>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -115,6 +116,7 @@
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<MinimalRebuild>false</MinimalRebuild>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -132,6 +134,7 @@
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -151,6 +154,7 @@
<PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
+4
View File
@@ -100,6 +100,7 @@
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<MinimalRebuild>false</MinimalRebuild>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -117,6 +118,7 @@
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<MinimalRebuild>false</MinimalRebuild>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -135,6 +137,7 @@
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -155,6 +158,7 @@
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
+176
View File
@@ -0,0 +1,176 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{07CF01C0-B887-499D-AD9C-799CB6A9FE64}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>pugixml</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v145</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v145</PlatformToolset>
<WholeProgramOptimization>false</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v145</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v145</PlatformToolset>
<WholeProgramOptimization>false</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>vs2026\$(Platform)_$(Configuration)\</OutDir>
<IntDir>vs2026\$(Platform)_$(Configuration)\</IntDir>
<TargetName>pugixml</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>vs2026\$(Platform)_$(Configuration)\</OutDir>
<IntDir>vs2026\$(Platform)_$(Configuration)\</IntDir>
<TargetName>pugixml</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>vs2026\$(Platform)_$(Configuration)\</OutDir>
<IntDir>vs2026\$(Platform)_$(Configuration)\</IntDir>
<TargetName>pugixml</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>vs2026\$(Platform)_$(Configuration)\</OutDir>
<IntDir>vs2026\$(Platform)_$(Configuration)\</IntDir>
<TargetName>pugixml</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<MinimalRebuild>false</MinimalRebuild>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<MinimalRebuild>false</MinimalRebuild>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\src\pugiconfig.hpp" />
<ClInclude Include="..\src\pugixml.hpp" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\pugixml.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
+180
View File
@@ -0,0 +1,180 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{07CF01C0-B887-499D-AD9C-799CB6A9FE64}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>pugixml</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v145</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v145</PlatformToolset>
<WholeProgramOptimization>false</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v145</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v145</PlatformToolset>
<WholeProgramOptimization>false</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>vs2026\$(Platform)_$(Configuration)Static\</OutDir>
<IntDir>vs2026\$(Platform)_$(Configuration)Static\</IntDir>
<TargetName>pugixml</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>vs2026\$(Platform)_$(Configuration)Static\</OutDir>
<IntDir>vs2026\$(Platform)_$(Configuration)Static\</IntDir>
<TargetName>pugixml</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>vs2026\$(Platform)_$(Configuration)Static\</OutDir>
<IntDir>vs2026\$(Platform)_$(Configuration)Static\</IntDir>
<TargetName>pugixml</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>vs2026\$(Platform)_$(Configuration)Static\</OutDir>
<IntDir>vs2026\$(Platform)_$(Configuration)Static\</IntDir>
<TargetName>pugixml</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<MinimalRebuild>false</MinimalRebuild>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<MinimalRebuild>false</MinimalRebuild>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\src\pugiconfig.hpp" />
<ClInclude Include="..\src\pugixml.hpp" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\pugixml.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
+47
View File
@@ -0,0 +1,47 @@
{
"bomFormat": "CycloneDX",
"specVersion": "1.6",
"version": 1,
"metadata": {
"authors": [
{
"name": "@VCS_SBOM_AUTHORS@"
}
]
},
"components": [
{
"type": "library",
"bom-ref": "pkg:github/zeux/pugixml@@VCS_TAG@",
"cpe": "cpe:2.3:a:pugixml_project:pugixml:@VCS_TAG@:*:*:*:*:*:*:*",
"name": "pugixml",
"version": "@VCS_VERSION@",
"description": "C++ XML processing library",
"supplier": {
"name": "pugixml developers"
},
"authors": [
{
"name": "@VCS_AUTHORS@"
}
],
"licenses": [
{
"license": {
"id": "MIT"
}
}
],
"externalReferences": [
{
"type": "website",
"url": "https://pugixml.org/"
},
{
"type": "vcs",
"url": "https://github.com/zeux/pugixml"
}
]
}
]
}
+12 -8
View File
@@ -1,14 +1,12 @@
/**
* pugixml parser - version 1.12
* pugixml parser - version 1.16
* --------------------------------------------------------
* 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
* of this file.
* SPDX-FileCopyrightText: Copyright (C) 2006-2026, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
* SPDX-License-Identifier: MIT
*
* This work is based on the pugxml parser, which is:
* Copyright (C) 2003, by Kristen Wegner (kristen@tima.net)
* See LICENSE.md or notice at the end of this file.
*/
#ifndef HEADER_PUGICONFIG_HPP
@@ -17,6 +15,9 @@
// Uncomment this to enable wchar_t mode
// #define PUGIXML_WCHAR_MODE
// Uncomment this to enable from_chars/to_chars for number conversion
// #define PUGIXML_CHARCONV_FLOAT
// Uncomment this to enable compact mode
// #define PUGIXML_COMPACT
@@ -46,13 +47,16 @@
// Uncomment this to switch to header-only version
// #define PUGIXML_HEADER_ONLY
// Uncomment this to enable long long support
// Uncomment this to enable long long support (usually enabled automatically)
// #define PUGIXML_HAS_LONG_LONG
// Uncomment this to enable support for std::string_view (usually enabled automatically)
// #define PUGIXML_HAS_STRING_VIEW
#endif
/**
* Copyright (c) 2006-2022 Arseny Kapoulkine
* Copyright (c) 2006-2026 Arseny Kapoulkine
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
+2002 -1255
View File
File diff suppressed because it is too large Load Diff
+168 -65
View File
@@ -1,20 +1,18 @@
/**
* pugixml parser - version 1.12
* pugixml parser - version 1.16
* --------------------------------------------------------
* 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
* of this file.
* SPDX-FileCopyrightText: Copyright (C) 2006-2026, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
* SPDX-License-Identifier: MIT
*
* This work is based on the pugxml parser, which is:
* Copyright (C) 2003, by Kristen Wegner (kristen@tima.net)
* See LICENSE.md or notice at the end of this file.
*/
#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 1160 // 1.16
#endif
// Include user configuration file (this can define various configuration macros)
@@ -38,6 +36,20 @@
# include <string>
#endif
// Check if std::string_view is available
#if !defined(PUGIXML_HAS_STRING_VIEW) && !defined(PUGIXML_NO_STL)
# if __cplusplus >= 201703L
# define PUGIXML_HAS_STRING_VIEW
# elif defined(_MSVC_LANG) && _MSVC_LANG >= 201703L
# define PUGIXML_HAS_STRING_VIEW
# endif
#endif
// Include string_view if appropriate
#ifdef PUGIXML_HAS_STRING_VIEW
# include <string_view>
#endif
// Macro for deprecated features
#ifndef PUGIXML_DEPRECATED
# if defined(__GNUC__)
@@ -82,14 +94,14 @@
# endif
#endif
// If C++ is 2011 or higher, add 'noexcept' specifiers
// If C++ is 2011 or higher, use 'noexcept' specifiers
#ifndef PUGIXML_NOEXCEPT
# if __cplusplus >= 201103
# define PUGIXML_NOEXCEPT noexcept
# elif defined(_MSC_VER) && _MSC_VER >= 1900
# define PUGIXML_NOEXCEPT noexcept
# else
# define PUGIXML_NOEXCEPT
# define PUGIXML_NOEXCEPT throw()
# endif
#endif
@@ -115,11 +127,22 @@
#ifndef PUGIXML_NULL
# if __cplusplus >= 201103
# define PUGIXML_NULL nullptr
# elif defined(_MSC_VER) && _MSC_VER >= 1600
# define PUGIXML_NULL nullptr
# else
# define PUGIXML_NULL 0
# endif
#endif
// If C++ is 2017 or higher, add 'inline' variables
#ifndef PUGIXML_INLINE_VAR
# ifdef __cpp_inline_variables
# define PUGIXML_INLINE_VAR inline
# else
# define PUGIXML_INLINE_VAR
# endif
#endif
// Character interface macros
#ifdef PUGIXML_WCHAR_MODE
# define PUGIXML_TEXT(t) L ## t
@@ -136,7 +159,12 @@ namespace pugi
#ifndef PUGIXML_NO_STL
// String type used for operations that work with STL string; depends on PUGIXML_WCHAR_MODE
typedef std::basic_string<PUGIXML_CHAR, std::char_traits<PUGIXML_CHAR>, std::allocator<PUGIXML_CHAR> > string_t;
typedef std::basic_string<PUGIXML_CHAR> string_t;
#endif
#ifdef PUGIXML_HAS_STRING_VIEW
// String view type used for operations that can work with a length delimited string; depends on PUGIXML_WCHAR_MODE
typedef std::basic_string_view<PUGIXML_CHAR> string_view_t;
#endif
}
@@ -161,65 +189,69 @@ namespace pugi
// Minimal parsing mode (equivalent to turning all other flags off).
// Only elements and PCDATA sections are added to the DOM tree, no text conversions are performed.
const unsigned int parse_minimal = 0x0000;
PUGIXML_INLINE_VAR const unsigned int parse_minimal = 0x0000;
// This flag determines if processing instructions (node_pi) are added to the DOM tree. This flag is off by default.
const unsigned int parse_pi = 0x0001;
PUGIXML_INLINE_VAR const unsigned int parse_pi = 0x0001;
// This flag determines if comments (node_comment) are added to the DOM tree. This flag is off by default.
const unsigned int parse_comments = 0x0002;
PUGIXML_INLINE_VAR const unsigned int parse_comments = 0x0002;
// This flag determines if CDATA sections (node_cdata) are added to the DOM tree. This flag is on by default.
const unsigned int parse_cdata = 0x0004;
PUGIXML_INLINE_VAR const unsigned int parse_cdata = 0x0004;
// This flag determines if plain character data (node_pcdata) that consist only of whitespace are added to the DOM tree.
// This flag is off by default; turning it on usually results in slower parsing and more memory consumption.
const unsigned int parse_ws_pcdata = 0x0008;
PUGIXML_INLINE_VAR const unsigned int parse_ws_pcdata = 0x0008;
// This flag determines if character and entity references are expanded during parsing. This flag is on by default.
const unsigned int parse_escapes = 0x0010;
PUGIXML_INLINE_VAR const unsigned int parse_escapes = 0x0010;
// This flag determines if EOL characters are normalized (converted to #xA) during parsing. This flag is on by default.
const unsigned int parse_eol = 0x0020;
PUGIXML_INLINE_VAR const unsigned int parse_eol = 0x0020;
// This flag determines if attribute values are normalized using CDATA normalization rules during parsing. This flag is on by default.
const unsigned int parse_wconv_attribute = 0x0040;
PUGIXML_INLINE_VAR const unsigned int parse_wconv_attribute = 0x0040;
// This flag determines if attribute values are normalized using NMTOKENS normalization rules during parsing. This flag is off by default.
const unsigned int parse_wnorm_attribute = 0x0080;
PUGIXML_INLINE_VAR const unsigned int parse_wnorm_attribute = 0x0080;
// This flag determines if document declaration (node_declaration) is added to the DOM tree. This flag is off by default.
const unsigned int parse_declaration = 0x0100;
PUGIXML_INLINE_VAR const unsigned int parse_declaration = 0x0100;
// This flag determines if document type declaration (node_doctype) is added to the DOM tree. This flag is off by default.
const unsigned int parse_doctype = 0x0200;
PUGIXML_INLINE_VAR const unsigned int parse_doctype = 0x0200;
// This flag determines if plain character data (node_pcdata) that is the only child of the parent node and that consists only
// of whitespace is added to the DOM tree.
// This flag is off by default; turning it on may result in slower parsing and more memory consumption.
const unsigned int parse_ws_pcdata_single = 0x0400;
PUGIXML_INLINE_VAR const unsigned int parse_ws_pcdata_single = 0x0400;
// This flag determines if leading and trailing whitespace is to be removed from plain character data. This flag is off by default.
const unsigned int parse_trim_pcdata = 0x0800;
PUGIXML_INLINE_VAR const unsigned int parse_trim_pcdata = 0x0800;
// This flag determines if plain character data that does not have a parent node is added to the DOM tree, and if an empty document
// is a valid document. This flag is off by default.
const unsigned int parse_fragment = 0x1000;
PUGIXML_INLINE_VAR const unsigned int parse_fragment = 0x1000;
// This flag determines if plain character data is be stored in the parent element's value. This significantly changes the structure of
// This flag determines if plain character data is stored in the parent element's value. This significantly changes the structure of
// the document; this flag is only recommended for parsing documents with many PCDATA nodes in memory-constrained environments.
// This flag is off by default.
const unsigned int parse_embed_pcdata = 0x2000;
PUGIXML_INLINE_VAR const unsigned int parse_embed_pcdata = 0x2000;
// This flag determines whether two adjacent pcdata should be merged or not, if no intermediary data are parsed in the document.
// This flag is off by default.
PUGIXML_INLINE_VAR const unsigned int parse_merge_pcdata = 0x4000;
// The default parsing mode.
// Elements, PCDATA and CDATA sections are added to the DOM tree, character/reference entities are expanded,
// End-of-Line characters are normalized, attribute values are normalized using CDATA normalization rules.
const unsigned int parse_default = parse_cdata | parse_escapes | parse_wconv_attribute | parse_eol;
PUGIXML_INLINE_VAR const unsigned int parse_default = parse_cdata | parse_escapes | parse_wconv_attribute | parse_eol;
// The full parsing mode.
// Nodes of all types are added to the DOM tree, character/reference entities are expanded,
// End-of-Line characters are normalized, attribute values are normalized using CDATA normalization rules.
const unsigned int parse_full = parse_default | parse_pi | parse_comments | parse_declaration | parse_doctype;
PUGIXML_INLINE_VAR const unsigned int parse_full = parse_default | parse_pi | parse_comments | parse_declaration | parse_doctype;
// These flags determine the encoding of input data for XML document
enum xml_encoding
@@ -233,47 +265,47 @@ namespace pugi
encoding_utf32_be, // Big-endian UTF32
encoding_utf32, // UTF32 with native endianness
encoding_wchar, // The same encoding wchar_t has (either UTF16 or UTF32)
encoding_latin1
encoding_latin1 // Latin1 encoding (ISO-8859-1)
};
// Formatting flags
// Indent the nodes that are written to output stream with as many indentation strings as deep the node is in DOM tree. This flag is on by default.
const unsigned int format_indent = 0x01;
PUGIXML_INLINE_VAR const unsigned int format_indent = 0x01;
// Write encoding-specific BOM to the output stream. This flag is off by default.
const unsigned int format_write_bom = 0x02;
PUGIXML_INLINE_VAR const unsigned int format_write_bom = 0x02;
// Use raw output mode (no indentation and no line breaks are written). This flag is off by default.
const unsigned int format_raw = 0x04;
PUGIXML_INLINE_VAR const unsigned int format_raw = 0x04;
// Omit default XML declaration even if there is no declaration in the document. This flag is off by default.
const unsigned int format_no_declaration = 0x08;
PUGIXML_INLINE_VAR const unsigned int format_no_declaration = 0x08;
// Don't escape attribute values and PCDATA contents. This flag is off by default.
const unsigned int format_no_escapes = 0x10;
PUGIXML_INLINE_VAR const unsigned int format_no_escapes = 0x10;
// Open file using text mode in xml_document::save_file. This enables special character (i.e. new-line) conversions on some systems. This flag is off by default.
const unsigned int format_save_file_text = 0x20;
PUGIXML_INLINE_VAR const unsigned int format_save_file_text = 0x20;
// Write every attribute on a new line with appropriate indentation. This flag is off by default.
const unsigned int format_indent_attributes = 0x40;
PUGIXML_INLINE_VAR const unsigned int format_indent_attributes = 0x40;
// Don't output empty element tags, instead writing an explicit start and end tag even if there are no children. This flag is off by default.
const unsigned int format_no_empty_element_tags = 0x80;
PUGIXML_INLINE_VAR const unsigned int format_no_empty_element_tags = 0x80;
// Skip characters belonging to range [0; 32) instead of "&#xNN;" encoding. This flag is off by default.
const unsigned int format_skip_control_chars = 0x100;
PUGIXML_INLINE_VAR const unsigned int format_skip_control_chars = 0x100;
// Use single quotes ' instead of double quotes " for enclosing attribute values. This flag is off by default.
const unsigned int format_attribute_single_quote = 0x200;
PUGIXML_INLINE_VAR const unsigned int format_attribute_single_quote = 0x200;
// The default set of formatting flags.
// Nodes are indented depending on their depth in DOM tree, a default declaration is output if document has none.
const unsigned int format_default = format_indent;
PUGIXML_INLINE_VAR const unsigned int format_default = format_indent;
const int default_double_precision = 17;
const int default_float_precision = 9;
PUGIXML_INLINE_VAR const int default_double_precision = 17;
PUGIXML_INLINE_VAR const int default_float_precision = 9;
// Forward declarations
struct xml_attribute_struct;
@@ -322,7 +354,7 @@ namespace pugi
class PUGIXML_CLASS xml_writer
{
public:
virtual ~xml_writer() {}
virtual ~xml_writer();
// Write memory chunk into stream/file/whatever
virtual void write(const void* data, size_t size) = 0;
@@ -347,14 +379,14 @@ namespace pugi
{
public:
// Construct writer from an output stream object
xml_writer_stream(std::basic_ostream<char, std::char_traits<char> >& stream);
xml_writer_stream(std::basic_ostream<wchar_t, std::char_traits<wchar_t> >& stream);
xml_writer_stream(std::basic_ostream<char>& stream);
xml_writer_stream(std::basic_ostream<wchar_t>& stream);
virtual void write(const void* data, size_t size) PUGIXML_OVERRIDE;
private:
std::basic_ostream<char, std::char_traits<char> >* narrow_stream;
std::basic_ostream<wchar_t, std::char_traits<wchar_t> >* wide_stream;
std::basic_ostream<char>* narrow_stream;
std::basic_ostream<wchar_t>* wide_stream;
};
#endif
@@ -390,7 +422,7 @@ namespace pugi
bool operator<=(const xml_attribute& r) const;
bool operator>=(const xml_attribute& r) const;
// Check if attribute is empty
// Check if attribute is empty (null)
bool empty() const;
// Get attribute name/value, or "" if attribute is empty
@@ -416,7 +448,15 @@ namespace pugi
// Set attribute name/value (returns false if attribute is empty or there is not enough memory)
bool set_name(const char_t* rhs);
bool set_name(const char_t* rhs, size_t size);
#ifdef PUGIXML_HAS_STRING_VIEW
bool set_name(string_view_t rhs);
#endif
bool set_value(const char_t* rhs);
bool set_value(const char_t* rhs, size_t size);
#ifdef PUGIXML_HAS_STRING_VIEW
bool set_value(string_view_t rhs);
#endif
// Set attribute value with type conversion (numbers are converted to strings, boolean is converted to "true"/"false")
bool set_value(int rhs);
@@ -444,6 +484,10 @@ namespace pugi
xml_attribute& operator=(float rhs);
xml_attribute& operator=(bool rhs);
#ifdef PUGIXML_HAS_STRING_VIEW
xml_attribute& operator=(string_view_t rhs);
#endif
#ifdef PUGIXML_HAS_LONG_LONG
xml_attribute& operator=(long long rhs);
xml_attribute& operator=(unsigned long long rhs);
@@ -499,7 +543,7 @@ namespace pugi
bool operator<=(const xml_node& r) const;
bool operator>=(const xml_node& r) const;
// Check if node is empty.
// Check if node is empty (null)
bool empty() const;
// Get node type
@@ -538,9 +582,18 @@ namespace pugi
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;
#ifdef PUGIXML_HAS_STRING_VIEW
xml_node child(string_view_t name) const;
xml_attribute attribute(string_view_t name) const;
xml_node next_sibling(string_view_t name) const;
xml_node previous_sibling(string_view_t name) const;
#endif
// Get attribute, starting the search from a hint (and updating hint so that searching for a sequence of attributes is fast)
xml_attribute attribute(const char_t* name, xml_attribute& hint) const;
#ifdef PUGIXML_HAS_STRING_VIEW
xml_attribute attribute(string_view_t name, xml_attribute& hint) const;
#endif
// Get child value of current node; that is, value of the first child node of type PCDATA/CDATA
const char_t* child_value() const;
@@ -550,13 +603,33 @@ namespace pugi
// Set node name/value (returns false if node is empty, there is not enough memory, or node can not have name/value)
bool set_name(const char_t* rhs);
bool set_name(const char_t* rhs, size_t size);
#ifdef PUGIXML_HAS_STRING_VIEW
bool set_name(string_view_t rhs);
#endif
bool set_value(const char_t* rhs);
bool set_value(const char_t* rhs, size_t size);
#ifdef PUGIXML_HAS_STRING_VIEW
bool set_value(string_view_t rhs);
#endif
// Add attribute with specified name. Returns added attribute, or empty attribute on errors.
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);
#ifdef PUGIXML_HAS_STRING_VIEW
xml_attribute append_attribute(string_view_t name);
xml_attribute prepend_attribute(string_view_t name);
xml_attribute insert_attribute_after(string_view_t name, const xml_attribute& attr);
xml_attribute insert_attribute_before(string_view_t name, const xml_attribute& attr);
#endif
// Get attribute with specified name, adding one if it does not exist. Returns the existing or added attribute, or empty attribute on errors.
xml_attribute ensure_attribute(const char_t* name);
#ifdef PUGIXML_HAS_STRING_VIEW
xml_attribute ensure_attribute(string_view_t name);
#endif
// Add a copy of the specified attribute. Returns added attribute, or empty attribute on errors.
xml_attribute append_copy(const xml_attribute& proto);
@@ -575,6 +648,18 @@ namespace pugi
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);
#ifdef PUGIXML_HAS_STRING_VIEW
xml_node append_child(string_view_t name);
xml_node prepend_child(string_view_t name);
xml_node insert_child_after(string_view_t name, const xml_node& node);
xml_node insert_child_before(string_view_t name, const xml_node& node);
#endif
// Get child with specified name, adding one if it does not exist. Returns the existing or added node, or empty node on errors.
xml_node ensure_child(const char_t* name);
#ifdef PUGIXML_HAS_STRING_VIEW
xml_node ensure_child(string_view_t name);
#endif
// Add a copy of the specified node as a child. Returns added node, or empty node on errors.
xml_node append_copy(const xml_node& proto);
@@ -591,6 +676,9 @@ namespace pugi
// Remove specified attribute
bool remove_attribute(const xml_attribute& a);
bool remove_attribute(const char_t* name);
#ifdef PUGIXML_HAS_STRING_VIEW
bool remove_attribute(string_view_t name);
#endif
// Remove all attributes
bool remove_attributes();
@@ -598,6 +686,9 @@ namespace pugi
// Remove specified child
bool remove_child(const xml_node& n);
bool remove_child(const char_t* name);
#ifdef PUGIXML_HAS_STRING_VIEW
bool remove_child(string_view_t name);
#endif
// Remove all children
bool remove_children();
@@ -690,8 +781,8 @@ namespace pugi
#ifndef PUGIXML_NO_STL
// Print subtree to stream
void print(std::basic_ostream<char, std::char_traits<char> >& os, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto, unsigned int depth = 0) const;
void print(std::basic_ostream<wchar_t, std::char_traits<wchar_t> >& os, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, unsigned int depth = 0) const;
void print(std::basic_ostream<char>& os, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto, unsigned int depth = 0) const;
void print(std::basic_ostream<wchar_t>& os, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, unsigned int depth = 0) const;
#endif
// Child nodes iterators
@@ -708,9 +799,12 @@ namespace pugi
// Range-based for support
xml_object_range<xml_node_iterator> children() const;
xml_object_range<xml_named_node_iterator> children(const char_t* name) const;
xml_object_range<xml_attribute_iterator> attributes() const;
// Range-based for support for all children with the specified name
// Note: name pointer must have a longer lifetime than the returned object; be careful with passing temporaries!
xml_object_range<xml_named_node_iterator> children(const char_t* name) const;
// Get node offset in parsed file/string (in char_t units) for debugging purposes
ptrdiff_t offset_debug() const;
@@ -751,7 +845,7 @@ namespace pugi
// Borland C++ workaround
bool operator!() const;
// Check if text object is empty
// Check if text object is empty (null)
bool empty() const;
// Get text, or "" if object is empty
@@ -776,6 +870,10 @@ namespace pugi
// Set text (returns false if object is empty or there is not enough memory)
bool set(const char_t* rhs);
bool set(const char_t* rhs, size_t size);
#ifdef PUGIXML_HAS_STRING_VIEW
bool set(string_view_t rhs);
#endif
// Set text with type conversion (numbers are converted to strings, boolean is converted to "true"/"false")
bool set(int rhs);
@@ -803,6 +901,10 @@ namespace pugi
xml_text& operator=(float rhs);
xml_text& operator=(bool rhs);
#ifdef PUGIXML_HAS_STRING_VIEW
xml_text& operator=(string_view_t rhs);
#endif
#ifdef PUGIXML_HAS_LONG_LONG
xml_text& operator=(long long rhs);
xml_text& operator=(unsigned long long rhs);
@@ -922,6 +1024,7 @@ namespace pugi
xml_named_node_iterator();
// Construct an iterator which points to the specified node
// Note: name pointer is stored in the iterator and must have a longer lifetime than iterator itself
xml_named_node_iterator(const xml_node& node, const char_t* name);
// Iterator operators
@@ -1057,8 +1160,8 @@ namespace pugi
#ifndef PUGIXML_NO_STL
// Load document from stream.
xml_parse_result load(std::basic_istream<char, std::char_traits<char> >& stream, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
xml_parse_result load(std::basic_istream<wchar_t, std::char_traits<wchar_t> >& stream, unsigned int options = parse_default);
xml_parse_result load(std::basic_istream<char>& stream, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
xml_parse_result load(std::basic_istream<wchar_t>& stream, unsigned int options = parse_default);
#endif
// (deprecated: use load_string instead) Load document from zero-terminated string. No encoding conversions are applied.
@@ -1087,8 +1190,8 @@ namespace pugi
#ifndef PUGIXML_NO_STL
// Save XML document to stream (semantics is slightly different from xml_node::print, see documentation for details).
void save(std::basic_ostream<char, std::char_traits<char> >& stream, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const;
void save(std::basic_ostream<wchar_t, std::char_traits<wchar_t> >& stream, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default) const;
void save(std::basic_ostream<char>& stream, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const;
void save(std::basic_ostream<wchar_t>& stream, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default) const;
#endif
// Save XML to file
@@ -1257,7 +1360,7 @@ namespace pugi
// Evaluate expression as string value in the specified context; performs type conversion if necessary.
// At most capacity characters are written to the destination buffer, full result size is returned (includes terminating zero).
// If PUGIXML_NO_EXCEPTIONS is not defined, throws std::bad_alloc on out of memory errors.
// If PUGIXML_NO_EXCEPTIONS is defined, returns empty set instead.
// If PUGIXML_NO_EXCEPTIONS is defined, returns empty string instead.
size_t evaluate_string(char_t* buffer, size_t capacity, const xpath_node& n) const;
// Evaluate expression as node set in the specified context.
@@ -1299,7 +1402,7 @@ namespace pugi
explicit xpath_exception(const xpath_parse_result& result);
// Get error message
virtual const char* what() const throw() PUGIXML_OVERRIDE;
virtual const char* what() const PUGIXML_NOEXCEPT PUGIXML_OVERRIDE;
// Get parse result
const xpath_parse_result& result() const;
@@ -1424,12 +1527,12 @@ namespace pugi
#ifndef PUGIXML_NO_STL
// Convert wide string to UTF8
std::basic_string<char, std::char_traits<char>, std::allocator<char> > PUGIXML_FUNCTION as_utf8(const wchar_t* str);
std::basic_string<char, std::char_traits<char>, std::allocator<char> > PUGIXML_FUNCTION as_utf8(const std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >& str);
std::basic_string<char> PUGIXML_FUNCTION as_utf8(const wchar_t* str);
std::basic_string<char> PUGIXML_FUNCTION as_utf8(const std::basic_string<wchar_t>& str);
// Convert UTF8 to wide string
std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > PUGIXML_FUNCTION as_wide(const char* str);
std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > PUGIXML_FUNCTION as_wide(const std::basic_string<char, std::char_traits<char>, std::allocator<char> >& str);
std::basic_string<wchar_t> PUGIXML_FUNCTION as_wide(const char* str);
std::basic_string<wchar_t> PUGIXML_FUNCTION as_wide(const std::basic_string<char>& str);
#endif
// Memory allocation function interface; returns pointer to allocated memory or NULL on failure
@@ -1476,7 +1579,7 @@ namespace std
#endif
/**
* Copyright (c) 2006-2022 Arseny Kapoulkine
* Copyright (c) 2006-2026 Arseny Kapoulkine
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
+10 -4
View File
@@ -12,9 +12,9 @@ function Invoke-CmdScript($scriptName)
$sources = @("src/pugixml.cpp") + (Get-ChildItem -Path "tests/*.cpp" -Exclude "fuzz_*.cpp")
$failed = $FALSE
foreach ($vs in $args)
foreach ($vs in @($args[0]))
{
foreach ($arch in "x86","x64")
foreach ($arch in @($args[1]))
{
Write-Output "# Setting up VS$vs $arch"
@@ -30,6 +30,10 @@ foreach ($vs in $args)
$vsdevcmdarch = if ($arch -eq "x64") { "amd64" } else { "x86" }
Invoke-CmdScript "C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\Tools\VsDevCmd.bat" "-arch=$vsdevcmdarch"
}
elseif ($vs -eq 26) {
$vsdevcmdarch = if ($arch -eq "x64") { "amd64" } else { "x86" }
Invoke-CmdScript "C:\Program Files\Microsoft Visual Studio\18\Community\Common7\Tools\VsDevCmd.bat" "-arch=$vsdevcmdarch"
}
else
{
Invoke-CmdScript "C:\Program Files (x86)\Microsoft Visual Studio $vs.0\VC\vcvarsall.bat" $arch
@@ -37,7 +41,9 @@ foreach ($vs in $args)
if (! $?) { throw "Error setting up VS$vs $arch" }
foreach ($defines in "standard", "PUGIXML_WCHAR_MODE", "PUGIXML_COMPACT")
$cxx = if ($vs -ge 19) { "/std:c++17" } else { "" }
foreach ($defines in @($args[2]))
{
$target = "tests_vs${vs}_${arch}_${defines}"
$deflist = if ($defines -eq "standard") { "" } else { "/D$defines" }
@@ -45,7 +51,7 @@ foreach ($vs in $args)
Add-AppveyorTest $target -Outcome Running
Write-Output "# Building $target.exe"
& cmd /c "cl.exe /Fe$target.exe /EHsc /W4 /WX $deflist $sources 2>&1" | Tee-Object -Variable buildOutput
& cmd /c "cl.exe /MP /Fe$target.exe /EHsc /W4 /WX $cxx $deflist $sources 2>&1" | Tee-Object -Variable buildOutput
if ($?)
{
+57
View File
@@ -0,0 +1,57 @@
$failed = $FALSE
$vs = $args[0]
$vsy = $args[1]
$target = "cmake_vs${vs}_${vsy}"
Add-AppveyorTest $target -Outcome Running
mkdir $target
pushd $target
try
{
Write-Output "# Setting up CMake VS$vs"
& cmake .. -G "Visual Studio $vs $vsy" | Tee-Object -Variable cmakeOutput
$sw = [Diagnostics.Stopwatch]::StartNew()
if ($?)
{
Write-Output "# Building"
& cmake --build . | Tee-Object -Variable cmakeOutput
if ($?)
{
Write-Output "# Passed"
Update-AppveyorTest $target -Outcome Passed -StdOut ($cmakeOutput | out-string) -Duration $sw.ElapsedMilliseconds
}
else
{
Write-Output "# Failed to build"
Update-AppveyorTest $target -Outcome Failed -StdOut ($cmakeOutput | out-string) -ErrorMessage "Building failed"
$failed = $TRUE
}
}
else
{
Write-Output "# Failed to configure"
Update-AppveyorTest $target -Outcome Failed -StdOut ($cmakeOutput | out-string) -ErrorMessage "Configuration failed"
$failed = $TRUE
}
}
finally
{
popd
}
if ($failed) { throw "One or more build steps failed" }
Write-Output "# End"
+30 -10
View File
@@ -1,26 +1,46 @@
#include "../src/pugixml.hpp"
#include "fuzzer/FuzzedDataProvider.h"
#include <stdint.h>
#include <string.h>
#include <string>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size)
{
char* text = new char[Size + 1];
memcpy(text, Data, Size);
text[Size] = 0;
FuzzedDataProvider fdp(Data, Size);
std::string text = fdp.ConsumeRandomLengthString(1024);
#ifdef PUGIXML_NO_EXCEPTIONS
pugi::xpath_query q(text);
#else
#ifndef PUGIXML_NO_EXCEPTIONS
try
#endif
{
pugi::xpath_query q(text);
pugi::xpath_variable_set vars;
size_t var_count = fdp.ConsumeIntegralInRange<size_t>(0, 50);
std::vector<std::string> var_name_storage;
for (size_t i = 0; i < var_count; ++i)
{
var_name_storage.push_back(fdp.ConsumeRandomLengthString(128));
const int xpath_value_type_count = pugi::xpath_type_boolean + 1;
pugi::xpath_value_type value_type = static_cast<pugi::xpath_value_type>(fdp.ConsumeIntegralInRange(0, xpath_value_type_count));
vars.add(var_name_storage.back().c_str(), value_type);
}
pugi::xpath_query q(text.c_str(), &vars);
std::vector<uint8_t> xml_buffer = fdp.ConsumeBytes<uint8_t>(fdp.ConsumeIntegralInRange(0, 1024));
pugi::xml_document doc;
doc.load_buffer(xml_buffer.data(), xml_buffer.size(), pugi::parse_full);
q.evaluate_boolean(doc);
q.evaluate_number(doc);
q.evaluate_string(doc);
q.evaluate_node(doc);
q.evaluate_node_set(doc);
}
#ifndef PUGIXML_NO_EXCEPTIONS
catch (pugi::xpath_exception&)
{
}
#endif
delete[] text;
return 0;
}
+92 -1
View File
@@ -473,6 +473,17 @@ TEST(document_load_string)
CHECK_NODE(doc, STR("<node/>"));
}
TEST(document_load_string_empty)
{
xml_document doc;
CHECK(doc.load_string(STR("")).status == status_no_document_element);
CHECK(!doc.first_child());
CHECK(doc.load_string(STR(""), parse_fragment));
CHECK(!doc.first_child());
}
TEST(document_load_file)
{
xml_document doc;
@@ -589,7 +600,7 @@ TEST(document_load_file_wide_out_of_memory)
CHECK(result.status == status_out_of_memory || result.status == status_file_not_found);
}
#if defined(__APPLE__)
#if defined(__linux__) || defined(__APPLE__)
TEST(document_load_file_special_folder)
{
xml_document doc;
@@ -605,6 +616,13 @@ TEST(document_load_file_special_device)
xml_parse_result result = doc.load_file("/dev/tty");
CHECK(result.status == status_file_not_found || result.status == status_io_error);
}
TEST(document_load_file_special_sysfs)
{
xml_document doc;
xml_parse_result result = doc.load_file("/sys/kernel/fscaps");
CHECK(result.status == status_file_not_found || result.status == status_io_error);
}
#endif
TEST_XML(document_save, "<node/>")
@@ -736,7 +754,12 @@ struct temp_file
temp_file()
{
static int index = 0;
#if __cplusplus >= 201103 || defined(__APPLE__) // Xcode 14 warns about use of sprintf in C++98 builds
snprintf(path, sizeof(path), "%stempfile%d", test_runner::_temp_path, index++);
#else
sprintf(path, "%stempfile%d", test_runner::_temp_path, index++);
#endif
}
~temp_file()
@@ -859,6 +882,19 @@ TEST(document_load_buffer_inplace_own)
CHECK_NODE(doc, STR("<node/>"));
}
TEST(document_load_buffer_inplace_own_empty)
{
allocation_function alloc = get_memory_allocation_function();
void* text1 = alloc(1);
void* text2 = alloc(1);
CHECK(text1 && text2);
xml_document doc;
CHECK(doc.load_buffer_inplace_own(text1, 0, parse_fragment));
CHECK(doc.load_buffer_inplace_own(text2, 0).status == status_no_document_element);
}
TEST(document_parse_result_bool)
{
xml_parse_result result;
@@ -1282,6 +1318,15 @@ TEST(document_load_buffer_empty_fragment)
}
}
TEST(document_load_buffer_empty_encoding)
{
xml_document doc;
xml_parse_result result = doc.load_buffer(0, 0, parse_fragment);
CHECK(result.status == status_ok);
CHECK(result.encoding == encoding_utf8);
}
TEST(document_load_buffer_null)
{
xml_document doc;
@@ -1817,3 +1862,49 @@ TEST(document_move_assign_empty)
CHECK_NODE(doc, STR("<node2/>"));
}
#endif
TEST(document_load_buffer_convert_out_of_memory)
{
const char* source = "<node>\xe7</node>";
size_t size = strlen(source);
test_runner::_memory_fail_threshold = 1;
xml_document doc;
xml_parse_result result;
result.status = status_out_of_memory;
CHECK_ALLOC_FAIL(result = doc.load_buffer(source, size, pugi::parse_default, pugi::encoding_latin1));
CHECK(result.status == status_out_of_memory);
}
TEST(document_load_buffer_own_convert_out_of_memory)
{
const char* source = "<node>\xe7</node>";
size_t size = strlen(source);
void* buffer = pugi::get_memory_allocation_function()(size);
CHECK(buffer);
memcpy(buffer, source, size);
test_runner::_memory_fail_threshold = 1;
xml_document doc;
xml_parse_result result;
result.status = status_out_of_memory;
CHECK_ALLOC_FAIL(result = doc.load_buffer_inplace_own(buffer, size, pugi::parse_default, pugi::encoding_latin1));
CHECK(result.status == status_out_of_memory);
}
TEST(document_load_buffer_wide_truncated)
{
xml_document doc;
char buf[1] = {};
CHECK(doc.load_buffer_inplace(buf, 1, parse_default, encoding_wchar).status == status_no_document_element);
CHECK(doc.load_buffer_inplace(buf, 1, parse_fragment, encoding_wchar).status == status_ok);
CHECK(!doc.first_child());
}
+287 -10
View File
@@ -33,7 +33,13 @@ TEST_XML(dom_attr_assign, "<node/>")
node.append_attribute(STR("attr8")) = true;
xml_attribute() = true;
CHECK_NODE(node, STR("<node attr1=\"v1\" attr2=\"-2147483647\" attr3=\"-2147483648\" attr4=\"4294967295\" attr5=\"4294967294\" attr6=\"0.5\" attr7=\"0.25\" attr8=\"true\"/>"));
#ifdef PUGIXML_HAS_STRING_VIEW
node.append_attribute(string_view_t(STR("attr9"))) = string_view_t(STR("v2"));
#else
node.append_attribute(STR("attr9")) = STR("v2");
#endif
CHECK_NODE(node, STR("<node attr1=\"v1\" attr2=\"-2147483647\" attr3=\"-2147483648\" attr4=\"4294967295\" attr5=\"4294967294\" attr6=\"0.5\" attr7=\"0.25\" attr8=\"true\" attr9=\"v2\"/>"));
}
TEST_XML(dom_attr_set_name, "<node attr='value' />")
@@ -46,6 +52,33 @@ TEST_XML(dom_attr_set_name, "<node attr='value' />")
CHECK_NODE(doc, STR("<node n=\"value\"/>"));
}
TEST_XML(dom_attr_set_name_with_size, "<node attr='value' />")
{
xml_attribute attr = doc.child(STR("node")).attribute(STR("attr"));
CHECK(attr.set_name(STR("n1234"), 1));
CHECK(!xml_attribute().set_name(STR("nfail"), 1));
CHECK_NODE(doc, STR("<node n=\"value\"/>"));
}
#ifdef PUGIXML_HAS_STRING_VIEW
TEST_XML(dom_attr_set_name_with_string_view, "<node attr='value' />")
{
xml_attribute attr = doc.child(STR("node")).attribute(STR("attr"));
CHECK(attr.set_name(string_view_t()));
CHECK(!xml_attribute().set_name(string_view_t()));
CHECK_NODE(doc, STR("<node :anonymous=\"value\"/>"));
CHECK(attr.set_name(string_view_t(STR("n1234"), 1)));
CHECK(!xml_attribute().set_name(string_view_t(STR("nfail"), 1)));
CHECK_NODE(doc, STR("<node n=\"value\"/>"));
}
#endif
TEST_XML(dom_attr_set_value, "<node/>")
{
xml_node node = doc.child(STR("node"));
@@ -70,7 +103,20 @@ TEST_XML(dom_attr_set_value, "<node/>")
CHECK(node.append_attribute(STR("attr8")).set_value(true));
CHECK(!xml_attribute().set_value(true));
CHECK_NODE(node, STR("<node attr1=\"v1\" attr2=\"-2147483647\" attr3=\"-2147483648\" attr4=\"4294967295\" attr5=\"4294967294\" attr6=\"0.5\" attr7=\"0.25\" attr8=\"true\"/>"));
CHECK(node.append_attribute(STR("attr9")).set_value(STR("v2"), 2));
CHECK(!xml_attribute().set_value(STR("v2")));
CHECK(node.append_attribute(STR("attr10")).set_value(STR("v3foobar"), 2));
CHECK(!xml_attribute().set_value(STR("v3")));
#ifdef PUGIXML_HAS_STRING_VIEW
CHECK(node.append_attribute(string_view_t(STR("attr11"))).set_value(string_view_t(STR("v4"))));
CHECK(!xml_attribute().set_value(string_view_t(STR("v4"))));
#else
CHECK(node.append_attribute(STR("attr11")).set_value(STR("v4")));
#endif
CHECK_NODE(node, STR("<node attr1=\"v1\" attr2=\"-2147483647\" attr3=\"-2147483648\" attr4=\"4294967295\" attr5=\"4294967294\" attr6=\"0.5\" attr7=\"0.25\" attr8=\"true\" attr9=\"v2\" attr10=\"v3\" attr11=\"v4\"/>"));
}
#if LONG_MAX > 2147483647
@@ -200,6 +246,34 @@ TEST_XML(dom_node_set_name, "<node>text</node>")
CHECK_NODE(doc, STR("<n>text</n>"));
}
TEST_XML(dom_node_set_name_with_size, "<node>text</node>")
{
CHECK(doc.child(STR("node")).set_name(STR("nlongname"), 1));
CHECK(!doc.child(STR("node")).first_child().set_name(STR("n42"), 1));
CHECK(!xml_node().set_name(STR("nanothername"), 1));
CHECK_NODE(doc, STR("<n>text</n>"));
}
#ifdef PUGIXML_HAS_STRING_VIEW
TEST_XML(dom_node_set_name_with_string_view, "<node>text</node>")
{
xml_node node = doc.child(STR("node"));
CHECK(node.set_name(string_view_t()));
CHECK(!node.first_child().set_name(string_view_t(STR("n42"), 1)));
CHECK(!xml_node().set_name(string_view_t(STR("nanothername"), 1)));
CHECK_NODE(doc, STR("<:anonymous>text</:anonymous>"));
CHECK(node.set_name(string_view_t(STR("nlongname"), 1)));
CHECK(!doc.child(STR("node")).first_child().set_name(string_view_t(STR("n42"), 1)));
CHECK(!xml_node().set_name(string_view_t(STR("nanothername"), 1)));
CHECK_NODE(doc, STR("<n>text</n>"));
}
#endif
TEST_XML(dom_node_set_value, "<node>text</node>")
{
CHECK(doc.child(STR("node")).first_child().set_value(STR("no text")));
@@ -209,6 +283,44 @@ TEST_XML(dom_node_set_value, "<node>text</node>")
CHECK_NODE(doc, STR("<node>no text</node>"));
}
TEST_XML(dom_node_set_value_partially_with_size, "<node>text</node>")
{
CHECK(doc.child(STR("node")).first_child().set_value(STR("no text"), 2));
CHECK(!doc.child(STR("node")).set_value(STR("no text"), 2));
CHECK(!xml_node().set_value(STR("no text"), 2));
CHECK_NODE(doc, STR("<node>no</node>"));
}
TEST_XML(dom_node_set_value_with_size, "<node>text</node>")
{
CHECK(doc.child(STR("node")).first_child().set_value(STR("no text"), 7));
CHECK(!doc.child(STR("node")).set_value(STR("no text"), 7));
CHECK(!xml_node().set_value(STR("no text"), 7));
CHECK_NODE(doc, STR("<node>no text</node>"));
}
#ifdef PUGIXML_HAS_STRING_VIEW
TEST_XML(dom_node_set_value_partially_with_string_view, "<node>text</node>")
{
CHECK(doc.child(STR("node")).first_child().set_value(string_view_t(STR("no text"), 2)));
CHECK(!doc.child(STR("node")).set_value(string_view_t(STR("no text"), 2)));
CHECK(!xml_node().set_value(string_view_t(STR("no text"), 2)));
CHECK_NODE(doc, STR("<node>no</node>"));
}
TEST_XML(dom_node_set_value_with_string_view, "<node>text</node>")
{
CHECK(doc.child(STR("node")).first_child().set_value(string_view_t(STR("no text"), 7)));
CHECK(!doc.child(STR("node")).set_value(string_view_t(STR("no text"), 7)));
CHECK(!xml_node().set_value(string_view_t(STR("no text"), 7)));
CHECK_NODE(doc, STR("<node>no text</node>"));
}
#endif
TEST_XML(dom_node_set_value_allocated, "<node>text</node>")
{
CHECK(doc.child(STR("node")).first_child().set_value(STR("no text")));
@@ -236,7 +348,15 @@ TEST_XML(dom_node_prepend_attribute, "<node><child/></node>")
CHECK(a3 && a1 != a3 && a2 != a3);
a3 = STR("v3");
CHECK_NODE(doc, STR("<node a2=\"v2\" a1=\"v1\"><child a3=\"v3\"/></node>"));
#ifdef PUGIXML_HAS_STRING_VIEW
xml_attribute a4 = doc.child(STR("node")).child(STR("child")).prepend_attribute(string_view_t(STR("a4")));
#else
xml_attribute a4 = doc.child(STR("node")).child(STR("child")).prepend_attribute(STR("a4"));
#endif
CHECK(a4 && a1 != a4 && a2 != a4 && a3 != a4);
a4 = STR("v4");
CHECK_NODE(doc, STR("<node a2=\"v2\" a1=\"v1\"><child a4=\"v4\" a3=\"v3\"/></node>"));
}
TEST_XML(dom_node_append_attribute, "<node><child/></node>")
@@ -259,6 +379,37 @@ TEST_XML(dom_node_append_attribute, "<node><child/></node>")
CHECK_NODE(doc, STR("<node a1=\"v1\" a2=\"v2\"><child a3=\"v3\"/></node>"));
}
TEST_XML(dom_node_ensure_attribute, "<node a1='v1'><child/></node>")
{
CHECK(xml_node().ensure_attribute(STR("a")) == xml_attribute());
CHECK(doc.ensure_attribute(STR("a")) == xml_attribute());
xml_node node = doc.child(STR("node"));
// existing attribute is returned as is
xml_attribute a1 = node.ensure_attribute(STR("a1"));
CHECK(a1 && a1 == node.attribute(STR("a1")));
CHECK_STRING(a1.value(), STR("v1"));
// missing attribute is appended
xml_attribute a2 = node.ensure_attribute(STR("a2"));
CHECK(a2 && a2 != a1);
a2 = STR("v2");
// ensuring an existing attribute does not add a duplicate
CHECK(node.ensure_attribute(STR("a2")) == a2);
#ifdef PUGIXML_HAS_STRING_VIEW
xml_attribute a3 = node.child(STR("child")).ensure_attribute(string_view_t(STR("a3")));
#else
xml_attribute a3 = node.child(STR("child")).ensure_attribute(STR("a3"));
#endif
CHECK(a3 && a3 != a1 && a3 != a2);
a3 = STR("v3");
CHECK_NODE(doc, STR("<node a1=\"v1\" a2=\"v2\"><child a3=\"v3\"/></node>"));
}
TEST_XML(dom_node_insert_attribute_after, "<node a1='v1'><child a2='v2'/></node>")
{
CHECK(xml_node().insert_attribute_after(STR("a"), xml_attribute()) == xml_attribute());
@@ -286,7 +437,17 @@ TEST_XML(dom_node_insert_attribute_after, "<node a1='v1'><child a2='v2'/></node>
CHECK(child.insert_attribute_after(STR("a"), a4) == xml_attribute());
CHECK_NODE(doc, STR("<node a1=\"v1\" a4=\"v4\" a3=\"v3\" a5=\"v5\"><child a2=\"v2\"/></node>"));
#ifdef PUGIXML_HAS_STRING_VIEW
xml_attribute a6 = node.insert_attribute_after(string_view_t(STR("a6")), a5);
CHECK(child.insert_attribute_after(string_view_t(STR("a")), a5) == xml_attribute());
#else
xml_attribute a6 = node.insert_attribute_after(STR("a6"), a5);
CHECK(child.insert_attribute_after(STR("a"), a5) == xml_attribute());
#endif
CHECK(a6 && a6 != a5 && a6 != a4 && a6 != a3 && a6 != a2 && a6 != a1);
a6 = STR("v6");
CHECK_NODE(doc, STR("<node a1=\"v1\" a4=\"v4\" a3=\"v3\" a5=\"v5\" a6=\"v6\"><child a2=\"v2\"/></node>"));
}
TEST_XML(dom_node_insert_attribute_before, "<node a1='v1'><child a2='v2'/></node>")
@@ -316,7 +477,17 @@ TEST_XML(dom_node_insert_attribute_before, "<node a1='v1'><child a2='v2'/></node
CHECK(child.insert_attribute_before(STR("a"), a4) == xml_attribute());
CHECK_NODE(doc, STR("<node a5=\"v5\" a3=\"v3\" a4=\"v4\" a1=\"v1\"><child a2=\"v2\"/></node>"));
#ifdef PUGIXML_HAS_STRING_VIEW
xml_attribute a6 = node.insert_attribute_before(string_view_t(STR("a6")), a1);
CHECK(child.insert_attribute_before(string_view_t(STR("a")), a4) == xml_attribute());
#else
xml_attribute a6 = node.insert_attribute_before(STR("a6"), a1);
CHECK(child.insert_attribute_before(STR("a"), a4) == xml_attribute());
#endif
CHECK(a6 && a6 != a5 && a6 != a4 && a6 != a3 && a6 != a2 && a6 != a1);
a6 = STR("v6");
CHECK_NODE(doc, STR("<node a5=\"v5\" a3=\"v3\" a4=\"v4\" a6=\"v6\" a1=\"v1\"><child a2=\"v2\"/></node>"));
}
TEST_XML(dom_node_prepend_copy_attribute, "<node a1='v1'><child a2='v2'/><child/></node>")
@@ -490,6 +661,14 @@ TEST_XML(dom_node_remove_attribute, "<node a1='v1' a2='v2' a3='v3'><child a4='v4
CHECK(child.remove_attribute(STR("a4")));
CHECK_NODE(doc, STR("<node a2=\"v2\"><child/></node>"));
#ifdef PUGIXML_HAS_STRING_VIEW
CHECK(!node.remove_attribute(string_view_t()));
CHECK(!node.remove_attribute(string_view_t(STR("a2"), 1)));
CHECK(node.remove_attribute(string_view_t(STR("a2extra"), 2)));
CHECK_NODE(doc, STR("<node><child/></node>"));
#endif
}
TEST_XML(dom_node_remove_attributes, "<node a1='v1' a2='v2' a3='v3'><child a4='v4'/></node>")
@@ -648,6 +827,10 @@ TEST_XML(dom_node_prepend_child_name, "<node>foo<child/></node>")
{
CHECK(xml_node().prepend_child(STR("")) == xml_node());
CHECK(doc.child(STR("node")).first_child().prepend_child(STR("")) == xml_node());
#ifdef PUGIXML_HAS_STRING_VIEW
CHECK(xml_node().prepend_child(string_view_t()) == xml_node());
CHECK(doc.child(STR("node")).first_child().prepend_child(string_view_t()) == xml_node());
#endif
xml_node n1 = doc.child(STR("node")).prepend_child(STR("n1"));
CHECK(n1);
@@ -655,7 +838,14 @@ TEST_XML(dom_node_prepend_child_name, "<node>foo<child/></node>")
xml_node n2 = doc.child(STR("node")).prepend_child(STR("n2"));
CHECK(n2 && n1 != n2);
CHECK_NODE(doc, STR("<node><n2/><n1/>foo<child/></node>"));
#ifdef PUGIXML_HAS_STRING_VIEW
xml_node n3 = doc.prepend_child(string_view_t(STR("n3")));
#else
xml_node n3 = doc.prepend_child(STR("n3"));
#endif
CHECK(n3 && n1 != n3 && n2 != n3);
CHECK_NODE(doc, STR("<n3/><node><n2/><n1/>foo<child/></node>"));
}
TEST_XML(dom_node_append_child_name, "<node>foo<child/></node>")
@@ -669,7 +859,42 @@ TEST_XML(dom_node_append_child_name, "<node>foo<child/></node>")
xml_node n2 = doc.child(STR("node")).append_child(STR("n2"));
CHECK(n2 && n1 != n2);
CHECK_NODE(doc, STR("<node>foo<child/><n1/><n2/></node>"));
#ifdef PUGIXML_HAS_STRING_VIEW
xml_node n3 = doc.append_child(string_view_t(STR("n3")));
#else
xml_node n3 = doc.append_child(STR("n3"));
#endif
CHECK(n3 && n3 != n2 && n3 != n1);
CHECK_NODE(doc, STR("<node>foo<child/><n1/><n2/></node><n3/>"));
}
TEST_XML(dom_node_ensure_child, "<node>foo<child/></node>")
{
CHECK(xml_node().ensure_child(STR("")) == xml_node());
CHECK(doc.child(STR("node")).first_child().ensure_child(STR("n")) == xml_node());
xml_node node = doc.child(STR("node"));
// existing child is returned as is
xml_node child = node.ensure_child(STR("child"));
CHECK(child && child == node.child(STR("child")));
// missing child is appended
xml_node n1 = node.ensure_child(STR("n1"));
CHECK(n1 && n1 != child);
// ensuring an existing child does not add a duplicate
CHECK(node.ensure_child(STR("child")) == child);
#ifdef PUGIXML_HAS_STRING_VIEW
xml_node n2 = doc.ensure_child(string_view_t(STR("n2")));
#else
xml_node n2 = doc.ensure_child(STR("n2"));
#endif
CHECK(n2 && n2 != child && n2 != n1);
CHECK_NODE(doc, STR("<node>foo<child/><n1/></node><n2/>"));
}
TEST_XML(dom_node_insert_child_after_name, "<node>foo<child/></node>")
@@ -691,7 +916,14 @@ TEST_XML(dom_node_insert_child_after_name, "<node>foo<child/></node>")
CHECK(child.insert_child_after(STR(""), n2) == xml_node());
CHECK_NODE(doc, STR("<node>foo<child/><n2/><n1/></node>"));
#ifdef PUGIXML_HAS_STRING_VIEW
xml_node n3 = node.insert_child_after(string_view_t(STR("n3")), n1);
#else
xml_node n3 = node.insert_child_after(STR("n3"), n1);
#endif
CHECK(n3 && n3 != node && n3 != child && n3 != n2 && n3 != n1);
CHECK_NODE(doc, STR("<node>foo<child/><n2/><n1/><n3/></node>"));
}
TEST_XML(dom_node_insert_child_before_name, "<node>foo<child/></node>")
@@ -713,7 +945,14 @@ TEST_XML(dom_node_insert_child_before_name, "<node>foo<child/></node>")
CHECK(child.insert_child_before(STR(""), n2) == xml_node());
CHECK_NODE(doc, STR("<node>foo<n1/><n2/><child/></node>"));
#ifdef PUGIXML_HAS_STRING_VIEW
xml_node n3 = node.insert_child_before(string_view_t(STR("n3")), child);
#else
xml_node n3 = node.insert_child_before(STR("n3"), child);
#endif
CHECK(n3 && n3 != node && n3 != child && n3 != n2 && n3 != n1);
CHECK_NODE(doc, STR("<node>foo<n1/><n2/><n3/><child/></node>"));
}
TEST_XML(dom_node_remove_child, "<node><n1/><n2/><n3/><child><n4/></child></node>")
@@ -735,6 +974,20 @@ TEST_XML(dom_node_remove_child, "<node><n1/><n2/><n3/><child><n4/></child></node
CHECK(child.remove_child(STR("n4")));
CHECK_NODE(doc, STR("<node><n2/><child/></node>"));
#ifdef PUGIXML_HAS_STRING_VIEW
CHECK(!node.remove_child(string_view_t()));
CHECK(!node.remove_child(string_view_t(STR("child"), 3)));
CHECK(!node.remove_child(string_view_t(STR("n2"), 1)));
CHECK_NODE(doc, STR("<node><n2/><child/></node>"));
CHECK(node.remove_child(string_view_t(STR("child"))));
CHECK_NODE(doc, STR("<node><n2/></node>"));
CHECK(node.remove_child(string_view_t(STR("n2_notinview"), 2)));
CHECK_NODE(doc, STR("<node/>"));
#endif
}
TEST_XML(dom_node_remove_children, "<node><n1/><n2/><n3/><child><n4/></child></node>")
@@ -1522,6 +1775,30 @@ TEST(dom_node_copy_stackless)
CHECK_NODE(doc, data.c_str());
}
TEST(dom_node_remove_child_stackless)
{
unsigned int count = 20000;
std::basic_string<char_t> data = STR("<root>");
for (unsigned int i = 0; i < count; ++i)
data += STR("<a>");
data += STR("text");
for (unsigned int j = 0; j < count; ++j)
data += STR("</a>");
data += STR("<tail/></root>");
xml_document doc;
CHECK(doc.load_string(data.c_str()));
xml_node root = doc.child(STR("root"));
CHECK(root.remove_child(root.child(STR("a"))));
CHECK_NODE(doc, STR("<root><tail/></root>"));
}
TEST(dom_node_copy_copyless)
{
std::basic_string<char_t> data;
@@ -1710,7 +1987,7 @@ TEST_XML(dom_node_set_deallocate, "<node attr='value'>text</node>")
node.set_name(STR(""));
node.text().set(STR(""));
CHECK_NODE(doc, STR("<:anonymous :anonymous=\"\"></:anonymous>"));
CHECK_NODE(doc, STR("<:anonymous :anonymous=\"\"/>"));
}
TEST(dom_node_copy_declaration_empty_name)
+158 -4
View File
@@ -119,7 +119,7 @@ TEST_XML(dom_text_as_integer_space, "<node><text1> \t\n1234</text1><text2>\n\t 0
CHECK(node.child(STR("text4")).text().as_int() == 0);
}
TEST_XML(dom_text_as_float, "<node><text1>0</text1><text2>1</text2><text3>0.12</text3><text4>-5.1</text4><text5>3e-4</text5><text6>3.14159265358979323846</text6></node>")
TEST_XML(dom_text_as_float, "<node><text1>0</text1><text2>1</text2><text3>0.12</text3><text4>-5.1</text4><text5>3e-4</text5><text6>3.14159265358979323846</text6><text7> \t\n+2.5</text7></node>")
{
xml_node node = doc.child(STR("node"));
@@ -130,9 +130,10 @@ TEST_XML(dom_text_as_float, "<node><text1>0</text1><text2>1</text2><text3>0.12</
CHECK_DOUBLE(double(node.child(STR("text4")).text().as_float()), -5.1);
CHECK_DOUBLE(double(node.child(STR("text5")).text().as_float()), 3e-4);
CHECK_DOUBLE(double(node.child(STR("text6")).text().as_float()), 3.14159265358979323846);
CHECK_DOUBLE(double(node.child(STR("text7")).text().as_float()), 2.5);
}
TEST_XML(dom_text_as_double, "<node><text1>0</text1><text2>1</text2><text3>0.12</text3><text4>-5.1</text4><text5>3e-4</text5><text6>3.14159265358979323846</text6></node>")
TEST_XML(dom_text_as_double, "<node><text1>0</text1><text2>1</text2><text3>0.12</text3><text4>-5.1</text4><text5>3e-4</text5><text6>3.14159265358979323846</text6><text7> \t\n+2.5</text7></node>")
{
xml_node node = doc.child(STR("node"));
@@ -143,6 +144,7 @@ TEST_XML(dom_text_as_double, "<node><text1>0</text1><text2>1</text2><text3>0.12<
CHECK_DOUBLE(node.child(STR("text4")).text().as_double(), -5.1);
CHECK_DOUBLE(node.child(STR("text5")).text().as_double(), 3e-4);
CHECK_DOUBLE(node.child(STR("text6")).text().as_double(), 3.14159265358979323846);
CHECK_DOUBLE(node.child(STR("text7")).text().as_double(), 2.5);
}
TEST_XML(dom_text_as_bool, "<node><text1>0</text1><text2>1</text2><text3>true</text3><text4>True</text4><text5>Yes</text5><text6>yes</text6><text7>false</text7></node>")
@@ -157,6 +159,9 @@ TEST_XML(dom_text_as_bool, "<node><text1>0</text1><text2>1</text2><text3>true</t
CHECK(node.child(STR("text5")).text().as_bool());
CHECK(node.child(STR("text6")).text().as_bool());
CHECK(!node.child(STR("text7")).text().as_bool());
xml_node text = node.append_child(node_pcdata);
CHECK(text.text().as_bool(true) == true);
}
#ifdef PUGIXML_HAS_LONG_LONG
@@ -236,7 +241,7 @@ TEST_XML(dom_text_set, "<node/>")
t.set(STR(""));
CHECK(node.first_child().type() == node_pcdata);
CHECK_NODE(node, STR("<node></node>"));
CHECK_NODE(node, STR("<node/>"));
t.set(STR("boo"));
CHECK(node.first_child().type() == node_pcdata);
@@ -247,8 +252,123 @@ TEST_XML(dom_text_set, "<node/>")
CHECK(node.first_child().type() == node_pcdata);
CHECK(node.first_child() == node.last_child());
CHECK_NODE(node, STR("<node>foobarfoobar</node>"));
t.set(STR(""));
CHECK(node.first_child().type() == node_pcdata);
CHECK_NODE(node, STR("<node/>"));
}
TEST_XML(dom_text_set_with_size, "<node/>")
{
xml_node node = doc.child(STR("node"));
xml_text t = node.text();
t.set(STR(""), 0);
CHECK(node.first_child().type() == node_pcdata);
CHECK_NODE(node, STR("<node/>"));
t.set(STR("boo"), 3);
CHECK(node.first_child().type() == node_pcdata);
CHECK(node.first_child() == node.last_child());
CHECK_NODE(node, STR("<node>boo</node>"));
t.set(STR("foobarfoobar"), 12);
CHECK(node.first_child().type() == node_pcdata);
CHECK(node.first_child() == node.last_child());
CHECK_NODE(node, STR("<node>foobarfoobar</node>"));
t.set(STR(""), 0);
CHECK(node.first_child().type() == node_pcdata);
CHECK_NODE(node, STR("<node/>"));
}
TEST_XML(dom_text_set_partially_with_size, "<node/>")
{
xml_node node = doc.child(STR("node"));
xml_text t = node.text();
t.set(STR("foo"), 0);
CHECK(node.first_child().type() == node_pcdata);
CHECK_NODE(node, STR("<node/>"));
t.set(STR("boofoo"), 3);
CHECK(node.first_child().type() == node_pcdata);
CHECK(node.first_child() == node.last_child());
CHECK_NODE(node, STR("<node>boo</node>"));
t.set(STR("foobarfoobar"), 3);
CHECK(node.first_child().type() == node_pcdata);
CHECK(node.first_child() == node.last_child());
CHECK_NODE(node, STR("<node>foo</node>"));
t.set(STR("foo"), 0);
CHECK(node.first_child().type() == node_pcdata);
CHECK_NODE(node, STR("<node/>"));
}
#ifdef PUGIXML_HAS_STRING_VIEW
TEST_XML(dom_text_set_with_string_view, "<node/>")
{
xml_node node = doc.child(STR("node"));
xml_text t = node.text();
t.set(string_view_t(STR("")));
CHECK(node.first_child().type() == node_pcdata);
CHECK_NODE(node, STR("<node/>"));
t.set(string_view_t(STR("boo")));
CHECK(node.first_child().type() == node_pcdata);
CHECK(node.first_child() == node.last_child());
CHECK_NODE(node, STR("<node>boo</node>"));
t.set(string_view_t(STR("foobarfoobar")));
CHECK(node.first_child().type() == node_pcdata);
CHECK(node.first_child() == node.last_child());
CHECK_NODE(node, STR("<node>foobarfoobar</node>"));
t.set(string_view_t(STR("")));
CHECK(node.first_child().type() == node_pcdata);
CHECK_NODE(node, STR("<node/>"));
t.set(string_view_t(STR("something")));
CHECK(node.first_child().type() == node_pcdata);
CHECK_NODE(node, STR("<node>something</node>"));
// empty string view (null data pointer)
t.set(string_view_t());
CHECK(node.first_child().type() == node_pcdata);
CHECK_NODE(node, STR("<node/>"));
t.set(string_view_t(STR("afternulldata")));
CHECK(node.first_child().type() == node_pcdata);
CHECK_NODE(node, STR("<node>afternulldata</node>"));
}
TEST_XML(dom_text_set_partially_with_string_view, "<node/>")
{
xml_node node = doc.child(STR("node"));
xml_text t = node.text();
t.set(string_view_t(STR("foo"), 0));
CHECK(node.first_child().type() == node_pcdata);
CHECK_NODE(node, STR("<node/>"));
t.set(string_view_t(STR("boofoo"), 3));
CHECK(node.first_child().type() == node_pcdata);
CHECK(node.first_child() == node.last_child());
CHECK_NODE(node, STR("<node>boo</node>"));
t.set(string_view_t(STR("foobarfoobar"), 3));
CHECK(node.first_child().type() == node_pcdata);
CHECK(node.first_child() == node.last_child());
CHECK_NODE(node, STR("<node>foo</node>"));
t.set(string_view_t(STR("foo"), 0));
CHECK(node.first_child().type() == node_pcdata);
CHECK_NODE(node, STR("<node/>"));
}
#endif
TEST_XML(dom_text_assign, "<node/>")
{
xml_node node = doc.child(STR("node"));
@@ -273,7 +393,14 @@ TEST_XML(dom_text_assign, "<node/>")
node.append_child(STR("text8")).text() = true;
xml_text() = true;
CHECK_NODE(node, STR("<node><text1>v1</text1><text2>-2147483647</text2><text3>-2147483648</text3><text4>4294967295</text4><text5>4294967294</text5><text6>0.5</text6><text7>0.25</text7><text8>true</text8></node>"));
#ifdef PUGIXML_HAS_STRING_VIEW
node.append_child(string_view_t(STR("text9"))).text() = string_view_t(STR("v2"));
xml_text() = string_view_t(STR("text9"));
#else
node.append_child(STR("text9")).text() = STR("v2");
#endif
CHECK_NODE(node, STR("<node><text1>v1</text1><text2>-2147483647</text2><text3>-2147483648</text3><text4>4294967295</text4><text5>4294967294</text5><text6>0.5</text6><text7>0.25</text7><text8>true</text8><text9>v2</text9></node>"));
}
TEST_XML(dom_text_set_value, "<node/>")
@@ -282,6 +409,10 @@ TEST_XML(dom_text_set_value, "<node/>")
CHECK(node.append_child(STR("text1")).text().set(STR("v1")));
CHECK(!xml_text().set(STR("v1")));
CHECK(!xml_text().set(STR("v1"), 2));
#ifdef PUGIXML_HAS_STRING_VIEW
CHECK(!xml_text().set(string_view_t(STR("v1"))));
#endif
CHECK(node.append_child(STR("text2")).text().set(-2147483647));
CHECK(node.append_child(STR("text3")).text().set(-2147483647 - 1));
@@ -418,6 +549,29 @@ TEST_XML(dom_text_middle, "<node><c1>notthisone</c1>text<c2/></node>")
CHECK(t.data() == node.last_child());
}
#ifdef PUGIXML_HAS_STRING_VIEW
TEST_XML(dom_text_middle_string_view, "<node><c1>notthisone</c1>text<c2/></node>")
{
xml_node node = doc.child(STR("node"));
xml_text t = node.text();
CHECK_STRING(t.get(), STR("text"));
t.set(string_view_t(STR("notext")));
CHECK_NODE(node, STR("<node><c1>notthisone</c1>notext<c2/></node>"));
CHECK(node.remove_child(t.data()));
CHECK(!t);
CHECK_NODE(node, STR("<node><c1>notthisone</c1><c2/></node>"));
t.set(string_view_t(STR("yestext")));
CHECK(t);
CHECK_NODE(node, STR("<node><c1>notthisone</c1><c2/>yestext</node>"));
CHECK(t.data() == node.last_child());
}
#endif
TEST_XML_FLAGS(dom_text_data, "<node><a>foo</a><b><![CDATA[bar]]></b><c><?pi value?></c><d/></node>", parse_default | parse_pi)
{
xml_node node = doc.child(STR("node"));
+185 -3
View File
@@ -183,6 +183,9 @@ TEST_XML(dom_attr_as_bool, "<node attr1='0' attr2='1' attr3='true' attr4='True'
CHECK(node.attribute(STR("attr5")).as_bool());
CHECK(node.attribute(STR("attr6")).as_bool());
CHECK(!node.attribute(STR("attr7")).as_bool());
xml_attribute attr = node.append_attribute(STR("attr8"));
CHECK(attr.as_bool(true) == true);
}
#ifdef PUGIXML_HAS_LONG_LONG
@@ -536,6 +539,42 @@ TEST_XML(dom_node_child, "<node><child1/><child2/></node>")
CHECK(doc.child(STR("node")).child(STR("child2")) == doc.child(STR("node")).last_child());
}
#ifdef PUGIXML_HAS_STRING_VIEW
TEST_XML(dom_node_child_stringview, "<node><child1/><child2/></node>")
{
CHECK(xml_node().child(string_view_t(STR("n"))) == xml_node());
CHECK(doc.child(string_view_t()) == xml_node());
CHECK(doc.child(string_view_t(STR("n"))) == xml_node());
xml_node node = doc.child(string_view_t(STR("node")));
CHECK_NAME_VALUE(node, STR("node"), STR(""));
CHECK(node.child(string_view_t(STR("child2"))) == node.last_child());
// verify only the characters in the view of the string view are included in the comparison
CHECK_NAME_VALUE(doc.child(string_view_t(STR("node_andextratext"), 4)), STR("node"), STR(""));
CHECK(doc.child(string_view_t(STR("node"), 2)) == xml_node());
}
TEST_XML(dom_node_child_interior_null, "<node><child1/><child2/></node>")
{
const char_t name[] = STR("node\0extra");
size_t len = (sizeof(name) / sizeof(char_t)) - 1;
CHECK(len == 10);
xml_node node = doc.child(string_view_t(name, 4)); // "node" view excluding null
CHECK_NAME_VALUE(node, STR("node"), STR(""));
CHECK(doc.child(string_view_t(name, 5)) == xml_node()); // "node\0" view including null
CHECK(doc.child(string_view_t(name, len)) == xml_node()); // "node\0extra" view
node.set_name(string_view_t(name, len));
CHECK_NODE(doc, STR("<node><child1/><child2/></node>"));
CHECK_NAME_VALUE(node, STR("node"), STR(""));
CHECK_NAME_VALUE(doc.child(string_view_t(name, 4)), STR("node"), STR("")); // "node" view excluding null
CHECK(doc.child(string_view_t(name, 5)) == xml_node()); // "node\0" view including null
CHECK(doc.child(string_view_t(name, len)) == xml_node()); // "node\0extra" view
}
#endif
TEST_XML(dom_node_attribute, "<node attr1='0' attr2='1'/>")
{
CHECK(xml_node().attribute(STR("a")) == xml_attribute());
@@ -547,6 +586,46 @@ TEST_XML(dom_node_attribute, "<node attr1='0' attr2='1'/>")
CHECK(node.attribute(STR("attr2")) == node.last_attribute());
}
#ifdef PUGIXML_HAS_STRING_VIEW
TEST_XML(dom_node_attribute_stringview, "<node attr1='0' attr2='1'/>")
{
CHECK(xml_node().attribute(string_view_t(STR("a"))) == xml_attribute());
xml_node node = doc.child(string_view_t(STR("node")));
CHECK(node.attribute(string_view_t()) == xml_attribute());
CHECK(node.attribute(string_view_t(STR("n"))) == xml_attribute());
CHECK_NAME_VALUE(node.attribute(string_view_t(STR("attr1"))), STR("attr1"), STR("0"));
CHECK(node.attribute(string_view_t(STR("attr2"))) == node.last_attribute());
// verify only the characters in the view of the string view are included in the comparison
CHECK_NAME_VALUE(node.attribute(string_view_t(STR("attr1_andextratext"), 5)), STR("attr1"), STR("0"));
CHECK(node.attribute(string_view_t(STR("attr1"), 2)) == xml_attribute());
}
TEST_XML(dom_node_attribute_interior_null, "<node attr1='0' attr2='1'/>")
{
xml_node node = doc.child(STR("node"));
CHECK_NAME_VALUE(node, STR("node"), STR(""));
const char_t name[] = STR("attr2\0extra");
size_t len = (sizeof(name) / sizeof(char_t)) - 1;
CHECK(len == 11);
CHECK_NAME_VALUE(node.attribute(string_view_t(name, 5)), STR("attr2"), STR("1")); // "attr2" view excluding null
CHECK(node.attribute(string_view_t(name, 6)) == xml_attribute()); // "attr2\0" view including null
CHECK(node.attribute(string_view_t(name, len)) == xml_attribute()); // "attr2\0extra" view
xml_attribute attr = node.attribute(STR("attr2"));
CHECK_NAME_VALUE(attr, STR("attr2"), STR("1"));
attr.set_name(string_view_t(name, len));
CHECK_NODE(doc, STR("<node attr1=\"0\" attr2=\"1\"/>"));
CHECK_NAME_VALUE(node.attribute(string_view_t(name, 5)), STR("attr2"), STR("1")); // "attr2" view excluding null
CHECK(node.attribute(string_view_t(name, 6)) == xml_attribute()); // "attr2\0" view including null
CHECK(node.attribute(string_view_t(name, len)) == xml_attribute()); // "attr2\0extra" view
}
#endif
TEST_XML(dom_node_next_previous_sibling, "<node><child1/><child2/><child3/></node>")
{
CHECK(xml_node().next_sibling() == xml_node());
@@ -567,9 +646,17 @@ TEST_XML(dom_node_next_previous_sibling, "<node><child1/><child2/><child3/></nod
CHECK(child1.next_sibling(STR("child3")) == child3);
CHECK(child1.next_sibling(STR("child")) == xml_node());
#ifdef PUGIXML_HAS_STRING_VIEW
CHECK(child1.next_sibling(string_view_t(STR("child3"))) == child3);
CHECK(child1.next_sibling(string_view_t(STR("child"))) == xml_node());
#endif
CHECK(child3.previous_sibling(STR("child1")) == child1);
CHECK(child3.previous_sibling(STR("child")) == xml_node());
#ifdef PUGIXML_HAS_STRING_VIEW
CHECK(child3.previous_sibling(string_view_t(STR("child1"))) == child1);
CHECK(child3.previous_sibling(string_view_t(STR("child"))) == xml_node());
#endif
}
TEST_XML(dom_node_child_value, "<node><novalue/><child1>value1</child1><child2>value2<n/></child2><child3><![CDATA[value3]]></child3>value4</node>")
@@ -795,7 +882,12 @@ struct test_walker: xml_tree_walker
std::basic_string<char_t> depthstr() const
{
char buf[32];
#if __cplusplus >= 201103 || defined(__APPLE__) // Xcode 14 warns about use of sprintf in C++98 builds
snprintf(buf, sizeof(buf), "%d", depth());
#else
sprintf(buf, "%d", depth());
#endif
#ifdef PUGIXML_WCHAR_MODE
wchar_t wbuf[32];
@@ -807,7 +899,7 @@ struct test_walker: xml_tree_walker
#endif
}
virtual bool begin(xml_node& node) PUGIXML_OVERRIDE
bool begin(xml_node& node) PUGIXML_OVERRIDE
{
log += STR("|");
log += depthstr();
@@ -819,7 +911,7 @@ struct test_walker: xml_tree_walker
return ++call_count != stop_count && xml_tree_walker::begin(node);
}
virtual bool for_each(xml_node& node) PUGIXML_OVERRIDE
bool for_each(xml_node& node) PUGIXML_OVERRIDE
{
log += STR("|");
log += depthstr();
@@ -831,7 +923,7 @@ struct test_walker: xml_tree_walker
return ++call_count != stop_count && xml_tree_walker::end(node);
}
virtual bool end(xml_node& node) PUGIXML_OVERRIDE
bool end(xml_node& node) PUGIXML_OVERRIDE
{
log += STR("|");
log += depthstr();
@@ -1161,6 +1253,64 @@ TEST_XML(dom_node_attribute_hinted, "<node attr1='1' attr2='2' attr3='3' />")
CHECK(!node.attribute(STR("attr"), hint) && hint == attr2);
}
#ifdef PUGIXML_HAS_STRING_VIEW
TEST_XML(dom_node_attribute_hinted_stringview, "<node attr1='1' attr2='2' attr3='3' />")
{
xml_node node = doc.first_child();
string_view_t a1name = string_view_t(STR("attr1"));
string_view_t a2name = string_view_t(STR("attr2"));
string_view_t a3name = string_view_t(STR("attr3"));
xml_attribute attr1 = node.attribute(a1name);
xml_attribute attr2 = node.attribute(a2name);
xml_attribute attr3 = node.attribute(a3name);
xml_attribute hint;
CHECK(!xml_node().attribute(string_view_t(string_view_t(STR("test"))), hint) && !hint);
CHECK(node.attribute(a2name, hint) == attr2 && hint == attr3);
CHECK(node.attribute(a3name, hint) == attr3 && !hint);
CHECK(node.attribute(a1name, hint) == attr1 && hint == attr2);
CHECK(node.attribute(a2name, hint) == attr2 && hint == attr3);
CHECK(node.attribute(a1name, hint) == attr1 && hint == attr2);
CHECK(node.attribute(a1name, hint) == attr1 && hint == attr2);
CHECK(!node.attribute(string_view_t(), hint) && hint == attr2);
CHECK(!node.attribute(string_view_t(STR("attr1"), 4), hint) && hint == attr2); // "attr"
CHECK(node.attribute(string_view_t(STR("attr3_extra"), 5), hint) == attr3 && !hint); // "attr3"
}
TEST_XML(dom_node_attribute_hint_interior_null, "<node attr1='1' attr2='2' attr3='3' />")
{
xml_node node = doc.first_child();
xml_attribute attr1 = node.attribute(STR("attr1"));
xml_attribute attr2 = node.attribute(STR("attr2"));
xml_attribute attr3 = node.attribute(STR("attr3"));
CHECK(node && attr1 && attr2 && attr3);
const char_t name[] = STR("attr2\0extra");
size_t len = (sizeof(name) / sizeof(char_t)) - 1;
CHECK(len == 11);
xml_attribute hint;
CHECK(node.attribute(string_view_t(name, 5), hint) == attr2 && hint == attr3); // "attr2"
CHECK(node.attribute(string_view_t(name, 5), hint) == attr2 && hint == attr3); // "attr2"
CHECK(!node.attribute(string_view_t(name, 6), hint) && hint == attr3); // "attr2\0"
CHECK(!node.attribute(string_view_t(name, len), hint) && hint == attr3); // "attr2\0extra"
attr2.set_name(string_view_t(name, len)); // attr2\0extra
CHECK(node.attribute(string_view_t(name, 5), hint) == attr2 && hint == attr3); // "attr2"
CHECK(node.attribute(string_view_t(name, 5), hint) == attr2 && hint == attr3); // "attr2"
CHECK(!node.attribute(string_view_t(name, 6), hint) && hint == attr3); // "attr2\0"
CHECK(!node.attribute(string_view_t(name, len), hint) && hint == attr3); // "attr2\0extra"
}
#endif
TEST_XML(dom_as_int_overflow, "<node attr1='-2147483649' attr2='2147483648' attr3='-4294967296' />")
{
xml_node node = doc.child(STR("node"));
@@ -1297,3 +1447,35 @@ TEST(dom_node_anonymous)
CHECK_STRING(doc.child_value(), STR(""));
CHECK_STRING(doc.last_child().child_value(), STR(""));
}
TEST_XML(dom_node_anonymous_child, "<node></node>")
{
xml_node node = doc.child(STR("node"));
CHECK_NAME_VALUE(node, STR("node"), STR(""));
node.set_name(STR(""));
CHECK_NODE(doc, STR("<:anonymous/>"));
CHECK(doc.first_child() != xml_node());
CHECK_NAME_VALUE(doc.first_child(), STR(""), STR(""));
// searching for empty string does not find a node with empty name
CHECK(doc.child(STR("")) == xml_node());
#ifdef PUGIXML_HAS_STRING_VIEW
CHECK(doc.child(string_view_t()) == xml_node());
CHECK(doc.child(string_view_t(STR("hi"), 0)) == xml_node());
#endif
}
TEST_XML(dom_node_anonymous_attribute, "<node attr='0'/>")
{
xml_attribute attr = doc.first_child().attribute(STR("attr"));
CHECK(attr != xml_attribute());
attr.set_name(STR(""));
CHECK_NODE(doc, STR("<node :anonymous=\"0\"/>"));
CHECK_NAME_VALUE(doc.first_child().first_attribute(), STR(""), STR("0"));
CHECK(doc.first_child().attribute(STR("")) == xml_attribute());
#ifdef PUGIXML_HAS_STRING_VIEW
CHECK(doc.first_child().attribute(string_view_t()) == xml_attribute());
CHECK(doc.first_child().attribute(string_view_t(STR("hi"), 0)) == xml_attribute());
#endif
}
+106
View File
@@ -1252,6 +1252,112 @@ TEST_XML_FLAGS(parse_embed_pcdata_comment, "<n>text1<!---->text2</n>", parse_emb
CHECK_STRING(n.last_child().value(), STR("text2"));
}
TEST(parse_merge_pcdata)
{
unsigned int flag_sets[] = {parse_cdata, parse_pi, parse_comments, parse_declaration};
for (unsigned int i = 0; i < sizeof(flag_sets) / sizeof(flag_sets[0]); ++i)
{
unsigned int flags = parse_merge_pcdata | flag_sets[i];
xml_document doc;
xml_parse_result res = doc.load_string(STR("<node>First text<!-- here is a mesh node -->Second text<![CDATA[someothertext]]>some more text<?include somedata?>Last text</node>"), flags);
CHECK(res);
xml_node child = doc.child(STR("node"));
if (flags & parse_comments)
{
CHECK_STRING(child.first_child().value(), STR("First text"));
CHECK(child.first_child().next_sibling().type() == node_comment);
CHECK_NODE(doc, STR("<node>First text<!-- here is a mesh node -->Second textsome more textLast text</node>"));
}
else if (flags & parse_cdata)
{
CHECK_STRING(child.first_child().value(), STR("First textSecond text"));
CHECK(child.first_child().next_sibling().type() == node_cdata);
CHECK_NODE(doc, STR("<node>First textSecond text<![CDATA[someothertext]]>some more textLast text</node>"));
}
else if (flags & parse_pi)
{
CHECK_STRING(child.first_child().value(), STR("First textSecond textsome more text"));
CHECK(child.first_child().next_sibling().type() == node_pi);
CHECK_NODE(doc, STR("<node>First textSecond textsome more text<?include somedata?>Last text</node>"));
}
else
{
CHECK(child.first_child() == child.last_child());
CHECK(child.first_child().type() == node_pcdata);
CHECK_NODE(doc, STR("<node>First textSecond textsome more textLast text</node>"));
}
CHECK(child.last_child().type() == node_pcdata);
}
}
TEST(parse_merge_pcdata_escape)
{
xml_document doc;
xml_parse_result res = doc.load_string(STR("<node>First &amp;lt; <!-- comment 1 --> Second &amp;gt; <!-- comment 2 --> Third &amp;quot;</node>"), parse_default | parse_merge_pcdata);
CHECK(res);
CHECK_STRING(doc.child(STR("node")).child_value(), STR("First &lt; Second &gt; Third &quot;"));
}
TEST(parse_merge_pcdata_whitespace)
{
unsigned int flag_sets[] = {0, parse_ws_pcdata, parse_ws_pcdata_single};
for (unsigned int i = 0; i < sizeof(flag_sets) / sizeof(flag_sets[0]); ++i)
{
unsigned int flags = parse_merge_pcdata | flag_sets[i];
xml_document doc;
xml_parse_result res = doc.load_string(STR("<node><child1> <!-- comment 1 -->\t<!-- comment 2 -->\n</child1><child2>text<!-- comment 1-->\t<!-- comment2 --> end</child2></node>"), flags);
CHECK(res);
if (flags & parse_ws_pcdata)
{
CHECK_STRING(doc.child(STR("node")).child(STR("child1")).child_value(), STR(" \t\n"));
CHECK_STRING(doc.child(STR("node")).child(STR("child2")).child_value(), STR("text\t end"));
}
else if (flags & parse_ws_pcdata_single)
{
CHECK_STRING(doc.child(STR("node")).child(STR("child1")).child_value(), STR("\n"));
CHECK_STRING(doc.child(STR("node")).child(STR("child2")).child_value(), STR("text end"));
}
else
{
CHECK(!doc.child(STR("node")).child(STR("child1")).first_child());
CHECK_STRING(doc.child(STR("node")).child(STR("child2")).child_value(), STR("text end"));
}
}
}
TEST(parse_merge_pcdata_append)
{
xml_document doc;
doc.append_child(STR("node")).append_child(node_pcdata);
xml_parse_result res = doc.child(STR("node")).append_buffer("hello <!--comment-->world", 25, parse_merge_pcdata | parse_fragment);
CHECK(res.status == status_append_invalid_root);
CHECK_STRING(doc.child(STR("node")).first_child().value(), STR(""));
doc.child(STR("node")).remove_children();
res = doc.child(STR("node")).append_buffer("hello <!--comment-->world", 25, parse_merge_pcdata | parse_fragment);
CHECK(res.status == status_ok);
CHECK_STRING(doc.child(STR("node")).first_child().value(), STR("hello world"));
}
TEST(parse_merge_pcdata_overlap)
{
xml_document doc;
xml_parse_result res = doc.load_string(STR("<node>short <!-- --> this string is very long so long that copying it will overlap itself</node>"), parse_merge_pcdata);
CHECK(res);
CHECK_STRING(doc.child_value(STR("node")), STR("short this string is very long so long that copying it will overlap itself"));
}
TEST(parse_encoding_detect)
{
char test[] = "<?xml version='1.0' encoding='utf-8'?><n/>";
+1 -2
View File
@@ -1,5 +1,3 @@
#ifndef PUGIXML_NO_STL
#include "test.hpp"
#include <string>
@@ -8,6 +6,7 @@ using namespace pugi;
// letters taken from http://www.utf8-chartable.de/
#ifndef PUGIXML_NO_STL
TEST(as_wide_empty)
{
CHECK(as_wide("") == L"");
+1 -1
View File
@@ -1,5 +1,5 @@
#include "../src/pugixml.hpp"
#if PUGIXML_VERSION != 1110
#if PUGIXML_VERSION != 1160 // 1.16
#error Unexpected pugixml version
#endif
+28 -4
View File
@@ -237,7 +237,7 @@ struct test_writer: xml_writer
{
std::basic_string<char_t> contents;
virtual void write(const void* data, size_t size) PUGIXML_OVERRIDE
void write(const void* data, size_t size) PUGIXML_OVERRIDE
{
CHECK(size % sizeof(char_t) == 0);
contents.append(static_cast<const char_t*>(data), size / sizeof(char_t));
@@ -572,12 +572,36 @@ TEST(write_pcdata_null)
xml_document doc;
doc.append_child(STR("node")).append_child(node_pcdata);
CHECK_NODE(doc, STR("<node></node>"));
CHECK_NODE_EX(doc, STR("<node></node>\n"), STR("\t"), format_indent);
CHECK_NODE(doc, STR("<node/>"));
CHECK_NODE_EX(doc, STR("<node />\n"), STR("\t"), format_indent);
CHECK_NODE_EX(doc, STR("<node></node>"), STR("\t"), format_raw | format_no_empty_element_tags);
CHECK_NODE_EX(doc, STR("<node></node>\n"), STR("\t"), format_indent | format_no_empty_element_tags);
doc.first_child().append_child(node_pcdata);
CHECK_NODE(doc, STR("<node></node>"));
CHECK_NODE_EX(doc, STR("<node></node>\n"), STR("\t"), format_indent);
CHECK_NODE_EX(doc, STR("<node></node>\n"), STR("\t"), format_indent | format_no_empty_element_tags);
}
TEST(write_pcdata_basic)
{
xml_document doc;
doc.append_child(STR("node")).append_child(node_pcdata).set_value(STR("text"));
CHECK_NODE(doc, STR("<node>text</node>"));
CHECK_NODE_EX(doc, STR("<node>text</node>\n"), STR("\t"), format_indent);
CHECK_NODE_EX(doc, STR("<node>text</node>"), STR("\t"), format_raw | format_no_empty_element_tags);
}
TEST(write_pcdata_empty_text)
{
xml_document doc;
doc.append_child(STR("node")).text().set(STR(""));
CHECK_NODE(doc, STR("<node/>"));
CHECK_NODE_EX(doc, STR("<node />\n"), STR("\t"), format_indent);
CHECK_NODE_EX(doc, STR("<node></node>"), STR("\t"), format_raw | format_no_empty_element_tags);
}
TEST(write_pcdata_whitespace_fixedpoint)
@@ -687,7 +711,7 @@ TEST(write_flush_coverage)
#ifndef PUGIXML_NO_EXCEPTIONS
struct throwing_writer: xml_writer
{
virtual void write(const void*, size_t) PUGIXML_OVERRIDE
void write(const void*, size_t) PUGIXML_OVERRIDE
{
throw std::runtime_error("write failed");
}
+36 -10
View File
@@ -10,14 +10,6 @@
#include <algorithm>
#include <limits>
// std::random_shuffle is deprecated in c++14, is removed in c++17.
#if defined(__cplusplus) && (__cplusplus >= 201402L)
# include <random>
# 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 <typename T>
static void random_shuffle(std::vector<T>& 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<char_t> query = STR("0");
@@ -163,7 +171,7 @@ TEST(xpath_sort_random_medium)
xpath_node_set ns = doc.select_nodes(STR("//node() | //@*"));
std::vector<xpath_node> 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<xpath_node> nsv(ns.begin(), ns.end());
PUGIXML_SHUFFLE(nsv);
random_shuffle(nsv);
xpath_node_set copy(&nsv[0], &nsv[0] + nsv.size());
copy.sort();
@@ -202,6 +210,24 @@ TEST(xpath_sort_random_large)
for (unsigned int i = 2; i < 129; ++i) tester % i;
}
TEST_XML(xpath_sort_coverage, "<node><a/><b/></node>")
{
xml_node a = doc.child(STR("node")).child(STR("a"));
xml_node b = doc.child(STR("node")).child(STR("b"));
xpath_node nodes[17];
for (size_t i = 0; i < sizeof(nodes) / sizeof(nodes[0]); ++i)
nodes[i] = (i == 0 || i == 8 || i == 16) ? a : b;
xpath_node_set ns(nodes, nodes + sizeof(nodes) / sizeof(nodes[0]), xpath_node_set::type_unsorted);
ns.sort();
CHECK(ns.type() == xpath_node_set::type_sorted);
for (size_t i = 0; i < ns.size(); ++i)
CHECK(ns[i].node() == (i < 3 ? a : b));
}
TEST(xpath_long_numbers_parse)
{
const char_t* str_flt_max = STR("340282346638528860000000000000000000000");
+4 -2
View File
@@ -573,7 +573,8 @@ TEST_XML(xpath_api_nodeset_move_assign_self, "<node><foo/><foo/><bar/></node>")
test_runner::_memory_fail_threshold = 1;
set = std::move(*&set);
xpath_node_set* self = &set;
set = std::move(*self);
}
TEST(xpath_api_query_move)
@@ -614,7 +615,8 @@ TEST(xpath_api_query_move)
CHECK(q4);
CHECK(q4.evaluate_boolean(c));
q4 = std::move(*&q4);
xpath_query* q4self = &q4;
q4 = std::move(*q4self);
CHECK(q4);
CHECK(q4.evaluate_boolean(c));
+12
View File
@@ -405,6 +405,18 @@ TEST(xpath_parse_depth_limit)
CHECK_XPATH_FAIL((STR("/foo") + rep(STR("//x"), limit / 2)).c_str());
}
TEST(xpath_parse_depth_limit_coverage)
{
const size_t almost_limit = 1023;
CHECK_XPATH_FAIL((rep(STR("("), almost_limit) + STR("string(1)") + rep(STR(")"), almost_limit)).c_str());
CHECK_XPATH_FAIL((rep(STR("("), almost_limit) + STR("foo[1]") + rep(STR(")"), almost_limit)).c_str());
xpath_variable_set vars;
CHECK(vars.set(STR("x"), xpath_node_set()));
CHECK_XPATH_FAIL_VAR((rep(STR("("), almost_limit) + STR("$x[1]") + rep(STR(")"), almost_limit)).c_str(), &vars);
}
TEST_XML(xpath_parse_location_path, "<node><child/></node>")
{
CHECK_XPATH_NODESET(doc, STR("/node")) % 2;
+4
View File
@@ -639,9 +639,13 @@ TEST_XML(xpath_paths_unsorted_child, "<node><foo><bar/></foo><node><foo><bar/></
TEST_XML(xpath_paths_optimize_compare_attribute, "<node id='1' /><node id='2' /><node xmlns='3' />")
{
xml_node node = doc.first_child();
CHECK_XPATH_NODESET(doc, STR("node[@id = '1']")) % 2;
CHECK_XPATH_NODESET(doc, STR("node[@id = '2']")) % 4;
CHECK_XPATH_NODESET(doc, STR("node[@id = 2]")) % 4;
CHECK_XPATH_BOOLEAN(node, STR("@id < 2"), true);
CHECK_XPATH_BOOLEAN(node, STR("2 > @id"), true);
CHECK_XPATH_NODESET(doc, STR("node[@id[. > 3] = '2']"));
CHECK_XPATH_NODESET(doc, STR("node['1' = @id]")) % 2;
+10
View File
@@ -463,6 +463,16 @@ TEST_XML(xpath_variables_copy, "<node />")
CHECK(!set3.get(STR("a")));
}
TEST(xpath_variables_copy_unset_string)
{
xpath_variable_set set1;
CHECK(set1.add(STR("v"), xpath_type_string));
xpath_variable_set set2 = set1;
CHECK(set2.get(STR("v")));
CHECK_STRING(set2.get(STR("v"))->get_string(), STR(""));
}
TEST_XML(xpath_variables_copy_out_of_memory, "<node1 /><node2 />")
{
xpath_variable_set set1;