0
|
1 |
include homepage.en.yhtml2
|
|
2 |
|
|
3 |
page "The Features" {
|
|
4 |
h2 id=text > Text
|
|
5 |
|
|
6 |
p >>
|
|
7 |
To output text nodes (¬http://www.w3.org/TR/2008/REC-xml-20081126/#syntax character data¬),
|
|
8 |
write literals. There are integer literals, floating point literals and text literals.
|
|
9 |
>>
|
|
10 |
|
|
11 |
p >>
|
|
12 |
Literals are written
|
|
13 |
¬http://docs.python.org/reference/lexical_analysis.html#id7 like in Python¬,
|
|
14 |
that means, text literals are in single or double quotes, or multiline
|
|
15 |
in triple double quotes:
|
|
16 |
>>
|
|
17 |
|
|
18 |
Code ||
|
|
19 |
"text" 'also text' """some more text"""
|
|
20 |
42 "an integer and" 42.23 "a floating point literal"
|
|
21 |
||
|
|
22 |
|
|
23 |
p >>
|
|
24 |
Literals are being output by the ¬#textfunction text function¬.
|
|
25 |
>>
|
|
26 |
|
|
27 |
h2 id=functioncalls > Function Calls
|
|
28 |
|
|
29 |
p >>
|
|
30 |
The main idea of YML scripts is calling functions which then generate
|
|
31 |
XML tags (¬http://www.w3.org/TR/2008/REC-xml-20081126/#syntax Markup¬).
|
|
32 |
Functions are generating single tags, lists or trees of tags.
|
|
33 |
>>
|
|
34 |
|
|
35 |
p >>
|
|
36 |
To call a function, write the name of the function, followed by a comma separated list
|
|
37 |
of function parameters (C like syntax) or just «attribute=value» pairs. Unlike C, you don't
|
|
38 |
need to insert the parameter list into parentheses. A simple function call can be terminated
|
|
39 |
by a semicolon «;» or by a period «.»
|
|
40 |
>>
|
|
41 |
|
|
42 |
p >>
|
|
43 |
It does not matter, if you're calling your function using parentheses or brackets or without.
|
|
44 |
So these statements are equal:
|
|
45 |
>>
|
|
46 |
|
|
47 |
Code ||
|
|
48 |
foo "hello, world";
|
|
49 |
foo "hello, world".
|
|
50 |
foo("hello, world");
|
|
51 |
foo["hello, world"];
|
|
52 |
||
|
|
53 |
|
|
54 |
h3 id=subtree > Subtrees
|
|
55 |
|
|
56 |
p >>
|
|
57 |
If you omit the tailing semicolon, you're creating a Subtree; YML Subtrees can also be
|
|
58 |
opened and closed with braces:
|
|
59 |
>>
|
|
60 |
|
|
61 |
Code ||
|
|
62 |
foo {
|
|
63 |
bar {
|
|
64 |
something;
|
|
65 |
}
|
|
66 |
}
|
|
67 |
||
|
|
68 |
|
|
69 |
p > If a Subtree only consists of one single subelement, then you may omit the braces:
|
|
70 |
|
|
71 |
Code ||
|
|
72 |
foo
|
|
73 |
bar;
|
|
74 |
||
|
|
75 |
|
|
76 |
h3 id=named > Named Parameters
|
|
77 |
|
|
78 |
p >>
|
|
79 |
To generate ¬http://www.w3.org/TR/2008/REC-xml-20081126/#attdecls attributes¬ by calling
|
|
80 |
a function, you can use Named Parameters.
|
|
81 |
>>
|
|
82 |
|
|
83 |
p >>
|
|
84 |
For that case, assign literals or symbols to attribute names like the following.
|
|
85 |
The name of the parameter then will be used as the name of the generated attribute.
|
|
86 |
An example:
|
|
87 |
>>
|
|
88 |
|
|
89 |
Code ||
|
|
90 |
div id=sample {
|
|
91 |
"this is a " a href="#sample" "link sample"
|
|
92 |
}
|
|
93 |
||
|
|
94 |
|
|
95 |
p > This generates:
|
|
96 |
|
|
97 |
Code | <div id="sample">this is a <a href="#sample">link sample</a></div>
|
|
98 |
|
|
99 |
h3 > Unnamed Parameters
|
|
100 |
|
|
101 |
p >>
|
|
102 |
Unnamed Parameters prepare values for predefined attributes. The following example is
|
|
103 |
equivalent to the sample above:
|
|
104 |
>>
|
|
105 |
|
|
106 |
Code ||
|
|
107 |
decl a(href);
|
|
108 |
decl div(id);
|
|
109 |
|
|
110 |
div "sample" {
|
|
111 |
"this is a " a "#sample" "link sample"
|
|
112 |
}
|
|
113 |
||
|
|
114 |
|
|
115 |
p > If no predefined attribute can be allocated, the value of the parameter is added to the body.
|
|
116 |
|
|
117 |
h3 > Calling with &
|
|
118 |
|
|
119 |
p >>
|
|
120 |
Especially if you have a ¬#defaultbody default body¬ for your function, calling with
|
|
121 |
a leading «&» can be sensible: then the tag itself is omitted and only the body is being output:
|
|
122 |
>>
|
|
123 |
|
|
124 |
Code ||
|
|
125 |
decl something { tag1; tag2; };
|
|
126 |
|
|
127 |
list {
|
|
128 |
&something;
|
|
129 |
}
|
|
130 |
||
|
|
131 |
|
|
132 |
p > results in:
|
|
133 |
|
|
134 |
Code ||
|
|
135 |
<list>
|
|
136 |
<tag1/>
|
|
137 |
<tag2/>
|
|
138 |
</list>
|
|
139 |
||
|
|
140 |
|
|
141 |
p >>
|
|
142 |
This has the same result as ¬#alias aliasing¬ «something» to «-».
|
|
143 |
>>
|
|
144 |
|
|
145 |
h3 id=funclist > Function Lists
|
|
146 |
|
|
147 |
p >>
|
|
148 |
Function Lists are a feature of YML to simulate a more C like syntax. Let's have some
|
|
149 |
examples. You can have a list of functions whereever you can have a function. Function
|
|
150 |
Lists are comma separated:
|
|
151 |
>>
|
|
152 |
|
|
153 |
Code ||
|
|
154 |
x i, j, k
|
|
155 |
||
|
|
156 |
|
|
157 |
p > compiles to:
|
|
158 |
|
|
159 |
Code ||
|
|
160 |
<x>
|
|
161 |
<i/>
|
|
162 |
<j/>
|
|
163 |
<k/>
|
|
164 |
</x>
|
|
165 |
||
|
|
166 |
|
|
167 |
h3 id=paramlists > Parameter Lists
|
|
168 |
|
|
169 |
p >>
|
|
170 |
A sample together with ¬#descending Descending Attributes¬:
|
|
171 |
>>
|
|
172 |
|
|
173 |
Code ||
|
|
174 |
decl Interface @name;
|
|
175 |
decl attr @type @name;
|
|
176 |
decl func @type @name;
|
|
177 |
|
|
178 |
Interface Icecream {
|
|
179 |
attr color flavour;
|
|
180 |
attr long number;
|
|
181 |
func int getPrice();
|
|
182 |
func void addFlavour(in color flavour, in long number);
|
|
183 |
}
|
|
184 |
||
|
|
185 |
|
|
186 |
p > compiles to:
|
|
187 |
|
|
188 |
Code ||
|
|
189 |
<Interface name="Icecream">
|
|
190 |
<attr type="color" name="flavour"/>
|
|
191 |
<attr type="long" name="number"/>
|
|
192 |
<func type="int" name="getPrice"/>
|
|
193 |
<func type="void" name="addFlavour">
|
|
194 |
<parm>
|
|
195 |
<in/>
|
|
196 |
<color/>
|
|
197 |
<flavour/>
|
|
198 |
</parm>
|
|
199 |
<parm>
|
|
200 |
<in/>
|
|
201 |
<long/>
|
|
202 |
<number/>
|
|
203 |
</parm>
|
|
204 |
</func>
|
|
205 |
</Interface>
|
|
206 |
||
|
|
207 |
|
|
208 |
p >>
|
|
209 |
Note the «parm» tags – they're generated by default, if you write a Parameter List
|
|
210 |
behind a Function Call. That differs from calling the function with parameters –
|
|
211 |
¬#functioncalls calling¬ means using ¬#text text¬ values.
|
|
212 |
>>
|
|
213 |
|
|
214 |
p >>
|
|
215 |
The «parm» tags are emitted, because the «_parm» function is called each time
|
|
216 |
such a parameter will be emitted.
|
|
217 |
>>
|
|
218 |
|
|
219 |
p >>
|
|
220 |
If you want to have the «_parm» function doing other things, just ¬#decl declare¬
|
|
221 |
it in another way.
|
|
222 |
>>
|
|
223 |
|
|
224 |
h3 id=generics > Generic Declarations
|
|
225 |
|
|
226 |
p >>
|
|
227 |
Using Generic Declarations is just like using ¬#paramlists Parameter Lists¬ – use angle brackets
|
|
228 |
instead of parentheses. For Generic Declarations, the «_generic» function is called each
|
|
229 |
time such a Generic Declaration will be emitted, generating «generic» tags as the default:
|
|
230 |
>>
|
|
231 |
|
|
232 |
Code | max<int>(x, y)
|
|
233 |
|
|
234 |
p > compiles to:
|
|
235 |
|
|
236 |
Code ||
|
|
237 |
<max>
|
|
238 |
<generic>
|
|
239 |
<int/>
|
|
240 |
</generic>
|
|
241 |
<parm>
|
|
242 |
<x/>
|
|
243 |
</parm>
|
|
244 |
<parm>
|
|
245 |
<y/>
|
|
246 |
</parm>
|
|
247 |
</max>
|
|
248 |
||
|
|
249 |
|
|
250 |
h3 id=contentfc > The «content» function
|
|
251 |
|
|
252 |
p >>
|
|
253 |
The «content;» Function Call has a special meaning (only in a ¬#defaultbody default body¬):
|
|
254 |
it does not generate a tag, but instead
|
|
255 |
the tags of a supplied body in a call will be inserted at each place where the «content;»
|
|
256 |
function call is existing in the ¬#defaultbody default body¬.
|
|
257 |
>>
|
|
258 |
|
|
259 |
h3 id=textfunction > The «text» function
|
|
260 |
|
|
261 |
p >>
|
|
262 |
There is a special YML function named «text». Usually, it's just ¬#alias aliased¬ to «-» (and
|
|
263 |
therefore outputting nothing). The «text» function is called each time a text literal will be
|
|
264 |
output.
|
|
265 |
>>
|
|
266 |
|
|
267 |
p >>
|
|
268 |
If you ¬#decl declare¬ the «text» function, you can overload that behaviour. For example,
|
|
269 |
¬yslt YSLT¬ is declaring «text» like this:
|
|
270 |
>>
|
|
271 |
|
|
272 |
Code ||
|
|
273 |
decl text alias xsl:text;
|
|
274 |
|
|
275 |
"test"
|
|
276 |
||
|
|
277 |
|
|
278 |
p > generates:
|
|
279 |
|
|
280 |
Code | <xsl:text>test</xsl:text>
|
|
281 |
|
|
282 |
p >>
|
|
283 |
The «text» function is not called, if you give text as a value for an attribute:
|
|
284 |
>>
|
|
285 |
|
|
286 |
Code ||
|
|
287 |
decl text alias xsl:text;
|
|
288 |
|
|
289 |
a "test"
|
|
290 |
||
|
|
291 |
|
|
292 |
p > generates:
|
|
293 |
|
|
294 |
Code | <a>test</a>
|
|
295 |
|
|
296 |
p >>
|
|
297 |
But it is called using the quoting operators:
|
|
298 |
>>
|
|
299 |
|
|
300 |
Code ||
|
|
301 |
decl text alias xsl:text;
|
|
302 |
|
|
303 |
a > test
|
|
304 |
||
|
|
305 |
|
|
306 |
p > generates:
|
|
307 |
|
|
308 |
Code | <a><xsl:text>test</xsl:text></a>
|
|
309 |
|
|
310 |
h3 id=declfunction > The «decl», «define» and «operator» functions
|
|
311 |
|
|
312 |
p >>
|
|
313 |
The «decl», «define» and «operator» functions are not defined, so they cannot be used
|
|
314 |
accidentally by having a syntax error i.e. in a «decl» statement. If you want to use such
|
|
315 |
a function, i.e. «decl()», you have to ¬#decl declare it explicitely¬:
|
|
316 |
>>
|
|
317 |
|
|
318 |
Code ||
|
|
319 |
decl decl;
|
|
320 |
decl();
|
|
321 |
||
|
|
322 |
|
|
323 |
p > will result in:
|
|
324 |
|
|
325 |
Code | <decl/>
|
|
326 |
|
|
327 |
h2 id=decl > Declaring Functions: decl
|
|
328 |
|
|
329 |
p >>
|
|
330 |
As default, each Function Call generates one XML tag, which has the same name. To be exact,
|
|
331 |
the XML tag has dashes in it's name where the YML function has underscores.
|
|
332 |
>>
|
|
333 |
|
|
334 |
p >>
|
|
335 |
To define, how tags and attributes look like, which are created by a Function Call, you
|
|
336 |
can use the «decl» statement.
|
|
337 |
>>
|
|
338 |
|
|
339 |
h3 > Trivial Declarations
|
|
340 |
|
|
341 |
p > In a trivial declaration, you're just declaring the Function Name and so the XML tag name:
|
|
342 |
|
|
343 |
Code | decl html, head, title, body, p, a;
|
|
344 |
|
|
345 |
p > As seen in the example, multiple declarations can be done in a comma separated list.
|
|
346 |
|
|
347 |
p >>
|
|
348 |
Because trivial declarations are done automatically, if you're using a function for the
|
|
349 |
first time, you usually don't need to declare this way.
|
|
350 |
>>
|
|
351 |
|
|
352 |
h3 > Specifying Unnamed Parameters
|
|
353 |
|
|
354 |
p >>
|
|
355 |
To specifiy Unnamed Parameters, give the parameter list comma separated in parentheses
|
|
356 |
or provide one or more brackets with parameter lists in them:
|
|
357 |
>>
|
|
358 |
|
|
359 |
Code | decl a(href), img[src];
|
|
360 |
|
|
361 |
p >>
|
|
362 |
If you're using the corresponding functions a() and img() together with an unnamed parameter
|
|
363 |
in a call, then these attributes are used for applying the values, respectively:
|
|
364 |
>>
|
|
365 |
|
|
366 |
Code | a "http://www.ccc.de" "The Club Homepage" img "logo.png";
|
|
367 |
|
|
368 |
p > These Function Calls generate:
|
|
369 |
|
|
370 |
Code | <a href="http://www.ccc.de">The Club Homepage</a><img src="logo.png"/>
|
|
371 |
|
|
372 |
h3 id=defaultattr > Giving Default Values for parameters
|
|
373 |
|
|
374 |
p >>
|
|
375 |
To give default values for generating XML attributes, assign a literal to each named parameter
|
|
376 |
in the declaration parentheses or brackets. Two examples, which do the same:
|
|
377 |
>>
|
|
378 |
|
|
379 |
Code
|
|
380 |
||
|
|
381 |
decl img(src, alt="picture");
|
|
382 |
decl img[src][alt="picture"];
|
|
383 |
||
|
|
384 |
|
|
385 |
h3 id=alias > Aliasing: using different YML functions for the same XML tag for different tasks
|
|
386 |
|
|
387 |
p >>
|
|
388 |
Sometimes tags are used in different ways to do different things. For this case, you can
|
|
389 |
use aliasing. Aliasing means, the YML function name and the XML tag name differ. For example:
|
|
390 |
>>
|
|
391 |
|
|
392 |
Code | decl a(href), target(name) alias a;
|
|
393 |
|
|
394 |
p > Both defined YML functions then generate «<a />» tags – but the Unnamed Parameter differs.
|
|
395 |
|
|
396 |
p >>
|
|
397 |
The alias name «-» has a special meaning: it omits the tag in the output. That is especially
|
|
398 |
sensible if you have a ¬#defaultbody default body¬. Then an alias to «-» has the same meaning
|
|
399 |
as starting the function call with the «&» character: only the body is emitted.
|
|
400 |
>>
|
|
401 |
|
|
402 |
h3 id=descending > Specifying Descending Attributes
|
|
403 |
|
|
404 |
p >>
|
|
405 |
Maybe you want to write something like this:
|
|
406 |
>>
|
|
407 |
|
|
408 |
Code ||
|
|
409 |
Module ERP {
|
|
410 |
Interface Customer {
|
|
411 |
// ...
|
|
412 |
}
|
|
413 |
}
|
|
414 |
||
|
|
415 |
|
|
416 |
p > Without any extras, this compiles to:
|
|
417 |
|
|
418 |
Code ||
|
|
419 |
<Module>
|
|
420 |
<ERP>
|
|
421 |
<Interface>
|
|
422 |
<Customer />
|
|
423 |
</Interface>
|
|
424 |
</ERP>
|
|
425 |
</Module>
|
|
426 |
||
|
|
427 |
|
|
428 |
p >>
|
|
429 |
For this case, it would be practical, if «ERP» would not be interpreted as extra tag
|
|
430 |
but as value for an attribute «name». This you can achive with Descending Attributes:
|
|
431 |
>>
|
|
432 |
|
|
433 |
Code | decl Module @name, Interface @name;
|
|
434 |
|
|
435 |
p > With this declaration, the code sample above is compiling to:
|
|
436 |
|
|
437 |
Code ||
|
|
438 |
<Module name="ERP">
|
|
439 |
<Interface name="Customer" />
|
|
440 |
</Module>
|
|
441 |
||
|
|
442 |
|
|
443 |
p >>
|
|
444 |
Descending attributes can also be used this way:
|
|
445 |
>>
|
|
446 |
|
|
447 |
Code ||
|
|
448 |
decl module +name;
|
|
449 |
decl element +name;
|
|
450 |
|
|
451 |
module Some {
|
|
452 |
element {
|
|
453 |
one;
|
|
454 |
two;
|
|
455 |
three;
|
|
456 |
}
|
|
457 |
element {
|
|
458 |
four; five; six
|
|
459 |
}
|
|
460 |
}
|
|
461 |
||
|
|
462 |
|
|
463 |
p >>
|
|
464 |
The above generates:
|
|
465 |
>>
|
|
466 |
|
|
467 |
Code ||
|
|
468 |
<?xml version='1.0' encoding='UTF-8'?>
|
|
469 |
<module name="Some">
|
|
470 |
<element name="one"/>
|
|
471 |
<element name="two"/>
|
|
472 |
<element name="three"/>
|
|
473 |
<element name="four"/>
|
|
474 |
<element name="five"/>
|
|
475 |
<element name="six"/>
|
|
476 |
</module>
|
|
477 |
||
|
|
478 |
|
|
479 |
h3 id=descending_pointer > Specifying Descending Pointers
|
|
480 |
|
|
481 |
p >>
|
|
482 |
Like with descending attributes, you can use descending ¬#pointer pointers¬. Instead of preceding the
|
|
483 |
name of an attribute with a «+» sign (like with ¬#descending descending attributes¬), precede it with an asterisk «*».
|
|
484 |
>>
|
|
485 |
|
|
486 |
p >>
|
|
487 |
Like with ¬#pointer pointers¬ in general, it's a good idea to combine that with a ¬#defaultbody default body¬:
|
|
488 |
>>
|
|
489 |
|
|
490 |
Code ||
|
|
491 |
decl f *p { some tags with *p };
|
|
492 |
|
|
493 |
f value;
|
|
494 |
||
|
|
495 |
|
|
496 |
p >>
|
|
497 |
This generates:
|
|
498 |
>>
|
|
499 |
|
|
500 |
Code ||
|
|
501 |
<?xml version='1.0' encoding='UTF-8'?>
|
|
502 |
<f>
|
|
503 |
<some>
|
|
504 |
<tags>
|
|
505 |
<with>value</with>
|
|
506 |
</tags>
|
|
507 |
</some>
|
|
508 |
</f>
|
|
509 |
||
|
|
510 |
|
|
511 |
h3 id=defaultbody > Supplying a Default Body
|
|
512 |
|
|
513 |
p >>
|
|
514 |
Additionally, you can supply a Default Body for each tag. For that case, add a YML function
|
|
515 |
block in braces to your declaration:
|
|
516 |
>>
|
|
517 |
|
|
518 |
Code ||
|
|
519 |
decl pageContent alias body {
|
|
520 |
a name=top;
|
|
521 |
include heading.en.yhtml2;
|
|
522 |
div id=entries
|
|
523 |
content;
|
|
524 |
};
|
|
525 |
||
|
|
526 |
|
|
527 |
p > The sample above is used for generating this homepage, for example.
|
|
528 |
|
|
529 |
p > See the ¬#contentfc content function¬.
|
|
530 |
|
|
531 |
h3 id=inheritance > Inheritance
|
|
532 |
|
|
533 |
p >>
|
|
534 |
Declarations can ¬http://en.wikipedia.org/wiki/Inheritance_(computer_science) inherit¬
|
|
535 |
information from previous declarations. For that case, there is the
|
|
536 |
possibility to use an «is» clause to give a function name to inherit from.
|
|
537 |
>>
|
|
538 |
|
|
539 |
p > The following is an example from the YSLT specification:
|
|
540 |
|
|
541 |
Code ||
|
|
542 |
decl stylesheet(version="1.0", xmlns:xsl="http://www.w3.org/1999/XSL/Transform");
|
|
543 |
|
|
544 |
decl estylesheet is stylesheet (
|
|
545 |
xmlns:exsl='http://exslt.org/common',
|
|
546 |
xmlns:math='http://exslt.org/math',
|
|
547 |
xmlns:func='http://exslt.org/functions',
|
|
548 |
xmlns:str='http://exslt.org/strings',
|
|
549 |
xmlns:dyn='http://exslt.org/dynamic',
|
|
550 |
xmlns:set='http://exslt.org/sets',
|
|
551 |
extension-element-prefixes='exsl func str dyn set math'
|
|
552 |
);
|
|
553 |
|
|
554 |
decl textstylesheet is estylesheet {
|
|
555 |
output "text";
|
|
556 |
const "space", !"'" + " " * 200 + "'"!;
|
|
557 |
param "autoindent", 4;
|
|
558 |
content;
|
|
559 |
}, tstylesheet is textstylesheet;
|
|
560 |
||
|
|
561 |
|
|
562 |
p >>
|
|
563 |
Here «estylesheet» inherits the tag name and the Default Values from «stylesheet»,
|
|
564 |
while «textstylesheet» inherits all from «estylesheet» again. «estylesheet» then adds
|
|
565 |
a Default Body, and «tstylesheet» does exactly the same as «textstylesheet».
|
|
566 |
>>
|
|
567 |
|
|
568 |
p > All of these YML functions output «stylesheet» XML tags, but with different defaults.
|
|
569 |
|
|
570 |
h3 id=shapes > Shapes
|
|
571 |
|
|
572 |
p >>
|
|
573 |
Shapes are comparable to ¬#inheritance inheritance¬. Declaring a shape inherits
|
|
574 |
every property beside the name.
|
|
575 |
>>
|
|
576 |
|
|
577 |
Code ||
|
|
578 |
decl coords(x=0, y=0);
|
|
579 |
decl point <coords> (name);
|
|
580 |
|
|
581 |
point "origin";
|
|
582 |
||
|
|
583 |
|
|
584 |
p > compiles to:
|
|
585 |
|
|
586 |
Code | <point y="0" x="0" name="origin"/>
|
|
587 |
|
|
588 |
p >>
|
|
589 |
It's possible to have more than one shape, too. Multiple shapes
|
|
590 |
are patching each other in the sequence they're listed:
|
|
591 |
>>
|
|
592 |
|
|
593 |
Code ||
|
|
594 |
decl coords(x=0, y=0);
|
|
595 |
decl named +name;
|
|
596 |
decl point <coords, named>;
|
|
597 |
|
|
598 |
point origin;
|
|
599 |
||
|
|
600 |
|
|
601 |
p > compiles to:
|
|
602 |
|
|
603 |
Code | <point y="0" x="0" name="origin" />
|
|
604 |
|
|
605 |
h3 > Namespaces
|
|
606 |
|
|
607 |
p >>
|
|
608 |
¬http://www.w3.org/TR/xml-names/ XML namespaces¬ can be used just by providing an
|
|
609 |
«alias» clause. Additionally, they can be used by an «in» clause; these two lines
|
|
610 |
are equivalent:
|
|
611 |
>>
|
|
612 |
|
|
613 |
Code ||
|
|
614 |
decl apply(select) alias xsl:apply-templates;
|
|
615 |
in xsl decl apply(select) alias apply-templates;
|
|
616 |
||
|
|
617 |
|
|
618 |
p > «in» clauses also can be used with a block of declarations in braces:
|
|
619 |
|
|
620 |
Code ||
|
|
621 |
in xsl {
|
|
622 |
decl template(match);
|
|
623 |
decl apply(select) alias apply-templates;
|
|
624 |
|
|
625 |
decl function(name) alias template;
|
|
626 |
decl call(name) alias call-template;
|
|
627 |
}
|
|
628 |
||
|
|
629 |
|
|
630 |
h3 id=pointer > Pointers
|
|
631 |
|
|
632 |
p >>
|
|
633 |
In some situations, it is good to have information in a Function Call, which then
|
|
634 |
changes the way XML tags are generated. For this case, there are Pointers.
|
|
635 |
>>
|
|
636 |
|
|
637 |
p >>
|
|
638 |
The name should not mislead you; I took it because I chose the «*» symbol to declare them,
|
|
639 |
and that is the meaning of this symbol in the programming language C. The concept behind
|
|
640 |
is very easy.
|
|
641 |
>>
|
|
642 |
|
|
643 |
p >>
|
|
644 |
For example, it could be a good idea to generate a small HTML document containing some
|
|
645 |
content. For this case, the title of the page is a good case for using pointers:
|
|
646 |
>>
|
|
647 |
|
|
648 |
Code ||
|
|
649 |
decl page(*title) alias html {
|
|
650 |
head {
|
|
651 |
title *title;
|
|
652 |
}
|
|
653 |
body {
|
|
654 |
h1 *title;
|
|
655 |
content;
|
|
656 |
}
|
|
657 |
};
|
|
658 |
||
|
|
659 |
|
|
660 |
p >>
|
|
661 |
In the example above, calling «page('My Page') { p 'hello, world'; }» will result in
|
|
662 |
this XML output:
|
|
663 |
>>
|
|
664 |
|
|
665 |
Code ||
|
|
666 |
<html>
|
|
667 |
<head>
|
|
668 |
<title>My Page</title>
|
|
669 |
</head>
|
|
670 |
<body>
|
|
671 |
<h1>My Page</h1>
|
|
672 |
<p>hello, world</p>
|
|
673 |
</body>
|
|
674 |
</html>
|
|
675 |
||
|
|
676 |
|
|
677 |
p >>
|
|
678 |
Pointers can be referenced in any place in the Default Body of a «decl» statement, also for
|
|
679 |
generating extra tags. Then the value for a Pointer will be the tag name.
|
|
680 |
>>
|
|
681 |
|
|
682 |
p >>
|
|
683 |
Additionally, you can insert the value of a pointer as text by calling it with two leading
|
|
684 |
asterisks, i.e. if the pointer is defined as «*x», you can insert its value as text using: «**x».
|
|
685 |
>>
|
|
686 |
|
|
687 |
h4 id=pwt > Pointers without tags
|
|
688 |
|
|
689 |
p >>
|
|
690 |
To give a literal a name, you can define pointers to literals.
|
|
691 |
>>
|
|
692 |
|
|
693 |
Code ||
|
|
694 |
define *answer = 42;
|
|
695 |
something *answer;
|
|
696 |
||
|
|
697 |
|
|
698 |
p > will compile to:
|
|
699 |
|
|
700 |
Code | <something>42</something>
|
|
701 |
|
|
702 |
p >>
|
|
703 |
The «define» keyword as well as the asterisk «*» can be omitted. So this is
|
|
704 |
equivalent to the statements above:
|
|
705 |
>>
|
|
706 |
|
|
707 |
Code ||
|
|
708 |
answer = 42;
|
|
709 |
something *answer;
|
|
710 |
||
|
|
711 |
|
|
712 |
h4 > The pointer *_debug_trace
|
|
713 |
|
|
714 |
p >>
|
|
715 |
If you're calling ¬toolchain#processor yml2proc¬ with ¬toolchain#debug --debug¬, then this pointer is filled
|
|
716 |
with tracing info text, otherwise it's an empty string.
|
|
717 |
>>
|
|
718 |
|
|
719 |
h3 id=macros, "Macros";
|
|
720 |
|
|
721 |
p >>
|
|
722 |
Macros are a way to generate values for attributes with variable content. Macros can be set
|
|
723 |
like any other parameters; they're used for a text search & replace in the values of attributes
|
|
724 |
when attributes are generated.
|
|
725 |
>>
|
|
726 |
|
|
727 |
p >>
|
|
728 |
Parameters, which represent macros, are determined with a preceding «%» sign. They're
|
|
729 |
accounted for before any other parameter is accounted for in a function call, even if
|
|
730 |
they were defined after other parameters.
|
|
731 |
>>
|
|
732 |
|
|
733 |
p > An example:
|
|
734 |
|
|
735 |
Code ||
|
|
736 |
decl foo(%macro, myAttr="something %macro for testing");
|
|
737 |
|
|
738 |
testing
|
|
739 |
foo "nice";
|
|
740 |
||
|
|
741 |
|
|
742 |
p > This generates:
|
|
743 |
|
|
744 |
Code ||
|
|
745 |
<testing>
|
|
746 |
<foo myAttr="something nice for testing"/>
|
|
747 |
</testing>
|
|
748 |
||
|
|
749 |
|
|
750 |
h3 id=nullfunction > The Null Function
|
|
751 |
|
|
752 |
p >>
|
|
753 |
The function with the name «_» (underscore) is called Null Function. If you define this
|
|
754 |
function, then you're switching off the default behaviour, that trivial declares are done
|
|
755 |
automatically.
|
|
756 |
>>
|
|
757 |
|
|
758 |
p >>
|
|
759 |
Instead, unknown functions now call the Null Function. This can be very sensible together
|
|
760 |
with ¬#descending Descending Attributes¬:
|
|
761 |
>>
|
|
762 |
|
|
763 |
Code ||
|
|
764 |
decl _ +type +name alias func;
|
|
765 |
decl interface +name;
|
|
766 |
|
|
767 |
interface Testcase {
|
|
768 |
void f(in string input);
|
|
769 |
long getOptions();
|
|
770 |
}
|
|
771 |
||
|
|
772 |
|
|
773 |
p > compiles to:
|
|
774 |
|
|
775 |
Code ||
|
|
776 |
<interface name="Testcase">
|
|
777 |
<func type="void" name="f">
|
|
778 |
<parm>
|
|
779 |
<in/>
|
|
780 |
<string/>
|
|
781 |
<input/>
|
|
782 |
</parm>
|
|
783 |
</func>
|
|
784 |
<func type="long" name="getOptions"/>
|
|
785 |
</interface>
|
|
786 |
||
|
|
787 |
|
|
788 |
h2 id=quoting > Quoting Operators
|
|
789 |
|
|
790 |
p > Five different quoting operators implement different functionality:
|
|
791 |
|
|
792 |
h3 id=quote > Quote >
|
|
793 |
|
|
794 |
p > The «>» operator quotes into text nodes, doing XML escaping of text. An example:
|
|
795 |
|
|
796 |
Code | > this text will be put into a text node and these angle brackets <> will be quoted
|
|
797 |
|
|
798 |
p > Additionally, it can be used to implement an indention system, see ¬yslt YSLT¬ below.
|
|
799 |
|
|
800 |
p >>
|
|
801 |
Then an integer literal can be the first part of the operator; it gives the indention
|
|
802 |
level. For example:
|
|
803 |
>>
|
|
804 |
|
|
805 |
Code ||
|
|
806 |
0> this text is indented to the actual level and then output,
|
|
807 |
> followed by this text.\\n
|
|
808 |
|
|
809 |
1> this text is indented one indention level\\n
|
|
810 |
2> two levels\\n
|
|
811 |
1> one level again\\n
|
|
812 |
||
|
|
813 |
|
|
814 |
p >>
|
|
815 |
Quote text is being output by the ¬#textfunction «text» function¬.
|
|
816 |
>>
|
|
817 |
|
|
818 |
h3 id=blockquote > Block Quote >>
|
|
819 |
|
|
820 |
p {
|
|
821 |
> To include more lines of text into a single quoted area, use double «>>». The lines
|
|
822 |
> are concatenated together then. An example:
|
|
823 |
}
|
|
824 |
|
|
825 |
Code ||
|
|
826 |
p >>
|
|
827 |
This generates a text paragraph for HTML. All this text, which you can find in
|
|
828 |
these lines, is being concatenated together to one single text node, and then put
|
|
829 |
into the body of the <p> ... </p> tag.
|
|
830 |
>>
|
|
831 |
||
|
|
832 |
|
|
833 |
p >>
|
|
834 |
Block quote text is being output by the ¬#textfunction «text» function¬.
|
|
835 |
>>
|
|
836 |
|
|
837 |
h3 > Line Quote |
|
|
838 |
|
|
839 |
p > The «|» operator does the same as the «>» operator, adding a newline character to the text node.
|
|
840 |
|
|
841 |
p > Additionally, it can be used to implement an indention system, see ¬yslt YSLT¬ below.
|
|
842 |
|
|
843 |
p > Then it's used together with additional «>» symbols showing the grade of indention:
|
|
844 |
|
|
845 |
Code ||
|
|
846 |
| not indented
|
|
847 |
|> single indent
|
|
848 |
|>> double indent
|
|
849 |
(...)
|
|
850 |
||
|
|
851 |
|
|
852 |
p >>
|
|
853 |
Line quote text is being output by the ¬#textfunction «text» function¬.
|
|
854 |
>>
|
|
855 |
|
|
856 |
h3 > Block Line Quote ||
|
|
857 |
|
|
858 |
p >>
|
|
859 |
The «||» operator opens and closes a block of lines, which then are handled like if each of
|
|
860 |
them would be preceeded with a Line Operator «|».
|
|
861 |
>>
|
|
862 |
|
|
863 |
p > Sample:
|
|
864 |
|
|
865 |
Code {
|
|
866 |
| ||
|
|
867 |
||
|
|
868 |
this is code being quoted through
|
|
869 |
this is the second line
|
|
870 |
||
|
|
871 |
| ||
|
|
872 |
}
|
|
873 |
|
|
874 |
p > is equivalent to:
|
|
875 |
|
|
876 |
Code {
|
|
877 |
||
|
|
878 |
| this is code being quoted through
|
|
879 |
| this is the second line
|
|
880 |
||
|
|
881 |
}
|
|
882 |
|
|
883 |
p >>
|
|
884 |
Block line quote text is being output by the ¬#textfunction «text» function¬.
|
|
885 |
>>
|
|
886 |
|
|
887 |
h3 > Inserting Commands
|
|
888 |
|
|
889 |
p >>
|
|
890 |
Just like with a ¬http://en.wikipedia.org/wiki/Shell_(computing)#Unix_shells Unix shell¬,
|
|
891 |
you can insert statements into text by using backticks:
|
|
892 |
>>
|
|
893 |
|
|
894 |
Code ] | Click `a href="http://fdik.org/yml/" "this link"`, please!
|
|
895 |
|
|
896 |
p {
|
|
897 |
>>
|
|
898 |
Being in a Block Line Quote «||», you additionally can use the Line Command operator
|
|
899 |
(two backquotes,
|
|
900 |
>>
|
|
901 |
] ``).
|
|
902 |
}
|
|
903 |
|
|
904 |
p > This is very interesting to have in YSLT, for example:
|
|
905 |
|
|
906 |
Code {
|
|
907 |
| ||
|
|
908 |
| some code
|
|
909 |
] ``
|
|
910 |
> apply "myTemplate";\n
|
|
911 |
| some other code
|
|
912 |
| ||
|
|
913 |
}
|
|
914 |
|
|
915 |
h3 id=userop > User defined in-text Operators
|
|
916 |
|
|
917 |
p > You can define short cuts for inserting commands into text by defining operators.
|
|
918 |
|
|
919 |
p >>
|
|
920 |
Therefore, you need a ¬http://en.wikipedia.org/wiki/Regular_expression regular expression¬
|
|
921 |
for matching text and YML text for replacing with. Here an example, how this is used by YSLT:
|
|
922 |
>>
|
|
923 |
|
|
924 |
Code ] define operator "«(.*?)»" as value "%1";
|
|
925 |
|
|
926 |
p > The RegEx have ¬http://docs.python.org/library/re.html Python syntax¬.
|
|
927 |
|
|
928 |
p >>
|
|
929 |
In this example all matches to the RegEx will be replaced by the YML text in the «as» clause.
|
|
930 |
The text of the first group in the RegEx will replace the «%1» in the resulting YML text. You
|
|
931 |
can do that for more than one group – just use «%2» for the second group, «%3» for the third
|
|
932 |
one and so on.
|
|
933 |
>>
|
|
934 |
|
|
935 |
p > The «define» keyword can be omitted.
|
|
936 |
|
|
937 |
h3 id=quotethrough > Quote Through ]
|
|
938 |
|
|
939 |
p >>
|
|
940 |
The ¬http://en.wikipedia.org/wiki/Apple_II_series Apple ][¬ prompt operator just quotes
|
|
941 |
through directly into XML what it gets.
|
|
942 |
>>
|
|
943 |
|
|
944 |
p >>
|
|
945 |
If the first character of a command is a «<», then quote through is applied
|
|
946 |
automatically.
|
|
947 |
>>
|
|
948 |
|
|
949 |
p > This is the preferred way to output XML tags directly in YML:
|
|
950 |
|
|
951 |
Code ||
|
|
952 |
<output me="directly" />
|
|
953 |
|
|
954 |
] <!--
|
|
955 |
] add some comment, which then appears in XML
|
|
956 |
] -->
|
|
957 |
||
|
|
958 |
|
|
959 |
h2 id=including > Including YML files
|
|
960 |
|
|
961 |
p >>
|
|
962 |
You can include a second YML script file into an existing YML script file
|
|
963 |
at any place using one of the following:
|
|
964 |
>>
|
|
965 |
|
|
966 |
Code ||
|
|
967 |
include something.yml2
|
|
968 |
include "something else.yml2"
|
|
969 |
include 'anything addionally.yml2'
|
|
970 |
||
|
|
971 |
|
|
972 |
a name="ymlpath";
|
|
973 |
p >>
|
|
974 |
If you're not starting the filename with '.' or '/' as in the example above, then
|
|
975 |
if the «YML_PATH» environment variable is set to a colon separated list of directories,
|
|
976 |
these directories are being searched for the given filename. Otherwise, the local
|
|
977 |
directory is searched.
|
|
978 |
>>
|
|
979 |
|
|
980 |
p >>
|
|
981 |
Filename ¬http://en.wikipedia.org/wiki/Glob_(programming) globbing¬ using «*» and «?»
|
|
982 |
placeholders is supported to include more than one file at a time:
|
|
983 |
>>
|
|
984 |
|
|
985 |
Code | include part*.yml2
|
|
986 |
|
|
987 |
p >>
|
|
988 |
Filename globbing also can be used reverted; that means, the files are included in reverse
|
|
989 |
order:
|
|
990 |
>>
|
|
991 |
|
|
992 |
Code | include reverse part*.yml2
|
|
993 |
|
|
994 |
p > If there are the files part1.yml, part2.yml and part3.yml, part3.yml is included first now.
|
|
995 |
|
|
996 |
p > To include plain text as text nodes, you can use:
|
|
997 |
|
|
998 |
Code | include text some.txt
|
|
999 |
|
|
1000 |
p > To include ready made XML, use:
|
|
1001 |
|
|
1002 |
Code | include xml some.xml
|
|
1003 |
|
|
1004 |
h2 id=python > Escaping into Python – the Escape Operator !
|
|
1005 |
|
|
1006 |
p > You can insert a Python command at any place by using the «!» operator:
|
|
1007 |
|
|
1008 |
Code | !class X(str): pass
|
|
1009 |
|
|
1010 |
h3 > Python script Operator !!
|
|
1011 |
|
|
1012 |
p > You can use the double «!!» to include more than one line of Python code:
|
|
1013 |
|
|
1014 |
Code ||
|
|
1015 |
!!
|
|
1016 |
def fak(n):
|
|
1017 |
if n == 0:
|
|
1018 |
return 1
|
|
1019 |
else:
|
|
1020 |
return n * fak(n - 1)
|
|
1021 |
|
|
1022 |
def getName(id):
|
|
1023 |
return SQL("select name from customers where id='"+str(id)+"';")[0]
|
|
1024 |
!!
|
|
1025 |
||
|
|
1026 |
|
|
1027 |
h3 > Python generated parameters in Function Calls
|
|
1028 |
|
|
1029 |
p >>
|
|
1030 |
You may use Python expressions to generate names and/or values in Function Calls.
|
|
1031 |
To do so, embed the Python expression in «! ... !»:
|
|
1032 |
>>
|
|
1033 |
|
|
1034 |
Code ||
|
|
1035 |
f x=!fak(5)!;
|
|
1036 |
customer name=!getName(42)!;
|
|
1037 |
tag !getNextAttributeName()!=42;
|
|
1038 |
||
|
|
1039 |
|
|
1040 |
h3 > Python generated Function Calls
|
|
1041 |
|
|
1042 |
p >>
|
|
1043 |
You can generate text with a Python expression, which represents an YML Function Call.
|
|
1044 |
The resulting YML function is then executed. Also here, embed the Python expression
|
|
1045 |
in «! ... !»:
|
|
1046 |
>>
|
|
1047 |
|
|
1048 |
Code | !getTagName() + " " + getAttrib() + "='" + getValue() + "'"!
|
|
1049 |
|
|
1050 |
h3 > Using Pointers as values in Python function calls
|
|
1051 |
|
|
1052 |
p >>
|
|
1053 |
Sometimes it is useful to call a generating Python function using information of a
|
|
1054 |
YML Function Call. For that case, there is the «python» statement in YML. You can
|
|
1055 |
call there a single Python function using YML Pointers as parameters.
|
|
1056 |
>>
|
|
1057 |
|
|
1058 |
p > This is used in the YSLT specification, for example:
|
|
1059 |
|
|
1060 |
Code ||
|
|
1061 |
decl apply(select, *indent=1) alias apply-templates {
|
|
1062 |
python withIndent(*indent);
|
|
1063 |
content;
|
|
1064 |
};
|
|
1065 |
||
|
|
1066 |
|
|
1067 |
h2 id=comments > Comments //, /* */
|
|
1068 |
|
|
1069 |
p > Comments are written like in Java or C++:
|
|
1070 |
|
|
1071 |
Code ||
|
|
1072 |
// this is a comment
|
|
1073 |
something() { // this is a comment after a tag
|
|
1074 |
/* this is some comment, too */
|
|
1075 |
||
|
|
1076 |
|
|
1077 |
p > After Quoting Operators, comments are not possible. Instead, they're quoted through:
|
|
1078 |
|
|
1079 |
Code ||
|
|
1080 |
// the following line you'll find in the output document
|
|
1081 |
> this text is being output // and this too
|
|
1082 |
||
|
|
1083 |
|
|
1084 |
div id=bottom {
|
|
1085 |
> ¬programming << Using YML 2¬
|
|
1086 |
> ¬#top ^Top^¬
|
|
1087 |
> ¬yslt >> show me YSLT¬
|
|
1088 |
> ¬features.en.yhtml2 (source)¬
|
|
1089 |
}
|
|
1090 |
}
|