[gxml] * fixed NodeList for addition of DocumentFragment * successfully test get_elements_by_tag_name's liv
- From: Richard Hans Schwarting <rschwart src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gxml] * fixed NodeList for addition of DocumentFragment * successfully test get_elements_by_tag_name's liv
- Date: Fri, 29 Jul 2011 02:13:32 +0000 (UTC)
commit e9a5532a544c592831c4f7e83ae54f9e60de9098
Author: Richard Schwarting <aquarichy gmail com>
Date: Thu Jul 28 22:11:54 2011 -0400
* fixed NodeList for addition of DocumentFragment
* successfully test get_elements_by_tag_name's live nature
gxml/Element.vala | 16 ++++++-
gxml/NodeList.vala | 43 +++++++++++++------
test/ElementTest.vala | 109 +++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 152 insertions(+), 16 deletions(-)
---
diff --git a/gxml/Element.vala b/gxml/Element.vala
index 3157124..38fd7c8 100644
--- a/gxml/Element.vala
+++ b/gxml/Element.vala
@@ -207,6 +207,11 @@ namespace GXml.Dom {
}
}
}
+ /**
+ * Checks whether a descendant of a node is an Element, or whether its descendants
+ * are elements. If they are, we check the basenode and its ancestors to see
+ * whether they're keeping that node in a TagNameNodeList, so we can remove it.
+ */
private void check_remove_tag_name (Element basenode, XNode child) {
// TODO: make sure there aren't any other NodeTypes that could have elements as children
if (child.node_type == NodeType.ELEMENT) {
@@ -220,21 +225,21 @@ namespace GXml.Dom {
}
}
- /*** XNode methods ***/
+ /* ** XNode methods ** */
public override XNode? insert_before (XNode new_child, XNode? ref_child) throws DomError {
XNode ret = base.insert_before (new_child, ref_child);
check_add_tag_name (this, new_child);
return ret;
}
public override XNode? replace_child (XNode new_child, XNode old_child) throws DomError {
+ check_remove_tag_name (this, old_child);
XNode ret = base.replace_child (new_child, old_child);
- check_remove_tag_name (this, old_child); // removal should probably precede addition, in case we're moving something around
check_add_tag_name (this, new_child);
return ret;
}
public override XNode? remove_child (XNode old_child) throws DomError {
- XNode ret = base.remove_child (old_child);
check_remove_tag_name (this, old_child);
+ XNode ret = base.remove_child (old_child);
return ret;
}
public override XNode? append_child (XNode new_child) throws DomError {
@@ -284,6 +289,11 @@ namespace GXml.Dom {
if (this.parent_node != null && this.parent_node.node_type == NodeType.ELEMENT)
((Element)this.parent_node).on_new_descendant_with_tag_name (elem);
}
+ /**
+ * Checks whether this element has a TagNameNodeList containing this element,
+ * and if so, removes it. It also asks the parents above if they have such
+ * a list.
+ */
private void on_remove_descendant_with_tag_name (Element elem) {
foreach (TagNameNodeList list in tag_name_lists) {
if (elem.tag_name == list.tag_name) {
diff --git a/gxml/NodeList.vala b/gxml/NodeList.vala
index 84bd2bf..85dd3e4 100644
--- a/gxml/NodeList.vala
+++ b/gxml/NodeList.vala
@@ -508,7 +508,6 @@ namespace GXml.Dom {
this.append_child (ref_child);
}
-
while (child != ((BackedNode)ref_child).node && child != null) {
child = child->next;
}
@@ -516,7 +515,13 @@ namespace GXml.Dom {
throw new DomError.NOT_FOUND ("ref_child not found.");
// TODO: provide a more useful description of ref_child, but there are so many different types
} else {
- child->add_prev_sibling (((BackedNode)new_child).node);
+ if (new_child.node_type == NodeType.DOCUMENT_FRAGMENT) {
+ foreach (XNode new_grand_child in new_child.child_nodes) {
+ child->add_prev_sibling (((BackedNode)new_grand_child).node);
+ }
+ } else {
+ child->add_prev_sibling (((BackedNode)new_child).node);
+ }
}
return new_child;
}
@@ -530,19 +535,25 @@ namespace GXml.Dom {
// TODO: need to handle errors?
// TODO: want to do a 'find_child' function
- Xml.Node *child = head;
+ if (new_child.node_type == NodeType.DOCUMENT_FRAGMENT) {
+ this.insert_before (new_child, old_child);
+ this.remove_child (old_child);
+ } else {
+ Xml.Node *child = head;
- while (child != null && child != ((BackedNode)old_child).node) {
- child = child->next;
- }
+ while (child != null && child != ((BackedNode)old_child).node) {
+ child = child->next;
+ }
- if (child != null) {
- // it is a valid child
- child->replace (((BackedNode)new_child).node);
- } else {
- throw new DomError.NOT_FOUND ("old_child not found");
- // TODO: provide more useful descr. of old_child
+ if (child != null) {
+ // it is a valid child
+ child->replace (((BackedNode)new_child).node);
+ } else {
+ throw new DomError.NOT_FOUND ("old_child not found");
+ // TODO: provide more useful descr. of old_child
+ }
}
+
return old_child;
}
internal new XNode? remove_child (XNode old_child) /* throws DomError */ {
@@ -557,7 +568,13 @@ namespace GXml.Dom {
// new_child if it already exists elsewhere in
// the tree.
- parent_as_xmlnode->add_child (((BackedNode)new_child).node);
+ if (new_child.node_type == NodeType.DOCUMENT_FRAGMENT) {
+ foreach (XNode grand_child in new_child.child_nodes) {
+ parent_as_xmlnode->add_child (((BackedNode)grand_child).node);
+ }
+ } else {
+ parent_as_xmlnode->add_child (((BackedNode)new_child).node);
+ }
return new_child;
}
diff --git a/test/ElementTest.vala b/test/ElementTest.vala
index 33cccdb..66361fc 100644
--- a/test/ElementTest.vala
+++ b/test/ElementTest.vala
@@ -171,6 +171,115 @@ class ElementTest : GXmlTest {
assert (false);
}
});
+ Test.add_func ("/gxml/element/get_elements_by_tag_name.live", () => {
+ /* Need to test the following cases:
+
+ you have an element, it has 3 title descendants.
+ get the node list, has 3 nodes
+ add a title to the element, node list has 4 nodes
+ add a title to a grand child, node list has 5 nodes
+ add another element tree with 2 titles at various depths, list has 7
+ add a document fragment with 2 titles at various depths, list has 9
+
+ remove a single child element, list has 8
+ remove a deeper descendent, list has 7
+ remove a tree with 2, list has 5
+ readd the tree, list has 7
+ */
+ try {
+ Document doc;
+ string xml;
+
+ xml =
+"<A>
+ <t />
+ <Bs>
+ <t />
+ <B>
+ <t />
+ <D><t /></D>
+ <D><t /></D>
+ </B>
+ <B><t /></B>
+ <B></B>
+ </Bs>
+ <Cs><C><t /></C></Cs>
+</A>";
+ doc = new Document.from_string (xml);
+
+ XNode a = doc.document_element;
+ XNode bs = a.child_nodes.item (3);
+ XNode b3 = bs.child_nodes.item (7);
+ XNode t1, t2;
+
+ NodeList ts = ((Element)bs).get_elements_by_tag_name ("t");
+ assert (ts.length == 5);
+
+ // Test adding direct child
+ bs.append_child (t1 = doc.create_element ("t"));
+ assert (ts.length == 6);
+
+ // Test adding descendant
+ b3.append_child (doc.create_element ("t"));
+ assert (ts.length == 7);
+
+ // Test situation where we add a node tree
+ XNode b4;
+ XNode d, d2;
+
+ b4 = doc.create_element ("B");
+ b4.append_child (doc.create_element ("t"));
+ d = doc.create_element ("D");
+ d.append_child (t2 = doc.create_element ("t"));
+ b4.append_child (d);
+
+ bs.append_child (b4);
+
+ assert (ts.length == 9);
+
+ // Test situation where we use insert_before
+ d2 = doc.create_element ("D");
+ d2.append_child (doc.create_element ("t"));
+ b4.insert_before (d2, d);
+
+ assert (ts.length == 10);
+
+ // Test situation where we add a document fragment
+ DocumentFragment frag;
+
+ frag = doc.create_document_fragment ();
+ frag.append_child (doc.create_element ("t"));
+ d = doc.create_element ("D");
+ d.append_child (doc.create_element ("t"));
+ frag.append_child (d);
+ d2 = doc.create_element ("D");
+ d2.append_child (doc.create_element ("t"));
+ frag.insert_before (d2, d);
+
+ b4.append_child (frag);
+ assert (ts.length == 13);
+
+ // Test removing single child
+ t1.parent_node.remove_child (t1);
+ assert (ts.length == 12);
+
+ // Test removing deeper descendant
+ t2.parent_node.remove_child (t2);
+ assert (ts.length == 11);
+
+ // Test removing subtree
+ b4 = b4.parent_node.remove_child (b4);
+
+ assert (ts.length == 6);
+
+ // Test restoring subtree
+ bs.append_child (b4);
+ assert (ts.length == 11);
+ } catch (GXml.Dom.DomError e) {
+ GLib.warning ("%s", e.message);
+ assert (false);
+ }
+ });
Test.add_func ("/gxml/element/normalize", () => {
try {
Element elem = get_elem_new_doc ("tagname");
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]