I\'m creating a HL7 Continuity of Care Document (CCD) using FOR XML statements in SQL Server 2008 R2.
I\'ve done A LOT with this method, but this is the first time I
Mikael's answer works but so will this:
Rather than using FOR XML PATH('tr'), use FOR XML RAW('tr'), ELEMENTS. This will prevent the values from being concatenated and give you very clean output. Your query would look like this:
SELECT p.ProblemType AS td,
p.Onset AS td,
p.DiagnosisStatus AS td
FROM tblProblemList p
WHERE p.PatientUnitNumber = @PatientUnitNumber
FOR XML RAW('tr'), ELEMENTS
I prefer to append the header row using pure markup so I can have a little better control over what is happening. The full code block would look something like this:
DECLARE @body NVARCHAR(MAX)
SET @body = N''
+ N'Problem Onset Status '
+ CAST((
SELECT p.ProblemType AS td,
p.Onset AS td,
p.DiagnosisStatus AS td
FROM tblProblemList p
WHERE p.PatientUnitNumber = @PatientUnitNumber
FOR XML RAW('tr'), ELEMENTS
) AS NVARCHAR(MAX))
+ N'
'
I wanted to add some extra value that I came up based on the need to format the output table.
The "AS td" alias will produce
elements in the markup but not because it understands that a table cell is a td. This disconnect allows us to create fake HTML elements that can be later updated after the query has been executed. For instance, if I wanted to the ProblemType value to be center aligned I can tweak the element name to allow for this. I can't add a style or class to the element name because it breaks alias naming conventions in SQL, but I can create a new element name such as tdc. This will produce value
elements. While this is not valid markup in any way, it is easy for a replace statement to handle.
DECLARE @body NVARCHAR(MAX)
SET @body = N''
+ N'Problem Onset Status '
+ CAST((
SELECT p.ProblemType AS tdc,
p.Onset AS td,
p.DiagnosisStatus AS td
FROM tblProblemList p
WHERE p.PatientUnitNumber = @PatientUnitNumber
FOR XML RAW('tr'), ELEMENTS
) AS NVARCHAR(MAX))
+ N'
'
SET @body = REPLACE(@body, '', '')
SET @body = REPLACE(@body, '', ' ')
This will create cell elements with the format
. A quick block at the top of the string and you'll have center aligned values with a simple tweak.value
Another situation I needed to solve was inclusion of links in the markup. As long as the value in the cell is the value you need in the href this is pretty easy to solve. I'll expand the example to include an ID field that I want linked to a detail URL.
DECLARE @body NVARCHAR(MAX)
SET @body = N''
+ N'Problem Onset Status '
+ CAST((
SELECT p.ID as tda
p.ProblemType AS td,
p.Onset AS td,
p.DiagnosisStatus AS td
FROM tblProblemList p
WHERE p.PatientUnitNumber = @PatientUnitNumber
FOR XML RAW('tr'), ELEMENTS
) AS NVARCHAR(MAX))
+ N'
'
SET @body = REPLACE(@body, '', 'click-me ')
This example doesn't account for using the value in the cell inside of the link text but that is a solvable problem with some CHARINDEX work.
My final implementation of this system was for sending HTML emails based on SQL queries. I had a repeated need for cell alignment and common link types so I moved the replace functions into a shared scalar function in SQL so I didn't have to have them in all my stored procedures that sent email.
I hope this adds some value.