|
在AUTO模式中是不可能实现这些改动的。
下面是创建这个新XML文档的EXPLICIT模式查询:
【图 2A】
|
SELECT 1 as Tag, NULL as Parent, s.stor_id as [Store!1!id], s.stor_name as [Store!1!name], NULL as [Sale!2!orderno], NULL as [Sale!2!1ty], NULL as [Discount!3!type], NULL as [Discount!3!lowqty], NULL as [Discount!3!highqty], NULL as [Discount!3!amount!element] FROM stores s UNION ALL SELECT 2, 1, s.stor_id, s.stor_name, sa.ord_num, sa.qty, NULL, NULL, NULL, NULL FROM stores s, sales sa WHERE s.stor_id = sa.stor_id UNION ALL SELECT 3, 1, NULL, s.stor_name, NULL, NULL, d.discounttype, d.lowqty, d.highqty, d.discount FROM stores s, discounts d WHERE s.stor_id = d.stor_id ORDER BY [store!1!name] For XML EXPLICIT |
为了创建图2A所显示的EXPLICIT模式查询,我们对图2的查询进行了如下修改:
增加了第三个子查询提取折扣数据,通过Tag列声明这些数据的标签值为3。
通过指定Parent列为1将折扣数据设置成<Store>元素的子元素。
注意在第三个SELECT子查询中我们只包含了那些必需的列,并用NULL补足空列。这个子查询包含store_name列,虽然Discount元素并不要用到这个列,但如果把这个列也设置为NULL,则结果Universal表将不会按照解析器所要求的那样以节点升序排序(不妨自己试一下看看)。Universal表的排序列也可以用Tag列替代。
为维持结果Universal表的完整性,第一、二两个SELECT语句也用NULL补足以反映为折扣数据增加的列。
为指定新折扣列的元数据修改了第一个SELECT语句。
通过在第四个参数中声明element指定Amount列为Discount的一个元素(element是可在第四个参数中声明的多个指令之一)。
下面这个XML文档只能用EXPLICIT模式生成:

