XML与SQL SERVER2005 (四)

4 篇文章 0 订阅

 第四篇旨在对路径表达式中的步骤(轴步骤 、一般步骤)详细说明。

--  本文来自happyflystone -CSDN博客,

--  转载请标明出处:http://blog.csdn.net/happyflystone

------------------------------------------------------------------------

 

1、  先说说轴

轴定义移动的方向,从上下文节点开始,导航到在轴指定的方向上可访问的那些节点。用轴步骤得用到上面一节说的全文、缩写语法及绝对、相对路径。此外假设你对此已经有了解。

下面我们介绍一下2005下的XML支持哪些轴:

Axis                                   说明

 

child                           返回上下文节点的子级

descendant                      返回上下文节点的所有后代

parent                          返回上下文节点的父级

attribute                        返回上下文节点的属性

self                            返回上下文节点本身

descendant-or-self                返回上下文节点及其所有后代

 

很显然,我们可以想像一下这些轴里除了parent 轴是向反方向的,其它全是正向,所以我们又称除了parent以外的轴是正向轴,而parent 轴是反向轴,其实我们简单点理解一下就是一个是正向向下搜索,一个是反向向上搜索。

好,下面还是以例子来说明问题:

A、下面演示用child轴操作一下查询(注意下面查询语句包括了绝对与相对路径表达式)

declare @xml xml

set @xml = '<address>

<exam>

    <name> flystone1    </name>

    <street> 1401 Main Street  </street>

    <city state="NC">Anytown</city>

<postal-code> 210000  </postal-code>

</exam>

<exam>

    <name> flystone2    </name>

    <street> 1402 Main Street  </street>

    <city state="NM">Anytown</city>

<postal-code> 210000  </postal-code>

</exam>

</address>

'

select @xml.query('/child::address/child::exam')

select @xml.query('//exam')

select @xml.query('/address/exam')

select @xml.query('address/exam')

select @xml.query('child::address/child::exam')

 

/*

--------------------------------------------------------------------

<exam><name> flystone1    </name><street> 1401 Main Street  </street><city state="NC">Anytown</city><postal-code> 210000  </postal-code></exam><exam><name> flystone2    </name><street> 1402 Main Street  </street><city state="NM">Anytown</city><postal-code>

 

(1 行受影响)

*/

B、下面看看descendant轴、descendant-or-self轴,其实后者只是比前多了上下文节点,大家看看例子就知道

 

declare @xml xml

set @xml = '<address>

<exam>

    <name>

        <firstname>fly</firstname>

        <lastname>stone1</lastname>

    </name>

    <street> 1401 Main Street  </street>

    <city state="NC">Anytown</city>

<postal-code> 210000  </postal-code>

</exam>

<exam>

    <name>

        <firstname>fly</firstname>

        <lastname>stone2</lastname>

    </name>

    <street> 1402 Main Street  </street>

    <city state="NM">Anytown</city>

<postal-code> 210000  </postal-code>

</exam>

</address>

'

select @xml.query('/child::address/child::exam/child::name/descendant::*')

select @xml.query('//./address/exam/name/descendant::*')

select @xml.query('/./address/exam/name/descendant::*')

select @xml.query('./address/exam/name/descendant::*')

select @xml.query('/address/exam/name/descendant::*')

select @xml.query('address/exam/name/descendant::*')

/*

-----------------------------------------

<firstname>fly</firstname><lastname>stone1</lastname><firstname>fly</firstname><lastname>stone2</lastname>

 

(1 行受影响)

*/

 

declare @xml xml

set @xml = '<address>

<exam>

    <name>

        <firstname>fly</firstname>

        <lastname>stone1</lastname>

    </name>

    <street> 1401 Main Street  </street>

    <city state="NC">Anytown</city>

<postal-code> 210000  </postal-code>

</exam>

<exam>

    <name>

        <firstname>fly</firstname>

        <lastname>stone2</lastname>

    </name>

    <street> 1402 Main Street  </street>

    <city state="NM">Anytown</city>

<postal-code> 210000  </postal-code>

</exam>

</address>

'

select @xml.query('/child::address/child::exam/child::name/descendant-or-self::*')

select @xml.query('//./address/exam/name/descendant-or-self::*')

select @xml.query('/./address/exam/name/descendant-or-self::*')

select @xml.query('./address/exam/name/descendant-or-self::*')

