zer0stimulus
zer0stimulus

Reputation: 23666

How to assert that an element value is of certain type?

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

Answers (4)

Max Toro
Max Toro

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

Dimitre Novatchev
Dimitre Novatchev

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

Martin Honnen
Martin Honnen

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

Swapnil
Swapnil

Reputation: 8328

In XPath, you can use instance of like this:

5 instance of xs:integer

This example returns true because the given value is an instance of the given type.

For additional information, you can check this.

Upvotes: 0

Related Questions