[gxml] GomNode: GomAttr: Fixing compilation errors



commit d84a88d27dd8cab600be689a35de0826350401a6
Author: Daniel Espinosa <esodan gmail com>
Date:   Wed Oct 26 23:57:35 2016 -0500

    GomNode: GomAttr: Fixing compilation errors
    
    Added new GomAttr, constructors and build fixes.

 NEWS                     |    1 +
 gxml/DomCollections.vala |   22 +++
 gxml/DomDocument.vala    |    4 +-
 gxml/DomNode.vala        |   22 +++-
 gxml/GXmlDocument.vala   |    2 +-
 gxml/GomDocument.vala    |  146 ++++++++++++++----
 gxml/GomElement.vala     |  389 ++++++++++++++++++++++++++++++++++++++--------
 gxml/GomNode.vala        |  168 +++++++++++++-------
 gxml/GomObject.vala      |  356 ++++++++----------------------------------
 gxml/GomText.vala        |   51 ++++---
 gxml/Makefile.am         |    5 +
 11 files changed, 698 insertions(+), 468 deletions(-)
---
diff --git a/NEWS b/NEWS
index cb828c0..cdbe24a 100644
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,7 @@ Version 0.13.0
 
 * Added XPath interfaces and initial implementation based on libxml2
 * Removed old DOM1 implementation on xNode/xDocument
+* API change on DomImplementation.with_ids () for DocumentType to DomDocumentType
 
 ===============
 Version 0.12.0
