级别: 中级 James R. Fuller (jim.fuller@webcomposite.com), 技术总监, FlameDigital Limited & Webcomposite s.r.o.
2008 年 7 月 21 日 从 2005 年 10 月起,W3C XML 处理模型工作组就开始研究名为 “XProc: An XML Pipeline Language” 的工作草案(Working Draft,WD)规范。随着早期的实现开始出现,以及 W3C 工作组对第二次 Last Call 的预报(为 W3C 草案建议铺平道路),很明显,在过去的一年里,对 Xproc 规范的研究工作已经加快了速度。探索 Xproc 的现状和未来,了解一些有争议的问题背后的故事,并演示一些例子。
Xproc 是一种描述处理管道的标记语言,由一些在 XML 文档上进行操作的离散步骤组成。如果规范的重要性与从事此项工作的个人素质有关,那么 Xproc 的确意义重大。W3C XML 处理模型 WG 聚集了大量务实的 XML 工作者和著名人物,还有过去对 XML 相关成果做出贡献的头发花白的老手:Erik Bruchez、Andrew Fang、Paul Grosso、Rui Lopes、Murray Maloney、Alex Milowski、Michael Sperberg-McQueen、Jeni Tennison、Henry Thompson、Richard Tobin、Alessandro Vernet、Norman Walsh(主席)和 Mohamed Zergaoui 等等。
 |
常用缩写词
- DTD:文档类型定义 (Document Type Definition)
- HTTP:超文本传输协议 (Hypertext Transfer Protocol)
- W3C:万维网联盟 (World Wide Web Consortium)
- XML:可扩展标记语言 (Extensible Markup Language)
- XSL:可扩展样式表语言 (Extensible Stylesheet Language)
- XSLT:可扩展样式表语言转换 (Extensible Stylesheet Language Transformations)
|
|
Xproc 并不是 W3C 对建立一个 XML 处理管道标准所做的第一次尝试。在 2002 年,作为 XML Processing Model Workshop 的一部分,Sun Microsystems、Alis Technologies、Arbortext、Cisco Systems、Fujitsu、Markup Technology 和 Oracle 就曾提交了一个 “XML Pipeline Definition Language Submission”,并于 2002 年 2 月 28 日作为 “XML Pipeline Definition Language Version 1.0” 出版。
2004 年,W3C Note 曾尝试建立 XML 处理模型的需求:“XML Processing Model Requirements”,该需求由 W3C Working Group Note 于 2004 年 4 月 5 日完成。2005 年 3 月 11 日,Orbeon, Inc. 提交了另一个 W3C 成员报告 “XML Pipeline Language (XPL) Version
1.0”(草案),该报告于 4 月 11 日出版。
我还没见过针对 Xproc 需求的专门研究,因此,在这里我大胆提出自己的一些片面观点:
- Xproc 的说明性格式以及管道思想的简单性,将意味着非技术人员能够参与处理工作流的编写和维护。
- 在许多配置中,Xproc 都能够进行流线化,而其他控制 XML 处理的方法却无法实现这一点(例如 XSLT)。
- Xproc 步骤专注于执行具体操作,随着时间的推移,这种方法将比您或我编写的一次性代码具有更好的优化性能。
- Xproc 的标准步骤库和扩展机制使 Xproc 成为了一种全能的解决方案。
- 结构化数据(例如 Xproc 标记)通常比结构化代码更易重用。
- Xproc 的灵感之一来自 UNIX® 管道,几乎所有人都认为这是一个不错的功能!
 |
