103 lines
2.6 KiB
Go
103 lines
2.6 KiB
Go
package xpath
|
|
|
|
import (
|
|
"reflect"
|
|
"strconv"
|
|
"strings"
|
|
|
|
path "github.com/antchfx/xpath"
|
|
"github.com/srebhan/cborquery"
|
|
)
|
|
|
|
type cborDocument struct{}
|
|
|
|
func (*cborDocument) Parse(buf []byte) (dataNode, error) {
|
|
return cborquery.Parse(strings.NewReader(string(buf)))
|
|
}
|
|
|
|
func (*cborDocument) QueryAll(node dataNode, expr string) ([]dataNode, error) {
|
|
// If this panics it's a programming error as we changed the document type while processing
|
|
native, err := cborquery.QueryAll(node.(*cborquery.Node), expr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
nodes := make([]dataNode, 0, len(native))
|
|
for _, n := range native {
|
|
nodes = append(nodes, n)
|
|
}
|
|
return nodes, nil
|
|
}
|
|
|
|
func (*cborDocument) CreateXPathNavigator(node dataNode) path.NodeNavigator {
|
|
// If this panics it's a programming error as we changed the document type while processing
|
|
return cborquery.CreateXPathNavigator(node.(*cborquery.Node))
|
|
}
|
|
|
|
func (d *cborDocument) GetNodePath(node, relativeTo dataNode, sep string) string {
|
|
names := make([]string, 0)
|
|
|
|
// If these panic it's a programming error as we changed the document type while processing
|
|
nativeNode := node.(*cborquery.Node)
|
|
nativeRelativeTo := relativeTo.(*cborquery.Node)
|
|
|
|
// Climb up the tree and collect the node names
|
|
n := nativeNode.Parent
|
|
for n != nil && n != nativeRelativeTo {
|
|
nodeName := d.GetNodeName(n, sep, false)
|
|
names = append(names, nodeName)
|
|
n = n.Parent
|
|
}
|
|
|
|
if len(names) < 1 {
|
|
return ""
|
|
}
|
|
|
|
// Construct the nodes
|
|
nodepath := ""
|
|
for _, name := range names {
|
|
nodepath = name + sep + nodepath
|
|
}
|
|
|
|
return nodepath[:len(nodepath)-1]
|
|
}
|
|
|
|
func (d *cborDocument) GetNodeName(node dataNode, sep string, withParent bool) string {
|
|
// If this panics it's a programming error as we changed the document type while processing
|
|
nativeNode := node.(*cborquery.Node)
|
|
|
|
name := nativeNode.Name
|
|
|
|
// Check if the node is part of an array. If so, determine the index and
|
|
// concatenate the parent name and the index.
|
|
kind := reflect.Invalid
|
|
if nativeNode.Parent != nil && nativeNode.Parent.Value() != nil {
|
|
kind = reflect.TypeOf(nativeNode.Parent.Value()).Kind()
|
|
}
|
|
|
|
switch kind {
|
|
case reflect.Slice, reflect.Array:
|
|
// Determine the index for array elements
|
|
if name == "" && nativeNode.Parent != nil && withParent {
|
|
name = nativeNode.Parent.Name + sep
|
|
}
|
|
return name + d.index(nativeNode)
|
|
}
|
|
|
|
return name
|
|
}
|
|
|
|
func (*cborDocument) OutputXML(node dataNode) string {
|
|
native := node.(*cborquery.Node)
|
|
return native.OutputXML()
|
|
}
|
|
|
|
func (*cborDocument) index(node *cborquery.Node) string {
|
|
idx := 0
|
|
|
|
for n := node; n.PrevSibling != nil; n = n.PrevSibling {
|
|
idx++
|
|
}
|
|
|
|
return strconv.Itoa(idx)
|
|
}
|