Last active
December 22, 2015 12:59
-
-
Save alxarch/6476434 to your computer and use it in GitHub Desktop.
XQuery numerals module
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module namespace num = "http://thinking.gr/modules/numerals"; | |
declare variable $num:valid-greek := "^[ρστυφχψωϠϡͲͳ]?[ικλμνξοπϞϟ]?[αβγδεζηθςϜϝ]$"; | |
declare function num:to-greek($i as xs:integer) as xs:string | |
{ | |
if($i gt 0 and $i lt 1000) then | |
let $x100 := op:numeric-integer-divide($i, 100) | |
let $x10 := op:numeric-integer-divide($i mod 100, 10) | |
let $x1 := $i mod 10 | |
return concat( | |
if($x100 eq 0) then () else ('ρ','σ','τ','υ','φ','χ','ψ','ω','ϡ')[$x100], | |
if($x10 eq 0) then () else ('ι','κ','λ','μ','ν','ξ','ο','π', 'ϟ')[$x10], | |
if($x1 eq 0) then () else ('α', 'β', 'γ', 'δ', 'ε', 'στ', 'ζ', 'η', 'θ')[$x1] | |
) | |
else error(QName("", "NUMERR"), "Greek numerals only supported for numbers in 1-999 range.") | |
}; | |
declare function num:greek($numeral as xs:string) as xs:integer | |
{ | |
(: Replace double-letter numeral for 6 with single letter equivalent :) | |
let $normalized := replace($numeral, "(στ|ΣΤ)", "ς") | |
return | |
if(matches($numeral, $num:valid-greek, "i")) | |
then sum( | |
for $code in string-to-codepoints($normalized) | |
return | |
(: ΣΤ, στ, ς , Ϝ, ϝ (digamma) :) | |
if($code = (962, 988, 989)) then 6 | |
(: Α,Β,Γ,Δ,Ε :) | |
else if($code ge 913 and $code le 917) then $code - 912 | |
(: α,β,γ,δ,ε :) | |
else if($code ge 945 and $code le 949) then $code - 944 | |
(: Ζ,Η,Θ :) | |
else if($code ge 918 and $code le 920) then $code - 917 | |
(: ζ,η,θ :) | |
else if($code ge 950 and $code le 952) then $code - 943 | |
(: Ι,Κ,Λ,Μ,Ν,Ξ,Ο,Π :) | |
else if($code ge 921 and $code le 928) then ($code - 920) * 10 | |
(: ι,κ,λ,μ,ν,ξ,ο,π :) | |
else if($code ge 953 and $code le 960) then ($code - 952) * 10 | |
(: ρΡ :) | |
else if($code eq 961 or $code eq 929) then 100 | |
(: Σ,Τ,Υ,Φ,Χ,Ψ,Ω :) | |
else if($code ge 931 and $code le 937) then ($code - 929) * 100 | |
(: σ,τ,υ,φ,χ,ψ,ω :) | |
else if($code ge 963 and $code le 969) then ($code - 961) * 100 | |
(: Ϟ, ϟ (koppa) :) | |
else if($code eq 991 or $code eq 990) then 90 | |
(: Ϡ ϡ Ͳ ͳ (sampi) :) | |
else if($code = (992, 993, 882, 883)) then 900 | |
else 0 | |
) | |
else -1 | |
}; | |
declare function num:resolve($num as xs:string) as xs:integer? | |
{ | |
if(matches($num, "\d+")) then xs:integer($num) | |
else if(matches($num, $num:valid-greek, "i")) then num:greek($num) | |
else () | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment