XQuery 和 XQuery 函数
这个小节花点时间回顾 XQuery,并简单介绍如何使用 XQuery 函数。
XQuery 快速回顾
这很简单:XQuery 之于 XML 文档犹如 Structured Query Language(SQL)之于关系数据库。XQuery 使开发人员能够使用表达式从 XML 文档提取数据。可以提取的数据包括简单的值或文档的整个子树,比如一个元素及其所有子元素。
为了实现这个目标,XQuery 需要使用 XPath 表达式。这涉及到著名的 FLWOR 表达式:for、let、where、order by 和 return。这些表达式为从 XML 文档提取和返回数据提供强大的方法。
该语言的语法基于 XML 文档本身的树状结构。XQuery 能够感知处理指令、属性和元素。
注意,要使 XQuery 能够正确地处理 XML 文档,查询不一定是有效的,但它必须 具有良好的结构。记住,具有良好结构的 XML 文档意味着它遵循 W3C 的 XML 标准(参见 参考资料)。当一个 XML 文档遵循它自身的文档类型定义(Document Type Definition,DTD)或模式时,它就是有效的。
要获得关于 XQuery 的详细解释,请参阅 参考资料。
什么是 XQuery 函数
仍然使用关系数据库作为类比,XQuery 与 XML 文档的关系,就像存储过程和关系数据库的关系。那就是,它们都是其他表达式可以调用的用户自定义的例程。对于喜欢使用 Java 的人员,XQuery 函数就像实用程序类中的一个方法,它是静态声明的,但可以公开使用。
看看 清单 1 中的 XQuery 函数,我将解释它的各个部分。为了方便理解,我现在使用的函数也用于后面的模拟 eCommerce 环境中。
清单 1. XQuery 函数
declare function local:calculateReceivedIn($delay as xs:integer)
{
let $receivedIn := ($delay + $shippingDelay)
return ($receivedIn)
};
|
这是一个非常基础的函数,但能够在 eCommerce 应用程序中很好地工作。它主要添加了两个值,一个作为该函数的参数,另一个是整个模块的独特变量。以后还会对此进行论述。
首先,要注意函数的声明。这可以通过两个词很直观地实现:declare function。这将通知 XQuery 处理程序所声明的是函数,而不是表达式。
其次,函数的名称分为两部分:local:calculateReceivedIn。冒号前面的部分(local)是名称空间,并且遵循使用名称空间的 XML 标准。在本例中,使用的是 local。一个具有行业强度的应用程序可能拥有几个模块,并且 XQuery 函数将使用特定于这些模块的名称空间。函数名称的另一部分就是:函数名。在本例中是 calculateReceivedIn,因为它计算在输出结果的 “Received in X days” 部分中显示的数字。
接下来便是参数的声明。通常,圆括号中的参数紧接着函数名。参数名以美元符号($)开始。这是标准的 XQuery 实践。注意,您还定义了参数的类型。在本例中,参数的类型为整数,因此将其定义为 as xs:integer。熟悉 XML Schema 规范的人员能够认出这种数据类型的语法。要获得完整的数据类型列表,请参见 参考资料。
然后,您将开始学习函数的工作部件。它包含在大括号中,并且使用标准的 XQuery 表达式。它从计算 receivedIn 开始。这通过使用 let 表达式(let 是首字母缩写词 FLWOR 中的 L)来实现。在这里,您只是声明 receivedIn 等于 delay 和 shippingDelay 之和。记住,shippingDelay 是一个全局性变量。在这里它不能声明为参数,因为它已经在前面的 XQuery 模块中声明。此示例会清楚地说明这点。
那么如何调用 XQuery 函数呢?看看 清单 2,考虑来自 XQuery 表达式的代码片段。
清单 2. 调用 XQuery 函数
{local:calculateReceivedIn($minnow/availability/shipping/delay)}
|
这是 XML 文档的一部分。在虚构的 eCommerce 应用程序中,XML 文档被返回给应用程序,然后用于向用户显示信息。要计算这个产品(在这个例子中是一种鱼饵,形状像米诺鱼)的运输延误,需要在大括号内部调用该函数。使用完全限定的名称(包括名称和空间名),并传入从 XML 文档获取的值。这里的值来自 <delay> 元素,它必须是一个整数,否则 XQuery 会拒绝它。注意,必须使用标准的 XQueryote 表达式来获取参数的值。然后该函数从 XML 文档的 <delay> 元素接收这个值,并将其添加到 $shippingDelay 的值。它将返回这两个数值之和,如清单 2 的输出结果所示。
XQuery 函数的优点
使用 XQuery 函数有很多优点。首先,XQuery 表达式本身就是可读性很强的。看一看 清单 3。
清单 3. 没有函数的 XQuery 表达式
<shipping-info>
<received-in>
{$minnow/availability/shipping/delay/_cnnew1@unit}
{
let $delay := $minnow/availability/shipping/delay
let $receivedIn := ($delay + $shippingDelay)
return ($receivedIn)
}
</received-in>
</shipping-info>
|
实际上,清单 3 展示了关于运输信息的整个 XML 子树。计算 $receivedIn 的 XQuery 表达式处于中间的位置,它代替了 清单 1 中的 XQuery 函数。如上所示,没有这个函数之后,这段代码显得复杂一些,并且对于不熟悉该代码的人而言,解析它的时间也要长些。如果 XQuery 函数要执行更加复杂的工作,这段代码的可读性则会更差。
XQuery 函数的另一个优点是关注点分离功能。这个函数使开发人员能够在数据返回之前定义如何操作或处理数据,同时又可以使用 XQuery 表达式的主体部分查找函数需要处理的数据。
XQuery 表达式的最后一个优点是可重用性。在这个例子中,您可以根据一般的运输延迟和用户的地理位置定义一个函数,用于计算某一物品到达用户手中所需的时间长度。再看一看修改后的 清单 3。如果您为每个类型的物品定义了以上函数,并且添加了计算时间长度的逻辑,您则需要在整个 XQuery 表达式过程中反复执行这个操作。不过,在一个函数中定义逻辑使您能够在其他表达式中重用该逻辑。如果逻辑发生改变,您仅需在该函数内部更改它。
|