您的位置:首页 > 数据库

用RAW模式查询创建XML(SQL Server 与 XML 笔记)

2013-04-09 16:00 323 查看
在开发过程中,会遇到提取关系数据并返回给客户端时需将其格式化为XML的情况,SQL Server通过叫做For xml的T-SQL子句支持该功能,呵呵,多么幸运!

RAW模式是最简单的xml输出格式。假设有如下数据:

DECLARE @T1 table(UserID int , UserName nvarchar(50),CityName nvarchar(50));
insert into @T1 (UserID,UserName,CityName) values (1,null,'上海')
insert into @T1 (UserID,UserName,CityName) values (2,'b','北京')
insert into @T1 (UserID,UserName,CityName) values (3,'c','上海')
insert into @T1 (UserID,UserName,CityName) values (4,'d','北京')
insert into @T1 (UserID,UserName,CityName) values (5,'e','上海')
1、使用RAW模式:

现有一条SQL就可以将其变为一个xml字符串:

/*列做为属性名存在行标签为row的元素中*/
select * from @T1 for xml raw
查询出来的结果如下:
<row UserID="1" CityName="上海" />
<row UserID="2" UserName="b" CityName="北京" />
<row UserID="3" UserName="c" CityName="上海" />
<row UserID="4" UserName="d" CityName="北京" />
<row UserID="5" UserName="e" CityName="上海" />


2、ELEMENTS 与 XSINL条件的应用

我们可以看到1中输出的xml的格式并非良好,并且userid为1 的那行元素丢失了UserName属性。

首先给行(row)与列标签自定义别名,具体SQL如下:

/*可以对列属性起别名,并对原行标签为row的元素起别名(person),放在根元素为(persons)下*/
select
UserID id,
UserName name,
CityName city
from @T1
for xml raw('person'),
root('persons') ;
输出结果如下:
<persons>
<person id="1" city="上海" />
<person id="2" name="b" city="北京" />
<person id="3" name="c" city="上海" />
<person id="4" name="d" city="北京" />
<person id="5" name="e" city="上海" />
</persons>
这样就加入了根元素(persons)及行元素(person)的标签名称。

如何将行元素的属性变为其子元素呢?

即变成这个样子:

<persons xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<person>
<id>1</id>
<name xsi:nil="true" />
<city>上海</city>
</person>
<person>
<id>2</id>
<name>b</name>
<city>北京</city>
</person>
<person>
<id>3</id>
<name>c</name>
<city>上海</city>
</person>
<person>
<id>4</id>
<name>d</name>
<city>北京</city>
</person>
<person>
<id>5</id>
<name>e</name>
<city>上海</city>
</person>
</persons>
呵呵 有了ELEMENTS条件就容易多了,再加上XSINIL条件给力地将userid为1 的person属性Name补全了:
/*在子句中加入 elements条件,查询将返回元素而不是属性;
将XSINIL条件与Elements条件一起使用可以解决列值为空时导致该元素标签缺失问题
*/
select
UserID id,
UserName name,
CityName city
from @T1
for xml raw('person'),
root('persons')	,
elements xsinil
这样一个完整的结构良好的xml输出结果就有了。

3、加入明确的命名空间

可以在xml中包含一个生成架构。

在For XML子句中使用 XMLSCHEMA条件会产生带有明确目标命名空间的架构。

select
UserID id,
UserName name,
CityName city
from @T1
for xml raw('person'),
root('persons')	,
elements xsinil,
xmlschema
输出如下:
<persons xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsd:schema targetNamespace="urn:schemas-microsoft-com:sql:SqlRowSet1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sqltypes="http://schemas.microsoft.com/sqlserver/2004/sqltypes" elementFormDefault="qualified">
<xsd:import namespace="http://schemas.microsoft.com/sqlserver/2004/sqltypes" schemaLocation="http://schemas.microsoft.com/sqlserver/2004/sqltypes/sqltypes.xsd" />
<xsd:element name="person">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="id" type="sqltypes:int" nillable="1" />
<xsd:element name="name" nillable="1">
<xsd:simpleType>
<xsd:restriction base="sqltypes:nvarchar" sqltypes:localeId="2052" sqltypes:sqlCompareOptions="IgnoreCase IgnoreKanaType IgnoreWidth">
<xsd:maxLength value="50" />
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="city" nillable="1">
<xsd:simpleType>
<xsd:restriction base="sqltypes:nvarchar" sqltypes:localeId="2052" sqltypes:sqlCompareOptions="IgnoreCase IgnoreKanaType IgnoreWidth">
<xsd:maxLength value="50" />
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<person xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1">
<id>1</id>
<name xsi:nil="true" />
<city>上海</city>
</person>
<person xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1">
<id>2</id>
<name>b</name>
<city>北京</city>
</person>
<person xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1">
<id>3</id>
<name>c</name>
<city>上海</city>
</person>
<person xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1">
<id>4</id>
<name>d</name>
<city>北京</city>
</person>
<person xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1">
<id>5</id>
<name>e</name>
<city>上海</city>
</person>
</persons>


如何自定义命名空间呢?可以使用XMLSHEMA(‘urn:sampleNamespace’)来定义自己的命名空间标识符。

select
UserID id,
UserName name,
CityName city
from @T1
for xml raw('person'),
root('persons')	,
elements xsinil,
xmlschema('urn:mynamespace')
输出如下:
<persons xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsd:schema targetNamespace="urn:mynamespace" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sqltypes="http://schemas.microsoft.com/sqlserver/2004/sqltypes" elementFormDefault="qualified">
<xsd:import namespace="http://schemas.microsoft.com/sqlserver/2004/sqltypes" schemaLocation="http://schemas.microsoft.com/sqlserver/2004/sqltypes/sqltypes.xsd" />
<xsd:element name="person">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="id" type="sqltypes:int" nillable="1" />
<xsd:element name="name" nillable="1">
<xsd:simpleType>
<xsd:restriction base="sqltypes:nvarchar" sqltypes:localeId="2052" sqltypes:sqlCompareOptions="IgnoreCase IgnoreKanaType IgnoreWidth">
<xsd:maxLength value="50" />
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="city" nillable="1">
<xsd:simpleType>
<xsd:restriction base="sqltypes:nvarchar" sqltypes:localeId="2052" sqltypes:sqlCompareOptions="IgnoreCase IgnoreKanaType IgnoreWidth">
<xsd:maxLength value="50" />
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<person xmlns="urn:mynamespace">
<id>1</id>
<name xsi:nil="true" />
<city>上海</city>
</person>
<person xmlns="urn:mynamespace">
<id>2</id>
<name>b</name>
<city>北京</city>
</person>
<person xmlns="urn:mynamespace">
<id>3</id>
<name>c</name>
<city>上海</city>
</person>
<person xmlns="urn:mynamespace">
<id>4</id>
<name>d</name>
<city>北京</city>
</person>
<person xmlns="urn:mynamespace">
<id>5</id>
<name>e</name>
<city>上海</city>
</person>
</persons>
SQL server将用该目标名称空间来标记数据流。当给实用工具(这些实用工具需要用于绑定的架构信息)返回数据时,该方法就显得非常有用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: