TMQL Canonizer
This is a new service from the Topic Maps Lab but absent any documentation, it is hard to say what to expect from it.
For example, I took a query from the rather excellent TMQL tutorials by Sven Krosse (also of the Topic Maps Lab):
%prefix o http://psi.ontopia.net/music/
FOR $topic IN // tm:subject
RETURN
IF $topic ISA o:composer
THEN $topic >> indicators
ELSE $topic / tm:name [0]
Fed it to the canonizer and got this result:
QueryExpression([%prefix, o, http://psi.ontopia.net/music/, FOR, $topic, IN, //, tm:subject, RETURN, IF, $topic, ISA, o:composer, THEN, $topic, >>, indicators, ELSE, $topic, /, tm:name, [, 0, ]])
|–EnvironmentClause([%prefix, o, http://psi.ontopia.net/music/])
| |–PrefixDirective([%prefix, o, http://psi.ontopia.net/music/])
|–FlwrExpression([FOR, $topic, IN, //, tm:subject, RETURN, IF, $topic, ISA, o:composer, THEN, $topic, >>, indicators, ELSE, $topic, /, tm:name, [, 0, ]])
|–ForClause([FOR, $topic, IN, //, tm:subject])
| |–BindingSet([$topic, IN, //, tm:subject])
| |–VariableAssignment([$topic, IN, //, tm:subject])
| |–Variable([$topic])
| |–Content([//, tm:subject])
| |–QueryExpression([//, tm:subject])
| |–PathExpression([//, tm:subject])
| |–PostfixedExpression([//, tm:subject])
| |–SimpleContent([//, tm:subject])
| |–Anchor([tm:subject])
| |–Navigation([<<, types])
| |--StepDefinition([<<, types])
| |--Step([<<, types])
|--ReturnClause([RETURN, IF, $topic, ISA, o:composer, THEN, $topic, >>, indicators, ELSE, $topic, /, tm:name, [, 0, ]])
|–Content([IF, $topic, ISA, o:composer, THEN, $topic, >>, indicators, ELSE, $topic, /, tm:name, [, 0, ]])
|–PathExpression([$topic, ISA, o:composer])
| |–ISAExpression([$topic, ISA, o:composer])
| |–SimpleContent([$topic])
| | |–Anchor([$topic])
| |–SimpleContent([o:composer])
| |–Anchor([o:composer])
|–Content([$topic, >>, indicators])
| |–QueryExpression([$topic, >>, indicators])
| |–PathExpression([$topic, >>, indicators])
| |–PostfixedExpression([$topic, >>, indicators])
| |–SimpleContent([$topic, >>, indicators])
| |–Anchor([$topic])
| |–Navigation([>>, indicators])
| |–StepDefinition([>>, indicators])
| |–Step([>>, indicators])
|–Content([$topic, /, tm:name, [, 0, ]])
|–QueryExpression([$topic, /, tm:name, [, 0, ]])
|–PathExpression([$topic, /, tm:name, [, 0, ]])
|–PostfixedExpression([$topic, /, tm:name, [, 0, ]])
|–SimpleContent([$topic, /, tm:name, [, 0, ]])
|–Anchor([$topic])
|–Navigation([/, tm:name, [, 0, ]])
|–StepDefinition([>>, characteristics, tm:name])
| |–Step([>>, characteristics, tm:name])
| |–Anchor([tm:name])
|–StepDefinition([>>, atomify, [, 0, ]])
|–Step([>>, atomify])
|–FilterPostfix([[, 0, ]])
|–Anchor([0])
OK, so I omitted the prefix on composer for the following query:
%prefix o http://psi.ontopia.net/music/
FOR $topic IN // tm:subject
RETURN
IF $topic ISA composer
THEN $topic >> indicators
ELSE $topic / tm:name [0]
Then I get:
QueryExpression([%prefix, o, http://psi.ontopia.net/music/, FOR, $topic, IN, //, tm:subject, RETURN, IF, $topic, ISA, composer, THEN, $topic, >>, indicators, ELSE, $topic, /, tm:name, [, 0, ]])
|–EnvironmentClause([%prefix, o, http://psi.ontopia.net/music/])
| |–PrefixDirective([%prefix, o, http://psi.ontopia.net/music/])
|–FlwrExpression([FOR, $topic, IN, //, tm:subject, RETURN, IF, $topic, ISA, composer, THEN, $topic, >>, indicators, ELSE, $topic, /, tm:name, [, 0, ]])
|–ForClause([FOR, $topic, IN, //, tm:subject])
| |–BindingSet([$topic, IN, //, tm:subject])
| |–VariableAssignment([$topic, IN, //, tm:subject])
| |–Variable([$topic])
| |–Content([//, tm:subject])
| |–QueryExpression([//, tm:subject])
| |–PathExpression([//, tm:subject])
| |–PostfixedExpression([//, tm:subject])
| |–SimpleContent([//, tm:subject])
| |–Anchor([tm:subject])
| |–Navigation([<<, types])
| |--StepDefinition([<<, types])
| |--Step([<<, types])
|--ReturnClause([RETURN, IF, $topic, ISA, composer, THEN, $topic, >>, indicators, ELSE, $topic, /, tm:name, [, 0, ]])
|–Content([IF, $topic, ISA, composer, THEN, $topic, >>, indicators, ELSE, $topic, /, tm:name, [, 0, ]])
|–PathExpression([$topic, ISA, composer])
| |–ISAExpression([$topic, ISA, composer])
| |–SimpleContent([$topic])
| | |–Anchor([$topic])
| |–SimpleContent([composer])
| |–Anchor([composer])
|–Content([$topic, >>, indicators])
| |–QueryExpression([$topic, >>, indicators])
| |–PathExpression([$topic, >>, indicators])
| |–PostfixedExpression([$topic, >>, indicators])
| |–SimpleContent([$topic, >>, indicators])
| |–Anchor([$topic])
| |–Navigation([>>, indicators])
| |–StepDefinition([>>, indicators])
| |–Step([>>, indicators])
|–Content([$topic, /, tm:name, [, 0, ]])
|–QueryExpression([$topic, /, tm:name, [, 0, ]])
|–PathExpression([$topic, /, tm:name, [, 0, ]])
|–PostfixedExpression([$topic, /, tm:name, [, 0, ]])
|–SimpleContent([$topic, /, tm:name, [, 0, ]])
|–Anchor([$topic])
|–Navigation([/, tm:name, [, 0, ]])
|–StepDefinition([>>, characteristics, tm:name])
| |–Step([>>, characteristics, tm:name])
| |–Anchor([tm:name])
|–StepDefinition([>>, atomify, [, 0, ]])
|–Step([>>, atomify])
|–FilterPostfix([[, 0, ]])
|–Anchor([0])
So then I enter a query that omits the “$” from the second instance of topic:
%prefix o http://psi.ontopia.net/music/
FOR $topic IN // tm:subject
RETURN
IF topic ISA o:composer
THEN $topic >> indicators
ELSE $topic / tm:name [0]
You can enter that one for yourself. No substantive change in result.
By omitting the “$” from all instances of topic I was finally able to get “an invalid expression” result.
Do note that the following is treated as a valid expression:
%prefix o http://psi.ontopia.net/music/
FOR $topic IN // tm:subject
RETURN
IF topic ISA o:composer
THEN topic >> indicators
ELSE topic / tm:name [0]
A bit more attention to documentation would go a long way to making this a useful project.
*****
PS: From the 2008 TMQL draft:
Examples for invalid variables are x (sigil missing),