1package goxpath 2 3import ( 4 "bytes" 5 "encoding/xml" 6 "io" 7 8 "github.com/ChrisTrenkamp/goxpath/tree" 9) 10 11//Marshal prints the result tree, r, in XML form to w. 12func Marshal(n tree.Node, w io.Writer) error { 13 return marshal(n, w) 14} 15 16//MarshalStr is like Marhal, but returns a string. 17func MarshalStr(n tree.Node) (string, error) { 18 ret := bytes.NewBufferString("") 19 err := marshal(n, ret) 20 21 return ret.String(), err 22} 23 24func marshal(n tree.Node, w io.Writer) error { 25 e := xml.NewEncoder(w) 26 err := encTok(n, e) 27 if err != nil { 28 return err 29 } 30 31 return e.Flush() 32} 33 34func encTok(n tree.Node, e *xml.Encoder) error { 35 switch n.GetNodeType() { 36 case tree.NtAttr: 37 return encAttr(n.GetToken().(xml.Attr), e) 38 case tree.NtElem: 39 return encEle(n.(tree.Elem), e) 40 case tree.NtNs: 41 return encNS(n.GetToken().(xml.Attr), e) 42 case tree.NtRoot: 43 for _, i := range n.(tree.Elem).GetChildren() { 44 err := encTok(i, e) 45 if err != nil { 46 return err 47 } 48 } 49 return nil 50 } 51 52 //case tree.NtChd, tree.NtComm, tree.NtPi: 53 return e.EncodeToken(n.GetToken()) 54} 55 56func encAttr(a xml.Attr, e *xml.Encoder) error { 57 str := a.Name.Local + `="` + a.Value + `"` 58 59 if a.Name.Space != "" { 60 str += ` xmlns="` + a.Name.Space + `"` 61 } 62 63 pi := xml.ProcInst{ 64 Target: "attribute", 65 Inst: ([]byte)(str), 66 } 67 68 return e.EncodeToken(pi) 69} 70 71func encNS(ns xml.Attr, e *xml.Encoder) error { 72 pi := xml.ProcInst{ 73 Target: "namespace", 74 Inst: ([]byte)(ns.Value), 75 } 76 return e.EncodeToken(pi) 77} 78 79func encEle(n tree.Elem, e *xml.Encoder) error { 80 ele := xml.StartElement{ 81 Name: n.GetToken().(xml.StartElement).Name, 82 } 83 84 attrs := n.GetAttrs() 85 ele.Attr = make([]xml.Attr, len(attrs)) 86 for i := range attrs { 87 ele.Attr[i] = attrs[i].GetToken().(xml.Attr) 88 } 89 90 err := e.EncodeToken(ele) 91 if err != nil { 92 return err 93 } 94 95 if x, ok := n.(tree.Elem); ok { 96 for _, i := range x.GetChildren() { 97 err := encTok(i, e) 98 if err != nil { 99 return err 100 } 101 } 102 } 103 104 return e.EncodeToken(ele.End()) 105} 106