Skip to content

Commit 2bc30ca

Browse files
committed
Various bug fixes
1 parent b66f166 commit 2bc30ca

File tree

7 files changed

+331
-62
lines changed

7 files changed

+331
-62
lines changed

function.go

Lines changed: 73 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -962,6 +962,74 @@ func fnFormatNumber(ctx *Context, args []Sequence) (Sequence, error) {
962962
return Sequence{result.String()}, nil
963963
}
964964

965+
func fnFormatInteger(ctx *Context, args []Sequence) (Sequence, error) {
966+
if len(args[0]) == 0 {
967+
return Sequence{""}, nil
968+
}
969+
num, err := NumberValue(args[0])
970+
if err != nil {
971+
return nil, err
972+
}
973+
picture, err := StringValue(args[1])
974+
if err != nil {
975+
return nil, err
976+
}
977+
intVal := int(num)
978+
979+
switch {
980+
case picture == "A":
981+
return Sequence{formatIntegerAlpha(intVal, 'A')}, nil
982+
case picture == "a":
983+
return Sequence{formatIntegerAlpha(intVal, 'a')}, nil
984+
case picture == "I":
985+
return Sequence{formatRoman(intVal, true)}, nil
986+
case picture == "i":
987+
return Sequence{formatRoman(intVal, false)}, nil
988+
default:
989+
// Decimal picture: count digits to determine minimum width.
990+
width := len(picture)
991+
for _, r := range picture {
992+
if r != '0' && r != '#' {
993+
// Not a simple decimal picture, fall back to plain number.
994+
return Sequence{fmt.Sprintf("%d", intVal)}, nil
995+
}
996+
}
997+
return Sequence{fmt.Sprintf("%0*d", width, intVal)}, nil
998+
}
999+
}
1000+
1001+
func formatIntegerAlpha(n int, base rune) string {
1002+
if n <= 0 {
1003+
return fmt.Sprintf("%d", n)
1004+
}
1005+
var result []rune
1006+
for n > 0 {
1007+
n--
1008+
result = append([]rune{rune(int(base) + n%26)}, result...)
1009+
n /= 26
1010+
}
1011+
return string(result)
1012+
}
1013+
1014+
func formatRoman(n int, upper bool) string {
1015+
if n <= 0 || n >= 4000 {
1016+
return fmt.Sprintf("%d", n)
1017+
}
1018+
vals := []int{1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}
1019+
syms := []string{"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"}
1020+
var sb strings.Builder
1021+
for i, v := range vals {
1022+
for n >= v {
1023+
sb.WriteString(syms[i])
1024+
n -= v
1025+
}
1026+
}
1027+
if upper {
1028+
return sb.String()
1029+
}
1030+
return strings.ToLower(sb.String())
1031+
}
1032+
9651033
func fnHoursFromTime(ctx *Context, args []Sequence) (Sequence, error) {
9661034
firstarg := args[0]
9671035
if len(firstarg) != 1 {
@@ -1389,13 +1457,10 @@ func fnNormalizeSpace(ctx *Context, args []Sequence) (Sequence, error) {
13891457
if len(arg) > 1 {
13901458
return nil, fmt.Errorf("The cardinality of first argument of fn:normalize-string() is zero or one; supplied value has cardinality more than one")
13911459
}
1392-
itm := arg[0]
1393-
if str, ok := itm.(string); ok {
1394-
str = multipleWSRegexp.ReplaceAllString(str, " ")
1395-
str = strings.TrimSpace(str)
1396-
return Sequence{str}, nil
1397-
}
1398-
return Sequence{}, nil
1460+
str := itemStringvalue(arg[0])
1461+
str = multipleWSRegexp.ReplaceAllString(str, " ")
1462+
str = strings.TrimSpace(str)
1463+
return Sequence{str}, nil
13991464
}
14001465

14011466
func fnName(ctx *Context, args []Sequence) (Sequence, error) {
@@ -1962,30 +2027,6 @@ func fnSort(ctx *Context, args []Sequence) (Sequence, error) {
19622027
return result, nil
19632028
}
19642029

1965-
func fnCurrentGroupingKey(ctx *Context, args []Sequence) (Sequence, error) {
1966-
if ctx.Store == nil {
1967-
return Sequence{""}, nil
1968-
}
1969-
if key, ok := ctx.Store["current-grouping-key"]; ok {
1970-
if s, ok := key.(string); ok {
1971-
return Sequence{s}, nil
1972-
}
1973-
}
1974-
return Sequence{""}, nil
1975-
}
1976-
1977-
func fnCurrentGroup(ctx *Context, args []Sequence) (Sequence, error) {
1978-
if ctx.Store == nil {
1979-
return Sequence{}, nil
1980-
}
1981-
if group, ok := ctx.Store["current-group"]; ok {
1982-
if seq, ok := group.(Sequence); ok {
1983-
return seq, nil
1984-
}
1985-
}
1986-
return Sequence{}, nil
1987-
}
1988-
19892030
func init() {
19902031
multipleWSRegexp = regexp.MustCompile(`\s+`)
19912032
RegisterFunction(&Function{Name: "abs", Namespace: nsFN, F: fnAbs, MinArg: 1, MaxArg: 1})
@@ -2004,8 +2045,6 @@ func init() {
20042045
RegisterFunction(&Function{Name: "current-date", Namespace: nsFN, F: fnCurrentDate, MinArg: 0, MaxArg: 0})
20052046
RegisterFunction(&Function{Name: "current-dateTime", Namespace: nsFN, F: fnCurrentDateTime, MinArg: 0, MaxArg: 0})
20062047
RegisterFunction(&Function{Name: "current-time", Namespace: nsFN, F: fnCurrentTime, MinArg: 0, MaxArg: 0})
2007-
RegisterFunction(&Function{Name: "current-group", Namespace: nsFN, F: fnCurrentGroup, MinArg: 0, MaxArg: 0})
2008-
RegisterFunction(&Function{Name: "current-grouping-key", Namespace: nsFN, F: fnCurrentGroupingKey, MinArg: 0, MaxArg: 0})
20092048
RegisterFunction(&Function{Name: "data", Namespace: nsFN, F: fnData, MinArg: 1, MaxArg: 1})
20102049
RegisterFunction(&Function{Name: "deep-equal", Namespace: nsFN, F: fnDeepEqual, MinArg: 2, MaxArg: 3})
20112050
RegisterFunction(&Function{Name: "distinct-values", Namespace: nsFN, F: fnDistinctValues, MinArg: 1, MaxArg: 2})
@@ -2020,6 +2059,7 @@ func init() {
20202059
RegisterFunction(&Function{Name: "false", Namespace: nsFN, F: fnFalse})
20212060
RegisterFunction(&Function{Name: "floor", Namespace: nsFN, F: fnFloor, MinArg: 1, MaxArg: 1})
20222061
RegisterFunction(&Function{Name: "format-date", Namespace: nsFN, F: fnFormatDate, MinArg: 2, MaxArg: 5})
2062+
RegisterFunction(&Function{Name: "format-integer", Namespace: nsFN, F: fnFormatInteger, MinArg: 2, MaxArg: 3})
20232063
RegisterFunction(&Function{Name: "format-number", Namespace: nsFN, F: fnFormatNumber, MinArg: 2, MaxArg: 3})
20242064
RegisterFunction(&Function{Name: "day-from-date", Namespace: nsFN, F: fnDayFromDate, MinArg: 1, MaxArg: 1})
20252065
RegisterFunction(&Function{Name: "day-from-dateTime", Namespace: nsFN, F: fnDayFromDateTime, MinArg: 1, MaxArg: 1})

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
module github.com/speedata/goxpath
22

33
require (
4-
github.com/speedata/goxml v1.0.6
4+
github.com/speedata/goxml v1.0.7
55
golang.org/x/net v0.48.0
66
golang.org/x/text v0.32.0
77
)

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
github.com/speedata/goxml v1.0.6 h1:+lADGwSGmBCQJH7S/Jyh20o84/bZvctUohwfiEoIqjY=
2-
github.com/speedata/goxml v1.0.6/go.mod h1:G++cv0h2rC8ltAhvQmANDgwMbKRd3MetXlF8PLob6dw=
1+
github.com/speedata/goxml v1.0.7 h1:4X6VQoHGlg34YHku2tSb2OpcuJ2hCYBls4boTCTZXuQ=
2+
github.com/speedata/goxml v1.0.7/go.mod h1:G++cv0h2rC8ltAhvQmANDgwMbKRd3MetXlF8PLob6dw=
33
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
44
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
55
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=

map_array_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,3 +229,35 @@ func TestArrayConstructorWithVariables(t *testing.T) {
229229
t.Errorf("got %v, want [2]", seq)
230230
}
231231
}
232+
233+
func TestMapLookupSyntax(t *testing.T) {
234+
sr := strings.NewReader(doc)
235+
np, err := NewParser(sr)
236+
if err != nil {
237+
t.Fatal(err)
238+
}
239+
np.SetVariable("month", Sequence{&XPathMap{
240+
Entries: []MapEntry{
241+
{Key: "1", Value: Sequence{"01"}},
242+
{Key: "12", Value: Sequence{"12"}},
243+
},
244+
}})
245+
np.SetVariable("m", Sequence{"12"})
246+
247+
seq, err := np.Evaluate(`$month($m)`)
248+
if err != nil {
249+
t.Fatal(err)
250+
}
251+
if len(seq) != 1 || seq[0] != "12" {
252+
t.Errorf("got %v, want [12]", seq)
253+
}
254+
255+
// Static key
256+
seq, err = np.Evaluate(`$month('1')`)
257+
if err != nil {
258+
t.Fatal(err)
259+
}
260+
if len(seq) != 1 || seq[0] != "01" {
261+
t.Errorf("got %v, want [01]", seq)
262+
}
263+
}

navigator.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,11 @@ func (ctx *Context) parentAxis(tf testFunc) (Sequence, error) {
216216
for _, n := range ctx.sequence {
217217
switch t := n.(type) {
218218
case *goxml.Element:
219-
if tf(ctx, t.Parent) {
219+
if t.Parent != nil && tf(ctx, t.Parent) {
220+
seq = append(seq, t.Parent)
221+
}
222+
case *goxml.Attribute:
223+
if t.Parent != nil && tf(ctx, t.Parent) {
220224
seq = append(seq, t.Parent)
221225
}
222226
}

0 commit comments

Comments
 (0)