xml,已成为近来最热门的web技术,它是sql server 2000中的重要部分。本文将综合七条sql server 2000中最重要的xml综合特性组成xml之七种兵器。
兵器之一:for xml
在sql server 2000中,标准的t-sql select语句包括for xml子句,它以xml文档形式返回一个查询结果。新的for xml子句有三种模式——raw,auto,和explicit,每个都能对xml文档格式提供附加标准的控制。
下面首先介绍“for xml”的使用方法。
为了从sql server提取xml格式的数据,t-sql中加入了一个for xml命令。在查询命令中使用for xml命令使得查询结果以xml格式出现。for xml命令有三种模式:raw,auto和explicit。图1所显示的sql命令访问sql server提供的pubs示例数据库。有关pubs数据库的更多信息,请参见msdn说明。如果我们依次指定该sql命令的模式为三种允许的模式之一,就可以得到各种模式所支持的不同xml输出。
【图1 】
select store.stor_id as id, stor_name as name,
sale.ord_num as orderno,sale.qty as qty
from stores store inner join
sales sale on store.stor_id = sale.stor_id
order by stor_name
for xml <模式>
该查询命令所生成的结果包含所有销售记录及其对应的商店,结果以商店名称的字母升序排列。查询的最后加上了for xml命令以及具体的模式,比如for xml raw。
理想情况下,sql命令所生成的xml文档应具有如下结构:
<stores>
<store id=&single;&single; name=&single;&single;>
</sale orderno=&single;&single; qty=&single;&single;>
</store>
</stores>
下面我们来看看具体的处理方法。
raw模式
下面是指定raw模式时结果xml文档的一个片断。
查询结果集中每一个记录包含唯一的元素<row>。由于我们无法控制元素名字和文档结构,因此这种模式不是很有用。raw模式所生成的文档结构与我们所希望的不符,而且它的用途也非常有限。
auto模式
下面是指定auto模式时结果文档的一个片断:
可以看到,<stroe>和<sale>两个元素是父-子关系,形成了我们所希望的层次结构。这种节点关系由查询中表的声明次序决定,后声明的表成为前声明表的孩子。
再参考图1,我们可以看出查询命令所指定的别名决定了xml文档中的名字。根据这一点,我们可以控制xml文档元素、属性的名字,使得这些名字符合我们所要求的命名惯例。
可见auto模式能够创建出我们所需要的xml文档。不过它存在以下缺点:
虽然可以得到层次结构,但这种层次结构是线性的,即每个父节点只能有一个子节点,反之亦然。
通过别名指定元素名字不太方便,而且有时候会影响查询命令本身的可读性。
无法在文档中同时生成元素和属性。要么全部是元素(通过elements关键词指定),要么全部是属性(默认)。 explicit模式解决了上述不足。
explicit模式
explicit模式比较复杂,我们将用另外一种方法来表达图1所显示的查询。这种方法使得我们能够完全地控制查询所生成的xml文档。首先我们将介绍如何改用explicit模式编写图1所显示的查询,然后看看这种方法如何赋予我们远远超过auto模式的能力。
下面是图1查询用explicit模式表达的代码:
【图2 】
--商店数据
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!qty]
from stores s
union all
-- 销售数据
select 2, 1,
s.stor_id,
s.stor_name,
sa.ord_num,
sa.qty
from stores s, sales sa
where s.stor_id = sa.stor_id
order by [store!1!name]
for xml explicit
这个查询初看起来有点复杂,其实它只是把不同的数据集(即这里的store和sale)分解到了独立的select语句里,然后再用union all操作符连结成一个查询。
我们之所以要把查询写成上面的形式,是为了让查询结果不仅包含xml文档所描述的数据,而且还包含描述xml文档结构的元数据。上述查询所生成的表称为universal表,sqlxml.dll生成xml文档时需要这种格式。universal表对于编写代码的人来说是透明的,但了解这个表还是很有意义的,它将有助于代码的开发和调试。下面是universal表的一个例子:
tag parent store!1!id store!1!name sale!2!orderno sale!2!qty
1 null 7066 barnum&single;s null null
2 1 7066 barnum&single;s a297650 50
2 1 7066 barnum&single;s qa7442 375
1 null 8042 bookbeat null null
2 1 8042 bookbeat 423ll9 2215
universal表和explicit模式查询的元数据部分都以红色表示,黑色表示数据。比较查询和表就可以找出sqlxml.dll生成xml文档所需要的元素。我们来仔细地分析一下它们描述的是什么。
tag和parent列是xml文档层次结构方面的信息,我们可以认为图2中的每个select语句代表了一个xml节点,而tag和parent列让我们指定节点在文档层次结构中的位置。如果在第二个select语句中指定tag为2、指定parent为1,就表示为这些数据加上了一个值为2的标签,而这些数据的父亲是那些标签为1的数据(即第一个select语句)。这就使得我们能够构造出<store>和<sale>之间的父-子关系,而且正如你可能猜想到的,它使得我们可以生成任意合法的xml文档结构。注意第一个select命令的parent列设置成了null,这表示<store>元素处于最顶层的位置。
以黑色表示的数据将成为节点的属性或元素,例如,store_id就通过列名提供了这方面的信息。列名字中的“!”是分隔符,总共可分成四项(四个参数),其中第四个参数是可选的。这些参数描述的是:
第一个参数描述该列所属元素的名字,在这里是<store>元素。
第二个是标签编号,它指定了该列信息在xml树形结构中所处位置。
第三个参数指定xml文档内的属性或元素名字。在这里名字指定为id。
数据列默认被创建为参数2所指定节点的属性,即id将成为<store>节点的属性。如果要指定id是<store>的一个子元素,我们可以使用第四个可选的参数,这个参数的一个作用就是让我们把该项指定为元素,例如store!1!id!element。
由于使用了union all操作符来连结select语句,为了保证sql查询的合法性,所有select语句的选择结果必须具有相同数量的列。我们使用null关键词来补足select语句,从而避免了重复数据。
通过explicit模式查询所生成的xml文档和通过auto模式生成的完全相同,那么为什么要创建explicit模式查询呢?
假设现在有人要求在xml文档中包含商店的打折信息。查看pubs数据库,我们得知每个商店都可以有0到n范围内的折扣率。因此,一种合理的方法是在<store>元素下面加上子元素<discount>,这样我们就得到如下xml文档结构:
<stores>
<store id=&single;&single; name=&single;&single;>
<discount type=&single;&single; lowqty=&single;&single; highqty=&single;&single;>
<amount></amount>
</discount>
<sale ordno=&single;&single; qty=&single;&single;>
</sale>
</store>
</stores>
这里的改动包括:
要在<sale>元素所在的层次增加一个xml元素<discount>,即<discount>是<stroe>的子元素。
amount嵌套在<discount>里面,但不应该是<discount>元素的属性。
在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
explicit模式
explicit模式比较复杂,我们将用另外一种方法来表达图1所显示的查询。这种方法使得我们能够完全地控制查询所生成的xml文档。首先我们将介绍如何改用explicit模式编写图1所显示的查询,然后看看这种方法如何赋予我们远远超过auto模式的能力。
下面是图1查询用explicit模式表达的代码:
【图2 】
--商店数据
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!qty]
from stores s
union all
-- 销售数据
select 2, 1,
s.stor_id,
s.stor_name,
sa.ord_num,
sa.qty
from stores s, sales sa
where s.stor_id = sa.stor_id
order by [store!1!name]
for xml explicit
这个查询初看起来有点复杂,其实它只是把不同的数据集(即这里的store和sale)分解到了独立的select语句里,然后再用union all操作符连结成一个查询。
我们之所以要把查询写成上面的形式,是为了让查询结果不仅包含xml文档所描述的数据,而且还包含描述xml文档结构的元数据。上述查询所生成的表称为universal表,sqlxml.dll生成xml文档时需要这种格式。universal表对于编写代码的人来说是透明的,但了解这个表还是很有意义的,它将有助于代码的开发和调试。下面是universal表的一个例子:
tag parent store!1!id store!1!name sale!2!orderno sale!2!qty
1 null 7066 barnum&single;s null null
2 1 7066 barnum&single;s a297650 50
2 1 7066 barnum&single;s qa7442 375
1 null 8042 bookbeat null null
2 1 8042 bookbeat 423ll9 2215
universal表和explicit模式查询的元数据部分都以红色表示,黑色表示数据。比较查询和表就可以找出sqlxml.dll生成xml文档所需要的元素。我们来仔细地分析一下它们描述的是什么。
tag和parent列是xml文档层次结构方面的信息,我们可以认为图2中的每个select语句代表了一个xml节点,而tag和parent列让我们指定节点在文档层次结构中的位置。如果在第二个select语句中指定tag为2、指定parent为1,就表示为这些数据加上了一个值为2的标签,而这些数据的父亲是那些标签为1的数据(即第一个select语句)。这就使得我们能够构造出<store>和<sale>之间的父-子关系,而且正如你可能猜想到的,它使得我们可以生成任意合法的xml文档结构。注意第一个select命令的parent列设置成了null,这表示<store>元素处于最顶层的位置。
以黑色表示的数据将成为节点的属性或元素,例如,store_id就通过列名提供了这方面的信息。列名字中的“!”是分隔符,总共可分成四项(四个参数),其中第四个参数是可选的。这些参数描述的是:
第一个参数描述该列所属元素的名字,在这里是<store>元素。
第二个是标签编号,它指定了该列信息在xml树形结构中所处位置。
第三个参数指定xml文档内的属性或元素名字。在这里名字指定为id。
数据列默认被创建为参数2所指定节点的属性,即id将成为<store>节点的属性。如果要指定id是<store>的一个子元素,我们可以使用第四个可选的参数,这个参数的一个作用就是让我们把该项指定为元素,例如store!1!id!element。
由于使用了union all操作符来连结select语句,为了保证sql查询的合法性,所有select语句的选择结果必须具有相同数量的列。我们使用null关键词来补足select语句,从而避免了重复数据。
通过explicit模式查询所生成的xml文档和通过auto模式生成的完全相同,那么为什么要创建explicit模式查询呢?
假设现在有人要求在xml文档中包含商店的打折信息。查看pubs数据库,我们得知每个商店都可以有0到n范围内的折扣率。因此,一种合理的方法是在<store>元素下面加上子元素<discount>,这样我们就得到如下xml文档结构:
<stores>
<store id=&single;&single; name=&single;&single;>
<discount type=&single;&single; lowqty=&single;&single; highqty=&single;&single;>
<amount></amount>
</discount>
<sale ordno=&single;&single; qty=&single;&single;>
</sale>
</store>
</stores>
这里的改动包括:
要在<sale>元素所在的层次增加一个xml元素<discount>,即<discount>是<stroe>的子元素。
amount嵌套在<discount>里面,但不应该是<discount>元素的属性。
在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
explicit模式
explicit模式比较复杂,我们将用另外一种方法来表达图1所显示的查询。这种方法使得我们能够完全地控制查询所生成的xml文档。首先我们将介绍如何改用explicit模式编写图1所显示的查询,然后看看这种方法如何赋予我们远远超过auto模式的能力。
下面是图1查询用explicit模式表达的代码:
【图2 】
--商店数据
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!qty]
from stores s
union all
-- 销售数据
select 2, 1,
s.stor_id,
s.stor_name,
sa.ord_num,
sa.qty
from stores s, sales sa
where s.stor_id = sa.stor_id
order by [store!1!name]
for xml explicit
这个查询初看起来有点复杂,其实它只是把不同的数据集(即这里的store和sale)分解到了独立的select语句里,然后再用union all操作符连结成一个查询。
我们之所以要把查询写成上面的形式,是为了让查询结果不仅包含xml文档所描述的数据,而且还包含描述xml文档结构的元数据。上述查询所生成的表称为universal表,sqlxml.dll生成xml文档时需要这种格式。universal表对于编写代码的人来说是透明的,但了解这个表还是很有意义的,它将有助于代码的开发和调试。下面是universal表的一个例子:
tag parent store!1!id store!1!name sale!2!orderno sale!2!qty
1 null 7066 barnum&single;s null null
2 1 7066 barnum&single;s a297650 50
2 1 7066 barnum&single;s qa7442 375
1 null 8042 bookbeat null null
2 1 8042 bookbeat 423ll9 2215
universal表和explicit模式查询的元数据部分都以红色表示,黑色表示数据。比较查询和表就可以找出sqlxml.dll生成xml文档所需要的元素。我们来仔细地分析一下它们描述的是什么。
tag和parent列是xml文档层次结构方面的信息,我们可以认为图2中的每个select语句代表了一个xml节点,而tag和parent列让我们指定节点在文档层次结构中的位置。如果在第二个select语句中指定tag为2、指定parent为1,就表示为这些数据加上了一个值为2的标签,而这些数据的父亲是那些标签为1的数据(即第一个select语句)。这就使得我们能够构造出<store>和<sale>之间的父-子关系,而且正如你可能猜想到的,它使得我们可以生成任意合法的xml文档结构。注意第一个select命令的parent列设置成了null,这表示<store>元素处于最顶层的位置。
以黑色表示的数据将成为节点的属性或元素,例如,store_id就通过列名提供了这方面的信息。列名字中的“!”是分隔符,总共可分成四项(四个参数),其中第四个参数是可选的。这些参数描述的是:
第一个参数描述该列所属元素的名字,在这里是<store>元素。
第二个是标签编号,它指定了该列信息在xml树形结构中所处位置。
第三个参数指定xml文档内的属性或元素名字。在这里名字指定为id。
数据列默认被创建为参数2所指定节点的属性,即id将成为<store>节点的属性。如果要指定id是<store>的一个子元素,我们可以使用第四个可选的参数,这个参数的一个作用就是让我们把该项指定为元素,例如store!1!id!element。
由于使用了union all操作符来连结select语句,为了保证sql查询的合法性,所有select语句的选择结果必须具有相同数量的列。我们使用null关键词来补足select语句,从而避免了重复数据。
通过explicit模式查询所生成的xml文档和通过auto模式生成的完全相同,那么为什么要创建explicit模式查询呢?
假设现在有人要求在xml文档中包含商店的打折信息。查看pubs数据库,我们得知每个商店都可以有0到n范围内的折扣率。因此,一种合理的方法是在<store>元素下面加上子元素<discount>,这样我们就得到如下xml文档结构:
<stores>
<store id=&single;&single; name=&single;&single;>
<discount type=&single;&single; lowqty=&single;&single; highqty=&single;&single;>
<amount></amount>
</discount>
<sale ordno=&single;&single; qty=&single;&single;>
</sale>
</store>
</stores>
这里的改动包括:
要在<sale>元素所在的层次增加一个xml元素<discount>,即<discount>是<stroe>的子元素。
amount嵌套在<discount>里面,但不应该是<discount>元素的属性。
在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
explicit模式
explicit模式比较复杂,我们将用另外一种方法来表达图1所显示的查询。这种方法使得我们能够完全地控制查询所生成的xml文档。首先我们将介绍如何改用explicit模式编写图1所显示的查询,然后看看这种方法如何赋予我们远远超过auto模式的能力。
下面是图1查询用explicit模式表达的代码:
【图2 】
--商店数据
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!qty]
from stores s
union all
-- 销售数据
select 2, 1,
s.stor_id,
s.stor_name,
sa.ord_num,
sa.qty
from stores s, sales sa
where s.stor_id = sa.stor_id
order by [store!1!name]
for xml explicit
这个查询初看起来有点复杂,其实它只是把不同的数据集(即这里的store和sale)分解到了独立的select语句里,然后再用union all操作符连结成一个查询。
我们之所以要把查询写成上面的形式,是为了让查询结果不仅包含xml文档所描述的数据,而且还包含描述xml文档结构的元数据。上述查询所生成的表称为universal表,sqlxml.dll生成xml文档时需要这种格式。universal表对于编写代码的人来说是透明的,但了解这个表还是很有意义的,它将有助于代码的开发和调试。下面是universal表的一个例子:
tag parent store!1!id store!1!name sale!2!orderno sale!2!qty
1 null 7066 barnum&single;s null null
2 1 7066 barnum&single;s a297650 50
2 1 7066 barnum&single;s qa7442 375
1 null 8042 bookbeat null null
2 1 8042 bookbeat 423ll9 2215
universal表和explicit模式查询的元数据部分都以红色表示,黑色表示数据。比较查询和表就可以找出sqlxml.dll生成xml文档所需要的元素。我们来仔细地分析一下它们描述的是什么。
tag和parent列是xml文档层次结构方面的信息,我们可以认为图2中的每个select语句代表了一个xml节点,而tag和parent列让我们指定节点在文档层次结构中的位置。如果在第二个select语句中指定tag为2、指定parent为1,就表示为这些数据加上了一个值为2的标签,而这些数据的父亲是那些标签为1的数据(即第一个select语句)。这就使得我们能够构造出<store>和<sale>之间的父-子关系,而且正如你可能猜想到的,它使得我们可以生成任意合法的xml文档结构。注意第一个select命令的parent列设置成了null,这表示<store>元素处于最顶层的位置。
以黑色表示的数据将成为节点的属性或元素,例如,store_id就通过列名提供了这方面的信息。列名字中的“!”是分隔符,总共可分成四项(四个参数),其中第四个参数是可选的。这些参数描述的是:
第一个参数描述该列所属元素的名字,在这里是<store>元素。
第二个是标签编号,它指定了该列信息在xml树形结构中所处位置。
第三个参数指定xml文档内的属性或元素名字。在这里名字指定为id。
数据列默认被创建为参数2所指定节点的属性,即id将成为<store>节点的属性。如果要指定id是<store>的一个子元素,我们可以使用第四个可选的参数,这个参数的一个作用就是让我们把该项指定为元素,例如store!1!id!element。
由于使用了union all操作符来连结select语句,为了保证sql查询的合法性,所有select语句的选择结果必须具有相同数量的列。我们使用null关键词来补足select语句,从而避免了重复数据。
通过explicit模式查询所生成的xml文档和通过auto模式生成的完全相同,那么为什么要创建explicit模式查询呢?
假设现在有人要求在xml文档中包含商店的打折信息。查看pubs数据库,我们得知每个商店都可以有0到n范围内的折扣率。因此,一种合理的方法是在<store>元素下面加上子元素<discount>,这样我们就得到如下xml文档结构:
<stores>
<store id=&single;&single; name=&single;&single;>
<discount type=&single;&single; lowqty=&single;&single; highqty=&single;&single;>
<amount></amount>
</discount>
<sale ordno=&single;&single; qty=&single;&single;>
</sale>
</store>
</stores>
这里的改动包括:
要在<sale>元素所在的层次增加一个xml元素<discount>,即<discount>是<stroe>的子元素。
amount嵌套在<discount>里面,但不应该是<discount>元素的属性。
在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
explicit模式
explicit模式比较复杂,我们将用另外一种方法来表达图1所显示的查询。这种方法使得我们能够完全地控制查询所生成的xml文档。首先我们将介绍如何改用explicit模式编写图1所显示的查询,然后看看这种方法如何赋予我们远远超过auto模式的能力。
下面是图1查询用explicit模式表达的代码:
【图2 】
--商店数据
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!qty]
from stores s
union all
-- 销售数据
select 2, 1,
s.stor_id,
s.stor_name,
sa.ord_num,
sa.qty
from stores s, sales sa
where s.stor_id = sa.stor_id
order by [store!1!name]
for xml explicit
这个查询初看起来有点复杂,其实它只是把不同的数据集(即这里的store和sale)分解到了独立的select语句里,然后再用union all操作符连结成一个查询。
我们之所以要把查询写成上面的形式,是为了让查询结果不仅包含xml文档所描述的数据,而且还包含描述xml文档结构的元数据。上述查询所生成的表称为universal表,sqlxml.dll生成xml文档时需要这种格式。universal表对于编写代码的人来说是透明的,但了解这个表还是很有意义的,它将有助于代码的开发和调试。下面是universal表的一个例子:
tag parent store!1!id store!1!name sale!2!orderno sale!2!qty
1 null 7066 barnum&single;s null null
2 1 7066 barnum&single;s a297650 50
2 1 7066 barnum&single;s qa7442 375
1 null 8042 bookbeat null null
2 1 8042 bookbeat 423ll9 2215
universal表和explicit模式查询的元数据部分都以红色表示,黑色表示数据。比较查询和表就可以找出sqlxml.dll生成xml文档所需要的元素。我们来仔细地分析一下它们描述的是什么。
tag和parent列是xml文档层次结构方面的信息,我们可以认为图2中的每个select语句代表了一个xml节点,而tag和parent列让我们指定节点在文档层次结构中的位置。如果在第二个select语句中指定tag为2、指定parent为1,就表示为这些数据加上了一个值为2的标签,而这些数据的父亲是那些标签为1的数据(即第一个select语句)。这就使得我们能够构造出<store>和<sale>之间的父-子关系,而且正如你可能猜想到的,它使得我们可以生成任意合法的xml文档结构。注意第一个select命令的parent列设置成了null,这表示<store>元素处于最顶层的位置。
以黑色表示的数据将成为节点的属性或元素,例如,store_id就通过列名提供了这方面的信息。列名字中的“!”是分隔符,总共可分成四项(四个参数),其中第四个参数是可选的。这些参数描述的是:
第一个参数描述该列所属元素的名字,在这里是<store>元素。
第二个是标签编号,它指定了该列信息在xml树形结构中所处位置。
第三个参数指定xml文档内的属性或元素名字。在这里名字指定为id。
数据列默认被创建为参数2所指定节点的属性,即id将成为<store>节点的属性。如果要指定id是<store>的一个子元素,我们可以使用第四个可选的参数,这个参数的一个作用就是让我们把该项指定为元素,例如store!1!id!element。
由于使用了union all操作符来连结select语句,为了保证sql查询的合法性,所有select语句的选择结果必须具有相同数量的列。我们使用null关键词来补足select语句,从而避免了重复数据。
通过explicit模式查询所生成的xml文档和通过auto模式生成的完全相同,那么为什么要创建explicit模式查询呢?
假设现在有人要求在xml文档中包含商店的打折信息。查看pubs数据库,我们得知每个商店都可以有0到n范围内的折扣率。因此,一种合理的方法是在<store>元素下面加上子元素<discount>,这样我们就得到如下xml文档结构:
<stores>
<store id=&single;&single; name=&single;&single;>
<discount type=&single;&single; lowqty=&single;&single; highqty=&single;&single;>
<amount></amount>
</discount>
<sale ordno=&single;&single; qty=&single;&single;>
</sale>
</store>
</stores>
这里的改动包括:
要在<sale>元素所在的层次增加一个xml元素<discount>,即<discount>是<stroe>的子元素。
amount嵌套在<discount>里面,但不应该是<discount>元素的属性。
在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
explicit模式
explicit模式比较复杂,我们将用另外一种方法来表达图1所显示的查询。这种方法使得我们能够完全地控制查询所生成的xml文档。首先我们将介绍如何改用explicit模式编写图1所显示的查询,然后看看这种方法如何赋予我们远远超过auto模式的能力。
下面是图1查询用explicit模式表达的代码:
【图2 】
--商店数据
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!qty]
from stores s
union all
-- 销售数据
select 2, 1,
s.stor_id,
s.stor_name,
sa.ord_num,
sa.qty
from stores s, sales sa
where s.stor_id = sa.stor_id
order by [store!1!name]
for xml explicit
这个查询初看起来有点复杂,其实它只是把不同的数据集(即这里的store和sale)分解到了独立的select语句里,然后再用union all操作符连结成一个查询。
我们之所以要把查询写成上面的形式,是为了让查询结果不仅包含xml文档所描述的数据,而且还包含描述xml文档结构的元数据。上述查询所生成的表称为universal表,sqlxml.dll生成xml文档时需要这种格式。universal表对于编写代码的人来说是透明的,但了解这个表还是很有意义的,它将有助于代码的开发和调试。下面是universal表的一个例子:
tag parent store!1!id store!1!name sale!2!orderno sale!2!qty
1 null 7066 barnum&single;s null null
2 1 7066 barnum&single;s a297650 50
2 1 7066 barnum&single;s qa7442 375
1 null 8042 bookbeat null null
2 1 8042 bookbeat 423ll9 2215
universal表和explicit模式查询的元数据部分都以红色表示,黑色表示数据。比较查询和表就可以找出sqlxml.dll生成xml文档所需要的元素。我们来仔细地分析一下它们描述的是什么。
tag和parent列是xml文档层次结构方面的信息,我们可以认为图2中的每个select语句代表了一个xml节点,而tag和parent列让我们指定节点在文档层次结构中的位置。如果在第二个select语句中指定tag为2、指定parent为1,就表示为这些数据加上了一个值为2的标签,而这些数据的父亲是那些标签为1的数据(即第一个select语句)。这就使得我们能够构造出<store>和<sale>之间的父-子关系,而且正如你可能猜想到的,它使得我们可以生成任意合法的xml文档结构。注意第一个select命令的parent列设置成了null,这表示<store>元素处于最顶层的位置。
以黑色表示的数据将成为节点的属性或元素,例如,store_id就通过列名提供了这方面的信息。列名字中的“!”是分隔符,总共可分成四项(四个参数),其中第四个参数是可选的。这些参数描述的是:
第一个参数描述该列所属元素的名字,在这里是<store>元素。
第二个是标签编号,它指定了该列信息在xml树形结构中所处位置。
第三个参数指定xml文档内的属性或元素名字。在这里名字指定为id。
数据列默认被创建为参数2所指定节点的属性,即id将成为<store>节点的属性。如果要指定id是<store>的一个子元素,我们可以使用第四个可选的参数,这个参数的一个作用就是让我们把该项指定为元素,例如store!1!id!element。
由于使用了union all操作符来连结select语句,为了保证sql查询的合法性,所有select语句的选择结果必须具有相同数量的列。我们使用null关键词来补足select语句,从而避免了重复数据。
通过explicit模式查询所生成的xml文档和通过auto模式生成的完全相同,那么为什么要创建explicit模式查询呢?
假设现在有人要求在xml文档中包含商店的打折信息。查看pubs数据库,我们得知每个商店都可以有0到n范围内的折扣率。因此,一种合理的方法是在<store>元素下面加上子元素<discount>,这样我们就得到如下xml文档结构:
<stores>
<store id=&single;&single; name=&single;&single;>
<discount type=&single;&single; lowqty=&single;&single; highqty=&single;&single;>
<amount></amount>
</discount>
<sale ordno=&single;&single; qty=&single;&single;>
</sale>
</store>
</stores>
这里的改动包括:
要在<sale>元素所在的层次增加一个xml元素<discount>,即<discount>是<stroe>的子元素。
amount嵌套在<discount>里面,但不应该是<discount>元素的属性。
在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
兵器之二: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"]