本专栏文章介绍了 XML Query(也称为 XQuery)工作草案的当前状态。Kevin Williams 演示了如何使用 FLWR(“flower”)子句,介绍了 distinct-values 函数(该函数被使用于透视数据关系)并就 XQuery 将如何影响数据文档操作给出了他的评价。XQuery 和 XML 的样本代码演示了 for、let、where 和 return(FLWR)子句的用法。
假如您曾经尝试过使用 XSL 进行任何形式的复杂数据操作(例如连接两个元素集、透视关系或者甚至相对简单的数学计算),那么您就知道它在数据操作的特性方面稍微欠缺了一点。要解决这个问题,样式表作者们不得不使用书上的每种诀窍 ? 将多个样式表链接在一起、对 xsl:for-each 运算符进行很深的嵌套以及编写令 Perl 专家都头痛的语法烦琐的代码。不用担心,马上就会得到帮助。即将于 2002 年夏季发布的 XQuery 规范将解决所有这些问题以及更多其它问题。
那么什么是 XML Query?
XML Query,通常缩写为 XQuery,是一种已经以这样或那样的方式存在几年的规范。XML Query 工作组在 1999 年 9 月正式成立,任务是创建一种灵活的查询语言来从 XML 文档中抽取数据。最新的工作草案(请参阅参考资料)对实现这个目标大有帮助。
XQuery 构建在 XPath 规范之上。事实上,XQuery 的一些特性已公认为是非常基本的,以致于它们已被合并入 XPath 2.0 规范中,而且这个规范目前为 W3C 的 XML Query 和 XSL 工作组共同拥有。这是个好消息,因为它意味着样式表作者们将很快就能利用象序列、量化和更强有力的类型控制这样的特性。同样,已将条件表达式和迭代器添加到了 XPath 语言中,而在以前它们是 XSL 语言的一部分。这样就可以在样式表中编写更清楚的代码,并且为样式表创建者带来较少的麻烦。
FLWR 表达式
XQuery 中最强大的新特性是 FLWR 表达式。FLWR(发音为 flower)是 For-Let-Where-Return 的首字母缩略词,这些子句都答应在这些表达式的任何一个中。FLWR 表达式可以完成很多您在 XSL 样式表中做梦都别想完成的任务。
每个 FLWR 表达式都有一个或多个 for 子句、一个或多个 let 子句、一个可选的 where 子句以及一个 return 子句。
for 子句
如清单 1 所示,使用 for 子句来指定一组笛卡尔元组,表达式的其余部分将对该元组求值。通过为这些笛卡尔组选定次序来控制求值的次序。
清单 1. 单个 for 子句 for $exp1 in (, )
运行的程序将对清单 1 中的表达式进行二次求值,其中 $exp 变量分别被设置为 和 。假如引入了另一个 for 表达式,那么这个程序将对笛卡尔积求值。看一下清单 2 中的示例,其中使用了多个 for 子句。
清单 2. 多个 for 子句
for $exp1 in (, )
for $exp2 in (, )
在清单 2 中,程序将对表达式进行四次求值,每次对一个元组求值:
(, )
(, )
(, )
(, )
let 子句
let 子句为一个变量赋一个值或一个序列。在 where 或 return 子句中,这可能是非常有用的简写。
where 和 return 子句
假如特定的元组不能满足非凡条件,那么 where 子句命令程序废弃这些元组。return 子句定义每个元组要返回的内容。
在本示例中,查询返回了文档中已编写了多于三本书的所有作者的名字。它以一个示例文档开始,表达式对该示例文档进行操作,如清单 3 所示。
清单 3. 示例文档 authorList.xml
Professional XML, 2nd Edition
Professional XML Databases
Professional XML Schemas
Esoteric Topics in Programming, Vol. 1
Esoteric Topics in Programming, Vol. 2
对 authorList.xml 文档进行操作的查询如清单 4 所示。
清单 4. 选择编写了多于三本书的作者的样本查询
{
let $inDoc := document("authors.xml")
for $author in ($inDoc//author)
let $cb := count($author/book)
where ($cb >= 3)
return
$author/@name
}
清单 4 中的 XQuery 将返回清单 5 中的内容。
清单 5. 对多产作者查询的结果
Kevin Williams
distinct-values 函数
XQuery 还引入了一个在执行数据操作时会给您带来很多方便的函数:distinct-values 函数(在 XPath 2.0 中也有)。这个函数答应您方便地透视文档中的关系。例如,假设您有一个您的软件公司的客户和他们已购产品的列表,如清单 6 所示。
清单 6. 样本客户数据,customerList.xml
假如您想将这个文档转换为一个列出所有产品以及每个产品的客户列表的文档,那么您手头可有活干了。完成这样的工作是可能的,但是编码却非常烦琐。而通过使用 XQuery,问题就变得非常简单,如清单 7 所示。
清单 7. 透视客户-产品关系的代码
{
let $inDoc := document("customerList.xml")
for $product in distinct-values("$input//customer/product/@name)
return
{
for $customer in $input//customer
where $customer/product/@name = $product
return
}
}
清单 7 将产生清单 8 所示的输出。
清单 8. 转换代码的结果
强大、易于使用和易于理解:XQuery 使那种数据操作变得简单。
应该何时使用 XQuery?
何时开始使用 XQuery 才是明智的取决于您何时阅读本专栏以及您是否十分渴望开始使用一种新规范。到 2002 ?2 月为止,这个规范还处于“工作草案(Working Draft)”状态,这意味着从现在开始到它发行的这段时间内,可能还会对它进行重大的更改。一旦它进入“推荐的建议书(Proposed Recommendation)”状态,通常就认为它很稳定,足以经受考验了 ? 事实上,W3C 鼓励开发人员在这时使用各种规范,那么当新规范进入“建议书(Recommendation)”状态之前,可以获取反馈信息,从而进一步修改规范,使之更趋完善。假如您认为该规范将带来非常多的好处,以致于当它一进入“推荐的建议书”状态,您就想尝试使用它,那么 2002 年春季将是了解这个规范的好时机。
无论何时您觉得 XQuery 对您来说可能是个可行的解决方案时,您都应当记住以下几条准则,以判定 XQuery 何时应该成为您解决方案的一个适当部分。
首先,XQuery 不是一粒魔弹。尽管依照句法来说,它在数据操作上比 XSL 要好用得多(它还支持许多 XSL 不直接支持的操作),但是其底层的引擎还是必须读取每篇文档、解析它,然后使用查询语言对它操作。因此,对于已建立索引的文档资源库(即所谓的 XML“数据库”),XQuery 是快速访问文档具体内容的好的解决方案,但是对于未建立索引的文档,它不是一个好的解决方案。
其次,XQuery 包含一些用来访问资源库中多个文档的机制。这个文档函数答应您以编程方式在同一个查询中访问多个文档。但是,相同的问题出现了:您仍需要装入并解析每个文档。因此,要达到最佳性能,您最好还是使用 XML 数据库或一些其它形式的索引模型。
最后,XQuery 最擅优点理“混合”文档 ? 同时包含叙述流和量化数据的文档。例如,一个医疗记录文档可能包含手术期间外科医生操作的描述,以及手术期间使用的药物、血和其它物品的数量。该文档不适合存储在关系型数据库中,但是,XQuery 却非常擅长此道,它能直接从该 XML 文档中抽取出量化信息。但是,假如您的文档是纯数据,那么将该文档引入到关系型数据库中进行操作会更有意义。
结束语
XQuery 为 XML 文档中的数据操作提供了一种强大的语法。它最适合于那些同时包含叙述性文本和量化数据的文档。在对这些类型的文档上使用 XQuery 时,为达到最佳性能,可以将这些文档装入一些已建立索引的 XML 资源库中。
W3C 是否会在夏季发布规范还有待观察;目前有许多未解决的重大问题,包括在 XPath 2.0 表达式中是否应该有保留字。几乎可以肯定的是,解决这些问题是要花一些时间的。但是,现在知道了对文档的需求可以使您在这种技术广泛可用时,最大程度地利用这种技术。