1package xpath 2 3import ( 4 "errors" 5) 6 7// NodeType represents a type of XPath node. 8type NodeType int 9 10const ( 11 // RootNode is a root node of the XML document or node tree. 12 RootNode NodeType = iota 13 14 // ElementNode is an element, such as <element>. 15 ElementNode 16 17 // AttributeNode is an attribute, such as id='123'. 18 AttributeNode 19 20 // TextNode is the text content of a node. 21 TextNode 22 23 // CommentNode is a comment node, such as <!-- my comment --> 24 CommentNode 25 26 // allNode is any types of node, used by xpath package only to predicate match. 27 allNode 28) 29 30// NodeNavigator provides cursor model for navigating XML data. 31type NodeNavigator interface { 32 // NodeType returns the XPathNodeType of the current node. 33 NodeType() NodeType 34 35 // LocalName gets the Name of the current node. 36 LocalName() string 37 38 // Prefix returns namespace prefix associated with the current node. 39 Prefix() string 40 41 // Value gets the value of current node. 42 Value() string 43 44 // Copy does a deep copy of the NodeNavigator and all its components. 45 Copy() NodeNavigator 46 47 // MoveToRoot moves the NodeNavigator to the root node of the current node. 48 MoveToRoot() 49 50 // MoveToParent moves the NodeNavigator to the parent node of the current node. 51 MoveToParent() bool 52 53 // MoveToNextAttribute moves the NodeNavigator to the next attribute on current node. 54 MoveToNextAttribute() bool 55 56 // MoveToChild moves the NodeNavigator to the first child node of the current node. 57 MoveToChild() bool 58 59 // MoveToFirst moves the NodeNavigator to the first sibling node of the current node. 60 MoveToFirst() bool 61 62 // MoveToNext moves the NodeNavigator to the next sibling node of the current node. 63 MoveToNext() bool 64 65 // MoveToPrevious moves the NodeNavigator to the previous sibling node of the current node. 66 MoveToPrevious() bool 67 68 // MoveTo moves the NodeNavigator to the same position as the specified NodeNavigator. 69 MoveTo(NodeNavigator) bool 70} 71 72// NodeIterator holds all matched Node object. 73type NodeIterator struct { 74 node NodeNavigator 75 query query 76} 77 78// Current returns current node which matched. 79func (t *NodeIterator) Current() NodeNavigator { 80 return t.node 81} 82 83// MoveNext moves Navigator to the next match node. 84func (t *NodeIterator) MoveNext() bool { 85 n := t.query.Select(t) 86 if n != nil { 87 if !t.node.MoveTo(n) { 88 t.node = n.Copy() 89 } 90 return true 91 } 92 return false 93} 94 95// Select selects a node set using the specified XPath expression. 96// This method is deprecated, recommend using Expr.Select() method instead. 97func Select(root NodeNavigator, expr string) *NodeIterator { 98 exp, err := Compile(expr) 99 if err != nil { 100 panic(err) 101 } 102 return exp.Select(root) 103} 104 105// Expr is an XPath expression for query. 106type Expr struct { 107 s string 108 q query 109} 110 111type iteratorFunc func() NodeNavigator 112 113func (f iteratorFunc) Current() NodeNavigator { 114 return f() 115} 116 117// Evaluate returns the result of the expression. 118// The result type of the expression is one of the follow: bool,float64,string,NodeIterator). 119func (expr *Expr) Evaluate(root NodeNavigator) interface{} { 120 val := expr.q.Evaluate(iteratorFunc(func() NodeNavigator { return root })) 121 switch val.(type) { 122 case query: 123 return &NodeIterator{query: expr.q.Clone(), node: root} 124 } 125 return val 126} 127 128// Select selects a node set using the specified XPath expression. 129func (expr *Expr) Select(root NodeNavigator) *NodeIterator { 130 return &NodeIterator{query: expr.q.Clone(), node: root} 131} 132 133// String returns XPath expression string. 134func (expr *Expr) String() string { 135 return expr.s 136} 137 138// Compile compiles an XPath expression string. 139func Compile(expr string) (*Expr, error) { 140 if expr == "" { 141 return nil, errors.New("expr expression is nil") 142 } 143 qy, err := build(expr) 144 if err != nil { 145 return nil, err 146 } 147 return &Expr{s: expr, q: qy}, nil 148} 149 150// MustCompile compiles an XPath expression string and ignored error. 151func MustCompile(expr string) *Expr { 152 exp, err := Compile(expr) 153 if err != nil { 154 return nil 155 } 156 return exp 157} 158