[gxml] Split of XParser.read_current_node in methods
- From: Daniel Espinosa Ortiz <despinosa src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gxml] Split of XParser.read_current_node in methods
- Date: Fri, 20 Jan 2017 18:59:13 +0000 (UTC)
commit d05b41c3bdd839c901857190fad2eeee4f13fa26
Author: Daniel Espinosa <esodan gmail com>
Date: Wed Jan 18 12:43:51 2017 -0600
Split of XParser.read_current_node in methods
gxml/GomAttr.vala | 1 -
gxml/GomCollections.vala | 2 +-
gxml/GomElement.vala | 16 ++-
gxml/XParser.vala | 329 +++++++++++++++++++++++++++++++++++++++-
test/GomSerializationTest.vala | 19 ++-
test/gxml-performance.vala | 14 ++-
6 files changed, 361 insertions(+), 20 deletions(-)
---
diff --git a/gxml/GomAttr.vala b/gxml/GomAttr.vala
index 89ca0ff..2c0ac34 100644
--- a/gxml/GomAttr.vala
+++ b/gxml/GomAttr.vala
@@ -26,7 +26,6 @@ using Gee;
public class GXml.GomAttr : GXml.GomNode, GXml.DomAttr {
protected string _namespace_uri;
- protected string _prefix;
public string local_name { owned get { return _local_name; } }
public string name {
owned get {
diff --git a/gxml/GomCollections.vala b/gxml/GomCollections.vala
index be068a8..ee62328 100644
--- a/gxml/GomCollections.vala
+++ b/gxml/GomCollections.vala
@@ -266,7 +266,7 @@ public abstract class GXml.BaseCollection : Object {
public class GXml.GomArrayList : GXml.BaseCollection, GomCollection {
public override bool validate_add (int index, DomElement element) throws GLib.Error {
#if DEBUG
- GLib.message ("Adding node:"+n.node_name);
+ GLib.message ("Adding node:"+element.node_name);
#endif
return true;
}
diff --git a/gxml/GomElement.vala b/gxml/GomElement.vala
index 96cf77d..a0284da 100644
--- a/gxml/GomElement.vala
+++ b/gxml/GomElement.vala
@@ -39,16 +39,24 @@ public class GXml.GomElement : GomNode,
protected Attributes _attributes;
// Convenient Serialization methods
/**
- * Uses element's {@link GomDocument} to parse an XML file, deserializing it.
+ * Parsing a URI file.
+ */
+ public void read_from_uri (string uri) throws GLib.Error {
+ this.read_from_file (File.new_for_uri (uri));
+ }
+ /**
+ * Parses an XML file, deserializing it over {@link GomElemen}.
*/
public void read_from_file (GLib.File f) throws GLib.Error {
- (this.owner_document as GomDocument).read_from_file (f);
+ var parser = new XParser (this);
+ parser.read_file (f, null);
}
/**
- * Uses element's {@link GomDocument} to parse an XML string, deserializing it.
+ * Parses an XML string, deserializing it over {@link GomElemen}.
*/
public void read_from_string (string str) throws GLib.Error {
- (this.owner_document as GomDocument).read_from_string (str);
+ var parser = new XParser (this);
+ parser.read_string (str, null);
}
/**
* Uses element's {@link GomDocument} to write an XML to a file, serializing it.
diff --git a/gxml/XParser.vala b/gxml/XParser.vala
index 6f272af..f26d6f1 100644
--- a/gxml/XParser.vala
+++ b/gxml/XParser.vala
@@ -104,8 +104,326 @@ public class GXml.XParser : Object, GXml.Parser {
while (read_current_node (_node, true));
}
/**
- * Read current node from a TextReader
+ * Reads a node using current parser.
*/
+ public void read_node (DomNode node) {
+ if (node is DomElement) read_element (node as DomElement);
+ read_child_nodes (node);
+ }
+ /**
+ * Creates a new {@link DomElement} and append it as a child of parent.
+ */
+ public DomElement? create_element (DomNode parent) {
+ DomElement n = null;
+#if DEBUG
+ GLib.message ("Creating a standard element: "
+ +tr.const_local_name ());
+ GLib.message ("Reading: Element: "+tr.const_local_name ());
+#endif
+ string prefix = tr.prefix ();
+ if (prefix != null) {
+#if DEBUG
+ GLib.message ("Is namespaced element");
+#endif
+ string nsuri = tr.lookup_namespace (prefix);
+ n = _document.create_element_ns (nsuri, tr.prefix () +":"+ tr.const_local_name ());
+ } else
+ n = _document.create_element (tr.const_local_name ());
+ parent.append_child (n);
+ return n;
+ }
+ /**
+ * Reads a {@link DomElement}
+ */
+ public void read_element (DomElement element) throws GLib.Error {
+ var nattr = tr.attribute_count ();
+#if DEBUG
+ GLib.message ("Number of Attributes:"+nattr.to_string ());
+#endif
+ for (int i = 0; i < nattr; i++) {
+ var c = tr.move_to_attribute_no (i);
+#if DEBUG
+ GLib.message ("Current Attribute: "+i.to_string ());
+#endif
+ if (c != 1) {
+ throw new DomError.HIERARCHY_REQUEST_ERROR (_("Parsing ERROR: Fail to move to attribute number:
%i").printf (i));
+ }
+ if (tr.is_namespace_decl () == 1) {
+#if DEBUG
+ GLib.message ("Is Namespace Declaration...");
+#endif
+ string nsp = tr.const_local_name ();
+ string aprefix = tr.prefix ();
+ tr.read_attribute_value ();
+ if (tr.node_type () == Xml.ReaderType.TEXT) {
+ string ansuri = tr.read_string ();
+#if DEBUG
+ GLib.message ("Property Read: "+aprefix+":"+nsp+"="+ansuri);
+#endif
+ string ansp = nsp;
+ if (nsp != "xmlns")
+ ansp = aprefix+":"+nsp;
+#if DEBUG
+ GLib.message ("To append: "+ansp+"="+ansuri);
+#endif
+ element.set_attribute_ns ("http://www.w3.org/2000/xmlns/",
+ ansp, ansuri);
+ }
+ } else {
+ var attrname = tr.const_local_name ();
+ string prefix = tr.prefix ();
+#if DEBUG
+ GLib.message ("Attribute: "+tr.const_local_name ());
+#endif
+ tr.read_attribute_value ();
+ if (tr.node_type () == Xml.ReaderType.TEXT) {
+ var attrval = tr.read_string ();
+#if DEBUG
+ GLib.message ("Attribute:"+attrname+" Value: "+attrval);
+#endif
+ bool processed = false;
+ if (node is GomObject) {
+ processed = (element as GomObject).set_attribute (attrname, attrval);
+ }
+ if (!processed) {
+ if (prefix != null) {
+#if DEBUG
+ GLib.message ("Prefix found: "+prefix);
+#endif
+ string nsuri = null;
+ if (prefix == "xml")
+ nsuri = "http://www.w3.org/2000/xmlns/";
+ else
+ nsuri = tr.lookup_namespace (prefix);
+ element.set_attribute_ns (nsuri, prefix+":"+attrname, attrval);
+ } else
+ element.set_attribute (attrname, attrval);
+ }
+ }
+ }
+ }
+ }
+ /**
+ * Iterates in all child nodes and append them to node.
+ */
+ private void read_child_nodes (DomNode node) throws GLib.Error {
+ if (tr.is_empty_element () == 1) return;
+ DomNode n = null;
+ bool cont = true;
+ while (cont) {
+ int res = tr.read ();
+ if (res == -1)
+ throw new ParserError.INVALID_DATA_ERROR (_("Can't read node data"));
+ if (res == 0) {
+#if DEBUG
+ GLib.message ("ReadNode: No more nodes");
+#endif
+ return;
+ }
+ var t = tr.node_type ();
+ switch (t) {
+ case Xml.ReaderType.NONE:
+#if DEBUG
+ GLib.message ("Type NONE");
+#endif
+ res = tr.read ();
+ if (res == -1)
+ throw new ParserError.INVALID_DATA_ERROR (_("Can't read node data"));
+ break;
+ case Xml.ReaderType.ATTRIBUTE:
+#if DEBUG
+ GLib.message ("Type ATTRIBUTE");
+#endif
+ break;
+ case Xml.ReaderType.TEXT:
+ var txtval = tr.read_string ();
+#if DEBUG
+ GLib.message ("Type TEXT");
+ GLib.message ("ReadNode: Text Node : '"+txtval+"'");
+#endif
+ n = _document.create_text_node (txtval);
+ node.append_child (n);
+ break;
+ case Xml.ReaderType.CDATA:
+ break;
+ case Xml.ReaderType.ENTITY_REFERENCE:
+#if DEBUG
+ GLib.message ("Type ENTITY_REFERENCE");
+#endif
+ break;
+ case Xml.ReaderType.ENTITY:
+#if DEBUG
+ GLib.message ("Type ENTITY");
+#endif
+ break;
+ case Xml.ReaderType.PROCESSING_INSTRUCTION:
+ var pit = tr.const_local_name ();
+ var pival = tr.value ();
+#if DEBUG
+ GLib.message ("Type PROCESSING_INSTRUCTION");
+ GLib.message ("ReadNode: PI Node : '"+pit+"' : '"+pival+"'");
+#endif
+ n = node.owner_document.create_processing_instruction (pit,pival);
+ node.append_child (n);
+ break;
+ case Xml.ReaderType.COMMENT:
+ var commval = tr.value ();
+#if DEBUG
+ GLib.message ("Type COMMENT");
+ GLib.message ("ReadNode: Comment Node : '"+commval+"'");
+#endif
+ n = node.owner_document.create_comment (commval);
+ node.append_child (n);
+ break;
+ case Xml.ReaderType.DOCUMENT:
+#if DEBUG
+ GLib.message ("Type DOCUMENT");
+#endif
+ break;
+ case Xml.ReaderType.DOCUMENT_TYPE:
+#if DEBUG
+ GLib.message ("Type DOCUMENT_TYPE");
+#endif
+ break;
+ case Xml.ReaderType.DOCUMENT_FRAGMENT:
+#if DEBUG
+ GLib.message ("Type DOCUMENT_FRAGMENT");
+#endif
+ break;
+ case Xml.ReaderType.NOTATION:
+#if DEBUG
+ GLib.message ("Type NOTATION");
+#endif
+ break;
+ case Xml.ReaderType.WHITESPACE:
+#if DEBUG
+ GLib.message ("Type WHITESPACE");
+#endif
+ break;
+ case Xml.ReaderType.SIGNIFICANT_WHITESPACE:
+ var stxtval = tr.read_string ();
+#if DEBUG
+ GLib.message ("ReadNode: Text Node : '"+stxtval+"'");
+ GLib.message ("Type SIGNIFICANT_WHITESPACE");
+#endif
+ n = _document.create_text_node (stxtval);
+ node.append_child (n);
+ break;
+ case Xml.ReaderType.END_ELEMENT:
+#if DEBUG
+ GLib.message ("Type END_ELEMENT");
+#endif
+ return;
+ case Xml.ReaderType.END_ENTITY:
+#if DEBUG
+ GLib.message ("Type END_ENTITY");
+#endif
+ return;
+ case Xml.ReaderType.XML_DECLARATION:
+#if DEBUG
+ GLib.message ("Type XML_DECLARATION");
+#endif
+ break;
+ case Xml.ReaderType.ELEMENT:
+#if DEBUG
+ GLib.debug ("Type ELEMENT_NODE");
+#endif
+ if (!read_element_property (node, out n))
+ n = create_element (node);
+ if (n == null) return;
+ read_element (n as DomElement);
+ read_child_nodes (n);
+ break;
+ }
+ }
+ }
+ /**
+ * Creates a new {@link DomElement} as a child of parent: for current
+ * read node, only if :
+ *
+ * # parent: have a property as {@link DomElement} type and current
+ * node have same local name as property element.
+ * # parent: have a property as {@link GomCollection} type and current
+ * node have same local name as collection {@link GomCollection.items_name}
+ *
+ * Returns: true if element is set to a new object, it is set as a parent:
+ * property or has been added to a parent: collection property.
+ */
+ public bool read_element_property (DomNode parent,
+ out DomNode element) throws GLib.Error {
+ if (!(parent is GomObject)) return false;
+ GomElement node = parent as GomElement;
+#if DEBUG
+ GLib.message ("Searching for Properties Nodes for:"+
+ (node as DomElement).local_name+
+ " Current node name: "+ tr.const_local_name ());
+#endif
+ foreach (ParamSpec pspec in
+ (node as GomObject).get_property_element_list ()) {
+ if (pspec.value_type.is_a (typeof (GomCollection))) {
+#if DEBUG
+ GLib.message (" Is Collection in: "+(node as DomElement).local_name);
+#endif
+ GomCollection col;
+ Value vc = Value (pspec.value_type);
+ node.get_property (pspec.name, ref vc);
+ col = vc.get_object () as GomCollection;
+ if (col == null) {
+#if DEBUG
+ GLib.message ("Initializing Collection property...");
+#endif
+ col = Object.new (pspec.value_type,
+ "element", node) as GomCollection;
+ vc.set_object (col);
+ node.set_property (pspec.name, vc);
+ }
+ if (col.items_type == GLib.Type.INVALID
+ || !(col.items_type.is_a (typeof (GomObject)))) {
+ throw new DomError.INVALID_NODE_TYPE_ERROR
+ (_("Invalid object type set to Collection"));
+ }
+ if (col.items_name == "" || col.items_name == null) {
+ throw new DomError.INVALID_NODE_TYPE_ERROR
+ (_("Invalid DomElement name for objects in Collection"));
+ }
+ if (col.element == null || !(col.element is GomElement)) {
+ throw new DomError.INVALID_NODE_TYPE_ERROR
+ (_("Invalid Element set to Collection"));
+ }
+ if (col.items_name.down () == tr.const_local_name ().down ()) {
+#if DEBUG
+ GLib.message ("Is a Node to append in collection");
+#endif
+ if (node.owner_document == null)
+ throw new DomError.HIERARCHY_REQUEST_ERROR
+ (_("No document is set to node"));
+ var obj = Object.new (col.items_type,
+ "owner-document", _document);
+#if DEBUG
+ GLib.message ("Object Element to add in Collection: "
+ +(_node as DomNode).node_name);
+#endif
+ col.append (obj as DomElement);
+ element = obj as DomNode;
+ return true;
+ }
+ } else {
+ var obj = Object.new (pspec.value_type,
+ "owner-document", _document);
+ if ((obj as DomElement).local_name.down ()
+ == tr.const_local_name ().down ()) {
+ Value v = Value (pspec.value_type);
+ read_current_node (obj as DomNode, true, true);
+ node.append_child (obj as DomNode);
+ v.set_object (obj);
+ node.set_property (pspec.name, v);
+ element = obj as DomNode;
+ return true;
+ }
+ }
+ }
+ return false;
+ }
public bool read_current_node (DomNode node,
bool read_current = false,
bool read_property = false)
@@ -238,12 +556,10 @@ public class GXml.XParser : Object, GXml.Parser {
.printf ((node as DomElement).local_name));
}
if (!isproperty) {
-#if DEBUG
- GLib.message ("No object Property is set. Creating a standard element: "
- +tr.const_local_name ());
-#endif
if (node is DomDocument || !read_current) {
#if DEBUG
+ GLib.message ("No object Property is set. Creating a standard element: "
+ +tr.const_local_name ());
GLib.message ("No deserializing current node");
if (isempty) GLib.message ("Is Empty node:"+node.node_name);
GLib.message ("ReadNode: Element: "+tr.const_local_name ());
@@ -336,9 +652,6 @@ public class GXml.XParser : Object, GXml.Parser {
GLib.message ("Getting child nodes in element");
#endif
while (read_current_node (n) == true);
-#if DEBUG
- GLib.message ("Current Document: "+node.document.to_string ());
-#endif
break;
case Xml.ReaderType.ATTRIBUTE:
#if DEBUG
diff --git a/test/GomSerializationTest.vala b/test/GomSerializationTest.vala
index 0437ab8..7fb54fa 100644
--- a/test/GomSerializationTest.vala
+++ b/test/GomSerializationTest.vala
@@ -114,6 +114,7 @@ class GomBook : GomElement
resumes = Object.new (typeof (GomResume.Map),
"element", this)
as GomResume.Map;
+ assert (this.local_name == "Book");
}
public class Array : GomArrayList {
construct { initialize (typeof (GomBook)); }
@@ -124,13 +125,23 @@ class GomBookStore : GomElement
{
[Description (nick="::name")]
public string name { get; set; }
+ public GomBook.Array books { get; set; }
construct {
+ message ("Initialization of GomBookStore");
initialize ("BookStore");
- assert (this != null);
books = Object.new (typeof(GomBook.Array),"element", this) as GomBook.Array;
- assert_not_reached ();
}
- public GomBook.Array books { get; set; }
+ public string to_string () {
+ var parser = new XParser (this);
+ string s = "";
+ try {
+ s = parser.write_string ();
+ } catch (GLib.Error e) {
+ GLib.message ("Error: "+e.message);
+ assert_not_reached ();
+ }
+ return s;
+ }
}
class GomSerializationTest : GXmlTest {
@@ -243,6 +254,8 @@ class GomSerializationTest : GXmlTest {
construct { initialize_with_key (typeof (Book), "name"); }
}
public class BookStore : GomElement {
+ [Description (nick="::Name")]
+ public string name { get; set; }
public Books books { get; set; }
construct {
initialize ("BookStore");
diff --git a/test/gxml-performance.vala b/test/gxml-performance.vala
index 0852830..f5ae85e 100644
--- a/test/gxml-performance.vala
+++ b/test/gxml-performance.vala
@@ -242,17 +242,24 @@ public class Performance
try {
double time;
GomDocument doc;
- var f = GLib.File.new_for_path (GXmlTestConfig.TEST_DIR + "/test-large.xml");
+ var f = GLib.File.new_for_path (GXmlTestConfig.TEST_DIR + "/test-collection.xml");
assert (f.query_exists ());
Test.timer_start ();
var bs = new GomBookStore ();
- assert_not_reached ();
assert (bs != null);
+ assert (bs.books != null);
+ assert (bs.books.element != null);
+ assert (bs.books.items_type.is_a (typeof(GomBook)));
+ assert (bs.books.items_name == "Book");
+ GLib.message ("Empty XML:"+bs.to_string ());
bs.read_from_file (f);
+ GLib.message ("XML:"+bs.to_string ());
+ assert_not_reached ();
assert (bs.local_name == "BookStore");
+ assert (bs.get_attribute ("name") != null);
+ assert (bs.name != null);
assert (bs.name == "The Great Book");
time = Test.timer_elapsed ();
- assert_not_reached ();
Test.minimized_result (time, "deserialize/performance: %g seconds", time);
var of = GLib.File.new_for_path (GXmlTestConfig.TEST_SAVE_DIR + "/test-large-new.xml");
Test.timer_start ();
@@ -266,6 +273,7 @@ public class Performance
assert (bs.owner_document.document_element.node_name.down () == "bookstore");
assert (bs.child_nodes.length > 0);
var ns = bs.get_elements_by_tag_name ("book");
+ GLib.message ("Query Books: "+ns.length.to_string ());
assert (ns.length > 0);
GLib.message ("Books: "+bs.books.length.to_string ());
/*assert (bs.books.length > 0);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]