Files correlati : cg0.exe cg0700a.msk cg0700b.msk cg3.exe cg4.exe Bug : Commento: Merge 1.0 libraries
1451 lines
51 KiB
Plaintext
1451 lines
51 KiB
Plaintext
This is a TODO file for XSL-T 2.0 support.
|
|
|
|
- LHF:
|
|
* Warning bug, last parameter is always whined about.
|
|
* Box in comment/PI/text/ws(?) handling -- pending Matthias
|
|
* type036 -- namespace on top element isn't copied
|
|
* XTDE0865
|
|
* Attend XSLTTokenizer::isXSLT()
|
|
* Remove redundant set() calls in setFocusHelper().
|
|
|
|
- Missing features:
|
|
General Priority
|
|
---------------------
|
|
* 1.0 QXmlQuery::evaluateTo(QIODevice *) P1 DONE
|
|
* 1.0 Test suite integration P1 DONE
|
|
* 1.0 xsl:key P1
|
|
* 1.0 fn:key() P1
|
|
* 1.0 2.0 Compatibility mode P1
|
|
* 1.0 Regular parameters in templates P1
|
|
* 1.0 xsl:include P1
|
|
* 1.0 xsl:copy-of P1
|
|
* 1.0 xsl:copy P1
|
|
* 1.0 xsl:import P1
|
|
* 1.0 fn:format-number P1
|
|
* 1.0 xsl:message P2
|
|
* 1.0 fn:current() P1 DONE
|
|
* 2.0 fn:type-available() P3 DONE
|
|
* 2.0 xsl:use-when P3
|
|
* 2.0 fn:unparsed-entity-uri() P3
|
|
* 2.0 fn:unparsed-entity-public-id() P3
|
|
* 2.0 Tunnel Parameters P3
|
|
* 2.0 xsl:attribute-set P3
|
|
* 1.0 xsl:decimal-format P2
|
|
* 1.0 xmlpatterns: initial template P1 DONE
|
|
* 1.0 xsl:number P1
|
|
* 1.0 Complete handling of xsl:sort P2
|
|
* 2.0 Grouping
|
|
- fn:current-group()
|
|
- fn:grouping-key()
|
|
- xsl:for-each-group()
|
|
* 2.0 Regexp
|
|
- xsl:analyze-string
|
|
- xsl:matching-substring
|
|
- xsl:non-matching-substring
|
|
- fn:regex-group()
|
|
* 2.0 Date & Time formatting
|
|
- fn:format-dateTime()
|
|
- fn:format-date()
|
|
- fn:format-time()
|
|
|
|
Serialization & Output:
|
|
----------------------
|
|
* 1.0 xsl:output
|
|
--- Tie together serialization. Should we add
|
|
QXmlQuery::evaluateTo(QIODevice 1.0 const) ?
|
|
* 2.0 xsl:character-maps
|
|
* 2.0 xsl:character-map
|
|
* 2.0 xsl:result-document
|
|
--- Should the "default output" be handle with xsl:result-document? Would
|
|
depend on compilation.
|
|
|
|
Optimizations:
|
|
* Remove adjacent text node constructors
|
|
* Remove string-join when first arg's static cardinality is not more than one
|
|
* Remove string-join when the second arg is statically known to be the empty string.
|
|
* Remove string-join when the second arg is a single space and the parent is a text node ctor.
|
|
* Rewrite to operand if operands are one. What about type conversions?
|
|
* Replace lookups with xml:id with calls on id().
|
|
* Recognize that a/(b, c) is equal to a/(b | c). The later does selection and node sorting in one step.
|
|
* Remove LetClause which has empty sequence as return clause, or no variable dependencies at all.
|
|
* Do a mega test for rewriting /patterns/:
|
|
"node() | element()" => element()
|
|
"comment() | node()" => comment()
|
|
|
|
and so forth. This sometimes happens in poorly written patterns. How does
|
|
this rewrite affect priority calculation?
|
|
|
|
Tests:
|
|
* xml:id
|
|
- Come on, the stuff needs to be reorganized xml:id.
|
|
- Read in xml:id document with whitespace in attrs, write the doc out. Attrs should be normalized.
|
|
- Do lookups of IDs with xml:id attrs containing whitespace.
|
|
|
|
* current()
|
|
- Use current() inside each instruction
|
|
- In a template pattern
|
|
- Several invocations: current()/current()/current()
|
|
|
|
|
|
* Diagnosticsts:
|
|
- See http://www.w3.org/Bugs/Public/show_bug.cgi?id=5643 . Comments
|
|
should be taken into account when comparing. This suggests that we
|
|
don't have any test which produces a document with XML comments.
|
|
|
|
* element-available()
|
|
- Review the tests.
|
|
- Try using declarations in XSL-T, should return false
|
|
- Use xsl:variable(both instr and decl)
|
|
- invoke with all the XSL-T instructions.
|
|
- Should return false for when, otherwise, matching-substring, non-matching-substring, etc?
|
|
- Supply the namespace in the name via the default namespace, no prefix.
|
|
|
|
* unparsed-text()
|
|
- Load an empty file
|
|
- Use a fragment in the URI
|
|
- Use an invalid URI
|
|
- Use device bindings and a QRC to ensure that we're not using a generic
|
|
network manager.
|
|
- Duplicate all the network tests. Same as for doc()
|
|
|
|
* unparsed-text-available()
|
|
- Same as for unparsed-text()
|
|
|
|
* Sequence constructor that contains only:
|
|
- XML comment
|
|
- whitespace text node
|
|
- processing instruction
|
|
- a mix of the three
|
|
|
|
* xsl:function
|
|
- Ensure that it's not it's not in scope for use-when.
|
|
- xsl:function/xsl:param: use processing instructions, whitespace and comments as child: should be stripped
|
|
- Use <xsl:function/> : @name missing.
|
|
- Don't strip ws, and have ws between two xsl:param, and between xsl:function and xsl:param.
|
|
- Use xsl:function with no body.
|
|
- use xsl:param/@tunnel = no
|
|
- use xsl:param/@tunnel = yes
|
|
- use an invalid value for xsl:param/@tunnel = yes
|
|
- Have a non-WS text node in xsl:function/xsl:param/
|
|
- Have a WS text node in xsl:function/xsl:param/
|
|
- Have a WS text node in xsl:function/xsl:param/ while preserving WS.
|
|
- use a comment as child of xsl:param
|
|
- use a PI as child of xsl:param
|
|
- XTSE0770 with import precedence and all that.
|
|
- have two identical function in the stylesheet. The last has override=no. Should still report XTSE0770.
|
|
- have @override with invalid value.
|
|
- have whitespace inside xsl:param with different strip modes.
|
|
- Have @select => error
|
|
- Have body => error
|
|
- call current() inside body. XPDY0002?
|
|
|
|
* Does xml:base/StaticBaseURI and StaticCompatiblityStore prevent proper
|
|
type checking due to expectedOperandTypes() returns item()*?
|
|
|
|
* xsl:template/xsl:param
|
|
- Have @required=yes, and have @select => error
|
|
- Have @required=yes, and have body => error
|
|
- Have a variable reference in a template after another, which has
|
|
param, to ensure they aren't in scope.
|
|
|
|
* xsl:template/@match
|
|
- Have a pattern with unions, and have a body which relies on its
|
|
static type.
|
|
|
|
* @version:
|
|
Have @version on *all* attributes.
|
|
|
|
* xsl:call-template
|
|
- Have a variable reference just after a xsl:call-template which has
|
|
with-param, to ensure they aren't in scope.
|
|
- Have an xsl:with-param which isn't used in the template. Error?
|
|
- Have an xsl:with-param that has a type error.
|
|
- an xsl:with-param is not in scope for the next one. Test this => error.
|
|
- Have a call:template, whose with-param computes its value by calling
|
|
another template, while using an with-param too.
|
|
|
|
* XQuery:
|
|
- DONE Ensure namespace {expr} {expr} is flagged as invalid
|
|
- Use all XSL-T functions: error. Or we do that already?
|
|
- Ensure order by collation 1 + 1 is an error
|
|
- Ensure order by collation {1 + 1} is an error
|
|
|
|
* document()
|
|
- Basic node deduplication, no test exists for that.
|
|
|
|
* xsl:perform-sort
|
|
- Have no xsl:sort. Error. Must be at least one.
|
|
- have xsl:sort with invalid value.
|
|
- sort atomic values.
|
|
- Trigger "The stable attribute is permitted only on the first xsl:sort element within a sort key specification"
|
|
- have xsl:sort with no select and no seq ctor.
|
|
- trigger the delegated queueing. All instructions inside.. xsl:sort?
|
|
- have multiple sort statements, with the last being <xsl:sort/> only.
|
|
- have WS between xsl:sort that is not ignorable.
|
|
- Use a variable reference whose name is equal to our synthetic name. This should be XPST0008, but probably isn't.
|
|
- Have an invalid value in xsl:sort/order. Use space
|
|
- have xsl:sort return numbers, but data-type specify string.
|
|
- have an AVT in xsl:sort/@lang
|
|
- have an AVT in xsl:sort/@case-order
|
|
- have an AVT in xsl:sort/@data-type
|
|
- have an AVT in xsl:sort/@stable
|
|
- Have mixed result, and hence incorrectly trigger XPTY0018 which the code currently raise.
|
|
- Depend on the context position inside xsl:sort, when being child of
|
|
perform-sort. Currently we create singleton focuses(I think), while
|
|
we want the focus to be over the whole input sequence, not on indivual items.
|
|
- Have <xsl:perform-sort select="valid-expr"/>: xsl:sort is missing
|
|
- Use current() in the xsl:sort and the body, to ensure the right scope is picked up
|
|
|
|
* xsl:copy-of
|
|
- Have a text node. It's not allowed.
|
|
- Have PIs, comments, and ignorable whitespace as children. Sigh.
|
|
|
|
* xsl:namespace
|
|
- Use xsl:fallback.
|
|
- Use xsl:namespace inside xsl:variable and introspec the result in various
|
|
ways. This is a big area, we don't have namespace nodes in XQuery. Yes, calling evaluateSingleton() will probably crash.
|
|
- Use no select and no body, error: XTSE0910
|
|
- Have name expression evaluate to the empty sequence.
|
|
|
|
* Sequence ctor that:
|
|
- Has invalid element in XSL namespace. E.g, xsl:foo
|
|
|
|
* xsl:import
|
|
- Have element as child as xsl:import: disallowed.
|
|
- Have text as child as xsl:import: disallowed.
|
|
- Have PIs and comments as child as xsl:import: allowed.
|
|
|
|
* xsl:include
|
|
- Have element as child as xsl:include: disallowed.
|
|
- Have text as child as xsl:include: disallowed.
|
|
- Have PIs and comments as child as xsl:include: allowed.
|
|
|
|
* xsl:strip-space
|
|
- Have PIs, comments, whitespace as child.
|
|
|
|
* xsl:element
|
|
- Extract EBV from result.
|
|
- Use space in validation element.
|
|
|
|
* xsl:perform-sort
|
|
- Have PIs and comments in between xsl:sort elements.
|
|
|
|
* xml:space
|
|
- We never pop our stack. Fix the bug, and ensure we have tests for it.
|
|
|
|
* fn:unparsed-entity-uri
|
|
- Check type of return value
|
|
- Do basic unparsed-entity-uri("does-not-exist")
|
|
|
|
* fn:unparsed-entity-public-id
|
|
- Do basic unparsed-entity-uri("does-not-exist"), two permutations, check the spec
|
|
|
|
* xsl:element
|
|
- Use disallowed attribute: select
|
|
- use unknown type in @type
|
|
- Use @namespace, but be not in the lexical space of xs:anyURI
|
|
- use disallowed enumeration in @validation
|
|
- have a name expression that evaluates to a xs:QName value as opposed to a string.
|
|
- have a name expression that evaluates to a xs:QName value as opposed to a string. but
|
|
also have the namespace attribute
|
|
|
|
* xsl:attribute
|
|
- Use disallowed attribute: match
|
|
- use unknown type in @type
|
|
- Use @namespace, but be not in the lexical space of xs:anyURI
|
|
- use disallowed enumeration in @validation
|
|
- have a name expression that evaluates to a xs:QName value as opposed to a string.
|
|
- have a name expression that evaluates to a xs:QName value as opposed to a string. but
|
|
also have the namespace attribute
|
|
|
|
* xsl:template
|
|
- Use the union keyword, it's forbidden, only "|" is allowed
|
|
- Use an expression other than Literal and VarRef in KeyValue[8]
|
|
- use a function other than key().
|
|
- have a declaration that only can apperar as a child of xsl:stylesheet.
|
|
- Have an element in the XSL-T namespace, but which is invalid, e.g "bar"
|
|
- Use an axis other than child or attribute in pattern.
|
|
- Have a template that no no match and no name attribute., XTSE0500
|
|
- use child::document-node() in pattern
|
|
- use @foo/child in pattern
|
|
- apply templates to parentless attributes.
|
|
- Have 3e3 in @priority
|
|
- Have a @match with more than two alternatives, e.g "a | b | c", and have them all actually matching.
|
|
- Use an XML name in the mode so we trigger
|
|
NCNameConstructor::validateTargetName()
|
|
- A template which only has a non-WS text node.
|
|
- A template with param, followed by text node.
|
|
|
|
* Simplified stylesheet
|
|
- Use @version attribute only on doc element. Should fail, since @{XSL-T]version must be present
|
|
|
|
* fn:current()
|
|
- Have <xsl:value-of select="current()"/>
|
|
|
|
* xsl:variable have a variable reference appearing before its global declaration, and then somehow trigger recursion.
|
|
* xsl:choose
|
|
- elements/nodes intermixed with xsl:choose/xsl:when
|
|
- invalid attribute on xsl:choose
|
|
- invalid attribute on xsl:when
|
|
- invalid attribute on xsl:otherwise
|
|
- invalid attribute on xsl:if
|
|
- invalid attribute on xsl:template
|
|
- invalid attribute on xsl:stylesheet
|
|
- invalid attribute on xsl:transform
|
|
- xsl:otherwise in the middle between xsl:when elements.
|
|
- use namespace declarations on xsl:when
|
|
- use namespace declarations on xsl:otherwise
|
|
- use namespace declarations on xsl:choose
|
|
|
|
* Namespaces:
|
|
- Have:
|
|
<xsl:sequence xmlns:bar="http://example.com/" select="1"/>
|
|
<xsl:sequence select="bar:foo()"/>
|
|
|
|
* XPath
|
|
- For each XQuery-specific expression, add a test using that expression:
|
|
- typeswitch
|
|
- let
|
|
- validate
|
|
- extension expression
|
|
- unordered
|
|
- ordered
|
|
- for
|
|
- computed text node constructor
|
|
- computed attribute constructor
|
|
- computed comment constructor
|
|
- computed PI constructor
|
|
- computed element constructor
|
|
- computed document constructor
|
|
- direct element constructor
|
|
- direct comment constructor
|
|
- direct PI constructor
|
|
- all declarations
|
|
|
|
- Use all the predefined prefixes in XQuery; non are in XSL-T.
|
|
|
|
* xsl:when
|
|
- Use xml:space on it
|
|
|
|
* xsl:otherwise
|
|
- Use xml:space on it
|
|
|
|
* xsl:version
|
|
- Use letters, XTSE0110
|
|
- Use a float: 2e3, XTSE0110
|
|
- Use a weird number, 2.00000001
|
|
|
|
* xsl:document
|
|
- use disallowed attribute: select.
|
|
- use unknown type in @type
|
|
- use disallowed enumeration in @validation
|
|
- What happens if the type in @type is unknown?
|
|
- Use xml:base attr and check URI.
|
|
|
|
* xsl:sequence
|
|
- use match attribute
|
|
|
|
* xsl:stylesheet
|
|
- Use @xsl:default-collation on xsl:stylesheet. Shouldn't have any effect. Or?
|
|
- Use an XSL-T instruction as child -- invalid.
|
|
- Have an element in the XSL-T namespace, but which is invalid, e.g "foo"
|
|
- Have xsl:default-collation="http://example.com/" on xsl:stylesheet
|
|
- Use prefix local: in say a function name. Not allowed.
|
|
- Use comments after document element.
|
|
- XTSE0010: <xsl:invalid version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"/>
|
|
- Change the version with @xsl:version on all elements that we have.
|
|
|
|
* Patterns.
|
|
- Basic */* test:
|
|
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:template match="*/*"><xsl:sequence select="'MATCH'"/></xsl:template>
|
|
|
|
|
|
</xsl:stylesheet>
|
|
|
|
- Basic a/b test:
|
|
<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>
|
|
|
|
|
|
</xsl:stylesheet>
|
|
* xsl:strip-whitespace
|
|
- Use a namespace prefix which is not unboudn
|
|
- have a syntax error in one of the node tests
|
|
|
|
* xsl:preserve-whitespace
|
|
- Use a namespace prefix which is not unboudn
|
|
- have a syntax error in one of the node tests
|
|
|
|
* xsl:value-of
|
|
- select attribute, and comment in body(error, XTSE0870)
|
|
- select attribute, and processing instruction in body(error, XTSE0870)
|
|
- select attribute, and CCDATA in body(error, XTSE0870)
|
|
- select attribute, and element in body(error, XTSE0870)
|
|
- use xsl:sequence in body. Default separator should be none.
|
|
- use match attribute
|
|
- use double apostrophes/quotes. How are they dealt with?
|
|
|
|
* xsl:apply-templates
|
|
- use match attribute
|
|
- apply in a mode for which no templates are declared
|
|
- apply in a mode which is mispelled for another.
|
|
- Have: <xsl:apply-templates select="id('id2')/a | id('id5')"/>
|
|
We CRASH
|
|
|
|
* xsl:for-each
|
|
- No body: <xsl:for-each select="abc"/>
|
|
- No select attribute: <xsl:for-each>text</xsl:for-each>
|
|
- Have mixed result, and hence incorrectly trigger XPTY0018 which the code currently raise.
|
|
- Have:
|
|
<xsl:for-each select="1, 'asd'">
|
|
<xsl:sequence select="."/>
|
|
</xsl:for-each>
|
|
|
|
* xsl:variable
|
|
- Test that function conversion rules are invoked
|
|
- For what is an xsl:variable in scope? Where does the spec state it? Test
|
|
that it is not in scope where applicable.
|
|
- Have: <variable name="a" select=""/>
|
|
|
|
* xsl:text
|
|
- count the result of a template that has text node(non-ws),
|
|
xsl:text(content), xsl:content(zero content), text node(non-ws
|
|
- Have an element inside xsl:text: XTSE0010.
|
|
- Use comments and PIs intermixed with text inside.
|
|
|
|
* xsl:for-each
|
|
- use match attribute
|
|
- What should this produce? Saxon produces "123" but with xsl:text removed, "1 2 3".
|
|
<xsl:template match="/">
|
|
<xsl:for-each select="1 to 3">
|
|
<xsl:sequence select="."/>
|
|
<xsl:text></xsl:text>
|
|
</xsl:for-each>
|
|
</xsl:template>
|
|
|
|
* xsl:if
|
|
- Have <xsl:if test="">body</xsl:if>. Error
|
|
- Have <xsl:if test="valid-test"/>. That is, empty body.
|
|
|
|
* xsl:sequence
|
|
- select attribute missing: <xsl:sequence/>
|
|
- content other than xsl:fallback, e.g text node.
|
|
- How do we sort?
|
|
|
|
* for every state for XSL-T parsing:
|
|
- Use invalid element that is in the XSL-T namespace.
|
|
|
|
* In all cases expressions are queued/generated:
|
|
- Trigger expression precedence bugs, due to lack of paranteses.
|
|
|
|
* Use xml:space in stylsheeet that doesn't have value preserve nor default.
|
|
* For each case we have while(!reader.atEnd()):
|
|
- test that triggers parser error and that we detect it properly.
|
|
|
|
* for every element that allows text:
|
|
* Use CDATA. QXmlStreamReader distinguishes between the two. text before and after.:wa
|
|
* Use XML Comments and split up text nodes.
|
|
|
|
* Patterns:
|
|
* Ensure node() doesn't match document nodes().
|
|
* "//" is an invalid pattern
|
|
* Is there some expression which has no children? findAxisStep()
|
|
* Use @*/asdo
|
|
* XPST0003: key(concat("abc", "def"), "abc")
|
|
* XPST0003: id(concat("abc", "def"))
|
|
* XPST0003: concat('abc', 'def') // WILL CRASH
|
|
* XPST0003: unknownFunction()
|
|
* Use double: key("abc", 3e3)
|
|
* Use three argument key() in pattern.
|
|
|
|
* Simplified stylsheet modules:
|
|
* Omit the xsl:version attribute. XTSE0010
|
|
|
|
* type-available()
|
|
* We have no tests at all?
|
|
|
|
* have xml:base on the following elements and check them with
|
|
static-base-uri():
|
|
- all instructions
|
|
- all declarations, eg:
|
|
- xsl:choose, xsl:choice, xsl:otherwise
|
|
- xsl:template
|
|
- xsl:function
|
|
- etc
|
|
|
|
Embedded stylesheet modules
|
|
- Verify that we don't choke on xsl attrs with invalid attributes outside;
|
|
"In an embedded stylesheet module, standard attributes appearing on
|
|
ancestors of the outermost element of the stylesheet module have no effect."
|
|
|
|
Parsing:
|
|
- Error message for:
|
|
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
|
<xsl:template match="/">
|
|
<e/>
|
|
</xsl:stylesheet>
|
|
- Use the document "<do/" as focus.
|
|
- Write a test for each call to checkForParseError();
|
|
|
|
|
|
function-available:
|
|
- Generally low coverage it seems.
|
|
|
|
|
|
<xsl:template match="/"/> <!-- t0 -->
|
|
<xsl:template match="*"/> <!-- t1 -->
|
|
<xsl:template match="asd"/> <!-- t2 -->
|
|
<xsl:template match="comment()"/> <!-- t3 -->
|
|
<xsl:template match="a/b"/> <!-- t4 -->
|
|
|
|
<xsl:apply-templates select="*"/>
|
|
|
|
|
|
*(
|
|
((/)/call-template(t0))
|
|
(*/call-template(t1))
|
|
(element(asd)/call-template(t2))
|
|
(comment()/call-template(t3))
|
|
(a/b/call-template(t3))
|
|
)
|
|
|
|
==>
|
|
|
|
*/typeswitch(.)
|
|
case $g0 as document-root() return call-template(t0)
|
|
case $g0 as element() return call-template(t1)
|
|
case $g0 as element(asd) return call-template(t2)
|
|
case $g0 as comment() return (call-template(t3)
|
|
case $g0 as a/b return (call-template(t4)
|
|
|
|
|
|
Patterns are used in:
|
|
- xsl:for-each-group/@group-starting-with
|
|
- xsl:key/@match
|
|
- xsl:number/(@count, @from)
|
|
- xsl:template/@match
|
|
|
|
|
|
|
|
c/b
|
|
=>
|
|
child-or-self::element(b)[parent::element(c)]
|
|
|
|
c/b/a
|
|
=>
|
|
child-or-self::element(a)[parent::element(b)[parent::element(c)]]
|
|
|
|
d/c/b/a
|
|
=>
|
|
child-or-self::element(a)[parent::element(b)[parent::element(c)[parent::element(d)]]]
|
|
|
|
|
|
|
|
-----------------------------------
|
|
<xsl:apply-templates select="foo"/>
|
|
=>
|
|
|
|
child::element(foo) map apply-template(#default)
|
|
-----------------------------------
|
|
|
|
-----------------------------------
|
|
<xsl:apply-templates mode="yo" select="foo">
|
|
<xsl:sort select="@bar"/>
|
|
</xsl:apply-templates>
|
|
=>
|
|
|
|
let $g0 := for $g1 in child::element(foo)
|
|
order by @bar
|
|
return $g1
|
|
return apply-template(yo)
|
|
-----------------------------------
|
|
|
|
-----------------------------------
|
|
<xsl:perform-sort select="$in">
|
|
<xsl:sort select="@sortKey"/>
|
|
</xsl:perform-sort>
|
|
|
|
=>
|
|
|
|
sort $in/order by @sortKey
|
|
-----------------------------------
|
|
|
|
|
|
-----------
|
|
|
|
John Snelson of Oracle Berkeley DB XML & XQilla writes in private mail:
|
|
|
|
I'd had the same thought myself, too - you must be reading my mind ;-)
|
|
|
|
What is he referring to?
|
|
|
|
If one spends some time on fancy diagrams, QtXmlPatterns[LINK]'s, the XQuery
|
|
engine that shipped in Qt 4.4, architecture looks like this:
|
|
|
|
|
|
Recently I've started implementing XSL-T 2.0(hopefully to be done for Qt 4.5)
|
|
and the whole approach to this is modifying the existing codebase as follows:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Put differently, when QtXmlPatterns is dealing with XSL-T stylesheets, it
|
|
replaces the XQuery tokenizer with a tokenizer which translates the
|
|
stylesheet into XQuery tokens, that is consumed by the existing XQuery
|
|
parser, extended with both grammar non-terminals and tokens to accomodate the
|
|
XSL-T features that XQuery doesn't have. In compiler terms, it can be seen as
|
|
an "extreme" frontend. Not only is the same intermediate representation used,
|
|
the grammar is too.
|
|
|
|
What is the point of this?
|
|
|
|
The functional overlaps XQuery, XSL-T and others as well have is of course
|
|
widely established. Even the specifications are at times generated from the
|
|
same source documents, and that implementations subsequently modularize code
|
|
is of course second nature to any engineer, and seen to some degree or
|
|
another in contemporary implementations. Typically this happens in a
|
|
traditional fashion, classes are re-used, their functionality widened to
|
|
cover both/more languages. However, I believe doing it directly on the
|
|
grammar level introduce several advantages.
|
|
|
|
The parser is based on Bison and since it's not running in the experimental
|
|
pull mode, it uninterruptedly calls the tokenizer. The tokenizer, class
|
|
XSLTTokenizer, in turns calls an pull-based XML parser: QXmlStreamReader.
|
|
What often complicate in ocassions like this is who that gets the right to
|
|
call who, and who gets the convenience of tracking state in a natural way
|
|
through a call stack.
|
|
|
|
XSLTTokenizer is conveniently implemented: as it encounters declarations and
|
|
instructions in the stylsheet, it recursively descends in the XSL-T grammar
|
|
through its own functions, adding tokens to a queue, which is delivered to
|
|
the parser when asked -- and when the queue is empty it resumes queuing
|
|
tokens. The tokenizer is fairly crude, it queues up tokens for instructions
|
|
uninterrupted, and only have states between declarations. Hence,
|
|
XSLTTokenizer queues up tokens for each template and function body, but
|
|
enters "delivery mode" inbetween. This of course periodically breaks
|
|
streaming since it's buffering up tokens, but considering that the memory
|
|
usage for tokens is low and that a finer granularity for states(say, being
|
|
able to pop the stacks when being inbetween two xsl:when elements) requires a
|
|
significant effort, this is fine until proven otherwise.
|
|
|
|
|
|
Advantages
|
|
---------------
|
|
discuss analysis.
|
|
|
|
|
|
XSLTTokenizer rewrite XSL-T to XQuery as follows:'
|
|
|
|
Instructions
|
|
-------------
|
|
xsl:if An if/then/else expression whose else branch is the empty sequence
|
|
|
|
xsl:choose: again, a nesting of if/then/else expressions
|
|
|
|
xsl:value-of: a computed text node constructor. Its body contains a call to
|
|
string-join() involving the separator attribute
|
|
|
|
xsl:variable: a let/return binding. Since XSL-T is statement-like in its
|
|
sequence constructors, parantheses are used to ensure the variable binding is
|
|
in-scope for all subsequent statements.
|
|
|
|
for-each: it is the iteration/mapping mechanism XQuery fails to supply,
|
|
despite path steps and the FLWOR machinery. for-each iterates using a
|
|
focus(which for doesn't, but paths do), but can do so over atomic values and
|
|
unconditionally without sorting the result by document order(which paths
|
|
can't/doesn't, but for do). For implementations that normalize paths into for
|
|
loops as the formal semantics do, the approach is straight forward. In
|
|
QtXmlPatterns' case, a synthetic token is queued which signals to create
|
|
a "relaxed" path expression which skips halting on atomic values in its
|
|
operands(XPTY0019) and also skips node sorting.
|
|
|
|
All "direct" node constructors, like <myElement/>, and "computed" node
|
|
constructors, like xsl:element, are all rewritten into the corresponding
|
|
XQuery computed node constructors. In some cases direct node constructors
|
|
could have been used, but in anycase the IR yielded is the same, and that
|
|
computed constructors happen to use less tokens.
|
|
|
|
A particular case is xsl:namespace, an instruction which doesn't have any
|
|
corresponding expression in XQuery. In the case of QtXmlPatterns, the code
|
|
obvious already have a notion of "create this namespace on this element", and
|
|
an AST node was trivially added for fetching the namespace components
|
|
computationally. However, the introduction of xsl:namespace in an XQuery
|
|
implementation is not to be taken lightly wrt. to for instance testing, since
|
|
it introduces a new node type.
|
|
|
|
perform-sort: surprisingly this expression of all complicate matters, for the
|
|
simple reason that its operands occur in the opposite order compared to
|
|
XQuery when the input sequence is supplied through a sequence constructor,
|
|
hence breaking the streamed approach. XSLTokenizer solves this by
|
|
buffer: the attributes of the xsl:perform-sort elements are stored,
|
|
the xsl:sort elements queued onto a temporary queue, and subsequently is
|
|
either the select attribute or the sequence constructor queued, and the
|
|
tokens for xsl:sort appended afterwards. This complicated code greatly, since
|
|
XSLTokenizer had to be able to "move around" sequences of tokens.
|
|
|
|
In addition perform-sort has the same problem as for-each, the iteration
|
|
mechanism falls inbetween paths and the for loop. The focus for perform-sort
|
|
is also the focus for the sequence constructor and the select attribute, but
|
|
the focus for the xsl:sort elements is the initial sequence. This is
|
|
approached by having a for loop, and where the expression in each order by
|
|
clause has a relaxed path expression whose left operand is a variable
|
|
reference to what the for loop bound.
|
|
TODO Doesn't work. Focus size wrong.
|
|
|
|
This is an approach that implementations of the "second generation" of the
|
|
technologies can take. The bif difference is that XSL-T 2.0 doesn't have the
|
|
restrictions of 1.0, more evident in XQuery's syntax.
|
|
|
|
xsl:sort XSL-T is much more dynamic than XQuery through the use of templates,
|
|
but also
|
|
because more decisions can be taken at runtime through all attribute value
|
|
templates. xsl:sort is surely a good example of this with its AVTs for
|
|
language, order, collation, stability and what not. XQuery's order by stands
|
|
in strong contrast, which has these coded in the grammar. In QtXmlPatterns'
|
|
case, the AST node corresponding to order by was generalized to take things
|
|
such as stability and order from operands. This is paid by the code paths in
|
|
XQuery since for them are constants generated and inserted as operands even
|
|
though its known at compile time what is needed. However, considering that
|
|
these evaluations are not inside the actual sort loop, but instead only
|
|
computed on each sort invocation, it shouldn't be too bad.
|
|
|
|
xsl:message
|
|
|
|
Templates
|
|
-------------------------
|
|
|
|
A big bucket of questions for an XQuery implementation is of course the
|
|
introduction of templates. In this case it is too of large interest to
|
|
rewrite relevant code into primitive XQuery expressions.
|
|
|
|
Templates' drawback is often mentioned to be their dynamic nature which makes
|
|
static inferences hard or impossible. However, by again rewriting in clever
|
|
ways and making the code visible in a standard way, existing analysis code
|
|
can operate upon it.
|
|
|
|
For the purposes of this discussion, templates can be broken down into three
|
|
distinct problems:
|
|
|
|
A Finding what nodes to invoke upon. This is the expression found on
|
|
xsl:apply-templates/@select, in the case of template rules
|
|
|
|
B Concluding what template to invoke. This is the analyzis and evaluation of
|
|
patterns, as found on xsl:template/@match, in the case of templates rules.
|
|
This is seen as a critical, as for instance Michael Kay emphasizes in Saxon:
|
|
Anatomy of an XSLT processor [LINK
|
|
http://www.ibm.com/developerworks/library/x-xslt2/]
|
|
|
|
C Invoking the template for the given context node
|
|
|
|
For these three steps, the two first are specific to template rules, while the
|
|
latter, invoking templates, can be seen to be treated identically regardless
|
|
of kind: template rules as well as named templates.
|
|
|
|
With this perspective as background, lets try to write it into XQuery
|
|
primitives.
|
|
|
|
First, all templates regardless of kind are instanciated by name. In the case
|
|
of templates rules, a synthetic name is given. They are invoked by an XPath
|
|
function named call-template() that as first argument takes the name of the
|
|
template, and also handles template parameters. This "template callsite"
|
|
which is separated from what it is invoked with and whether it is invoked,
|
|
knows its target template statically, and hence can be subject to inlining,
|
|
and usual functional analysis.
|
|
|
|
Focus and concatenation of output handled.
|
|
One should consider whether templates couldn't be considered as functions,
|
|
with specialized arguments in the case of tunnel parameters.
|
|
Knowing what templates will be invoked could be used to conclude
|
|
node sorting is not necessary.
|
|
Mention how we do builtin templates
|
|
|
|
Attribute Value Templates
|
|
-------------------------
|
|
XSL-T make extensive use of Attribute Value Templates(AVTs), which are handled
|
|
by turning the grammar piece in XQuery that is closest, into an expression.
|
|
Simply, ExprSingle[32] is extended with the branch:
|
|
|
|
AVT LPAREN AttrValueContent RPAREN
|
|
|
|
where AVT is a synthetic token XSLTokenizer generates. This means that the
|
|
code handling AVTs in XQuery's direct attribute constructors handles AVTs as
|
|
generic expressions. AttrValueContent creates a call to the concat()
|
|
function, over the operands.
|
|
|
|
Deal with fn:current by using let $current := . return instruction.
|
|
|
|
Another thing related to order and parsing is that XSL-T has more freedom wrt.
|
|
to where variables are in scope. For instance, a variable declaration appearing
|
|
after a user function declaration is in scope for the function in XSL-T, but
|
|
that's not the case in XQuery. This means that delayed variable resolution must
|
|
be added, something which wasn't, and cannot be active, for the XQuery code.
|
|
See 9.7 Scope of Variables.
|
|
|
|
The parser generates for the builtin template rules:
|
|
|
|
declare template matches (text() | @*) mode #all
|
|
{
|
|
text{.}
|
|
};
|
|
|
|
*
|
|
By having templates invocations essentially expressed as a callsite, or
|
|
branching, allows control flow analysis in a traditional manner, and hence the
|
|
possiblity to conclude what templates that are possibly invoked in various
|
|
contexts (or not invoked). One good example where this could improve template
|
|
matching is patterns containg predicates: let's say a template matches text
|
|
nodes with a predicate, but , doh I'm wrong.
|
|
|
|
The problem with expressing template invocation with if expressions, is finding
|
|
ambiguous matches.
|
|
|
|
Although normalizing down to a small set of primitives has its advantages, one
|
|
problem is with doing it too early. When doing it directly when tokenization,
|
|
the higher-level perspective is lost and therefore must be restored
|
|
again(example?). For instance, if an error is reported in a primitive, it must
|
|
not appear as originating from that primitive. It's not contstrained to error
|
|
reporting(example?). However, this is a general problem when compilers shift
|
|
between different representations.
|
|
|
|
One effect this parsing approach has, is that the stylesheet cannot be used as
|
|
an input document(e.g, what document("") would evaluate to); in that case it
|
|
has to be parsed again. I think this is for the better; in the case that the
|
|
stylsheet has this dual role, it means representations are used which are
|
|
designed specifically for these respective roles. Although doing a dual parsing
|
|
step is costly, it's somewhat relieved by that the input is typically cached at
|
|
the byte level(file system and higher layers such as web/application caches) in
|
|
the case of traditional file loading.
|
|
|
|
Another problem is that the grammar is used to solve implementation details,
|
|
and this might show as part of when the parser do error reporting.
|
|
|
|
If one decide to not send XSL-T through the XQuery parser, it can be an
|
|
advantage to have as little business logic as possible in the XQuery parser
|
|
such that it can be reused.
|
|
|
|
Some parts of XSL-T's syntax doesn't translate well to XQUery syntax. Some
|
|
parts doesn't follow structure very strongly, surely not the structures that
|
|
map well to XQuery's syntax. These are xml:base, @version and other attributes
|
|
that can appear on any element. Their information needs to be preserved and
|
|
need to affect the output code, but these cannot be done in a way which fits
|
|
naturally with the XQuery syntax, and hence leads to workarounds. Have whole
|
|
section on how we do @version and @xml:base. Another problem is namespace
|
|
declarations on the top document element.
|
|
|
|
What largely makes me believe this technique fails is that the large and most
|
|
important parts, templates, instructions, maps well to XQuery, but the small
|
|
but yet not ignorable details like @version and @xml:base does not, to the
|
|
degree that the approach at large fails.
|
|
|
|
fn:document()
|
|
------------------------
|
|
See class documentation for DocumentFN. Document what optimizations one typically
|
|
wants to implement(const-fold on card 1, constant propagate).
|
|
|
|
|
|
In other words, it's reasonable to believe that it's possible to extend the
|
|
XQuery grammar such that it functionality wise is able to do the same as XSL-T,
|
|
but this doesn't equal that it is a good way to reach every gritty corner of
|
|
the XSL-T specification.
|
|
|
|
Patterns
|
|
--------------------
|
|
The up-side-down turning, discuss id/key().
|
|
|
|
Declarations
|
|
---------------------
|
|
xsl:function: the 'declare function' declaration. TODO override
|
|
|
|
XSL-T's error codes goes against good refactoring. Its codes are
|
|
specific on each usage, compared to for instance XPTY0004.
|
|
|
|
Optimizations: string-join()/value-of
|
|
|
|
<xsl:template match="document-node">
|
|
<xsl:apply-templates select="child::element(doc)"/>
|
|
</xsl:template>
|
|
|
|
<xsl:template match="child-or-top::element(doc)"/>
|
|
|
|
=>
|
|
|
|
document-node()/child::element(doc) map apply-template
|
|
|
|
matches child-or-top::element(doc)
|
|
|
|
=>
|
|
|
|
N/root(.)//(EE)
|
|
|
|
N == document-node()
|
|
EE == child::element(doc)
|
|
|
|
=>
|
|
|
|
document-node()/root(.)/descendant-or-self::node()/child::element(doc)
|
|
|
|
Optimize out already in createCopyOf()
|
|
|
|
Bugs:
|
|
- DynamicContextStore and CurrentItemStore needs to implement
|
|
evaluateToReceiver().
|
|
- Don't we have a parsing bug in each place where we call insideSequenceConstructor(), and don't
|
|
wrap the result in parantheses? E.g, a whitespace node followed by an instruction will lead to parse
|
|
error if the parent is for instance xsl:when.
|
|
|
|
In patterns we find:
|
|
- Function :id()
|
|
- Function :key()
|
|
- AxisStep
|
|
- GenericPredicate. Also used for paths.
|
|
- (CombineNodes)
|
|
- empty sequence; attribute::foo()/child::asd
|
|
|
|
|
|
Test case, tokenizer asserts(fixed in 2a0e83b):
|
|
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
|
|
|
|
|
|
<xsl:template match="/">
|
|
<xsl:call-template name="TestFunction"/>
|
|
</xsl:template>
|
|
|
|
|
|
<xsl:template name="TestFunction">
|
|
|
|
|
|
<xsl:call-template name="GetElem">
|
|
<xsl:with-param name="element-set"select="$super/*"/>
|
|
</xsl:call-template>
|
|
|
|
</xsl:template>
|
|
|
|
<xsl:template name="GetElem">
|
|
<xsl:param name="element-set"/>
|
|
<xsl:copy-of select="$element-set[@name]"/>
|
|
</xsl:template>
|
|
|
|
</xsl:stylesheet>
|
|
|
|
Typing code:
|
|
|
|
<xsl:stylesheet xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
|
|
|
|
<xsl:template match="/">
|
|
|
|
<xsl:call-template name="templateName">
|
|
<xsl:with-param name="a" select="2" />
|
|
</xsl:call-template>
|
|
|
|
</xsl:template>
|
|
|
|
<xsl:template name="templateName">
|
|
<xsl:param name="a" as="xs:integer"/>
|
|
<xsl:sequence select="$a"/>
|
|
</xsl:template>
|
|
|
|
</xsl:stylesheet>
|
|
|
|
Compat mode in attribute sets:
|
|
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
|
|
|
<xsl:attribute-set name="attrSet" version="1.0">
|
|
<xsl:attribute name="attributeName" select="1 + 'type error without compat mode'"/>
|
|
</xsl:attribute-set>
|
|
|
|
<xsl:template match="/">
|
|
<out xsl:use-attribute-sets="attrSet"/>
|
|
</xsl:template>
|
|
|
|
</xsl:stylesheet>
|
|
|
|
Space in mode:
|
|
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
|
|
|
|
<xsl:template match="/">
|
|
<xsl:apply-templates mode=" #default"/>
|
|
</xsl:template>
|
|
|
|
</xsl:stylesheet>
|
|
|
|
|
|
Type error in global template:
|
|
|
|
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
|
|
|
|
<xsl:variable name="wa" as="item()"/><!-- HERE, incorrect cardinality. -->
|
|
|
|
<xsl:template name="templateName"/>
|
|
|
|
</xsl:stylesheet>
|
|
|
|
|
|
Variables are not in scope before its siblings:
|
|
|
|
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
|
|
|
|
<xsl:template name="templateName">
|
|
<xsl:sequence select="$var"/>
|
|
<xsl:variable name="var" select="1"/>
|
|
</xsl:template>
|
|
|
|
</xsl:stylesheet>
|
|
|
|
Crashes:
|
|
|
|
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
|
xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
|
xmlns:local="http://example.com/"
|
|
version="2.0">
|
|
|
|
<xsl:variable name="var" as="xs:boolean">
|
|
<xsl:value-of select="local:doesNotExist()"/>
|
|
</xsl:variable>
|
|
|
|
</xsl:stylesheet>
|
|
|
|
|
|
|
|
Whitespace handling, the important part is WS after xsl:template:
|
|
|
|
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
|
|
|
|
<xsl:template match="/" xml:space="preserve"><MATCH/></xsl:template>
|
|
|
|
</xsl:stylesheet>
|
|
|
|
|
|
|
|
Whitespace handling, preserve, but not inside xsl:apply-templates:
|
|
|
|
<xsl:stylesheet xmlns:xsl="http://www.w2.org/1999/XSL/Transform" version="2.0">
|
|
|
|
<xsl:template match="/" xml:space="preserve">MATCH<xsl:apply-templates>
|
|
|
|
</xsl:apply-templates></xsl:template>
|
|
|
|
</xsl:stylesheet>
|
|
|
|
Have top-level xml:space, ensure whitespace as child of xsl:stylesheet is ignored:
|
|
|
|
<xsl:stylesheet xml:space="preserve" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
|
|
|
|
<xsl:template match="/">MATCH<xsl:apply-templates>
|
|
|
|
</xsl:apply-templates>
|
|
</xsl:template>
|
|
|
|
</xsl:stylesheet>
|
|
|
|
Compat mode, Saxon & QtXmlPatterns fails:
|
|
|
|
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
|
|
|
|
<xsl:template match="/">
|
|
<xsl:sequence version="1.0" select="string-join(current-dateTime(), 'separator')"/>
|
|
</xsl:template>
|
|
|
|
</xsl:stylesheet>
|
|
|
|
Compat mode, this is not in the suite:
|
|
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
|
|
|
|
<xsl:template match="/">
|
|
<xsl:sequence version="1.0" select="subsequence((1, 2), '2')"/>
|
|
</xsl:template>
|
|
|
|
</xsl:stylesheet>
|
|
|
|
Crashes:
|
|
|
|
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
|
|
|
|
<xsl:template match="doc"/>
|
|
|
|
<xsl:apply-templates select="item" mode="crazy" />
|
|
|
|
|
|
</xsl:stylesheet>
|
|
|
|
Incorrectly yields compile error, XPST0003:
|
|
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
|
|
|
|
<xsl:template match=""/>
|
|
|
|
<xsl:apply-templates select="item" mode="crazy" />
|
|
|
|
</xsl:stylesheet>
|
|
|
|
Have a basic simplified stylesheet module:
|
|
|
|
<output xsl:version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
|
<xsl:value-of select="/"/>
|
|
</output>
|
|
|
|
Have no @version:
|
|
<output xsl:version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
|
<xsl:value-of select="/"/>
|
|
</output>
|
|
|
|
|
|
Is valid:
|
|
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" >
|
|
|
|
<xsl:template match="/">
|
|
<xsl:perform-sort select=".">
|
|
<xsl:sort select="*"/>
|
|
<xsl:variable name="abc" select="b"/>
|
|
</xsl:perform-sort>
|
|
</xsl:template>
|
|
|
|
</xsl:stylesheet>
|
|
|
|
|
|
Is valid:
|
|
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" >
|
|
|
|
<xsl:template match="/">
|
|
<xsl:perform-sort select=".">
|
|
<xsl:sort select="*"/>
|
|
TEXT
|
|
</xsl:perform-sort>
|
|
</xsl:template>
|
|
|
|
</xsl:stylesheet>
|
|
|
|
XTSE0020:
|
|
<literalResultElement xsl:validation="disallowedValue"/>
|
|
|
|
XTSE0020:
|
|
<xsl:element name="localName" validation="disallowedValue"/>
|
|
|
|
XTSE0805:
|
|
<e xsl:disallowedAttribute=""/>
|
|
|
|
not XPST0003, not in test suite:
|
|
|
|
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
|
|
<xsl:template match="/">
|
|
<xsl:variable name="s" as="element()*"/>
|
|
</xsl:template>
|
|
</xsl:stylesheet>
|
|
|
|
Parsing of many exprs in xsl:value-of(with separator):
|
|
|
|
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
|
|
|
<xsl:template match="/">
|
|
<xsl:value-of separator="SEP">
|
|
<xsl:sequence select="1"/>
|
|
<xsl:sequence select="2"/>
|
|
</xsl:value-of>
|
|
</xsl:template>
|
|
|
|
</xsl:stylesheet>
|
|
|
|
|
|
Parsing of many exprs in xsl:value-of(without separator):
|
|
|
|
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
|
|
|
<xsl:template match="/">
|
|
<xsl:value-of>
|
|
<xsl:sequence select="1"/>
|
|
<xsl:sequence select="2"/>
|
|
</xsl:value-of>
|
|
</xsl:template>
|
|
|
|
</xsl:stylesheet>
|
|
|
|
|
|
Check type of empty variables:
|
|
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
|
xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
|
version="2.0">
|
|
|
|
<xsl:template match="/">
|
|
<xsl:variable name="empty"/>
|
|
|
|
<xsl:sequence select="'instance of xs:string:', $empty instance of xs:string, '(should be true)',
|
|
'instance of document-node():', $empty instance of document-node(), '(should be false)',
|
|
'value is:', $empty,
|
|
'END'"/>
|
|
|
|
</xsl:template>
|
|
|
|
</xsl:stylesheet>
|
|
|
|
|
|
Crashes:
|
|
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
|
|
|
<xsl:template match="/">
|
|
<e xmlns="ABC"/>
|
|
</xsl:template>
|
|
|
|
</xsl:stylesheet>
|
|
|
|
|
|
invalid standard attributes on a simplified stylesheet module.
|
|
|
|
|
|
|
|
|
|
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
|
xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
|
version="2.0">
|
|
|
|
<!-- Type error: applying templates to a variable of type string -->
|
|
<?spec xslt#applying-templates?>
|
|
<?error XTTE0520?>
|
|
|
|
<xsl:template match="/">
|
|
<xsl:variable name="empty"/>
|
|
|
|
<xsl:sequence select="'instance of xs:string:', $empty instance of xs:string, 'instance of document-node():', $empty instance of document-node()"/>
|
|
|
|
</xsl:template>
|
|
|
|
</xsl:stylesheet>
|
|
|
|
|
|
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
|
|
|
|
<xsl:template match="/">
|
|
<output>
|
|
<xsl:sequence select="string-length(doesNotMatch)"/>
|
|
</output>
|
|
</xsl:template>
|
|
|
|
</xsl:stylesheet>
|
|
|
|
Asserts(not wellformed):
|
|
|
|
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
|
|
<xsl:template match="/">
|
|
<output>
|
|
</outpu>
|
|
</xsl:template>
|
|
|
|
</xsl:stylesheet>
|
|
|
|
|
|
From within a function, use the focus /through/ a variable reference:
|
|
|
|
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:local="http://www.w3.org/2005/xquery-local-functions">
|
|
|
|
<xsl:variable name="var" select="node()"/>
|
|
|
|
<xsl:function name="local:function">
|
|
<xsl:sequence select="$var"/>
|
|
</xsl:function>
|
|
|
|
<xsl:template match="/">
|
|
<xsl:sequence select="local:function()"/>
|
|
</xsl:template>
|
|
|
|
</xsl:stylesheet>
|
|
|
|
|
|
|
|
Loops infinitely:
|
|
|
|
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
|
|
|
|
<xsl:template match="/" version="1.0">
|
|
<xsl:namespace name="{doc/item}" select="'http://www.example.com'" version="1.0"/>
|
|
</xsl:template>
|
|
|
|
</xsl:stylesheet>
|
|
|
|
|
|
Gives crash in coloring code:
|
|
Stylesheet:
|
|
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
|
|
|
|
<xsl:template match="/">
|
|
</xsl:template>
|
|
|
|
</xsl:stylesheet>
|
|
|
|
Focus:
|
|
<a><b/><</a>
|
|
|
|
|
|
Should evaluate to true:
|
|
|
|
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0">
|
|
|
|
<xsl:template match="/">
|
|
<xsl:call-template name="yo">
|
|
<xsl:with-param name="arg" as="xs:integer">
|
|
<xsl:sequence select="xs:untypedAtomic('1')"/>
|
|
</xsl:with-param>
|
|
</xsl:call-template>
|
|
</xsl:template>
|
|
|
|
<xsl:template name="yo">
|
|
<xsl:param name="arg"/>
|
|
<xsl:sequence select="$arg instance of xs:integer"/>
|
|
</xsl:template>
|
|
|
|
</xsl:stylesheet>
|
|
|
|
Crashes, should be XTTE0570:
|
|
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
|
xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
|
exclude-result-prefixes="xs" version="2.0">
|
|
|
|
<xsl:template match="/">
|
|
<xsl:apply-templates>
|
|
<xsl:with-param name="second_seq" as="xs:string">
|
|
</xsl:with-param>
|
|
|
|
</xsl:apply-templates>
|
|
</xsl:template>
|
|
|
|
<xsl:template match="empty">
|
|
<xsl:param name="second_seq">def</xsl:param>
|
|
<xsl:sequence select="$second_seq instance of xs:string"/>
|
|
</xsl:template>
|
|
|
|
</xsl:stylesheet>
|
|
|
|
* Parse error:
|
|
|
|
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
|
|
|
<xsl:template match="/">
|
|
<xsl:copy>
|
|
<xsl:sequence select="1"/>
|
|
<xsl:sequence select="2"/>
|
|
</xsl:copy>
|
|
</xsl:template>
|
|
|
|
</xsl:stylesheet>
|
|
|
|
* Write tests with xsl:with-param whose body is empty. That's effectively an
|
|
empty sequence(?) which needs to be handled properly, and (dynamically) type
|
|
checked correctly.
|
|
|
|
--------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------
|
|
|
|
|
|
|
|
-------------------------------------------------------------
|
|
/a/b
|
|
|
|
=>
|
|
|
|
b[parent::a[parent::document()]]
|
|
|
|
but we currently have:
|
|
|
|
(b[parent::a])[parent::document()]
|
|
|
|
-------------------------------------------------------------
|
|
a/b
|
|
|
|
=>
|
|
|
|
b[parent::a]
|
|
|
|
-------------------------------------------------------------
|
|
a/b/c
|
|
|
|
=>
|
|
|
|
c[parent::b[parent::a]]
|
|
|
|
-------------------------------------------------------------
|
|
a/b/c/d
|
|
|
|
=>
|
|
|
|
d[parent::c[parent::b[parent::a]]]
|
|
|
|
|
|
-------------------------------------------------------------
|
|
/a/b/c/d
|
|
|
|
=>
|
|
|
|
d[parent::c[parent::b[parent::a[parent::document()]]]]
|
|
|
|
This is handled specially; see | SLASH RelativePathPattern
|
|
|
|
|
|
b/c rewrites to:
|
|
TruthPredicate
|
|
AxisStep self::element(c)
|
|
AxisStep parent::element(b)
|
|
|
|
For a/b/c we get:
|
|
|
|
TruthPredicate
|
|
TruthPredicate
|
|
AxisStep self::element(c)
|
|
AxisStep parent::element(b)
|
|
AxisStep parent::element(a)
|
|
|
|
But we want:
|
|
|
|
TruthPredicate
|
|
AxisStep child-or-top::element(c)
|
|
TruthPredicate
|
|
AxisStep parent::element(b)
|
|
AxisStep parent::element(a)
|
|
|
|
For a/b/c/d we get:
|
|
|
|
TruthPredicate
|
|
TruthPredicate
|
|
TruthPredicate
|
|
AxisStep self::element(d)
|
|
AxisStep parent::element(c)
|
|
AxisStep parent::element(b)
|
|
AxisStep parent::element(a)
|
|
|
|
For a/b/c/d we want:
|
|
|
|
TruthPredicate
|
|
AxisStep self::element(d)
|
|
TruthPredicate
|
|
AxisStep parent::element(c)
|
|
TruthPredicate
|
|
AxisStep parent::element(b)
|
|
AxisStep parent::element(a)
|
|
|
|
|
|
For /a/b we get:
|
|
|
|
TruthPredicate
|
|
TruthPredicate:
|
|
AxisStep self::element(b)
|
|
AxisStep parent::element(a)
|
|
AxisStep parent::document()
|
|
|
|
but we want:
|
|
|
|
TruthPredicate
|
|
AxisStep self::element(b)
|
|
TruthPredicate: // PREDICATE
|
|
AxisStep parent::element(a)
|
|
AxisStep parent::document() // PREDICATE
|
|
|
|
--------------------------------------------------------------
|
|
For a/b/c we get:
|
|
TruthPredicate
|
|
AxisStep self::element(c)
|
|
TruthPredicate
|
|
parent::element(b)
|
|
parent::element(a)
|
|
|