Skip to content

Commit

Permalink
Correct C implementation issues for sparklemotion#2494.
Browse files Browse the repository at this point in the history
  • Loading branch information
TreyE committed Apr 3, 2022
1 parent 0395906 commit 6ea4995
Showing 1 changed file with 28 additions and 5 deletions.
33 changes: 28 additions & 5 deletions ext/nokogiri/xml_node.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,16 @@ _xml_node_mark(xmlNodePtr node)


static void
relink_namespace(xmlNodePtr reparented)
relink_namespace(xmlNodePtr reparented, int reconcile_namespaces)
{
xmlNodePtr child;
xmlAttrPtr attr;
xmlNsPtr possible_collision_ns;
int ns_collision;

if (reconcile_namespaces) {
xmlReconciliateNs(reparented->doc, reparented);
}

if (reparented->type != XML_ATTRIBUTE_NODE &&
reparented->type != XML_ELEMENT_NODE) { return; }
Expand Down Expand Up @@ -78,6 +84,10 @@ relink_namespace(xmlNodePtr reparented)
xmlSetNs(reparented, reparented->parent->ns);
}

/* Are we missing a definition of our own ns?
This can happen under cut/paste sometimes.
*/

/* Search our parents for an existing definition */
if (reparented->nsDef) {
xmlNsPtr curr = reparented->nsDef;
Expand All @@ -89,9 +99,16 @@ relink_namespace(xmlNodePtr reparented)
reparented->parent,
curr->href
);
/* Track and check for a namespace which might be 'squatting' on a
* the same prefix but a different href. */
ns_collision = 0;
possible_collision_ns = xmlSearchNs(reparented->doc, reparented->parent, curr->prefix);
if (possible_collision_ns && !xmlStrEqual(curr->href, possible_collision_ns->href)) {
ns_collision = 1;
}
/* If we find the namespace is already declared, remove it from this
* definition list. */
if (ns && ns != curr && xmlStrEqual(ns->prefix, curr->prefix)) {
if (ns && ns != curr && !ns_collision && xmlStrEqual(ns->prefix, curr->prefix)) {
if (prev) {
prev->next = curr->next;
} else {
Expand Down Expand Up @@ -132,14 +149,14 @@ relink_namespace(xmlNodePtr reparented)
/* their namespaces are reparented as well. */
child = reparented->children;
while (NULL != child) {
relink_namespace(child);
relink_namespace(child, 0);
child = child->next;
}

if (reparented->type == XML_ELEMENT_NODE) {
attr = reparented->properties;
while (NULL != attr) {
relink_namespace((xmlNodePtr)attr);
relink_namespace((xmlNodePtr)attr, 0);
attr = attr->next;
}
}
Expand Down Expand Up @@ -189,6 +206,7 @@ reparent_node_with(VALUE pivot_obj, VALUE reparentee_obj, pivot_reparentee_func
{
VALUE reparented_obj ;
xmlNodePtr reparentee, original_reparentee, pivot, reparented, next_text, new_next_text, parent ;
int reconcile_ns = 1;
int original_ns_prefix_is_default = 0 ;

if (!rb_obj_is_kind_of(reparentee_obj, cNokogiriXmlNode)) {
Expand All @@ -198,6 +216,11 @@ reparent_node_with(VALUE pivot_obj, VALUE reparentee_obj, pivot_reparentee_func
rb_raise(rb_eArgError, "node must be a Nokogiri::XML::Node");
}

// Don't reconcile children of fragments.
if (rb_obj_is_kind_of(pivot_obj, cNokogiriXmlDocumentFragment)) {
reconcile_ns = 0;
}

Data_Get_Struct(reparentee_obj, xmlNode, reparentee);
Data_Get_Struct(pivot_obj, xmlNode, pivot);

Expand Down Expand Up @@ -379,7 +402,7 @@ reparent_node_with(VALUE pivot_obj, VALUE reparentee_obj, pivot_reparentee_func
/* if we've created a cycle, raise an exception */
raise_if_ancestor_of_self(reparented);

relink_namespace(reparented);
relink_namespace(reparented, reconcile_ns);

return reparented_obj ;
}
Expand Down

0 comments on commit 6ea4995

Please sign in to comment.