65.9K
CodeProject 正在变化。 阅读更多。
Home

.NET 中的 XSL 2.0 和 XQuery 1.0

starIconstarIconstarIconstarIconstarIcon

5.00/5 (11投票s)

2008年3月29日

Ms-PL

4分钟阅读

viewsIcon

147072

downloadIcon

4471

使用开源 Saxon 库,.NET 程序员可以受益于 XSL 2.0 和 XQuery 1.0。

注意:SaxonWrapper 正常工作需要下载两个部分。

引言

这个小型项目起源于我想在我的 .NET 代码中使用 XSL 2.0 和 XPath 2.0。问题是 .NET 框架默认只提供 XSL 1.0 和 XPath 1.0。据我所知,XSL 2.0 和 XPath 2.0 的唯一实现是Saxon。根据我的经验,由于 Saxon 接口和 .NET XML 接口之间存在相当大的差异,Saxon 在 .NET 社区中并没有得到广泛采用。该项目的目的是编写非常简单的接口适配器,以便 .NET 程序员能够像使用System.Xml一样使用 Saxon。

读者应该对 XML 有一定的了解。W3Schools 网站提供了关于 XSL、XPath 和 XQuery 的非常易于理解的教程。

使用 Saxon 的动机

XPath 2.0 比 XPath 1.0 更丰富、更灵活。在 XPath 2.0 中,所有内容都是序列而不是“节点集”,并且支持条件逻辑和循环。例如,以下是一个返回序列的有效 XPath 2.0 语句

for $x in /order/item return $x/price * $x/quantity

XML.com 有一篇关于XPath 2.0 的非常好的文章。这篇文章写于 2002 年初,这表明这项技术已经存在了很长时间。

XQuery 1.0 是 XPath 2.0 的扩展,是一种非常强大的查询语言。XQuery 可用于生成基于 XML 的输出以代替 XSL。事实上,编写 XQuery 比编写 XSL 要容易得多。XQuery 的主要结构是FLOWR语句。FLOWR代表“For、Let、Order by、Where、Return”,类似于 LINQ。

<pricing>
for $x in doc("NorthWind.xml")/order/item
where $x/price>

XSL 2.0 使用 XPath 2.0,而 XSL 1.0 使用 XPath 1.0。与 XSL 1.0 相比,使用 XSL 2.0 有许多好处。在 XSL 2.0 中,您可以在 XSL 中编写函数,并使用xsl:function元素在 XPath 中访问该函数。这改进了之前的情况,即您在 .NET 代码中编写 XPath 函数,最终得到平台特定的 XSL。此外,当自定义函数在 XSL 中编写时,开发周期会更快。

XSL 2.0 还使用xsl:for-each-group元素进行分组。来自 XML.com 文章的以下代码是此功能的一个很好的示例

  <xsl:for-each-group select="cities/city" group-by="@country">
    <tr>
      <td><xsl:value-of select="@country"/></td>
      <td>
        <xsl:value-of select="current-group()/@name" separator=", "/>
      </td>
      <td><xsl:value-of select="sum(current-group()/@pop)"/></td>
    </tr>
  </xsl:for-each-group>

有关 XSL 2.0 的详细信息,请访问XML.com

Using the Code

如上所述,Saxon 的 API 与 .NET 的标准 XML API 有些不同。该项目使用适配器模式解决了这个问题。类Xsl2ProcessorXQueryProcessor以类似于System.XmlXslCompiledTransform的方式向 .NET 程序员呈现 Saxon API。主要区别在于XslCompiledTransform接受IXPathNavigable作为 XML 源,而包装器接受不太通用的XmlNode。这是因为 Saxon API 使用XmlNode

代码将 Saxon 及其相关的库作为名为SaxonWrappers的 Visual Studio 项目集成。有两种使用方法。第一种是将SaxonWrappers项目添加到您的解决方案中。这允许您自定义包装器。或者,您可以引用 zip 文件根目录中的所有程序集。确保saxon9api.netmodule文件与 DLL 文件位于同一目录中。

以下代码对books.xml执行books.xsl的 XSL 2.0 转换,并将生成的输出写入books.html。输入文件包含在下载文件中。

using (StreamWriter streamWriter = 
       new StreamWriter("books.html", false, Encoding.UTF8))
{            
    // Load the input doc
    XmlDocument xmlDoc = new XmlDocument();
    xmlDoc.Load("books.xml");

    // Create the output XmlWriter
    XmlTextWriter xmlWriter = new XmlTextWriter(streamWriter);

    // Do the transformation
    Xsl2Processor processor = new Xsl2Processor();
    processor.Load("books.xsl");
    processor.Transform(xmlDoc, xmlWriter);
}

以下代码对books.xml执行books-to-html.xq中的 XQuery 1.0,并将生成的输出写入books_xq.html。输入文件包含在下载文件中。

using (StreamWriter streamWriter = 
       new StreamWriter("books_xq.html", false, Encoding.UTF8))
{
    // Load the input doc
    XmlDocument xmlDoc = new XmlDocument();
    xmlDoc.Load("books.xml");

    // Create the output XmlWriter
    XmlTextWriter xmlWriter = new XmlTextWriter(streamWriter);

    // Do the transformation
    XQueryProcessor xp = new XQueryProcessor();
    xp.LoadFromFile("books-to-html.xq");
    xp.RunQuery(xmlDoc, xmlWriter);    
}

XQueryProcessor类还有一个Load方法,用于从string加载 XQuery 语句。

更多关于 Saxon、Java 和 .NET 的信息

Saxon 由 Michael Kay 编写和维护,他也是XSL 2.0标准的编辑者。Saxon是用Java编写的,Michael 使用IKVM使这项工作可用于 .NET。Saxon 使用 IKVM 编译的 GNU Class Path 连接到 Java 核心库。所有这些库都在宽松的开源许可下可用,包括 Saxon,它在 Mozilla 公共许可下。

延伸阅读

历史

  • 2008 年 3 月 25 日 - 首次发布
© . All rights reserved.