goProject/.svn/pristine/9c/9c35576ff44b8980211e15c08927f4fca761e72d.svn-base
2025-01-06 16:21:36 +08:00

194 lines
3.8 KiB
Plaintext

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++
}
}