select @xml.query('/address/exam/name/descendant-or-self::*')

select @xml.query('address/exam/name/descendant-or-self::*')

/*

------------------------------------------------------------

<name><firstname>fly</firstname><lastname>stone1</lastname></name><firstname>fly</firstname><lastname>stone1</lastname><name><firstname>fly</firstname><lastname>stone2</lastname></name><firstname>fly</firstname><lastname>stone2</lastname>

 

(1 行受影响)

*/

C、下面看看parent轴的用法
declare @xml xml

set @xml = '<address>

<exam>

    <name>

        <firstname>fly</firstname>

        <lastname>stone1</lastname>

    </name>

    <street> 1401 Main Street  </street>

    <city state="NC">Anytown</city>

<postal-code> 210000  </postal-code>

</exam>

<exam>

    <name>

        <firstname>fly</firstname>

        <lastname>stone2</lastname>

    </name>

    <street> 1402 Main Street  </street>

    <city state="NM">Anytown</city>

<postal-code> 210000  </postal-code>

</exam>

</address>

'

select @xml.query('/child::address/child::exam/child::name/parent::exam')

select @xml.query('//name/parent::exam')

--先把上下文定位到name节点然后再找父节点

/*

------------------------------------------------------------------

<exam><name><firstname>fly</firstname><lastname>stone1</lastname></name><street> 1401 Main Street  </street><city state="NC">Anytown</city><postal-code> 210000  </postal-code></exam><exam><name><firstname>fly</firstname><lastname>stone2</lastname></name><street> 1402 Main Street  </street><city state="NM">Anytown</city><postal-code> 210000  </postal-code></exam>

 

(1 行受影响)

*/

 

