- 易迪拓培训,专注于微波、射频、天线设计工程师的培养
XQJ解析 用于XQuery查询的Java API
查询是用于查询XML的声明性语言,类似于用于查询关系数据的SQL。大部分Java程序员熟悉JDBC,它提供了标准的Java API来和各种关系数据库的SQL引擎进行交互。XQJ具有相同的目的:它向Java程序员提供了标准的Java API用于和各种XML数据源的XQuery引擎进行交互。
XQJ也被称为JSR 255,因为它是由Java Community Process设计的。这个JSR 255规范定义了接口和Class集合,用于Java应用能够向一个XQuery引擎对一个或者多个XML数据源提交XQuery查询和使用查询结果。这篇文章通过给出基本的用况(use-case)来提供对XQJ的介绍,并且讨论了作为XQuery基础的XQJ中的几个关键的接口。此外,这篇文章强调了XQL和JDBC之间的不同之处。
对那些熟悉JDBC的程序员而言比较幸运的是,XQJ遵守了几个熟悉的模式。执行一个查询的典型编码顺序——获得连接(connection),准备XQuery表达式,在已经准备好的XQuery表达式中的值和变量绑定起来,执行表达式,使用XQuery结果并且清理资源——是和JDBC的次序基本一致。然而,XQuery中的几个关键概念要求创建XQJ中的专用接口,比如static context、dynamic context、XQuery data model和XQuery Sequence Type。进一步,在XQuery数据模型中一个主要元素是XML node。XQJ需要和现有的XML节点操作API如DOM、SAX和StAX等相结合。XQuery允许节点通过XMLSchema定义类型。XQJ通过XQuery Sequence Type接口定义和XMLSchema的关系。
一个简单的例子
下面是简单的、使用XQJ来执行查询的代码示例,演示了典型的使用情况。注意为了简单起见,错误处理已经被忽略了。
// obtain an XQDataSource instance XQDataSource xqds = (XQDataSource) Class.forName("com.jsr225.xqj").newInstance(); // obtain a connection XQConnection con = xqds.getConnection("usr", "passwd"); // prepare an XQuery Expression String xqry = "for $i in fn:collection('dept') " + "where $i/deptname = %dname return count($i/employees)"; XQPreparedExpression expr = con,preparedExpression(xqry); // bind variable with value expr.bindString(new Qname("dname"), "engineering"); // execute the XQuery Expression XQResultSequence rs = expr.executeQuery(); // Consume results while (rs.next()) { System.out.printLn(rs.getInt()); } // clean up resources rs.close(); con.close(); |
在上面的例子中,XQDataSource是你用来获得XQuery连接的接口。你可以通过典型的数据源实例化机制,比如JNDI查询或者显式的类装载方法来创建XQDataSource 接口初始实现类。这类似于JDBC的DataSource和Connection接口的设计。
在获得了XQConnection之后,你可以通过XQExpression或者XQPreparedExpression接口来执行XQuery。假如你只执行XQuery表达式一次,那么你应该使用XQExpression,并且如果你要准备XQuery表达式一次而使用不同的绑定值来多次执行这个表达式,像在前面的例子中那样,那么你应该使用XQPreparedExpression。这两个接口分别类似于JDBC中的Statement和PreparedStatement概念。
XQuery结果是XQuery数据模型的一个实例。在例子中显示的XQResultSequence提供了以光标为中心的接口,允许用户在结果的sequence中迭代每一个元素。用户可以从每个元素获得值,或者是原子数值或者XML节点。这类似于JDBC结果集中的迭代。
在使用完XQuery结果之后,程序员需要对XQResultSequence和XQConnection接口调用close()方法来清理这些资源。合理的用于释放资源的错误处理代码对避免资源泄露非常关键。在sequence结果关闭的时候,这个框架隐含的关闭从sequence结果中创建的元素。类似的,在连接被关闭的时候,这个sequence结果也被隐含的关闭了。
XQuery上下文(Context)的支持
XQuery有双重的"上下文"概念:静态的上下文和动态的上下文。XQJ提供了XQStaticContext和XQDynamicContext接口来为它们建模。XQStaticContext提供了方法检索定义在XQuery静态上下文中的信息,比如base URI、the boundary-space policy等等,允许应用检索关于全局静态上下文中的信息。比如,XQConnection接口扩展了XQStaticContext接口。
相比之下,XQDynamicContext接口让应用检索关于动态上下文的信息,并且改变这些信息。尤其,它提供方法绑定XQuery变量到各种数值,这些变量是动态上下文的一部分。XQPreparedExpression和XQExpression接口都扩展XQDynamicContext。上面的例子可以对XQPreparedExpression调用bindString()方法,因为bindString()是基类的XQDynamicContext接口中定义的方法。
和JDBC不同的是由于绑定到XQuery变量的值不一定是简单的标量值,XQDynamicContext中的bindXXX()方法可以有一种延迟绑定模式(deferred binding mode)。在延迟绑定模式中,这个绑定的数值可能直到XQuery处理器真正的访问了该变量才会被使用,这让XQJ潜在的使用基于流水线的惰性数值赋值模型。
XQuery数据模型的支持
再次,XQuery的结果是XQuery数据模型的一个实例,它由XQuery元素的序列组成。每个元素可以是原子数值或者XML节点(文档, 元素, 属性, 注释, 处理指令, 或者文本)。XQSequence接口建模XQuery数据模型。它包含零个或者多个XQItem接口对象。XQItem接口代表了XQuery 数据模型中的元素。程序员通过调用XQSequence.getItem()或XQConnection.createItem()方法获得XQItem 。
虽然XQItem和XQSequence代表了独立于XQuery结果的XQuery的元素和序列,XQResultItem和XQResultSequence(分别扩展了XQItem和XQSequence)代表了从XQuery执行结果中得到的XQuery元素和序列。
如果XQItem是原子数值,你可以使用某种getXXX()方法将它转换到对应的Java数据类型,这些方法包括getInt()、getString()等等。假如XQItem是XML节点,你可以通过已有的XML节点操作接口访问它,这些接口包括DOM、SAX或者StAX。XQItem和XQSequence都扩展了XQItemAccessor接口,该接口定义了各种元素访问方法。比如,getNode()方法返回了DOM节点。writeItemToSAX()方法通过将序列顺序化为SAX事件来产生SAX事件。getItemAsStream()方法将序列顺序化为XMLStreamReader事件流。进一步,XQJ定义了一套进行Java数据类型和XQuery数据类型之间的标准映射,来辅助将标准的Java类型绑定到XQuery变量。
XQuery类型系统的支持
XQuery有类型——并且还有支持它们的接口。XQSequenceType和XQItemType接口允许用户使用XQuery类型系统。XQSequenceType接口代表了XQuery中定义的序列类型(sequence ),而XQItemType接口代表了XQuery中定义的元素类型(item type) 。XQItemType扩展了XQSequenceType 但是将出现次数限制为1。XQItem接口包含了获得关于XQuery元素类型信息的方法,比如元素类型、基础类型、节点名(如果有的话)、节点类型名(如果有的话)以及和类型有联系的任何XML Schema URI。
XQJ给予了实现很大的自由处理XML模式类型。因为XQJ被设计为能够和各种XQuery引擎协同工作,你不能为XQJ的实现和底层的XQuery引擎之间假设任何特定的关系。因此你不能假设某个XQJ的时间和XQuery引擎会共享相同的XML模式仓储。为了解决这个问题,XQJ API使用叫做isUserDefinedXMLSchemaTypeSupported()的XQMetaData方法来判断是否XQJ的实现可以回答关于对XML模式依赖的问题。对于紧耦合的系统,XQuery引擎和XQJ实现共享了相同的XML模式仓储,isUserDefinedXMLSchemaTypeSupported 就会返回ture,对于松耦合的系统,这个值被设为false。
使用XQMetaData
XQMetaData接口为用户提供了关于底层XQJ和XQuery实现的额外的信息。它包含方法查询某些特定的XQuery的功能,比如StaticTypingFeature和SchemaImportFeature,是否被支持。它还提供了关于数据源的通用信息。XQMetaData接口为XQJ用户起到了可移植层的作用。这类似于JDBC中的DatabaseMetaData接口。
未来的发展方向
随着SQL/XML成为标准,程序员将能够在SQL中嵌入和执行XQuery——这样JDBC最终会支持XQuery。但是,我们相信XQJ仍然是必要的,由于不是所有的需要XQJ的XQuery处理器都支持SQL和SQL/XML。进一步,XQJ已经定义了一些重要的接口(上面已提到)来建模XQuery中的关键概念,以及经典的XML Java接口,比如DOM、SAX和StaX。当JDBC最终支持SQL/XML 2006,它让SQL调用XQuery,这些XQJ接口会被使用。潜在的集成点是让JDBC XMLType支持一个使用XQJ定义的接口来创建XQuery数据模型。
这篇文章对XQJ(XQuery Java API)进行了简要的介绍,并且讨论了一些为XQuery中的关键概念进行建模的接口。如同JDBC在关系数据库中的成功,我们相信XQJ会成为对XML数据源的XQuery引擎进行交互中最广泛使用的Java API.
上一篇:换个角度解决内容管理的问题
下一篇:数据库归档要考虑的四大问题