Commit f5e352e5 authored by Daniel Espinosa Ortiz's avatar Daniel Espinosa Ortiz

GOM: Adding new independent DOM4 implementation

GXML Object Model, is a set of new GObject classes
implementing DOM4, without libxml2.

Read and Write of XML documents will be replicated
from TDocument implementation. Plans include to
create an interface to read and write documents,
implementing DOM4 interfaces, allowing to use
different engines like libxml2 or GLib's GMarkup.
parent 94ebd331
/* -*- Mode: vala; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */
/* -*- Mode: vala; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */
/*
*
* Copyright (C) 2016 Daniel Espinosa <esodan@gmail.com>
......@@ -56,7 +56,6 @@ public interface GXml.DomNode : GLib.Object, GXml.DomEventTarget {
public abstract bool has_child_nodes ();
public abstract void normalize ();
public abstract DomNode clone_node (bool deep = false);
public abstract bool is_equal_node (DomNode? node);
[Flags]
......@@ -80,6 +79,67 @@ 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) {
/**
* Copy a {@link GXml.DomNode} relaying on {@link GXml.DomDocument} to other {@link GXml.DomNode}.
*
* {@link node} could belongs from different {@link GXml.DomDocument}, while source is a node
* belonging to given document.
*
* Only {@link GXml.DomElement} objects are supported. For attributes, use
* {@link GXml.DomElement.set_attr} method, passing source's name and value as arguments.
*
* @param doc a {@link GXml.DomDocument} owning destiny node
* @param node a {@link GXml.DomElement} to copy nodes to
* @param source a {@link GXml.DomElement} to copy nodes from, it could be holded by different {@link GXml.DomDocument}
*/
public static bool copy (GXml.DomDocument doc, GXml.DomNode node, GXml.DomNode source, bool deep)
{
#if DEBUG
GLib.message ("Copying GXml.Node");
#endif
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");
#endif
foreach (GXml.DomNode p in source._attributes.values) {
((GXml.DomElement) node).set_attribute (p.node_name, p.node_value); // TODO: Namespace
}
if (!deep) return true;
#if DEBUG
GLib.message ("Copying source's child nodes to destiny node");
#endif
foreach (DomNode c in source.child_nodes) {
if (c is DomElement) {
if (c.node_name == null) continue;
#if DEBUG
GLib.message (@"Copying child Element node: $(c.node_name)");
#endif
try {
var e = doc.create_element (c.node_name); // TODO: Namespace
node.child_nodes.add (e);
copy (doc, e, c, deep);
} catch {}
}
if (c is DomText) {
if ((c as DomText).data == null) {
GLib.warning (_("Text node with NULL string"));
continue;
}
var t = doc.create_text ((c as DomText).data);
node.child_nodes.add (t);
#if DEBUG
GLib.message (@"Copying source's Text node '$(source.node_name)' to destiny node with text: $(c.node_value) : Size= $(node.child_nodes.size)");
GLib.message (@"Added Text: $(node.child_nodes.get (node.child_nodes.size - 1))");
#endif
}
}
}
return false;
}
}
}
public errordomain GXml.DomError {
......
/* -*- Mode: vala; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */
/*
*
* Copyright (C) 2016 Daniel Espinosa <esodan@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Daniel Espinosa <esodan@gmail.com>
*/
using GXml;
public class GXml.GomDocument : GomNode,
DomParentNode,
DomNonElementParentNode
{
protected
// DomDocument implementation
protected DomImplementation _implementation = new GomImplementation ();
protected string _url = "about:blank";
protected string _origin = "";
protected string _compat_mode = "";
protected string _character_set = "utf-8";
protected string _content_type = "application/xml";
public DomImplementation implementation { get { return _implementation; } }
public string url { get { return _url; } }
public string document_uri { get { return _url; } }
public string origin { get { return _origin; } }
public string compat_mode { get { return _compat_mode; } }
public string character_set { get { return _character_set; } }
public string content_type { get { return _content_type; } }
public DomDocumentType? doctype {
owned get {
foreach (DomNode n in child_nodes) {
if (n is DomDocumentType) return (DomDocumentType) n;
}
return null;
}
}
public DomElement? document_element {
owned get {
if (child_nodes.size == 0) return null;
child_nodes[0];
}
}
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 GXml.DomDocument.create_element_ns (string? ns, string qualified_name) throws GLib.Error
{
string n = "";
string nsp = "";
if (":" in qualified_name) {
var s = qualified_name.split (":");
if (s.length != 2)
throw new DomError.NOT_SUPPORTED_ERROR (_("Invalid node name"));
nsp = s[0];
n = s[1];
} else
n = qualified_name;
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;
}
public DomHTMLCollection get_elements_by_tag_name (string local_name) {
var l = new GDomHTMLCollection ();
if (document_element == null) return l;
l.add_all (document_element.get_elements_by_tag_name (local_name));
return l;
}
public DomHTMLCollection get_elements_by_tag_name_ns (string? ns, string local_name) {
var l = new GDomHTMLCollection ();
if (document_element == null) return l;
l.add_all (document_element.get_elements_by_tag_name_ns (ns, local_name));
return l;
}
public DomHTMLCollection get_elements_by_class_name(string class_names) {
var l = new GDomHTMLCollection ();
if (document_element == null) return l;
l.add_all (document_element.get_elements_by_class_name (class_names));
return l;
}
public DomDocumentFragment create_document_fragment() {
return new GDocumentFragment (this);
}
public DomText create_text_node (string data) throws GLib.Error {
var t = new GomText ();
t._document = this;
t.data = data;
}
public DomComment GXml.DomDocument.create_comment (string data) throws GLib.Error {
var t = new GomComment ();
t._document = this;
t.data = 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;
}
public DomNode import_node (DomNode node, bool deep = false) throws GLib.Error {
if (node is DomDocument)
throw new GXml.DomError.NOT_SUPPORTED_ERROR (_("Can't import a Document"));
if (!(node is DomElement) && this.document_element == null)
throw new GXml.DomError.HIERARCHY_REQUEST_ERROR (_("Can't import a non Element type node to a Document"));
GXml.DomNode dst = null;
if (node is DomElement) {
dst = (this as DomDocument).create_element (node.node_name);
GXml.DomNode.copy (this, dst, node, deep);
if (document_element == null) {
this.append_child (dst);
return dst;
}
}
if (node is DomText)
dst = this.create_text_node ((node as DomText).data);
if (node is DomComment)
dst = (this as DomDocument).create_comment ((node as DomComment).data);
if (node is DomProcessingInstruction)
dst = this.create_processing_instruction ((node as DomProcessingInstruction).target, (node as DomProcessingInstruction).data);
if (dst != null) {
document_element.append_child (dst as DomNode);
return dst;
}
return node;
}
public DomNode adopt_node (DomNode node) throws GLib.Error {
if (node is DomDocument)
throw new GXml.DomError.NOT_SUPPORTED_ERROR (_("Can't adopt a Document"));
if (this == node.owner_document) return node;
var dst = this.create_element (node.node_name);
GXml.DomNode.copy (this, dst, node, true);
if (node.parent_node != null)
node.parent_node.child_nodes.remove_at (node.parent_node.child_nodes.index_of (node));
if (this.document_element == null)
this.append_child (dst as DomNode);
else
document_element.append_child (dst as DomNode);
return (DomNode) dst;
}
protected GXml.DomEvent _constructor;
public DomEvent create_event (string iface) {
var s = iface.down ();
if (s == "customevent") _constructor = new GXml.GDomCustomEvent ();
if (s == "event") _constructor = new GXml.GDomCustomEvent ();
if (s == "events") _constructor = new GXml.GDomCustomEvent ();
if (s == "htmlevents") _constructor = new GXml.GDomCustomEvent ();
if (s == "keyboardevent") _constructor = null;
if (s == "keyevents") _constructor = null;
if (s == "messageevent") _constructor = null;
if (s == "mouseevent") _constructor = null;
if (s == "mouseevents") _constructor = null;
if (s == "touchevent") _constructor = null;
if (s == "uievent") _constructor = null;
if (s == "uievents") _constructor = null;
return _constructor;
}
public DomRange create_range() {
return new GDomRange (this);
}
// NodeFilter.SHOW_ALL = 0xFFFFFFFF
public DomNodeIterator create_node_iterator (DomNode root, ulong what_to_show = (ulong) 0xFFFFFFFF, DomNodeFilter? filter = null)
{
return new GDomNodeIterator (root, what_to_show, filter);
}
public DomTreeWalker create_tree_walker (DomNode root, ulong what_to_show = (ulong) 0xFFFFFFFF, DomNodeFilter? filter = null) {
return new GDomTreeWalker (root, what_to_show, filter);
}
// DomParentNode
public DomHTMLCollection children { owned get { return (DomHTMLCollection) children_nodes; } }
public DomElement? first_element_child {
owned get { return (DomElement) (this as Document).children_nodes.first (); }
}
public DomElement? last_element_child {
owned get { return (DomElement) (this as Document).children_nodes.last (); }
}
public ulong child_element_count { get { return (ulong) children_nodes.size; } }
public DomElement? query_selector (string selectors) throws GLib.Error {
return null; // FIXME
}
public DomNodeList query_selector_all (string selectors) throws GLib.Error {
return null; // FIXME
}
// DomNonElementParentNode
public DomElement? get_element_by_id (string element_id) throws GLib.Error {
var l = this.get_elements_by_property_value ("id", element_id);
if (l.size > 0) return (DomElement) l[0];
return null;
}
}
/* -*- Mode: vala; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */
/*
*
* Copyright (C) 2016 Daniel Espinosa <esodan@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Daniel Espinosa <esodan@gmail.com>
*/
using GXml;
/**
* 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 interface GXml.GomElement : GLib.Object,
DomNode,
DomElement {
/**
* 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}
*/
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 ();
}
}
return (this as DomElement).get_attribute ();
}
/**
* 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}
*/
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);
}
}
return (this as DomElement).set_attribute (name, val);
}
/**
* 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.
*
*/
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);
}
}
if ((this as DomNode).has_child_nodes ()) {
return (this as DomElement).child_nodes.named_item (name);
}
}
}
/* -*- Mode: vala; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */
/*
*
* Copyright (C) 2016 Daniel Espinosa <esodan@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Daniel Espinosa <esodan@gmail.com>
*/
using GXml;
public class GXml.GomNode : Object,
DomEventTarget,
DomNode {
// DomNode
protected string _local_name = "";
protected string _prefix = null;
protected DomNode.NodeType _node_type = DomNode.INVALID;
public DomNode.NodeType node_type { return _node_type; }
public string node_name {
owned get {
if (_prefix == null) return _local_name;
return _prefix+":"+_local_name;
}
}
protected string _base_uri = null;
public string? base_uri { get { return _base_uri; } }
protected GXml.DomDocument _document;
public DomDocument? owner_document { get { return (GXml.DomDocument?) _document; } }
protected GXml.DomNode _parent;
public DomNode? parent_node { owned get { return _parent as DomNode?; } }
public DomElement? parent_element {
owned get {
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; } }
}
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];
}
}
public DomNode? last_child {
owned get {
if (_children_nodes.size == 0) return null;
return children_nodes[children_nodes.size - 1];
}
}
public DomNode? previous_sibling {
owned get {
if (_parent == null) return null;
if (_parent.child_nodes == null) return null;
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];
}
}
public DomNode? next_sibling {
owned get {
if (_parent == null) return null;
if (_parent.child_nodes == null) return null;
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];
}
}
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);
}
}
public bool has_child_nodes () { return (children_nodes.size > 0); }
public void normalize () {
try {
for (int i = 0; i < children_nodes.size; i++) {
var n = children_nodes.get (i);
if (n is DomText) {
child_nodes.remove_at (i);
}
}
} 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;
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;
}
return true;
}
public DomNode.DocumentPosition compare_document_position (DomNode other) {
if ((this as GXml.DomNode) == other) return DomNode.DocumentPosition.NONE;
if (this.document != (other as GXml.Node).document || other.parent_node == null) {
var p = DomNode.DocumentPosition.DISCONNECTED & DomNode.DocumentPosition.IMPLEMENTATION_SPECIFIC;
if ((&this) > (&other))
p = p & DomNode.DocumentPosition.PRECEDING;
else
p = p & DomNode.DocumentPosition.FOLLOWING;
return p;
}
if ((this as DomNode).contains (other))
return DomNode.DocumentPosition.CONTAINED_BY & DomNode.DocumentPosition.FOLLOWING;
if (this.parent_node.contains (other)) {
var par = this.parent_node;
if (par.child_nodes.index_of (this) > par.child_nodes.index_of (other))
return DomNode.DocumentPosition.PRECEDING;
else
return DomNode.DocumentPosition.FOLLOWING;
}
if (other.contains (this))
return DomNode.DocumentPosition.CONTAINS & DomNode.DocumentPosition.PRECEDING;
GLib.warning (_("Can't find node position"));
return DomNode.DocumentPosition.NONE;
}
public bool contains (DomNode? other) {
if (other == null) return false;
return this.child_nodes.contains (other);
}
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:
return null;
}
public string? lookup_namespace_uri (string? prefix) {
if (this is GXml.DocumentType || this is GXml.DocumentFragment) return null;
// FIXME;
}
public bool is_default_namespace (string? nspace) {
var ns = lookup_namespace_uri (null);
if (ns == nspace) return true;
return false;
}
public DomNode insert_before (DomNode node, DomNode? child) throws GLib.Error {
if (!(node is GXml.GNode))
throw new DomError.INVALID_NODE_TYPE_ERROR (_("Invalid attempt to add invalid node type"));
if (child != null && !this.contains (child))
throw new DomError.NOT_FOUND_ERROR (_("Can't find child to insert node before"));
if (!(this is DomDocument
|| this is DomElement
|| this is DomDocumentFragment))
throw new DomError.HIERARCHY_REQUEST_ERROR (_("Invalid attempt to insert a node"));
if (!(node is DomDocumentFragment
|| node is DomDocumentType
|| node is DomElement
|| node is DomText
|| node is DomProcessingInstruction
|| node is DomComment))
throw new DomError.HIERARCHY_REQUEST_ERROR (_("Invalid attempt to insert an invalid node type"));
if ((node is DomText && this is DomDocument)
|| (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: 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));
return node;
}
children_nodes.add ((node as GXml.Node));
return node;
}
public DomNode append_child (DomNode node) throws GLib.Error {
return insert_before (node, null);
}
public DomNode replace_child (DomNode node, DomNode child) throws GLib.Error {
if (!(node is GXml.GNode))
throw new DomError.INVALID_NODE_TYPE_ERROR (_("Invalid attempt to add invalid node type"));
if (child == null || !this.contains (child))
throw new DomError.NOT_FOUND_ERROR (_("Can't find child node to replace or child have a different parent"));
if (!(this is DomDocument
|| this is DomElement
|| this is DomDocumentFragment))
throw new DomError.HIERARCHY_REQUEST_ERROR (_("Invalid attempt to insert a node"));
if (!(node is DomDocumentFragment
|| node is DomDocumentType
|| node is DomElement
|| node is DomText
|| node is DomProcessingInstruction
|| node is DomComment))
throw new DomError.HIERARCHY_REQUEST_ERROR (_("Invalid attempt to insert an invalid node type"));
if ((node is DomText && this is DomDocument)
|| (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)
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);
}
// DomEventTarget implementation
public void add_event_listener (string type, DomEventListener? callback, bool capture = false)
{ return; } // FIXME:
public void remove_event_listener (string type, DomEventListener? callback, bool capture = false)
{ return; } // FIXME:
public bool dispatch_event (DomEvent event)
{ return false; } // FIXME:
}
/* -*- Mode: vala; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */
/*
*
* Copyright (C) 2016 Daniel Espinosa <esodan@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Daniel Espinosa <esodan@gmail.com>
*/
using GXml;
/**
* A GXml Object Model (GOM) implementation of {@link GomElement}.It can be used
* transparently as {@link DomElement} in a XML tree.
*/
public abstract class GXml.GomObject : GomNode,
DomChildNode,
DomNonDocumentTypeChildNode,
DomParentNode,
DomElement,
GomElement {
/**
* Holds namespaces in current node, using URI as key and prefix as value
*/
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);
</