github.com/fluhus/gostuff@v0.4.1-0.20240331134726-be71864f2b5d/xmlnode/node.go (about) 1 package xmlnode 2 3 import ( 4 "encoding/xml" 5 ) 6 7 // DESIGN NOTE: 8 // The idea behind the somewhat clumsy interface (rather than something like 9 // the empty Token interface) is to eliminate some of the need for type checks. 10 // 11 // For example, if you need to traverse the node tree, you don't need to check 12 // if a node is a Tag node before you call its children. Or if you need to 13 // search for a specific text, you don't need to check which nodes are actually 14 // text nodes. 15 // 16 // You can, of course, check node types (returned by Type()) if you still need 17 // to. 18 19 // DESIGN NOTE (2): 20 // The Type() function is used instead of exported types to avoid cluttering 21 // the package's godoc. 22 23 // A Node represents a single XML node. Can be one of: Root, Tag, Text, Comment, 24 // ProcInst or Directive. 25 // 26 // String methods return empty strings when called on a non-relevant node. For 27 // example, calling TagName() on a Text node or vise versa. The Children() 28 // method returns nil for non Tag or Root nodes. The Attr() method returns nil 29 // for non Tag nodes. 30 // 31 // Parent node is nil only in Root. 32 type Node interface { 33 // Parent of the current node. Nil for root node. 34 Parent() Node 35 36 // Tag name of tag nodes of the form <tagname>...</tagname>. Empty for 37 // other node types. 38 TagName() string 39 40 // Attributes of tag nodes. Nil for other node types. 41 Attr() []*xml.Attr 42 43 // Child nodes of root and tag nodes. Nil for other node types. 44 Children() []Node 45 46 // Text data of text nodes. Empty for other node types. 47 Text() string 48 49 // Comment data of comments of the form <!--comment-->. Does not include the 50 // <!-- and --> markers. Empty for other node types. 51 Comment() string 52 53 // Target of processing instructions of the form <?target inst?>. 54 // Empty for other node types. 55 Target() string 56 57 // Instruction of processing instructions of the form <?target inst?>. 58 // Empty for other node types. 59 Inst() string 60 61 // Directive of the form <!directive>. Does not include the <! and > 62 // markers. Empty for other node types. 63 Directive() string 64 65 // Type of this node. Returns one of: Root, Tag, Text, Comment, ProcInst 66 // or Directive. 67 Type() int 68 } 69 70 // Represents the root node of an XML tree. Only has children, no other 71 // properties. 72 type root struct { 73 children []Node 74 } 75 76 func (n *root) Parent() Node { return nil } 77 func (n *root) TagName() string { return "" } 78 func (n *root) Attr() []*xml.Attr { return nil } 79 func (n *root) Children() []Node { return n.children } 80 func (n *root) Text() string { return "" } 81 func (n *root) Comment() string { return "" } 82 func (n *root) Target() string { return "" } 83 func (n *root) Inst() string { return "" } 84 func (n *root) Directive() string { return "" } 85 func (n *root) Type() int { return Root } 86 87 // Represents a start-end element, along with its children. 88 type tag struct { 89 parent Node 90 tagName string 91 attr []*xml.Attr 92 children []Node 93 } 94 95 func (n *tag) Parent() Node { return n.parent } 96 func (n *tag) TagName() string { return n.tagName } 97 func (n *tag) Attr() []*xml.Attr { return n.attr } 98 func (n *tag) Children() []Node { return n.children } 99 func (n *tag) Text() string { return "" } 100 func (n *tag) Comment() string { return "" } 101 func (n *tag) Target() string { return "" } 102 func (n *tag) Inst() string { return "" } 103 func (n *tag) Directive() string { return "" } 104 func (n *tag) Type() int { return Tag } 105 106 // Represents raw text data, in which XML escape sequences have been replaced 107 // by the characters they represent. 108 type text struct { 109 parent Node 110 text string 111 } 112 113 func (n *text) Parent() Node { return n.parent } 114 func (n *text) TagName() string { return "" } 115 func (n *text) Attr() []*xml.Attr { return nil } 116 func (n *text) Children() []Node { return nil } 117 func (n *text) Text() string { return n.text } 118 func (n *text) Comment() string { return "" } 119 func (n *text) Target() string { return "" } 120 func (n *text) Inst() string { return "" } 121 func (n *text) Directive() string { return "" } 122 func (n *text) Type() int { return Text } 123 124 // A Comment represents an XML comment of the form <!--comment-->. The string 125 // does not include the <!-- and --> comment markers. 126 type comment struct { 127 parent Node 128 comment string 129 } 130 131 func (n *comment) Parent() Node { return n.parent } 132 func (n *comment) TagName() string { return "" } 133 func (n *comment) Attr() []*xml.Attr { return nil } 134 func (n *comment) Children() []Node { return nil } 135 func (n *comment) Text() string { return "" } 136 func (n *comment) Comment() string { return n.comment } 137 func (n *comment) Target() string { return "" } 138 func (n *comment) Inst() string { return "" } 139 func (n *comment) Directive() string { return "" } 140 func (n *comment) Type() int { return Comment } 141 142 // Represents an XML processing instruction of the form <?target inst?>. 143 type procInst struct { 144 parent Node 145 target string 146 inst string 147 } 148 149 func (n *procInst) Parent() Node { return n.parent } 150 func (n *procInst) TagName() string { return "" } 151 func (n *procInst) Attr() []*xml.Attr { return nil } 152 func (n *procInst) Children() []Node { return nil } 153 func (n *procInst) Text() string { return "" } 154 func (n *procInst) Comment() string { return "" } 155 func (n *procInst) Target() string { return n.target } 156 func (n *procInst) Inst() string { return n.inst } 157 func (n *procInst) Directive() string { return "" } 158 func (n *procInst) Type() int { return ProcInst } 159 160 // Represents an XML directive of the form <!text>. The string does not include 161 // the <! and > markers. 162 type directive struct { 163 parent Node 164 directive string 165 } 166 167 func (n *directive) Parent() Node { return n.parent } 168 func (n *directive) TagName() string { return "" } 169 func (n *directive) Attr() []*xml.Attr { return nil } 170 func (n *directive) Children() []Node { return nil } 171 func (n *directive) Text() string { return "" } 172 func (n *directive) Comment() string { return "" } 173 func (n *directive) Target() string { return "" } 174 func (n *directive) Inst() string { return "" } 175 func (n *directive) Directive() string { return n.directive } 176 func (n *directive) Type() int { return Directive } 177 178 // Possible return values of Type(). 179 const ( 180 Root = iota 181 Tag 182 Text 183 Comment 184 ProcInst 185 Directive 186 )