I wanted to add my "own answer" really just for completeness to possibly help others.. however it is most definitely based on the great help from @Mikael above!! so again, this is really for completeness only - all kudos to @Mikael.
Basically I ended up with the following proc. I needed to select some data/filter, and get some joined data too and allow some boolean filtering on some of the input params. Then drop into the next section which was create a temp table of my relational data and the required xml nodes via the cross apply. The final step was to then pivot the results/dynamically create the columns from the selected XML node..
CREATE PROCEDURE [dbo].[usp_RPT_ExtractFlattenentries]
@CompanyID int,
@MainSelector nvarchar(50) = null,
@SecondarySelector nvarchar(255) = null,
@DateFrom datetime = '01-jan-2012',
@DateTo datetime = '31-dec-2100',
@SysReference nvarchar(20) = null
AS
BEGIN
SET NOCOUNT ON;
-- Create the table var to hold the XML form data from the entries
declare @FeedbackXml table (
ID int identity primary key,
XMLCol xml,
CompanyName nvarchar(20),
SysReference nvarchar(20),
RecordDate datetime,
EntryName nvarchar(255),
MainSelector nvarchar(50)
)
-- STEP 1: Get the raw submission data based on the params passed in
-- *Note: The double casting is necessary as the "form" field is nvarchar (not varchar) and we need xml in UTF-8 format
begin
insert into @FeedbackXml
(XMLCol, CompanyName, SysReference, RecordDate, EntryName, MainSelector)
select cast(cast(e.form as nvarchar(max)) as xml), c.name, e.SysReference, e.RecordDate, e.name, e.wizard
from
entries s
left join
companies o on e.companies = c.ID
where
(@CompanyID = -1 or @CompanyID = e.companies)
and
(@MainSelector is null or @MainSelector = e.wizard)
and
(@SecondarySelector is null or @SecondarySelector = e.name)
and
(@SysReference is null or @SysReference = e.SysReference)
and
(e.RecordDate >= @DateFrom and e.RecordDate <= @DateTo)
end
-- STEP 2: Flatten the required XML structure to provide a base for the pivot, and include other fields we wish to output
select dense_rank() over(order by ID) as ID,
T.RecordDate, T.CompanyName, T.SysReference, T.EntryName, T.MainSelector,
F.N.value('(FieldNameNode/text())[1]', 'nvarchar(max)') as FieldName,
F.N.value('(FieldNameValue/text())[1]', 'nvarchar(max)') as FieldValue
into #TempData
from @FeedbackXml as T
cross apply T.XMLCol.nodes('/root/companies/') as I(N) -- Xpath to the desired node start point
cross apply I.N.nodes('company') as F(N) -- The actual node collection that forms the "field name" and "field value" data
-- STEP 3: Pivot the #TempData table creating a dynamic column structure based on the selected XML nodes in step 2
declare @SQL nvarchar(max)
declare @Col nvarchar(max)
select @Col =
(
select distinct ','+quotename(FieldName)
from #TempData
for xml path(''), type
).value('substring(text()[1], 2)', 'nvarchar(max)')
set @SQL = 'select CompanyName, SysReference, EntryName, MainSelector, RecordDate, '+@Col+'
from #TempData
pivot (max(FieldValue) for FieldName in ('+@Col+')) as P'
exec (@SQL)
drop table #TempData
END
Again, really only added this answer to provide a complete picture from my perspective, and may help others.