xs:anySimpleType
One interesting simple type that can be the cause of a number of static type issues is xs:anySimpleType. This type is the base type of all simple types. That includes list and union types. By default, attributes are typed xs:anySimpleType, so if you do not specify a type via the type attribute, any simple type value is valid for that attribute. This includes list type values. You can also have element content typed to xs:anySimpleType. In that case, you can optionally specify the specific simple type that a specific element instance contains.
Because xs:anySimpleType includes list types, you may end up with static typing errors if you do not specify a type for an attribute and are querying for the attribute in a typed xml column. The problem has to do with cardinality. The error message that you get can be confusing and the typical way to correct such a static typing error does not work in this case. Here is an example:
create xml schema collection att as N'
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="mult">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:string"
name="elem" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="att"/>
</xs:complexType>
</xs:element>
</xs:schema>'
go
declare @x xml(att)
set @x = 'string'
select @x.query('/mult/elem cast as xs:string?')
go
declare @x xml(att)
set @x = 'string'
select @x.query('/mult/@att cast as xs:string?')
These two queries will result in the follow error messages:
Msg 2365, Level 16, State 1, Line 3
XQuery [query()]: Cannot explicitly convert
from 'xs:string *' to 'xs:string ?'
Msg 2365, Level 16, State 1, Line 4
XQuery [query()]: Cannot explicitly convert
from 'xdt:anyAtomicType *' to 'xs:string ?'
The first query is easy to fix. Because there can be more than one elem element under the mult element, you must specify which chlid element you really want. We change the query to be (/mult/elem)[1] cast as xs:string?. So why do we see the same error with the second query? There can only be one @att element under the mult element, so why is the type that is inferred xdt:anyAtomicType*? If we try to fix the second query using the same workaround as the first, we still get the same error message! Even though you don't see it, the attribute is being implicitly atomized because of the cast operator. Because xs:anySimpleType includes list types, the atomization results in potentially zero or more atomic values. Since the query compiler can not possible know up front what the type is for the atomic values, we infer xdt:anyAtomicType.
The workaround is to explicitly atomize the attribute and place a positional predicate or more simply, supply an atomic type for the attribute. To atomize the attribute you can change the query as such:
declare @x xml(att)
set @x = '<mult att="foo"><elem>string</elem></mult>'
select @x.query('data(/mult/@att)[1] cast as xs:string?')
Note that the work around is also applicable for elements and attributes that are list types.