forked from lestrrat-go/libxml2
-
Notifications
You must be signed in to change notification settings - Fork 0
/
node_element.go
149 lines (132 loc) · 3.35 KB
/
node_element.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package dom
import (
"bytes"
"errors"
"strings"
"github.com/wayf-dk/go-libxml2/clib"
"github.com/wayf-dk/go-libxml2/types"
)
// SetNamespace sets up a new namespace on the given node.
// An XML namespace declaration is explicitly created only if
// the activate flag is enabled, and the namespace is not
// declared in a previous tree hierarchy.
func (n *Element) SetNamespace(uri, prefix string, activate ...bool) error {
activateflag := false
if len(activate) < 1 {
activateflag = true
} else {
activateflag = activate[0]
}
if uri == "" && prefix == "" {
// Empty namespace
doc, err := n.OwnerDocument()
if err != nil {
return err
}
nsptr, err := clib.XMLSearchNs(doc, n, "")
if err != nil {
return err
}
ns := wrapNamespaceNode(nsptr)
if ns.URI() != "" {
if activateflag {
clib.XMLSetNs(n, nil)
}
}
return nil
}
if uri == "" {
return errors.New("missing uri for SetNamespace")
}
if prefix == "" {
return errors.New("missing prefix for SetNamespace")
}
ns, err := clib.XMLNewNs(n, uri, prefix)
if err != nil {
return err
}
if activateflag {
if err := clib.XMLSetNs(n, wrapNamespaceNode(ns)); err != nil {
return err
}
}
return nil
}
// AppendText adds a new text node
func (n *Element) AppendText(s string) error {
return clib.XMLAppendText(n, s)
}
// SetAttribute sets an attribute
func (n *Element) SetAttribute(name, value string) error {
return clib.XMLSetProp(n, name, value)
}
// GetAttribute retrieves the value of an attribute
func (n *Element) GetAttribute(name string) (types.Attribute, error) {
attrNode, err := clib.XMLElementGetAttributeNode(n, name)
if err != nil {
return nil, err
}
return wrapAttributeNode(attrNode), nil
}
// Attributes returns a list of attributes on a node
func (n *Element) Attributes() ([]types.Attribute, error) {
attrs, err := clib.XMLElementAttributes(n)
if err != nil {
return nil, err
}
ret := make([]types.Attribute, len(attrs))
for i, attr := range attrs {
ret[i] = wrapAttributeNode(attr)
}
return ret, nil
}
// RemoveAttribute completely removes an attribute from the node
func (n *Element) RemoveAttribute(name string) error {
i := strings.IndexByte(name, ':')
if i == -1 {
return clib.XMLUnsetProp(n, name)
}
// look for the prefix
doc, err := n.OwnerDocument()
if err != nil {
return err
}
ns, err := clib.XMLSearchNs(doc, n, name[:i])
if err != nil {
return ErrAttributeNotFound
}
return clib.XMLUnsetNsProp(n, wrapNamespaceNode(ns), name)
}
// GetNamespaces returns Namespace objects associated with this
// element. WARNING: This method currently returns namespace
// objects which allocates C structures for each namespace.
// Therefore you MUST free the structures, or otherwise you
// WILL leak memory.
func (n *Element) GetNamespaces() ([]types.Namespace, error) {
list, err := clib.XMLElementNamespaces(n)
if err != nil {
return nil, err
}
ret := make([]types.Namespace, len(list))
for i, nsptr := range list {
ret[i] = wrapNamespaceNode(nsptr)
}
return ret, nil
}
// Literal returns a stringified version of this node and its
// children, inclusive.
func (n Element) Literal() (string, error) {
buf := bytes.Buffer{}
children, err := n.ChildNodes()
if err != nil {
return "", err
}
for _, c := range children {
l, err := c.Literal()
if err != nil {
return "", err
}
buf.WriteString(l)
}
return buf.String(), nil
}