跳转到内容

XQuery/DocBook 到 HTML

来自维基教科书,开放的书,开放的世界

您希望将 DocBook 文档转换为 HTML 格式。

我们将使用 XQuery 类型转换变换,将示例实例文档转换为 XQuery 类型转换模块。要开始此过程,您可以使用任何从 XML 架构生成实例文档的工具。然后,您可以编辑此文档以仅包含要转换的元素。然后,您可以通过该工具运行此文件以生成类型转换 XQuery 模块。

调度函数

[编辑 | 编辑源代码]

我们的主要调度函数将具有以下结构

declare namespace db="http://docbook.org/ns/docbook";)

declare function db2html:transform($nodes as node()*) as item()* {
    for $node in $nodes
    return 
        typeswitch($node)
            case text() return $node
            case element(db:article) return db2html:article($node)
            case element(db:book) return db2html:book($node)
            case element(db:info) return db2html:info($node)
            case element(db:para) return db2html:para($node)
            case element(db:sect1) return db2html:sect1($node)
            case element(db:title) return () (: all titles will be transformed by their parent node :)
            case element(db:emphasis) return db2html:emphasis($node)
            default return <u>{$node}</u>
};

注意以下几点

  1. transform 函数以节点序列作为参数,并且对每个节点都返回类型转换函数。
  2. transform 返回一个项目序列
  3. 默认操作是将节点从输入复制到输出。不在 case 语句中的所有节点都将无修改地传递。您可以通过更改 default 返回的类型来更改此默认行为。
  4. 对于每个元素,都会调用一个单独的函数“元素函数”。如果元素是叶元素,则它们可以只返回叶元素的内容。如果不是叶元素,则必须为它们包含的每个子分支调用 transform。通过更改每个函数,您可以更改该元素创建的输出。这种结构使您的转换模块化,易于维护。
  5. 每个元素的命名空间都是 Docbook 命名空间 (db 是与 DocBook 5 URL http://docbook.org/ns/docbook 关联的前缀)
  6. 不在 case 语句中的所有元素都将返回一个“u”用于未知元素包装器。这使得它们在调试时易于识别。

元素函数的结构

[编辑 | 编辑源代码]

每个元素函数都有一个简单的结构。例如,<para> 元素可能具有以下结构

declare function db2html:para($node as node()) as element() {
<p>
  {db2html:transform($node/node())}
</p>
};

这将把所有 <db:para> 节点转换为 <p> 节点。请注意,输入类型是 node(),返回类型是 element()。另请注意,由于 <para> 元素包含其他子节点(元素和文本),因此它们都由对 db2html:transform($node/node()) 的递归调用进行处理。

以下是上述模块的函数完整列表。

declare function db2html:article($node as node()) as element() {
<div class="article">
  {db2html:transform($node/node())}
</div>
};

declare function db2html:book($node as node()) as element() {
<div class="book">
  {db2html:transform($node/node())}
</div>
};

declare function db2html:info($node as node()) as element() {
<div class="info">
  <h1>{$node/db:title/text()}</h1>
</div>
};


declare function db2html:sect1($node as node()) as element() {
<div class="sect1">
  <h2>{$node/db:title/text()}</h2>
  {db2html:transform($node/node())}
</div>
};

declare function db2html:title($node as node()) as element() {
<div class="title">
  {db2html:transform($node/node())}
</div>
};

declare function db2html:para($node as node()) as element() {
<p>
  {db2html:transform($node/node())}
</p>
};

declare function db2html:emphasis($node as node()) as element() {
<b>
  {db2html:transform($node/node())}
</b>
};


示例转换

[编辑 | 编辑源代码]
<article xmlns="http://docbook.org/ns/docbook" version="5.0">
    <info>
        <title>Article Template Title</title>
    </info>
    <sect1>
        <title>Section1 Title</title>
        <para>Typewsitch transforms are <emphasis role="bold">very</emphasis> powerful.</para>
    </sect1>
</article>

要调用转换,您只需将 DocBook 文档的根节点传递给函数即可

let $input := doc('/db/my-docbook-5-document.xml')/db:article
let $output := db2html:transform($input)
return $output

请注意,您必须在 doc() 函数之后放置要转换的根元素。如果没有,doc() 函数将返回一个文档节点,该节点将与任何文档 case 语句都不匹配。

<div class="article">
   <div class="info">
     <h1>Article Template Title</h1>
   </div>
   <div class="sect1">
      <h2>Section1 Title</h2>
      <p>Typewsitch transforms are <b>very</b>powerful.</p>
   </div>
</div>

参考文献

[编辑 | 编辑源代码]

此示例在 Google Code 上的源代码:http://code.google.com/p/xrx/source/browse/#svn%2Ftrunk%2F21-docbook-2-html

Chis Wallace 提供了一个工具,可以将 XML Docbook 转换为类型转换,如下所示:生成骨架类型转换转换模块

DocBook 到 HTML 类型转换转换

华夏公益教科书