SQL SERVER2005看到一个有意思的东东,我们来试试(里面涉及FLWOR 语句大家先跳过,以后我们再细说FLWOR

declare @xml xml

set @xml = '

<address>

    <exam id="1">

        <name>

           <firstname>fly</firstname>

           <lastname>stone1</lastname>

        </name>

        <street> 1401 Main Street  </street>

       <city state="NC">Anytown</city>

    <postal-code> 210000  </postal-code>

    </exam>

    <exam id="2">

        <name>

           <firstname>fly</firstname>

           <lastname>stone2</lastname>

        </name>

        <street> 1402 Main Street  </street>

       <city state="NM">Anytown</city>

    <postal-code> 210000  </postal-code>

    </exam>

</address>

'

select @xml.query('

for $f in /child::address/child::exam/name/child::*

  return

   <name

     id="{($f/parent::name/parent::exam/attribute::id)[1]}" >

          { $f }

   </name>

')

 

select @xml.query('

for $f in //name/child::*

  return

   <name

     id="{($f/parent::name/parent::exam/attribute::id)[1]}" >

          { $f }

   </name>

')

 

/*

------------------------------------------------------------------

<name id="1">

    <firstname>fly</firstname>

</name>

<name id="1">

    <lastname>stone1</lastname>

</name>

<name id="2">

    <firstname>fly</firstname>

</name>

<name id="2">

    <lastname>stone2</lastname>

</name>

 

(1 行受影响)

*/

请注意,在路径表达式中添加了谓词 [1],这是为了确保返回单一值。因为我们这样测试也没问题:

select @xml.query('

for $f in //name/child::*

  return

   <name

     id="{($f/parent::name/parent::exam/attribute::id)}" >

          { $f }

   </name>

')

 

2、  节点测试

节点测试是一个条件,在步骤中选定的所有节点都必须满节点名测试或节点类型测试。节点名称很好理解,就是<>内的东东,下面先说说节点类型:

节点类型

返回

示例

comment()

如果是注释节点,则返回 True

following::comment() 将选择显示在上下文节点之后的所有注释节点。

node()

无论是任何类型的节点,都返回 True

preceding::node() 将选择显示在上下文节点之前的所有节点。

processing-instruction()

如果是处理指令节点,则返回 True

self::processing instruction() 将选择上下文节点内的所有处理指令节点。

text()

如果是文本节点,则返回 True

child::text() 将选择作为上下文节点的子级的文本节点。

在节点名作测试时要注意,可以使用通配符 (*) 来指定节点的本地名称或作为其命名空间前缀。

举一个简单的例子:

declare @x xml

set @x = '

<address xmlns="ns1">

   <salutation>hello</salutation>

</address>

<address xmlns="ns2">

   <salutation>welcome</salutation>

</address>

<exam xmlns="ns1" >

    <salutation>you</salutation>

</exam>'

--注意这两个结果集

select @x.query('//*:address')—-主要匹配节点本地名称

select @x.query('declare namespace ns="ns1"; /ns:*')—主要匹配命名空间

/*

<address xmlns="ns1">

  <salutation>hello</salutation>

</address>

<address xmlns="ns2">

  <salutation>welcome</salutation>

</address>

(1 行受影响)

 

 

<address xmlns="ns1">

  <salutation>hello</salutation>

</address>

<exam xmlns="ns1">

  <salutation>you</salutation>

</exam>

 

(1 行受影响)

*/

 

以节名为测试的例子上说得太多了,下面重点说一下节点类型,比如node()是显示在上下文节点之前的所有节点,那么我们在上面介绍的通配符* ,下面我先来例子:

declare @xml xml

set @xml = '

<address>

    <exam pid ="d" id="1">

        <name>

           <firstname>fly</firstname>

           <lastname>stone1</lastname>

        </name>

        <street> 1401 Main Street  </street>

       <city state="NC">Anytown</city>

    <postal-code> 210000  </postal-code>

    </exam>

    <exam id="2">

        <name>

           <firstname>fly</firstname>

           <lastname>stone2</lastname>

        </name>

        <street> 1402 Main Street  </street>

       <city state="NM">Anytown</city>

    <postal-code> 210000  </postal-code>

    </exam>

</address>

'

select @xml.query('

for $f in /child::address/child::exam/name/child::node()

  return

   <name

     id="{($f/parent::name/parent::exam/attribute::id)}" >

          { $f }

   </name>

')

 

 

/*

--------------------------------------------------------------------

<name id="1">

  <firstname>fly</firstname>

</name>

<name id="1">

  <lastname>stone1</lastname>

</name>

<name id="2">

  <firstname>fly</firstname>

</name>

<name id="2">

  <lastname>stone2</lastname>

</name>

 

(1 行受影响)

*/

node()取代*达到和上面一样的效果。

下面再来试试text()函数:

 

declare @xml xml

set @xml = '

<address>

    <exam pid ="d" id="1">

        <name>

           <firstname>fly</firstname>

           <lastname>stone1</lastname>

        </name>

        <street> 1401 Main Street  </street>

       <city state="NC">Anytown</city>

    <postal-code> 210000  </postal-code>

    </exam>

    <exam id="2">

        <name>

           <firstname>fly</firstname>

           <lastname>stone2</lastname>

        </name>

        <street> 1402 Main Street  </street>

       <city state="NM">Anytown</city>

    <postal-code> 210000  </postal-code>

    </exam>

</address>

'

select @xml.query('/child::address/child::exam/name/child::firstname/child::text()')

select @xml.query('//name/lastname/child::text()')

/*

---------------

flyfly

 

(1 行受影响)

 

 

-------------

stone1stone2

 

(1 行受影响)

 

*/

 

最后对另两个函数分别举一个例子来说:

 

declare @xml xml

set @xml = '

<?xml-stylesheet href="flystonefriend.xsl" type="text/xsl"?>

<address>

    <exam pid ="d" id="1"><!-- step1  -->

        <name>

           <firstname>fly</firstname>

           <lastname>stone1</lastname>

        </name>

        <street> 1401 Main Street  </street>

       <city state="NC">Anytown</city>

    <postal-code> 210000  </postal-code>

    </exam>

    <exam id="2"><!-- step2 -->

        <name>

           <firstname>fly</firstname>

           <lastname>stone2</lastname>

        </name>

        <street> 1402 Main Street  </street>

       <city state="NM">Anytown</city>

    <postal-code> 210000  </postal-code>

    </exam>

</address>

'

select @xml.query('/child::address/child::exam/child::comment()')

select @xml.query('//exam/child::comment()')

 

 

 

/*

-------------------------------------------------------------------

<!-- step1  --><!-- step2 -->

 

(1 行受影响)

*/

 

select @xml.query('/child::processing-instruction()')

select @xml.query('child::processing-instruction()')

 

/*

 

------------------------------------------------------------------

<?xml-stylesheet href="flystonefriend.xsl" type="text/xsl"?>

 

(1 行受影响)

*/

 

 

 

3、  可选谓词

这一篇太长了,这个留到下回再说

 

 

 

 

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值