跳转到内容

XQuery/XQuery 和 XSLT

来自 Wikibooks,开放世界中的开放书籍

您想创建一个执行 XSLT 转换的 XML 文档的 RESTful Web 服务。

XQuery 在许多方面优于 XSLT。XQuery 被设计成一种简短而简洁的编程语言,它将 XML 和函数式语言语句交织在一起。因此,XQuery 程序通常比 XSLT 小得多。XQuery 处理器还被设计为使用索引,以便对大型数据集执行 XQuery 可以快速运行。但不幸的是,仍然有一些时候您必须使用 XSLT。其中一个例子是在浏览器中的转换。eXist 数据库附带一个 XQuery 函数,允许您使用 XSLT 转换 XML 文件。

创建 XSLT 服务

[编辑 | 编辑源代码]

eXist 包含一个函数来调用 XSLT 转换,如下所示

  transform:transform($input as node()?, $stylesheet as item(), $params as node()?) node()?

其中

  $input is the node tree to be transformed
  $stylesheet  is either a URI or a node to be transformed.  If it is an URI, it can either point to an external 
   location or to an XSL stored in the db by using the 'xmldb:' scheme.
  $params are the optional XSLT name/value parameters with the following structure:
  <parameters>
     <param name="param-name1" value="param-value1"/>
  </parameters>

结果为零个或一个节点。转换模块的命名空间为 http://exist-db.org/xquery/transform

transform:transform() 函数可用于提供一项服务,该服务接受 XML 文件的 URL、XSLT 脚本的 URL 以及传递给样式表的任何其他参数。

目前输出为 text/html。

declare option exist:serialize "method=html media-type=text/html";

(: look for URL parameters for the XML file and the transform :)
let $xslt:= request:get-parameter("xslt",())
let $xml := request:get-parameter("xml",())

(: now get a list of all the URL parameters that are not either xml= or xslt= :)
let $params := 
<parameters>
   {for $p in request:parameter-names()
    let $val := request:get-parameter($p,())
    where  not($p = ("xml","xslt"))
    return
       <param name="{$p}"  value="{$val}"/>
   }
</parameters>

return 
  (: now run the transform :)
  transform:transform(doc($xml), doc($xslt), $params)

检查 XSLT 版本

[编辑 | 编辑源代码]

以下 XSLT 有助于检查您正在运行的 XSLT 版本。

<xsl:stylesheet version="1.0"
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
   <html>
      <body>
         <p>Version:
         <xsl:value-of select="system-property('xsl:version')" />
         <br />
         Vendor:
         <xsl:value-of select="system-property('xsl:vendor')" />
         <br />
         Vendor URL:
         <xsl:value-of select="system-property('xsl:vendor-url')" />
         </p>
      </body>
   </html>
</xsl:template>

</xsl:stylesheet>
[编辑 | 编辑源代码]

在此示例中,一个主机上的 XML 文件通过另一个主机上的 XSLT 脚本进行转换。XSLT 脚本定义了一个表单,允许用户选择 XML 文件中的条目子集,然后是搜索结果(如果有)。

  1. 样式表
  2. 数据
  3. 搜索威士忌数据

序列图描述了涉及的交互

序列图

页面抓取示例

[编辑 | 编辑源代码]

参见 页面抓取和雅虎天气

使用 XSLT 导入

[编辑 | 编辑源代码]

XSLT 允许您调用导入其他 XSLT 模板的公共库的样式表。但并非所有 XSLT 导入路径语句都可以在 eXist 中使用。在以下示例中,我们将使用一个导入另一个样式表的 XSLT 样式表。以下假设您有一个名为 /db/test/xslt 的集合,并且所有文件都放置在该集合中。

XQuery XSLT 测试程序

[编辑 | 编辑源代码]
xquery version "1.0";
declare namespace transform="http://exist-db.org/xquery/transform";
declare option exist:serialize "method=xhtml media-type=text/html indent=yes";

let $input :=
<data>
   <element>element 1</element>
   <element>element 2</element>
   <element>element 3</element>
</data>

return
<html>
    <head>
       <title>Demonstration of running XSLT within an XQuery</title>
    </head>
    <body>  
        <h1>Demonstration of running XSLT within an XQuery</h1>
        { transform:transform($input, doc("/db/test/xslt/style.xsl"), ()) }  
    </body>  
</html>

顶级 Style.xsl

[编辑 | 编辑源代码]
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:import href="common.xsl"/>
    <xsl:template match="/">
        <ol>
            <xsl:apply-templates/>
        </ol>
    </xsl:template>
</xsl:stylesheet>

在第二行,以下导入按预期工作

   <xsl:import href="common.xsl"/>
   <xsl:import href="common.xsl" xml:base="https://127.0.0.1/exist/rest/db/test/xslt"/>
   <xsl:import href="common.xsl" xml:base="/exist/rest/db/test/xslt"/>

但是您会注意到,使用以下内容无效

   <xsl:import href="/exist/rest/db/test/xslt/common.xsl"/>

导入的 common.xsl

[编辑 | 编辑源代码]
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:template match="element">
    <li>
        <xsl:value-of select="."/>
    </li>
</xsl:template>

</xsl:stylesheet>

XForms 示例

[编辑 | 编辑源代码]

您还可以创建一个简单的 XForms 示例,作为该脚本的前端。请参阅 XRX Wikibook 以获取此 XForms 前端的示例。

xquery version "1.0";
declare option exist:serialize "method=xhtml media-type=text/xml indent=no process-xsl-pi=yes";
 
 (:
 transform:transform($node-tree as node()?, $stylesheet as item(), $parameters as node()?,  as xs:string) node()?
 :)

let $transform := 'https://127.0.0.1:8080/exist/rest/db/xforms/xsltforms/xsltforms.xsl'

let $form :=
<html xmlns="http://www.w3.org/1999/xhtml" 
   xmlns:ev="http://www.w3.org/2001/xml-events" 
   xmlns:xf="http://www.w3.org/2002/xforms">
    <head>
      <title>XForms Template</title>
      <xf:model>
         <xf:instance xmlns="" id="save-data">
            <data>
               <name>John Smith</name>
            </data>
        </xf:instance>
      </xf:model>
   </head>
   <body>
      <h1>XForms Test Program</h1>
      <xf:input ref="name">
         <xf:label>Name: </xf:label>
      </xf:input>
   </body>
</html>

let $serialization-options := 'method=xml media-type=text/xml omit-xml-declaration=yes indent=no'

let $params := 
<parameters>
   <param name="output.omit-xml-declaration" value="yes"/>
   <param name="output.indent" value="no"/>
   <param name="output.media-type" value="text/html"/>
   <param name="output.method" value="xhtml"/>
</parameters>

return 
   transform:transform($form, $transform, $params, $serialization-options)

缓存管理

[编辑 | 编辑源代码]

默认情况下,一旦文档完成转换,它就会驻留在缓存中。如果文件需要重新转换,这对于性能原因来说非常有用,但有时如果源文件发生变化,则需要重新运行转换。

您可以通过更改配置文件来禁用缓存。在 conf.xml 文件中,将 @caching 值从 yes 更改为 no。

   <transformer  class="org.apache.xalan.processor.TransformerFactoryImpl" caching="no"/>

http://demo.exist-db.org/exist/xquery.xml#N10375

华夏公益教科书