结果XML文档中不会显示出NULL数据,如折扣lowqty和highqty。
看来上面的介绍,大家可能已经对FOR XML的语法有所了解。通过FOR XML 我们在能够在Query Analyzer 中直接返回一个XML格式的数据或者通过其他多样化表现方式将XML格式的数据显示出来,比如可以将数据显示在浏览器上。下面这个例子就使用FOR XML和ADO将数据输出到浏览器的例子。
|
Dim adoConn Set adoConn = Server.CreateObject("ADODB.Connection")
Dim sConn sConn = "Provider=SQLOLEDB;Data Source=192.168.0.160;Initial Catalog=Northwind;User ID=SA;Password=;" adoConn.ConnectionString = sConn adoConn.CursorLocation = adUseClient adoConn.Open
Dim adoCmd Set adoCmd = Server.CreateObject("ADODB.Command") Set adoCmd.ActiveConnection = adoConn
Dim sQuery ‘定义 FOR XML的查询。具体的语法在以后的章节中将详细介绍。 sQuery = "<ROOT xmlns:sql='urn:schemas-microsoft-com:xml-sql'><sql:query>SELECT * FROM PRODUCTS ORDER BY PRODUCTNAME FOR XML AUTO</sql:query></ROOT>"
‘建立ADODB Stream 对象,ADODB Stream 对象需要ADO2.5以上版本支持,它可以将记录集转换为数据流。 Dim adoStreamQuery Set adoStreamQuery = Server.CreateObject("ADODB.Stream") adoStreamQuery.Open adoStreamQuery.WriteText sQuery, adWriteChar adoStreamQuery.Position = 0 adoCmd.CommandStream = adoStreamQuery adoCmd.Dialect = "{5D531CB2-E6Ed-11D2-B252-00C04F681B71}"
Response.write "Pushing XML to client for processing " & "<BR/>"
adoCmd.Properties("Output Stream") = Response ‘输出XML格式的文本 Response.write "<XML ID=MyDataIsle>" adoCmd.Execute , , adExecuteStream Response.write "</XML>"
‘通过IE的XML解析器,使用DOM方法将XML的文本转换为HTML <SCRIPT language="VBScript" For="window" Event="onload">
Dim xmlDoc Set xmlDoc = MyDataIsle.XMLDocument xmlDoc.resolveExternals=false xmlDoc.async=false
Dim root, child Set root = xmlDoc.documentElement
For each child in root.childNodes dim OutputXML OutputXML = document.all("log").innerHTML document.all("log").innerHTML = OutputXML & "<LI>" & child.getAttribute("ProductName") & "</LI>" Next
</SCRIPT> |
兵器之二:XPath
W3C 于 1999 年 10 月 8 日提出的 XPath 语言规范,它是一种基于XML的查询语言,它能在XML文挡中处理数据。SQL Server 2000 中实现的是该规范的子集。它把table和views作为XML的组件,并把columns作为XML属性。SQL Server 2000的XML支持IIS使用URL或者模板的方式提交到SQL Server处理Xpath查询,并返回XML的结果。
支持的功能
下表显示 SQL Server 2000 中实现的 XPath 语言的功能。
|
功能 |
项目 |
|
轴 |
attribute、child、parent 和 self 轴 |
|
包括连续谓词和嵌套谓词在内的布尔值谓词 |
|
|
所有关系运算符 |
=, !=, <, <=, >, >= |
|
算术运算符 |
+, -, *, div |
|
显式转换函数 |
number()、string()、Boolean() |
|
布尔运算符 |
AND, OR |
|
布尔函数 |
true()、false()、not() |
|
XPath 变量 |
|
不支持的功能
下表显示 SQL Server 2000 中没有实现的 XPath 语言的功能。
|
功能 |
项目 |
|
轴 |
ancestor、ancestor-or-self、descendant、descendant-or-self (//)、following、following-sibling、namespace、preceding、preceding-sibling |
|
数值谓词 |
|
|
算术运算符 |
mod |
|
节点函数 |
ancestor、ancestor-or-self、descendant、descendant-or-self (//)、following、following-sibling、namespace、preceding、preceding-sibling |
|
字符串函数 |
string()、concat()、starts-with()、contains()、substring-before()、substring-after()、substring()、string-length()、normalize()、translate() |
|
布尔函数 |
lang() |
|
数字函数 |
sum()、floor()、ceiling()、round() |
|
Union 运算符 |
| |
XPath 查询是以表达式的形式指定的。位置路径是一种比较常用表达式,用以选择相对于上下文节点的节点集。位置路径表达式的求值结果是节点集。
|
XML 文档 <root> <order productid="Prod-28" unitprice="45.6" quantity="15"> <discount>0.25</discount> </order> <order productid="Prod-39" unitprice="18" quantity="21"> <discount>0.25</discount> </order> <order productid="Prod-46" unitprice="12" quantity="2"> <discount>0.25</discount> </order> </root> |
下面是查询该XML 文档的XPath位置路径表达式,它的含义是返回根节点下所有<ROOT>子元素下的ProductID属性的属性值为 "prod-39"的 <order> 元素。

位置路径的类型
可以分为绝对位置路径和相对位置路径。
绝对位置路径以文档的根节点开始,由斜杠 (/) 组成,后面可以是相对位置路径。斜杠 (/) 选定文档的根节点。
相对位置路径以文档的上下文节点(Context)开始,由斜杠 (/) 所分开的一个或多个位置步骤序列组成。每个步骤都选定相对于上下文节点的节点集。初始步骤序列选定相对于上下文节点的节点集。节点集中的每个节点都用作后续步骤的上下文节点。由后续步骤标识的节点集联接在一起。例如,child::Order/child::OrderDetail 选定上下文节点的<order> 子元素的 <orderdetail> 子元素。
位置步骤 (绝对或相对)位置路径由包含下面三部分的位置步骤组成:
轴
轴指定位置步骤选定的节点与上下文节点之间的树关系。SQL Server 2000 支持 parent、child、attribute 及 self 轴。
如果在位置路径中指定 child 轴,查询选定的所有节点都将是上下文节点的子节点。 比如说要查询从当前的上下文节点中选定所有 <Order>节点的子节点,可以使用 child:: Order
如果指定 parent 轴,选定的节点将是上下文节点的父节点。 比如说要查询从当前的上下文节点中选定所有 <Order>节点的父节点,可以使用 parent:: Order
如果指定 attribute 轴,选定的节点是上下文节点的属性。 比如说要查询从当前的上下文节点中选定所有 <Order>节点的属性,可以使用 attribute:: Order
节点测试
节点测试指定位置步骤选定的节点类型。每个轴(child、parent、attribute 和 self)都具有主要节点类型。对于 attribute 轴,主要节点类型是 <attribute>。对于 parent、child 和 self 轴,主要节点类型是 <element>。
例如,如果位置路径指定 child::Order,则将选定上下文节点的 <Order> 子元素。因为 child 轴以 <element> 为其主要节点类型,而且如果Order是 <element> 节点,则节点测试Order为 TRUE。
选择谓词(零个或多个)
谓词围绕着轴筛选节点集。在 XPath 表达式中指定选择谓词与在 SELECT 语句中指定 WHERE 子句相似。谓词在括号中指定。应用在选择谓词中指定的测试将对节点测试返回的节点进行筛选。对于要筛选的节点集中的每个节点,在对谓词表达式取值时将此节点作为上下文节点,将节点集中的节点数作为上下文大小。如果谓词表达式对此节点取值为 TRUE,则此节点将包括在最后所得到的节点集中。
例如: 1. Child::Order [attribute::ProductID="Prod-39"] 表示从当前的上下文节点中选定ProductID属性值为Prod-39的所有 <order>子节点。
2. Child::Order [child:: Discount] 表示从当前的上下文节点中选定包含一个或多个 <Discount> 子节点的所有 <Order> 子节点。
3. Child::Order [not(child:: Discount)] 表示从当前的上下文节点中选定不包含 <Discount> 子节点的所有 <Order> 子节点。
位置步骤的语法
是用两个冒号 (::) 分开的轴名和节点测试,后面是分别放在方括号中的零个或多个表达式。
例如,在 XPath 表达式(位置路径)child::Order[attribute::ProductID="prod-39"]中,选定上下文节点的所有 <order> 子元素。然后将谓词中的测试应用于节点集,将只返回 ProductID属性的属性值为 "prod-39"的 <order> 元素节点。
缩略语法
Sqlservr2000支持下面的位置路径缩略语法: attribute::可以缩略为 @。 比如:[attribute::ProductID="Prod-39"] 可以缩写成 [@ProductID =" Prod-39"]
child::可以在位置步骤中省略。 比如:位置路径child::ROOT/child::Orde可以缩写成 ROOT /Order
self::node() 可缩略为一个句点 (.),而 parent::node() 可缩略两个句点 (..)。
所以 /child::ROOT/child::Order[attribute::ProductID="prod-39"]也可以缩写成 /ROOT/Order[@ProductID="prod-39"] |