8.10 包含和导入

XSLT允许将多个样式单文件合并成一个样式单文件,XSLT提供了2种方式来合并样式单:

alt 使用<import…/>元素导入另一份样式单文档。

alt 使用<include…/>元素包含另一份样式单文档。

8.10.1 使用import导入

使用<import…/>元素可导入另一份XSLT样式单,使用<import…/>元素时必须指定如下属性:

alt href:用来指定被导入的XSLT文档的URI地址。

需要指出的是,<import…/>只能作为<stylesheet…/>和<transform…/>两个元素的子元素使用,<import…/>元素必须出现在<stylesheet…/>元素的所有其他子元素之前。

使用<import…/>元素导入其他XSLT样式单的语法比较简单,如下XSLT文档中导入了另外两份样式单文档:

程序清单:codes\08\8.10\import.xslt

alt

使用<import…/>元素导入的样式单可以包含和原样式单相同的模板定义,在这种情况下,原样式单里定义的模板定义取胜。也就是说,原样式单里的模板定义具有较高的优先级。

使用<import…/>元素导入其他样式单具有如下规律:

alt 原样式单里的模板定义的优先级比导入样式单里的模板定义的优先级高。

alt 后导入样式单里的模板定义的优先级比先导入样式单里的模板定义的优先级高。

比如样式单A依次导入了B、C两个样式单,样式单B又导入了样式单D,样式单C又导入了样式单E,它们所包含的模板定义的优先级由低到高为D、B、E、C、A。


alt注意

使用<import…/>元素不能导入当前样式单本身,只要导入了当前样式单自身,样式单文档就会出现错误。


根据前面的介绍可以知道:在使用<import…/>导入其他样式单文档时,如果两份样式单文档里包含了相同的模板定义,则原有的模板定义会覆盖导入的模板定义,而且后导入的模板定义也会覆盖先导入的模板定义。如果希望在原XSLT中使用被覆盖的模板定义,可使用<apply-imports…/>元素。

<apply-imports…/>元素的用法非常简单,既不需要指定任何属性,又不能包含任何子元素,直接使用该元素即可。

例如有如下XLST文档:

程序清单:codes\08\8.10\imported.xslt

alt

上面的样式单文档中为<book…/>元素定义了一个模板规则,如果将上面的XSLT文档导入其他XSLT文档中,而原XSLT中已经包含<book…/>元素的模板规则,则上面的XSLT中为<book…/>元素定义的模板规则将被覆盖。此时就可以使用<apply-imports…/>元素调用被覆盖的模板规则,如下所示:

程序清单:codes\08\8.10\book.xslt

alt

上面的代码中的粗体字代码用于调用被覆盖的模板规则,XSLT将会调用imported.xslt中为<book…/>元素定义的模板定义来转换该<book…/>元素,这就是<xsl:apply-imports…/>元素无须指定任何属性的原因。<xsl:apply-imports…/>到底调用哪个被覆盖的模板规则,取决于该元素所在的上下文,如果当前上下文正在处理的XML元素是<abc…/>,<xsl:apply-imports…/>元素就会调用被覆盖的<abc…/>元素的模板定义进行转换。

8.10.2 使用include包含

<inclulde…/>元素用于包含另一份XSLT文档,<include…/>和<import…/>元素的用法基本相似:不能包含任何子元素,且必须指定一个href属性。

使用<inclulde…/>有如下几个注意点:

alt <inclulde…/>只能作为<stylesheet…/>和<transform…/>两个元素的子元素使用。

alt <inclulde…/>元素之前只能出现<import…/>,其他元素都必须在<include…/>元素之后。

alt 包含的样式单必须是完整的样式单。

alt 包含的样式单和原样式单里的模板定义具有相同的优先级。

alt 如果包含的样式单和原样式单的模板定义产生冲突,整个XSLT文档将出现错误。

<include…/>元素包含的多份XSLT中的所有模板定义具有相同的优先级,这表明<include…/>元素的作用只是将一份XSLT的多个片段再次组合成一份完整的XSLT样式单;只有<import…/>元素才可以真正处理多份XSLT样式单。

如下两份XSLT文档原来只是一份XSLT文档,现在将它们分为2份样式单文档,然后使用<include…/>元素将它们包含进来,如下所示:

程序清单:codes\08\8.10\book2.xslt

alt

下面是被包含的included.xslt样式单,该样式单里包含了<book…/>元素的模板定义,该模板定义将直接插入上面的book2.xslt文档中:

程序清单:codes\08\8.10\included.xslt

alt

与<import…/>元素类似的是,使用<include…/>元素也不能包含样式单自身,否则样式单文件将出现错误。

8.10.3 解决模板定义冲突

如果一份XSLT文档里有多个模板定义可以匹配同一个节点,XSLT转换器将会选择其中优先级最高的模板定义来转换该节点。

在XSLT文档中使用<template…/>元素定义模板时可用priority属性来指定该模板定义的优先级,关于priority的说明如下:

alt priority:指定模板定义的优先级。此属性的值可以是一个任意的实数,正数、负数都可以。

如果开发者没有为<template…/>元素指定priority属性,则该<template…/>元素对应的模板定义将具有默认的优先级,默认的优先级总在-0.5~0.5之间。基本上有个规律,match属性值对应XPath表达式所表示的范围越明确,该模板定义的优先级越高。

由于系统默认优先级的最大值是0.5,因此如果希望XSLT优先使用某个模板定义,只要将该模板定义的priority属性值设为大于0.5的值即可。