aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrett Vickers <beevik@users.noreply.github.com>2019-11-04 21:02:52 -0800
committerGitHub <noreply@github.com>2019-11-04 21:02:52 -0800
commitdcd53a58ac74b465a34228d599f14376ccdcc6ab (patch)
tree2b0732471da9af26c7e2a098b97f6fde61e55043
parent6e5cd8a302168f3c32305811f9da1d4bd858be4c (diff)
downloadgo-etree-dcd53a58ac74b465a34228d599f14376ccdcc6ab.tar.gz
Fix a bug in attribute namespaces. (#80)
Unprefixed attributes were being assigned an incorrect namespace URI. See issue https://github.com/beevik/etree/issues/79
-rw-r--r--etree.go9
-rw-r--r--etree_test.go73
2 files changed, 45 insertions, 37 deletions
diff --git a/etree.go b/etree.go
index 1311454..8a8c9bb 100644
--- a/etree.go
+++ b/etree.go
@@ -1149,10 +1149,13 @@ func (a *Attr) Element() *Element {
}
// NamespaceURI returns the XML namespace URI associated with this attribute.
-// The function returns the empty string if this attribute is part of the XML
-// default namespace.
+// The function returns the empty string if the attribute is unprefixed or
+// if the attribute is part of the XML default namespace.
func (a *Attr) NamespaceURI() string {
- return a.element.NamespaceURI()
+ if a.Space == "" {
+ return ""
+ }
+ return a.element.findLocalNamespaceURI(a.Space)
}
// writeTo serializes the attribute to the writer.
diff --git a/etree_test.go b/etree_test.go
index 6288ec7..501f4ad 100644
--- a/etree_test.go
+++ b/etree_test.go
@@ -936,12 +936,12 @@ func TestAttrParent(t *testing.T) {
func TestDefaultNamespaceURI(t *testing.T) {
s := `
-<root xmlns="http://root.example.com" a="foo">
- <child1 xmlns="http://child.example.com" a="foo">
- <grandchild1 xmlns="http://grandchild.example.com" a="foo">
+<root xmlns="https://root.example.com" xmlns:attrib="https://attrib.example.com" attrib:a="foo" b="bar">
+ <child1 xmlns="https://child.example.com" attrib:a="foo">
+ <grandchild1 xmlns="https://grandchild.example.com" a="foo">
</grandchild1>
<grandchild2 a="foo">
- <greatgrandchild1 a="foo"/>
+ <greatgrandchild1 attrib:a="foo"/>
</grandchild2>
</child1>
<child2 a="foo"/>
@@ -956,31 +956,36 @@ func TestDefaultNamespaceURI(t *testing.T) {
greatgrandchild1 := grandchild2.SelectElement("greatgrandchild1")
checkStrEq(t, doc.NamespaceURI(), "")
- checkStrEq(t, root.NamespaceURI(), "http://root.example.com")
- checkStrEq(t, child1.NamespaceURI(), "http://child.example.com")
- checkStrEq(t, child2.NamespaceURI(), "http://root.example.com")
- checkStrEq(t, grandchild1.NamespaceURI(), "http://grandchild.example.com")
- checkStrEq(t, grandchild2.NamespaceURI(), "http://child.example.com")
- checkStrEq(t, greatgrandchild1.NamespaceURI(), "http://child.example.com")
-
- checkStrEq(t, root.Attr[0].NamespaceURI(), "http://root.example.com")
- checkStrEq(t, child1.Attr[0].NamespaceURI(), "http://child.example.com")
- checkStrEq(t, child2.Attr[0].NamespaceURI(), "http://root.example.com")
- checkStrEq(t, grandchild1.Attr[0].NamespaceURI(), "http://grandchild.example.com")
- checkStrEq(t, grandchild2.Attr[0].NamespaceURI(), "http://child.example.com")
- checkStrEq(t, greatgrandchild1.Attr[0].NamespaceURI(), "http://child.example.com")
-
- f := doc.FindElements("//*[namespace-uri()='http://root.example.com']")
+ checkStrEq(t, root.NamespaceURI(), "https://root.example.com")
+ checkStrEq(t, child1.NamespaceURI(), "https://child.example.com")
+ checkStrEq(t, child2.NamespaceURI(), "https://root.example.com")
+ checkStrEq(t, grandchild1.NamespaceURI(), "https://grandchild.example.com")
+ checkStrEq(t, grandchild2.NamespaceURI(), "https://child.example.com")
+ checkStrEq(t, greatgrandchild1.NamespaceURI(), "https://child.example.com")
+
+ checkStrEq(t, root.Attr[0].NamespaceURI(), "")
+ checkStrEq(t, root.Attr[1].NamespaceURI(), "")
+ checkStrEq(t, root.Attr[2].NamespaceURI(), "https://attrib.example.com")
+ checkStrEq(t, root.Attr[3].NamespaceURI(), "")
+ checkStrEq(t, child1.Attr[0].NamespaceURI(), "")
+ checkStrEq(t, child1.Attr[1].NamespaceURI(), "https://attrib.example.com")
+ checkStrEq(t, child2.Attr[0].NamespaceURI(), "")
+ checkStrEq(t, grandchild1.Attr[0].NamespaceURI(), "")
+ checkStrEq(t, grandchild1.Attr[1].NamespaceURI(), "")
+ checkStrEq(t, grandchild2.Attr[0].NamespaceURI(), "")
+ checkStrEq(t, greatgrandchild1.Attr[0].NamespaceURI(), "https://attrib.example.com")
+
+ f := doc.FindElements("//*[namespace-uri()='https://root.example.com']")
if len(f) != 2 || f[0] != root || f[1] != child2 {
t.Error("etree: failed namespace-uri test")
}
- f = doc.FindElements("//*[namespace-uri()='http://child.example.com']")
+ f = doc.FindElements("//*[namespace-uri()='https://child.example.com']")
if len(f) != 3 || f[0] != child1 || f[1] != grandchild2 || f[2] != greatgrandchild1 {
t.Error("etree: failed namespace-uri test")
}
- f = doc.FindElements("//*[namespace-uri()='http://grandchild.example.com']")
+ f = doc.FindElements("//*[namespace-uri()='https://grandchild.example.com']")
if len(f) != 1 || f[0] != grandchild1 {
t.Error("etree: failed namespace-uri test")
}
@@ -998,9 +1003,9 @@ func TestDefaultNamespaceURI(t *testing.T) {
func TestLocalNamespaceURI(t *testing.T) {
s := `
-<a:root xmlns:a="http://root.example.com">
- <b:child1 xmlns:b="http://child.example.com">
- <c:grandchild1 xmlns:c="http://grandchild.example.com"/>
+<a:root xmlns:a="https://root.example.com">
+ <b:child1 xmlns:b="https://child.example.com">
+ <c:grandchild1 xmlns:c="https://grandchild.example.com"/>
<b:grandchild2>
<a:greatgrandchild1/>
</b:grandchild2>
@@ -1025,27 +1030,27 @@ func TestLocalNamespaceURI(t *testing.T) {
greatgrandchild1 := grandchild2.SelectElement("greatgrandchild1")
checkStrEq(t, doc.NamespaceURI(), "")
- checkStrEq(t, root.NamespaceURI(), "http://root.example.com")
- checkStrEq(t, child1.NamespaceURI(), "http://child.example.com")
- checkStrEq(t, child2.NamespaceURI(), "http://root.example.com")
+ checkStrEq(t, root.NamespaceURI(), "https://root.example.com")
+ checkStrEq(t, child1.NamespaceURI(), "https://child.example.com")
+ checkStrEq(t, child2.NamespaceURI(), "https://root.example.com")
checkStrEq(t, child3.NamespaceURI(), "")
- checkStrEq(t, grandchild1.NamespaceURI(), "http://grandchild.example.com")
- checkStrEq(t, grandchild2.NamespaceURI(), "http://child.example.com")
- checkStrEq(t, grandchild3.NamespaceURI(), "http://root.example.com")
+ checkStrEq(t, grandchild1.NamespaceURI(), "https://grandchild.example.com")
+ checkStrEq(t, grandchild2.NamespaceURI(), "https://child.example.com")
+ checkStrEq(t, grandchild3.NamespaceURI(), "https://root.example.com")
checkStrEq(t, grandchild4.NamespaceURI(), "")
- checkStrEq(t, greatgrandchild1.NamespaceURI(), "http://root.example.com")
+ checkStrEq(t, greatgrandchild1.NamespaceURI(), "https://root.example.com")
- f := doc.FindElements("//*[namespace-uri()='http://root.example.com']")
+ f := doc.FindElements("//*[namespace-uri()='https://root.example.com']")
if len(f) != 4 || f[0] != root || f[1] != child2 || f[2] != grandchild3 || f[3] != greatgrandchild1 {
t.Error("etree: failed namespace-uri test")
}
- f = doc.FindElements("//*[namespace-uri()='http://child.example.com']")
+ f = doc.FindElements("//*[namespace-uri()='https://child.example.com']")
if len(f) != 2 || f[0] != child1 || f[1] != grandchild2 {
t.Error("etree: failed namespace-uri test")
}
- f = doc.FindElements("//*[namespace-uri()='http://grandchild.example.com']")
+ f = doc.FindElements("//*[namespace-uri()='https://grandchild.example.com']")
if len(f) != 1 || f[0] != grandchild1 {
t.Error("etree: failed namespace-uri test")
}