IBM®
跳转到主要内容
    中国 [选择]    使用条款
 
 
Select a scope: Search for:    
    首页    产品    服务与解决方案     支持与下载    个性化服务    
跳转到主要内容

developerWorks 中国  >  XML  >

用于数据的 XML: XPath 2.0 有哪些新特性?

对 XPath 2.0 计划采用的一些特性的前瞻

developerWorks
文档选项

未显示需要 JavaScript 的文档选项


级别: 初级

Kevin Williams (kevin@blueoxide.com), CTO, Blue Oxide Technologies,LLC

2003 年 1 月 01 日

专栏图标Kevin Williams 研究了 XPath 2.0 规范的最新状态,并且提供了一些 XPath 2.0 特性的特定示例,这些特性会使 XML 开发人员的工作更加轻松。示例是用 XML 和 XPath 的形式提供的。

XSLT 1.0 和 XPath 1.0 最初是打算为 XML 文档提供简单的样式语言支持,主要是将这些文档转换成 HTML 以呈现在浏览器中。但是,自从 XSLT 和 XPath 可以使用之后,它们就被强行用于各种任务中,而这些任务 ― 从 XML 文档中复杂的数据操作(聚合、单值选择和关系旋转)到一种 XML 形式向另一种形式的 XSLT 转换 ― 并不是它们的设计初衷。在这些规范的版本 2.0 中,W3C 试图使 XSLT 和 XPath 更加灵活和健壮,以便于处理这些技术的新用法。

在上一篇专栏文章中,我研究了 XSLT 的一些新特性。在本篇专栏文章中,我只研究 XPath2.0 的几个要点 ― 由于要点太多,因而无法在一篇专栏文章中全部研究。