diff --git a/gxml/DomCollections.vala b/gxml/DomCollections.vala
index 261b474..99aacbe 100644
--- a/gxml/DomCollections.vala
+++ b/gxml/DomCollections.vala
@@ -33,6 +33,28 @@ public interface GXml.DomParentNode : GLib.Object {
 
   public abstract DomElement? query_selector (string selectors) throws GLib.Error;
   public abstract DomNodeList query_selector_all (string selectors) throws GLib.Error;
+  /**
+   * Search all child {@link GXml.Element} with a given property's name and with
+   * value contained in text.
+   */
+  public virtual GXml.DomElementList
+   get_elements_by_property_value (string property, string value)
+  {
+    var list = new GXml.DomElementList ();
+    foreach (var child in children) {
+      if (child is GXml.Element) {
+        list.add_all (child.get_elements_by_property_value (property, value));
+        if (child.attributes == null) continue;
+        var cls = child.attributes.get (property);
+        if (cls == null) {
+          continue;
+        }
+        if (value in cls.node_value)
+            list.add ((GXml.DomElement) child);
+      }
+    }
+    return list;
+  }
 }
 
 public interface GXml.DomNonDocumentTypeChildNode : GLib.Object {
diff --git a/gxml/DomDocument.vala b/gxml/DomDocument.vala
index fe3ff24..5458420 100644
--- a/gxml/DomDocument.vala
+++ b/gxml/DomDocument.vala
@@ -79,7 +79,9 @@ public interface GXml.DomXMLDocument : GLib.Object, GXml.DomDocument {}
  */
 public interface GXml.DomImplementation : GLib.Object {
   public abstract DomDocumentType create_document_type (string qualified_name, string public_id, string 
system_id) throws GLib.Error;
-  public abstract DomXMLDocument create_document (string? nspace, string? qualified_name, DocumentType? 
doctype = null) throws GLib.Error;
+  public abstract DomXMLDocument create_document (string? nspace,
+                                                  string? qualified_name,
+                                                  DomDocumentType? doctype = null) throws GLib.Error;
   public abstract Document create_html_document (string title);
 
   public virtual bool has_feature() { return true; } // useless; always returns true
diff --git a/gxml/DomNode.vala b/gxml/DomNode.vala
index afcf088..7021655 100644
--- a/gxml/DomNode.vala
+++ b/gxml/DomNode.vala
@@ -79,7 +79,23 @@ public interface GXml.DomNode : GLib.Object, GXml.DomEventTarget {
   public abstract DomNode append_child (DomNode node) throws GLib.Error;
   public abstract DomNode replace_child (DomNode node, DomNode child) throws GLib.Error;
   public abstract DomNode remove_child (DomNode child) throws GLib.Error;
-  public abstract DomNode clone_node (bool deep = false);
+  public virtual DomNode clone_node (bool deep = false) {
+    DomNode n = new GomNode ();
+    if (_document == null) return new GomNode ();
+    switch (node_type) {
+      case NodeType.ELEMENT_NODE:
+        n = _document.create_element (node_name);
+        copy (_document, n, this, true);
+        break;
+      case NodeType.COMMENT_NODE:
+        n = _document.create_comment ((this as DomComment).data);
+        break;
+      case NodeType.TEXT_NODE:
+        n = _document.create_text_node ((this as DomText).data);
+        break;// FIXME: more nodes
+    }
+    return n;
+  }
     /**
    * Copy a {@link GXml.DomNode} relaying on {@link GXml.DomDocument} to other {@link GXml.DomNode}.
    *
@@ -101,8 +117,8 @@ public interface GXml.DomNode : GLib.Object, GXml.DomEventTarget {
     if (node is GXml.DomDocument) return false;
     if (source is GXml.DomElement && node is GXml.DomElement) {
 #if DEBUG
-    GLib.message ("Copying source and destiny nodes are GXml.Elements... copying...");
-    GLib.message ("Copying source's attributes to destiny node");
+      GLib.message ("Copying source and destiny nodes are GXml.Elements... copying...");
+      GLib.message ("Copying source's attributes to destiny node");
 #endif
       foreach (GXml.DomNode p in (source as DomElement).attributes.values) {
         ((GXml.DomElement) node).set_attribute (p.node_name, p.node_value); // TODO: Namespace
diff --git a/gxml/GXmlDocument.vala b/gxml/GXmlDocument.vala
index 64d8d83..2b3fe56 100644
--- a/gxml/GXmlDocument.vala
+++ b/gxml/GXmlDocument.vala
@@ -380,7 +380,7 @@ public class GXml.GImplementation : GLib.Object, GXml.DomImplementation {
   }
   public DomXMLDocument create_document (string? namespace,
                                          string? qualified_name,
-                                         DocumentType? doctype = null)
+                                         DomDocumentType? doctype = null)
                                          throws GLib.Error
   { return new GDocument (); } // FIXME
   public Document create_html_document (string title) {
diff --git a/gxml/GomDocument.vala b/gxml/GomDocument.vala
index bfc9df1..a961cc3 100644
--- a/gxml/GomDocument.vala
+++ b/gxml/GomDocument.vala
@@ -24,9 +24,10 @@ using GXml;
 
 public class GXml.GomDocument : GomNode,
                               DomParentNode,
-                              DomNonElementParentNode
+                              DomNonElementParentNode,
+                              DomDocument,
+                              DomXMLDocument
 {
-  protected
   // DomDocument implementation
   protected DomImplementation _implementation = new GomImplementation ();
   protected string _url = "about:blank";
@@ -53,16 +54,14 @@ public class GXml.GomDocument : GomNode,
   public DomElement? document_element {
     owned get {
       if (child_nodes.size == 0) return null;
-      child_nodes[0];
+      return child_nodes[0] as DomElement;
     }
   }
 
-  public DomElement GXml.DomDocument.create_element (string local_name) throws GLib.Error {
-      var e = new GomElement ();
-      e._document = this;
-      e._local_name = local_name;
+  public DomElement create_element (string local_name) throws GLib.Error {
+      return new GomElement (this, local_name);
   }
-  public DomElement GXml.DomDocument.create_element_ns (string? ns, string qualified_name) throws GLib.Error
+  public DomElement create_element_ns (string? ns, string qualified_name) throws GLib.Error
   {
     string n = "";
     string nsp = "";
@@ -77,10 +76,7 @@ public class GXml.GomDocument : GomNode,
     if (nsp == "" && ns == null)
       throw new DomError.NAMESPACE_ERROR (_("Invalid namespace"));
       // TODO: check for xmlns https://www.w3.org/TR/dom/#dom-document-createelementns
-    var e = create_element (n);
-    e._namespaces.set (ns, nsp);
-    e._prefix = nsp;
-    e._namespace_uri = ns;
+    return new GomElement.namespace (this, ns, nsp, n);
   }
 
   public DomHTMLCollection get_elements_by_tag_name (string local_name) {
@@ -103,23 +99,16 @@ public class GXml.GomDocument : GomNode,
   }
 
   public DomDocumentFragment create_document_fragment() {
-    return new GDocumentFragment (this);
+    return new GomDocumentFragment (this);
   }
   public DomText create_text_node (string data) throws GLib.Error {
-    var t = new GomText ();
-    t._document = this;
-    t.data = data;
+    return new GomText (this, data);
   }
   public DomComment GXml.DomDocument.create_comment (string data) throws GLib.Error {
-    var t = new GomComment ();
-    t._document = this;
-    t.data = data;
+    return new GomComment (this, data);
   }
   public DomProcessingInstruction create_processing_instruction (string target, string data) throws 
GLib.Error {
-    var pi = new GomProcessingInstruction ();
-    pi._document = this;
-    pi.data = data;
-    pi._target = target;
+    return new GomProcessingInstruction (this, target, data);
   }
 
   public DomNode import_node (DomNode node, bool deep = false) throws GLib.Error {
@@ -194,14 +183,14 @@ public class GXml.GomDocument : GomNode,
       return new GDomTreeWalker (root, what_to_show, filter);
   }
   // DomParentNode
-  public DomHTMLCollection children { owned get { return (DomHTMLCollection) children_nodes; } }
+  public DomHTMLCollection children { owned get { return (DomHTMLCollection) child_nodes; } }
   public DomElement? first_element_child {
-    owned get { return (DomElement) (this as Document).children_nodes.first (); }
+    owned get { return (DomElement) child_nodes.first (); }
   }
   public DomElement? last_element_child {
-    owned get { return (DomElement) (this as Document).children_nodes.last (); }
+    owned get { return (DomElement) child_nodes.last (); }
   }
-  public ulong child_element_count { get { return (ulong) children_nodes.size; } }
+  public ulong child_element_count { get { return (ulong) child_nodes.size; } }
 
   public DomElement? query_selector (string selectors) throws GLib.Error {
     return null; // FIXME
@@ -216,3 +205,106 @@ public class GXml.GomDocument : GomNode,
     return null;
   }
 }
+
+public class GXml.GomImplementation : GLib.Object, GXml.DomImplementation {
+  public DomDocumentType
+    create_document_type (string qualified_name, string public_id, string system_id)
+        throws GLib.Error
+  {
+
+    return new GomDocumentType.with_ids (new GomDocument (), qualified_name, public_id, system_id); // FIXME
+  }
+  public DomXMLDocument create_document (string? namespace,
+                                         string? qualified_name,
+                                         DomDocumentType? doctype = null)
+                                         throws GLib.Error
+  {
+    var d = new GomDocument ();
+    if (doctype != null)
+      d.append_child (new GomDocumentType.with_ids (d,
+                                                    doctype.name,
+                                                    doctype.public_id,
+                                                    doctype.system_id));
+    d.append_child (d.create_element_ns (namespace, qualified_name));
+    return d as DomXMLDocument;
+  } // FIXME
+  public Document create_html_document (string title) {
+    return new HtmlDocument (); // FIXME:
+  }
+}
+
+
+public class GXml.GomDocumentType : GXml.GomNode,
+                                  GXml.DomNode,
+                                  GXml.DomChildNode,
+                                  GXml.DomDocumentType
+{
+  protected string _name = "";
+  protected string _public_id = "";
+  protected string _system_id = "";
+
+  public  new string name { get { return _name; } }
+  public string public_id { get { return _public_id; } }
+  public string system_id { get { return _system_id; } }
+
+  public GomDocumentType.with_name (DomDocument doc, string name) {
+    _document = doc;
+    _name = name;
+    _public_id = "";
+    _system_id = "";
+  }
+  public GomDocumentType.with_ids (DomDocument doc, string name, string public_id, string system_id) {
+    _document = doc;
+    _name = name;
+    _public_id = public_id;
+    _system_id = system_id;
+  }
+  // DomChildNode implementation
+  public void remove () {
+    if (parent_node == null) return;
+    if (parent_node.child_nodes == null) return;
+    var i = parent_node.child_nodes.index_of (this);
+    parent_node.child_nodes.remove_at (i);
+  }
+}
+
+
+public class GXml.GomDocumentFragment : GXml.GomNode,
+                                        GXml.DomParentNode,
+                                        GXml.DomNonElementParentNode,
+                                        GXml.DomDocumentFragment
+{
+  public GomDocumentFragment (DomDocument doc) {
+    _document = doc;
+  }
+  // DomParentNode
+  public new DomHTMLCollection children {
+    owned get {
+      var l = new DomElementList ();
+      foreach (GXml.DomNode n in child_nodes) {
+        if (n is DomElement) l.add ((DomElement) n);
+      }
+      return l;
+    }
+  }
+  public DomElement? first_element_child { owned get { return (DomElement) children.first (); } }
+  public DomElement? last_element_child { owned get { return (DomElement) children.last (); } }
+  public ulong child_element_count { get { return (ulong) children.size; } }
+
+  public DomElement? query_selector (string selectors) throws GLib.Error {
+  // FIXME:
+    throw new DomError.SYNTAX_ERROR (_("DomElement query_selector is not implemented"));
+  }
+  public DomNodeList query_selector_all (string selectors) throws GLib.Error {
+  // FIXME:
+    throw new DomError.SYNTAX_ERROR (_("DomElement query_selector_all is not implemented"));
+  }
+
+  // DomNonElementParentNode
+  public DomElement? get_element_by_id (string element_id) throws GLib.Error {
+    var l = get_elements_by_property_value ("id", element_id);
+    if (l.size > 0) return (DomElement) l[0];
+    return null;
+  }
+}
+
diff --git a/gxml/GomElement.vala b/gxml/GomElement.vala
index de69838..8bbce8f 100644
--- a/gxml/GomElement.vala
+++ b/gxml/GomElement.vala
@@ -21,89 +21,342 @@
  */
 
 using GXml;
-
+using Gee;
 /**
- * A GXml Object Model (GOM) represents a {@link DomElement}. It has attributes
- * and children. All object's properties are handled as attributes if they are
- * basic types like integers, strings, enums and others; {@link SerializableProperty}
- * objects are handled as attributes too. If object's attribute is a {@link GLib.Object}
- * it is handled as node's child, but only if it is a {@link GomElement} object,
- * other wise it is ignored when this object is used as {@link DomNode} in XML
- * documents.
+ * A GXml Object Model (GOM) implementation of {@link GomElement}.It can be used
+ * transparently as {@link DomElement} in a XML tree.
  */
-public interface GXml.GomElement : GLib.Object,
-                                  DomNode,
-                                  DomElement {
+public class GXml.GomElement : GomNode,
+                                  DomChildNode,
+                                  DomNonDocumentTypeChildNode,
+                                  DomParentNode,
+                                  DomElement,
+                                  GomObject {
   /**
-   * Search for properties in objects, it should be
-   * an {@link GLib.Object}'s property. If found a
-   * property with given name its value is returned
-   * as string representation.
-   *
-   * If property is a {@link SerializableProperty}
-   * returned value is a string representation according
-   * with object implementation.
-   *
-   * If given property name is not found, then {@link DomElement.get_attribute}
-   * is called.
-   *
-   * By default all {@link GLib.Object} are children of
-   * this object, see {@link get_child}
+   * Holds namespaces in current node, using URI as key and prefix as value
    */
-  public virtual string? get_attribute (string name) {
-    var prop = get_class ().find_property_spec (name);
-    if (prop != null) {
-      if (prop.value_type is SerializableProperty) {
-        var ov = get_property (name, out ov);
-        SerializableProperty so = (Object) ov;
-        if (so == null) return null;
-        return so.get_serializable_property_value ();
+  protected Gee.HashMap<string?,string> _namespaces = new Gee.HashMap<string?,string> ();
+
+
+  // DomNode overrides
+  public string? lookup_prefix (string? nspace) {
+    if (nspace == null) return null;
+    var nsp = _namespaces.get (nspace);
+    if (nsp == "") return null;
+    return nsp;
+  }
+  public string? lookup_namespace_uri (string? prefix) {
+    string s = "";
+    if (prefix != null) s = prefix;
+    foreach (string k in _namespaces.keys) {
+      if (_namespaces.get (k) == prefix) return k;
+    }
+    return null;
+  }
+
+  // DomChildNode
+  public void remove () {
+    if (parent_node != null) {
+      var i = parent_node.child_nodes.index_of (this);
+      parent_node.child_nodes.remove_at (i);
+    }
+  }
+  // DomNonDocumentTypeChildNode
+  public DomElement? previous_element_sibling {
+    get {
+      if (parent_node != null) {
+        var i = parent_node.child_nodes.index_of (this);
+        if (i == 0) return null;
+        var n = parent_node.child_nodes.item (i - 1);
+        if (n is DomElement) return (DomElement) n;
+        return null;
+      }
+      return null;
+    }
+  }
+  public DomElement? next_element_sibling {
+    get {
+      if (parent_node != null) {
+        var i = parent_node.child_nodes.index_of (this);
+        if (i == parent_node.child_nodes.length - 1) return null;
+        var n = parent_node.child_nodes.item (i + 1);
+        if (n is DomElement) return (DomElement) n;
+        return null;
+      }
+      return null;
+    }
+  }
+
+  // DomParentNode
+  public new DomHTMLCollection children {
+    owned get {
+      var l = new DomElementList ();
+      foreach (GXml.DomNode n in child_nodes) {
+        if (n is DomElement) l.add ((DomElement) n);
       }
+      return l;
     }
-    return (this as DomElement).get_attribute ();
   }
+  public DomElement? first_element_child { owned get { return (DomElement) children.first (); } }
+  public DomElement? last_element_child { owned get { return (DomElement) children.last (); } }
+  public ulong child_element_count { get { return (ulong) children.size; } }
+
+  public DomElement? query_selector (string selectors) throws GLib.Error {
+  // FIXME:
+    throw new DomError.SYNTAX_ERROR (_("DomElement query_selector is not implemented"));
+  }
+  public DomNodeList query_selector_all (string selectors) throws GLib.Error {
+  // FIXME:
+    throw new DomError.SYNTAX_ERROR (_("DomElement query_selector_all is not implemented"));
+  }
+  // GXml.DomElement
+  protected string _namespace_uri = null;
+  public string? namespace_uri { owned get { return _namespace_uri.dup (); } }
+  protected string _prefix = null;
+  public string? prefix { owned get { return _prefix; } }
   /**
-   * Search for a {@link GLib.Object} property with
-   * given name, if found, given string representation
-   * is used as value to property, using any required
-   * transformation from string.
-   *
-   * By default all {@link GLib.Object} are children of
-   * this object, see {@link set_child}
+   * Derived classes should define this value at construction time.
    */
-  public virtual void set_attribute (string name, string val) {
-    var prop = get_class ().find_property_spec (name);
-    if (prop != null) {
-      if (prop.value_type is SerializableProperty) {
-        var ov = get_property (name, out ov);
-        SerializableProperty so = (Object) ov;
-        if (so == null) return;
-        so.set_serializable_property_value (val);
-      }
+  protected string _local_name = "";
+  public string local_name {
+    owned get {
+      return _local_name;
     }
-    return (this as DomElement).set_attribute (name, val);
+  }
+
+  public string tag_name { owned get { return _local_name; } }
+
+  public string? id {
+    owned get { return (this as GomElement).get_attribute ("id"); }
+    set { (this as GomObject).set_attribute ("id", value); }
+  }
+  public string? class_name {
+    owned get { return (this as GomElement).get_attribute ("class"); }
+    set { (this as GomObject).set_attribute ("class", value); }
+  }
+  public DomTokenList class_list {
+    owned get {
+      return new GDomTokenList (this, "class");
+    }
+  }
+
+
+  construct {
+    _node_type = DomNode.NodeType.ELEMENT_NODE;
+  }
+
+  public GomElement (DomDocument doc, string local_name) {
+    _document = doc;
+    _local_name = local_name;
+  }
+  public GomElement.namespace (DomDocument doc, string namespace, string prefix, string local_name) {
+    _document = doc;
+    _local_name = local_name;
+    _namespace_uri = namespace;
+    string nsp = prefix;
+    if (nsp == null) nsp = "";
+    _prefix = nsp;
+    if (!_namespaces.has_key (namespace))
+      _namespaces.set (namespace, nsp);
   }
   /**
-   * Search a {@link GLib.Object} property with given name
-   * and returns it, if it is a {@link DomElement}. If not found,
-   * {@link DomNode.get_elements_by_tag_name} is called, returning
-   * first node found. Tag name to use, is the given name parameter.
-   *
-   * @param name a name of this object's property of type {@link DomElement} or
-   * first {@link DomNode} with that name in child nodes.
-   *
+   * Holds attributes in current node, using attribute's name as key
+   * and it's value as value. Appends namespace prefix to attribute's name as
+   * key if a namespaced attribute.
    */
-  public virtual DomElement get_child (string name) {
-    var prop = get_class ().find_property_spec (name);
-    if (prop != null) {
-      if (prop.value_type is DomElement) {
-        var vo = Value(prop.value_type);
-        get_property (name, out vo);
-        return (DomElement) ((Object) vo);
+  protected class Attributes : HashMap<string,string>, DomNamedNodeMap  {
+    public ulong length { get { return (ulong) size; } }
+    public DomNode? item (ulong index) { return null; }
+    public DomNode? get_named_item (string name) {
+      if (":" in name) return null;
+      var v = get (name);
+      if (v == null) return null;
+      var n = new GomAttr (this, name, v);
+      return n;
+    }
+    public DomNode? set_named_item (DomNode node) throws GLib.Error {
+      if (":" in node.node_name) return null;
+      set (node.node_name, node.node_value);
+      var n = new GomAttr (this, node.node_name, node.node_value);
+    }
+    public DomNode? remove_named_item (string name) throws GLib.Error {
+      if (":" in name) return null;
+      var v = get (name);
+      if (v == null) return null;
+      var n = new GomAttr (this, name, v);
+      set (name, null);
+      return n;
+    }
+    // Introduced in DOM Level 2:
+    public DomNode? remove_named_item_ns (string namespace_uri, string local_name) throws GLib.Error {
+      if (":" in local_name) return null;
+      var nsp = _name_spaces.get (namespace_uri);
+      if (nsp == null) return null;
+      var v = get (nsp+":"+local_name);
+      if (v == null) return null;
+      var n = new GomAttr (this, namespace_uri, nsp, local_name, v);
+      set (name, null);
+      return n;
+    }
+    // Introduced in DOM Level 2:
+    public DomNode? get_named_item_ns (string namespace_uri, string local_name) throws GLib.Error {
+      if (":" in local_name) return null;
+      var nsp = _name_spaces.get (namespace_uri);
+      if (nsp == null) return null;
+      var v = get (nsp+":"+local_name);
+      if (v == null) return null;
+      var n = new GomNode ();
+      n._node_value = v;
+      n._local_name = local_name;
+      return n;
+    }
+    // Introduced in DOM Level 2:
+    public DomNode? set_named_item_ns (DomNode node) throws GLib.Error {
+      /* TODO:Ç
+      WRONG_DOCUMENT_ERR: Raised if arg was created from a different document than the one that created this 
map.
+
+NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly.
+
+INUSE_ATTRIBUTE_ERR: Raised if arg is an Attr that is already an attribute of another Element object. The 
DOM user must explicitly clone Attr nodes to re-use them in other elements.
+
+HIERARCHY_REQUEST_ERR: Raised if an attempt is made to add a node doesn't belong in this NamedNodeMap. 
Examples would include trying to insert something other than an Attr node into an Element's map of 
attributes, or a non-Entity node into the DocumentType's map of Entities.
+
+NOT_SUPPORTED_ERR: May be raised if the implementation does not support the feature "XML" and the language 
exposed through the Document does not support XML Namespaces (such as [HTML 4.01]).
+      */
+      string ns, ln, nsp;
+      if (node is DomElement) {
+        ns = (node as DomElement).namespace_uri;
+        ln = (node as DomElement).local_name;
+        nsp = (node as DomElement).prefix;
+      } else
+        return null;
+      if (":" in ln)
+        throw new DomError.NOT_SUPPORTED_ERROR (_("Invalid local name"));
+      var nsp = _name_spaces.get (ns);
+      if (nsp == null && _namespaces.size == 0) {
+        _namespaces.set (ns, "");
       }
+      if (nsp == null) nsp = "";
+      set (nsp+":"+local_name, node.node_value);
+      var n = new GomNode ();
+      n.node_value = v;
+      n._local_name = name;
+      return n;
     }
-    if ((this as DomNode).has_child_nodes ()) {
-      return (this as DomElement).child_nodes.named_item (name);
+  }
+  protected Attributes _attributes = new Attributes ();
+  public DomNamedNodeMap attributes { owned get { return (DomNamedNodeMap) _attributes; } }
+  public string? get_attribute (string name) { return (this as GomObject).get_attribute (name); }
+  public string? get_attribute_ns (string? namespace, string local_name) {
+    DomNode p = null;
+    try { p = _attributes.get_named_item_ns (namespace, local_name); }
+    catch (GLib.Error e) {
+      string s = _("Error:");
+      GLib.warning (s+e.message);
+      return null;
     }
+    if (p == null) return null;
+    return p.node_value;
+  }
+  public void set_attribute (string name, string? value) { (this as GomObject).set_attribute (name, value); }
+  public void set_attribute_ns (string? namespace, string name, string? value) {
+    string p = "";
+    string n = name;
+    if (":" in name) {
+      var s = name.split (":");
+      if (s.length != 2) return;
+      p = s[0];
+      n = s[1];
+    } else
+      n = name;
+      //TODO: Throw errors on xmlns and no MXLNS https://www.w3.org/TR/dom/#dom-element-setattributens
+    var nsp = _namespaces.get (namespace);
+    if (nsp != p) {
+      _namespaces.set (namespace, p); // Set Default
+    }
+    _attributes.set (p+":"+n, value);
+  }
+  public void remove_attribute (string name) {
+    (this as GomElement).remove_attribute (name);
+  }
+  public void remove_attribute_ns (string? namespace, string local_name) {
+    if (":" in local_name) return;
+    var nsp = _namespaces.get (namespace);
+    if (nsp == null) return;
+    var a = _attributes.get (nsp+local_name);
+    if (a == null) return;
+    _namespaces.set (nsp+local_name, null);
+  }
+  public bool has_attribute (string name) {
+    return _attributes.has_key (name);
+  }
+  public bool has_attribute_ns (string? namespace, string local_name) {
+    var nsp = _namespaces.get (namespace);
+    if (nsp == null) return false;
+    var a = _namespaces.get (nsp+local_name);
+    if (a != null) return true;
+  }
+
+
+  public DomHTMLCollection get_elements_by_tag_name (string local_name) {
+    var l = new GDomHTMLCollection ();
+    //FIXME: quircks mode not considered
+    foreach (GXml.DomNode n in child_nodes) {
+      if (!(n is DomElement)) continue;
+      if (n.node_name == local_name)
+        l.add (n as DomElement);
+      l.add_all ((n as DomElement).get_elements_by_tag_name (local_name));
+    }
+    return l;
+  }
+  public DomHTMLCollection get_elements_by_tag_name_ns (string? namespace, string local_name) {
+    var l = new GDomHTMLCollection ();
+    //FIXME: quircks mode not considered
+    foreach (GXml.DomNode n in child_nodes) {
+      if (!(n is DomElement)) continue;
+      if (n.node_name == local_name
+          && (n as DomElement).namespace_uri == namespace)
+        l.add (n as DomElement);
+      l.add_all ((n as DomElement).get_elements_by_tag_name_ns (namespace, local_name));
+    }
+    return l;
+  }
+  public DomHTMLCollection get_elements_by_class_name (string class_names) {
+    var l = new GDomHTMLCollection ();
+    if (class_names == "") return l;
+    string[] cs = {};
+    if (" " in class_names) {
+      cs = class_names.split (" ");
+    } else
+      cs += class_names;
+    foreach (GXml.DomNode n in child_nodes) {
+      if (!(n is DomElement)) continue;
+      string cls = (n as DomElement).get_attribute ("class");
+      if (cls != null) {
+        string[] ncls = {};
+        if (" " in cls)
+          ncls = cls.split (" ");
+        else
+          ncls += cls;
+        int found = 0;
+        foreach (string cl in cs) {
+          foreach (string ncl in ncls) {
+            if (cl == ncl) {
+              found++;
+            }
+          }
+        }
+        if (found == cs.length) {
+          if (l.size == 0)
+            l.add (n as DomElement);
+          else
+            l.insert (0, n as DomElement);
+        }
+      }
+      l.add_all ((n as DomElement).get_elements_by_class_name (class_names));
+    }
+    return l;
   }
 }
+
+
diff --git a/gxml/GomNode.vala b/gxml/GomNode.vala
index 9a0c8a4..3a3999f 100644
--- a/gxml/GomNode.vala
+++ b/gxml/GomNode.vala
@@ -21,6 +21,7 @@
  */
 
 using GXml;
+using Gee;
 
 public class GXml.GomNode : Object,
                             DomEventTarget,
@@ -28,8 +29,8 @@ public class GXml.GomNode : Object,
 // DomNode
   protected string _local_name = "";
   protected string _prefix = null;
-  protected DomNode.NodeType _node_type = DomNode.INVALID;
-  public DomNode.NodeType node_type { return _node_type; }
+  protected DomNode.NodeType _node_type = DomNode.NodeType.INVALID;
+  public DomNode.NodeType node_type { get { return _node_type; } }
   public string node_name {
     owned get {
       if (_prefix == null) return _local_name;
@@ -47,27 +48,27 @@ public class GXml.GomNode : Object,
   public DomNode? parent_node { owned get { return _parent as DomNode?; } }
   public DomElement? parent_element {
     owned get {
-      if (parent is DomElement) return parent as DomElement?;
+      if (_parent is DomElement) return _parent as DomElement?;
       return null;
     }
   }
 
   protected class NodeList : Gee.ArrayList<DomNode>, DomNodeList {
     public DomNode? item (ulong index) { return base.get ((int) index); }
-    public abstract ulong length { get { return (ulong) base.size; } }
+    public ulong length { get { return (ulong) base.size; } }
   }
   protected NodeList _child_nodes = new NodeList ();
   public DomNodeList child_nodes { owned get { return _child_nodes as DomNodeList; } }
   public DomNode? first_child {
     owned get {
-    if (_children_nodes.size == 0) return null;
-    return children_nodes[0];
+    if (child_nodes.size == 0) return null;
+    return child_nodes[0];
     }
   }
   public DomNode? last_child {
     owned get {
-      if (_children_nodes.size == 0) return null;
-      return children_nodes[children_nodes.size - 1];
+      if (child_nodes.size == 0) return null;
+      return child_nodes[child_nodes.size - 1];
     }
   }
   public DomNode? previous_sibling {
@@ -77,8 +78,8 @@ public class GXml.GomNode : Object,
      if (_parent.child_nodes.length == 0) return null;
      var pos = (_parent.child_nodes as ArrayList<DomNode>).index_of (this);
      if (pos == 0) return null;
-     if ((pos - 1) > 0 && (pos - 1) < _parent._children_nodes.size)
-      return _parent._children_nodes[pos - 1];
+     if ((pos - 1) > 0 && (pos - 1) < _parent.child_nodes.size)
+      return _parent.child_nodes[pos - 1];
     }
   }
   public DomNode? next_sibling {
@@ -88,36 +89,35 @@ public class GXml.GomNode : Object,
      if (_parent.child_nodes.length == 0) return null;
      var pos = (_parent.child_nodes as ArrayList<DomNode>).index_of (this);
      if (pos == 0) return null;
-     if ((pos + 1) > 0 && (pos + 1) < _parent._children_nodes.size)
-      return _parent._children_nodes[pos + 1];
+     if ((pos + 1) > 0 && (pos + 1) < _parent.child_nodes.size)
+      return _parent.child_nodes[pos + 1];
     }
   }
 
-  string _node_value = null;
+  protected string _node_value = null;
        public string? node_value { owned get { return _node_value; } set { _node_value = value; } }
        public string? text_content {
          owned get {
            string t = null;
-             foreach (GXml.DomNode n in children_nodes) {
-          if (n is GXml.DomText) {
-            if (t == null) t = n.node_value;
-            else t += n.node_value;
-          }
-             }
-           }
-           return t;
-         }
-         set {
-           var t = owner_document.create_text (text_content);
-           _children_nodes.add (t);
-         }
-       }
+      foreach (GXml.DomNode n in child_nodes) {
+        if (n is GXml.DomText) {
+          if (t == null) t = n.node_value;
+          else t += n.node_value;
+        }
+      }
+      return t;
+    }
+    set {
+      var t = owner_document.create_text_node (text_content);
+      child_nodes.add (t);
+    }
+  }
 
-  public bool has_child_nodes () { return (children_nodes.size > 0); }
+  public bool has_child_nodes () { return (_child_nodes.size > 0); }
   public void normalize () {
     try {
-    for (int i = 0; i < children_nodes.size; i++) {
-      var n = children_nodes.get (i);
+    for (int i = 0; i < child_nodes.size; i++) {
+      var n = child_nodes.get (i);
       if (n is DomText) {
         child_nodes.remove_at (i);
       }
@@ -125,22 +125,22 @@ public class GXml.GomNode : Object,
     } catch {}
   }
 
-  public DomNode clone_node (bool deep = false) {
-    // FIXME:
-    return new GomElement ();
-  }
-  public bool is_equal_node (DomNode? node) {
-    if (!(node is GXml.DomNode)) return false;
+  public bool is_equal_node (DomNode? node) { // FIXME:
     if (node == null) return false;
-    if (this.children_nodes.size != (node as Node).children_nodes.size) return false;
-    foreach (GXml.DomNode a in attrs.values) {
-      if (!(node as GXml.Node?).attrs.has_key (a.name)) return false;
-      if (a.value != (node as GXml.Node).attrs.get (a.name).value) return false;
-    }
-    for (int i=0; i < children_nodes.size; i++) {
-      if (!(children_nodes[i] as GXml.DomNode).is_equal_node ((node as GXml.Node?).children_nodes[i] as 
GXml.DomNode?)) return false;
+    if (this is DomCharacterData)
+      return (this as DomComment).data == (node as DomComment).data;
+    if ((this is DomElement) && (node is DomElement)) {
+      if ((this as DomElement).child_nodes.size != (node as DomElement).child_nodes.size) return false;
+      foreach (GXml.DomNode a in attributes.values) {
+        if (!(node as GXml.Node?).attributes.has_key (a.name)) return false;
+        if (a.value != (node as GXml.Node).attributes.get (a.name).value) return false;
+      }
+      for (int i=0; i < child_nodes.size; i++) {
+        if (!((this as DomElement).child_nodes[i] as GXml.DomNode).is_equal_node ((node as 
GXml.Node?).child_nodes[i] as GXml.DomNode?)) return false;
+      }
+      return true;
     }
-    return true;
+    return false;
   }
 
   public DomNode.DocumentPosition compare_document_position (DomNode other) {
@@ -173,15 +173,24 @@ public class GXml.GomNode : Object,
   }
 
   public string? lookup_prefix (string? nspace) {
-    if (_node == null) return null;
-    if (parent == null) return null;
-    if (this is GXml.DocumentType || this is GXml.DocumentFragment) return null;
-    // FIXME:
+    if (this is GXml.DomDocumentType ||
+        this is GXml.DomDocumentFragment) return null;
+    if (this is DomElement) {
+      return (this as DomElement).lookup_prefix (nspace);
+    }
+    if (this is DomAttr) {
+      if (this.parent_node == null) return  null;
+      return this.parent_node.lookup_prefix (nspace);
+    }
     return null;
   }
   public string? lookup_namespace_uri (string? prefix) {
-    if (this is GXml.DocumentType || this is GXml.DocumentFragment) return null;
-    // FIXME;
+    if (this is GXml.DomDocumentType ||
+        this is GXml.DomDocumentFragment) return null;
+    if (this is DomElement) {
+        return (this as DomElement).lookup_namespace_uri (prefix);
+    }
+    return null;
   }
   public bool is_default_namespace (string? nspace) {
     var ns = lookup_namespace_uri (null);
@@ -210,11 +219,11 @@ public class GXml.GomNode : Object,
       throw new DomError.HIERARCHY_REQUEST_ERROR (_("Invalid attempt to insert a document's type or text 
node to a invalid parent"));
     //FIXME: We should follow steps for DOM4 observers in https://www.w3.org/TR/dom/#concept-node-pre-insert
     if (child != null) {
-      int i = this.children_nodes.index_of (child as GXml.Node);
-      children_nodes.insert (i, (node as GXml.Node));
+      int i = this.child_nodes.index_of (child as GXml.DomNode);
+      child_nodes.insert (i, (node as GXml.DomNode));
       return node;
     }
-    children_nodes.add ((node as GXml.Node));
+    child_nodes.add ((node as GXml.DomNode));
     return node;
   }
   public DomNode append_child (DomNode node) throws GLib.Error {
@@ -240,19 +249,19 @@ public class GXml.GomNode : Object,
           || (node is DomDocumentType && !(this is DomDocument)))
       throw new DomError.HIERARCHY_REQUEST_ERROR (_("Invalid attempt to insert a document's type or text 
node to a invalid parent"));
     //FIXME: Checks for HierarchyRequestError for https://www.w3.org/TR/dom/#concept-node-replace
-    int i = children_nodes.index_of ((child as GXml.Node));
-    children_nodes.remove_at (i);
-    if (i < children_nodes.size)
-      children_nodes.insert (i, (node as GXml.Node));
-    if (i >= children_nodes.size)
+    int i = child_nodes.index_of ((child as GXml.DomNode));
+    child_nodes.remove_at (i);
+    if (i < child_nodes.size)
+      child_nodes.insert (i, (node as GXml.DomNode));
+    if (i >= child_nodes.size)
       child_nodes.add (node);
     return child;
   }
   public DomNode remove_child (DomNode child) throws GLib.Error {
     if (!this.contains (child))
       throw new DomError.NOT_FOUND_ERROR (_("Can't find child node to remove or child have a different 
parent"));
-    int i = children_nodes.index_of ((child as GXml.Node));
-    return (DomNode) children_nodes.remove_at (i);
+    int i = child_nodes.index_of ((child as GXml.DomNode));
+    return (DomNode) child_nodes.remove_at (i);
   }
   // DomEventTarget implementation
   public void add_event_listener (string type, DomEventListener? callback, bool capture = false)
@@ -262,3 +271,42 @@ public class GXml.GomNode : Object,
   public bool dispatch_event (DomEvent event)
   { return false; } // FIXME:
 }
+
+public class GXml.GomAttr : GXml.GomNode {
+  protected string _namespace_uri;
+  protected string _prefix;
+  public string local_name { owned get { return _local_name; } }
+  public string name {
+    owned get {
+      string s = "";
+      if (_prefix != null) s = _prefix+":";
+      return s+_local_name;
+    }
+  }
+  public string? namespace_uri { owned get { return _namespace_uri; } }
+  public string? prefix {
+    owned get {
+      if (_prefix == "") return null;
+      return _prefix;
+    }
+  }
+  public string value { owned get { return _node_value; } set { _node_value = value; } }
+
+  public GomAttr (DomElement element, string name, string value) {
+    _document = element.owner_document;
+    _parent = element;
+    _local_name = name;
+    _node_value = value;
+  }
+  public GomAttr.namespace (DomElement element, string namespace, string? prefix, string name, string value) 
{
+    _document = element.owner_document;
+    _parent = element;
+    _local_name = name;
+    _node_value = value;
+    if (element.lookup_prefix (namespace) == prefix
+        || (prefix == null && element.lookup_prefix (namespace) == "")) {
+      _namespace_uri = namespace;
+      _prefix = prefix;
+    }
+  }
+}
diff --git a/gxml/GomObject.vala b/gxml/GomObject.vala
index caee228..8d40906 100644
--- a/gxml/GomObject.vala
+++ b/gxml/GomObject.vala
@@ -21,308 +21,90 @@
  */
 
 using GXml;
+
 /**
- * A GXml Object Model (GOM) implementation of {@link GomElement}.It can be used
- * transparently as {@link DomElement} in a XML tree.
+ * A GXml Object Model (GOM) represents a {@link DomElement}. It has attributes
+ * and children. All object's properties are handled as attributes if they are
+ * basic types like integers, strings, enums and others; {@link SerializableProperty}
+ * objects are handled as attributes too. If object's attribute is a {@link GLib.Object}
+ * it is handled as node's child, but only if it is a {@link GomElement} object,
+ * other wise it is ignored when this object is used as {@link DomNode} in XML
+ * documents.
  */
-public abstract class GXml.GomObject : GomNode,
-                                  DomChildNode,
-                                  DomNonDocumentTypeChildNode,
-                                  DomParentNode,
-                                  DomElement,
-                                  GomElement {
+public interface GXml.GomObject : GLib.Object,
+                                  DomNode,
+                                  DomElement {
   /**
-   * Holds namespaces in current node, using URI as key and prefix as value
+   * Search for properties in objects, it should be
+   * an {@link GLib.Object}'s property. If found a
+   * property with given name its value is returned
+   * as string representation.
+   *
+   * If property is a {@link SerializableProperty}
+   * returned value is a string representation according
+   * with object implementation.
+   *
+   * If given property name is not found, then {@link DomElement.get_attribute}
+   * is called.
+   *
+   * By default all {@link GLib.Object} are children of
+   * this object, see {@link get_child}
    */
-  protected Gee.HashMap<string?,string> _namespaces = Gee.HashMap<string?,string> ();
-
-  construct {
-    _node_type = DomNode.NodeType.ELEMENT_NODE;
-  }
-
-  // DomChildNode
-  public void remove () {
-    if (parent_node != null) {
-      var i = parent_node.child_nodes.index_of (this);
-      parent_node.child_nodes.remove_at (i);
-    }
-  }
-  // DomNonDocumentTypeChildNode
-  public DomElement? previous_element_sibling {
-    get {
-      if (parent_node != null) {
-        var i = parent_node.child_nodes.index_of (this);
-        if (i == 0) return null;
-        var n = parent_node.child_nodes.item (i - 1);
-        if (n is DomElement) return (DomElement) n;
-        return null;
-      }
-      return null;
-    }
-  }
-  public DomElement? next_element_sibling {
-    get {
-      if (parent_node != null) {
-        var i = parent_node.child_nodes.index_of (this);
-        if (i == parent_node.child_nodes.length - 1) return null;
-        var n = parent_node.child_nodes.item (i + 1);
-        if (n is DomElement) return (DomElement) n;
-        return null;
-      }
-      return null;
-    }
-  }
-
-  // DomParentNode
-  public new DomHTMLCollection children {
-    owned get {
-      var l = new DomElementList ();
-      foreach (GXml.DomNode n in child_nodes) {
-        if (n is DomElement) l.add ((DomElement) n);
+  public virtual string? get_attribute (string name) {
+    var prop = get_class ().find_property (name);
+    if (prop != null) {
+      if (prop.value_type is SerializableProperty) {
+        var ov = Value(prop.value_type);
+        get_property (name, ref ov);
+        SerializableProperty so = (Object) ov;
+        if (so == null) return null;
+        return so.get_serializable_property_value ();
       }
-      return l;
     }
+    return (this as DomElement).get_attribute ();
   }
-  public DomElement? first_element_child { owned get { return (DomElement) children.first (); } }
-  public DomElement? last_element_child { owned get { return (DomElement) children.last (); } }
-  public ulong child_element_count { get { return (ulong) children.size; } }
-
-  public DomElement? query_selector (string selectors) throws GLib.Error {
-  // FIXME:
-    throw new DomError.SYNTAX_ERROR (_("DomElement query_selector is not implemented"));
-  }
-  public DomNodeList query_selector_all (string selectors) throws GLib.Error {
-  // FIXME:
-    throw new DomError.SYNTAX_ERROR (_("DomElement query_selector_all is not implemented"));
-  }
-  // GXml.DomElement
-  protected string _namespace_uri = null;
-  public string? namespace_uri { owned get { return _namespace_uri.dup (); } }
-  protected string _prefix = null;
-  public string? prefix { owned get { return _prefix; } }
   /**
-   * Derived classes should define this value at construction time.
+   * Search for a {@link GLib.Object} property with
+   * given name, if found, given string representation
+   * is used as value to property, using any required
+   * transformation from string.
+   *
+   * By default all {@link GLib.Object} are children of
+   * this object, see {@link set_child}
    */
-  protected string _local_name = "";
-  public string local_name {
-    owned get {
-      return _local_name;
-    }
-  }
-
-  public string tag_name { owned get { return _local_name; } }
-
-  public string? id {
-    owned get { return (this as GomElement).get_attribute ("id"); }
-    set { (this as GomElement).set_attribute ("id", value); }
-  }
-  public string? class_name {
-    owned get { return (this as GomElement).get_attribute ("class"); }
-    set { this as GomElement).set_attribute ("class", value); }
-  }
-  public DomTokenList class_list {
-    owned get {
-      return new GDomTokenList (this, "class");
+  public virtual void set_attribute (string name, string val) {
+    var prop = get_class ().find_property (name);
+    if (prop != null) {
+      if (prop.value_type is SerializableProperty) {
+        var ov = get_property (name, ref ov);
+        SerializableProperty so = (Object) ov;
+        if (so == null) return;
+        so.set_serializable_property_value (val);
+      }
     }
+    return (this as DomElement).set_attribute (name, val);
   }
-
   /**
-   * Holds attributes in current node, using attribute's name as key
-   * and it's value as value. Appends namespace prefix to attribute's name as
-   * key if a namespaced attribute.
+   * Search a {@link GLib.Object} property with given name
+   * and returns it, if it is a {@link DomElement}. If not found,
+   * {@link DomNode.get_elements_by_tag_name} is called, returning
+   * first node found. Tag name to use, is the given name parameter.
+   *
+   * @param name a name of this object's property of type {@link DomElement} or
+   * first {@link DomNode} with that name in child nodes.
+   *
    */
-  protected class Attributes : HashMap<string,string>, DomNamedNodeMap  {
-    public ulong length { get { return (ulong) size; } }
-    public DomNode? item (ulong index) { return null; }
-    public DomNode? get_named_item (string name) {
-      if (":" in name) return null;
-      var v = get (name);
-      if (v == null) return null;
-      var n = new GomNode ();
-      n._node_value = v;
-      n._local_name = name;
-      return n;
-    }
-    public DomNode? set_named_item (DomNode node) throws GLib.Error {
-      if (":" in node.node_name) return null;
-      set (node.node_name, node.node_value);
-      var n = new GomNode ();
-      n._node_value = node.node_value;
-      n._local_name = node.node_name;
-    }
-    public DomNode? remove_named_item (string name) throws GLib.Error {
-      if (":" in name) return null;
-      var v = get (name);
-      if (v == null) return null;
-      var n = new GomNode ();
-      n._node_value = v;
-      n._local_name = name;
-      set (name, null);
-      return n;
-    }
-    // Introduced in DOM Level 2:
-    public DomNode? remove_named_item_ns (string namespace_uri, string local_name) throws GLib.Error {
-      if (":" in local_name) return null;
-      var nsp = _name_spaces.get (namespace_uri);
-      if (nsp == null) return null;
-      var v = get (nsp+":"+local_name);
-      if (v == null) return null;
-      var n = new GomNode ();
-      n._node_value = v;
-      n._local_name = name;
-      set (name, null);
-      return n;
-    }
-    // Introduced in DOM Level 2:
-    public DomNode? get_named_item_ns (string namespace_uri, string local_name) throws GLib.Error {
-      if (":" in local_name) return null;
-      var nsp = _name_spaces.get (namespace_uri);
-      if (nsp == null) return null;
-      var v = get (nsp+":"+local_name);
-      if (v == null) return null;
-      var n = new GomNode ();
-      n._node_value = v;
-      n._local_name = local_name;
-      return n;
-    }
-    // Introduced in DOM Level 2:
-    public DomNode? set_named_item_ns (DomNode node) throws GLib.Error {
-      /* TODO:Ç
-      WRONG_DOCUMENT_ERR: Raised if arg was created from a different document than the one that created this 
map.
-
-NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly.
-
-INUSE_ATTRIBUTE_ERR: Raised if arg is an Attr that is already an attribute of another Element object. The 
DOM user must explicitly clone Attr nodes to re-use them in other elements.
-
-HIERARCHY_REQUEST_ERR: Raised if an attempt is made to add a node doesn't belong in this NamedNodeMap. 
Examples would include trying to insert something other than an Attr node into an Element's map of 
attributes, or a non-Entity node into the DocumentType's map of Entities.
-
-NOT_SUPPORTED_ERR: May be raised if the implementation does not support the feature "XML" and the language 
exposed through the Document does not support XML Namespaces (such as [HTML 4.01]).
-      */
-      string ns, ln, nsp;
-      if (node is DomElement) {
-        ns = (node as DomElement).namespace_uri;
-        ln = (node as DomElement).local_name;
-        nsp = (node as DomElement).prefix;
-      } else
-        return null;
-      if (":" in ln)
-        throw new DomError.NOT_SUPPORTED_ERROR (_("Invalid local name"));
-      var nsp = _name_spaces.get (ns);
-      if (nsp == null && _namespaces.size == 0) {
-        _namespaces.set (ns, "");
+  public virtual DomElement get_child (string name) {
+    var prop = get_class ().find_property (name);
+    if (prop != null) {
+      if (prop.value_type is DomElement) {
+        var vo = Value(prop.value_type);
+        get_property (name, ref vo);
+        return (DomElement) ((Object) vo);
       }
-      if (nsp == null) nsp = "";
-      set (nsp+":"+local_name, node.node_value);
-      var n = new GomNode ();
-      n._node_value = v;
-      n._local_name = name;
-      return n;
     }
-  }
-  protected Attributes _attributes = new Attributes ();
-  public DomNamedNodeMap attributes { owned get { return (DomNamedNodeMap) _attributes; } }
-  public string? get_attribute (string name) { return (this as GomElement).get_attribute (name); }
-  public string? get_attribute_ns (string? namespace, string local_name) {
-    var p = _attributes.get_named_item_ns (namespace, local_name);
-    if (p == null) return null;
-    return p.node_value;
-  }
-  public void set_attribute (string name, string? value) { (this as GomElement).set_attribute (name, value); 
}
-  public void set_attribute_ns (string? namespace, string name, string? value) {
-    string p = "";
-    string n = name;
-    if (":" in name) {
-      var s = name.split (":");
-      if (s.length != 2) return null;
-      p = s[0];
-      n = s[1];
-    } else
-      n = name;
-      //TODO: Throw errors on xmlns and no MXLNS https://www.w3.org/TR/dom/#dom-element-setattributens
-    var nsp = _namespaces.get (namespace);
-    if (nsp != p) {
-      _namespaces.set (namespace, p); // Set Default
+    if ((this as DomNode).has_child_nodes ()) {
+      return (this as DomElement).child_nodes.named_item (name);
     }
-    _attributes.set (p+":"+n, value);
-  }
-  public void remove_attribute (string name) {
-    (this as GomElement).remove_attribute (name);
-  }
-  public void remove_attribute_ns (string? namespace, string local_name) {
-    if (":" in local_name) return;
-    var nsp = _namespaces.get (namespace);
-    if (nsp == null) return;
-    var a = _attributes.get (nsp+local_name);
-    if (a == null) return;
-    set (nsp+local_name, null);
-  }
-  public bool has_attribute (string name) {
-    return _attributes.has_key (name);
-  }
-  public bool has_attribute_ns (string? namespace, string local_name) {
-    var nsp = _namespaces.get (namespace);
-    if (nsp == null) return false;
-    var a = get (nsp+local_name);
-    if (a != null) return true;
-  }
-
-
-  public DomHTMLCollection get_elements_by_tag_name (string local_name) {
-    var l = new GDomHTMLCollection ();
-    //FIXME: quircks mode not considered
-    foreach (GXml.DomElement n in child_nodes) {
-      if (n.node_name == local_name)
-        l.add (n);
-      l.add_all (n.get_elements_by_tag_name (local_name));
-    }
-    return l;
-  }
-  public DomHTMLCollection get_elements_by_tag_name_ns (string? namespace, string local_name) {
-    var l = new GDomHTMLCollection ();
-    //FIXME: quircks mode not considered
-    foreach (GXml.DomElement n in child_nodes) {
-      if (n.node_name == local_name
-          && n.namespace_uri == namespace)
-        l.add (n);
-      l.add_all (n.get_elements_by_tag_name_ns (namespace, local_name));
-    }
-    return l;
-  }
-  public DomHTMLCollection get_elements_by_class_name (string class_names) {
-    var l = new GDomHTMLCollection ();
-    if (class_names == "") return l;
-    string[] cs = {};
-    if (" " in class_names) {
-      cs = class_names.split (" ");
-    } else
-      cs += class_names;
-    foreach (GXml.DomElement n in child_nodes) {
-      string cls = n.get_attribute ("class");
-      if (cls != null) {
-        string[] ncls = {};
-        if (" " in cls)
-          ncls = cls.split (" ");
-        else
-          ncls += cls;
-        int found = 0;
-        foreach (string cl in cs) {
-          foreach (string ncl in ncls) {
-            if (cl == ncl) {
-              found++;
-            }
-          }
-        }
-        if (found == cs.length) {
-          if (l.size == 0)
-            l.add (n);
-          else
-            l.insert (0, n);
-        }
-      }
-      l.add_all (n.get_elements_by_class_name (class_names));
-    }
-    return l;
   }
 }
-
-
diff --git a/gxml/GomText.vala b/gxml/GomText.vala
index 99c6d8f..94c98fe 100644
--- a/gxml/GomText.vala
+++ b/gxml/GomText.vala
@@ -22,20 +22,14 @@
 
 using GXml;
 
-public class GXml.GomText : GomNode,
-                          DomCharacterData,
-                          DomNode,
+public class GXml.GomCharacterData : GomNode,
                           DomNonDocumentTypeChildNode,
                           DomChildNode,
-                          DomText
-
+                          DomCharacterData
 {
-  construct {
-    _node_type = DomNode.NodeType.TEXT_NODE;
-    _local_name = "#TEXT";
-  }
+  protected string _data;
   // DomCharacterData
-  public string data { owned get; set; }
+  public string data { owned get { return _data; } set { _data = value; } }
   // DomNonDocumentTypeChildNode
   public DomElement? previous_element_sibling {
     get {
@@ -70,28 +64,43 @@ public class GXml.GomText : GomNode,
   }
 }
 
-public class GXml.GomProcessingInstruction : GomNode,
-              DomCharacterData,
-              DomProcessingInstruction
+public class GXml.GomText : GomCharacterData,
+                          DomText
+
 {
-  protected string _target = null;
-  // DomCharacterData
-  public string data { owned get { return _node_value; } set { _node_value = value; } }
+  construct {
+    _node_type = DomNode.NodeType.TEXT_NODE;
+    _local_name = "#TEXT";
+  }
 
+  public GomText (DomDocument doc, string data);
+}
+public class GXml.GomProcessingInstruction : GomCharacterData,
+                                            DomProcessingInstruction
+{
+  protected string _target = null;
+  // DomProcessingInstruction
+  public string target { owned get { return _target; } }
   construct {
     _node_type = DomNode.NodeType.PROCESSING_INSTRUCTION_NODE;
     _local_name = "#PROCESSING_INSTRUCTION";
   }
+  public GomProcessingInstruction (DomDocument doc, string target, string data) {
+    _document = doc;
+    _target = target;
+    _data = data;
+  }
 }
 
-public class GXml.GomComment : GomNode,
-                                  DomCharacterData,
-                                  DomComment
+public class GXml.GomComment : GomCharacterData,
+                              DomComment
 {
-  // DomCharacterData
-  public string data { owned get; set; }
   construct {
     _node_type = DomNode.NodeType.COMMENT_NODE;
     _local_name = "#COMMENT";
   }
+  public GomComment (DomDocument doc, string data) {
+    _document = doc;
+    _data = data;
+  }
 }
diff --git a/gxml/Makefile.am b/gxml/Makefile.am
index d18f033..b2fb497 100644
--- a/gxml/Makefile.am
+++ b/gxml/Makefile.am
@@ -82,6 +82,11 @@ sources = \
        DomRange.vala \
        XPath.vala \
        GXPathObject.vala \
+       GomDocument.vala \
+       GomElement.vala \
+       GomNode.vala \
+       GomText.vala \
+       GomObject.vala \
        $(NULL)
 
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]