用例
Xproc 的目标是提供一种可互操作的标准方法来处理 XML 文档。这些需求被正式列在一组用例中(参见 参考资料),下面列出了其中的部分内容:
- 对 XML 文档执行一系列操作。
- 解析 XML,针对一种模式对其进行验证,然后执行 XSLT 转换。
- 合并多个 XML 文档(文档聚合)。
- 与 Web 服务交互。
- 使用元数据检索。
|
|
毫无疑问,Xproc 将会受到使用和生成 XML 文档的人群的喜爱。也可以想象经常处理业务工作流和 XML 文档的人群也会从中受益,他们可以使用 Xproc 管道对工作流进行建模,然后在 XML 文档中运行。
XProc 词汇表
Xproc 由一个小词汇表组成,该词汇表可以分为三个类别:核心元素,辅助元素和一个标准的步骤库。核心元素提供现代计算机语言构造,例如条件和循环处理以及尝试/捕获错误机制:
-
<p:for-each>:循环处理语句
-
<p:choose>:选择逻辑语句(类似于 XSLT <xsl:choose>)
-
<p:group>:将一系列步骤分组到指定的子管道中
-
<p:try>:提供一种尝试/捕获机制来处理动态错误
-
<p:viewport>:对包含在单个 XML 文档中的子树应用子管道进程
在步骤的声明和定义中使用的元素为 Xproc 的可扩展性和可重用性提供了坚实基础:
-
<p:library>:包含步骤声明以提供可重用的步骤库
-
<p:declare-step>:定义一个步骤及其函数签名,通常位于一个
<p:library> 元素中
-
<p:import>:通过统一资源标识符(Uniform Resource Identifier,URI)将任何已声明的管道或库导入到当前管道中
Xproc 辅助元素主要是 Xproc 步骤的子节点,处理步骤绑定、简化步骤配置等任务。这些元素包括:
-
输入和输出:这些元素定义可以绑定到其他步骤的输入或输出的端口,并定义 XML 文档的流。另外,还可以(直接在 Xproc 文档中)定义 XML 文档内联或者通过外部 URI 导入文档。
-
选项:选项是配置步骤的主要机制,带有
<p:with-option> 元素或作为步骤实例中的一个名称-值属性。注意,选项是步骤的函数签名的一部分,它们的名称都是不变的。
-
变量:变量和复合步骤一起使用,定义在复合步骤子管道中使用的 Xpath 变量。
-
参数:正如
<p:declare-step> 所定义的,与选项、变量不同,参数的名称是在运行时计算出来的,与函数签名无关。Xproc 的最重要的方面也许是标准 Xproc 库中定义的第 30-40 步,这些步骤被划分为必需和可选的步骤集合。
Xproc 真正的强大之处在于必需和可选步骤的标准库,这些步骤执行广泛的任务,例如:
- XSLT、XQuery、XInclude 处理
- 模式验证(DTD、RelaxNG、Schematron、XML 模式)
- XML 更新操作,例如插入或删除 XML 元素或属性
- XML 存储和检索
- 对 XML 进行包装、解包、转义(escape)和转回(unescape)
- HTTP 请求
- 执行本机命令
下面简要概述 Xproc 标准库中包含的各个步骤:
- 必需步骤:
-
<p:add-attribute>:向匹配元素集中添加一个属性。
-
<p:add-xml-base>:添加或纠正元素的 xml:base 属性。
-
<p:compare>:比较两个文档是否相等。
-
<p:count>:统计源输入中的文档数目。
-
<p:delete>:从源输入中删除由匹配模式指定的项。
-
<p:directory-list>:在输出结果中枚举目录列表。
-
<p:error>:生成一个动态错误。
-
<p:escape-markup>:对源输入进行转义。
-
<p:http-request>:与由基于 HTTP 的国际化资源标识符(IRI)标识的资源进行交互。
-
<p:identity>:将输入源精确复制到结果输出。
-
<p:insert>:在源输入中插入一个 XML 选择。
-
<p:label-elements>:为每个匹配元素创建一个标签,并在属性中存储标签值。
-
<p:load>:载入一个由 IRI 指定的 XML 资源并提供为结果输出。
-
<p:make-absolute-uris>:将源输入中的元素或属性值转换为结果输出中的绝对 IRI 值。
-
<p:namespace-rename>:重命名名称空间声明。
-
<p:pack>:合并两个文档序列。
-
<p:parameters>:将一组参数作为 c:param-set XML 文档在结果输出中提供。
-
<p:rename>:重命名元素、属性或处理指令。
-
<p:replace>:替换匹配元素。
-
<p:set-attributes>:设置匹配元素上的属性。
-
<p:sink>:接受源输入但不生成结果输出。
-
<p:split-sequence>:将一个序列分解为两个序列。
-
<p:store>:将源输入的序列化版本存储到 URI 中。
-
<p:string-replace>:在源输入上执行字符串替换。
-
<p:unescape-markup>:对输入源进行转回。
-
<p:unwrap>:用子元素替换匹配元素。
-
<p:wrap>:用一个新的父元素包装源文档中的匹配节点。
-
<p:wrap-sequence>:生成一个新的文档序列。
-
<p:xinclude>:对输入源应用 Xinclude 处理。
-
<p:xslt>:对输入源应用 XSLT 1.0 或 2.0 版样式表。
- 可选步骤:
-
<p:exec>:对输入源使用外部命令。
-
<p:hash>:为一些值生成消息摘要或数字指纹。
-
<p:uuid>:生成一个全球统一标识符(Universally Unique Identifier,UUID)。
-
<p:validate-with-relax-ng>:用 RelaxNG 模式验证输入的 XML。
-
<p:validate-with-schematron>:用 Schematron 模式验证输入的 XML。
-
<p:validate-with-xml-schema>:用 XML 模式验证输入的 XML。
-
<p:www-form-urldecode>:将 x-www-form-urlencoded 字符串解码为一组 Xproc 参数。
-
<p:www-form-urlencode>:将一组 Xproc 参数值编码为 x-www-form-urlencoded 字符串。
-
<p:xquery>:应用 XQuery 1.0 版进行查询。
-
<p:xsl-formatter>:呈现 XSL 1.1 版文档(与 XSL-FO 一样)。
从现有管道创建新的步骤非常容易。如果您喜欢,甚至可以使用扩展步骤创建第三方库来扩充 Xproc 处理器本身的功能。
注意:由于规范的制定还在进行中,标准库部分随时都可能改动。因此,建议参考当前 WD(参见 参考资料)中针对指定细节的最新定义。
示例管道
清单 1 展示了一个包含单个步骤的 Xproc 管道,该步骤对 XML 文档应用 XSLT 操作。
清单 1. 简单的隐式管道
<p:pipeline xmlns:p="http://www.w3.org/ns/xproc" name="xslt-example">
<p:xslt>
<p:input port="stylesheet">
<p:document href="mystylesheet.xslt"/>
</p:input>
</p:xslt>
</p:pipeline>
|
Xproc 管道接受 0 个或多个 XML 文档作为输入,生成 0 个或多个 XML 文档作为输出。清单 1 中的 Xproc 代码仅包含一个
<p:pipeline> 顶层元素和一个
<p:xslt> 步骤。传入到 Xproc 处理器的标准输入中的 XML 文档由 <p:xslt> 步骤进行处理,该步骤应用 mystylesheet.xslt(mystylesheet 由 <p:input>/<p:document>
元素定义)对 XML 文档进行 XSLT 处理。
由于只有一个步骤,其结果被存放在整个管道的结果端口上,该端口通常会将 XML 文档输出到标准输出。图 1 显示了该过程,概括了 XML 文档从源流到结果端口的路径。
图 1. 简单管道的逻辑流
端口之间的这些连接称为步骤绑定,它们控制 XML 文档处理流。这些绑定可以通过隐式或显式方式定义。在 清单 1 的例子中,绑定是隐式的,带有 Xproc 内部默认机制所规定的处理流。
清单 2 展示了带有显式步骤绑定、具有相同功能的管道。
清单 2. 简单显式管道
<p:declare-step xmlns:p="http://www.w3.org/ns/xproc" name="xslt-example">
<p:input port="my-source" primary="true" sequence="false"/>
<p:output port="my-result" primary="true" sequence="false">
<p:pipe step="step1" port="result"/>
</p:output>
<p:xslt name="step1">
<p:input port="source">
<p:pipe step="xslt-example" port="my-source"/>
</p:input>
<p:input port="stylesheet">
<p:document href="mystylesheet.xslt"/>
</p:input>
</p:xslt>
</p:declare-step>
|
在 清单 1 中,我使用了 <p:pipeline>,它隐式声明了一个源输入和结果输出端口。现在采用
<p:declare-step> 意味着我必须显式定义这些端口,并在连续的同级步骤之间声明步骤绑定。这些绑定和端口概括如下:
- 顶层 my-source 输入端口将接收到所有标准输入。
- 顶层 my-result 输出端口将接收到 step1 结果端口的结果并将它们放在标准输出上。
-
step1 源输入被绑定到 my-source 输入端口。
很难使用只有单个步骤的管道示范步骤之间的步骤绑定;因此,我创建了一个特殊的例子来展示多个 Xproc 步骤和逻辑结构。清单 3 展示了一个更有代表性的 Xproc 的例子,其中包含多个步骤以及一些条件逻辑步骤。
清单 3. 复杂管道
<p:pipeline name="mypipeline" type="myexample" xmlns:p="http://www.w3.org/ns/xproc">
<p:xinclude name="step1"/>
<p:choose name="step2">
<p:when test="/*[@version < 2.0]">
<!-- subpipeline //-->
<p:validate-with-xml-schema name="step2a1">
<p:input port="schema">
<p:document href="newer-schema.xsd"/>
</p:input>
</p:validate-with-xml-schema>
</p:when>
<p:otherwise>
<!-- subpipeline //-->
<p:validate-with-xml-schema name="step2b1">
<p:input port="schema">
<p:document href="older-schema.xsd"/>
</p:input>
</p:validate-with-xml-schema>
</p:otherwise>
</p:choose>
<p:for-each name="step3">
<p:iteration-source select="//div"/>
<!-- subpipeline //-->
<p:string-replace name="step3a1">
<p:option name="match" value="//span[@class=’css1’]"/>
<p:option name="replace" value=""/>
</p:string-replace>
</p:for-each>
<p:wrap-sequence name="step4">
<p:option name="wrapper" value="document"/>
</p:wrap-sequence>
</p:pipeline>
|
该管道可概括如下:
- 从标准输入设备输入 XML 文档。
- 执行
<xinclude> 处理(step1)。
- 在(step2)新模式(step2a1)或旧模式(step2b1)之间进行选择和验证。
- 提取每个(step3)HTML
<div>
元素,执行字符串替换操作(step3a1)。
- 使用
<document> 元素包装 <div> 元素的最终序列(step4)。
- 将 XML 文档输出到标准输出。
步骤可以定义其他输入和输出端口来处理非 XML 文档,但是只有 XML 文档(正如 XML infoset 中所描述的)能够在基本输入输出端口之间传送。
在本例中,我用了三种 Xproc 步骤,步骤类型在工作流图中用矩形表示,如
图 2 所示。
图 2. 复杂管道的逻辑流
p:pipeline 复合步骤
最大的矩形代表整个
<p:pipeline>,它本身可以作为一个步骤被调用。因为它包含子管道,所以是一个复合步骤。
p:choose 多容器步骤
<p:choose> 步骤包含两个子管道,因此称为多容器步骤。它根据 <p:when> Xpath 表达式的赋值确定选择哪个子管道。
p:for-each 复合步骤
<p:for-each> 步骤包含由一个步骤组成的单个子管道,因此,它是一个复合步骤。
原子步骤
大多数 XProc 步骤都是原子步骤,它们对 XML 文档执行特定的操作。例如
<p:xinclude>、<p:validate->、
<p:string-replace> 和
<p:wrap>。
Xproc 开发的考虑因素
在 Xproc 规范的发展过程中,WG 必须解决一些问题:
目前的状态
同任何 W3C 规范一样,Xproc 在语法和语义方面都有了很大的变化(参见 参考资料)。最新的 WD(于 2008 年 5 月 1 日发布)进行了重大改进,它去除了以前的草案决策中的一些混淆内容,同时支持 Xpath 和 XSLT 第 1 和第 2 版。
当前的 WD 也进行了重大改进,它重新编写了规范,诠释了 <p:option>
元素现在的一些概念。例如 <p:option> 现在只用于一个步骤的函数签名(仅限
<p:declare-step>);当设置一个选项值时,将
<p:with-option> 在步骤实例自身的内部使用。另外,添加了 <p:variable/>
元素来存放计算值,具体来讲,用于与复合步骤结合使用。
对选项,参数和变量来说,最有趣的变化是移除了值属性;现在值是一个 Xpath 表达式的计算结果,该表达式由一个选择属性定义。清单 4 以 p:with-option 为例阐明了该过程。
清单 4. 将 p:with-option 与 Xpath 表达式结合使用的例子
<ex:someStep>
<p:with-option name="some-option-name" select="'some value'"/>
</ex:someStep>
|
使用 Xpath 表达式定义选项的简单值现在变得有点繁琐(例如,需要使用嵌套的双引号(")和单引号('))。语法简写(参见 清单 5)作为首选的方法被保留,可以在步骤元素上使用名称-值属性定义选项。
清单 5. 使用语法简写设置选项
<ex:stepType option-name="some value"/>
|
所有这些变化使规范的条理更加清晰,但是 Xproc 词汇表变得更加庞大(<p:variable>、<p:with-option>、<p:with-param> 等)。
最后需要提及的一个重大变化是,现在你必须始终使用
<p:declare-step/> 来声明新的步骤。这个变化给用户增加了一些认知压力,现在他们必须考虑一个步骤实例 而不是步骤的声明(位于一个库或管道中)。在 Xproc 中,在解释步骤 元素的时候引入过多的概念可能会带来潜在的局限性。我认为 WG 现在对概念进行划分是一个实用的决策。
结束语
对 XML 技术专家而言,重要的是提醒自己一些领域的开发人员并不使用 XML。当一些人问道,“为什么我需要 Xmroc” 时,我通常的回答是 “Xproc 与平台无关,只要能够运行兼容 XProc 的处理器的地方就可以运行 Xproc”。然而,如果你已经在使用 XML 文档和技术,您可能会使用其他方法 (XSLT、Apache Ant、Apache Cocoon 站点地图 和 Jelly 等)来效仿 XProc,你将会很高兴地看到 Xproc 处理器的到来。
注意:虽然所有 Xproc 实现都还不能用于生产,但一些实现已经在开发过程中。请参阅 参考资料 获得更多信息。
随着 XML 渗透到各个计算领域,如果能够找到像 Xproc 这样的独立且容易理解的方法来处理日益膨胀的 XML 应用领域,那么这种方法必定是一种革命性的技术。Xproc 标准库,连同可以编写自己的第三方步骤库的扩展功能,为现有和未来的 XML 处理器带来了强大的动力。因此,您无需让工作流去适应变化多端的特定技术,现在可以将自己的处理定义为 XML 文档上的一系列操作。
在接下来的几个月中,Xproc 将会进入第二次 Last Call,这意味着您会在 2008 年末看到一个 W3C 建议。
参考资料 学习
获得产品和技术
-
Xproc 实现列表:查看当前正在开发的 Xproc 实现。
-
Smallx:探究 Smallx。根据其开发人员描述,“它是为处理 XML infoset 而开发的一个库和工具集。它有两个不同的特性,一个是 infoset 实现允许文档流,另一个是 infoset 的处理可以使用管道概念来完成。”
-
Sxpipe:尝试使用简单 XML 管道(Simple XML Pipelines,sxpipe)构建简单的 XML 文档处理模型,并选择计算组件的顺序。
-
Apache Ant:获得更多相关信息并下载这个基于 Java™ 的构建工具。
-
Apache Cocoon:下载此框架并了解这个围绕关注分离概念构建的 Web 开发框架的更多信息。
-
Jelly:使用该工具把 XML 代码转换为可执行文件。
-
用于产品评估的 IBM 试用软件:使用可从 developerWorks 直接下载的 IBM 试用软件构建您的下一个项目,这些软件包括来自 DB2®、Lotus®、Rational®、Tivoli® 和 WebSphere® 的应用程序开发工具和中间件产品。
讨论
关于作者
对本文的评价
|