package xmlUtil import ( "fmt" "goutil/xmlUtil/gxpath" "goutil/xmlUtil/gxpath/xpath" ) // xml节点查找结构(用于遍历xml节点) type xmlNodeNavigator struct { root, curr *Node attr int } // 节点类型 func (x *xmlNodeNavigator) NodeType() xpath.NodeType { switch x.curr.Type { case CommentNode: return xpath.CommentNode case TextNode: return xpath.TextNode case DeclarationNode, DocumentNode: return xpath.RootNode case ElementNode: if x.attr != -1 { return xpath.AttributeNode } return xpath.ElementNode } panic(fmt.Sprintf("unknown XML node type: %v", x.curr.Type)) } // 当前查找的节点名或属性名 func (x *xmlNodeNavigator) LocalName() string { if x.attr != -1 { return x.curr.Attr[x.attr].Name.Local } return x.curr.NodeName } // 名节点前缀 func (x *xmlNodeNavigator) Prefix() string { return x.curr.Namespace } // 节点值或属性值 func (x *xmlNodeNavigator) Value() string { switch x.curr.Type { case CommentNode: return x.curr.NodeName case ElementNode: if x.attr != -1 { return x.curr.Attr[x.attr].Value } return x.curr.InnerText() case TextNode: return x.curr.NodeName } return "" } // 创建一个拷贝对象 func (x *xmlNodeNavigator) Copy() xpath.NodeNavigator { n := *x return &n } // 移动到根节点 func (x *xmlNodeNavigator) MoveToRoot() { x.curr = x.root } // 移动到父节点 func (x *xmlNodeNavigator) MoveToParent() bool { if node := x.curr.Parent; node != nil { x.curr = node return true } return false } // 移动到下一个属性 func (x *xmlNodeNavigator) MoveToNextAttribute() bool { if x.attr >= len(x.curr.Attr)-1 { return false } x.attr++ return true } // 移动到子节点 func (x *xmlNodeNavigator) MoveToChild() bool { if node := x.curr.FirstChild; node != nil { x.curr = node return true } return false } // 移动到第一个节点 func (x *xmlNodeNavigator) MoveToFirst() bool { if x.curr.PrevSibling == nil { return false } for { node := x.curr.PrevSibling if node == nil { break } x.curr = node } return true } // 节点的值 func (x *xmlNodeNavigator) String() string { return x.Value() } // 移动到下一个兄弟节点 func (x *xmlNodeNavigator) MoveToNext() bool { if node := x.curr.NextSibling; node != nil { x.curr = node return true } return false } // 移动到上一个兄弟节点 func (x *xmlNodeNavigator) MoveToPrevious() bool { if node := x.curr.PrevSibling; node != nil { x.curr = node return true } return false } // 移动到指定节点 func (x *xmlNodeNavigator) MoveTo(other xpath.NodeNavigator) bool { node, ok := other.(*xmlNodeNavigator) if !ok || node.root != x.root { return false } x.curr = node.curr x.attr = node.attr return true } // CreateXPathNavigator creates a new xpath.NodeNavigator for the specified html.Node. func CreateXPathNavigator(top *Node) xpath.NodeNavigator { return &xmlNodeNavigator{curr: top, root: top, attr: -1} } // 按照xpath查找所有匹配的节点 // top:根节点 // expr:xpath表达式 // 返回值: // []*Node:结果 func Find(top *Node, expr string) []*Node { t := gxpath.Select(CreateXPathNavigator(top), expr) var elems []*Node for t.MoveNext() { elems = append(elems, (t.Current().(*xmlNodeNavigator)).curr) } return elems } // 按照xpath查找第一个匹配的节点 // top:根节点 // expr:xpath表达式 // 返回值: // *Node:查找到的第一个节点 func FindOne(top *Node, expr string) *Node { t := gxpath.Select(CreateXPathNavigator(top), expr) var elem *Node if t.MoveNext() { elem = (t.Current().(*xmlNodeNavigator)).curr } return elem } // FindEach searches the html.Node and calls functions cb. func FindEach(top *Node, expr string, cb func(int, *Node)) { t := gxpath.Select(CreateXPathNavigator(top), expr) var i int for t.MoveNext() { cb(i, (t.Current().(*xmlNodeNavigator)).curr) i++ } }