Skip to content

Nokogiri Changelog

Nokogiri follows Semantic Versioning, please see the README.md for details.


v1.19.7 / 2026-11-02

Fixed

  • [CRuby] Compile against Ruby 4.1.0-preview1, which defines HAVE_RB_LEN_T but not RB_FIX2LEN. (#3755) @andrewfader

v1.19.6 / 2026-11-02

Fixed

  • [JRuby] Parsing or reparenting an HTML4 element that has an xmlns attribute and a child element no longer raises NullPointerException. This was a regression in v1.19.5. (#3753) @flavorjones

v1.19.5 / 2026-11-01

Security

  • [CRuby] (Low) Fixed a possible use-after-free when an attribute value is replaced via Node#[]= or Node#lang= while Ruby objects still reference the attribute's children. See GHSA-3w22-6jfg-527w for more information.
  • [CRuby] (Low) The HTML5 serializer now escapes text inside noscript unless the document was parsed with parse_noscript_content_as_text: true, preventing a mutation XSS in applications that allow noscript in sanitized HTML. A fragment now parses noscript content the same way as its document, and raises ArgumentError if given a conflicting parse_noscript_content_as_text: value. Comments and raw-text elements inside noscript are still serialized unchanged, as the HTML standard requires, so applications that sanitize HTML and allow noscript should parse with parse_noscript_content_as_text: true or remove noscript elements. See GHSA-4p39-36wj-23h4 for more information.
  • [JRuby] (Low) NONET now blocks external DTDs and entities whose systemId uses a short-form IPv4 host such as 127.1, or is an absolute path in a document parsed from a network URL. Previously Nokogiri fetched them over the network during a parse with DTDLOAD or NOENT, potentially enabling SSRF. See GHSA-v995-44v6-5fqm for more information.

Improved

  • [CRuby] The HTML5 parser now has linear performance when parsing many attributes. Previously performance was quadratic due to two hotspots, one in detecting duplicate attributes and one in constructing the libxml2 data structures. (#3393) @flavorjones
  • [CRuby] Improved XPath argument marshalling performance by using ALLOCV_N instead of rb_gc_register_address. (#3648) @jhawthorn

Fixed

  • Node#namespace= now declares the namespace on the node when no declaration of its prefix is in scope there. Previously, on CRuby, a node given a namespace and then moved under an element that binds the same prefix, or the default namespace, to a different URI was serialized in that other namespace. On JRuby, the namespace was missing from Node#namespace_definitions. (#3459, #3462) @flavorjones
  • XML::Reader is no longer affected by changes made to its source String after the reader is created. Previously, such a change could make the reader parse the changed String on JRuby, or changed or freed memory on CRuby with libxml2 < 2.11. (#3694) @flavorjones
  • Node#namespace = false now raises TypeError. Previously it crashed the process on CRuby and raised ClassCastException on JRuby. (#3719) @flavorjones
  • XML::XPathContext.new and XML::XPathContext#node= raise TypeError when the argument is not a Node. Previously, on CRuby, most such arguments crashed the process. (#3720) @flavorjones
  • CSS an+b selectors with a zero or negative step now follow the Selectors spec: :nth-child(0n+3) matches only the third element (previously nothing), 0n-1 matches nothing instead of raising ZeroDivisionError, and -n+0 / -2n match nothing instead of every (or every other) element. @afurm
  • CSS #id, .class and attribute selectors whose value contains a quote character, such as #it\'s or [a=\'b\'], now match that value. Previously they raised Nokogiri::XML::XPath::SyntaxError or generated an XPath query with a different meaning. An #id selector containing an escaped newline no longer drops the text after it. (#3724, #3727) @flavorjones
  • CSS :contains() arguments, custom pseudo-class string arguments, and element names containing a CSS escape, such as p:contains('it\'s') or a\-b, now match. Previously they raised Nokogiri::XML::XPath::SyntaxError. An element name that is not an XML name after unescaping, such as a\!b, raises Nokogiri::CSS::SyntaxError, except as an unprefixed name in an HTML5 document, where it matches by local name. In ids, classes, attribute values, element names and string arguments, an escape for U+0000, a surrogate, or a code point above U+10FFFF now decodes to U+FFFD, and a vertical tab after a hexadecimal escape is no longer dropped, as CSS Syntax Level 3 requires. (#3728, #3729) @flavorjones
  • CSS attribute names containing a CSS escape, such as [a\-b], now match. Previously they raised Nokogiri::XML::XPath::SyntaxError. An unprefixed attribute name that cannot be written as an XPath name test after unescaping, such as [\[@click](https://github.com/click)] or [\:class], matches an attribute with that exact name in no namespace. The HTML parsers create such attributes. A prefixed one, such as [x|a\!b], raises Nokogiri::CSS::SyntaxError. (#3732, #3735) @flavorjones
  • [CRuby] The HTML5 serializer escapes < and > in attribute values as &lt; and &gt;, following whatwg/html#6362. Previously they were written literally. (#3529, #3741) @flavorjones
  • [CRuby] Reparenting removes a node's declaration of a prefix that the new parent binds to the same URI. (#3462) @flavorjones
  • [CRuby] Builder now correctly builds namespaced nodes that define their own namespace when that ns prefix collides with one defined by the parent (or another ancestor). (#3458, #3461) @flavorjones
  • [CRuby] Reader.outer_xml and .inner_xml properly capture syntax errors. (#3558) @flavorjones
  • [CRuby] XML::SAX::PushParser and HTML4::SAX::PushParser keep parsing correctly after GC compaction relocates their SAX parser. (#3665) @zanker
  • [CRuby] XML::Reader keeps reading correctly when GC compaction runs. Previously, compaction could move the IO or String the reader was created from, and the reader then crashed or parsed the wrong bytes. (#3666, #3668) @zanker
  • [CRuby] XSLT::Stylesheet#transform calls custom XSLT extension functions correctly when GC compaction runs. Previously, after compaction moved a stylesheet that uses an extension module, a later transform raised an exception or crashed. (#3667) @jeremy
  • [CRuby] XSLT::Stylesheet#transform passes the correct params when GC compaction runs while it converts a param with #to_str. Previously, compaction could move the bytes of earlier short params, and the transform raised RuntimeError or silently left a param empty. (#3670) @flavorjones
  • [CRuby] XML::SAX::ParserContext.io and HTML4::SAX::ParserContext.io keep parsing correctly after GC compaction relocates the IO. (#3669) @zanker
  • [CRuby] Document#canonicalize passes the correct inclusive namespace prefixes when it converts a prefix with #to_str, and when GC compaction runs during canonicalization. Previously, libxml2 could read freed or moved memory, and the output lost namespaces or Ruby crashed. Raising on a prefix with a null byte also no longer leaks memory. (#3714, #3750) @Priyank-gouda678 @flavorjones
  • [CRuby] XSLT::Stylesheet#transform calls custom XSLT extension functions correctly when GC compaction runs during the transform. Previously, compaction could move an extension handler instance, and a later call to one of its functions raised an exception or crashed. (#3748) @flavorjones
  • [CRuby] XSLT::Stylesheet#transform calls custom XSLT extension functions correctly after an extension function runs another transform with the same stylesheet, or while another thread does. Previously, the inner or concurrent transform released extension handler instances that the other transform still used, and GC could free them. (#3748) @flavorjones
  • [CRuby] XML::Reader.from_memory accepts an object that responds to to_str. Previously, it could raise Nokogiri::XML::SyntaxError. (#3694) @flavorjones
  • [CRuby] XPathContext#evaluate no longer leaks memory when a custom XPath function handler raises an exception. (#3715, #1610) @flavorjones
  • [CRuby] When a custom XPath function handler raises an exception, XPathContext#evaluate now resets libxml2's error handlers and unregisters the custom function lookup. Previously, libxml2 could keep references to garbage-collected Ruby objects. (#3715) @flavorjones
  • [CRuby MacOS] Fixed an issue handling SIGINT during HTML5 parsing. (#3528, #3535) @stevecheckoway
  • [CRuby] gumbo: gumbo_parse_with_options no longer crashes when stop_on_first_error is set and the parse ends on an unknown end tag in a fragment context. This is a C API path; it is not reachable from Ruby, because Nokogiri never sets stop_on_first_error. (#3672) @jeremy
  • [JRuby] Fixed multiple issues with Node#namespace_definitions so that it now behaves identically to CRuby. (#2543, #3460) @flavorjones
  • [CRuby] HTML5 fragment parsing raises TypeError when the context node or one of its ancestors is an element whose name returns something other than a String. Previously this could crash the process. (#3740) @flavorjones
  • [CRuby] HTML5 parsing no longer leaks memory when a comment follows </body> and a <frameset> start tag follows the comment. (#3744) @flavorjones
  • [CRuby] An XSLT extension function that raises an exception no longer leaks memory or leaves behind a stale libxml2 error handler, which could write into a freed Ruby object. (#3718, #3721) @Priyank-gouda678 @flavorjones
  • [CRuby] When an IO's read raises an exception that is not a StandardError, such as Interrupt or Timeout::ExitException, parsing with XML::Document, HTML4::Document or XML::Reader no longer leaks memory or leaves behind a stale libxml2 error handler. (#3718, #3721) @Priyank-gouda678 @flavorjones
  • [CRuby] Nokogiri compiles on 64-bit Windows with Ruby 4.1, which stores String and Array lengths in the new rb_len_t type. Previously compilation failed with an incompatible pointer type error in xml_node_set.c. (#3711) @larskanis
  • [CRuby] Node#line= now raises NoMethodError on Document, DTD, Attr, ElementDecl, AttributeDecl and EntityDecl, as #line already does on all of them except Attr. Previously it wrote past the end of the node's memory or overwrote an unrelated field, which could crash the process. (#3737, #3738) @Priyank-gouda678 @flavorjones
  • [JRuby] Document#create_element and Node.new no longer set the namespace to the document's default namespace. The namespace must be set explicitly with namespace= or by parenting the node. (#3457, #3463) @flavorjones
  • [JRuby] XPath queries work when Xalan is loaded by a parent of the JRuby class loader and the thread's context class loader is that parent, as in a servlet container with Xalan in WEB-INF/lib. Previously they raised DTMConfigurationException: No default implementation found. Nokogiri also no longer sets the JVM-wide system property org.apache.xml.dtm.DTMManager, which made XSLT transformations and other Xalan users in the same JVM fail in that setup. (#3707) @flavorjones

v1.19.4 / 2026-06-18

Security

  • [CRuby] (Low) Fixed a possible invalid memory read when XML::Node#initialize_copy_with_args is called with an argument that is not a Node. See GHSA-g9g8-vgvw-g3vf for more information.
  • [CRuby] (Low) Fixed a possible use-after-free when an XML::XPathContext is used after its source document has been garbage collected. See GHSA-p67v-3w7g-wjg7 for more information.
  • [CRuby] (Low) Fixed a possible use-after-free during XInclude processing via Node#do_xinclude. See GHSA-wfpw-mmfh-qq69 for more information.
  • [CRuby] (Low) Fixed a possible use-after-free when Document#root= is assigned a non-element node. See GHSA-wjv4-x9w8-wm3h for more information.
  • [CRuby] (Low) Fixed a possible use-after-free when setting an attribute value via XML::Attr#value= or #content=. See GHSA-phwj-rprq-35pp for more information.
  • [CRuby] (Low) Fixed a null pointer dereference when methods are called on uninitialized wrapper objects (e.g. via allocate); these now raise instead of crashing the process. See GHSA-9cv2-cfxc-v4v2 for more information.
  • [CRuby] (Low) Fixed a possible use-after-free when Document#encoding= raises an exception. See GHSA-5v8h-3h3q-446p for more information.
  • [CRuby] (Medium) Fixed an out-of-bounds read in XML::NodeSet#[] (alias #slice) when given a large negative index. See GHSA-5prr-v3j2-97mh for more information.
  • [JRuby] (Low) XML::Schema now enforces the NONET parse option, which Nokogiri enables by default. It was not enforced on JRuby, so a schema parsed with default options could still fetch external resources over the network, potentially enabling SSRF or XXE attacks and bypassing the mitigation for CVE-2020-26247. See GHSA-8678-w3jw-xfc2 for more information.

v1.19.3 / 2026-04-27

Fixed / Security

  • Address exponential regex backtracking in CSS selector tokenizer. See GHSA-c4rq-3m3g-8wgx for more information.
  • [CRuby] Address memory leak in XSLT::Stylesheet#transform. See GHSA-v2fc-qm4h-8hqv for more information.

v1.19.2 / 2026-03-19

Dependencies

  • [JRuby] Saxon-HE is updated to 12.7, from 9.6.0-4. Saxon-HE is a transitive dependency of nu.validator:jing, and this update addresses CVEs in Saxon-HE's own transitive dependencies JDOM and dom4j. We don't think this warrants a security release, however we're cutting a patch release to help users whose security scanners are flagging this. [#3611] @flavorjones

v1.19.1 / 2026-02-16

Security

  • [CRuby] Address unchecked return value from xmlC14NExecute which was a contributing cause to ruby-saml GHSA-x4h9-gwv3-r4m4. See GHSA-wx95-c6cv-8532 for more information.

v1.19.0 / 2025-12-28

Ruby

This release is focused on changes to Ruby version support, and is otherwise functionally identical to v1.18.10.

v1.18.10 / 2025-09-15

Dependencies

  • [CRuby] Vendored libxml2 is updated to v2.13.9. Note that the security fixes published in v2.13.9 were already present in Nokogiri v1.18.9.
  • [CRuby] [Windows and MacOS] Vendored libiconv is updated to v1.18

v1.18.9 / 2025-07-20

Security

  • [CRuby] Applied upstream libxml2 patches to address CVE-2025-6021, CVE-2025-6170, CVE-2025-49794, CVE-2025-49795, and CVE-2025-49796. See GHSA-353f-x4gh-cqq8 for more information.

v1.18.8 / 2025-04-21

Security

  • [CRuby] Vendored libxml2 is updated to v2.13.8 to address CVE-2025-32414 and CVE-2025-32415. See GHSA-5w6v-399v-w3cc for more information.

v1.18.7 / 2025-03-31

Dependencies

  • [CRuby] Vendored libxml2 is updated to v2.13.7, which is a bugfix release.

v1.18.6 / 2025-03-24

Fixed

  • [JRuby] In HTML documents, Node#attribute now returns the correct attribute. This has been broken, and returnin nil, since v1.17.0. (#3487) @flavorjones

v1.18.5 / 2025-03-19

Fixed

v1.18.4 / 2025-03-14

Security

  • [CRuby] Vendored libxslt is updated to v1.1.43 to address CVE-2025-24855 and CVE-2024-55549. See GHSA-mrxw-mxhj-p664 for more information.

v1.18.3 / 2025-02-18

Security

  • [CRuby] Vendored libxml2 is updated to v2.13.6 to address CVE-2025-24928 and CVE-2024-56171. See GHSA-vvfq-8hwr-qm4m for more information.

v1.18.2 / 2024-01-19

Fixed

  • When performing a CSS selector query, an XML document's root namespace declarations should not be applied to wildcard selectors ("*"). Fixes a bug introduced in v1.17.0. (#3411) @flavorjones

v1.18.1 / 2024-12-29

Fixed

  • [CRuby] XML::SAX::ParserContext keeps a reference to the input to avoid a potential use-after-free issue that's existed since v1.4.0 (2009). (#3395) @flavorjones

v1.18.0 / 2024-12-25

Notable Changes

Ruby

This release introduces native gem support for Ruby 3.4.

This release ends support for Ruby 3.0, for which upstream support ended 2024-04-23.

This release ships separate precompiled GNU and Musl gems for all linux platforms. Previously both GNU and Musl target systems could use and install the same gem, e.g., the platform gem for x86_64-linux. Now, however, the precompiled gem platforms would be x86_64-linux-gnu and x86_64-linux-musl. So long as you're on bundler >= 2.5.6 this should be seamless other than perhaps needing to update the platforms in your "Gemfile.lock".

This release drops precompiled native platform gems for x86-linux and x86-mingw32. These platforms are still supported. Users on these platforms must install the "ruby platform" gem which requires a compiler toolchain. See Installing the ruby platform gem in the installation docs. (#3369, #3081)

Improved

  • [CRuby] CSS and XPath queries are faster now that Node#xpath, Node#css, and related functions are using a faster XPathContext initialization process. We benchmarked a 1.9x improvement for a 6kb file. Big thanks to @nwellnhof for helping with this one. (#3378, superseded by #3389) @flavorjones

v1.17.2 / 2024-12-12

Fixed

  • [JRuby] Fixed an issue where Node#dup when called with the new_parent_doc parameter was not decorating the node with the document's Node decorators. [#3372] @flavorjones

v1.17.1 / 2024-12-10

Fixed

  • Fixed a potential segfault when using Node#dup and DocumentFragment#dup. [#3359] @byroot @flavorjones
  • Node#dup and Node#clone now correctly decorate the new node with the document's Node decorators. [#3363] @flavorjones

v1.17.0 / 2024-12-08

Dependencies

Notable changes

SAX Parsers

The XML and HTML4 SAX parsers have received a lot of attention in this release, and we've fixed multiple long-standing bugs with encoding and entity handling. In addition, libxml2 v2.13 has also made some underlying fixes and improvements to encoding and entity handling.

We're shipping these fixes in a minor release because we firmly believe the resulting behavior is correct and standards-compliant, however applications that have been depending on the buggy behavior may be impacted.

If your application relies on the SAX parsers, and in particular if you're SAX-parsing documents with parsed entities or incorrect encoding declarations, please read the changelog below carefully.

Fragment parsing

Document fragment parsing has been improved, particularly with respect to handling malformed fragments or fragments with implicit namespace prefixes. Namespace reconciliation still isn't where we want it to be, but it's an improvement.

HTML5 fragment parsing now allows the context node to be specified as a context: keyword argument to the HTML5::DocumentFragment.parse and .new methods, which should allow for more flexible sanitization and future support for the draft HTML Sanitizer API in downstream libraries.

Error handling

In scenarios where multiple errors could be reported by the underlying parser, the errors will be aggregated into a single Nokogiri::XML::SyntaxError that is raised. Previously only the final error reported by libxml2 was raised (which was often misleading if it was only a warning and not the fatal error).

Schema validation

We've resolved many long-standing bugs in the various schema classes, validation methods, and their error reporting. Behavior is now consistent across schema types and input types, as well as parser backends (Xerces and libxml2).

Keyword arguments

The following methods now accept keyword arguments in addition to positional arguments, and use ... parameter forwarding when possible: HTML4(), HTML4.fragment, HTML4.parse, HTML4::Document.parse, HTML4::DocumentFragment#initialize, HTML4::DocumentFragment.parse, HTML5(), HTML5.fragment, HTML5.parse, HTML5::Document.parse, HTML5::Document.read_io, HTML5::Document.read_memory, HTML5::DocumentFragment#initialize, HTML5::DocumentFragment.parse, XML(), XML.fragment, XML.parse, XML::Document.parse, XML::DocumentFragment#initialize, XML::DocumentFragment.parse, XML::Node#canonicalize, XML::Node.parse, XML::Reader(), XML::RelaxNG(), XML::RelaxNG.new, XML::RelaxNG.read_memory, XML::SAX::PushParser#initialize, XML::Schema(), XML::Schema.new, XML::Schema.read_memory, and XSLT().

Special thanks to those contributors who participated in the RubyConf 2024 Hack Day to work on #3323 to help modernize Nokogiri by adding keyword arguments and using parameter forwarding in many methods, and expanding some of the documentation! We intend to continue adding keyword argument support to more methods. #3323 #3324 #3326 #3327 #3329 #3330 #3332 #3333 #3334 #3335 #3336 #3342 #3355 #3356 @infews @matiasow @MattJones @mononoken @openbl @flavorjones

Added

  • Introduce support for a new SAX callback XML::SAX::Document#reference, which is called to report some parsed XML entities when XML::SAX::ParserContext#replace_entities is set to the default value false. This is necessary functionality for some applications that were previously relying on incorrect entity error reporting which has been fixed (see below). For more information, read the docs for Nokogiri::XML::SAX::Document. [#1926] @flavorjones
  • XML::SAX::Parser#parse_memory and #parse_file now accept an optional encoding argument. When not provided, the parser will fall back to the encoding passed to the initializer, and then fall back to autodetection. [#3288] @flavorjones
  • XML::SAX::ParserContext.memory now accepts an optional encoding argument. When not provided, the encoding will be autodetected. [#3288] @flavorjones
  • New readonly attributes XML::DocumentFragment#parse_options and HTML4::DocumentFragment#parse_options return the options used to parse the document fragment. @flavorjones
  • New method XML::Reader.new is the primary constructor to which XML::Reader() forwards. Both methods now take url:, encoding:, and options: kwargs in addition to the previous calling convention of passing positional parameters. #3326 @infews @flavorjones
  • [CRuby] The HTML5 parse methods accept a :parse_noscript_content_as_text keyword argument which will emulate the parsing behavior of a browser which has scripting enabled. [#3178, #3231] @stevecheckoway
  • [CRuby] HTML5::DocumentFragment.parse and .new accept a :context keyword argument that is the parse context node or element name. Previously this could only be passed in as a positional argument to .new and not at all to .parse. @flavorjones
  • [CRuby] Nokogiri::HTML5::Builder is similar to HTML4::Builder but returns an HTML5::Document. [#3119] @flavorjones
  • [CRuby] Attributes in an HTML5 document can be serialized individually, something that has always been supported by the HTML4 serializer. [#3125, #3127] @flavorjones
  • [CRuby] Introduce a compile-time option, --disable-xml2-legacy, to remove from libxml2 its dependencies on zlib and liblzma and disable implicit HTTP network requests. These all remain enabled by default, and are present in the precompiled native gems. This option is a precursor for removing these libraries in a future major release, but may be interesting for the security-minded who do not need features like automatic decompression and would like to remove these dependencies. You can read more and give feedback on these plans in #3168. [#3247] @flavorjones
  • [CRuby] If errors are returned from schema validation, a new attribute SyntaxError#path will contain the XPath path of the node that caused the validation failure. [#3316] @ryanong

Improved

  • Documentation has been improved for XML::RelaxNG, XML::Schema, XML::Reader, HTML5, HTML5::Document, HTML5::DocumentFragment, HTML4::Document, HTML4::DocumentFragment, XML, XML::Document, XML::DocumentFragment. #3355 @flavorjones
  • Documentation has been improved for CSS.xpath_for. [#3224] @flavorjones
  • Documentation for the SAX parsing classes has been greatly improved, including encoding overrides and the complex entity-handling behavior. [#3265] @flavorjones
  • XML::Schema#read_memory and XML::RelaxNG#read_memory are now Ruby methods that call #from_document. Previously these were native functions, but they were buggy on both CRuby and JRuby (but worse on JRuby) and so this is now useful, comparable in performance, and simpler code that is easier to maintain. [#2113, #2115] @flavorjones
  • XML::SAX::ParserContext.io's encoding argument is now optional, and can now be an Encoding or an encoding name. When not provided will default to autodetecting the encoding. [#3288] @flavorjones
  • [CRuby] The update to libxml v2.13 improves "in context" fragment parsing recovery. We removed our hacky workaround for recovery that led to silently-degraded functionality when parsing fragments with parse errors. Specifically, malformed XML fragments that used implicit namespace prefixes will now "link up" to the namespaces in the parent document or node, where previously they did not. [#2092] @flavorjones
  • [CRuby] When multiple errors could be detected by the parser and there's no obvious document to save them in (for example, when parsing a document with the recovery parse option turned off), the libxml2 errors are aggregated into a single Nokogiri::XML::SyntaxError. Previously, only the last error recorded by libxml2 was raised, which might be misleading if it's merely a warning and not the fatal error preventing the operation. [#2562] @flavorjones
  • [CRuby] The SAX parser context and handler implementation has been simplified and now takes advantage of some of libxml2's default SAX handlers for entities and DTD management. [#3265] @flavorjones
  • [CRuby] When compiling packaged libraries from source, allow users' AR and LD environment variables to set the archiver and linker commands, respectively. This augments the existing CC environment variable to set the compiler command. [#3165] @ziggythehamster
  • [CRuby] When building from source on MacOS, environment variables AR and RANLIB are now respected when set instead of being overridden to /usr/bin/{ar,ranlib} (which is still the default). [#3338] @joshheinrichs-shopify

Fixed

  • Node#clone, NodeSet#clone, and *::Document#clone all properly copy the metaclass of the original as expected. Previously, #clone had been aliased to #dup for these classes (since v1.3.0 in 2009). [#316, #3117] @flavorjones
  • CSS queries for pseudo-selectors that cannot be translated into XPath expressions now raise a more descriptive Nokogiri::CSS::SyntaxError when they are parsed. Previously, an invalid XPath expression was evaluated and a hard-to-understand XPath error was raised by the query engine. [#3193] @flavorjones
  • Schema#validate returns errors on empty and malformed files. Previously, it would return errors on empty/malformed Documents, but not when reading from files. [#642] @flavorjones
  • XML::Builder is now consistent with how it sets block scope. Previously, missing methods with blocks on dynamically-created nodes were always handled by invoking instance_eval(&block) on the Builder, even when the Builder was yielding self for all other missing methods with blocks. [#1041] @flavorjones
  • HTML4::DocumentFragment.parse accepts IO input. Previously, it required a string and would raise a TypeError when passed an IO. [#2069] @sharvy
  • [CRuby] libgumbo (the HTML5 parser) treats reaching max-depth as EOF. This addresses a class of issues when the parser is interrupted in this way. [#3121] @stevecheckoway
  • [CRuby] Update node GC lifecycle to avoid a potential memory leak with fragments in libxml 2.13.0 caused by changes in xmlAddChild. [#3156] @flavorjones
  • [CRuby] libgumbo correctly prints nonstandard element names in error messages. [#3219] @stevecheckoway
  • [CRuby] External entity references no long cause the SAX parser to register errors. [#1926] @flavorjones
  • [JRuby] Fixed entity reference serialization, which rendered both the reference and the replacement text. Incredibly nobody noticed this bug for over a decade. [#3272] @flavorjones
  • [JRuby] Fixed some bugs in how Node#attributes handles attributes with namespaces. [#2677, #2679] @flavorjones
  • [JRuby] Fix Schema#validate to only return the most recent Document's errors. Previously, if multiple documents were validated, this method returned the accumulated errors of all previous documents. [#1282] @flavorjones
  • [JRuby] Fix Schema#validate to not clobber the [@errors](https://github.com/errors) instance variable. [#1282] @flavorjones
  • [JRuby] Empty documents fail schema validation as they should. [#783] @flavorjones
  • [JRuby] SAX parsing now respects the #replace_entities attribute, which defaults to false. Previously this flag defaulted to true and was completely ignored. [#614] @flavorjones
  • [JRuby] The SAX callback Document#start_element_namespace received a blank string for the URI when a namespace was not present. It now receives nil (as does the CRuby impl). [#3265] @flavorjones
  • [JRuby] Reader#outer_xml and #inner_xml encode entities properly. [#1523] @flavorjones

Changed

  • [CRuby] Nokogiri::XML::CData.new no longer accepts nil as the content argument, making CData behave like other character data classes (like Comment and Text). This change was necessitated by behavioral changes in libxml2 v2.13.0. If you wish to create an empty CDATA node, pass an empty string. [#3156] @flavorjones
  • Internals:
    • The internal CSS::XPathVisitor class now accepts the xpath prefix and the context namespaces as constructor arguments. The prefix: and ns: keyword arguments to CSS.xpath_for cannot be specified if the visitor: keyword argument is also used. CSS::XPathVisitor now exposes #builtins, #doctype, #prefix, and #namespaces attributes. [#3225] @flavorjones
    • The internal CSS selector cache has been extracted into a distinct class, CSS::SelectorCache. Previously it was part of the CSS::Parser class. [#3226] @flavorjones
    • The internal Gumbo.parse and Gumbo.fragment methods now take keyword arguments instead of positional arguments. [#3199] @flavorjones

Deprecated

  • The undocumented and unused method Nokogiri::CSS.parse is now deprecated and will generate a warning. The AST returned by this method is private and subject to change and removal in future versions of Nokogiri. This method will be removed in a future version of Nokogiri.
  • Passing an options hash to CSS.xpath_for is now deprecated and will generate a warning. Use keyword arguments instead. This will become an error in a future version of Nokogiri.
  • Passing libxml2 encoding IDs to SAX::ParserContext methods is now deprecated and will generate a warning. The use of SAX::Parser::ENCODINGS is also deprecated. Use Encoding objects or encoding names instead.

Thank you!

The following people and organizations were kind enough to sponsor @flavorjones or the Nokogiri project during the development of v1.17.0:

We'd also like to thank @github who donate a ton of compute time for our CI pipelines!

v1.16.8 / 2024-12-02

Fixed

  • [CRuby] When serializing HTML5 documents, properly escape foreign content "style" elements. Normally, a "style" tag contains raw text that does not need entity-escaping, but when it appears in either SVG or MathML foreign content, the "style" tag is now correctly escaped when serialized. @flavorjones

v1.16.7 / 2024-07-27

Dependencies

  • [CRuby] Vendored libxml2 is updated to v2.12.9, which the upstream release notes state is a security release to address CVE-2024-40896. Nokogiri's maintainers believe this vulnerability does not affect users of Nokogiri, but we advise upgrading at your earliest convenience anyway.

v1.16.6 / 2024-06-13

Dependencies

  • [CRuby] Vendored libxml2 is updated to v2.12.8, which the release notes state is a bugfix release.

v1.16.5

Security

  • [CRuby] Vendored libxml2 is updated to address CVE-2024-34459. See GHSA-r95h-9x8f-r3f7 for more information.

Dependencies

v1.16.4 / 2024-04-10

Dependencies

  • [CRuby] Vendored zlib in the precompiled native gems is updated to v1.3.1 from v1.3. Nokogiri is not affected by the minizip CVE patched in this version, but this update may satisfy some security scanners. Related, see this discussion about removing the compression libraries altogether in a future version of Nokogiri.

v1.16.3 / 2024-03-15

Dependencies

Changed

  • [CRuby] XML::Reader sets the [@encoding](https://github.com/encoding) instance variable during reading if it is not passed into the initializer. Previously, it would remain nil. The behavior of Reader#encoding has not changed. This works around changes to how libxml2 reports the encoding used in v2.12.6.

v1.16.2 / 2024-02-04

Security

  • [CRuby] Vendored libxml2 is updated to address CVE-2024-25062. See GHSA-xc9x-jj77-9p9j for more information.

Dependencies

v1.16.1 / 2024-02-03

Dependencies

Fixed

  • [CRuby] XML::Reader defaults the encoding to UTF-8 if it's not specified in either the document or as a method parameter. Previously non-ASCII characters were serialized as NCRs in this case. [#2891] (@flavorjones)
  • [CRuby] Restored support for compilation by GCC versions earlier than 4.6, which was broken in v1.15.0 (540e9aee). [#3090] (@adfoster-r7)
  • [CRuby] Patched upstream libxml2 to allow parsing HTML5 in the context of a namespaced node (e.g., foreign content like MathML). [#3112, #3116] (@flavorjones)
  • [CRuby] Fixed a small memory leak in libgumbo (HTML5 parser) when the maximum tree depth limit is hit. [#3098, #3100] (@stevecheckoway)

v1.16.0 / 2023-12-27

Notable Changes

Ruby

This release introduces native gem support for Ruby 3.3.

This release ends support for Ruby 2.7, for which upstream support ended 2023-03-31.

Pattern matching

This version marks official support for the pattern matching API in XML::Attr, XML::Document, XML::DocumentFragment, XML::Namespace, XML::Node, and XML::NodeSet (and their subclasses), originally introduced as an experimental feature in v1.14.0. (@flavorjones)

Documentation on what can be matched:

Dependencies

Fixed

  • CSS nth pseudo-classes now handle spaces, e.g. "2n + 1". [#3018] (@fusion2004)
  • [CRuby] libgumbo no longer leaks memory when an incomplete tag is abandoned by the HTML5 parser. [#3036] (@flavorjones)

Removed

  • Removed Nokogiri::HTML5.get which was deprecated in v1.12.0. [#2278] (@flavorjones)
  • Removed the CSS-to-XPath utility modules XPathVisitorAlwaysUseBuiltins and XPathVisitorOptimallyUseBuiltins, which were deprecated in v1.13.0 in favor of XPathVisitor constructor args. [#2403] (@flavorjones)
  • Removed XML::Reader#attribute_nodes which was deprecated in v1.13.8 in favor of #attribute_hash. [#2598, #2599] (@flavorjones)
  • [CRuby] Removed the libxml/libxml2_path key from VersionInfo, used in the past for third-party library integration, in favor of the nokogiri/cppflags and nokogiri/ldflags keys. Please note that third-party library integration is not fully supported and may be deprecated soon, see #2746 for more context. [#2143] (@flavorjones)

Thank you!

The following people and organizations were kind enough to sponsor @flavorjones or the Nokogiri project during the development of v1.16.0:

We'd also like to thank @github who donate a ton of compute time for our CI pipelines!

Older releases

See misc/CHANGELOG-archive.md