# Change Log
## [0.3.10] (in development)
## [0.3.9] (2026-04-22)
### Added
* `Node::new_comment` constructor, wrapping `xmlNewDocComment`. Returns an
unlinked comment node bound to the given document; propagates an error
rather than panicking on embedded NULs.
* `libxml::init_parser()`, a top-level safe wrapper around
`xmlInitParser()` guarded by `std::sync::Once`. Useful for application
code that touches libxml2 directly without going through `parser::Parser`.
### Changes
* `Parser::default()` and `Parser::default_html()` now route through
`libxml::init_parser()` instead of their own private `Once`, giving a
single source of truth for libxml2 parser initialisation.
## [0.3.8] (2025-25-09)
### Changes
* Corrected the vcpkg include directories used during build
## [0.3.7] (2025-18-08)
### Changes
* Corrected the bindgen configuration for c14n, thanks to @Qubitza
## [0.3.6] (2025-13-07)
### Added
* c14n, thanks to @saks and @tstenner
* add `canonicalize` method for `Node` and `Document`
* see `tests/c14n.rs` for examples
* Utility node methods, thanks to @saks (nokogiri inspired)
* add `Node::ancestors` method
* add `Node::at_xpath` method. Similar to `findnodes` but nokogiri inspired.
This work still hasn't been extended to `RoNode`, contributions welcome.
### Changes
* Added more low-level headers from bindgen for wrapper uses interested in unsafe low-level libxml2 calls.
The bindgen coverage has been in flux since the v0.3.4 release, as we stabilize the new build approach.
### Removed
## [0.3.5] (2025-28-04)
This release stabilizes the new "bindgen during build" approach of v0.3.4 to more platforms.
Support for newer libxml2 versions has been improved.
- CI support for v2.12.9, v2.13.8, v2.14.1
Thanks go to @wetneb and @charmitro for contributing.
### Added
* cargo build: expose libxml2 version to main build script;
* creating a new `Parser` now initializes via `bindings::xmlInitParser`, called at most once.
### Changes
* cargo build: mark `max_align_t` as opaque to fix i386 build failure
* cfg: adapt mutability of error pointer depending on libxml version
* change the return type of `xmlGetNodeType` from `u32` to the more portable `bindings::xmlElementType`
* change the argument type of `NodeType::from_int` from `u32` to the more portable `bindings::xmlElementType`
* protect `Schema` initialization to be closer to thread-safe (note that this wrapper is NOT thread-safe in general)
### Removed
* The use of `SchemaParserContext` and `SchemaValidationContext` is currently NOT thread safe.
Hence, The `schema_test` has been weakened to run in a single thread (future improvements welcome).
## [0.3.4] (2025-16-04)
Thanks go to @wetneb, @anwaralameddin, @rudolphfroger, @jcamiel, @imcsk8 for contributions to this release.
### Added
* Node methods: `get_property_no_ns` (alias: `get_attribute_no_ns`), `get_properties_ns` (alias: `get_attributes_ns`), `has_property_no_ns` (alias: `has_attribute_no_ns`), `remove_property_no_ns` (alias: `remove_attribute_no_ns`), `get_property_node_ns` (alias: `get_attribute_node_ns`), `get_property_node_no_ns` (alias: `get_attribute_node_no_ns`)
* Added implementations of `Hash`, `PartialEq` and `Eq` traits for `Namespace`
### Changed
* Call bindgen at build time on Unix platforms (thanks @wetneb)
## [0.3.3] 2023-17-07
### Changed
* Update the implementation of `StructuredError` so that all validation errors are returned from the validation methods present on `SchemaValidationContext`. Previously, all returned validation errors were identical due to libxml reusing a global memory address for all reported errors. Thanks @JDSeiler !
* The `message` method of `StructuredError` has been deprecated.
## [0.3.2] 2023-07-05
### Added
* XPath: `Context::findvalues`, with optional node-bound evaluation, obtaining `String` values.
* `Node::findvalues` method for direct XPath search obtaining `String` values, without first explicitly instantiating a `Context`. Reusing a `Context` remains more efficient.
## [0.3.1] 2022-26-03
* Added: Thanks to @lepapareil, @hurlenko and @ballsteve for contributing installation docs for Windows and MacOS.
* Added: `Node` and `RoNode` now have `has_property` (alias `has_attribute`) and `has_property_ns` (alias `has_attribute_ns`) to check attribute presence without allocating the value.
* Added: `xpath::is_well_formed_xpath`, thanks @bcpeinhardt !
## [0.3.0] 2021-27-05
* Change `Parser::parse_file/string_with_encoding` to `Parser::parse_file/string_with_options`.
* Introduce `ParserOptions` which encapsulates the forced encoding setting together with libxml2s HTML and XML parser options.
* For systems without a pkg-config capability, we now use the `LIBXML2` environment variable to detect an installed libxml2 toolchain. (thanks @przygienda !)
## [0.2.16] 2021-31-01
### Added
* More element-oriented methods: `get_next_element_sibling`, `get_prev_element_sibling`, `get_last_element_child`, added to both `Node` and `RoNode`.
* `Document::ronode_to_string` for printing read-only nodes
* `RoNode::node_ptr` for getting the internal libxml2 raw pointer of a read-only node
## [0.2.15] 2020-28-09
Thanks to @JoshuaNitschke for contributing OS-based package detection for the native libxml2! Also thanks to @coding-yogi, @ignatenkobrain and @simoin for investigating platform-specific issues with this crate, some of which expect resolution in upcoming versions.
### Added
* Support for x64-Windows use via the vcpkg package manager (with new CI monitoring via appveyor).
### Changed
* Added back an `Error` trait implementation for `XmlParseError`
### Removed
* Dropped a large number of memory layout tests that were auto-generated by bindgen, until we have a more sophisticated test-generation setup that can enforce multiple architectures. Ideally this has no day-to-day impact and just makes portability easier in the short-term.
## [0.2.14] 2020-27-03
### Changed
More consistently use `c_char` to successfully compile on ARM targets
## [0.2.13] 2020-16-01
Thanks to @jangernert for the upgrades to `Document` serialization.
Thanks to @lweberk for contributing the `Schema` featureset and to @cbarber for refining the FFI interop.
### Added
* `Document::to_string_with_options` allowing to customize document serialization
* `Document::SaveOptions` containing the currently supported serialization options, as provided internally by libxml
* `Schema` holding and managing `xmlSchemaPtr` as created while parsing by `SchemaParserContext`
* `SchemaParserContext` holding source of XSD and parsing into a `Schema` while gathering and –in case returning– errors that arise from the XSD parser across the FFI to libxml
* `SchemaValidationContext` holding the `Schema` from resulting `SchemaParserContext` parse and offering validation methods for `Document`, `Node` or file path to XML, while gathering and –in case returning– validation errors from the XML validator across the FFI to libxml
### Changed
* the `Document::to_string()` serialization method is now implemented through `fmt::Display` and no longer takes an optional boolean flag. The default behavior is now unformatted serialization - previously `to_string(false)`, while `to_string(true)` can be realized via
```
.to_string_with_options(SaveOptions { format: true, ..SaveOptions::default()})`
```
## [0.2.12] 2019-16-06
Thanks to @Alexhuszagh for contributing all enhancements for the `0.2.12` release!
### Added
* BOM-aware Unicode support
* New `Parser` methods allowing to specify an explicit encoding: `parse_file_with_encoding`, `parse_string_with_encoding`, `is_well_formed_html_with_encoding`
### Changed
* Default encodings in `Parser` are now left for libxml to guess internally, rather than defaulted to `utf-8`.
## [0.2.11] 2019-15-04
### Added
* `RoNode::to_hashable` and `RoNode::null` for parity with existing `Node`-leveraging applications
## [0.2.10] 2019-14-04
### Added
* `RoNode` primitive for simple and efficient **read-only** parallel processing
* Benchmarking a 120 MB XML document shows a twenty five fold speedup, when comparing `Node` to parallel rayon processing over `RoNode` with a 32 logical core desktop
* While `RoNode` is added as an experiment for high performance read-only scans, any mutability requires using `Node` and incurring a bookkeeping cost of safety at runtime.
* Introduced benchmarking via `criterion`, only installed during development.
* `benches/parsing_benchmarks` contains examples of parallel scanning via `rayon` iterators.
* added `Document::get_root_readonly` method for obtaining a `RoNode` root.
* added `Context::node_evaluate_readonly` method for searching over a `RoNode`
* added `Context::get_readonly_nodes_as_vec` method for collecting xpath results as `RoNode`
## [0.2.9] 2019-28-03
* Squash memory leak in creating new `Node`s from the Rust API
* Safely unlink `Node`s obtained via XPath searches
## [0.2.8] 2019-25-03
### Changed
Minor internal changes to make the crate compile more reliably under MacOS, and other platforms which enable the `LIBXML_THREAD_ENABLED` compile-time flag. Thank you @caldwell !
## [0.2.7] 2019-09-03
### Added
* implement and test `replace_child_node` for element nodes
## [0.2.6] 2018-07-12
* Internal update to Rust 2018 Edition
* fix deallocation bugs with `.import_node()` and `.get_namespaces()`
## [0.2.5] 2018-26-09
### Added
* `Node::null` placeholder that avoids the tricky memory management of `Node::mock` that can lead to memory leaks. Really a poor substitute for the better `Option<Node>` type with a `None` value, which is **recommended** instead.
## [0.2.4] 2018-24-09
### Added
* `Context::from_node` method for convenient XPath context initialization via a Node object. Possible as nodes keep a reference to their owner `Document` object.
### Changed
* Ensured memory safety of cloning xpath `Context` objects
* Switched to using `Weak` references to the owner document, in `Node`, `Context` and `Object`, to prevent memory leaks in mutli-document pipelines.
* Speedup to XPath node retrieval
## [0.2.3] 2018-19-09
### Added
* `Node::findnodes` method for direct XPath search, without first explicitly instantiating a `Context`. Reusing a `Context` remains more efficient.
## [0.2.2] 2018-23-07
* Expose the underlying `libxml2` data structures in the public crate interface, to enable a first [libxslt](https://crates.io/crates/libxslt) crate proof of concept.
## [0.2.1] 2018-23-07
### Added
* `Node::set_node_rc_guard` which allows customizing the reference-count mutability threshold for Nodes.
* serialization tests for `Document`
* (crate internal) full set of libxml2 bindings as produced via `bindgen` (see #39)
* (crate internal) using libxml2's type language in the wrapper Rust modules
* (crate internal) setup bindings for reuse in higher-level crates, such as libxslt
### Changed
* `NodeType::from_c_int` renamed to `NodeType::from_int`, now accepting a `u32` argument
### Removed
* Removed dependence on custom C code; also removed gcc from build dependencies
## [0.2.0] 2018-19-07
This release adds fundamental breaking changes to the API. The API continues to be considered unstable until the `1.0.0` release.
### Added
* `dup` and `dup_from` methods for deeply duplicating a libxml2 document
* `is_unlinked` for quick check if a `Node` has been unlinked from a parent
### Changed
* safe API for `Node`s and `Document`s, with automatic pointer bookkeeping and memory deallocation, by @triptec
* `Node`s are now bookkept by their owning document
* libxml2 low-level memory deallocation is postponed until the `Document` is dropped, with the exception of unlinked nodes, who are deallocated on drop.
* `Document::get_root_element` now has an option type, and returns `None` for an empty Document
* `Node::mock` now takes owner `Document` as argument
* proofed tests with `valgrind` and removed all obvious memory leaks
* All node operations that modify a `Node` now both require a `&mut Node` argument and return a `Result` type.
* Full list of changed signatures in Node: `remove_attribute`, `remove_property`, `set_name`, `set_content`, `set_property`, `set_property_ns`, `set_attribute`, `set_attribute_ns`, `remove_attribute`, `set_namespace`, `recursively_remove_namespaces`, `append_text`
* Tree transforming operations that use operate on `&mut self`, and no longer return a Node if the return value is identical to the argument.
* Changed signatures: `add_child`, `add_prev_sibling`, `add_next_sibling`
* `Result` types should always be checked for errors, as mutability conflicts are reported during runtime.
### Removed
* `global` module, which attempted to manage global libxml state for threaded workflows. May be readed after the API stabilizes
## [0.1.2] 2018-12-01
* We welcome Andreas (@triptec) to the core developer team!
### Added
* Workaround `.free` method for freeing nodes, until the `Rc<RefCell<_Node>>` free-on-drop solution by Andreas is introduced in 0.2
## [0.1.1] 2017-18-12
### Added
* `get_first_element_child` - similar to `get_first_child` but only returns XML Elements
* `is_element_node` - check if a given `Node` is an XML Element
### Changed
* Requiring owned `Node` function arguments only when consumed - `add_*` methods largely take `&Node` now.
## [0.1.0] 2017-09-11
Pushing up release to a 0.1, as contributor interest is starting to pick up, and the 0. version were getting a bit silly/wrong.
### Added
* Node methods: `unbind_node`, `recursively_remove_namespaces`, `set_name`,
* Document methods: `import_node`
### Changed
* Updated gcc build to newer incantation, upped dependency version.
## [0.0.75] 2017-04-06
### Added
* Node methods: `get_namespace_declarations`, `get_property_ns` (alias: `get_attribute_ns`), `remove_property` (alias: `remove_attribute`), `get_attribute_node`, `get_namespace`, `lookup_namespace_prefix`, `lookup_namespace_uri`
* XPath methods: `findvalue` and `findnodes`, with optional node-bound evaluation.
### Changed
* The Node setter for a namespaced attribute is now `set_property_ns` (alias: `set_attribute_ns`)
* Node set_* methods are now consistently defined on `&mut self`
* Refactored wrongly used `url` to `href` for namespace-related Node ops.
* Fixed bug with Node's `get_content` method always returning empty
* More stable `append_text` for node, added tests
## [0.0.74] 2016-25-12
### Changed
* Namespace::new only requires a borrowed &Node now
* Fixed bug with wrongly discarded namespace prefixes on Namespace::new
### Added
* Namespace methods: `get_prefix`, `get_url`
## [0.0.73] 2016-25-12
### Added
* Document method: `as_node`
## [0.0.72] 2016-25-12
### Added
* Node methods: `get_last_child`, `get_child_nodes`, `get_child_elements`, `get_properties`, `get_attributes`
## [0.0.71] 2016-29-11
### Changed
* Namespace::new takes Node argument last
### Added
* Node namespace accessors - `set_namespace`, `get_namespaces`, `set_ns_attribute`, `set_ns_property`
* Namespace registration for XPath
## [0.0.7] 2016-27-11
### Changed
* stricter dependency spec in Cargo.toml
* cargo clippy compliant
* Document's `get_root_element` returns the document pointer as a Node for empty documents, type change from `Option<Node>` to simple `<Node>`
### Added
* Node accessors: `set_attribute`, `get_attribute`, `set_property` (the `attribute` callers are simple aliases for `property`)
* Node `to_hashable` for simple hashing of nodes
* Node `mock` for simple mock nodes in testing
## [0.0.5] 2016-07-01
Thanks to @grray for most of these improvements!
### Changed
* Switched to using the more permissive MIT license, consistent with libxml2 licensing
* Fixed segfault issues with xpath contexts
### Added
* Can now evaluate ```string(/foo//@bar)``` type XPath expressions, and use their result via ```.to_string()```
## [0.0.4] 2016-04-25
### Changed
* The ```Node.add_child``` method now adds a Node, while the old behavior of creating a new node with a given namespace and name is now ```Node.new_child```
### Added
* Can add following siblings via ```Node.add_next_sibling```
* Can now add text nodes via ```Node.new_text```