github.com/aarzilli/tools@v0.0.0-20151123112009-0d27094f75e0/net/http/dom/mini_go_query.go (about) 1 // Package dom supplies simple node manipulations. 2 package dom 3 4 import ( 5 "bytes" 6 "fmt" 7 "log" 8 "os" 9 "strings" 10 11 "github.com/pbberlin/tools/runtimepb" 12 "golang.org/x/net/html" 13 ) 14 15 var wpf = fmt.Fprintf 16 17 // inspired by https://github.com/PuerkitoBio/goquery/blob/master/manipulation.go 18 19 func ReplaceNode(self, dst *html.Node) { 20 InsertAfter(self, dst) 21 RemoveNode(self) 22 } 23 24 func RemoveNode(n *html.Node) { 25 par := n.Parent 26 if par != nil { 27 par.RemoveChild(n) 28 } else { 29 log.Printf("\nNode to remove has no Parent\n") 30 runtimepb.StackTrace(4) 31 } 32 } 33 34 // InsertBefore inserts before itself. 35 // node.InsertBefore refers to its children 36 func InsertBefore(insPnt, toInsert *html.Node) { 37 if insPnt.Parent != nil { 38 insPnt.Parent.InsertBefore(toInsert, insPnt) 39 } else { 40 log.Printf("\nInsertBefore - insPnt has no Parent\n") 41 runtimepb.StackTrace(4) 42 } 43 } 44 45 // InsertBefore inserts at the end, when NextSibling is null. 46 // compare http://stackoverflow.com/questions/4793604/how-to-do-insert-after-in-javascript-without-using-a-library 47 func InsertAfter(insPnt, toInsert *html.Node) { 48 if insPnt.Parent != nil { 49 insPnt.Parent.InsertBefore(toInsert, insPnt.NextSibling) 50 } else { 51 log.Printf("\nInsertAfter - insPnt has no Parent\n") 52 runtimepb.StackTrace(4) 53 } 54 } 55 56 // 57 // 58 // Deep copy a node. 59 // The new node has clones of all the original node's 60 // children but none of its parents or siblings 61 func CloneNodeWithSubtree(n *html.Node) *html.Node { 62 nn := &html.Node{ 63 Type: n.Type, 64 DataAtom: n.DataAtom, 65 Data: n.Data, 66 Attr: make([]html.Attribute, len(n.Attr)), 67 } 68 69 copy(nn.Attr, n.Attr) 70 for c := n.FirstChild; c != nil; c = c.NextSibling { 71 nn.AppendChild(CloneNodeWithSubtree(c)) // recursion 72 } 73 return nn 74 } 75 76 // 77 // 78 // Deep copy a node. 79 // no children, no parent, no siblings 80 func CloneNode(n *html.Node) *html.Node { 81 nn := &html.Node{ 82 Type: n.Type, 83 DataAtom: n.DataAtom, 84 Data: n.Data, 85 Attr: make([]html.Attribute, len(n.Attr)), 86 } 87 copy(nn.Attr, n.Attr) 88 return nn 89 } 90 91 // 92 func PrintSubtree(n *html.Node) *bytes.Buffer { 93 b := new(bytes.Buffer) 94 return printSubtree(n, b, 0) 95 } 96 func printSubtree(n *html.Node, b *bytes.Buffer, lvl int) *bytes.Buffer { 97 98 if lvl > 40 { 99 log.Printf("%s", b.String()) 100 log.Printf("possible circular relationship\n") 101 os.Exit(1) 102 } 103 104 ind := strings.Repeat(" ", lvl) 105 slvl := fmt.Sprintf("%sL%v", ind, lvl) 106 wpf(b, "%-10v %v", slvl, NodeTypeStr(n.Type)) 107 wpf(b, " %v\n", strings.TrimSpace(n.Data)) 108 109 for c := n.FirstChild; c != nil; c = c.NextSibling { 110 printSubtree(c, b, lvl+1) // recursion 111 } 112 113 return b 114 } 115 116 func Nd(ntype string, content ...string) *html.Node { 117 118 nd0 := new(html.Node) 119 120 if ntype == "text" { 121 nd0.Type = html.TextNode 122 if len(content) > 0 { 123 nd0.Data = content[0] 124 } 125 } else { 126 nd0.Type = html.ElementNode 127 nd0.Data = ntype 128 if len(content) > 0 { 129 runtimepb.StackTrace(4) 130 log.Printf("Element nodes can't have content") 131 } 132 } 133 134 return nd0 135 136 }