对于本专栏而言,特定前缀的映射含义如下:

  • xf: 前缀被认为映射到 XPath 2.0 函数名称空间(http://www.w3.org/2002/08/xquery-functions)。
  • xsl: 前缀映射到 XSLT 2.0 名称空间。
  • xs: 前缀映射到 XML 模式名称空间。

xf:distinct-values 函数

在使用 XSLT 1.0 样式表时,开发人员面临的最重大的挑战之一就是编写与 SQL 中 SELECT DISTINCT 等同功能的 XML 代码 ― 即一个获取节点集并返回那些节点唯一值列表的表达式。在 XSLT 1.0 和 XPath 1.0 中这不是不可能实现的,但都是极其困难的。基本上,您都必须写一条 xsl:for-each 语句以特殊的排序顺序对每个节点求值,然后不断回头查看节点列表,以了解是否所有匹配特定值的任何其它节点都被处理了。有了 XSLT 2.0 ,以及引入了 xf:distinct-values 函数,这个问题就迎刃而解了。下面 清单 1中是一个 XML 文档的快速示例:


清单 1. 带有作者姓名的 books
<books>
  <book author="Kevin Williams" title="Professional XML 2.0" />
  <book author="Lewis Carroll" title="Alice in Wonderland" />
  <book author="Lewis Carroll" title="Through the Looking-Glass" />
</books>

假定您想要标准化输出作者信息,并创建一个类似 清单 2的文档:


清单 2. 带有书名的 authors
<authors>
  <author name="Kevin Williams">
    <book title="Professional XML 2.0" />
  </author>
  <author name="Lewis Carroll">
    <book title="Alice in Wonderland" />
    <book title="Through the Looking-Glass" />
  </author>
</authors>

要做到这一点,使用 XPath 和 XSLT 1.0 时,需要做类似于 清单 3的工作:


清单 3. XPath 1.0 中的 SELECT DISTINCT
<xsl:template match="books">
  <authors>
    <xsl:for-each select="book">
      <xsl:sort select="@author" />
      <xsl:variable name="thisAuthor">
        <xsl:value-of select="@author" />
      </xsl:variable>
      <xsl:if test="count(preceding-sibling::book)=0">
        <author name="{$thisAuthor}">
          <xsl:for-each select="../book[@author=$thisAuthor]">
            <book title="{@title}" />
          </xsl:for-each>
        </author>
      </xsl:if>
      <xsl:if test="preceding-sibling::book[1]/@author != $thisAuthor">
        <author name="{$thisAuthor}">
          <xsl:for-each select="../book[@author=$thisAuthor]">
            <book title="{@title}" />
          </xsl:for-each>
        </author>
      </xsl:if>
      </xsl:for-each>
    </authors>
</xsl:template>

记录文档的过程稍微有点凌乱和困难,但是使用 xf:distinct ,这会变的很容易,如 清单 4所示:


清单 4. XPath 2.0 中的 xf:distinct
<xsl:template match="books">
  <authors>
    <xsl:for-each select="xf:distinct(book/@author)">
      <xsl:variable name="thisAuthor"><xsl:value-of select=".">
      <author name="{$thisAuthor}">
        <xsl:for-each select="book[@author=$thisAuthor]">
          <book title="{@title}" />
        </xsl:for-each>
      </author>
    </xsl:for-each>
  </authors>
</xsl:template>

这与 xsl:for-each-group 有什么区别呢?任何实现 XPath 的地方都可以使用 xf:distinct ― 因此,它可以作为 XQuery 1.0 的一部分及专门的 XPath 处理器使用。利用 xf:distinct ,可以在值集合上执行其它操作,这与 xsl:for-each-group 相反,后者强制对不同的值单独进行操作。

这一变化解决了 XSLT 作者在试图样式化文档时遇到的许多问题。XSLT 还有许多其它变化,样式表程序员会发现它们非常有用。





回页首


xf:document 函数

在 XSLT 1.0 中使用多个文档是有问题的。XPath 2.0 的设计人员明智地选择了通过 xf:document 机制来包括额外的文档处理能力。该函数允许从 URL 装入一个或多个文档,并进行处理。例如,假定您在资源库中拥有 清单 5、6 和 7中所示的文档类型:


清单 5. 样本零件文档 1
<part name="Grommets" size="3 in." color="blue" />



清单 6. 样本零件文档 2
<part name="Grommets" size="3 in." color="blue" />



清单 7. 样本零件文档 3
<part name="Grommets" size="3 in." color="blue" />

假定您现在在一个目录中有 500 个这样的文档,您希望创建您所拥有的所有蓝色零件的列表。无需利用中间层语言(如 Java)编写代码以装入所有这些文档并查找颜色为蓝色的零件,可以编写一个列出在哪可以找到所有零件的索引(请参阅 清单 8):


清单 8. 零件索引文档
<parts>
  <part file="part1.doc" />
  <part file="part2.doc" />
  <part file="part3.doc" />
</parts>

您可以编写一个为您完成这项工作的样式表,其代码片段类似于 清单 9


清单 9. 用于跨文档的 xf:document
<xsl:template match="parts">
  <blueParts>
    <xsl:for-each select="xf:document(part/@file)/@color='blue'">
      <part name={@name} size={@size} color={@color} />
    </xsl:for-each>
  </blueParts>
</xsl:template>

这种技术特别适用于分布式网络的内容,在分布式网络中,零件信息可以放在一台服务器上,而客户信息可以放在另一台服务器上。通过利用样式表(使用 xf:document 从其它 URL“拉”信息),允许该数据可以在创建它的地方起作用。





回页首


xf:current-dateTime 函数

将样式表应用于 XML 文档时,在输出中包含已转换结果的创建日期通常都很有用。当创建 HTML 文档以驱动用户界面时,这特别重要;此类信息可以帮助高速缓存系统知道什么时候信息的副本失效了。使用 XPath 2.0 中的 xf:current-dateTime 函数可以获得当前日期和时间(请参阅 清单 10):


清单 10. xf:current-dateTime 示例
<xsl:value-of select="xf:current-dateTime()" />

这可能会返回 清单 11中所示的字符串:


清单 11. xf:current-dateTime 样本结果
2002-09-17T18:22:08z

然后,可以“按现状”使用该字符串,或者将其转换成不同的日期格式,以便于在生成的文档中使用。





回页首


更佳的 XML 模式兼容性

因为 XPath 2.0 目前在 XSLT 2.0 和 XQuery 1.0 之间共享,因此,XPath 需要更健壮的 XML 模式支持。实际上,XPath 2.0 中的整个数据模型目前都是强类型的:而不是简单的字符串、数字和布尔类型,值目前使用了作为 XML 模式规范一部分定义的原语。提供了完整的函数集,因此可以把这些值显式地从一种类型转换为另一种类型,将这种转换作为它们在 XPath 2.0 中操作的一部分。例如,通过使用类型名称可以将一个值强制转换为另一种类型,就象是一个函数一样。因此,使用 清单 12中的代码片段,可以将值强制转换为无符号整数:


清单 12. XML 模式类型强制转换示例
xs:unsignedInt(item)

XPath 2.0 中的强类型确保由 XSLT 样式表创建的文档能够依据强类型的 XML 模式进行验证。在 XSLT 2.0 之前,没有方法可以保证这一点(例如,保证数字是无符号整数)― 为了确保样式表不提供错误值,XML 模式验证步骤是必需的。

在本文中,我只是略微谈及了 XPath 2.0 必须提供的一些要点。虽然距离这项技术提升为建议书状态还有一段时日(至少 6 个月),但是,熟悉 XPath 2.0 的特性和功能将有助于您在开始实现时能够充分利用它。



参考资料



关于作者

Kevin Williams Blue Oxide Technologies,LLC 的技术主管(CTO),该公司从事 XML 和 XML Web 服务设计软件的设计业务。请访问该公司的网站 http://www.blueoxide.com。可以通过 kevin@blueoxide.com向 Kevin 提出意见。




对本文的评价










回页首


IBM 公司保留在 developerWorks 网站上发表的内容的著作权。未经IBM公司或原始作者的书面明确许可,请勿转载。如果您希望转载,请通过 提交转载请求表单 联系我们的编辑团队。
    关于 IBM 隐私条约 联系 IBM 使用条款