go-pkg-xmlx/src/node.go

267 lines
5.4 KiB
Go
Raw Normal View History

package xmlx
import "xml"
import "fmt"
2009-11-23 05:15:40 +00:00
import "strconv"
const (
NT_ROOT = 0x00;
NT_DIRECTIVE = 0x01;
NT_PROCINST = 0x02;
NT_COMMENT = 0x03;
NT_ELEMENT = 0x04;
)
type Attr struct {
Name xml.Name;
Value string;
}
type Node struct {
Type byte;
Name xml.Name;
Children []*Node;
Attributes []Attr;
Parent *Node;
Value string;
// procinst field
Target string;
}
func NewNode(tid byte) *Node { return &Node{Type: tid} }
2009-11-23 05:15:40 +00:00
// Get attribute value as string
func (this *Node) GetAttr(namespace, name string) string {
for _,v := range this.Attributes {
if namespace == v.Name.Space && name == v.Name.Local {
return v.Value;
}
}
return "";
}
// Get attribute value as int
func (this *Node) GetAttri(namespace, name string) int {
s := this.GetAttr(namespace, name);
if s == "" { return 0 }
n, _ := strconv.Atoi(s);
return n;
}
// Get attribute value as uint
func (this *Node) GetAttrui(namespace, name string) uint {
s := this.GetAttr(namespace, name);
if s == "" { return 0 }
n, _ := strconv.Atoui(s);
return n;
}
// Get attribute value as uint64
func (this *Node) GetAttrui64(namespace, name string) uint64 {
s := this.GetAttr(namespace, name);
if s == "" { return 0 }
n, _ := strconv.Atoui64(s);
return n;
}
// Get attribute value as int64
func (this *Node) GetAttri64(namespace, name string) int64 {
s := this.GetAttr(namespace, name);
if s == "" { return 0 }
n, _ := strconv.Atoi64(s);
return n;
}
// Get attribute value as float
func (this *Node) GetAttrf(namespace, name string) float {
s := this.GetAttr(namespace, name);
if s == "" { return 0 }
n, _ := strconv.Atof(s);
return n;
}
// Get attribute value as float32
func (this *Node) GetAttrf32(namespace, name string) float32 {
s := this.GetAttr(namespace, name);
if s == "" { return 0 }
n, _ := strconv.Atof32(s);
return n;
}
// Get attribute value as float64
func (this *Node) GetAttrf64(namespace, name string) float64 {
s := this.GetAttr(namespace, name);
if s == "" { return 0 }
n, _ := strconv.Atof64(s);
return n;
}
// Returns true if this node has the specified attribute. False otherwise.
func (this *Node) HasAttr(namespace, name string) bool {
for _,v := range this.Attributes {
if namespace == v.Name.Space && name == v.Name.Local {
return true
}
}
return false
}
// Select single node by name
func (this *Node) SelectNode(namespace, name string) *Node {
return rec_SelectNode(this, namespace, name);
}
func rec_SelectNode(cn *Node, namespace, name string) *Node {
if cn.Name.Space == namespace && cn.Name.Local == name {
return cn;
}
for _, v := range cn.Children {
tn := rec_SelectNode(v, namespace, name);
if tn != nil { return tn }
}
return nil;
}
2009-11-23 05:15:40 +00:00
// Select multiple nodes by name
func (this *Node) SelectNodes(namespace, name string) []*Node {
list := make([]*Node, 0);
rec_SelectNodes(this, namespace, name, &list);
return list;
}
func rec_SelectNodes(cn *Node, namespace, name string, list *[]*Node) {
if cn.Name.Space == namespace && cn.Name.Local == name {
slice := make([]*Node, len(*list) + 1);
for i,v := range *list {
slice[i] = v;
}
slice[len(slice) - 1] = cn;
*list = slice;
return
}
for _, v := range cn.Children {
rec_SelectNodes(v, namespace, name, list);
}
}
2009-11-23 05:15:40 +00:00
// Convert node to appropriate string representation based on it's @Type.
// Note that NT_ROOT is a special-case empty node used as the root for a
// Document. This one has no representation by itself. It merely forwards the
// String() call to it's child nodes.
func (this *Node) String() (s string) {
switch this.Type {
case NT_PROCINST:
s = this.printProcInst()
case NT_COMMENT:
s = this.printComment()
case NT_DIRECTIVE:
s = this.printDirective()
case NT_ELEMENT:
s = this.printElement()
case NT_ROOT:
s = this.printRoot()
}
return;
}
func (this *Node) printRoot() (s string) {
for _, v := range this.Children {
s += v.String()
}
return;
}
func (this *Node) printProcInst() (s string) {
s = "<?" + this.Target + " " + this.Value + "?>";
return;
}
func (this *Node) printComment() (s string) {
s = "<!-- " + this.Value + " -->";
return;
}
func (this *Node) printDirective() (s string) {
s = "<!" + this.Value + "!>";
return;
}
func (this *Node) printElement() (s string) {
if len(this.Name.Space) > 0 {
s = "<" + this.Name.Space + ":" + this.Name.Local
} else {
s = "<" + this.Name.Local
}
for _, v := range this.Attributes {
if len(v.Name.Space) > 0 {
s += fmt.Sprintf(` %s:%s="%s"`, v.Name.Space, v.Name.Local, v.Value)
} else {
s += fmt.Sprintf(` %s="%s"`, v.Name.Local, v.Value)
}
}
if len(this.Children) == 0 && len(this.Value) == 0 {
s += " />";
return;
}
s += ">";
for _, v := range this.Children {
s += v.String()
}
s += this.Value;
if len(this.Name.Space) > 0 {
s += "</" + this.Name.Space + ":" + this.Name.Local + ">"
} else {
s += "</" + this.Name.Local + ">"
}
return;
}
2009-11-23 05:15:40 +00:00
// Add a child node
func (this *Node) AddChild(t *Node) {
if t.Parent != nil {
t.Parent.RemoveChild(t)
}
t.Parent = this;
slice := make([]*Node, len(this.Children)+1);
for i, v := range this.Children {
slice[i] = v
}
slice[len(slice)-1] = t;
this.Children = slice;
}
2009-11-23 05:15:40 +00:00
// Remove a child node
func (this *Node) RemoveChild(t *Node) {
pos := -1;
for i, v := range this.Children {
if v == t {
pos = i;
break;
}
}
if pos == -1 {
return
}
slice := make([]*Node, len(this.Children)-1);
idx := 0;
for i, v := range this.Children {
if i != pos {
slice[idx] = v;
idx++;
}
}
t.Parent = nil;
}