From 24fc53326c9782a3a66cca49bd555c4a9e053dae Mon Sep 17 00:00:00 2001
From: Lucas Hills <2potatocakes@gmail.com>
Date: Thu, 27 Feb 2014 22:55:08 +1100
Subject: [PATCH] Fix attribute nodes namespace when using XML::Reader
Fixes assertion failure. xml reader is choking while trying to access
namespace information tied to the attribute nodes. The assertion was:
Assertion failed: (doc->_private), function Nokogiri_wrap_xml_namespace,
file xml_namespace.c, line 41
---
ext/nokogiri/xml_namespace.c | 16 ++++++++++------
test/test_reader.rb | 19 +++++++++++++++++++
2 files changed, 29 insertions(+), 6 deletions(-)
diff --git a/ext/nokogiri/xml_namespace.c b/ext/nokogiri/xml_namespace.c
index 44bb25657f..4aa5ec784d 100644
--- a/ext/nokogiri/xml_namespace.c
+++ b/ext/nokogiri/xml_namespace.c
@@ -37,20 +37,24 @@ static VALUE href(VALUE self)
VALUE Nokogiri_wrap_xml_namespace(xmlDocPtr doc, xmlNsPtr node)
{
VALUE ns, document, node_cache;
+ nokogiriTuplePtr node_has_a_document;
- assert(doc->_private);
+ if (doc->type == XML_DOCUMENT_FRAG_NODE) doc = doc->doc;
+ node_has_a_document = DOC_RUBY_OBJECT_TEST(doc);
- if(node->_private)
+ if(node->_private && node_has_a_document)
return (VALUE)node->_private;
ns = Data_Wrap_Struct(cNokogiriXmlNamespace, 0, 0, node);
- document = DOC_RUBY_OBJECT(doc);
+ if (doc->_private) {
+ document = DOC_RUBY_OBJECT(doc);
- node_cache = rb_iv_get(document, "@node_cache");
- rb_ary_push(node_cache, ns);
+ node_cache = rb_iv_get(document, "@node_cache");
+ rb_ary_push(node_cache, ns);
- rb_iv_set(ns, "@document", DOC_RUBY_OBJECT(doc));
+ rb_iv_set(ns, "@document", DOC_RUBY_OBJECT(doc));
+ }
node->_private = (void *)ns;
diff --git a/test/test_reader.rb b/test/test_reader.rb
index c1a96c3ae4..e43cbb1ebf 100644
--- a/test/test_reader.rb
+++ b/test/test_reader.rb
@@ -386,6 +386,25 @@ def test_ns_uri
reader.map { |n| n.namespace_uri })
end
+ def test_namespaced_attributes
+ reader = Nokogiri::XML::Reader.from_memory(<<-eoxml)
+
+ hello
+
+
+ eoxml
+ attr_ns = []
+ while reader.read
+ if reader.node_type == Nokogiri::XML::Node::ELEMENT_NODE
+ reader.attribute_nodes.each {|attr| attr_ns << (attr.namespace.nil? ? nil : attr.namespace.prefix) }
+ end
+ end
+ assert_equal(['commons',
+ 'edi',
+ nil],
+ attr_ns)
+ end
+
def test_local_name
reader = Nokogiri::XML::Reader.from_memory(<<-eoxml)