Dav*_*ker 27 html xml t-sql sql-server html-table
我正在使用SQL Server 2008 R2中的FOR XML语句创建HL7 Continuity of Care Document(CCD).
我用这种方法做了很多,但这是我第一次在HTML表格中表示部分数据,这给我带来了麻烦.
所以,我在表格中有以下信息:
Problem | Onset | Status
---------------------------------
Ulcer | 01/01/2008 | Active
Edema | 02/02/2005 | Active
Run Code Online (Sandbox Code Playgroud)
我试图渲染以下内容
<tr>
<th>Problem</th>
<th>Onset</th>
<th>Status</th>
</tr>
<tr>
<td>Ulcer</td>
<td>01/01/2008</td>
<td>Active</td>
</tr>
<tr>
<td>Edema</td>
<td>02/02/2005</td>
<td>Active</td>
</tr>
Run Code Online (Sandbox Code Playgroud)
我正在使用此查询:
SELECT p.ProblemType AS "td"
, p.Onset AS "td"
, p.DiagnosisStatus AS "td"
FROM tblProblemList p
WHERE p.PatientUnitNumber = @PatientUnitNumber
FOR XML PATH('tr')
Run Code Online (Sandbox Code Playgroud)
我一直得到以下内容:
<tr>
<td>Ulcer2008-01-01Active</td>
</tr>
<tr>
<td>Edema2005-02-02Active</td>
</tr>
Run Code Online (Sandbox Code Playgroud)
有人有任何建议吗?
Mik*_*son 33
select
(select p.ProblemType as 'td' for xml path(''), type),
(select p.Onset as 'td' for xml path(''), type),
(select p.DiagnosisStatus as 'td' for xml path(''), type)
from tblProblemList p
where p.PatientUnitNumber = @PatientUnitNumber
for xml path('tr')
Run Code Online (Sandbox Code Playgroud)
要添加标题,您也可以使用union all
.
select
(select 'Problem' as th for xml path(''), type),
(select 'Onset' as th for xml path(''), type),
(select 'Status' as th for xml path(''), type)
union all
select
(select p.ProblemType as 'td' for xml path(''), type),
(select p.Onset as 'td' for xml path(''), type),
(select p.DiagnosisStatus as 'td' for xml path(''), type)
from tblProblemList p
where p.PatientUnitNumber = @PatientUnitNumber
for xml path('tr')
Run Code Online (Sandbox Code Playgroud)
Chr*_*ter 25
Mikael的答案有效,但这样做:
而不是使用FOR XML PATH('tr'),使用FOR XML RAW('tr'),ELEMENTS.这将阻止值连接并为您提供非常干净的输出.您的查询将如下所示:
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
Run Code Online (Sandbox Code Playgroud)
我更喜欢使用纯标记附加标题行,这样我就可以更好地控制正在发生的事情.完整的代码块看起来像这样:
DECLARE @body NVARCHAR(MAX)
SET @body = N'<table>'
+ N'<tr><th>Problem</th><th>Onset</th><th>Status</th></tr>'
+ 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'</table>'
Run Code Online (Sandbox Code Playgroud)
我想根据格式化输出表的需要添加一些额外的值.
"AS td"别名将<td>value</td>
在标记中生成元素,但不是因为它理解表格单元格是td.这种断开连接允许我们创建伪造的HTML元素,这些元素可以在执行查询后更新.例如,如果我想将ProblemType值设置为居中对齐,我可以调整元素名称以允许这样做.我无法在元素名称中添加样式或类,因为它在SQL中打破了别名命名约定,但我可以创建一个新的元素名称,例如tdc.这将产生<tdc>value</tdc>
元素.虽然这不是任何有效的标记,但是替换语句很容易处理.
DECLARE @body NVARCHAR(MAX)
SET @body = N'<table>'
+ N'<tr><th>Problem</th><th>Onset</th><th>Status</th></tr>'
+ 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'</table>'
SET @body = REPLACE(@body, '<tdc>', '<td class="center">')
SET @body = REPLACE(@body, '</tdc>', '</td>')
Run Code Online (Sandbox Code Playgroud)
这将创建具有格式的单元格元素<td class="center">value</td>
.字符串顶部的快速块,您将通过简单的调整获得中心对齐的值.
我需要解决的另一个问题是在标记中包含链接.只要单元格中的值是href中需要的值,这很容易解决.我将展开示例以包含我想要链接到详细URL的ID字段.
DECLARE @body NVARCHAR(MAX)
SET @body = N'<table>'
+ N'<tr><th>Problem</th><th>Onset</th><th>Status</th></tr>'
+ 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'</table>'
SET @body = REPLACE(@body, '<tda>', '<td><a href="http://mylinkgoeshere.com/id/')
SET @body = REPLACE(@body, '</tda>', '">click-me</a></td>')
Run Code Online (Sandbox Code Playgroud)
此示例不考虑使用链接文本内部单元格中的值,但这是一些CHARINDEX工作的可解决问题.
我对该系统的最终实现是基于SQL查询发送HTML电子邮件.我一再需要单元格对齐和常见的链接类型,因此我将替换函数移动到SQL中的共享标量函数中,因此我不必在发送电子邮件的所有存储过程中都使用它们.
我希望这会增加一些价值.
Shn*_*ugo 18
FUNCTION
on XML
-base 的通用解决方案它会将任何SELECT
转换为XHTML表.
它与2008R2 +一起工作(测试),但我很确定这可以在2008年使用,甚至可能在2005年.如果有人想验证这一点,请发表评论.谢谢
以下函数替换了我之前提供的所有各种函数(如果需要,请参阅上一版本)
CREATE FUNCTION dbo.CreateHTMLTable
(
@SelectForXmlPathRowElementsXsinil XML
,@tblClass VARCHAR(100) --NULL to omit this class
,@thClass VARCHAR(100) --same
,@tbClass VARCHAR(100) --same
)
RETURNS XML
AS
BEGIN
RETURN
(
SELECT @tblClass AS [@class]
,@thClass AS [thead/@class]
,@SelectForXmlPathRowElementsXsinil.query(
N'let $first:=/row[1]
return
<tr>
{
for $th in $first/*
return <th>{if(not(empty($th/@caption))) then xs:string($th/@caption) else local-name($th)}</th>
}
</tr>') AS thead
,@tbClass AS [tbody/@class]
,@SelectForXmlPathRowElementsXsinil.query(
N'for $tr in /row
return
<tr>{$tr/@class}
{
for $td in $tr/*
return
if(empty($td/@link))
then <td>{$td/@class}{string($td)}</td>
else <td>{$td/@class}<a href="{$td/@link}">{string($td)}</a></td>
}
</tr>') AS tbody
FOR XML PATH('table'),TYPE
)
END
GO
Run Code Online (Sandbox Code Playgroud)
带有一些值的模拟表
DECLARE @tbl TABLE(ID INT, [Message] VARCHAR(100));
INSERT INTO @tbl VALUES
(1,'Value 1')
,(2,'Value 2');
Run Code Online (Sandbox Code Playgroud)
- 电话必须包含SELECT ... FOR XML
在paranthesis!
- 点击运行代码段查看结果!
SELECT dbo.CreateHTMLTable
(
(SELECT * FROM @tbl FOR XML PATH('row'),ELEMENTS XSINIL)
,NULL,NULL,NULL
);
Run Code Online (Sandbox Code Playgroud)
<table>
<thead>
<tr>
<th>ID</th>
<th>Message</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Value 1</td>
</tr>
<tr>
<td>2</td>
<td>Value 2</td>
</tr>
</tbody>
</table>
Run Code Online (Sandbox Code Playgroud)
如果您的表包含名称中有空白的列,或者您想手动设置列的标题(多语言支持!),或者您想要用外写标题替换CamelCaseName,则可以将其作为属性:
DECLARE @tbl2 TABLE(ID INT, [With Blank] VARCHAR(100));
INSERT INTO @tbl2 VALUES
(1,'Value 1')
,(2,'Value 2');
SELECT dbo.CreateHTMLTable
(
(
SELECT ID
,'The new name' AS [SomeOtherName/@caption] --set a caption
,[With Blank] AS [SomeOtherName]
FROM @tbl2 FOR XML PATH('row'),ELEMENTS XSINIL
)
,NULL,NULL,NULL
);
Run Code Online (Sandbox Code Playgroud)
<table>
<thead>
<tr>
<th>ID</th>
<th>The new name</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Value 1</td>
</tr>
<tr>
<td>2</td>
<td>Value 2</td>
</tr>
</tbody>
</table>
Run Code Online (Sandbox Code Playgroud)
您可以使用属性来传递链接或基于行,甚至是基于值的类,以标记CSS样式的列甚至单元格.
--a mock-up table with a row based condition and hyper-links
DECLARE @tbl3 TABLE(ID INT, [With blank] VARCHAR(100),Link VARCHAR(MAX),ShouldNotBeNull INT);
INSERT INTO @tbl3 VALUES
(1,'NoWarning',NULL,1)
,(2,'No Warning too','http://www.Link2.com',2)
,(3,'Warning','http://www.Link3.com',3)
,(4,NULL,NULL,NULL)
,(5,'Warning',NULL,5)
,(6,'One more warning','http://www.Link6.com',6);
--The query adds an attribute Link to an element (NULL if not defined)
SELECT dbo.CreateHTMLTable
(
(
SELECT
CASE WHEN LEFT([With blank],2) != 'No' THEN 'warning' ELSE NULL END AS [@class] --The first @class is the <tr>-class
,ID
,'center' AS [Dummy/@class] --a class within TestText (appeary always)
,Link AS [Dummy/@link] --a mark to pop up as link
,'New caption' AS [Dummy/@caption] --a different caption
,[With blank] AS [Dummy] --blanks in the column's name must be tricked away...
,CASE WHEN ShouldNotBeNull IS NULL THEN 'MarkRed' END AS [ShouldNotBeNull/@class] --a class within ShouldNotBeNull (appears only if needed)
,'Should not be null' AS [ShouldNotBeNull/@caption] --a caption for a CamelCase-ColumnName
,ShouldNotBeNull
FROM @tbl3 FOR XML PATH('row'),ELEMENTS XSINIL),'testTbl','testTh','testTb'
);
Run Code Online (Sandbox Code Playgroud)
<style type="text/css" media="screen,print">
.center
{
text-align: center;
}
.warning
{
color: red;
}
.MarkRed
{
background-color: red;
}
table,th
{
border: 1px solid black;
}
</style>
<table class="testTbl">
<thead class="testTh">
<tr>
<th>ID</th>
<th>New caption</th>
<th>Should not be null</th>
</tr>
</thead>
<tbody class="testTb">
<tr>
<td>1</td>
<td class="center">NoWarning</td>
<td>1</td>
</tr>
<tr>
<td>2</td>
<td class="center">
<a href="http://www.Link2.com">No Warning too</a>
</td>
<td>2</td>
</tr>
<tr class="warning">
<td>3</td>
<td class="center">
<a href="http://www.Link3.com">Warning</a>
</td>
<td>3</td>
</tr>
<tr>
<td>4</td>
<td class="center" />
<td class="MarkRed" />
</tr>
<tr class="warning">
<td>5</td>
<td class="center">Warning</td>
<td>5</td>
</tr>
<tr class="warning">
<td>6</td>
<td class="center">
<a href="http://www.Link6.com">One more warning</a>
</td>
<td>6</td>
</tr>
</tbody>
</table>
Run Code Online (Sandbox Code Playgroud)
作为一种可能的增强,可以传递一个单行 - 页脚,其中聚合值作为附加参数并将其附加为<tfoot>