Skip to content

Commit

Permalink
fragment support in Node#replace, Node#add_child, Node#add_previous_s…
Browse files Browse the repository at this point in the history
…ibling and Node#add_next_sibling
  • Loading branch information
flavorjones committed Nov 18, 2009
1 parent abcb2ec commit 1fefd59
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 36 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.rdoc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
* XML::Node#next_element added
* XML::Node#> added for searching a nodes immediate children
* XML::NodeSet#reverse added
* Added fragment support to Node#add_child, Node#add_next_sibling,
Node#add_previous_sibling, and Node#replace.

* Bugfixes

Expand Down
31 changes: 8 additions & 23 deletions ext/nokogiri/xml_node.c
Original file line number Diff line number Diff line change
Expand Up @@ -680,12 +680,7 @@ static VALUE get_content(VALUE self)
return Qnil;
}

/*
* call-seq:
* add_child(node)
*
* Add +node+ as a child of this node. Returns the new child node.
*/
/* :nodoc: */
static VALUE add_child(VALUE self, VALUE child)
{
return reparent_node_with(child, self, xmlAddChild);
Expand Down Expand Up @@ -755,23 +750,13 @@ static VALUE path(VALUE self)
return rval ;
}

/*
* call-seq:
* add_next_sibling(node)
*
* Insert +node+ after this node (as a sibling).
*/
/* :nodoc: */
static VALUE add_next_sibling(VALUE self, VALUE rb_node)
{
return reparent_node_with(rb_node, self, xmlAddNextSibling) ;
}

/*
* call-seq:
* add_previous_sibling(node)
*
* Insert +node+ before this node (as a sibling).
*/
/* :nodoc: */
static VALUE add_previous_sibling(VALUE self, VALUE rb_node)
{
return reparent_node_with(rb_node, self, xmlAddPrevSibling) ;
Expand Down Expand Up @@ -1030,7 +1015,6 @@ void init_xml_node()
rb_define_method(klass, "node_name", get_name, 0);
rb_define_method(klass, "document", document, 0);
rb_define_method(klass, "node_name=", set_name, 1);
rb_define_method(klass, "add_child", add_child, 1);
rb_define_method(klass, "parent", get_parent, 0);
rb_define_method(klass, "child", child, 0);
rb_define_method(klass, "children", children, 0);
Expand All @@ -1049,8 +1033,6 @@ void init_xml_node()
rb_define_method(klass, "attribute_with_ns", attribute_with_ns, 2);
rb_define_method(klass, "namespace", namespace, 0);
rb_define_method(klass, "namespace_definitions", namespace_definitions, 0);
rb_define_method(klass, "add_previous_sibling", add_previous_sibling, 1);
rb_define_method(klass, "add_next_sibling", add_next_sibling, 1);
rb_define_method(klass, "encode_special_chars", encode_special_chars, 1);
rb_define_method(klass, "dup", duplicate_node, -1);
rb_define_method(klass, "unlink", unlink_node, 0);
Expand All @@ -1061,14 +1043,17 @@ void init_xml_node()
rb_define_method(klass, "pointer_id", pointer_id, 0);
rb_define_method(klass, "line", line, 0);

rb_define_private_method(klass, "add_child_node", add_child, 1);
rb_define_private_method(klass, "add_previous_sibling_node", add_previous_sibling, 1);
rb_define_private_method(klass, "add_next_sibling_node", add_next_sibling, 1);
rb_define_private_method(klass, "replace_node", replace, 1);
rb_define_private_method(klass, "dump_html", dump_html, 0);
rb_define_private_method(klass, "native_write_to", native_write_to, 4);
rb_define_private_method(klass, "replace_with_node", replace, 1);
rb_define_private_method(klass, "native_content=", set_content, 1);
rb_define_private_method(klass, "get", get, 1);
rb_define_private_method(klass, "set_namespace", set_namespace, 1);
rb_define_private_method(klass, "compare", compare, 1);

decorate = rb_intern("decorate");
decorate = rb_intern("decorate");
decorate_bang = rb_intern("decorate!");
}
8 changes: 4 additions & 4 deletions lib/nokogiri/ffi/xml/node.rb
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ def next_element
return sibling_ptr.null? ? nil : Node.wrap(sibling_ptr)
end

