Skip to content

Instantly share code, notes, and snippets.

@alxarch
Last active December 22, 2015 12:59
Show Gist options
  • Save alxarch/6476434 to your computer and use it in GitHub Desktop.
Save alxarch/6476434 to your computer and use it in GitHub Desktop.
XQuery numerals module
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