Skip to content

Commit 80713ac

Browse files
Made namespace prefix handling for some common xml attributes such as xml, xmlns, xsi, xlink
1 parent 8e8daf3 commit 80713ac

File tree

4 files changed

+155
-12
lines changed

4 files changed

+155
-12
lines changed

dom.go

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,17 @@ import (
1010
"strings"
1111
)
1212

13+
const (
14+
xmlPrefix = "xml"
15+
xmlUrl = "http://www.w3.org/XML/1998/namespace"
16+
xmlnsPrefix = "xmlns"
17+
xmlnsUrl = "http://www.w3.org/2000/xmlns"
18+
xlinkPrefix = "xlink"
19+
xlinkUrl = "http://www.w3.org/1999/xlink"
20+
xsiPrefix = "xsi"
21+
xsiUrl = "http://www.w3.org/2001/XMLSchema-instance"
22+
)
23+
1324
func Must(doc *Document, err error) *Document {
1425
if err != nil {
1526
panic(err)
@@ -49,9 +60,23 @@ func Parse(r io.Reader) (*Document, error) {
4960
el.Parent = e
5061
el.Name = token.Name.Local
5162
for _, attr := range token.Attr {
52-
name := attr.Name.Local
63+
var name, ns string
5364
if attr.Name.Space != "" {
54-
name = fmt.Sprintf("%s:%s", attr.Name.Space, attr.Name.Local)
65+
ns = attr.Name.Space
66+
switch ns {
67+
case xmlnsUrl:
68+
name = fmt.Sprintf("%s:%s", xmlnsPrefix, attr.Name.Local)
69+
case xmlUrl:
70+
name = fmt.Sprintf("%s:%s", xmlPrefix, attr.Name.Local)
71+
case xlinkUrl:
72+
name = fmt.Sprintf("%s:%s", xlinkPrefix, attr.Name.Local)
73+
case xsiUrl:
74+
name = fmt.Sprintf("%s:%s", xsiPrefix, attr.Name.Local)
75+
default:
76+
name = fmt.Sprintf("%s:%s", attr.Name.Space, attr.Name.Local)
77+
}
78+
} else {
79+
name = attr.Name.Local
5580
}
5681
el.Attributes = append(el.Attributes, &Attribute{
5782
Name: name,

dom_test.go

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package xmldom
2+
3+
import (
4+
"strings"
5+
"testing"
6+
)
7+
8+
func TestParseNamespaces(t *testing.T) {
9+
testCases := []struct {
10+
inputXML string
11+
expectedAttr map[string]string
12+
}{
13+
{
14+
inputXML: `<root xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="https://github.com/subchen/go-xmldom"></root>`,
15+
expectedAttr: map[string]string{
16+
"xmlns:xlink": "http://www.w3.org/1999/xlink",
17+
"xlink:href": "https://github.com/subchen/go-xmldom",
18+
},
19+
},
20+
{
21+
inputXML: `<root xml:lang="en" xsi:type="string" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"></root>`,
22+
expectedAttr: map[string]string{
23+
"xml:lang": "en",
24+
"xsi:type": "string",
25+
"xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
26+
},
27+
},
28+
}
29+
30+
for _, testCase := range testCases {
31+
r := strings.NewReader(testCase.inputXML)
32+
doc, err := Parse(r)
33+
if err != nil {
34+
t.Fatalf("Unexpected error: %v", err)
35+
}
36+
37+
root := doc.Root
38+
attributes := root.Attributes
39+
40+
attrMap := make(map[string]string)
41+
for _, attr := range attributes {
42+
attrMap[attr.Name] = attr.Value
43+
}
44+
45+
for expectedName, expectedValue := range testCase.expectedAttr {
46+
if value, exists := attrMap[expectedName]; !exists {
47+
t.Errorf("Attribute %s was expected but not found", expectedName)
48+
} else if value != expectedValue {
49+
t.Errorf("Attribute %s has unexpected value. Got: %s, Want: %s", expectedName, value, expectedValue)
50+
}
51+
}
52+
}
53+
}
54+
55+
func TestSvgParse(t *testing.T) {
56+
root := Must(ParseFile("test.svg")).Root
57+
58+
imagesNodes := root.FindByName("image")
59+
if len(imagesNodes) < 4 {
60+
t.Fatalf("No images")
61+
}
62+
}
63+
64+
func TestSvgAttrNamespace(t *testing.T) {
65+
root := Must(ParseFile("test.svg")).Root
66+
uses := root.FindByName("use")
67+
68+
var contains bool
69+
for _, a := range root.Attributes {
70+
if a.Name == "xmlns:xlink" {
71+
contains = true
72+
}
73+
}
74+
75+
if !contains {
76+
t.Fatalf("Expect root to contain xmlns:xlink attribute")
77+
}
78+
79+
for _, u := range uses {
80+
for _, a := range u.Attributes {
81+
if a.Name != "xlink:href" {
82+
t.Fatalf("Expect use tag to contain xlink:href attribute but got %s", a.Name)
83+
}
84+
}
85+
}
86+
}

example_test.go

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package xmldom_test
22

33
import (
44
"fmt"
5-
"testing"
65

76
"github.com/subchen/go-xmldom"
87
)
@@ -155,12 +154,3 @@ func ExampleNewDocument() {
155154
// </testsuite>
156155
// </testsuites>
157156
}
158-
159-
func TestAttrNamespace(t *testing.T) {
160-
root := xmldom.Must(xmldom.ParseXML(ExampleXml)).Root
161-
node := root.FindByID("AttrNamespace")
162-
163-
if node.Attributes[0].Name != "xmlns:test" {
164-
t.Fatalf("Expected attribute name to be xmlns:test, got=%s", node.Attributes[0].Name)
165-
}
166-
}

0 commit comments

Comments
 (0)