Skip to content

Commit d7b58c3

Browse files
authored
Merge pull request #2252 from sparklemotion/2250-doc-frag-path-v1_11_x
fix(v1.11.x): `DocumentFragment#path` with libxml > 2.9.10
2 parents e43f521 + a1b0e6b commit d7b58c3

File tree

6 files changed

+56
-9
lines changed

6 files changed

+56
-9
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@ Nokogiri follows [Semantic Versioning](https://semver.org/), please see the [REA
44

55
---
66

7+
## 1.11.6 / unreleased
8+
9+
### Fixed
10+
11+
* [CRuby] `DocumentFragment#xpath` checks for error case introduced in libxml > 2.9.10. In v1.11.4 and v1.11.5, calling `DocumentFragment#path` results in a segfault.
12+
13+
714
## 1.11.5 / 2021-05-19
815

916
### Fixed

ROADMAP.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
- [#572](https://github.com/sparklemotion/nokogiri/issues/572)
6060
could we fix this by making DocumentFragment be a subclass of NodeSet?
6161

62+
* potentially related, we should figure out a way that we can round-trip `DocumentFragment#path` through `#xpath` and get the `DocumentFragment back again - [#2250](https://github.com/sparklemotion/nokogiri/issues/2250)
6263

6364
## Better Syntax for custom XPath function handler
6465

ext/nokogiri/xml_node.c

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1292,17 +1292,25 @@ get_name(VALUE self)
12921292
* Returns the path associated with this Node
12931293
*/
12941294
static VALUE
1295-
path(VALUE self)
1295+
noko_xml_node_path(VALUE rb_node)
12961296
{
1297-
xmlNodePtr node;
1298-
xmlChar *path ;
1297+
xmlNodePtr c_node;
1298+
xmlChar *c_path ;
12991299
VALUE rval;
13001300

1301-
Data_Get_Struct(self, xmlNode, node);
1301+
Data_Get_Struct(rb_node, xmlNode, c_node);
1302+
1303+
c_path = xmlGetNodePath(c_node);
1304+
if (c_path == NULL) {
1305+
// see https://github.com/sparklemotion/nokogiri/issues/2250
1306+
// this behavior is clearly undesirable, but is what libxml <= 2.9.10 returned, and so we
1307+
// do this for now to preserve the behavior across libxml2 versions.
1308+
rval = NOKOGIRI_STR_NEW2("?");
1309+
} else {
1310+
rval = NOKOGIRI_STR_NEW2(c_path);
1311+
xmlFree(c_path);
1312+
}
13021313

1303-
path = xmlGetNodePath(node);
1304-
rval = NOKOGIRI_STR_NEW2(path);
1305-
xmlFree(path);
13061314
return rval ;
13071315
}
13081316

@@ -1779,7 +1787,7 @@ noko_init_xml_node()
17791787
rb_define_method(cNokogiriXmlNode, "next_element", next_element, 0);
17801788
rb_define_method(cNokogiriXmlNode, "previous_element", previous_element, 0);
17811789
rb_define_method(cNokogiriXmlNode, "node_type", node_type, 0);
1782-
rb_define_method(cNokogiriXmlNode, "path", path, 0);
1790+
rb_define_method(cNokogiriXmlNode, "path", noko_xml_node_path, 0);
17831791
rb_define_method(cNokogiriXmlNode, "key?", key_eh, 1);
17841792
rb_define_method(cNokogiriXmlNode, "namespaced_key?", namespaced_key_eh, 2);
17851793
rb_define_method(cNokogiriXmlNode, "blank?", blank_eh, 0);

rakelib/markdown.rake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
require "hoe/markdown"
2-
Hoe::Markdown::Standalone.new("nokogiri").define_markdown_tasks("CHANGELOG.md", "CONTRIBUTING.md")
2+
Hoe::Markdown::Standalone.new("nokogiri").define_markdown_tasks("CHANGELOG.md", "CONTRIBUTING.md", "ROADMAP.md")

test/xml/test_document.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1167,6 +1167,18 @@ def initialize(*args)
11671167
assert_equal("expected Nokogiri::XML::Node but received Nokogiri::XML::NodeSet", e.message);
11681168
end
11691169
end
1170+
1171+
describe "#path" do
1172+
it "should return '/'" do
1173+
xml = <<~EOF
1174+
<root></root>
1175+
EOF
1176+
1177+
doc = Nokogiri::XML::Document.parse(xml)
1178+
assert_equal("/", doc.path)
1179+
assert_equal(doc, doc.at_xpath(doc.path)) # make sure we can round-trip
1180+
end
1181+
end
11701182
end
11711183
end
11721184
end

test/xml/test_document_fragment.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,25 @@ def initialize(*args)
363363
end
364364
end
365365
end
366+
367+
describe "#path" do
368+
it "should return '?'" do
369+
# see https://github.com/sparklemotion/nokogiri/issues/2250
370+
# this behavior is clearly undesirable, but is what libxml <= 2.9.10 returned, and so we
371+
# do this for now to preserve the behavior across libxml2 versions.
372+
xml = <<~EOF
373+
<root1></root1>
374+
<root2></root2>
375+
EOF
376+
377+
frag = Nokogiri::XML::DocumentFragment.parse(xml)
378+
assert_equal "?", frag.path
379+
380+
# # TODO: we should circle back and fix both the `#path` behavior and the `#xpath`
381+
# # behavior so we can round-trip and get the DocumentFragment back again.
382+
# assert_equal(frag, frag.at_xpath(doc.path)) # make sure we can round-trip
383+
end
384+
end
366385
end
367386
end
368387
end

0 commit comments

Comments
 (0)