package dom
import (
"encoding/xml"
"fmt"
"bytes"
)
type Attr struct {
Name xml .Name
Value string
}
type Element struct {
name xml .Name
children []*Element
parent *Element
content string
attributes []*Attr
namespaces []*Namespace
document *Document
}
func CreateElement (n string ) *Element {
element := &Element { name : xml .Name { Local : n } }
element .children = make ([]*Element , 0 , 5 )
element .attributes = make ([]*Attr , 0 , 10 )
element .namespaces = make ([]*Namespace , 0 , 10 )
return element
}
func (node *Element ) AddChild (child *Element ) *Element {
if child .parent != nil {
child .parent .RemoveChild (child )
}
child .SetParent (node )
node .children = append (node .children , child )
return node
}
func (node *Element ) RemoveChild (child *Element ) *Element {
p := -1
for i , v := range node .children {
if v == child {
p = i
break
}
}
if p == -1 {
return node
}
copy (node .children [p :], node .children [p +1 :])
node .children = node .children [0 : len (node .children )-1 ]
child .parent = nil
return node
}
func (node *Element ) SetAttr (name string , value string ) *Element {
attr := &Attr { Name : xml .Name { Local : name }, Value : value }
node .attributes = append (node .attributes , attr )
return node
}
func (node *Element ) SetParent (parent *Element ) *Element {
node .parent = parent
return node
}
func (node *Element ) SetContent (content string ) *Element {
node .content = content
return node
}
func (node *Element ) DeclareNamespace (ns Namespace ) *Element {
prefix := node .namespacePrefix (ns .Uri )
if prefix == ns .Prefix {
return node
}
node .namespaces = append (node .namespaces , &ns )
return node
}
func (node *Element ) DeclaredNamespaces () []*Namespace {
return node .namespaces
}
func (node *Element ) SetNamespace (prefix string , uri string ) {
resolved := node .namespacePrefix (uri )
if resolved == "" {
node .namespaces = append (node .namespaces , &Namespace { Prefix : prefix , Uri : uri })
}
node .name .Space = uri
}
func (node *Element ) Bytes (out *bytes .Buffer , indent bool , indentType string , level int ) {
empty := len (node .children ) == 0 && node .content == ""
content := node .content != ""
indentStr := ""
nextLine := ""
if indent {
nextLine = "\n"
for i := 0 ; i < level ; i ++ {
indentStr += indentType
}
}
if node .name .Local != "" {
if len (node .name .Space ) > 0 {
prefix := node .namespacePrefix (node .name .Space )
fmt .Fprintf (out , "%s<%s:%s" , indentStr , prefix , node .name .Local )
} else {
fmt .Fprintf (out , "%s<%s" , indentStr , node .name .Local )
}
}
for _ , v := range node .namespaces {
prefix := node .namespacePrefix (v .Uri )
fmt .Fprintf (out , ` xmlns:%s="%s"` , prefix , v .Uri )
}
for _ , v := range node .attributes {
if len (v .Name .Space ) > 0 {
prefix := node .namespacePrefix (v .Name .Space )
fmt .Fprintf (out , ` %s:%s="%s"` , prefix , v .Name .Local , v .Value )
} else {
fmt .Fprintf (out , ` %s="%s"` , v .Name .Local , v .Value )
}
}
if empty {
fmt .Fprintf (out , "/>%s" , nextLine )
} else {
if content {
out .WriteRune ('>' )
} else {
fmt .Fprintf (out , ">%s" , nextLine )
}
}
if len (node .children ) > 0 {
for _ , child := range node .children {
child .Bytes (out , indent , indentType , level + 1 )
}
} else if node .content != "" {
out .WriteString (node .content )
}
if !empty && len (node .name .Local ) > 0 {
var indentation string
if content {
indentation = ""
} else {
indentation = indentStr
}
if len (node .name .Space ) > 0 {
prefix := node .namespacePrefix (node .name .Space )
fmt .Fprintf (out , "%s</%s:%s>\n" , indentation , prefix , node .name .Local )
} else {
fmt .Fprintf (out , "%s</%s>\n" , indentation , node .name .Local )
}
}
}
func (node *Element ) namespacePrefix (uri string ) string {
for _ , ns := range node .namespaces {
if ns .Uri == uri {
return ns .Prefix
}
}
if node .parent == nil {
return ""
}
return node .parent .namespacePrefix (uri )
}
func (node *Element ) String () string {
var b bytes .Buffer
node .Bytes (&b , false , "" , 0 )
return string (b .Bytes ())
}
The pages are generated with Golds v0.6.7 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds .