Skip to content

Commit

Permalink
Ensure that prefixed attributes are properly namespaced when reparented
Browse files Browse the repository at this point in the history
  • Loading branch information
mbklein committed Mar 20, 2013
1 parent 61101e5 commit 9fd03d8
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 5 deletions.
5 changes: 4 additions & 1 deletion ext/java/nokogiri/XmlNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -1199,17 +1199,20 @@ public IRubyObject set(ThreadContext context, IRubyObject rbkey, IRubyObject rbv
String val = rubyStringToString(rbval);
Element element = (Element) node;

String uri = null;
int colonIndex = key.indexOf(":");
if (colonIndex > 0) {
String prefix = key.substring(0, colonIndex);
String uri = null;
if (prefix.equals("xml")) {
uri = "http://www.w3.org/XML/1998/namespace";
} else if (prefix.equals("xmlns")) {
uri = "http://www.w3.org/2000/xmlns/";
} else {
uri = findNamespaceHref(context, prefix);
}
}

if (uri != null) {
element.setAttributeNS(uri, key, val);
} else {
element.setAttribute(key, val);
Expand Down
17 changes: 13 additions & 4 deletions lib/nokogiri/xml/node.rb
Original file line number Diff line number Diff line change
Expand Up @@ -270,9 +270,9 @@ def []= name, value
def add_child node_or_tags
node_or_tags = coerce(node_or_tags)
if node_or_tags.is_a?(XML::NodeSet)
node_or_tags.each { |n| add_child_node n }
node_or_tags.each { |n| add_child_node_and_reparent_attrs n }
else
add_child_node node_or_tags
add_child_node_and_reparent_attrs node_or_tags
end
node_or_tags
end
Expand Down Expand Up @@ -361,9 +361,9 @@ def children= node_or_tags
node_or_tags = coerce(node_or_tags)
children.unlink
if node_or_tags.is_a?(XML::NodeSet)
node_or_tags.each { |n| add_child_node n }
node_or_tags.each { |n| add_child_node_and_reparent_attrs n }
else
add_child_node node_or_tags
add_child_node_and_reparent_attrs node_or_tags
end
node_or_tags
end
Expand Down Expand Up @@ -938,6 +938,15 @@ def implied_xpath_context
def inspect_attributes
[:name, :namespace, :attribute_nodes, :children]
end

def add_child_node_and_reparent_attrs node
add_child_node node
node.attribute_nodes.find_all { |a| a.name =~ /:/ }.each do |attr_node|
attr_node.remove
node[attr_node.name] = attr_node.value
end
end

end
end
end
9 changes: 9 additions & 0 deletions test/namespaces/test_namespaces_in_builder_doc.rb
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,15 @@ def test_builder_namespace_count
ns_attrs = n.to_xml.scan(/\bxmlns(?::.+?)?=/)
assert_equal 3, ns_attrs.length
end

def test_builder_namespaced_attribute_on_unparented_node
doc = Nokogiri::XML::Builder.new do |x|
x.root('xmlns:foo' => 'http://foo.io') {
x.obj('foo:attr' => 'baz')
}
end.doc
assert_equal 'http://foo.io', doc.root.children.first.attribute_nodes.first.namespace.href
end
end
end
end
7 changes: 7 additions & 0 deletions test/namespaces/test_namespaces_in_created_doc.rb
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,13 @@ def test_created_namespace_count
ns_attrs = n.to_xml.scan(/\bxmlns(?::.+?)?=/)
assert_equal 3, ns_attrs.length
end

def test_created_namespaced_attribute_on_unparented_node
doc = Nokogiri::XML('<root xmlns:foo="http://foo.io"/>')
node = @doc.create_element('obj', 'foo:attr' => 'baz')
doc.root.add_child(node)
assert_equal 'http://foo.io', doc.root.children.first.attribute_nodes.first.namespace.href
end
end
end
end

0 comments on commit 9fd03d8

Please sign in to comment.