1

我有以下用于数据库电子邮件的 T-Sql。

-- create proc TableToHtml @table varchar(max) as
declare @table varchar(max) = '(select 1 a, ''one'' b union all select 2, ''two'') t '
declare @sql varchar(max) = '
    declare @xml xml = (
        select * from ' + @table + ' 
        for xml path(''tr''), root(''table'')
    ); 
    select @xml'
declare @tmp table (x xml)
insert into @tmp exec(@sql) 
declare @x xml = (select x from @tmp)
select @x 

它返回

<table>
  <tr>
    <a>1</a>
    <b>one</b>
  </tr>
  <tr>
    <a>2</a>
    <b>two</b>
  </tr>
</table>

是否可以编写 xquery 让它返回以下 html?

<table>
  <tr>
    <th>a</th>
    <th>b</th>
  </tr>
  <tr>
    <td>1</td>
    <td>one</td>
  </tr>
  <tr>
    <td>2</td>
    <td>two</td>
  </tr>
</table>
4

2 回答 2

2

我想出了一个不那么黑客的东西。唯一的问题是它将创建<td />而不是<td></td>如果值为空。当电子邮件发送到一些旧的 Outlook 客户端时,它会导致一些布局问题。

declare @table varchar(max) = '(select 1 a, ''one'' b union all select 2, ''two'') t '
declare @sql varchar(max) = '
    declare @xml xml = (
        select * from ' + @table + ' 
        for xml path(''tr''), root(''table'')
    ); 
    select @xml'
declare @tmp table (x xml)
insert into @tmp exec(@sql) 
declare @x xml = (select x from @tmp)
select @x.query('<body>
<table>
  <tr>
    {for $c in /table/tr[1]/* return element th { local-name($c) } }
  </tr>
  {
    for $r in /table/* 
    return element tr { for $c in $r/* return element td { data($c) } } 
  }
</table>
</body>')
于 2013-03-15T17:35:16.790 回答
0

重大黑客警报!

可能有一种更优雅的方法可以做到这一点,但这里是快速破解:

declare @xml xml = (
    select * from (
        select 'a' + '</th><th>' + 'b' as th, null as td
        union all
        select null, '1' + '</td><td>' + 'one'    
        union all
        select null, '2' + '</td><td>' + 'two'    
    ) t
    for xml path('tr'), root('table')
); 
select cast(replace(replace(cast(@xml as varchar(max)), '&lt;/th&gt;&lt;th&gt;', '</th><th>'), '&lt;/td&gt;&lt;td&gt;', '</td><td>') as xml)

输出:

<table>
  <tr>
    <th>a</th>
    <th>b</th>
  </tr>
  <tr>
    <td>1</td>
    <td>one</td>
  </tr>
  <tr>
    <td>2</td>
    <td>two</td>
  </tr>
</table>

黑客列表:

  • 使用空值在同一“列”中获取 th 和 td
  • 显式添加标题值 a 和 b
  • 连接列值并在中间显式放置结束和开始标记
  • 将xml转换为varchar
  • 用尖括号版本替换这些标签的净化版本
  • 转换回xml

其中大部分可能可以重构为使用变量,可能是从您的输入/数据中收集的。

笔记:

一般来说,您应该让您的表示层为您创建 html。您可能可以在您的数据库中创建一个通用函数来从表中创建 html,但是已经有很多很棒的表示类、控件等旨在执行此操作。您的应用程序几乎总是可以比您的数据库更好地扩展。

于 2013-03-15T17:08:32.307 回答