194 lines
3.8 KiB
Plaintext
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++
|
||
|
|
}
|
||
|
|
}
|