Ingenious. However I don't think it will work if there is more than one record in TestXML. I tried these experiments: -
Step 1. I wrote: Select title as "@title", [image] as "@image" from dbo.timelinehistorydata("robertb")
As I expected this correctly returned the following from my test database. After all, my virtual table functions like your actual table TestXML: -
<data>
<event title="Essex Voyage" />
<event title="Error" />
<event title="Battle of Grand Port" image="http://en.wikipedia.org/wiki/File:Grand_Port_mg6971.jpg" />
<event title="Great Depression" />
<event title="Treaty of Waitangi" />
<event title="SS Tainui" />
<event title="World War 2" />
<event title="Baltic Action" />
<event title="Error" />
<event title="First World War" />
<event title="Gertrude Voyage" />
<event title="Franklin's Lost Expedition" />
<event title="Search Expedition of 1852-3" />
</data>
I then added the subquery (SELECT [description] FROM testxml), making the whole query
Select title as "@title", [image] as "@image", (SELECT [description] FROM dbo.TimeLineHistoryData('robertb')) from dbo.TimeLineHistoryData('robertb') FOR XML PATH('event'), ROOT('data')
Now the query throws an error message: -
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
In fact, there is actually only one record with the virtual table dbo.TimeLineHistoryData('robertb') with a value for Description. However in a more general case there could be several.
If I simply write
Select title as "@title", [image] as "@image", [description] from dbo.TimeLineHistoryData('robertb') FOR XML PATH('event'), ROOT('data')
then I get this result for the record that contains a value for [description]: -
<event title="SS Tainui">
<description>J A Pym arrives in New Zealand 31 Aug 1923 on this ship</description>
</event>
This is not accepted by the Simile timeline, which will not accept the "elements" form of XML.
Going back to your query but with dbo.TimelineHistoryData(), I added an identity field called "num" to the table returned by the function so that I had something for a unique lookup, and wrote
Select title as "@title", [image] as "@Image", (Select [description] from dbo.TimeLineHistoryData('robertb') as T2 where t2.num = t1.num)
from dbo.TimeLineHistoryData('robertb') as T1 FOR XML auto, ROOT('data')
Now I was blocked by a message: -
Unnamed tables cannot be used as XML identifiers as well as unnamed columns cannot be used for attribute names. Name unnamed columns/tables using AS in the SELECT statement.
I wondered about changing the function to return the XML directly, but I'd already failed with this approach. I'd written my first version of TimelineData to return a string, being the XML that I wanted. The problem is that it returns the whole table as
XML, so it doen't take much to exceed the 2033 character limit. The only thing that works (that I've found so far) is to use an XML reader handling one row at a time within a loop like this: -
Dim OutputXML As New StringBuilder
OutputXML.Append("<data>")
xmlr = GDBCommand.ExecuteXmlReader()
xmlr.Read()
Do While xmlr.ReadState <> System.Xml.ReadState.EndOfFile
OutputXML.Append(xmlr.ReadOuterXml())
Loop
OutputXML.Append("</data>")
So at the moment the only solution that I can think of is to change my web handler to read SQL normally (not as XML), and manually create the XML I want within my read loop.
Robert Barne...
Member
451 Points
708 Posts
Re: What is the property name for the text of an XML node
Oct 12, 2011 03:55 AM|LINK
Ingenious. However I don't think it will work if there is more than one record in TestXML. I tried these experiments: -
Step 1. I wrote: Select title as "@title", [image] as "@image" from dbo.timelinehistorydata("robertb")
As I expected this correctly returned the following from my test database. After all, my virtual table functions like your actual table TestXML: -
<data>
<event title="Essex Voyage" />
<event title="Error" />
<event title="Battle of Grand Port" image="http://en.wikipedia.org/wiki/File:Grand_Port_mg6971.jpg" />
<event title="Great Depression" />
<event title="Treaty of Waitangi" />
<event title="SS Tainui" />
<event title="World War 2" />
<event title="Baltic Action" />
<event title="Error" />
<event title="First World War" />
<event title="Gertrude Voyage" />
<event title="Franklin's Lost Expedition" />
<event title="Search Expedition of 1852-3" />
</data>
I then added the subquery (SELECT [description] FROM testxml), making the whole query
Select title as "@title", [image] as "@image", (SELECT [description] FROM dbo.TimeLineHistoryData('robertb')) from dbo.TimeLineHistoryData('robertb') FOR XML PATH('event'), ROOT('data')
Now the query throws an error message: -
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
In fact, there is actually only one record with the virtual table dbo.TimeLineHistoryData('robertb') with a value for Description. However in a more general case there could be several.
If I simply write
Select title as "@title", [image] as "@image", [description] from dbo.TimeLineHistoryData('robertb') FOR XML PATH('event'), ROOT('data')
then I get this result for the record that contains a value for [description]: -
<event title="SS Tainui">
<description>J A Pym arrives in New Zealand 31 Aug 1923 on this ship</description>
</event>
This is not accepted by the Simile timeline, which will not accept the "elements" form of XML.
Going back to your query but with dbo.TimelineHistoryData(), I added an identity field called "num" to the table returned by the function so that I had something for a unique lookup, and wrote
Select title as "@title", [image] as "@Image", (Select [description] from dbo.TimeLineHistoryData('robertb') as T2 where t2.num = t1.num)
from dbo.TimeLineHistoryData('robertb') as T1 FOR XML auto, ROOT('data')
Now I was blocked by a message: -
Unnamed tables cannot be used as XML identifiers as well as unnamed columns cannot be used for attribute names. Name unnamed columns/tables using AS in the SELECT statement.
I wondered about changing the function to return the XML directly, but I'd already failed with this approach. I'd written my first version of TimelineData to return a string, being the XML that I wanted. The problem is that it returns the whole table as XML, so it doen't take much to exceed the 2033 character limit. The only thing that works (that I've found so far) is to use an XML reader handling one row at a time within a loop like this: -
Dim OutputXML As New StringBuilder
OutputXML.Append("<data>")
xmlr = GDBCommand.ExecuteXmlReader()
xmlr.Read()
Do While xmlr.ReadState <> System.Xml.ReadState.EndOfFile
OutputXML.Append(xmlr.ReadOuterXml())
Loop
OutputXML.Append("</data>")
So at the moment the only solution that I can think of is to change my web handler to read SQL normally (not as XML), and manually create the XML I want within my read loop.
Surely there's a better way!