Skip to content

Commit

Permalink
fix: DocumentFragment#path checks for error case in libxml 2.9.11+
Browse files Browse the repository at this point in the history
Fixes #2250
  • Loading branch information
flavorjones committed May 26, 2021
1 parent e43f521 commit d0f14d1
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 8 deletions.
24 changes: 16 additions & 8 deletions ext/nokogiri/xml_node.c
Original file line number Diff line number Diff line change
Expand Up @@ -1292,17 +1292,25 @@ get_name(VALUE self)
* Returns the path associated with this Node
*/
static VALUE
path(VALUE self)
noko_xml_node_path(VALUE rb_node)
{
xmlNodePtr node;
xmlChar *path ;
xmlNodePtr c_node;
xmlChar *c_path ;
VALUE rval;

Data_Get_Struct(self, xmlNode, node);
Data_Get_Struct(rb_node, xmlNode, c_node);

c_path = xmlGetNodePath(c_node);
if (c_path == NULL) {
// see https://github.com/sparklemotion/nokogiri/issues/2250
// this behavior is clearly undesirable, but is what libxml <= 2.9.10 returned, and so we
// do this for now to preserve the behavior across libxml2 versions.
rval = NOKOGIRI_STR_NEW2("?");
} else {
rval = NOKOGIRI_STR_NEW2(c_path);
xmlFree(c_path);
}

path = xmlGetNodePath(node);
rval = NOKOGIRI_STR_NEW2(path);
xmlFree(path);
return rval ;
}

Expand Down Expand Up @@ -1779,7 +1787,7 @@ noko_init_xml_node()
rb_define_method(cNokogiriXmlNode, "next_element", next_element, 0);
rb_define_method(cNokogiriXmlNode, "previous_element", previous_element, 0);
rb_define_method(cNokogiriXmlNode, "node_type", node_type, 0);
rb_define_method(cNokogiriXmlNode, "path", path, 0);
rb_define_method(cNokogiriXmlNode, "path", noko_xml_node_path, 0);
rb_define_method(cNokogiriXmlNode, "key?", key_eh, 1);
rb_define_method(cNokogiriXmlNode, "namespaced_key?", namespaced_key_eh, 2);
rb_define_method(cNokogiriXmlNode, "blank?", blank_eh, 0);
Expand Down
12 changes: 12 additions & 0 deletions test/xml/test_document.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1167,6 +1167,18 @@ def initialize(*args)
assert_equal("expected Nokogiri::XML::Node but received Nokogiri::XML::NodeSet", e.message);
end
end

describe "#path" do
it "should return '/'" do
xml = <<~EOF
<root></root>
EOF

doc = Nokogiri::XML::Document.parse(xml)
assert_equal("/", doc.path)
assert_equal(doc, doc.at_xpath(doc.path)) # make sure we can round-trip
end
end
end
end
end
Expand Down
19 changes: 19 additions & 0 deletions test/xml/test_document_fragment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,25 @@ def initialize(*args)
end
end
end

describe "#path" do
it "should return '?'" do
# see https://github.com/sparklemotion/nokogiri/issues/2250
# this behavior is clearly undesirable, but is what libxml <= 2.9.10 returned, and so we
# do this for now to preserve the behavior across libxml2 versions.
xml = <<~EOF
<root1></root1>
<root2></root2>
EOF

frag = Nokogiri::XML::DocumentFragment.parse(xml)
assert_equal "?", frag.path

# # TODO: we should circle back and fix both the `#path` behavior and the `#xpath`
# # behavior so we can round-trip and get the DocumentFragment back again.
# assert_equal(frag, frag.at_xpath(doc.path)) # make sure we can round-trip
end
end
end
end
end
Expand Down

0 comments on commit d0f14d1

Please sign in to comment.