diff --git a/gxml/Element.vala b/gxml/Element.vala index 2cab03fc4af11430b9f0331a987734bf8ec6a3e9..cbfdeee60e326b6b3d22b630742ce493c6212084 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 6c723295c0764438e3987c7da9fc9ac49b29ef99..e6f745a636bc470cf610ca5e589041d65af6a064 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 b7b4ee3824290cd4f8a55895b52b8add1a08483d..8eda2399013fecf726825a299a7c128e4aa2b2cd 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 = """VAL3"""; + 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 (); + } + }); } }