Update xpath dependency (#507)

This commit is contained in:
WithoutPants
2020-04-30 08:32:33 +10:00
committed by GitHub
parent 3d22d5a742
commit 2166caf322
288 changed files with 34566 additions and 82048 deletions

View File

@@ -134,42 +134,64 @@ func roundFunc(q query, t iterator) interface{} {
}
// nameFunc is a XPath functions name([node-set]).
func nameFunc(q query, t iterator) interface{} {
v := q.Select(t)
if v == nil {
return ""
func nameFunc(arg query) func(query, iterator) interface{} {
return func(q query, t iterator) interface{} {
var v NodeNavigator
if arg == nil {
v = t.Current()
} else {
v = arg.Select(t)
if v == nil {
return ""
}
}
ns := v.Prefix()
if ns == "" {
return v.LocalName()
}
return ns + ":" + v.LocalName()
}
ns := v.Prefix()
if ns == "" {
return v.LocalName()
}
return ns + ":" + v.LocalName()
}
// localNameFunc is a XPath functions local-name([node-set]).
func localNameFunc(q query, t iterator) interface{} {
v := q.Select(t)
if v == nil {
return ""
func localNameFunc(arg query) func(query, iterator) interface{} {
return func(q query, t iterator) interface{} {
var v NodeNavigator
if arg == nil {
v = t.Current()
} else {
v = arg.Select(t)
if v == nil {
return ""
}
}
return v.LocalName()
}
return v.LocalName()
}
// namespaceFunc is a XPath functions namespace-uri([node-set]).
func namespaceFunc(q query, t iterator) interface{} {
v := q.Select(t)
if v == nil {
return ""
func namespaceFunc(arg query) func(query, iterator) interface{} {
return func(q query, t iterator) interface{} {
var v NodeNavigator
if arg == nil {
v = t.Current()
} else {
// Get the first node in the node-set if specified.
v = arg.Select(t)
if v == nil {
return ""
}
}
// fix about namespace-uri() bug: https://github.com/antchfx/xmlquery/issues/22
// TODO: In the next version, add NamespaceURL() to the NodeNavigator interface.
type namespaceURL interface {
NamespaceURL() string
}
if f, ok := v.(namespaceURL); ok {
return f.NamespaceURL()
}
return v.Prefix()
}
// fix about namespace-uri() bug: https://github.com/antchfx/xmlquery/issues/22
// TODO: In the next version, add NamespaceURL() to the NodeNavigator interface.
type namespaceURL interface {
NamespaceURL() string
}
if f, ok := v.(namespaceURL); ok {
return f.NamespaceURL()
}
return v.Prefix()
}
func asBool(t iterator, v interface{}) bool {
@@ -240,7 +262,7 @@ func startwithFunc(arg1, arg2 query) func(query, iterator) interface{} {
m, n string
ok bool
)
switch typ := arg1.Evaluate(t).(type) {
switch typ := functionArgs(arg1).Evaluate(t).(type) {
case string:
m = typ
case query:
@@ -252,7 +274,7 @@ func startwithFunc(arg1, arg2 query) func(query, iterator) interface{} {
default:
panic(errors.New("starts-with() function argument type must be string"))
}
n, ok = arg2.Evaluate(t).(string)
n, ok = functionArgs(arg2).Evaluate(t).(string)
if !ok {
panic(errors.New("starts-with() function argument type must be string"))
}
@@ -267,7 +289,7 @@ func endwithFunc(arg1, arg2 query) func(query, iterator) interface{} {
m, n string
ok bool
)
switch typ := arg1.Evaluate(t).(type) {
switch typ := functionArgs(arg1).Evaluate(t).(type) {
case string:
m = typ
case query:
@@ -279,7 +301,7 @@ func endwithFunc(arg1, arg2 query) func(query, iterator) interface{} {
default:
panic(errors.New("ends-with() function argument type must be string"))
}
n, ok = arg2.Evaluate(t).(string)
n, ok = functionArgs(arg2).Evaluate(t).(string)
if !ok {
panic(errors.New("ends-with() function argument type must be string"))
}
@@ -294,8 +316,7 @@ func containsFunc(arg1, arg2 query) func(query, iterator) interface{} {
m, n string
ok bool
)
switch typ := arg1.Evaluate(t).(type) {
switch typ := functionArgs(arg1).Evaluate(t).(type) {
case string:
m = typ
case query:
@@ -308,7 +329,7 @@ func containsFunc(arg1, arg2 query) func(query, iterator) interface{} {
panic(errors.New("contains() function argument type must be string"))
}
n, ok = arg2.Evaluate(t).(string)
n, ok = functionArgs(arg2).Evaluate(t).(string)
if !ok {
panic(errors.New("contains() function argument type must be string"))
}
@@ -345,7 +366,7 @@ func normalizespaceFunc(q query, t iterator) interface{} {
func substringFunc(arg1, arg2, arg3 query) func(query, iterator) interface{} {
return func(q query, t iterator) interface{} {
var m string
switch typ := arg1.Evaluate(t).(type) {
switch typ := functionArgs(arg1).Evaluate(t).(type) {
case string:
m = typ
case query:
@@ -359,14 +380,14 @@ func substringFunc(arg1, arg2, arg3 query) func(query, iterator) interface{} {
var start, length float64
var ok bool
if start, ok = arg2.Evaluate(t).(float64); !ok {
if start, ok = functionArgs(arg2).Evaluate(t).(float64); !ok {
panic(errors.New("substring() function first argument type must be int"))
} else if start < 1 {
panic(errors.New("substring() function first argument type must be >= 1"))
}
start--
if arg3 != nil {
if length, ok = arg3.Evaluate(t).(float64); !ok {
if length, ok = functionArgs(arg3).Evaluate(t).(float64); !ok {
panic(errors.New("substring() function second argument type must be int"))
}
}
@@ -384,7 +405,7 @@ func substringFunc(arg1, arg2, arg3 query) func(query, iterator) interface{} {
func substringIndFunc(arg1, arg2 query, after bool) func(query, iterator) interface{} {
return func(q query, t iterator) interface{} {
var str string
switch v := arg1.Evaluate(t).(type) {
switch v := functionArgs(arg1).Evaluate(t).(type) {
case string:
str = v
case query:
@@ -395,7 +416,7 @@ func substringIndFunc(arg1, arg2 query, after bool) func(query, iterator) interf
str = node.Value()
}
var word string
switch v := arg2.Evaluate(t).(type) {
switch v := functionArgs(arg2).Evaluate(t).(type) {
case string:
word = v
case query:
@@ -424,7 +445,7 @@ func substringIndFunc(arg1, arg2 query, after bool) func(query, iterator) interf
// equal to the number of characters in a given string.
func stringLengthFunc(arg1 query) func(query, iterator) interface{} {
return func(q query, t iterator) interface{} {
switch v := arg1.Evaluate(t).(type) {
switch v := functionArgs(arg1).Evaluate(t).(type) {
case string:
return float64(len(v))
case query:
@@ -441,9 +462,9 @@ func stringLengthFunc(arg1 query) func(query, iterator) interface{} {
// translateFunc is XPath functions translate() function returns a replaced string.
func translateFunc(arg1, arg2, arg3 query) func(query, iterator) interface{} {
return func(q query, t iterator) interface{} {
str := asString(t, arg1.Evaluate(t))
src := asString(t, arg2.Evaluate(t))
dst := asString(t, arg3.Evaluate(t))
str := asString(t, functionArgs(arg1).Evaluate(t))
src := asString(t, functionArgs(arg2).Evaluate(t))
dst := asString(t, functionArgs(arg3).Evaluate(t))
var replace []string
for i, s := range src {
@@ -457,6 +478,17 @@ func translateFunc(arg1, arg2, arg3 query) func(query, iterator) interface{} {
}
}
// replaceFunc is XPath functions replace() function returns a replaced string.
func replaceFunc(arg1, arg2, arg3 query) func(query, iterator) interface{} {
return func(q query, t iterator) interface{} {
str := asString(t, functionArgs(arg1).Evaluate(t))
src := asString(t, functionArgs(arg2).Evaluate(t))
dst := asString(t, functionArgs(arg3).Evaluate(t))
return strings.Replace(str, src, dst, -1)
}
}
// notFunc is XPATH functions not(expression) function operation.
func notFunc(q query, t iterator) interface{} {
switch v := q.Evaluate(t).(type) {
@@ -477,6 +509,7 @@ func concatFunc(args ...query) func(query, iterator) interface{} {
return func(q query, t iterator) interface{} {
var a []string
for _, v := range args {
v = functionArgs(v)
switch v := v.Evaluate(t).(type) {
case string:
a = append(a, v)
@@ -490,3 +523,31 @@ func concatFunc(args ...query) func(query, iterator) interface{} {
return strings.Join(a, "")
}
}
// https://github.com/antchfx/xpath/issues/43
func functionArgs(q query) query {
if _, ok := q.(*functionQuery); ok {
return q
}
return q.Clone()
}
func reverseFunc(q query, t iterator) func() NodeNavigator {
var list []NodeNavigator
for {
node := q.Select(t)
if node == nil {
break
}
list = append(list, node.Copy())
}
i := len(list)
return func() NodeNavigator {
if i <= 0 {
return nil
}
i--
node := list[i]
return node
}
}