I'm interested in building a website theme with Mathematica's XMLTemplate
as proposed by C. E. here.
The problem is, Mathematica's template syntax is verbose and a little clumsy, so I want to package up template routines. One common routine is checking if a template variable is defined.
I built the routine like so:
varExists=
"<wolfram:which>
<wolfram:if test='KeyMemberQ[#,First@#var]'>
<wolfram:slot id='if'></wolfram:slot>
</wolfram:if>
<wolfram:else>
<wolfram:slot id='else' />
</wolfram:else>
</wolfram:which>";
And it works to a degree:
dir = FileNameJoin@{$TemporaryDirectory, "xml_templates"};
CreateDirectory[dir];
(* export templates to file *)
Export[FileNameJoin@{dir, "varExists"},
varExists,
"Text"
]
temp=
"<title>
<wolfram:get path='varExists'>
<wolfram:slot id='var'>longTitle</wolfram:slot>
<wolfram:slot id='if'>A very long title</wolfram:slot>
<wolfram:slot id='else'>A more compact title</wolfram:slot>
</wolfram:get>
</title>";
Export[
FileNameJoin@{dir, "template.html"},
temp,
"Text"
];
(* test template *)
Block[{
$TemplatePath =
Append[$TemplatePath, dir]
},
TemplateApply[
XMLTemplate@File[FileNameJoin@{dir, "template.html"}],
<|
"longTitle" -> True
|>
]
]
"<title>
A very long title
</title>"
This is what we'd expect. But now let's use this template itself as a routine and pass a variable from within a different root template:
(* Export new template *)
temp2=
"<wolfram:with longTitle='True'>
<wolfram:get path='template.html' />
</wolfram:with>";
Export[
FileNameJoin@{dir, "template2.html"},
temp2,
"Text"
];
(* try again *)
Block[{
$TemplatePath =
Append[$TemplatePath, dir]
},
TemplateApply[
XMLTemplate@File[FileNameJoin@{dir, "template2.html"}],
<||>
]
]
"<title>
A more compact title
</title>"
So clearly that "<wolfram:with ... >"
isn't passing its variables.
If we add a Print[Templating`$TemplateArguments]
to our "test"
we find that it remains empty. If we look at the Templating`$TemplateArgumentStack
we find this:
{{<||>}, {<||>}, {<||>}, {}, {<|"longTitle" -> True|>}, {<|"var" :>
TemplateObject[{"longTitle"}],
"if" :> TemplateObject[{"A very long title"}],
"else" :> TemplateObject[{"A more compact title"}]|>}}
So these variables exit the stack before they can even be used. (Obviously I could screw around with the argument stack, but that seems like a pain).
So here's the question: how do I do this? If variables aren't passed, how am I supposed to build routines? I reallllly don't want to have to use the insanely verbose syntax everywhere in my templates.