0
|
1 |
This is a TODO file for XSL-T 2.0 support.
|
|
2 |
|
|
3 |
- LHF:
|
|
4 |
* Warning bug, last parameter is always whined about.
|
|
5 |
* Box in comment/PI/text/ws(?) handling -- pending Matthias
|
|
6 |
* type036 -- namespace on top element isn't copied
|
|
7 |
* XTDE0865
|
|
8 |
* Attend XSLTTokenizer::isXSLT()
|
|
9 |
* Remove redundant set() calls in setFocusHelper().
|
|
10 |
|
|
11 |
- Missing features:
|
|
12 |
General Priority
|
|
13 |
---------------------
|
|
14 |
* 1.0 QXmlQuery::evaluateTo(QIODevice *) P1 DONE
|
|
15 |
* 1.0 Test suite integration P1 DONE
|
|
16 |
* 1.0 xsl:key P1
|
|
17 |
* 1.0 fn:key() P1
|
|
18 |
* 1.0 2.0 Compatibility mode P1
|
|
19 |
* 1.0 Regular parameters in templates P1
|
|
20 |
* 1.0 xsl:include P1
|
|
21 |
* 1.0 xsl:copy-of P1
|
|
22 |
* 1.0 xsl:copy P1
|
|
23 |
* 1.0 xsl:import P1
|
|
24 |
* 1.0 fn:format-number P1
|
|
25 |
* 1.0 xsl:message P2
|
|
26 |
* 1.0 fn:current() P1 DONE
|
|
27 |
* 2.0 fn:type-available() P3 DONE
|
|
28 |
* 2.0 xsl:use-when P3
|
|
29 |
* 2.0 fn:unparsed-entity-uri() P3
|
|
30 |
* 2.0 fn:unparsed-entity-public-id() P3
|
|
31 |
* 2.0 Tunnel Parameters P3
|
|
32 |
* 2.0 xsl:attribute-set P3
|
|
33 |
* 1.0 xsl:decimal-format P2
|
|
34 |
* 1.0 xmlpatterns: initial template P1 DONE
|
|
35 |
* 1.0 xsl:number P1
|
|
36 |
* 1.0 Complete handling of xsl:sort P2
|
|
37 |
* 2.0 Grouping
|
|
38 |
- fn:current-group()
|
|
39 |
- fn:grouping-key()
|
|
40 |
- xsl:for-each-group()
|
|
41 |
* 2.0 Regexp
|
|
42 |
- xsl:analyze-string
|
|
43 |
- xsl:matching-substring
|
|
44 |
- xsl:non-matching-substring
|
|
45 |
- fn:regex-group()
|
|
46 |
* 2.0 Date & Time formatting
|
|
47 |
- fn:format-dateTime()
|
|
48 |
- fn:format-date()
|
|
49 |
- fn:format-time()
|
|
50 |
|
|
51 |
Serialization & Output:
|
|
52 |
----------------------
|
|
53 |
* 1.0 xsl:output
|
|
54 |
--- Tie together serialization. Should we add
|
|
55 |
QXmlQuery::evaluateTo(QIODevice 1.0 const) ?
|
|
56 |
* 2.0 xsl:character-maps
|
|
57 |
* 2.0 xsl:character-map
|
|
58 |
* 2.0 xsl:result-document
|
|
59 |
--- Should the "default output" be handle with xsl:result-document? Would
|
|
60 |
depend on compilation.
|
|
61 |
|
|
62 |
Optimizations:
|
|
63 |
* Remove adjacent text node constructors
|
|
64 |
* Remove string-join when first arg's static cardinality is not more than one
|
|
65 |
* Remove string-join when the second arg is statically known to be the empty string.
|
|
66 |
* Remove string-join when the second arg is a single space and the parent is a text node ctor.
|
|
67 |
* Rewrite to operand if operands are one. What about type conversions?
|
|
68 |
* Replace lookups with xml:id with calls on id().
|
|
69 |
* Recognize that a/(b, c) is equal to a/(b | c). The later does selection and node sorting in one step.
|
|
70 |
* Remove LetClause which has empty sequence as return clause, or no variable dependencies at all.
|
|
71 |
* Do a mega test for rewriting /patterns/:
|
|
72 |
"node() | element()" => element()
|
|
73 |
"comment() | node()" => comment()
|
|
74 |
|
|
75 |
and so forth. This sometimes happens in poorly written patterns. How does
|
|
76 |
this rewrite affect priority calculation?
|
|
77 |
|
|
78 |
Tests:
|
|
79 |
* xml:id
|
|
80 |
- Come on, the stuff needs to be reorganized xml:id.
|
|
81 |
- Read in xml:id document with whitespace in attrs, write the doc out. Attrs should be normalized.
|
|
82 |
- Do lookups of IDs with xml:id attrs containing whitespace.
|
|
83 |
|
|
84 |
* current()
|
|
85 |
- Use current() inside each instruction
|
|
86 |
- In a template pattern
|
|
87 |
- Several invocations: current()/current()/current()
|
|
88 |
|
|
89 |
|
|
90 |
* Diagnosticsts:
|
|
91 |
- See http://www.w3.org/Bugs/Public/show_bug.cgi?id=5643 . Comments
|
|
92 |
should be taken into account when comparing. This suggests that we
|
|
93 |
don't have any test which produces a document with XML comments.
|
|
94 |
|
|
95 |
* element-available()
|
|
96 |
- Review the tests.
|
|
97 |
- Try using declarations in XSL-T, should return false
|
|
98 |
- Use xsl:variable(both instr and decl)
|
|
99 |
- invoke with all the XSL-T instructions.
|
|
100 |
- Should return false for when, otherwise, matching-substring, non-matching-substring, etc?
|
|
101 |
- Supply the namespace in the name via the default namespace, no prefix.
|
|
102 |
|
|
103 |
* unparsed-text()
|
|
104 |
- Load an empty file
|
|
105 |
- Use a fragment in the URI
|
|
106 |
- Use an invalid URI
|
|
107 |
- Use device bindings and a QRC to ensure that we're not using a generic
|
|
108 |
network manager.
|
|
109 |
- Duplicate all the network tests. Same as for doc()
|
|
110 |
|
|
111 |
* unparsed-text-available()
|
|
112 |
- Same as for unparsed-text()
|
|
113 |
|
|
114 |
* Sequence constructor that contains only:
|
|
115 |
- XML comment
|
|
116 |
- whitespace text node
|
|
117 |
- processing instruction
|
|
118 |
- a mix of the three
|
|
119 |
|
|
120 |
* xsl:function
|
|
121 |
- Ensure that it's not it's not in scope for use-when.
|
|
122 |
- xsl:function/xsl:param: use processing instructions, whitespace and comments as child: should be stripped
|
|
123 |
- Use <xsl:function/> : @name missing.
|
|
124 |
- Don't strip ws, and have ws between two xsl:param, and between xsl:function and xsl:param.
|
|
125 |
- Use xsl:function with no body.
|
|
126 |
- use xsl:param/@tunnel = no
|
|
127 |
- use xsl:param/@tunnel = yes
|
|
128 |
- use an invalid value for xsl:param/@tunnel = yes
|
|
129 |
- Have a non-WS text node in xsl:function/xsl:param/
|
|
130 |
- Have a WS text node in xsl:function/xsl:param/
|
|
131 |
- Have a WS text node in xsl:function/xsl:param/ while preserving WS.
|
|
132 |
- use a comment as child of xsl:param
|
|
133 |
- use a PI as child of xsl:param
|
|
134 |
- XTSE0770 with import precedence and all that.
|
|
135 |
- have two identical function in the stylesheet. The last has override=no. Should still report XTSE0770.
|
|
136 |
- have @override with invalid value.
|
|
137 |
- have whitespace inside xsl:param with different strip modes.
|
|
138 |
- Have @select => error
|
|
139 |
- Have body => error
|
|
140 |
- call current() inside body. XPDY0002?
|
|
141 |
|
|
142 |
* Does xml:base/StaticBaseURI and StaticCompatiblityStore prevent proper
|
|
143 |
type checking due to expectedOperandTypes() returns item()*?
|
|
144 |
|
|
145 |
* xsl:template/xsl:param
|
|
146 |
- Have @required=yes, and have @select => error
|
|
147 |
- Have @required=yes, and have body => error
|
|
148 |
- Have a variable reference in a template after another, which has
|
|
149 |
param, to ensure they aren't in scope.
|
|
150 |
|
|
151 |
* xsl:template/@match
|
|
152 |
- Have a pattern with unions, and have a body which relies on its
|
|
153 |
static type.
|
|
154 |
|
|
155 |
* @version:
|
|
156 |
Have @version on *all* attributes.
|
|
157 |
|
|
158 |
* xsl:call-template
|
|
159 |
- Have a variable reference just after a xsl:call-template which has
|
|
160 |
with-param, to ensure they aren't in scope.
|
|
161 |
- Have an xsl:with-param which isn't used in the template. Error?
|
|
162 |
- Have an xsl:with-param that has a type error.
|
|
163 |
- an xsl:with-param is not in scope for the next one. Test this => error.
|
|
164 |
- Have a call:template, whose with-param computes its value by calling
|
|
165 |
another template, while using an with-param too.
|
|
166 |
|
|
167 |
* XQuery:
|
|
168 |
- DONE Ensure namespace {expr} {expr} is flagged as invalid
|
|
169 |
- Use all XSL-T functions: error. Or we do that already?
|
|
170 |
- Ensure order by collation 1 + 1 is an error
|
|
171 |
- Ensure order by collation {1 + 1} is an error
|
|
172 |
|
|
173 |
* document()
|
|
174 |
- Basic node deduplication, no test exists for that.
|
|
175 |
|
|
176 |
* xsl:perform-sort
|
|
177 |
- Have no xsl:sort. Error. Must be at least one.
|
|
178 |
- have xsl:sort with invalid value.
|
|
179 |
- sort atomic values.
|
|
180 |
- Trigger "The stable attribute is permitted only on the first xsl:sort element within a sort key specification"
|
|
181 |
- have xsl:sort with no select and no seq ctor.
|
|
182 |
- trigger the delegated queueing. All instructions inside.. xsl:sort?
|
|
183 |
- have multiple sort statements, with the last being <xsl:sort/> only.
|
|
184 |
- have WS between xsl:sort that is not ignorable.
|
|
185 |
- Use a variable reference whose name is equal to our synthetic name. This should be XPST0008, but probably isn't.
|
|
186 |
- Have an invalid value in xsl:sort/order. Use space
|
|
187 |
- have xsl:sort return numbers, but data-type specify string.
|
|
188 |
- have an AVT in xsl:sort/@lang
|
|
189 |
- have an AVT in xsl:sort/@case-order
|
|
190 |
- have an AVT in xsl:sort/@data-type
|
|
191 |
- have an AVT in xsl:sort/@stable
|
|
192 |
- Have mixed result, and hence incorrectly trigger XPTY0018 which the code currently raise.
|
|
193 |
- Depend on the context position inside xsl:sort, when being child of
|
|
194 |
perform-sort. Currently we create singleton focuses(I think), while
|
|
195 |
we want the focus to be over the whole input sequence, not on indivual items.
|
|
196 |
- Have <xsl:perform-sort select="valid-expr"/>: xsl:sort is missing
|
|
197 |
- Use current() in the xsl:sort and the body, to ensure the right scope is picked up
|
|
198 |
|
|
199 |
* xsl:copy-of
|
|
200 |
- Have a text node. It's not allowed.
|
|
201 |
- Have PIs, comments, and ignorable whitespace as children. Sigh.
|
|
202 |
|
|
203 |
* xsl:namespace
|
|
204 |
- Use xsl:fallback.
|
|
205 |
- Use xsl:namespace inside xsl:variable and introspec the result in various
|
|
206 |
ways. This is a big area, we don't have namespace nodes in XQuery. Yes, calling evaluateSingleton() will probably crash.
|
|
207 |
- Use no select and no body, error: XTSE0910
|
|
208 |
- Have name expression evaluate to the empty sequence.
|
|
209 |
|
|
210 |
* Sequence ctor that:
|
|
211 |
- Has invalid element in XSL namespace. E.g, xsl:foo
|
|
212 |
|
|
213 |
* xsl:import
|
|
214 |
- Have element as child as xsl:import: disallowed.
|
|
215 |
- Have text as child as xsl:import: disallowed.
|
|
216 |
- Have PIs and comments as child as xsl:import: allowed.
|
|
217 |
|
|
218 |
* xsl:include
|
|
219 |
- Have element as child as xsl:include: disallowed.
|
|
220 |
- Have text as child as xsl:include: disallowed.
|
|
221 |
- Have PIs and comments as child as xsl:include: allowed.
|
|
222 |
|
|
223 |
* xsl:strip-space
|
|
224 |
- Have PIs, comments, whitespace as child.
|
|
225 |
|
|
226 |
* xsl:element
|
|
227 |
- Extract EBV from result.
|
|
228 |
- Use space in validation element.
|
|
229 |
|
|
230 |
* xsl:perform-sort
|
|
231 |
- Have PIs and comments in between xsl:sort elements.
|
|
232 |
|
|
233 |
* xml:space
|
|
234 |
- We never pop our stack. Fix the bug, and ensure we have tests for it.
|
|
235 |
|
|
236 |
* fn:unparsed-entity-uri
|
|
237 |
- Check type of return value
|
|
238 |
- Do basic unparsed-entity-uri("does-not-exist")
|
|
239 |
|
|
240 |
* fn:unparsed-entity-public-id
|
|
241 |
- Do basic unparsed-entity-uri("does-not-exist"), two permutations, check the spec
|
|
242 |
|
|
243 |
* xsl:element
|
|
244 |
- Use disallowed attribute: select
|
|
245 |
- use unknown type in @type
|
|
246 |
- Use @namespace, but be not in the lexical space of xs:anyURI
|
|
247 |
- use disallowed enumeration in @validation
|
|
248 |
- have a name expression that evaluates to a xs:QName value as opposed to a string.
|
|
249 |
- have a name expression that evaluates to a xs:QName value as opposed to a string. but
|
|
250 |
also have the namespace attribute
|
|
251 |
|
|
252 |
* xsl:attribute
|
|
253 |
- Use disallowed attribute: match
|
|
254 |
- use unknown type in @type
|
|
255 |
- Use @namespace, but be not in the lexical space of xs:anyURI
|
|
256 |
- use disallowed enumeration in @validation
|
|
257 |
- have a name expression that evaluates to a xs:QName value as opposed to a string.
|
|
258 |
- have a name expression that evaluates to a xs:QName value as opposed to a string. but
|
|
259 |
also have the namespace attribute
|
|
260 |
|
|
261 |
* xsl:template
|
|
262 |
- Use the union keyword, it's forbidden, only "|" is allowed
|
|
263 |
- Use an expression other than Literal and VarRef in KeyValue[8]
|
|
264 |
- use a function other than key().
|
|
265 |
- have a declaration that only can apperar as a child of xsl:stylesheet.
|
|
266 |
- Have an element in the XSL-T namespace, but which is invalid, e.g "bar"
|
|
267 |
- Use an axis other than child or attribute in pattern.
|
|
268 |
- Have a template that no no match and no name attribute., XTSE0500
|
|
269 |
- use child::document-node() in pattern
|
|
270 |
- use @foo/child in pattern
|
|
271 |
- apply templates to parentless attributes.
|
|
272 |
- Have 3e3 in @priority
|
|
273 |
- Have a @match with more than two alternatives, e.g "a | b | c", and have them all actually matching.
|
|
274 |
- Use an XML name in the mode so we trigger
|
|
275 |
NCNameConstructor::validateTargetName()
|
|
276 |
- A template which only has a non-WS text node.
|
|
277 |
- A template with param, followed by text node.
|
|
278 |
|
|
279 |
* Simplified stylesheet
|
|
280 |
- Use @version attribute only on doc element. Should fail, since @{XSL-T]version must be present
|
|
281 |
|
|
282 |
* fn:current()
|
|
283 |
- Have <xsl:value-of select="current()"/>
|
|
284 |
|
|
285 |
* xsl:variable have a variable reference appearing before its global declaration, and then somehow trigger recursion.
|
|
286 |
* xsl:choose
|
|
287 |
- elements/nodes intermixed with xsl:choose/xsl:when
|
|
288 |
- invalid attribute on xsl:choose
|
|
289 |
- invalid attribute on xsl:when
|
|
290 |
- invalid attribute on xsl:otherwise
|
|
291 |
- invalid attribute on xsl:if
|
|
292 |
- invalid attribute on xsl:template
|
|
293 |
- invalid attribute on xsl:stylesheet
|
|
294 |
- invalid attribute on xsl:transform
|
|
295 |
- xsl:otherwise in the middle between xsl:when elements.
|
|
296 |
- use namespace declarations on xsl:when
|
|
297 |
- use namespace declarations on xsl:otherwise
|
|
298 |
- use namespace declarations on xsl:choose
|
|
299 |
|
|
300 |
* Namespaces:
|
|
301 |
- Have:
|
|
302 |
<xsl:sequence xmlns:bar="http://example.com/" select="1"/>
|
|
303 |
<xsl:sequence select="bar:foo()"/>
|
|
304 |
|
|
305 |
* XPath
|
|
306 |
- For each XQuery-specific expression, add a test using that expression:
|
|
307 |
- typeswitch
|
|
308 |
- let
|
|
309 |
- validate
|
|
310 |
- extension expression
|
|
311 |
- unordered
|
|
312 |
- ordered
|
|
313 |
- for
|
|
314 |
- computed text node constructor
|
|
315 |
- computed attribute constructor
|
|
316 |
- computed comment constructor
|
|
317 |
- computed PI constructor
|
|
318 |
- computed element constructor
|
|
319 |
- computed document constructor
|
|
320 |
- direct element constructor
|
|
321 |
- direct comment constructor
|
|
322 |
- direct PI constructor
|
|
323 |
- all declarations
|
|
324 |
|
|
325 |
- Use all the predefined prefixes in XQuery; non are in XSL-T.
|
|
326 |
|
|
327 |
* xsl:when
|
|
328 |
- Use xml:space on it
|
|
329 |
|
|
330 |
* xsl:otherwise
|
|
331 |
- Use xml:space on it
|
|
332 |
|
|
333 |
* xsl:version
|
|
334 |
- Use letters, XTSE0110
|
|
335 |
- Use a float: 2e3, XTSE0110
|
|
336 |
- Use a weird number, 2.00000001
|
|
337 |
|
|
338 |
* xsl:document
|
|
339 |
- use disallowed attribute: select.
|
|
340 |
- use unknown type in @type
|
|
341 |
- use disallowed enumeration in @validation
|
|
342 |
- What happens if the type in @type is unknown?
|
|
343 |
- Use xml:base attr and check URI.
|
|
344 |
|
|
345 |
* xsl:sequence
|
|
346 |
- use match attribute
|
|
347 |
|
|
348 |
* xsl:stylesheet
|
|
349 |
- Use @xsl:default-collation on xsl:stylesheet. Shouldn't have any effect. Or?
|
|
350 |
- Use an XSL-T instruction as child -- invalid.
|
|
351 |
- Have an element in the XSL-T namespace, but which is invalid, e.g "foo"
|
|
352 |
- Have xsl:default-collation="http://example.com/" on xsl:stylesheet
|
|
353 |
- Use prefix local: in say a function name. Not allowed.
|
|
354 |
- Use comments after document element.
|
|
355 |
- XTSE0010: <xsl:invalid version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"/>
|
|
356 |
- Change the version with @xsl:version on all elements that we have.
|
|
357 |
|
|
358 |
* Patterns.
|
|
359 |
- Basic */* test:
|
|
360 |
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:template match="*/*"><xsl:sequence select="'MATCH'"/></xsl:template>
|
|
361 |
|
|
362 |
|
|
363 |
</xsl:stylesheet>
|
|
364 |
|
|
365 |
- Basic a/b test:
|
|
366 |
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:template match="a/b"><xsl:sequence select="'MATCH'"/></xsl:template>
|
|
367 |
|
|
368 |
|
|
369 |
</xsl:stylesheet>
|
|
370 |
* xsl:strip-whitespace
|
|
371 |
- Use a namespace prefix which is not unboudn
|
|
372 |
- have a syntax error in one of the node tests
|
|
373 |
|
|
374 |
* xsl:preserve-whitespace
|
|
375 |
- Use a namespace prefix which is not unboudn
|
|
376 |
- have a syntax error in one of the node tests
|
|
377 |
|
|
378 |
* xsl:value-of
|
|
379 |
- select attribute, and comment in body(error, XTSE0870)
|
|
380 |
- select attribute, and processing instruction in body(error, XTSE0870)
|
|
381 |
- select attribute, and CCDATA in body(error, XTSE0870)
|
|
382 |
- select attribute, and element in body(error, XTSE0870)
|
|
383 |
- use xsl:sequence in body. Default separator should be none.
|
|
384 |
- use match attribute
|
|
385 |
- use double apostrophes/quotes. How are they dealt with?
|
|
386 |
|
|
387 |
* xsl:apply-templates
|
|
388 |
- use match attribute
|
|
389 |
- apply in a mode for which no templates are declared
|
|
390 |
- apply in a mode which is mispelled for another.
|
|
391 |
- Have: <xsl:apply-templates select="id('id2')/a | id('id5')"/>
|
|
392 |
We CRASH
|
|
393 |
|
|
394 |
* xsl:for-each
|
|
395 |
- No body: <xsl:for-each select="abc"/>
|
|
396 |
- No select attribute: <xsl:for-each>text</xsl:for-each>
|
|
397 |
- Have mixed result, and hence incorrectly trigger XPTY0018 which the code currently raise.
|
|
398 |
- Have:
|
|
399 |
<xsl:for-each select="1, 'asd'">
|
|
400 |
<xsl:sequence select="."/>
|
|
401 |
</xsl:for-each>
|
|
402 |
|
|
403 |
* xsl:variable
|
|
404 |
- Test that function conversion rules are invoked
|
|
405 |
- For what is an xsl:variable in scope? Where does the spec state it? Test
|
|
406 |
that it is not in scope where applicable.
|
|
407 |
- Have: <variable name="a" select=""/>
|
|
408 |
|
|
409 |
* xsl:text
|
|
410 |
- count the result of a template that has text node(non-ws),
|
|
411 |
xsl:text(content), xsl:content(zero content), text node(non-ws
|
|
412 |
- Have an element inside xsl:text: XTSE0010.
|
|
413 |
- Use comments and PIs intermixed with text inside.
|
|
414 |
|
|
415 |
* xsl:for-each
|
|
416 |
- use match attribute
|
|
417 |
- What should this produce? Saxon produces "123" but with xsl:text removed, "1 2 3".
|
|
418 |
<xsl:template match="/">
|
|
419 |
<xsl:for-each select="1 to 3">
|
|
420 |
<xsl:sequence select="."/>
|
|
421 |
<xsl:text></xsl:text>
|
|
422 |
</xsl:for-each>
|
|
423 |
</xsl:template>
|
|
424 |
|
|
425 |
* xsl:if
|
|
426 |
- Have <xsl:if test="">body</xsl:if>. Error
|
|
427 |
- Have <xsl:if test="valid-test"/>. That is, empty body.
|
|
428 |
|
|
429 |
* xsl:sequence
|
|
430 |
- select attribute missing: <xsl:sequence/>
|
|
431 |
- content other than xsl:fallback, e.g text node.
|
|
432 |
- How do we sort?
|
|
433 |
|
|
434 |
* for every state for XSL-T parsing:
|
|
435 |
- Use invalid element that is in the XSL-T namespace.
|
|
436 |
|
|
437 |
* In all cases expressions are queued/generated:
|
|
438 |
- Trigger expression precedence bugs, due to lack of paranteses.
|
|
439 |
|
|
440 |
* Use xml:space in stylsheeet that doesn't have value preserve nor default.
|
|
441 |
* For each case we have while(!reader.atEnd()):
|
|
442 |
- test that triggers parser error and that we detect it properly.
|
|
443 |
|
|
444 |
* for every element that allows text:
|
|
445 |
* Use CDATA. QXmlStreamReader distinguishes between the two. text before and after.:wa
|
|
446 |
* Use XML Comments and split up text nodes.
|
|
447 |
|
|
448 |
* Patterns:
|
|
449 |
* Ensure node() doesn't match document nodes().
|
|
450 |
* "//" is an invalid pattern
|
|
451 |
* Is there some expression which has no children? findAxisStep()
|
|
452 |
* Use @*/asdo
|
|
453 |
* XPST0003: key(concat("abc", "def"), "abc")
|
|
454 |
* XPST0003: id(concat("abc", "def"))
|
|
455 |
* XPST0003: concat('abc', 'def') // WILL CRASH
|
|
456 |
* XPST0003: unknownFunction()
|
|
457 |
* Use double: key("abc", 3e3)
|
|
458 |
* Use three argument key() in pattern.
|
|
459 |
|
|
460 |
* Simplified stylsheet modules:
|
|
461 |
* Omit the xsl:version attribute. XTSE0010
|
|
462 |
|
|
463 |
* type-available()
|
|
464 |
* We have no tests at all?
|
|
465 |
|
|
466 |
* have xml:base on the following elements and check them with
|
|
467 |
static-base-uri():
|
|
468 |
- all instructions
|
|
469 |
- all declarations, eg:
|
|
470 |
- xsl:choose, xsl:choice, xsl:otherwise
|
|
471 |
- xsl:template
|
|
472 |
- xsl:function
|
|
473 |
- etc
|
|
474 |
|
|
475 |
Embedded stylesheet modules
|
|
476 |
- Verify that we don't choke on xsl attrs with invalid attributes outside;
|
|
477 |
"In an embedded stylesheet module, standard attributes appearing on
|
|
478 |
ancestors of the outermost element of the stylesheet module have no effect."
|
|
479 |
|
|
480 |
Parsing:
|
|
481 |
- Error message for:
|
|
482 |
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
|
483 |
<xsl:template match="/">
|
|
484 |
<e/>
|
|
485 |
</xsl:stylesheet>
|
|
486 |
- Use the document "<do/" as focus.
|
|
487 |
- Write a test for each call to checkForParseError();
|
|
488 |
|
|
489 |
|
|
490 |
function-available:
|
|
491 |
- Generally low coverage it seems.
|
|
492 |
|
|
493 |
|
|
494 |
<xsl:template match="/"/> <!-- t0 -->
|
|
495 |
<xsl:template match="*"/> <!-- t1 -->
|
|
496 |
<xsl:template match="asd"/> <!-- t2 -->
|
|
497 |
<xsl:template match="comment()"/> <!-- t3 -->
|
|
498 |
<xsl:template match="a/b"/> <!-- t4 -->
|
|
499 |
|
|
500 |
<xsl:apply-templates select="*"/>
|
|
501 |
|
|
502 |
|
|
503 |
*(
|
|
504 |
((/)/call-template(t0))
|
|
505 |
(*/call-template(t1))
|
|
506 |
(element(asd)/call-template(t2))
|
|
507 |
(comment()/call-template(t3))
|
|
508 |
(a/b/call-template(t3))
|
|
509 |
)
|
|
510 |
|
|
511 |
==>
|
|
512 |
|
|
513 |
*/typeswitch(.)
|
|
514 |
case $g0 as document-root() return call-template(t0)
|
|
515 |
case $g0 as element() return call-template(t1)
|
|
516 |
case $g0 as element(asd) return call-template(t2)
|
|
517 |
case $g0 as comment() return (call-template(t3)
|
|
518 |
case $g0 as a/b return (call-template(t4)
|
|
519 |
|
|
520 |
|
|
521 |
Patterns are used in:
|
|
522 |
- xsl:for-each-group/@group-starting-with
|
|
523 |
- xsl:key/@match
|
|
524 |
- xsl:number/(@count, @from)
|
|
525 |
- xsl:template/@match
|
|
526 |
|
|
527 |
|
|
528 |
|
|
529 |
c/b
|
|
530 |
=>
|
|
531 |
child-or-self::element(b)[parent::element(c)]
|
|
532 |
|
|
533 |
c/b/a
|
|
534 |
=>
|
|
535 |
child-or-self::element(a)[parent::element(b)[parent::element(c)]]
|
|
536 |
|
|
537 |
d/c/b/a
|
|
538 |
=>
|
|
539 |
child-or-self::element(a)[parent::element(b)[parent::element(c)[parent::element(d)]]]
|
|
540 |
|
|
541 |
|
|
542 |
|
|
543 |
-----------------------------------
|
|
544 |
<xsl:apply-templates select="foo"/>
|
|
545 |
=>
|
|
546 |
|
|
547 |
child::element(foo) map apply-template(#default)
|
|
548 |
-----------------------------------
|
|
549 |
|
|
550 |
-----------------------------------
|
|
551 |
<xsl:apply-templates mode="yo" select="foo">
|
|
552 |
<xsl:sort select="@bar"/>
|
|
553 |
</xsl:apply-templates>
|
|
554 |
=>
|
|
555 |
|
|
556 |
let $g0 := for $g1 in child::element(foo)
|
|
557 |
order by @bar
|
|
558 |
return $g1
|
|
559 |
return apply-template(yo)
|
|
560 |
-----------------------------------
|
|
561 |
|
|
562 |
-----------------------------------
|
|
563 |
<xsl:perform-sort select="$in">
|
|
564 |
<xsl:sort select="@sortKey"/>
|
|
565 |
</xsl:perform-sort>
|
|
566 |
|
|
567 |
=>
|
|
568 |
|
|
569 |
sort $in/order by @sortKey
|
|
570 |
-----------------------------------
|
|
571 |
|
|
572 |
|
|
573 |
-----------
|
|
574 |
|
|
575 |
John Snelson of Oracle Berkeley DB XML & XQilla writes in private mail:
|
|
576 |
|
|
577 |
I'd had the same thought myself, too - you must be reading my mind ;-)
|
|
578 |
|
|
579 |
What is he referring to?
|
|
580 |
|
|
581 |
If one spends some time on fancy diagrams, QtXmlPatterns[LINK]'s, the XQuery
|
|
582 |
engine that shipped in Qt 4.4, architecture looks like this:
|
|
583 |
|
|
584 |
|
|
585 |
Recently I've started implementing XSL-T 2.0(hopefully to be done for Qt 4.5)
|
|
586 |
and the whole approach to this is modifying the existing codebase as follows:
|
|
587 |
|
|
588 |
|
|
589 |
|
|
590 |
|
|
591 |
|
|
592 |
|
|
593 |
Put differently, when QtXmlPatterns is dealing with XSL-T stylesheets, it
|
|
594 |
replaces the XQuery tokenizer with a tokenizer which translates the
|
|
595 |
stylesheet into XQuery tokens, that is consumed by the existing XQuery
|
|
596 |
parser, extended with both grammar non-terminals and tokens to accomodate the
|
|
597 |
XSL-T features that XQuery doesn't have. In compiler terms, it can be seen as
|
|
598 |
an "extreme" frontend. Not only is the same intermediate representation used,
|
|
599 |
the grammar is too.
|
|
600 |
|
|
601 |
What is the point of this?
|
|
602 |
|
|
603 |
The functional overlaps XQuery, XSL-T and others as well have is of course
|
|
604 |
widely established. Even the specifications are at times generated from the
|
|
605 |
same source documents, and that implementations subsequently modularize code
|
|
606 |
is of course second nature to any engineer, and seen to some degree or
|
|
607 |
another in contemporary implementations. Typically this happens in a
|
|
608 |
traditional fashion, classes are re-used, their functionality widened to
|
|
609 |
cover both/more languages. However, I believe doing it directly on the
|
|
610 |
grammar level introduce several advantages.
|
|
611 |
|
|
612 |
The parser is based on Bison and since it's not running in the experimental
|
|
613 |
pull mode, it uninterruptedly calls the tokenizer. The tokenizer, class
|
|
614 |
XSLTTokenizer, in turns calls an pull-based XML parser: QXmlStreamReader.
|
|
615 |
What often complicate in ocassions like this is who that gets the right to
|
|
616 |
call who, and who gets the convenience of tracking state in a natural way
|
|
617 |
through a call stack.
|
|
618 |
|
|
619 |
XSLTTokenizer is conveniently implemented: as it encounters declarations and
|
|
620 |
instructions in the stylsheet, it recursively descends in the XSL-T grammar
|
|
621 |
through its own functions, adding tokens to a queue, which is delivered to
|
|
622 |
the parser when asked -- and when the queue is empty it resumes queuing
|
|
623 |
tokens. The tokenizer is fairly crude, it queues up tokens for instructions
|
|
624 |
uninterrupted, and only have states between declarations. Hence,
|
|
625 |
XSLTTokenizer queues up tokens for each template and function body, but
|
|
626 |
enters "delivery mode" inbetween. This of course periodically breaks
|
|
627 |
streaming since it's buffering up tokens, but considering that the memory
|
|
628 |
usage for tokens is low and that a finer granularity for states(say, being
|
|
629 |
able to pop the stacks when being inbetween two xsl:when elements) requires a
|
|
630 |
significant effort, this is fine until proven otherwise.
|
|
631 |
|
|
632 |
|
|
633 |
Advantages
|
|
634 |
---------------
|
|
635 |
discuss analysis.
|
|
636 |
|
|
637 |
|
|
638 |
XSLTTokenizer rewrite XSL-T to XQuery as follows:'
|
|
639 |
|
|
640 |
Instructions
|
|
641 |
-------------
|
|
642 |
xsl:if An if/then/else expression whose else branch is the empty sequence
|
|
643 |
|
|
644 |
xsl:choose: again, a nesting of if/then/else expressions
|
|
645 |
|
|
646 |
xsl:value-of: a computed text node constructor. Its body contains a call to
|
|
647 |
string-join() involving the separator attribute
|
|
648 |
|
|
649 |
xsl:variable: a let/return binding. Since XSL-T is statement-like in its
|
|
650 |
sequence constructors, parantheses are used to ensure the variable binding is
|
|
651 |
in-scope for all subsequent statements.
|
|
652 |
|
|
653 |
for-each: it is the iteration/mapping mechanism XQuery fails to supply,
|
|
654 |
despite path steps and the FLWOR machinery. for-each iterates using a
|
|
655 |
focus(which for doesn't, but paths do), but can do so over atomic values and
|
|
656 |
unconditionally without sorting the result by document order(which paths
|
|
657 |
can't/doesn't, but for do). For implementations that normalize paths into for
|
|
658 |
loops as the formal semantics do, the approach is straight forward. In
|
|
659 |
QtXmlPatterns' case, a synthetic token is queued which signals to create
|
|
660 |
a "relaxed" path expression which skips halting on atomic values in its
|
|
661 |
operands(XPTY0019) and also skips node sorting.
|
|
662 |
|
|
663 |
All "direct" node constructors, like <myElement/>, and "computed" node
|
|
664 |
constructors, like xsl:element, are all rewritten into the corresponding
|
|
665 |
XQuery computed node constructors. In some cases direct node constructors
|
|
666 |
could have been used, but in anycase the IR yielded is the same, and that
|
|
667 |
computed constructors happen to use less tokens.
|
|
668 |
|
|
669 |
A particular case is xsl:namespace, an instruction which doesn't have any
|
|
670 |
corresponding expression in XQuery. In the case of QtXmlPatterns, the code
|
|
671 |
obvious already have a notion of "create this namespace on this element", and
|
|
672 |
an AST node was trivially added for fetching the namespace components
|
|
673 |
computationally. However, the introduction of xsl:namespace in an XQuery
|
|
674 |
implementation is not to be taken lightly wrt. to for instance testing, since
|
|
675 |
it introduces a new node type.
|
|
676 |
|
|
677 |
perform-sort: surprisingly this expression of all complicate matters, for the
|
|
678 |
simple reason that its operands occur in the opposite order compared to
|
|
679 |
XQuery when the input sequence is supplied through a sequence constructor,
|
|
680 |
hence breaking the streamed approach. XSLTokenizer solves this by
|
|
681 |
buffer: the attributes of the xsl:perform-sort elements are stored,
|
|
682 |
the xsl:sort elements queued onto a temporary queue, and subsequently is
|
|
683 |
either the select attribute or the sequence constructor queued, and the
|
|
684 |
tokens for xsl:sort appended afterwards. This complicated code greatly, since
|
|
685 |
XSLTokenizer had to be able to "move around" sequences of tokens.
|
|
686 |
|
|
687 |
In addition perform-sort has the same problem as for-each, the iteration
|
|
688 |
mechanism falls inbetween paths and the for loop. The focus for perform-sort
|
|
689 |
is also the focus for the sequence constructor and the select attribute, but
|
|
690 |
the focus for the xsl:sort elements is the initial sequence. This is
|
|
691 |
approached by having a for loop, and where the expression in each order by
|
|
692 |
clause has a relaxed path expression whose left operand is a variable
|
|
693 |
reference to what the for loop bound.
|
|
694 |
TODO Doesn't work. Focus size wrong.
|
|
695 |
|
|
696 |
This is an approach that implementations of the "second generation" of the
|
|
697 |
technologies can take. The bif difference is that XSL-T 2.0 doesn't have the
|
|
698 |
restrictions of 1.0, more evident in XQuery's syntax.
|
|
699 |
|
|
700 |
xsl:sort XSL-T is much more dynamic than XQuery through the use of templates,
|
|
701 |
but also
|
|
702 |
because more decisions can be taken at runtime through all attribute value
|
|
703 |
templates. xsl:sort is surely a good example of this with its AVTs for
|
|
704 |
language, order, collation, stability and what not. XQuery's order by stands
|
|
705 |
in strong contrast, which has these coded in the grammar. In QtXmlPatterns'
|
|
706 |
case, the AST node corresponding to order by was generalized to take things
|
|
707 |
such as stability and order from operands. This is paid by the code paths in
|
|
708 |
XQuery since for them are constants generated and inserted as operands even
|
|
709 |
though its known at compile time what is needed. However, considering that
|
|
710 |
these evaluations are not inside the actual sort loop, but instead only
|
|
711 |
computed on each sort invocation, it shouldn't be too bad.
|
|
712 |
|
|
713 |
xsl:message
|
|
714 |
|
|
715 |
Templates
|
|
716 |
-------------------------
|
|
717 |
|
|
718 |
A big bucket of questions for an XQuery implementation is of course the
|
|
719 |
introduction of templates. In this case it is too of large interest to
|
|
720 |
rewrite relevant code into primitive XQuery expressions.
|
|
721 |
|
|
722 |
Templates' drawback is often mentioned to be their dynamic nature which makes
|
|
723 |
static inferences hard or impossible. However, by again rewriting in clever
|
|
724 |
ways and making the code visible in a standard way, existing analysis code
|
|
725 |
can operate upon it.
|
|
726 |
|
|
727 |
For the purposes of this discussion, templates can be broken down into three
|
|
728 |
distinct problems:
|
|
729 |
|
|
730 |
A Finding what nodes to invoke upon. This is the expression found on
|
|
731 |
xsl:apply-templates/@select, in the case of template rules
|
|
732 |
|
|
733 |
B Concluding what template to invoke. This is the analyzis and evaluation of
|
|
734 |
patterns, as found on xsl:template/@match, in the case of templates rules.
|
|
735 |
This is seen as a critical, as for instance Michael Kay emphasizes in Saxon:
|
|
736 |
Anatomy of an XSLT processor [LINK
|
|
737 |
http://www.ibm.com/developerworks/library/x-xslt2/]
|
|
738 |
|
|
739 |
C Invoking the template for the given context node
|
|
740 |
|
|
741 |
For these three steps, the two first are specific to template rules, while the
|
|
742 |
latter, invoking templates, can be seen to be treated identically regardless
|
|
743 |
of kind: template rules as well as named templates.
|
|
744 |
|
|
745 |
With this perspective as background, lets try to write it into XQuery
|
|
746 |
primitives.
|
|
747 |
|
|
748 |
First, all templates regardless of kind are instanciated by name. In the case
|
|
749 |
of templates rules, a synthetic name is given. They are invoked by an XPath
|
|
750 |
function named call-template() that as first argument takes the name of the
|
|
751 |
template, and also handles template parameters. This "template callsite"
|
|
752 |
which is separated from what it is invoked with and whether it is invoked,
|
|
753 |
knows its target template statically, and hence can be subject to inlining,
|
|
754 |
and usual functional analysis.
|
|
755 |
|
|
756 |
Focus and concatenation of output handled.
|
|
757 |
One should consider whether templates couldn't be considered as functions,
|
|
758 |
with specialized arguments in the case of tunnel parameters.
|
|
759 |
Knowing what templates will be invoked could be used to conclude
|
|
760 |
node sorting is not necessary.
|
|
761 |
Mention how we do builtin templates
|
|
762 |
|
|
763 |
Attribute Value Templates
|
|
764 |
-------------------------
|
|
765 |
XSL-T make extensive use of Attribute Value Templates(AVTs), which are handled
|
|
766 |
by turning the grammar piece in XQuery that is closest, into an expression.
|
|
767 |
Simply, ExprSingle[32] is extended with the branch:
|
|
768 |
|
|
769 |
AVT LPAREN AttrValueContent RPAREN
|
|
770 |
|
|
771 |
where AVT is a synthetic token XSLTokenizer generates. This means that the
|
|
772 |
code handling AVTs in XQuery's direct attribute constructors handles AVTs as
|
|
773 |
generic expressions. AttrValueContent creates a call to the concat()
|
|
774 |
function, over the operands.
|
|
775 |
|
|
776 |
Deal with fn:current by using let $current := . return instruction.
|
|
777 |
|
|
778 |
Another thing related to order and parsing is that XSL-T has more freedom wrt.
|
|
779 |
to where variables are in scope. For instance, a variable declaration appearing
|
|
780 |
after a user function declaration is in scope for the function in XSL-T, but
|
|
781 |
that's not the case in XQuery. This means that delayed variable resolution must
|
|
782 |
be added, something which wasn't, and cannot be active, for the XQuery code.
|
|
783 |
See 9.7 Scope of Variables.
|
|
784 |
|
|
785 |
The parser generates for the builtin template rules:
|
|
786 |
|
|
787 |
declare template matches (text() | @*) mode #all
|
|
788 |
{
|
|
789 |
text{.}
|
|
790 |
};
|
|
791 |
|
|
792 |
*
|
|
793 |
By having templates invocations essentially expressed as a callsite, or
|
|
794 |
branching, allows control flow analysis in a traditional manner, and hence the
|
|
795 |
possiblity to conclude what templates that are possibly invoked in various
|
|
796 |
contexts (or not invoked). One good example where this could improve template
|
|
797 |
matching is patterns containg predicates: let's say a template matches text
|
|
798 |
nodes with a predicate, but , doh I'm wrong.
|
|
799 |
|
|
800 |
The problem with expressing template invocation with if expressions, is finding
|
|
801 |
ambiguous matches.
|
|
802 |
|
|
803 |
Although normalizing down to a small set of primitives has its advantages, one
|
|
804 |
problem is with doing it too early. When doing it directly when tokenization,
|
|
805 |
the higher-level perspective is lost and therefore must be restored
|
|
806 |
again(example?). For instance, if an error is reported in a primitive, it must
|
|
807 |
not appear as originating from that primitive. It's not contstrained to error
|
|
808 |
reporting(example?). However, this is a general problem when compilers shift
|
|
809 |
between different representations.
|
|
810 |
|
|
811 |
One effect this parsing approach has, is that the stylesheet cannot be used as
|
|
812 |
an input document(e.g, what document("") would evaluate to); in that case it
|
|
813 |
has to be parsed again. I think this is for the better; in the case that the
|
|
814 |
stylsheet has this dual role, it means representations are used which are
|
|
815 |
designed specifically for these respective roles. Although doing a dual parsing
|
|
816 |
step is costly, it's somewhat relieved by that the input is typically cached at
|
|
817 |
the byte level(file system and higher layers such as web/application caches) in
|
|
818 |
the case of traditional file loading.
|
|
819 |
|
|
820 |
Another problem is that the grammar is used to solve implementation details,
|
|
821 |
and this might show as part of when the parser do error reporting.
|
|
822 |
|
|
823 |
If one decide to not send XSL-T through the XQuery parser, it can be an
|
|
824 |
advantage to have as little business logic as possible in the XQuery parser
|
|
825 |
such that it can be reused.
|
|
826 |
|
|
827 |
Some parts of XSL-T's syntax doesn't translate well to XQUery syntax. Some
|
|
828 |
parts doesn't follow structure very strongly, surely not the structures that
|
|
829 |
map well to XQuery's syntax. These are xml:base, @version and other attributes
|
|
830 |
that can appear on any element. Their information needs to be preserved and
|
|
831 |
need to affect the output code, but these cannot be done in a way which fits
|
|
832 |
naturally with the XQuery syntax, and hence leads to workarounds. Have whole
|
|
833 |
section on how we do @version and @xml:base. Another problem is namespace
|
|
834 |
declarations on the top document element.
|
|
835 |
|
|
836 |
What largely makes me believe this technique fails is that the large and most
|
|
837 |
important parts, templates, instructions, maps well to XQuery, but the small
|
|
838 |
but yet not ignorable details like @version and @xml:base does not, to the
|
|
839 |
degree that the approach at large fails.
|
|
840 |
|
|
841 |
fn:document()
|
|
842 |
------------------------
|
|
843 |
See class documentation for DocumentFN. Document what optimizations one typically
|
|
844 |
wants to implement(const-fold on card 1, constant propagate).
|
|
845 |
|
|
846 |
|
|
847 |
In other words, it's reasonable to believe that it's possible to extend the
|
|
848 |
XQuery grammar such that it functionality wise is able to do the same as XSL-T,
|
|
849 |
but this doesn't equal that it is a good way to reach every gritty corner of
|
|
850 |
the XSL-T specification.
|
|
851 |
|
|
852 |
Patterns
|
|
853 |
--------------------
|
|
854 |
The up-side-down turning, discuss id/key().
|
|
855 |
|
|
856 |
Declarations
|
|
857 |
---------------------
|
|
858 |
xsl:function: the 'declare function' declaration. TODO override
|
|
859 |
|
|
860 |
XSL-T's error codes goes against good refactoring. Its codes are
|
|
861 |
specific on each usage, compared to for instance XPTY0004.
|
|
862 |
|
|
863 |
Optimizations: string-join()/value-of
|
|
864 |
|
|
865 |
<xsl:template match="document-node">
|
|
866 |
<xsl:apply-templates select="child::element(doc)"/>
|
|
867 |
</xsl:template>
|
|
868 |
|
|
869 |
<xsl:template match="child-or-top::element(doc)"/>
|
|
870 |
|
|
871 |
=>
|
|
872 |
|
|
873 |
document-node()/child::element(doc) map apply-template
|
|
874 |
|
|
875 |
matches child-or-top::element(doc)
|
|
876 |
|
|
877 |
=>
|
|
878 |
|
|
879 |
N/root(.)//(EE)
|
|
880 |
|
|
881 |
N == document-node()
|
|
882 |
EE == child::element(doc)
|
|
883 |
|
|
884 |
=>
|
|
885 |
|
|
886 |
document-node()/root(.)/descendant-or-self::node()/child::element(doc)
|
|
887 |
|
|
888 |
Optimize out already in createCopyOf()
|
|
889 |
|
|
890 |
Bugs:
|
|
891 |
- DynamicContextStore and CurrentItemStore needs to implement
|
|
892 |
evaluateToReceiver().
|
|
893 |
- Don't we have a parsing bug in each place where we call insideSequenceConstructor(), and don't
|
|
894 |
wrap the result in parantheses? E.g, a whitespace node followed by an instruction will lead to parse
|
|
895 |
error if the parent is for instance xsl:when.
|
|
896 |
|
|
897 |
In patterns we find:
|
|
898 |
- Function :id()
|
|
899 |
- Function :key()
|
|
900 |
- AxisStep
|
|
901 |
- GenericPredicate. Also used for paths.
|
|
902 |
- (CombineNodes)
|
|
903 |
- empty sequence; attribute::foo()/child::asd
|
|
904 |
|
|
905 |
|
|
906 |
Test case, tokenizer asserts(fixed in 2a0e83b):
|
|
907 |
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
|
|
908 |
|
|
909 |
|
|
910 |
<xsl:template match="/">
|
|
911 |
<xsl:call-template name="TestFunction"/>
|
|
912 |
</xsl:template>
|
|
913 |
|
|
914 |
|
|
915 |
<xsl:template name="TestFunction">
|
|
916 |
|
|
917 |
|
|
918 |
<xsl:call-template name="GetElem">
|
|
919 |
<xsl:with-param name="element-set"select="$super/*"/>
|
|
920 |
</xsl:call-template>
|
|
921 |
|
|
922 |
</xsl:template>
|
|
923 |
|
|
924 |
<xsl:template name="GetElem">
|
|
925 |
<xsl:param name="element-set"/>
|
|
926 |
<xsl:copy-of select="$element-set[@name]"/>
|
|
927 |
</xsl:template>
|
|
928 |
|
|
929 |
</xsl:stylesheet>
|
|
930 |
|
|
931 |
Typing code:
|
|
932 |
|
|
933 |
<xsl:stylesheet xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
|
|
934 |
|
|
935 |
<xsl:template match="/">
|
|
936 |
|
|
937 |
<xsl:call-template name="templateName">
|
|
938 |
<xsl:with-param name="a" select="2" />
|
|
939 |
</xsl:call-template>
|
|
940 |
|
|
941 |
</xsl:template>
|
|
942 |
|
|
943 |
<xsl:template name="templateName">
|
|
944 |
<xsl:param name="a" as="xs:integer"/>
|
|
945 |
<xsl:sequence select="$a"/>
|
|
946 |
</xsl:template>
|
|
947 |
|
|
948 |
</xsl:stylesheet>
|
|
949 |
|
|
950 |
Compat mode in attribute sets:
|
|
951 |
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
|
952 |
|
|
953 |
<xsl:attribute-set name="attrSet" version="1.0">
|
|
954 |
<xsl:attribute name="attributeName" select="1 + 'type error without compat mode'"/>
|
|
955 |
</xsl:attribute-set>
|
|
956 |
|
|
957 |
<xsl:template match="/">
|
|
958 |
<out xsl:use-attribute-sets="attrSet"/>
|
|
959 |
</xsl:template>
|
|
960 |
|
|
961 |
</xsl:stylesheet>
|
|
962 |
|
|
963 |
Space in mode:
|
|
964 |
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
|
|
965 |
|
|
966 |
<xsl:template match="/">
|
|
967 |
<xsl:apply-templates mode=" #default"/>
|
|
968 |
</xsl:template>
|
|
969 |
|
|
970 |
</xsl:stylesheet>
|
|
971 |
|
|
972 |
|
|
973 |
Type error in global template:
|
|
974 |
|
|
975 |
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
|
|
976 |
|
|
977 |
<xsl:variable name="wa" as="item()"/><!-- HERE, incorrect cardinality. -->
|
|
978 |
|
|
979 |
<xsl:template name="templateName"/>
|
|
980 |
|
|
981 |
</xsl:stylesheet>
|
|
982 |
|
|
983 |
|
|
984 |
Variables are not in scope before its siblings:
|
|
985 |
|
|
986 |
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
|
|
987 |
|
|
988 |
<xsl:template name="templateName">
|
|
989 |
<xsl:sequence select="$var"/>
|
|
990 |
<xsl:variable name="var" select="1"/>
|
|
991 |
</xsl:template>
|
|
992 |
|
|
993 |
</xsl:stylesheet>
|
|
994 |
|
|
995 |
Crashes:
|
|
996 |
|
|
997 |
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
|
998 |
xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
|
999 |
xmlns:local="http://example.com/"
|
|
1000 |
version="2.0">
|
|
1001 |
|
|
1002 |
<xsl:variable name="var" as="xs:boolean">
|
|
1003 |
<xsl:value-of select="local:doesNotExist()"/>
|
|
1004 |
</xsl:variable>
|
|
1005 |
|
|
1006 |
</xsl:stylesheet>
|
|
1007 |
|
|
1008 |
|
|
1009 |
|
|
1010 |
Whitespace handling, the important part is WS after xsl:template:
|
|
1011 |
|
|
1012 |
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
|
|
1013 |
|
|
1014 |
<xsl:template match="/" xml:space="preserve"><MATCH/></xsl:template>
|
|
1015 |
|
|
1016 |
</xsl:stylesheet>
|
|
1017 |
|
|
1018 |
|
|
1019 |
|
|
1020 |
Whitespace handling, preserve, but not inside xsl:apply-templates:
|
|
1021 |
|
|
1022 |
<xsl:stylesheet xmlns:xsl="http://www.w2.org/1999/XSL/Transform" version="2.0">
|
|
1023 |
|
|
1024 |
<xsl:template match="/" xml:space="preserve">MATCH<xsl:apply-templates>
|
|
1025 |
|
|
1026 |
</xsl:apply-templates></xsl:template>
|
|
1027 |
|
|
1028 |
</xsl:stylesheet>
|
|
1029 |
|
|
1030 |
Have top-level xml:space, ensure whitespace as child of xsl:stylesheet is ignored:
|
|
1031 |
|
|
1032 |
<xsl:stylesheet xml:space="preserve" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
|
|
1033 |
|
|
1034 |
<xsl:template match="/">MATCH<xsl:apply-templates>
|
|
1035 |
|
|
1036 |
</xsl:apply-templates>
|
|
1037 |
</xsl:template>
|
|
1038 |
|
|
1039 |
</xsl:stylesheet>
|
|
1040 |
|
|
1041 |
Compat mode, Saxon & QtXmlPatterns fails:
|
|
1042 |
|
|
1043 |
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
|
|
1044 |
|
|
1045 |
<xsl:template match="/">
|
|
1046 |
<xsl:sequence version="1.0" select="string-join(current-dateTime(), 'separator')"/>
|
|
1047 |
</xsl:template>
|
|
1048 |
|
|
1049 |
</xsl:stylesheet>
|
|
1050 |
|
|
1051 |
Compat mode, this is not in the suite:
|
|
1052 |
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
|
|
1053 |
|
|
1054 |
<xsl:template match="/">
|
|
1055 |
<xsl:sequence version="1.0" select="subsequence((1, 2), '2')"/>
|
|
1056 |
</xsl:template>
|
|
1057 |
|
|
1058 |
</xsl:stylesheet>
|
|
1059 |
|
|
1060 |
Crashes:
|
|
1061 |
|
|
1062 |
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
|
|
1063 |
|
|
1064 |
<xsl:template match="doc"/>
|
|
1065 |
|
|
1066 |
<xsl:apply-templates select="item" mode="crazy" />
|
|
1067 |
|
|
1068 |
|
|
1069 |
</xsl:stylesheet>
|
|
1070 |
|
|
1071 |
Incorrectly yields compile error, XPST0003:
|
|
1072 |
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
|
|
1073 |
|
|
1074 |
<xsl:template match=""/>
|
|
1075 |
|
|
1076 |
<xsl:apply-templates select="item" mode="crazy" />
|
|
1077 |
|
|
1078 |
</xsl:stylesheet>
|
|
1079 |
|
|
1080 |
Have a basic simplified stylesheet module:
|
|
1081 |
|
|
1082 |
<output xsl:version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
|
1083 |
<xsl:value-of select="/"/>
|
|
1084 |
</output>
|
|
1085 |
|
|
1086 |
Have no @version:
|
|
1087 |
<output xsl:version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
|
1088 |
<xsl:value-of select="/"/>
|
|
1089 |
</output>
|
|
1090 |
|
|
1091 |
|
|
1092 |
Is valid:
|
|
1093 |
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" >
|
|
1094 |
|
|
1095 |
<xsl:template match="/">
|
|
1096 |
<xsl:perform-sort select=".">
|
|
1097 |
<xsl:sort select="*"/>
|
|
1098 |
<xsl:variable name="abc" select="b"/>
|
|
1099 |
</xsl:perform-sort>
|
|
1100 |
</xsl:template>
|
|
1101 |
|
|
1102 |
</xsl:stylesheet>
|
|
1103 |
|
|
1104 |
|
|
1105 |
Is valid:
|
|
1106 |
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" >
|
|
1107 |
|
|
1108 |
<xsl:template match="/">
|
|
1109 |
<xsl:perform-sort select=".">
|
|
1110 |
<xsl:sort select="*"/>
|
|
1111 |
TEXT
|
|
1112 |
</xsl:perform-sort>
|
|
1113 |
</xsl:template>
|
|
1114 |
|
|
1115 |
</xsl:stylesheet>
|
|
1116 |
|
|
1117 |
XTSE0020:
|
|
1118 |
<literalResultElement xsl:validation="disallowedValue"/>
|
|
1119 |
|
|
1120 |
XTSE0020:
|
|
1121 |
<xsl:element name="localName" validation="disallowedValue"/>
|
|
1122 |
|
|
1123 |
XTSE0805:
|
|
1124 |
<e xsl:disallowedAttribute=""/>
|
|
1125 |
|
|
1126 |
not XPST0003, not in test suite:
|
|
1127 |
|
|
1128 |
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
|
|
1129 |
<xsl:template match="/">
|
|
1130 |
<xsl:variable name="s" as="element()*"/>
|
|
1131 |
</xsl:template>
|
|
1132 |
</xsl:stylesheet>
|
|
1133 |
|
|
1134 |
Parsing of many exprs in xsl:value-of(with separator):
|
|
1135 |
|
|
1136 |
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
|
1137 |
|
|
1138 |
<xsl:template match="/">
|
|
1139 |
<xsl:value-of separator="SEP">
|
|
1140 |
<xsl:sequence select="1"/>
|
|
1141 |
<xsl:sequence select="2"/>
|
|
1142 |
</xsl:value-of>
|
|
1143 |
</xsl:template>
|
|
1144 |
|
|
1145 |
</xsl:stylesheet>
|
|
1146 |
|
|
1147 |
|
|
1148 |
Parsing of many exprs in xsl:value-of(without separator):
|
|
1149 |
|
|
1150 |
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
|
1151 |
|
|
1152 |
<xsl:template match="/">
|
|
1153 |
<xsl:value-of>
|
|
1154 |
<xsl:sequence select="1"/>
|
|
1155 |
<xsl:sequence select="2"/>
|
|
1156 |
</xsl:value-of>
|
|
1157 |
</xsl:template>
|
|
1158 |
|
|
1159 |
</xsl:stylesheet>
|
|
1160 |
|
|
1161 |
|
|
1162 |
Check type of empty variables:
|
|
1163 |
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
|
1164 |
xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
|
1165 |
version="2.0">
|
|
1166 |
|
|
1167 |
<xsl:template match="/">
|
|
1168 |
<xsl:variable name="empty"/>
|
|
1169 |
|
|
1170 |
<xsl:sequence select="'instance of xs:string:', $empty instance of xs:string, '(should be true)',
|
|
1171 |
'instance of document-node():', $empty instance of document-node(), '(should be false)',
|
|
1172 |
'value is:', $empty,
|
|
1173 |
'END'"/>
|
|
1174 |
|
|
1175 |
</xsl:template>
|
|
1176 |
|
|
1177 |
</xsl:stylesheet>
|
|
1178 |
|
|
1179 |
|
|
1180 |
Crashes:
|
|
1181 |
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
|
1182 |
|
|
1183 |
<xsl:template match="/">
|
|
1184 |
<e xmlns="ABC"/>
|
|
1185 |
</xsl:template>
|
|
1186 |
|
|
1187 |
</xsl:stylesheet>
|
|
1188 |
|
|
1189 |
|
|
1190 |
invalid standard attributes on a simplified stylesheet module.
|
|
1191 |
|
|
1192 |
|
|
1193 |
|
|
1194 |
|
|
1195 |
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
|
1196 |
xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
|
1197 |
version="2.0">
|
|
1198 |
|
|
1199 |
<!-- Type error: applying templates to a variable of type string -->
|
|
1200 |
<?spec xslt#applying-templates?>
|
|
1201 |
<?error XTTE0520?>
|
|
1202 |
|
|
1203 |
<xsl:template match="/">
|
|
1204 |
<xsl:variable name="empty"/>
|
|
1205 |
|
|
1206 |
<xsl:sequence select="'instance of xs:string:', $empty instance of xs:string, 'instance of document-node():', $empty instance of document-node()"/>
|
|
1207 |
|
|
1208 |
</xsl:template>
|
|
1209 |
|
|
1210 |
</xsl:stylesheet>
|
|
1211 |
|
|
1212 |
|
|
1213 |
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
|
|
1214 |
|
|
1215 |
<xsl:template match="/">
|
|
1216 |
<output>
|
|
1217 |
<xsl:sequence select="string-length(doesNotMatch)"/>
|
|
1218 |
</output>
|
|
1219 |
</xsl:template>
|
|
1220 |
|
|
1221 |
</xsl:stylesheet>
|
|
1222 |
|
|
1223 |
Asserts(not wellformed):
|
|
1224 |
|
|
1225 |
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
|
|
1226 |
<xsl:template match="/">
|
|
1227 |
<output>
|
|
1228 |
</outpu>
|
|
1229 |
</xsl:template>
|
|
1230 |
|
|
1231 |
</xsl:stylesheet>
|
|
1232 |
|
|
1233 |
|
|
1234 |
From within a function, use the focus /through/ a variable reference:
|
|
1235 |
|
|
1236 |
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:local="http://www.w3.org/2005/xquery-local-functions">
|
|
1237 |
|
|
1238 |
<xsl:variable name="var" select="node()"/>
|
|
1239 |
|
|
1240 |
<xsl:function name="local:function">
|
|
1241 |
<xsl:sequence select="$var"/>
|
|
1242 |
</xsl:function>
|
|
1243 |
|
|
1244 |
<xsl:template match="/">
|
|
1245 |
<xsl:sequence select="local:function()"/>
|
|
1246 |
</xsl:template>
|
|
1247 |
|
|
1248 |
</xsl:stylesheet>
|
|
1249 |
|
|
1250 |
|
|
1251 |
|
|
1252 |
Loops infinitely:
|
|
1253 |
|
|
1254 |
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
|
|
1255 |
|
|
1256 |
<xsl:template match="/" version="1.0">
|
|
1257 |
<xsl:namespace name="{doc/item}" select="'http://www.example.com'" version="1.0"/>
|
|
1258 |
</xsl:template>
|
|
1259 |
|
|
1260 |
</xsl:stylesheet>
|
|
1261 |
|
|
1262 |
|
|
1263 |
Gives crash in coloring code:
|
|
1264 |
Stylesheet:
|
|
1265 |
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
|
|
1266 |
|
|
1267 |
<xsl:template match="/">
|
|
1268 |
</xsl:template>
|
|
1269 |
|
|
1270 |
</xsl:stylesheet>
|
|
1271 |
|
|
1272 |
Focus:
|
|
1273 |
<a><b/><</a>
|
|
1274 |
|
|
1275 |
|
|
1276 |
Should evaluate to true:
|
|
1277 |
|
|
1278 |
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0">
|
|
1279 |
|
|
1280 |
<xsl:template match="/">
|
|
1281 |
<xsl:call-template name="yo">
|
|
1282 |
<xsl:with-param name="arg" as="xs:integer">
|
|
1283 |
<xsl:sequence select="xs:untypedAtomic('1')"/>
|
|
1284 |
</xsl:with-param>
|
|
1285 |
</xsl:call-template>
|
|
1286 |
</xsl:template>
|
|
1287 |
|
|
1288 |
<xsl:template name="yo">
|
|
1289 |
<xsl:param name="arg"/>
|
|
1290 |
<xsl:sequence select="$arg instance of xs:integer"/>
|
|
1291 |
</xsl:template>
|
|
1292 |
|
|
1293 |
</xsl:stylesheet>
|
|
1294 |
|
|
1295 |
Crashes, should be XTTE0570:
|
|
1296 |
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
|
1297 |
xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
|
1298 |
exclude-result-prefixes="xs" version="2.0">
|
|
1299 |
|
|
1300 |
<xsl:template match="/">
|
|
1301 |
<xsl:apply-templates>
|
|
1302 |
<xsl:with-param name="second_seq" as="xs:string">
|
|
1303 |
</xsl:with-param>
|
|
1304 |
|
|
1305 |
</xsl:apply-templates>
|
|
1306 |
</xsl:template>
|
|
1307 |
|
|
1308 |
<xsl:template match="empty">
|
|
1309 |
<xsl:param name="second_seq">def</xsl:param>
|
|
1310 |
<xsl:sequence select="$second_seq instance of xs:string"/>
|
|
1311 |
</xsl:template>
|
|
1312 |
|
|
1313 |
</xsl:stylesheet>
|
|
1314 |
|
|
1315 |
* Parse error:
|
|
1316 |
|
|
1317 |
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
|
1318 |
|
|
1319 |
<xsl:template match="/">
|
|
1320 |
<xsl:copy>
|
|
1321 |
<xsl:sequence select="1"/>
|
|
1322 |
<xsl:sequence select="2"/>
|
|
1323 |
</xsl:copy>
|
|
1324 |
</xsl:template>
|
|
1325 |
|
|
1326 |
</xsl:stylesheet>
|
|
1327 |
|
|
1328 |
* Write tests with xsl:with-param whose body is empty. That's effectively an
|
|
1329 |
empty sequence(?) which needs to be handled properly, and (dynamically) type
|
|
1330 |
checked correctly.
|
|
1331 |
|
|
1332 |
--------------------------------------------------------------------------
|
|
1333 |
|
|
1334 |
|
|
1335 |
|
|
1336 |
|
|
1337 |
|
|
1338 |
--------------------------------------------------------------------------
|
|
1339 |
|
|
1340 |
|
|
1341 |
|
|
1342 |
-------------------------------------------------------------
|
|
1343 |
/a/b
|
|
1344 |
|
|
1345 |
=>
|
|
1346 |
|
|
1347 |
b[parent::a[parent::document()]]
|
|
1348 |
|
|
1349 |
but we currently have:
|
|
1350 |
|
|
1351 |
(b[parent::a])[parent::document()]
|
|
1352 |
|
|
1353 |
-------------------------------------------------------------
|
|
1354 |
a/b
|
|
1355 |
|
|
1356 |
=>
|
|
1357 |
|
|
1358 |
b[parent::a]
|
|
1359 |
|
|
1360 |
-------------------------------------------------------------
|
|
1361 |
a/b/c
|
|
1362 |
|
|
1363 |
=>
|
|
1364 |
|
|
1365 |
c[parent::b[parent::a]]
|
|
1366 |
|
|
1367 |
-------------------------------------------------------------
|
|
1368 |
a/b/c/d
|
|
1369 |
|
|
1370 |
=>
|
|
1371 |
|
|
1372 |
d[parent::c[parent::b[parent::a]]]
|
|
1373 |
|
|
1374 |
|
|
1375 |
-------------------------------------------------------------
|
|
1376 |
/a/b/c/d
|
|
1377 |
|
|
1378 |
=>
|
|
1379 |
|
|
1380 |
d[parent::c[parent::b[parent::a[parent::document()]]]]
|
|
1381 |
|
|
1382 |
This is handled specially; see | SLASH RelativePathPattern
|
|
1383 |
|
|
1384 |
|
|
1385 |
b/c rewrites to:
|
|
1386 |
TruthPredicate
|
|
1387 |
AxisStep self::element(c)
|
|
1388 |
AxisStep parent::element(b)
|
|
1389 |
|
|
1390 |
For a/b/c we get:
|
|
1391 |
|
|
1392 |
TruthPredicate
|
|
1393 |
TruthPredicate
|
|
1394 |
AxisStep self::element(c)
|
|
1395 |
AxisStep parent::element(b)
|
|
1396 |
AxisStep parent::element(a)
|
|
1397 |
|
|
1398 |
But we want:
|
|
1399 |
|
|
1400 |
TruthPredicate
|
|
1401 |
AxisStep child-or-top::element(c)
|
|
1402 |
TruthPredicate
|
|
1403 |
AxisStep parent::element(b)
|
|
1404 |
AxisStep parent::element(a)
|
|
1405 |
|
|
1406 |
For a/b/c/d we get:
|
|
1407 |
|
|
1408 |
TruthPredicate
|
|
1409 |
TruthPredicate
|
|
1410 |
TruthPredicate
|
|
1411 |
AxisStep self::element(d)
|
|
1412 |
AxisStep parent::element(c)
|
|
1413 |
AxisStep parent::element(b)
|
|
1414 |
AxisStep parent::element(a)
|
|
1415 |
|
|
1416 |
For a/b/c/d we want:
|
|
1417 |
|
|
1418 |
TruthPredicate
|
|
1419 |
AxisStep self::element(d)
|
|
1420 |
TruthPredicate
|
|
1421 |
AxisStep parent::element(c)
|
|
1422 |
TruthPredicate
|
|
1423 |
AxisStep parent::element(b)
|
|
1424 |
AxisStep parent::element(a)
|
|
1425 |
|
|
1426 |
|
|
1427 |
For /a/b we get:
|
|
1428 |
|
|
1429 |
TruthPredicate
|
|
1430 |
TruthPredicate:
|
|
1431 |
AxisStep self::element(b)
|
|
1432 |
AxisStep parent::element(a)
|
|
1433 |
AxisStep parent::document()
|
|
1434 |
|
|
1435 |
but we want:
|
|
1436 |
|
|
1437 |
TruthPredicate
|
|
1438 |
AxisStep self::element(b)
|
|
1439 |
TruthPredicate: // PREDICATE
|
|
1440 |
AxisStep parent::element(a)
|
|
1441 |
AxisStep parent::document() // PREDICATE
|
|
1442 |
|
|
1443 |
--------------------------------------------------------------
|
|
1444 |
For a/b/c we get:
|
|
1445 |
TruthPredicate
|
|
1446 |
AxisStep self::element(c)
|
|
1447 |
TruthPredicate
|
|
1448 |
parent::element(b)
|
|
1449 |
parent::element(a)
|
|
1450 |
|