rxeval 0.1.1

Evaluate ODK/OpenRosa XForms logic: XPath with the OpenRosa extensions, over a form instance
Documentation
{
  "$meta": {"engine": "javarosa", "version": "5.1.0"},
  "/data/age": {"type": "nodeset", "value": ["42"], "via": "javarosa"},
  "/data/missing": {"type": "nodeset", "value": [], "via": "javarosa"},
  "/data/household/resident/nome": {"type": "nodeset", "value": ["Ana", "Bia", "Caio"], "via": "javarosa"},
  "/data/household/resident[2]/nome": {"type": "nodeset", "value": [], "via": "javarosa"},
  "/data/household/resident[last()]/nome": {"type": "error", "value": "eval: XPath evaluation: cannot handle function 'last'", "via": "javarosa"},
  "/data/household/resident[position() = 2]/idade": {"type": "nodeset", "value": ["7"], "via": "javarosa"},
  "/data/household/resident[idade > 10]/nome": {"type": "nodeset", "value": ["Ana", "Caio"], "via": "javarosa"},
  "count(/data/household/resident)": {"type": "number", "value": 3.0, "via": "javarosa"},
  "count(/data/household/resident[idade > 10])": {"type": "number", "value": 2.0, "via": "javarosa"},
  "count(/data/missing)": {"type": "number", "value": 0.0, "via": "javarosa"},
  "count(//idade)": {"type": "error", "value": "eval: XPath evaluation: unsupported construct [step other than 'child::name', '.', '..']", "via": "javarosa"},
  "/data/@id": {"type": "nodeset", "value": ["oracle"], "via": "javarosa"},
  "/data/@version": {"type": "nodeset", "value": ["1"], "via": "javarosa"},
  ".": {"type": "nodeset", "value": [""], "via": "javarosa"},
  "//nome": {"type": "error", "value": "eval: XPath evaluation: unsupported construct [step other than 'child::name', '.', '..']", "via": "javarosa"},
  "string(/data/age)": {"type": "string", "value": "42", "via": "javarosa"},
  "string(/data/missing)": {"type": "string", "value": "", "via": "javarosa"},
  "concat(\"a\", \"b\", \"c\")": {"type": "string", "value": "abc", "via": "javarosa"},
  "concat(/data/household/resident/nome, \"!\")": {"type": "error", "value": "eval: XPath evaluation: type mismatch \nThis field is repeated: \n\n/data/household[1]/resident[1]/nome[1];/data/household[1]/resident[2]/nome[1];/data/household[1]/resident[3]/nome[1]\n\nYou may need to use the indexed-repeat() function to specify which value you want.", "via": "javarosa"},
  "string-length(/data/name)": {"type": "number", "value": 14.0, "via": "javarosa"},
  "string-length(/data/blank)": {"type": "number", "value": 0.0, "via": "javarosa"},
  "normalize-space(/data/spaced)": {"type": "string", "value": "padded", "via": "javarosa"},
  "contains(/data/name, \"Silva\")": {"type": "boolean", "value": true, "via": "javarosa"},
  "contains(/data/name, \"silva\")": {"type": "boolean", "value": false, "via": "javarosa"},
  "starts-with(/data/name, \"Maria\")": {"type": "boolean", "value": true, "via": "javarosa"},
  "ends-with(/data/name, \"Silva\")": {"type": "boolean", "value": true, "via": "javarosa"},
  "substring-before(/data/name, \" \")": {"type": "string", "value": "Maria", "via": "javarosa"},
  "substring-after(/data/name, \" \")": {"type": "string", "value": "da Silva", "via": "javarosa"},
  "substring(\"hello\", 2)": {"type": "error", "value": "eval: XPath evaluation: cannot handle function 'substring'", "via": "javarosa"},
  "substring(\"hello\", 2, 3)": {"type": "error", "value": "eval: XPath evaluation: cannot handle function 'substring'", "via": "javarosa"},
  "substring(\"hello\", 0, 3)": {"type": "error", "value": "eval: XPath evaluation: cannot handle function 'substring'", "via": "javarosa"},
  "substring(\"hello\", 1.5, 2.6)": {"type": "error", "value": "eval: XPath evaluation: cannot handle function 'substring'", "via": "javarosa"},
  "substr(\"hello\", 2, 3)": {"type": "string", "value": "l", "via": "javarosa"},
  "substr(\"hello\", 0, 2)": {"type": "string", "value": "he", "via": "javarosa"},
  "substr(\"hello\", -2)": {"type": "string", "value": "lo", "via": "javarosa"},
  "translate(\"bar\", \"abc\", \"ABC\")": {"type": "string", "value": "BAr", "via": "javarosa"},
  "upper-case(\"abc\")": {"type": "error", "value": "eval: XPath evaluation: cannot handle function 'upper-case'", "via": "javarosa"},
  "lower-case(\"ABC\")": {"type": "error", "value": "eval: XPath evaluation: cannot handle function 'lower-case'", "via": "javarosa"},
  "1 + 1": {"type": "number", "value": 2.0, "via": "javarosa"},
  "7 div 2": {"type": "number", "value": 3.5, "via": "javarosa"},
  "7 mod 3": {"type": "number", "value": 1.0, "via": "javarosa"},
  "-7 mod 3": {"type": "number", "value": -1.0, "via": "javarosa"},
  "1 div 0": {"type": "number", "value": "Infinity", "via": "javarosa"},
  "-1 div 0": {"type": "number", "value": "-Infinity", "via": "javarosa"},
  "0 div 0": {"type": "number", "value": "NaN", "via": "javarosa"},
  "number(\"abc\")": {"type": "number", "value": "NaN", "via": "javarosa"},
  "number(\"42\")": {"type": "number", "value": 42.0, "via": "javarosa"},
  "number(/data/age)": {"type": "number", "value": 42.0, "via": "javarosa"},
  "number(/data/blank)": {"type": "number", "value": "NaN", "via": "javarosa"},
  "sum(/data/household/resident/idade)": {"type": "number", "value": 60.0, "via": "javarosa"},
  "sum(/data/missing)": {"type": "number", "value": 0.0, "via": "javarosa"},
  "floor(1.9)": {"type": "error", "value": "eval: XPath evaluation: cannot handle function 'floor'", "via": "javarosa"},
  "ceiling(1.1)": {"type": "error", "value": "eval: XPath evaluation: cannot handle function 'ceiling'", "via": "javarosa"},
  "round(1.5)": {"type": "number", "value": 2.0, "via": "javarosa"},
  "round(2.5)": {"type": "number", "value": 3.0, "via": "javarosa"},
  "round(-1.5)": {"type": "number", "value": -1.0, "via": "javarosa"},
  "round(1.2345, 2)": {"type": "number", "value": 1.23, "via": "javarosa"},
  "round(1235.5, -2)": {"type": "number", "value": 1200.0, "via": "javarosa"},
  "int(1.9)": {"type": "number", "value": 1.0, "via": "javarosa"},
  "int(-1.9)": {"type": "number", "value": -1.0, "via": "javarosa"},
  "abs(-3)": {"type": "number", "value": 3.0, "via": "javarosa"},
  "pow(2, 10)": {"type": "number", "value": 1024.0, "via": "javarosa"},
  "min(/data/household/resident/idade)": {"type": "number", "value": 7.0, "via": "javarosa"},
  "max(/data/household/resident/idade)": {"type": "number", "value": 34.0, "via": "javarosa"},
  "min(3, 1, 2)": {"type": "number", "value": 1.0, "via": "javarosa"},
  "max(3, 1, 2)": {"type": "number", "value": 3.0, "via": "javarosa"},
  "true()": {"type": "boolean", "value": true, "via": "javarosa"},
  "false()": {"type": "boolean", "value": false, "via": "javarosa"},
  "not(true())": {"type": "boolean", "value": false, "via": "javarosa"},
  "boolean(\"0\")": {"type": "boolean", "value": true, "via": "javarosa"},
  "boolean(\"\")": {"type": "boolean", "value": false, "via": "javarosa"},
  "boolean(/data/blank)": {"type": "boolean", "value": false, "via": "javarosa"},
  "boolean(/data/missing)": {"type": "boolean", "value": false, "via": "javarosa"},
  "boolean-from-string(\"0\")": {"type": "boolean", "value": false, "via": "javarosa"},
  "boolean-from-string(\"1\")": {"type": "boolean", "value": true, "via": "javarosa"},
  "boolean-from-string(\"true\")": {"type": "boolean", "value": true, "via": "javarosa"},
  "boolean-from-string(\"TRUE\")": {"type": "boolean", "value": true, "via": "javarosa"},
  "boolean-from-string(\"no\")": {"type": "boolean", "value": false, "via": "javarosa"},
  "/data/age > 18": {"type": "boolean", "value": true, "via": "javarosa"},
  "/data/age = 42": {"type": "boolean", "value": true, "via": "javarosa"},
  "/data/age = \"42\"": {"type": "boolean", "value": true, "via": "javarosa"},
  "/data/household/resident/idade = 7": {"type": "error", "value": "eval: XPath evaluation: type mismatch \nThis field is repeated: \n\n/data/household[1]/resident[1]/idade[1];/data/household[1]/resident[2]/idade[1];/data/household[1]/resident[3]/idade[1]\n\nYou may need to use the indexed-repeat() function to specify which value you want.", "via": "javarosa"},
  "/data/household/resident/idade != 7": {"type": "error", "value": "eval: XPath evaluation: type mismatch \nThis field is repeated: \n\n/data/household[1]/resident[1]/idade[1];/data/household[1]/resident[2]/idade[1];/data/household[1]/resident[3]/idade[1]\n\nYou may need to use the indexed-repeat() function to specify which value you want.", "via": "javarosa"},
  "/data/missing = 0": {"type": "boolean", "value": false, "via": "javarosa"},
  "/data/missing != 0": {"type": "boolean", "value": true, "via": "javarosa"},
  "/data/blank = \"\"": {"type": "boolean", "value": true, "via": "javarosa"},
  "number(\"abc\") = number(\"abc\")": {"type": "boolean", "value": false, "via": "javarosa"},
  "number(\"abc\") > 0": {"type": "boolean", "value": false, "via": "javarosa"},
  "\"a\" < \"b\"": {"type": "boolean", "value": false, "via": "javarosa"},
  "1 < 2 and 2 < 3": {"type": "boolean", "value": true, "via": "javarosa"},
  "1 > 2 or 2 < 3": {"type": "boolean", "value": true, "via": "javarosa"},
  "selected(/data/services, \"water\")": {"type": "boolean", "value": true, "via": "javarosa"},
  "selected(/data/services, \"wat\")": {"type": "boolean", "value": false, "via": "javarosa"},
  "selected(/data/one_service, \"water\")": {"type": "boolean", "value": true, "via": "javarosa"},
  "count-selected(/data/services)": {"type": "number", "value": 2.0, "via": "javarosa"},
  "count-selected(/data/one_service)": {"type": "number", "value": 1.0, "via": "javarosa"},
  "selected-at(/data/services, 0)": {"type": "string", "value": "water", "via": "javarosa"},
  "selected-at(/data/services, 1)": {"type": "string", "value": "power", "via": "javarosa"},
  "selected-at(/data/services, 5)": {"type": "string", "value": "", "via": "javarosa"},
  "coalesce(/data/blank, \"fallback\")": {"type": "string", "value": "fallback", "via": "javarosa"},
  "coalesce(/data/age, \"fallback\")": {"type": "nodeset", "value": ["42"], "via": "javarosa"},
  "if(/data/age > 18, \"adult\", \"child\")": {"type": "string", "value": "adult", "via": "javarosa"},
  "if(/data/blank != \"\", 1 div 0, -1)": {"type": "number", "value": -1.0, "via": "javarosa"},
  "join(\", \", /data/household/resident/nome)": {"type": "string", "value": "Ana, Bia, Caio", "via": "javarosa"},
  "once(/data/age)": {"type": "nodeset", "value": ["42"], "via": "javarosa"},
  "format-date-time(\"2026-08-07T06:31:13.834-03:00\", \"%Y%m%d%H%M%S\")": {"type": "string", "value": "20260807063113", "via": "javarosa"},
  "format-date-time(\"2026-08-07T06:31:13.834-03:00\", \"%Y-%m-%d\")": {"type": "string", "value": "2026-08-07", "via": "javarosa"},
  "format-date-time(\"2026-08-07T06:31:13.834-03:00\", \"%H:%M:%S\")": {"type": "string", "value": "06:31:13", "via": "javarosa"},
  "format-date(\"2026-01-09\", \"%Y-%m-%d\")": {"type": "string", "value": "2026-01-09", "via": "javarosa"},
  "format-date(\"2026-01-09\", \"%e/%n/%y\")": {"type": "string", "value": "9/1/26", "via": "javarosa"},
  "regex(\"12345678901\", \"[0-9]{11}\")": {"type": "boolean", "value": true, "via": "javarosa"},
  "regex(\"12345678901\", \"^[0-9]{11}$\")": {"type": "boolean", "value": true, "via": "javarosa"},
  "regex(\"123\", \"[0-9]{11}\")": {"type": "boolean", "value": false, "via": "javarosa"},
  "regex(/data/cpf, \"[0-9]{11}\")": {"type": "boolean", "value": true, "via": "javarosa"},
  "regex(\"a12345678901b\", \"[0-9]{11}\")": {"type": "boolean", "value": false, "via": "javarosa"},
  "regex(\"abc123\", \"[0-9]+\")": {"type": "boolean", "value": false, "via": "javarosa"},
  "concat(/data/household/resident/nome)": {"type": "string", "value": "AnaBiaCaio", "via": "javarosa"},
  "distance(/data/trecho)": {"type": "number", "value": 3020.19014542737, "via": "javarosa"},
  "distance(/data/area_quadra)": {"type": "number", "value": 4267.237348415521, "via": "javarosa"},
  "distance(/data/um_ponto)": {"type": "number", "value": 0.0, "via": "javarosa"},
  "distance(\"-23.5505 -46.6333 0 0;-23.5605 -46.6333 0 0\")": {"type": "number", "value": 1113.1884482834857, "via": "javarosa"},
  "area(/data/area_quadra)": {"type": "number", "value": 1135931.145885644, "via": "javarosa"},
  "area(/data/trecho)": {"type": "number", "value": 1135887.9292798014, "via": "javarosa"},
  "area(\"-1 -1 0 0;-1 1 0 0;1 1 0 0;1 -1 0 0;-1 -1 0 0\")": {"type": "error", "value": "eval: XPath evaluation: cannot handle function 'area' requires a field as the parameter.", "via": "javarosa"},
  "round(distance(/data/trecho))": {"type": "number", "value": 3020.0, "via": "javarosa"},
  "round(area(/data/area_quadra))": {"type": "number", "value": 1135931.0, "via": "javarosa"}
}