[gxml] Add support for xsi:type properties
- From: Daniel Espinosa Ortiz <despinosa src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gxml] Add support for xsi:type properties
- Date: Wed, 10 Jul 2019 18:13:10 +0000 (UTC)
commit 3ebfcfd6cdf765caa62c176668a41bf8a875e7c8
Author: Daniel Espinosa <esodan gmail com>
Date: Wed Jul 10 13:11:13 2019 -0500
Add support for xsi:type properties
Defined prefix and namespaces for default for: xmlns, xml,
html and xsi.
Fixed handling of properties of the same name but
different namespace.
gxml/Element.vala | 116 +++++++++++++++++++++++++++++++++-----------------
gxml/XParser.vala | 31 ++++++++------
test/ElementTest.vala | 29 +++++++++++++
3 files changed, 123 insertions(+), 53 deletions(-)
---
diff --git a/gxml/Element.vala b/gxml/Element.vala
index 2cab03f..cbfdeee 100644
--- a/gxml/Element.vala
+++ b/gxml/Element.vala
@@ -158,6 +158,20 @@ public class GXml.Element : GXml.Node,
public new string? lookup_prefix (string? nspace) {
if (_namespace_uri == nspace)
return _prefix;
+ switch (nspace) {
+ case "http://www.w3.org/2000/xmlns/":
+ case "http://www.w3.org/2000/xmlns":
+ return "xmlns";
+ case "http://www.w3.org/XML/1998/namespace":
+ case "http://www.w3.org/XML/1998/namespace/":
+ return "xml";
+ case "http://www.w3.org/1999/xhtml":
+ case "http://www.w3.org/1999/xhtml/":
+ return "html";
+ case "http://www.w3.org/2001/XMLSchema-instance":
+ case "http://www.w3.org/2001/XMLSchema-instance/":
+ return "xsi";
+ }
foreach (string k in _attributes.keys) {
if (!("xmlns" in k)) continue;
string ns_uri = null;
@@ -184,6 +198,18 @@ public class GXml.Element : GXml.Node,
return parent_node.lookup_prefix (nspace);
}
public new string? lookup_namespace_uri (string? prefix) {
+ if (prefix == "xmlns") {
+ return "http://www.w3.org/2000/xmlns/";
+ }
+ if (prefix == "xml") {
+ return "http://www.w3.org/XML/1998/namespace";
+ }
+ if (prefix == "html") {
+ return "http://www.w3.org/1999/xhtml";
+ }
+ if (prefix == "xsi") {
+ return "http://www.w3.org/2001/XMLSchema-instance/";
+ }
foreach (string k in attributes.keys) {
if (!("xmlns" in k)) continue;
var p = _attributes.get (k) as GXml.Attr;
@@ -387,7 +413,6 @@ public class GXml.Element : GXml.Node,
i++;
if (i == index) {
var ret = get (e.value);
- message ("Found %s at %ld - Val=%s - as node val = %s", e.value, i, (ret as GXml.Attr).value,
ret.node_value);
return ret;
}
}
@@ -493,10 +518,16 @@ public class GXml.Element : GXml.Node,
}
// 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;
+ if (":" in local_name) {
+ throw new DomError.INVALID_CHARACTER_ERROR (_("Invalid attribute's local name '%s': invalid use of
':' character"), local_name);
+ }
var nsp = _element.lookup_prefix (namespace_uri);
- if (nsp == null) return null;
- var v = get ((nsp+":"+local_name).down ());
+ if (nsp == null) {
+ throw new DomError.NAMESPACE_ERROR (_("Namespace URI was not found: %s"), namespace_uri);
+ }
+ string k = (nsp+":"+local_name).down ();
+ message ("Searching Node with k: %s", k);
+ var v = get (k);
return v;
}
// Introduced in DOM Level 2:
@@ -522,7 +553,8 @@ public class GXml.Element : GXml.Node,
&& (node as GXml.Attr).local_name == "xmlns")
throw new DomError.NAMESPACE_ERROR (_("Invalid namespace attribute's name."));
if ((node as GXml.Attr).prefix == "xmlns"
- || (node as GXml.Attr).local_name == "xmlns") {
+ || (node as GXml.Attr).local_name == "xmlns"
+ || (node as GXml.Attr).prefix == "xsi") {
string asp = _element.get_attribute_ns (node.node_value,
(node as GXml.Attr).local_name);
if (asp != null) return node;
@@ -546,36 +578,43 @@ public class GXml.Element : GXml.Node,
}
}
if ((node as GXml.Attr).namespace_uri != "http://www.w3.org/2000/xmlns/"
- && (node as GXml.Attr).namespace_uri != "http://www.w3.org/2000/xmlns"){
+ && (node as GXml.Attr).namespace_uri != "http://www.w3.org/2000/xmlns"
+ && (node as GXml.Attr).namespace_uri != "http://www.w3.org/2001/XMLSchema-instance/"
+ && (node as GXml.Attr).namespace_uri != "http://www.w3.org/2001/XMLSchema-instance") {
string nsn = _element.lookup_namespace_uri ((node as GXml.Attr).prefix);
string nspn = _element.lookup_prefix (nsn);
if (nspn != (node as GXml.Attr).prefix
- && nsn != (node as GXml.Attr).namespace_uri)
+ && nsn != (node as GXml.Attr).namespace_uri) {
throw new DomError.NAMESPACE_ERROR
- (_("Trying to add an attribute with an undefined namespace prefix: %s").printf ((node as
GXml.Attr).prefix));
+ (_("Trying to add an attribute with an undefined namespace's prefix: %s").printf ((node as
GXml.Attr).prefix));
+ }
nspn = _element.lookup_prefix ((node as GXml.Attr).namespace_uri);
nsn = _element.lookup_namespace_uri (nspn);
if (nspn != (node as GXml.Attr).prefix
&& nsn != (node as GXml.Attr).namespace_uri)
throw new DomError.NAMESPACE_ERROR
- (_("Trying to add an attribute with a non found namespace URI"));
+ (_("Trying to add an attribute with an undefined namespace's URI"));
}
string p = "";
if ((node as GXml.Attr).prefix != null
- && (node as GXml.Attr).prefix != "")
+ && (node as GXml.Attr).prefix != "") {
p = (node as GXml.Attr).prefix + ":";
+ }
string k = (p+(node as GXml.Attr).local_name).down ();
GXml.Attr attr = null;
- var pprop = (_element as GXml.Object).find_property_name ((node as GXml.Attr).local_name);
+ message ("Searching: %s", k);
+ var pprop = (_element as GXml.Object).find_property_name (k);
if (pprop != null) {
- (_element as GXml.Object).set_attribute ((node as GXml.Attr).local_name, node.node_value);
- attr = new GXml.Attr.reference (_element, (node as GXml.Attr).local_name);
+ (_element as GXml.Object).set_attribute (k, node.node_value);
+ attr = new GXml.Attr.reference (_element, k);
} else {
+ message ("Not found as property creating a NS Attr with key: %s", k);
attr = new GXml.Attr.namespace (_element, (node as GXml.Attr).namespace_uri, (node as
GXml.Attr).prefix, (node as GXml.Attr).local_name, node.node_value);
}
set (k, attr);
order.set (size - 1, k);
+ message ("Added: %s size: %d", k, size);
return attr;
}
private long index_of (string name) {
@@ -602,22 +641,16 @@ public class GXml.Element : GXml.Node,
return str;
}
public string? get_attribute_ns (string? namespace_uri, string local_name) {
- string nsp = null;
- if ((namespace_uri == "http://www.w3.org/2000/xmlns/"
- || namespace_uri == "http://www.w3.org/2000/xmlns")
- && local_name != "xmlns")
- nsp = "xmlns";
- else
- nsp = lookup_prefix (namespace_uri);
- string name = local_name;
- if (nsp != null)
- name = nsp + ":" + local_name;
- string val = null;
- var prop = _attributes.get (name) as GXml.Attr;
- if (prop != null) {
- val = prop.value;
+ try {
+ var a = _attributes.get_named_item_ns (namespace_uri, local_name) as GXml.Attr;
+ if (a != null) {
+ return a.value;
+ }
+ return null;
+ } catch (GLib.Error e) {
+ message (_("Error getting attribute with namespace: %s"), e.message);
}
- return val;
+ return null;
}
public void set_attribute (string name, string value) throws GLib.Error {
var a = new GXml.Attr (this, name, value);
@@ -630,28 +663,33 @@ public class GXml.Element : GXml.Node,
string n = name;
if (":" in name) {
var s = name.split (":");
- if (s.length != 2)
+ if (s.length != 2) {
throw new DomError.NAMESPACE_ERROR (_("Invalid attribute name. Just one prefix is allowed"));
+ }
p = s[0];
n = s[1];
- if (":" in n)
+ if (":" in n) {
throw new DomError.NAMESPACE_ERROR (_("Invalid attribute name. Invalid use of colon: %s"), n);
- } else {
- n = name;
+ }
}
- if (namespace_uri == null && p == "")
+ if (namespace_uri == null && p == "") {
throw new DomError.NAMESPACE_ERROR (_("Invalid namespace. If prefix is null, namespace URI should not
be null"));
- if (p == "xml" && namespace_uri != "http://www.w3.org/2000/xmlns/" && namespace_uri !=
"http://www.w3.org/2000/xmlns")
+ }
+ if (p == "xml" && namespace_uri != "http://www.w3.org/2000/xmlns/" && namespace_uri !=
"http://www.w3.org/2000/xmlns") {
throw new DomError.NAMESPACE_ERROR (_("Invalid namespace. If prefix is xml, namespace URI should be
http://www.w3.org/2000/xmlns"));
+ }
if (p == "xmlns" && namespace_uri != "http://www.w3.org/2000/xmlns/"
- && namespace_uri != "http://www.w3.org/2000/xmlns")
- throw new DomError.NAMESPACE_ERROR (_("Invalid namespace. If attribute's prefix is xmlns, namespace
URI should be http://www.w3.org/2000/xmlns"));
+ && namespace_uri != "http://www.w3.org/2000/xmlns") {
+ throw new DomError.NAMESPACE_ERROR (_("Invalid namespace. 4If attribute's prefix is xmlns, namespace
URI should be http://www.w3.org/2000/xmlns"));
+ }
if (p == "" && n == "xmlns"
&& (namespace_uri != "http://www.w3.org/2000/xmlns/"
- && namespace_uri != "http://www.w3.org/2000/xmlns"))
+ && namespace_uri != "http://www.w3.org/2000/xmlns")) {
throw new DomError.NAMESPACE_ERROR (_("Invalid namespace. If attribute's name is xmlns, namespace URI
should be http://www.w3.org/2000/xmlns"));
- if (p == "" && n != "xmlns" && n != "xml")
- throw new DomError.NAMESPACE_ERROR (_("Invalid attribute name. No prefixed attributes should use xmlns
name"));
+ }
+ if (p == "" && n != "xmlns" && n != "xml") {
+ throw new DomError.NAMESPACE_ERROR (_("Invalid attribute name. No prefixed attributes should use xml
or xmlns name"));
+ }
var a = new GXml.Attr.namespace (this, namespace_uri, p, n, value);
try { _attributes.set_named_item_ns (a); }
catch (GLib.Error e) {
diff --git a/gxml/XParser.vala b/gxml/XParser.vala
index 6c72329..e6f745a 100644
--- a/gxml/XParser.vala
+++ b/gxml/XParser.vala
@@ -338,25 +338,28 @@ public class GXml.XParser : GLib.Object, GXml.Parser {
} else {
var attrname = tr.const_local_name ();
string prefix = tr.prefix ();
+ if (prefix == null && ":" in attrname) {
+ string[] sname = attrname.split (":");
+ prefix = sname[0];
+ attrname = sname[1];
+ }
tr.read_attribute_value ();
if (tr.node_type () == Xml.ReaderType.TEXT) {
var attrval = tr.read_string ();
- bool processed = false;
string attn = attrname;
if (prefix != null) attn = prefix+":"+attrname;
- if (node is GXml.Object) {
- processed = (element as GXml.Object).set_attribute (attn, attrval);
- }
- if (!processed) {
- if (prefix != null) {
- 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);
+ if (prefix != null) {
+ message ("Name: %s : Prefix = %s", attrname, prefix);
+ string nsuri = null;
+ if (prefix == "xmlns")
+ nsuri = "http://www.w3.org/2000/xmlns/";
+ else if (prefix == "xsi")
+ nsuri = "http://www.w3.org/2001/XMLSchema-instance/";
+ else
+ nsuri = tr.lookup_namespace (prefix);
+ element.set_attribute_ns (nsuri, prefix+":"+attrname, attrval);
+ } else {
+ element.set_attribute (attrname, attrval);
}
}
}
diff --git a/test/ElementTest.vala b/test/ElementTest.vala
index b7b4ee3..8eda239 100644
--- a/test/ElementTest.vala
+++ b/test/ElementTest.vala
@@ -207,6 +207,14 @@ class GXml.ElementTest : GXmlTest {
catch (GLib.Error e) { warning ("Error: "+e.message); }
}
}
+ }
+ public class ElementType : GXml.Element {
+ [Description (nick="::type")]
+ public string ttype { get; set; }
+
+ construct {
+ initialize ("elementType");
+ }
}
public static void add_tests () {
Test.add_func ("/gxml/gom-element/read/namespace_uri", () => {
@@ -380,6 +388,7 @@ class GXml.ElementTest : GXmlTest {
assert (p.get_attribute_ns ("http://www.w3.org/2000/xmlns", "c") ==
"http://c.org/1.0");
p.read_from_string (str);
message (p.write_string ());
+ assert (p.get_attribute_ns ("http://c.org/1.0", "name") == "edumor");
assert (p.cname == "edumor");
assert (p.ingredient != null);
assert (p.ingredient.cname == "spider");
@@ -863,5 +872,25 @@ class GXml.ElementTest : GXmlTest {
assert_not_reached ();
}
});
+ Test.add_func ("/gxml/gom-element/object-attributes/attributes-no-ns-same-name", () => {
+ try {
+ string str = """<elementType type="Val1" xsi:type="Val2"
VAL3</elementType>""";
+ var n = new ElementType ();
+ n.notify["ttype"].connect (()=>{
+ message ("Moddiffied ttype = %s", n.ttype);
+ });
+ n.read_from_string (str);
+ message (n.ttype);
+ message (n.get_attribute ("type"));
+ message (n.get_attribute_ns ("http://www.w3.org/2001/XMLSchema-instance",
"type"));
+ assert (n.ttype == "Val1");
+ assert (n.get_attribute_ns ("http://www.w3.org/2001/XMLSchema-instance",
"type") == "Val2");
+ message (n.get_attribute ("type"));
+ assert (n.get_attribute ("type") == "Val1");
+ } catch (GLib.Error e) {
+ GLib.message ("Error: "+e.message);
+ assert_not_reached ();
+ }
+ });
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]