@@ -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+
9651033func 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
14011466func 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-
19892030func 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 })
0 commit comments