<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="https://www.w3.org/2005/Atom" xmlns:sy="https://purl.org/rss/1.0/modules/syndication/" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:wfw="https://wellformedweb.org/CommentAPI/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>XQuery Inside SQL Server 2005</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/mrorke/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/mrorke/feed.xml</link>
    <description>Hopefully helpful postings, articles and walkthroughs for people using XQuery inside SQL Server 2005.</description>
    <lastBuildDate>Tue, 16 Apr 2019 05:19:42 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>XQuery Candidate Recommendation Documents Released</title>
      <link>https://docs.microsoft.com/archive/blogs/mrorke/xquery-candidate-recommendation-documents-released</link>
      <pubDate>Thu, 03 Nov 2005 13:09:00 GMT</pubDate>
      <dc:creator><![CDATA[mrorke]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/mrorke/2005/11/03/xquery-candidate-recommendation-documents-released/</guid>
      <description><![CDATA[The official candidate recommendation versions of the XQuery specifications have been published by...]]></description>
      <content:encoded><![CDATA[<P>The official candidate recommendation versions of the XQuery specifications have been published by the W3C at <A href="https://www.w3.org/TR/#CR">https://www.w3.org/TR/#CR</A>. The details of the specific documents are as follows:</P>
<P>XQuery 1.0: An XML Query Language<BR><A href="https://www.w3.org/TR/2005/CR-xquery-20051103/">https://www.w3.org/TR/2005/CR-xquery-20051103/</A></P>
<P>XQuery 1.0 and XPath 2.0 Functions and Operators<BR><A href="https://www.w3.org/TR/2005/CR-xpath-functions-20051103/">https://www.w3.org/TR/2005/CR-xpath-functions-20051103/</A></P>
<P>XQuery 1.0 and XPath 2.0 Data Model (XDM)<BR><A href="https://www.w3.org/TR/2005/CR-xpath-datamodel-20051103/">https://www.w3.org/TR/2005/CR-xpath-datamodel-20051103/</A></P>
<P>XQuery 1.0 and XPath 2.0 Formal Semantics<BR><A href="https://www.w3.org/TR/2005/CR-xquery-semantics-20051103/">https://www.w3.org/TR/2005/CR-xquery-semantics-20051103/</A></P>
<P>XSLT 2.0 and XQuery 1.0 Serialization<BR><A href="https://www.w3.org/TR/2005/CR-xslt-xquery-serialization-20051103/">https://www.w3.org/TR/2005/CR-xslt-xquery-serialization-20051103/</A></P>]]></content:encoded>
    </item>
    <item>
      <title>Dynamic XQuery Expressions</title>
      <link>https://docs.microsoft.com/archive/blogs/mrorke/dynamic-xquery-expressions</link>
      <pubDate>Mon, 24 Oct 2005 12:29:00 GMT</pubDate>
      <dc:creator><![CDATA[mrorke]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/mrorke/2005/10/24/dynamic-xquery-expressions/</guid>
      <description><![CDATA[We have had several requests through our message boards for details on how to execute dynamic XQuery...]]></description>
      <content:encoded><![CDATA[<P>We have had several requests through our message boards for details on how to execute dynamic XQuery expressions. A dynamic XQuery expression is one whose exact details are not know at the time when the query is written. For example, consider the following XML fragment stored in a single XML data-type instance:</P><PRE>&lt;foo id="1"&gt;foo 1&lt;/foo&gt;
&lt;foo id="2"&gt;foo 2&lt;/foo&gt;
&lt;foo id="3"&gt;foo 3&lt;/foo&gt;
</PRE>
<P>Suppose we have some client side logic where the user is able to choose which of the 3 foo elements that want to return. The XQuery expression used in this case is going to depend on the particular item requested and will not be known until the user makes their decision (i.e. it can not simply be hard-coded as a string). Since the XML data-type methods require a string <STRONG>constant</STRONG> as their input, there is no way to directly specify dynamic XQuery expressions. There are some workarounds for this problem, depending on exactly what part of the query is dynamic.</P>
<P>The easiest option is where the query simply needs to be parametrized. As is the case with the example above, the dynamic part of the query simply consists of a constant value that is different for each query execution. The easiest way to parametrize a query is to use the <FONT face="Courier New">sql:variable()</FONT> XQuery function and store the parameter value in the associated T-SQL variable. For example:</P><PRE>declare @index int
set @index=2

select data.query( N'
/foo[position()=<FONT color=#ff0000>sql:variable("@index")</FONT>]
 ') from test
</PRE>
<P>In this case, the index for the required item is stored in the T-SQL variable <FONT face="Courier New">@index</FONT> and this is then referenced in the XQuery expression through the <FONT face="Courier New">sql:variable()</FONT> function. Notice that we can not simply use the value of the <FONT face="Courier New">sql:variable()</FONT> function as an ordinal predicate - rather, we need to explicitly compare it's value to that of the <FONT face="Courier New">position()</FONT> function. This is due to a limitation of the XQuery implementation inside SQL Server 2005 that requires ordinal predicates to be numeric literal values (i.e. they can not be something that changes at query execution time). 
<P>While the parametrization of queries is a powerful tool, it does not solve the general problem of being able to execute truly dynamic XQuery expressions. In order to do this, you need to use the T-SQL <FONT face="Courier New">exec</FONT> function. The T-SQL <FONT face="Courier New">exec</FONT> function allows any string value to be executed as a T-SQL expression. For example:</P><PRE>declare @query nvarchar(200);

set @query=N'
<FONT style="BACKGROUND-COLOR: #ffffff" color=#ff0000>select data.query( N''
/foo[1]
 '') from test1</FONT>'

exec( @query )
</PRE>
<P>The part of the query marked in red is the dynamic XQuery expression. Notice that the entire T-SQL expression (i.e. including the <FONT face="Courier New">select ... from</FONT> part of the statement) needs to be included in the dynamic query string. Also, notice that the <FONT face="Courier New">'</FONT> characters that are used to contain the XQuery part of the expression need to be escaped (as <FONT face="Courier New">''</FONT>) in order to make the query string valid. 
<P>While this is not an ideal solution to the problem of dynamic queries, most cases can be handled by the parametrization option and the exec function should only be used as a last resort.</P>
<H6>-<BR>Disclaimer:<BR>This posting is provided “AS IS” with no warranties, and confers no rights.<BR>Use of included script samples are subject to the terms specified at <A href="https://www.microsoft.com/info/cpyright.htm"><FONT color=#003399>https://www.microsoft.com/info/cpyright.htm</FONT></A>.</H6>]]></content:encoded>
    </item>
    <item>
      <title>XQuery Test Suite - new version 0.7 released</title>
      <link>https://docs.microsoft.com/archive/blogs/mrorke/xquery-test-suite-new-version-0-7-released</link>
      <pubDate>Tue, 18 Oct 2005 15:39:00 GMT</pubDate>
      <dc:creator><![CDATA[mrorke]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/mrorke/2005/10/18/xquery-test-suite-new-version-0-7-released/</guid>
      <description><![CDATA[The XQuery Testing Task Force is pleased to announce the publication of version 0.7 of our XQuery...]]></description>
      <content:encoded><![CDATA[The XQuery Testing Task Force is pleased to announce the publication of version 0.7 of our XQuery test suite. Please visit <A href="https://www.w3.org/XML/Query/test-suite/">https://www.w3.org/XML/Query/test-suite/</A>&nbsp;for details.]]></content:encoded>
    </item>
    <item>
      <title>Static Typing Consequences for the Parent Axis and Attribute Types</title>
      <link>https://docs.microsoft.com/archive/blogs/mrorke/static-typing-consequences-for-the-parent-axis-and-attribute-types</link>
      <pubDate>Thu, 29 Sep 2005 13:08:00 GMT</pubDate>
      <dc:creator><![CDATA[mrorke]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/mrorke/2005/09/29/static-typing-consequences-for-the-parent-axis-and-attribute-types/</guid>
      <description><![CDATA[I posted a previous blog entry dealing with the static typing consequences of using the parent axis...]]></description>
      <content:encoded><![CDATA[<P>I posted a previous blog entry dealing with the static typing consequences of using the parent axis in your XQuery expressions over XML data inside SQL Server 2005 (<A href="https://blogs.msdn.com/mrorke/archive/2005/08/18/453187.aspx">Static Typing Consequences of the Parent Axis</A>). In addition to the general issue of typing information loss associated with the parent axis, there is an additional issue that is related to attributes in particular. This issue is best explained through an example. Consider the following XSD schema definition:</P><PRE>create xml schema collection attribute_types as N'
&lt;xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="https://www.w3.org/2001/XMLSchema"&gt;	
	&lt;xs:element name="root"&gt;
		&lt;xs:complexType&gt;
			&lt;xs:choice maxOccurs="unbounded"&gt;
				&lt;xs:element name="pointer"&gt;
					&lt;xs:complexType&gt;
						&lt;xs:choice&gt;
							&lt;xs:element name="sibling" type="xs:string" /&gt;
						&lt;/xs:choice&gt;
						&lt;xs:attribute name="singleton_attribute" type="xs:IDREF" /&gt;
						&lt;xs:attribute name="list_attribute" type="xs:IDREFS" /&gt;
					&lt;/xs:complexType&gt;
				&lt;/xs:element&gt;
				&lt;xs:element name="target"&gt;
					&lt;xs:complexType&gt;
						&lt;xs:attribute name="ID" type="xs:ID" /&gt;
					&lt;/xs:complexType&gt;
				&lt;/xs:element&gt;
			&lt;/xs:choice&gt;
		&lt;/xs:complexType&gt;
	&lt;/xs:element&gt;
&lt;/xs:schema&gt;'
</PRE>
<P>In this case, we have defined a schema for a piece of XML that uses <FONT face="Courier New">ID</FONT> and <FONT face="Courier New">IDREF</FONT> types to create links between different elements. The important thing to notice here is the difference between the types of the <FONT face="Courier New">singleton_attribute</FONT> and <FONT face="Courier New">list_attribute</FONT> attributes of the pointer element. Note that the&nbsp;<FONT face="Courier New">singleton_attribute</FONT> has a type of <FONT face="Courier New">xs:IDREF</FONT> (implying a single <FONT face="Courier New">IDREF</FONT> value), while the <FONT face="Courier New">list_attribute</FONT> has a type <FONT face="Courier New">xs:IDREFS</FONT> (implying a list of <FONT face="Courier New">IDREF</FONT> values). Another key piece of information is the way in which list types are handled in XQuery. XQuery does not have a concept of list types as such, and handles these by simply treating their values as a sequence of singleton simple types. This is best illustrated by examining the static types of some queries over an instance of this data. Taking the following XML instance:</P><PRE>declare @x xml(attribute_types)
set @x='
&lt;root&gt;
	&lt;pointer singleton_attribute="A"&gt;
		&lt;sibling&gt;test&lt;/sibling&gt;
	&lt;/pointer&gt;
	&lt;pointer list_attribute="A B"&gt;
		&lt;sibling&gt;test&lt;/sibling&gt;
	&lt;/pointer&gt;

	&lt;target ID="A"/&gt;
	&lt;target ID="B"/&gt;
&lt;/root&gt;'
</PRE>
<P>If we execute a query to select the value of a single instance of the <FONT face="Courier New">singleton_attribute</FONT>:</P><PRE>select @x.query('
data( (/root/pointer)[1]/@singleton_attribute )
')
</PRE>
<P>Examining the static type generated by this query, we get the following - <FONT face="Courier New">xs:IDREF <FONT color=#ff0000><STRONG>?</STRONG></FONT></FONT>&nbsp;i.e. a single instance (optional) of an <FONT face="Courier New">IDREF</FONT> value. If we now execute a query to select the value of a single instance of the <FONT face="Courier New">list_attribute</FONT>:</P><PRE>select @x.query('
data( (/root/pointer)[2]/@list_attribute )
')
</PRE>
<P>Examining the static type generated by this query, we get the following - <FONT face="Courier New">xs:IDREF <FONT style="BACKGROUND-COLOR: #ffffff" color=#ff0000><STRONG>*</STRONG></FONT></FONT> i.e. multiple (optional) <FONT face="Courier New">IDREF</FONT> values. So, the result of selecting a single attribute of an XSD list type is a sequence of values, not a singleton. This is very useful since we can now use standard XQuery semantics (e.g. the ordinal predicate or FLWOR iteration) to navigate through this list of values and find the one we want. 
<P>This all works fine since the <FONT face="Courier New">data </FONT>function is able to handle sequences of values. But, remember that a lot of the functions and operators in XQuery require a singleton value and these will fail if applied to the value(s) of the <FONT face="Courier New">list_attribute</FONT>. </P>
<P>Now, remembering that the parent axis causes a loss of type fidelity and understanding that the above semantics require that the type of the attribute be known - what happens when we combine the parent axis with these attributes. Taking the following query against the&nbsp;<FONT face="Courier New">singleton_attribute</FONT>:</P><PRE>select @x.query('
data( (/root/pointer)[1]/sibling/../@singleton_attribute )
')
</PRE>
<P>If we examine the static type generated by this query, we now get the following:&nbsp;<FONT face="Courier New">xdt:anyAtomicType *</FONT>. Two things to notice here, firstly we have lots type fidelity (<FONT face="Courier New">IDREF</FONT> has become&nbsp; <FONT face="Courier New">anyAtomicType</FONT>) and secondly we have gone from an (optional) singleton value to a sequence! In fact, if we run a similar query against the <FONT face="Courier New">list_attribute</FONT>:</P><PRE>select @x.query('
data( (/root/pointer)[2]/sibling/../@list_attribute )
')
</PRE>
<P>We get the exact same static type generated! The reasoning behind this is that, since we have lost all type fidelity by using the parent axis and there is a <STRONG>possibility</STRONG> that the attribute selected was a list type, we assume for the purposes of static typing that the result is a sequence i.e. we have lost the fact the the&nbsp;<FONT face="Courier New">singleton_attribute</FONT> was a singleton value!</P>
<P>This in and of itself is a problem, but (in most cases) the operations defined to deal with IDREF values can handle sequences of values, so this problem is moot in this case. But, armed with our knowledge of how the parent axis affects both the type and cardinality of attribute types, take the following new XSD schema:</P><PRE>create xml schema collection attribute_types2 as N'
&lt;xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="https://www.w3.org/2001/XMLSchema"&gt;	
	&lt;xs:element name="root"&gt;
		&lt;xs:complexType&gt;
			&lt;xs:choice maxOccurs="unbounded"&gt;
				&lt;xs:element name="value"&gt;
					&lt;xs:complexType&gt;
						&lt;xs:choice&gt;
							&lt;xs:element name="sibling" type="xs:string" /&gt;
						&lt;/xs:choice&gt;
						&lt;xs:attribute name="integer" type="xs:integer" /&gt;
					&lt;/xs:complexType&gt;
				&lt;/xs:element&gt;
			&lt;/xs:choice&gt;
		&lt;/xs:complexType&gt;
	&lt;/xs:element&gt;
&lt;/xs:schema&gt;'
</PRE>
<P>In this case, we have an attribute that stores a single integer value. Taking the following instance of the above schema:</P><PRE>declare @x xml(attribute_types2)
set @x='
&lt;root&gt;
	&lt;value integer="12"&gt;
		&lt;sibling&gt;test&lt;/sibling&gt;
	&lt;/value&gt;
&lt;/root&gt;
'
</PRE>
<P>We can use this attribute value in conjunction with the arithmetic operators to do some calculations:</P><PRE>select @x.query('
(/root/value)[1]/@integer + 10
')
</PRE>
<P>This works fine and returns the expected result of 22. Now, if we add in a parent axis to the mix:</P><PRE>select @x.query('
(/root/value)[1]/sibling/../@integer + 10
')
</PRE>
<P>We get the following error message returned:</P><PRE><FONT style="BACKGROUND-COLOR: #ffffff" color=#ff0000>Msg 2389, Level 16, State 1, Line 11
XQuery [query()]: '+' requires a singleton (or empty sequence), found operand of type 'xdt:anyAtomicType *'</FONT>
</PRE>
<P>So, even though we had no list types in our schema at all. Because of the loss of typing fidelity from the parent operator and the necessary assumption that any attribute might be a list type in this case, we loose cardinality fidelity too.</P>
<P>Again, the moral of the story is to use the parent operator with extreme caution :)</P>
<H6>-<BR>Disclaimer:<BR>This posting is provided “AS IS” with no warranties, and confers no rights.<BR>Use of included script samples are subject to the terms specified at <A href="https://www.microsoft.com/info/cpyright.htm">https://www.microsoft.com/info/cpyright.htm</A>.</H6>]]></content:encoded>
    </item>
    <item>
      <title>XML Data-type Usage By Other SQL Server 2005 Features</title>
      <link>https://docs.microsoft.com/archive/blogs/mrorke/xml-data-type-usage-by-other-sql-server-2005-features</link>
      <pubDate>Thu, 25 Aug 2005 13:40:00 GMT</pubDate>
      <dc:creator><![CDATA[mrorke]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/mrorke/2005/08/25/xml-data-type-usage-by-other-sql-server-2005-features/</guid>
      <description><![CDATA[Several of the other features within SQL Server 2005 leverage the XML data-type to pass information...]]></description>
      <content:encoded><![CDATA[<P>Several of the other features within SQL Server 2005 leverage the XML data-type to pass information around. For example, both Service Broker and triggers transfer data around the server in XML data-type instances. This means that you can easily leverage the power of the XQuery language and other XML data-type methods when using these features.</P>
<P>To illustrate this, we create a simple trigger on our database that fires when we create a new table:</P><PRE>create trigger CreateTableTrigger on database for create_table as 
select eventdata()
</PRE>
<P>In this case, our trigger is simply outputting the result of the <FONT face="Courier New">eventdata()</FONT> function each time a table is created. If we now create a table called <FONT face="Courier New">Test</FONT> in this database, we get the following XML instance returned:</P><PRE>&lt;EVENT_INSTANCE&gt;
  &lt;EventType&gt;CREATE_TABLE&lt;/EventType&gt;
  &lt;PostTime&gt;...&lt;/PostTime&gt;
  &lt;SPID&gt;51&lt;/SPID&gt;
  &lt;ServerName&gt;...&lt;/ServerName&gt;
  &lt;LoginName&gt;...&lt;/LoginName&gt;
  &lt;UserName&gt;dbo&lt;/UserName&gt;
  &lt;DatabaseName&gt;master&lt;/DatabaseName&gt;
  &lt;SchemaName&gt;dbo&lt;/SchemaName&gt;
  &lt;ObjectName&gt;Test&lt;/ObjectName&gt;
  &lt;ObjectType&gt;TABLE&lt;/ObjectType&gt;
  &lt;TSQLCommand&gt;
    &lt;SetOptions ANSI_NULLS="ON" ANSI_NULL_DEFAULT="ON" ANSI_PADDING="ON" QUOTED_IDENTIFIER="ON" ENCRYPTED="FALSE" /&gt;
    &lt;CommandText&gt;create table [Test](c1 int )&lt;/CommandText&gt;
  &lt;/TSQLCommand&gt;
&lt;/EVENT_INSTANCE&gt;
</PRE>
<P>I have removed some of the information from the XML for security reasons :) Basically, we see from this that the <FONT face="Courier New">eventdata()</FONT> function, called from within a trigger, returns an instance of the XML data-type. This means that we are free to go ahead and apply any of the XML data-type methods to this in order to customize the output from our trigger. If we drop the trigger we created earlier and create a new one with the following definition:</P><PRE>drop trigger CreateTableTrigger on database
go

create trigger CreateTableTrigger on database for create_table as 
select eventdata().value('( /EVENT_INSTANCE/ObjectName )[1]', 'nvarchar(max)')
</PRE>
<P>Now, if we create a new table (say <FONT face="Courier New">Test2</FONT>), we get the following output:</P><PRE>Test2
</PRE>
<P>Which is exactly what we expect if we run the <FONT face="Courier New">value()</FONT> method above over the XML returned from the event. 
<H6>-<BR>Disclaimer:<BR>This posting is provided “AS IS” with no warranties, and confers no rights.<BR>Use of included script samples are subject to the terms specified at <A href="https://www.microsoft.com/info/cpyright.htm"><FONT color=#003399>https://www.microsoft.com/info/cpyright.htm</FONT></A>.</H6>]]></content:encoded>
    </item>
    <item>
      <title>Static Typing Consequences of the Parent Axis</title>
      <link>https://docs.microsoft.com/archive/blogs/mrorke/static-typing-consequences-of-the-parent-axis</link>
      <pubDate>Thu, 18 Aug 2005 12:57:00 GMT</pubDate>
      <dc:creator><![CDATA[mrorke]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/mrorke/2005/08/18/static-typing-consequences-of-the-parent-axis/</guid>
      <description><![CDATA[SQL Server 2005 has an XQuery implementation that provides full support for the parent axis, as...]]></description>
      <content:encoded><![CDATA[<P>SQL Server 2005 has an XQuery implementation that provides full support for the parent axis, as defined in the XPath specification. Since our XQuery implementation is statically typed, we also support the static typing of the parent axis, as defined in the <A href="https://www.w3.org/TR/2004/WD-xquery-semantics-20040220/">XQuery Formal Semantics</A> document. The definition of static typing of the parent axis has a number of nuances that may not be entirely obvious without a detailed examination of it's definition. In essence, the main side effect of using this axis is that typing information is lost! This is best illustrated with an example.</P>
<P>Firstly, we create a simple schema with some typed elements that we will later query:</P><PRE>create xml schema collection small_type as N'
&lt;xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="https://www.w3.org/2001/XMLSchema"&gt;
	&lt;xs:element name="small"&gt;
		&lt;xs:complexType&gt;
			&lt;xs:sequence&gt;
				&lt;xs:element maxOccurs="unbounded" name="item"&gt;
					&lt;xs:complexType mixed="true"&gt;
						&lt;xs:sequence&gt;
							&lt;xs:element name="embed-string" type="xs:string" nillable="true"/&gt;
							&lt;xs:element name="embed-int" type="xs:int" /&gt;
						&lt;/xs:sequence&gt;
						&lt;xs:attribute name="index" type="xs:unsignedByte" use="required" /&gt;
					&lt;/xs:complexType&gt;
				&lt;/xs:element&gt;
			&lt;/xs:sequence&gt;
		&lt;/xs:complexType&gt;
	&lt;/xs:element&gt;
&lt;/xs:schema&gt;'
</PRE>
<P>Then we create a table and insert some instance data:</P><PRE>create table small_typed( id int IDENTITY PRIMARY KEY, xml_data xml(small_type), empty int)
go

insert into small_typed( xml_data ) values ('
&lt;small&gt;
	&lt;item index="1"&gt;
		Item 1
		&lt;embed-string&gt;String Item 1&lt;/embed-string&gt;
		&lt;embed-int&gt;1&lt;/embed-int&gt;
	&lt;/item&gt;
&lt;/small&gt;
')
</PRE>
<P>The next step is to set up an XQuery static type SQL profiler trace so we can examine the effects of various path expressions on the static type of the query. Once that is done, we execute the following path expression:</P><PRE>select xml_data.exist('
/small/item/embed-string
') from small_typed
</PRE>
<P>From the SQL profiler trace, we see that the static type of this expression is:</P><PRE>element(embed-string,xs:string) *
</PRE>
<P>Which is exactly what we expected, based on our XSD schema. Lets try another query, this time targeting the index attribute of the <FONT face="Courier New">item</FONT> element:</P><PRE>select xml_data.exist('
/small/item/@index
') from small_typed
</PRE>
<P>In this case, the static type returned is the following:</P><PRE>attribute(index,xs:unsignedByte) *
</PRE>
<P>Again, precisely what we expected based on our XSD schema. Now, throwing the parent axis into the mix, we execute the following query:</P><PRE>select xml_data.exist('
/small/item/embed-string/../@index
') from small_typed
</PRE>
<P>If we take a look at the static type that results from this query, we now get the following:</P><PRE>attribute(index,<FONT color=#ff0000>xdt:anyAtomicType</FONT>) *
</PRE>
<P>Notice that the static type of the expression is now the generic <FONT face="Courier New">xdt:anyAtomicType</FONT> type, instead of <FONT face="Courier New">xs:unsignedByte</FONT> (which is what we would expect based on our XSD schema!). This loss of typing has consequences when the result of these expressions are used for further processing e.g. if they are passed through to functions.</P>
<P>Consider the following query which uses the XQuery <FONT face="Courier New">number()</FONT> function to extract and parse the value of the <FONT face="Courier New">index</FONT> attribute:</P><PRE>select xml_data.query('
number( (/small/item)[1]/@index )
') from small_typed
</PRE>
<P>This query executes fine. We now alter the path expression to use the parent axis as follows:</P><PRE>select xml_data.query('
number( (/small/item/embed-string/..)[1]/@index )
') from small_typed
</PRE>
<P>We now get the following error message:</P><PRE><FONT color=#ff0000>Msg 2364, Level 16, State 1, Line 2
XQuery [small_typed.xml_data.query()]: Cannot implicitly convert from 'xdt:anyAtomicType ?' to 'xs:double'
</FONT></PRE>
<P>Essentially, the use of the parent axis (and it's associated loss of typing) can mean that the resultant static type precludes the use of the expression with many of the XQuery functions and other expressions that are type dependent.&nbsp;As a further example of this, consider the following query where we use the + operator on the value of the <FONT face="Courier New">index</FONT> attribute:</P><PRE>select xml_data.query('
(/small/item)[1]/@index + 1
') from small_typed
</PRE>
<P>This query executes and returns the expected results. Once again, if we alter the path expression to include the parent operator as follows:</P><PRE>select xml_data.query('
(/small/item/embed-string/..)[1]/@index + 1
') from small_typed
</PRE>
<P>The query now returns the following error message:</P><PRE><FONT style="BACKGROUND-COLOR: #ffffff" color=#ff0000>Msg 9308, Level 16, State 1, Line 2
XQuery [small_typed.xml_data.query()]: The argument of '+' must be of a single numeric primitive type or 'https://www.w3.org/2004/07/xpath-datatypes#untypedAtomic'. Found argument of type 'xdt:anyAtomicType ?'.
</FONT></PRE>
<P>The moral of the story - use the parent axis with caution :)</P>
<H6>-<BR>Disclaimer:<BR>This posting is provided “AS IS” with no warranties, and confers no rights.<BR>Use of included script samples are subject to the terms specified at <A href="https://www.microsoft.com/info/cpyright.htm"><FONT color=#003399>https://www.microsoft.com/info/cpyright.htm</FONT></A>.</H6>]]></content:encoded>
    </item>
    <item>
      <title>XML Query Test Suite - version 0.6 released</title>
      <link>https://docs.microsoft.com/archive/blogs/mrorke/xml-query-test-suite-version-0-6-released</link>
      <pubDate>Thu, 11 Aug 2005 15:14:00 GMT</pubDate>
      <dc:creator><![CDATA[mrorke]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/mrorke/2005/08/11/xml-query-test-suite-version-0-6-released/</guid>
      <description><![CDATA[The W3C XQuery Testing Task Force (of which I am a member) has released version 0.6 of the XML Query...]]></description>
      <content:encoded><![CDATA[The W3C XQuery Testing Task Force (of which I am a member) has released version 0.6 of the XML Query Test Suite. This is currently available at <A href="https://www.w3.org/XML/Query/test-suite/">https://www.w3.org/XML/Query/test-suite/</A>. The test suite consists of XQuery expressions, results and source files that test various different aspects of an XQuery implementation against the latest published drafts of the various XQuery specifications.]]></content:encoded>
    </item>
    <item>
      <title>Querying Over Constructed XML Using Sub-queries</title>
      <link>https://docs.microsoft.com/archive/blogs/mrorke/querying-over-constructed-xml-using-sub-queries</link>
      <pubDate>Tue, 02 Aug 2005 14:38:00 GMT</pubDate>
      <dc:creator><![CDATA[mrorke]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/mrorke/2005/08/02/querying-over-constructed-xml-using-sub-queries/</guid>
      <description><![CDATA[There are a number of cases where it would be useful to be able to run XQuery statements over the...]]></description>
      <content:encoded><![CDATA[<P>There are a number of cases where it would be useful to be able to run XQuery statements over the result of an XQuery expression which constructs new values. Unfortunately, directly querying over constructed XML is not supported in SQL Server 2005, so we need to use a work-around. Since the result of a <FONT face="Courier New">query()</FONT> method invocation is a new instance of the XML data-type, we can simply assign the results of a query to a variable, then perform further querying over that variable. While this will be acceptable for most cases, it is also possible to do this in a more direct manner, using sub-queries.</P>
<P>To illustrate this, I will use an example from our customer message boards. This particular case involved extracting the individual values from a list-typed simple value, using the <FONT face="Courier New">nodes()</FONT> method to create a separate relational row for each entry in the list. To start off with, I will create a simple schema which defines a the value of the <FONT face="Courier New">foo</FONT> element to be a string based list type:</P><PRE>create xml schema collection listExample as '
&lt;xs:schema xmlns:xs="https://www.w3.org/2001/XMLSchema"&gt;
&lt;xs:element name="foo"&gt;
	&lt;xs:simpleType&gt;
		&lt;xs:list itemType="xs:string" /&gt;
	&lt;/xs:simpleType&gt;
&lt;/xs:element&gt;
&lt;/xs:schema&gt;'
</PRE>
<P>We now create an instance of the xml data-type using this schema and some values:</P><PRE>declare @xml_data xml(listExample)
set @xml_data='&lt;foo&gt;Entry1 Entry2 Entry3&lt;/foo&gt;'
</PRE>
<P>The XQuery <FONT face="Courier New">data()</FONT> function will extract each individual entry from the list type. Thus, if we run the following query, we get the 3 'entry' items returned:</P><PRE>select @xml_data.query( 'data(/foo)' )
</PRE>
<P>At this point, we would simply execute the nodes method over this XQuery expression to extract each of the individual values into a separate relational row. For example, using the following query:</P><PRE>select ref.value('.', 'nvarchar(100)')
from @xml_data.nodes('data(/foo)') T(ref)
</PRE>
<P>Unfortunately, if you try to execute this query, you get the following error message returned:</P><PRE><FONT color=#ff0000>Msg 2374, Level 16, State 1, Line 8
XQuery [nodes()]: A node or set of nodes is required for 'nodes()'</FONT>
</PRE>
<P>Since the <FONT face="Courier New">data()</FONT> function causes the creation of new items which are not stored in the base XML data-type instance, we are unable to execute the <FONT face="Courier New">nodes()</FONT> method over the result of this expression! In order to run a <FONT face="Courier New">nodes()</FONT> method over this, we have to construct a new XML data-type instance in a sub-query and run nodes over the result of that. This can be done as follows:</P><PRE>select T.ref.value('.', 'nvarchar(100)')
from 
<FONT color=#008000>(
      select [Xml]=@xml_data.query('
			for $i in data(/foo) return 
			element temp { $i }
		')
) A</FONT>
cross apply A.Xml.nodes('/temp') T(ref)
</PRE>
<P>The sub-query (shown in <FONT color=#008000>green</FONT>) extracts the items out of the list-typed element node <FONT face="Courier New">foo</FONT>, returning each individual item as the text node of a newly constructed element named <FONT face="Courier New">temp</FONT>. Since the result of the query expression is a new XML data-type instance, we can now run <FONT face="Courier New">nodes()</FONT> over this sub-query to get the desired results.</P>
<H6>-<BR>Disclaimer:<BR>This posting is provided “AS IS” with no waranties, and confers no rights.<BR>Use of included script samples are subject to the terms specified at <A href="https://www.microsoft.com/info/cpyright.htm"><FONT color=#003399>https://www.microsoft.com/info/cpyright.htm</FONT></A>.</H6>]]></content:encoded>
    </item>
    <item>
      <title>Working with XML from Multiple Instances</title>
      <link>https://docs.microsoft.com/archive/blogs/mrorke/working-with-xml-from-multiple-instances</link>
      <pubDate>Thu, 21 Jul 2005 17:37:00 GMT</pubDate>
      <dc:creator><![CDATA[mrorke]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/mrorke/2005/07/21/working-with-xml-from-multiple-instances/</guid>
      <description><![CDATA[There are often cases where we need to perform operations based on multiple XML instances. To...]]></description>
      <content:encoded><![CDATA[<P>There are often cases where we need to perform operations based on multiple XML instances. To illustrate this, consider the example XML given below. Basically, we have two XML instances. The first instance (call this the <EM>results instance</EM>) contains information about the execution of a set of tests. Each test entry contains a name for the test, the result of the execution and an ID to the section of the specification that the test targets. The second instance (call this the <EM>sections instance</EM>) contains detailed information about the various sections of the specification, along with an identifying ID for each section. </P>
<P><STRONG>Results Instance</STRONG></P><PRE>&lt;results&gt;
	&lt;item name="First Item" section-id="Section1" result="PASS" /&gt;
	&lt;item name="Second Item" section-id="Section1" result="PASS" /&gt;
	&lt;item name="Third Item" section-id="Section2" result="PASS" /&gt;
	&lt;item name="Fourth Item" section-id="Section3" result="FAIL" /&gt;
	&lt;item name="Fifth Item" section-id="Section3" result="PASS" /&gt;
	&lt;item name="Sixth Item" section-id="Section3" result="FAIL" /&gt;
&lt;/results&gt;
</PRE>
<P><STRONG>Sections Instance</STRONG></P><PRE>&lt;sections&gt;
	&lt;section name="First Section" id="Section1" /&gt;
	&lt;section name="Second Section" id="Section2" /&gt;
	&lt;section name="Third Section" id="Section3" /&gt;
&lt;/sections&gt;</PRE>
<P>The report we would like to produce over this data shows the results of each tests, along with a detailed description of the section of the specification that the test targets. For example, the final data we want may look like the following:</P><PRE>&lt;result name="First Item" section="First Section"&gt;PASS&lt;/result&gt;
&lt;result name="Second Item" section="First Section"&gt;PASS&lt;/result&gt;
&lt;result name="Third Item" section="Second Section"&gt;PASS&lt;/result&gt;
&lt;result name="Fourth Item" section="Third Section"&gt;FAIL&lt;/result&gt;
&lt;result name="Fifth Item" section="Third Section"&gt;PASS&lt;/result&gt;
&lt;result name="Sixth Item" section="Third Section"&gt;FAIL&lt;/result&gt;</PRE>
<P>In order to do this, we essentially need to perform a join across the two instances. Using standard XQuery and the document function, we could write a FLWOR expression to do this, along the lines of the following: 
<P><PRE>let $sections := document("sections.xml")/sections
for $result in document("results.xml")/results/item
return
&lt;result 
	name="{$result/@name}" 
	section="{$sections/section[id=$result/@id]/@name}"&gt;
{ $result/text() }
&lt;/result&gt;
</PRE>
<P>Unfortunately, XQuery in SQL Server 2005 will not execute this query. Firstly, we do not support the <FONT face="Courier New">let</FONT> syntax. Secondly, there is no <FONT face="Courier New">document()</FONT> (or equivalent) function. So, we need to re-write this query to use T-SQL to get around the limitations of our XQuery implementation. In order to perform the join operation, we need to extract the relevant fields out of the XML instances and turn them into relational data, so we can use them in the standard T-SQL context - the recommended method for doing this is a combination of the the <FONT face="Courier New">value()</FONT> method for converting the XML into a relational type, and the <FONT face="Courier New">nodes()</FONT> method for extracting the multiple values from the single XML instance. 
<P>We use <FONT face="Courier New">nodes()</FONT> to&nbsp;extract the multiple <FONT face="Courier New">item</FONT> and&nbsp;<FONT face="Courier New">section</FONT> elements from the pair of XML instances.&nbsp;Once these are extracted, we can use the <FONT face="Courier New">value()</FONT> method on each individual entry to convert it to a relational value, using these to perform the join. The query to do this is as follows:</P><PRE>select R.i.value('@name', 'varchar(30)')   [Name], 
       S.s.value('@name', 'varchar(30)')   [Section],
       R.i.value('@result', 'varchar(30)') [Result]
from Results  cross apply xml_data.nodes('/results/item') R(i),
     Sections cross apply xml_data.nodes('/sections/section') S(s)
where R.i.value('@section-id', 'varchar(30)') = S.s.value('@id', 'varchar(30)')
</PRE>
<P>The join operation in this case is being done through the <FONT face="Courier New">where</FONT> clause of the select statement. Running this query will produce the following relational result set:</P><PRE>First Item	First Section	PASS
Second Item	First Section	PASS
Third Item	Second Section	PASS
Fourth Item	Third Section	FAIL
Fifth Item	Third Section	PASS
Sixth Item	Third Section	FAIL
</PRE>
<P>If a relational results is what you wanted, then you are done :) The initial goal was to output XML though, so we can add a <FONT face="Courier New">for xml</FONT> statement to this query to take these relational results and re-compose them back into XML. The query including the <FONT face="Courier New">for xml</FONT> statement is as follows:</P><PRE>select R.i.value('@name', 'varchar(30)')   [@name], 
       S.s.value('@name', 'varchar(30)')   [@section],
       R.i.value('@result', 'varchar(30)') [text()]
from Results  cross apply xml_data.nodes('/results/item') R(i),
     Sections cross apply xml_data.nodes('/sections/section') S(s)
where R.i.value('@section-id', 'varchar(30)') = S.s.value('@id', 'varchar(30)')
for xml path('result'), type
</PRE>
<P>This query then produces the expected results from above. The for xml statement itself is pretty self-explanatory. The string (result) given as the path parameter is the name of the container element, while the column names of the various values indicate how they will be stored. Notice that the column names for <FONT face="Courier New">@name</FONT> and <FONT face="Courier New">@section</FONT> correspond to the <FONT face="Courier New">name</FONT> and <FONT face="Courier New">section</FONT> attributes respectively, while the <FONT face="Courier New">text()</FONT> column becomes the text value of the element. 
<P>Thanks again to Jinghao for help with the for xml part of the query. 
<H6>-<BR>Disclaimer:<BR>This posting is provided “AS IS” with no waranties, and confers no rights.<BR>Use of included script samples are subject to the terms specified at <A href="https://www.microsoft.com/info/cpyright.htm"><FONT color=#003399>https://www.microsoft.com/info/cpyright.htm</FONT></A>.</H6>]]></content:encoded>
    </item>
    <item>
      <title>Namespace Nuances</title>
      <link>https://docs.microsoft.com/archive/blogs/mrorke/namespace-nuances</link>
      <pubDate>Mon, 11 Jul 2005 17:38:00 GMT</pubDate>
      <dc:creator><![CDATA[mrorke]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/mrorke/2005/07/11/namespace-nuances/</guid>
      <description><![CDATA[XQuery uses the concept of a namespace, adopted from the XML 1.0 specification. But, due to the...]]></description>
      <content:encoded><![CDATA[<P>XQuery uses the concept of a namespace, adopted from the XML 1.0 specification. But, due to the complex nature of the XQuery language and it's dual roles as both query and serialization/XML construction language, there are several nuances to the use of namespaces that may not be immediately obvious.</P>
<P>The first issue I will deal with is the concept of a default namespace. In XML 1.0, if you used an <FONT face="Courier New">xmlns</FONT> attribute without an associated name, all elements under that scope were considered to be in the namespace referenced by the associated URI. Notice I said all <STRONG>elements</STRONG> - attributes are&nbsp;not affected by default namespaces in XML. This functionality is mirrored in XQuery, either through the use of the <FONT face="Courier New">declare default element namespace</FONT> prolog entry, or by directly constructing the xmlns attribute on your constructed XML. Again, in XQuery the default element namespace does not affect non-element data i.e. attributes, function names&nbsp;and variables (all of which may have associated namespace prefixes) must be explicitly namespaced if required (<EM>NOTE: SQL Server 2005 XQuery does not currently allow variables to be placed into a namespace, even though this is allowed in the XQuery specification</EM>). Function names in XQuery have their own default namespace entry, accessible through the <FONT face="Courier New">declare default function namespace</FONT> prolog option.</P>
<P>In XQuery&nbsp;a previously declared namespace prefix can be used to add a namespace to elements, attributes, function calls and variables. Unlike the default options, the same namespace prefix can be used to apply to all 4 different identifier types.</P>
<P>Lastly, when doing XML construction, the order that a namespace is declared in does not affect the scope, since attribute order in XML is considered non normative. Take the following XQuery expression as an example:</P><PRE>&lt;foo:element foo:index="1" xmlns:foo="https://example.com/foo" /&gt;</PRE>
<P>In this simple case, we have constructed an element in the <FONT face="Courier New">foo</FONT> namespace, containing an attribute which is also in the <FONT face="Courier New">foo</FONT> namespace. Notice that we were able to use the <FONT face="Courier New">foo</FONT> namespace prefix even before it was technically defined (by the <FONT face="Courier New">xmlns</FONT> attribute). In this case, the result of the query was pretty obvious. Now, consider the following XQuery:</P><PRE>declare namespace foo="https://example.com/foo1";
&lt;foo:element xmlns:foo="https://example.com/foo2" /&gt;</PRE>
<P>In this case, we initially declare that the namespace prefix <FONT face="Courier New">foo</FONT> points to the URI <FONT face="Courier New">https://example.com/foo1</FONT>. But, when we construct the new element, the namespace prefix <FONT face="Courier New">foo</FONT> is redefined to point to the URI <FONT face="Courier New">https://example.com/foo2</FONT>, which is the URI used for the constructed XML element. Again, these results are pretty obvious, but the trick comes when we combine XML construction with XQuery expressions to generate dynamic content. Consider the following query:</P><PRE>declare namespace foo="https://example.com/foo1";
&lt;foo:element index="{/foo:index}" xmlns:foo="https://example.com/foo2" /&gt;</PRE>
<P>Initially, the namespace prefix <FONT face="Courier New">foo</FONT> is declared to point to the URI <FONT face="Courier New">https://example.com/foo1</FONT>. The element constructor in the query contains an attribute constructor for the attribute <FONT face="Courier New">index</FONT> which uses an XQuery expression to dynamically calculate the value for this attribute. Inside this dynamic attribute content expression, the namespace <FONT face="Courier New">foo</FONT> is referenced. Even though the redefinition of the foo namespace prefix technically occurs <STRONG>after</STRONG> the XQuery expression used to generate the contents of the <FONT face="Courier New">index</FONT> attribute, since the scope of the redefinition applies to the entire element constructor, within the dynamic attribute expression, the namespace prefix <FONT face="Courier New">foo</FONT> is defined to point to the URI <FONT face="Courier New">https://example.com/foo2</FONT>!</P>
<P>The easiest thing is to avoid such inconsistencies by placing any namespace prefix definitions as the first attributes in an element constructor. Thus, the order of assignment of URI's to namespace prefixes will be more immediately apparent. </P>
<H6>-<BR>Disclaimer:<BR>This posting is provided “AS IS” with no waranties, and confers no rights.<BR>Use of included script samples are subject to the terms specified at <A href="https://www.microsoft.com/info/cpyright.htm"><FONT color=#003399>https://www.microsoft.com/info/cpyright.htm</FONT></A>.</H6>]]></content:encoded>
    </item>
  </channel>
</rss>