Reputation: 23666
Is there a good way to assert that the value of the current element must be of a certain type (e.g. xs:integer), and thrown an exception if it's not? Using XSL 2.0
Upvotes: 1
Views: 291
Reputation: 28618
Use the cast as
operator, e.g.
'5' cast as xs:integer
returns 5
'foo' cast as xs:integer
throws Cannot convert string "d" to an integer
using Saxon.
If you want to throw your own error you can use castable as
, e.g.
if (not('foo' castable as xs:integer)) then
error((), 'bad')
Upvotes: 0
Reputation: 243579
One can use the f:type()
function of the FXSL library to dynamically determine the type of a variable/value.
Here is the test transformation in FXSL for f:type()
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:f="http://fxsl.sf.net/"
exclude-result-prefixes="f xs"
>
<xsl:import href="../f/func-type.xsl"/>
<!-- To be applied on ../data/numList.xml -->
<xsl:output omit-xml-declaration="yes"/>
<xsl:template match="/">
f:apply(f:typeConstructor(11),'03'): <xsl:value-of select="f:apply(f:typeConstructor(11),'03')"/>
f:apply(f:typeConstructor('xxx'),'03'): <xsl:value-of select="f:apply(f:typeConstructor('xxx'),'03')"/>
f:apply(f:typeConstructor(11),'03') gt 4: <xsl:value-of select="f:apply(f:typeConstructor(11),'03') gt 4"/>
f:type(f:apply(f:typeConstructor(11),'03')): <xsl:value-of select="f:type(f:apply(f:typeConstructor(11),'03'))"/>
f:type(f:apply(f:typeConstructor('string'), 3)): <xsl:value-of select="f:type(f:apply(f:typeConstructor('string'),'03'))"/>
<!-- Supported only by a SA Processor -->
xs:token('abc') : <xsl:value-of select="f:type(xs:token('abc'))"
use-when="system-property('xsl:is-schema-aware')='yes'"/>
-1 : <xsl:value-of select="f:type(-1)"/>
<!-- Supported only by a SA Processor -->
xs:negativeInteger(-1) : <xsl:value-of select="f:type(xs:negativeInteger(-1))"
use-when="system-property('xsl:is-schema-aware')='yes'" />
xs:nonPositiveInteger(0) : <xsl:value-of select="f:type(xs:nonPositiveInteger(0))"
use-when="system-property('xsl:is-schema-aware')='yes'" />
0 : <xsl:value-of select="f:type(0)"/>
3 : <xsl:value-of select="f:type(3)"/>
3. : <xsl:value-of select="f:type(3.)"/>
3.0E1 : <xsl:value-of select="f:type(3.0E1)"/>
xs:float(3) : <xsl:value-of select="f:type(xs:float(3))"/>
<!-- Supported only by a SA Processor -->
xs:positiveInteger(3) : <xsl:value-of select="f:type(xs:positiveInteger(3))"
use-when="system-property('xsl:is-schema-aware')='yes'" />
'3' : <xsl:value-of select="f:type('3')"/>
(/*/*/text())[1] : <xsl:value-of select="f:type((/*/*/text())[1])"/>
data((/*/*/text())[1]) : <xsl:value-of select="f:type(data((/*/*/text())[1]))"/>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on this XML document:
<nums>
<num>01</num>
<num>02</num>
<num>03</num>
<num>04</num>
<num>05</num>
<num>06</num>
<num>07</num>
<num>08</num>
<num>09</num>
<num>10</num>
</nums>
the wanted, corect results are produced:
f:apply(f:typeConstructor(11),'03'): 3
f:apply(f:typeConstructor('xxx'),'03'): 03
f:apply(f:typeConstructor(11),'03') gt 4: false
f:type(f:apply(f:typeConstructor(11),'03')): xs:integer
f:type(f:apply(f:typeConstructor('string'), 3)): xs:string
xs:token('abc') : xs:string
-1 : xs:integer
xs:negativeInteger(-1) : xs:integer
xs:nonPositiveInteger(0) : xs:integer
0 : xs:integer
3 : xs:integer
3. : xs:decimal
3.0E1 : xs:double
xs:float(3) : xs:float
xs:positiveInteger(3) : xs:integer
'3' : xs:string
(/*/*/text())[1] : xml:node
data((/*/*/text())[1]) : xs:string
Explanation:
f:type()
, as can be seen from its source uses internally the XPath 2.0 operator instance of
and tests a value from a most common type to more specific types until it determines a specific type.
Upvotes: 1
Reputation: 167716
With a schema aware XSLT 2.0 processor like the enterprise editions of Saxon 9 or like XmlPrime or AltovaXML you can use W3C XML schemas to validate your input documents when processing them with XSLT.
Upvotes: 0