tags:

views:

25

answers:

2

Does anyone know of an example of defining a datatype using xml schema and using it in a XSL template with a xsl:sort instruction

Thanks in advance.

A: 

In XSLT 2.0 the data-type attribute of <xsl:sort> remains only for compatibility with XSLT 1.0.

The sort-key values are compared using the lt value comparison operator. This means that it is no longer necessary to provide the type "text" or "number" as the value of the data-type attribute. If the type of the expression defining the sort-key is xs:string then the lt operator for xs:string is used.

If the type of the sort key is not a string or a number, but has an lt operator, then the lt operator for this type is used. For example, xs:date, xs:dateTime, ..., etc can be sorted correctly and this doesn't require specifying any value for the data-type attribute.

An user-defined type is likely to lack a defined lt attribute, which means that if the sort-keys are of this type, the sort operation will fail.

Of course, one can always provide an expression in the select attribute that is a reference to an xsl:function that the user has especially provided to convert the instance of the user-defined type to a type that has the lt operator.

Dimitre Novatchev
1) You say "lt attribute" here - "An user-defined type is likely to lack a defined lt attribute"But, "lt operator" later. Did you mean "attribute" or is this a typo?2) Is there a way to provide a "lt operator" or "attribute" to a user-defined type that the XSL processor can use? Or are you forced to do the conversion through a function? I know they will be essentially equivalent, but just wondered
Fred Finkle
@jweiner51 I said it: types that don't have the `lt` operator cannot be the types of the sort key. In such case you should use your oun `xsl:function` that accesses a value of this type and converts it to a value, for which there is an `lt` operator. For example your function may be named: `my:myTypeToInt` and it will convert any value of tupe `myType` to `xs:integer`. You will use it like this: `<xsl:sort select="my:myTypeToInt(myChildOfTypemyType)"/>`
Dimitre Novatchev
Thanks for the clarification.
Fred Finkle
A: 

To give you an example you asked for, assume we have a schema file test2010083101Xsd.xml as follows:

<xs:schema
  xmlns:xs="http://www.w3.org/2001/XMLSchema"&gt;

  <xs:element name="root">
    <xs:complexType>
      <xs:sequence maxOccurs="unbounded">
        <xs:element name="data" type="xs:double"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

</xs:schema>

an XML input document as follows:

<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="test2010083101Xsd.xml">
  <data>2</data>
  <data>10</data>
  <data>1.5</data>
</root>

and an XSLT 2.0 stylesheet as follows:

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="2.0">

  <xsl:output method="text"/>

  <xsl:template match="/">
    <xsl:apply-templates select="root/data">
      <xsl:sort select="."/>
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="data">
    <xsl:value-of select="concat(., '&#10;')"/>
  </xsl:template>

</xsl:stylesheet>

then when you run that stylesheet with AltovaXML tools (a schema aware XSLT 2.0 processor which takes the xsi:noNamespaceSchemaLocation into account) with

AltovaXML.exe /xslt2 test2010083101Xsl.xml /in test2010083101.xml

the output is

1.5
2
10

so the xs:double data type is taken into account when sorting the 'data' elements.

When you run the same stylesheet against the same XML input document with an XSLT 2.0 processor which is not schema aware (like Saxon 9.2 Home Edition) then the output is different:

1.5
10
2

as in that case the values are sorted as strings.

Martin Honnen
I guess your answer and the one above tells me that although I've used XML schema and XSL a lot, I've never used them (really) together. Need to do that - along with an upgrade to an XSLT processor that is schema-aware (and runs on MAC).
Fred Finkle
@Martin Honnen: this is a detail explanation, but you are ussing a built-in data type. This should works in both schema-aware or not schema-aware processor: `<xsl:sort select="xs:double(.)"/>`. But for user data type you must declare a function providing order for `op:lt` operator, as Dimitre's answer.
Alejandro