SQL与XML的FOR XML用法

在实际开发中,经常需要把从数据库中取出的数据直接转换成XML文件.
DataSet的GetXml()方法可以直接把表数据转换成XML格式的.
不过实际的需要可能需要不同格式的XML文件,比如表中某列作为某节点的属性,而有的列作为节点的值.
这就需要代码处理相应的列.
不过自从数据库与XML相融那天起,它们之间的转换就有了更为直接的方法
那就是SQL提供的FOR XML子句.
利用 FOR XML 子句,您可以直接从 SQL Server 2000/2005获得 XML 结果。
FOR XML 支持三种操作模式:Raw、Auto 和 Explicit。
每个选项都会改变您的查询返回的 XML 的格式。
Explicit 模式是唯一支持开放内容的模式。
Explicit 模式使您可以完全控制 XML 查询结果的形状(有时也称为 XML 语法或架构)。
使用 Explicit 模式查询,您可以指定 XML 文档的层次结构以及文档内的元素和属性的名称。

1.For XML Raw

For XML Raw模式返回一个结果集,其中每个返回的结果行位于使用该行的通用标志符命名的列中。
每个列的值是使用属性对返回的。
SELECT [personName], [personAge]
FROM [TestDB].[dbo].[person]
FOR XML RAW

结果:
<row personName="lisi   " personAge="30"/>
<row personName="zhangsan " personAge="30"/>

2.For XML Auto

For XML Auto模式根据SQL语句返回的标记提供了更强的灵活性。
然而,它在生成的XML结果的结构中仍然存在一些局限性。
默认情况下,SQL Server Table或View的名称用作元素名,而列名用作每个元素的属性。
您可以使用Elements指令指定将每个列创建到一个子元素中。
元素的嵌套是根据Select语句中使用的列的顺序进行控制的。
SELECT [personName], [personAge]
FROM [TestDB].[dbo].[person]
FOR XML AUTO

结果:
<TestDB.dbo.person personName="lisi   " personAge="30"/>
<TestDB.dbo.person personName="zhangsan " personAge="30"/>

3.For XML Explicit

For XML Explicit模式可以产生更灵活的结果,也可以用于满足复杂的需求。
Explicit模式提供了对标记名称以及所产生元素的层次结构和嵌套的完全控制。
列可以被个别地映射到各种元素或属性。
然而,For Explicit模式要求必须使用复杂的SQL查询指定通用表的结构,该结构描述了目标XML文档。
Explicit模式所需的语法是苛刻的,而且由您来确保生成的XML格式良好并有效。
Explicit模式的灵活性允许它满足许多行业标准的消息规范的需求。
Explicit模式是通过UNION ALL查询实现的,该查询主要将两个或更多查询的结果组合在一起。
每个查询都必须包含相同的列数,而且每个查询中相应的列必须使用一致的数据类型。
而XML层次结构是由顶部查询或父查询定义的。随后的查询检索了每个XML节点的数据。
select 1 as Tag ,null as parent
,RTRIM(personName) as [PersonBasic!1!personName]
,RTRIM(personAge) as [PersonBasic!1!personAge!xml]
FROM [TestDB].[dbo].[person]
FOR XML EXPLICIT

结果:

<PersonBasic personName="lisi">
  <personAge>30</personAge>
</PersonBasic>
<PersonBasic personName="zhangsan">
  <personAge>30</personAge>
</PersonBasic>

在我的项目中用到如下的语句:
表A
NewsID NewsTitle NewsTime NewsContent_Text
select TOP 10
1 as Tag,
null as parent,
NewsID as [row!1!NewsID],
NewsTitle as [row!1!NewsTitle],
NewsTime as [row!1!NewsTime],
NewsContent_Text as [row!1!NewsContent!xml]
from NewsDBBakup_Table
最后显示
<?xml version="1.0" encoding="UTF-8" ?>
<CentralBank>
<row NewsID="20080111111092080" NewsTitle="AA" NewsTime="20080111111051">
 <NewsContent>
  <![CDATA[各国改革
   蘑菇炒鸡蛋。
   这个菜基本上是迄今为止,我做的所有菜中最得意的一个。
  ]]>
 </NewsContent>
</row>
<row NewsID="20080111111091080" NewsTitle="BB" NewsTime="20080111111019">
 <NewsContent>
  <![CDATA[
   蘑菇外裹的鸡蛋“保护”了它的“鲜美”
   所以这样炒的蘑菇吃起来特别好吃,唇齿留香。。。。
  ]]>
 </NewsContent>
</row></CentralBank>

作者:Bober Song
出处:http://bober.cnblogs.com/
衣冠勤售: http://www.YiGuanShou.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
posted @ 2008-02-19 09:24 衣冠勤售 阅读(640) 评论(2)  编辑 收藏

 回复 引用 查看   
#1楼[楼主] 2008-02-19 09:25 大力bober      
select 1 as Tag, NULL as Parent
前两个参数一个为标记,一个为父节点

 回复 引用 查看   
#2楼[楼主] 2008-02-19 09:28 大力bober      
----- 更改显示Tag为中文 -----
select
1 as tag,
null as parent,
personName as [人员!1!姓名!xml],
personAge as [人员!1!年龄!xml]
from person
for xml EXPLICIT

结果:

<人员>
<姓名>lisi
<年龄>30

<人员>
<姓名>zhangsan
<年龄>30


----- 同表 多层 ----
select
1 as tag,
null as parent,
rtrim(A.personName) as [人员!1!姓名],
null as [人员信息!2!年龄!xml]
from person A

union all

select
2 as tag,
1 as parent,
rtrim(A.personName),
B.personAge
from person B,person A
where A.personName=B.personName

order by [人员!1!姓名],tag

for xml EXPLICIT

结果:

<人员 姓名="lisi">
<人员信息>
<年龄>30


<人员 姓名="zhangsan">
<人员信息>
<年龄>30



-------- 异表 多层 -------
select
1 as tag,
null as parent,
rtrim(A.personName) as [人员!1!姓名],
null as [人员信息!2!年龄!xml],
null as [人员信息!2!职业!xml]
from person A

union all

select
2 as tag,
1 as parent,
rtrim(A.personName),
B.personAge,
rtrim(B.personJob)
from personInfo B,person A
where B.personName=A.personName
order by [人员!1!姓名],tag
for xml EXPLICIT

结果:

<人员 姓名="lisi">
<人员信息>
<年龄>30
<职业>teacher


<人员 姓名="zhangsan">
<人员信息>
<年龄>30
<职业>worker



-------处理数据及日期等的Null值-------
数据库Person表中的数据为
personName personAge personBirth(可为空)
lisi 30 1987-06-06
zhangsan 30

当数据表中的字段为Null值时
产生的xml文档中 将没有该节点
为了解决这一问题
在必要的时候 可以将数字及日期类型
转换为字符串类型
这样就可以接收空串
(但不知实际运用中效果如何)

SELECT
1 as TAG,
null as parent,
RTRIM(personName) AS [人员!1!姓名!xml],
RTRIM(ISNULL(CONVERT(CHAR,personAge),'')) AS [人员!1!年龄!xml],
RTRIM(ISNULL(CONVERT(CHAR(10),personBirth,120),'')) AS [人员!1!出生日期!xml]
FROM person
FOR XML EXPLICIT

结果:

<人员>
<姓名>lisi
<年龄>30
<出生日期>1987-06-06

<人员>
<姓名>zhangsan
<年龄>
<出生日期>

作者:Bober Song
出处:http://bober.cnblogs.com/
衣冠勤售:http://www.YiGuanShou.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。