def replace_with_node(new_node)
def replace_node new_node
Node.reparent_node_with(new_node, self) do |new_node_cstruct, self_cstruct|
retval = LibXML.xmlReplaceNode(self_cstruct, new_node_cstruct)
if retval == self_cstruct.pointer
Expand Down Expand Up @@ -202,7 +202,7 @@ def content
content
end

def add_child(child)
def add_child_node child
Node.reparent_node_with(child, self) do |child_cstruct, my_cstruct|
LibXML.xmlAddChild(my_cstruct, child_cstruct)
end
Expand All @@ -228,13 +228,13 @@ def path
val
end

def add_next_sibling(next_sibling)
def add_next_sibling_node next_sibling
Node.reparent_node_with(next_sibling, self) do |sibling_cstruct, my_cstruct|
LibXML.xmlAddNextSibling(my_cstruct, sibling_cstruct)
end
end

def add_previous_sibling(prev_sibling)
def add_previous_sibling_node prev_sibling
Node.reparent_node_with(prev_sibling, self) do |sibling_cstruct, my_cstruct|
LibXML.xmlAddPrevSibling(my_cstruct, sibling_cstruct)
end
Expand Down
71 changes: 62 additions & 9 deletions lib/nokogiri/xml/node.rb
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,47 @@ def [] name
get(name.to_s)
end

###
# Add +node+ as a child of this Node.
# The new node must be a Nokogiri::XML::Node or a non-empty String.
# Returns the new child node.
def add_child(node)
Node.verify_nodeishness(node)
if node.type == DOCUMENT_FRAG_NODE
node.children.each do |child|
add_child_node child
end
else
add_child_node node
end
end

###
# Insert +node+ before this Node (as a sibling).
def add_previous_sibling(node)
Node.verify_nodeishness(node)
if node.type == DOCUMENT_FRAG_NODE
node.children.each do |child|
add_previous_sibling_node child
end
else
add_previous_sibling_node node
end
end

###
# Insert +node+ after this Node (as a sibling).
def add_next_sibling(node)
Node.verify_nodeishness(node)
if node.type == DOCUMENT_FRAG_NODE
node.children.reverse.each do |child|
add_next_sibling_node child
end
else
add_next_sibling_node node
end
end

alias :next :next_sibling
alias :previous :previous_sibling
alias :remove :unlink
Expand Down Expand Up @@ -483,16 +524,19 @@ def accept visitor
end

####
# +replace+ this Node with the +new_node+ in the Document. The new node
# must be a Nokogiri::XML::Node or a non-empty String
def replace new_node
if new_node.is_a?(Document) || !new_node.is_a?(XML::Node)
raise ArgumentError, <<-EOERR
Node.replace requires a Node argument, and cannot accept a Document.
(You probably want to select a node from the Document with at() or search(), or create a new Node via Node.new().)
EOERR
# +replace+ this Node with the +node+ in the Document.
# The new node must be a Nokogiri::XML::Node or a non-empty String.
# Returns the new child node.
def replace node
Node.verify_nodeishness(node)
if node.type == DOCUMENT_FRAG_NODE
node.children.each do |child|
add_previous_sibling child
end
unlink
else
replace_node node
end
replace_with_node new_node
end

###
Expand Down Expand Up @@ -667,6 +711,15 @@ def <=> other
end

private
def self.verify_nodeishness(node)
if node.is_a?(Document) || !node.is_a?(XML::Node)
raise ArgumentError, <<-EOERR
Node.replace requires a Node argument, and cannot accept a Document.
(You probably want to select a node from the Document with at() or search(), or create a new Node via Node.new().)
EOERR
end
end

def inspect_attributes
[:name, :namespace, :attribute_nodes, :children]
end
Expand Down

0 comments on commit 1fefd59

Please sign in to comment.