XSLT 1.0推荐标准摘译(第二部分)

来源:互联网 发布:手机桌面软件苹果 编辑:程序博客网 时间:2024/06/03 19:29

3 数据模型

XSLT采用和XPath基本一致的数据模型。

3.1 根节点的孩子

对于结果树而言,根节点可以拥有任意多个孩子,包括文本节点。如果转化为XML,结果树不一定是良构的XML文档,但必须是良构的一般外部解析实体。

对于源树而言,如果来自良构的XML文档,则根节点只能有一个非文本的孩子元素,否则没有很强的限制。

 

3.2 基准URI

每个节点都有一个基准URI,用于将相对URI属性解析为绝对URI。外部实体中的元素或处理指令的基准URI为外部实体的URI,其他则为文档的基准URI。文档节点的基准URI即文档实体的基准URI。文本节点、注释节点、属性节点、名称空间节点的基准URI是父节点的基准URI

 

3.3 非解析实体

 

3.4 去除空白字符

源文档树和样式表文档树构造之后,执行XSLT处理之前,一些文本节点将被删除。只有仅含空白字符的文本节点才会被挤掉。去除文档节点将从文档树上删除文本节点。去除过程允许指定需要保留其空白字符的元素名。样式表和源文档都要经过空白字符去除,但是采用不同方式指定需要保留空白的元素。

符合下列条件之一的文本节点将被保留:

l  文本节点的父元素要求保留空白字符;

l  至少包含一个非空白字符(XML中的空白字符包括#x20#x9#xD#xA.

l  文本节点的某个祖先元素指定了xsl:space属性而且没有被更近的祖先元素取消。

树中的xml:space属性不删除。

对于样式表来说,保留空白的元素只有xsl:text

<!-- Category:top-level-element -->
<xsl:strip-space
elements = tokens />

<!-- Category: top-level-element -->
<xsl:preserve-space elements = tokens />

源文档使用xsl:strip-spacexsl:preserve-space顶层元素指定要保留或删除空白字符节点的元素名称,默认情况下保留所有元素的空白字符。

 

4 表达式

XSLT使用XPath表达式1)选择要处理的节点,2)指定处理节点的条件,3)生成插入结果树中的文本。

最外层表达式(即不是其他表达式的一部分)确定上下文的规则如下:

l  上下文节点即当前节点

l  上下文位置即当前节点在当前节点列表中的位置,从1开始

l  上下文的大小即当前节点列表中的节点个数

l  变量绑定即表达式所属元素作用域内的绑定

l  名称空间声明即表达式所属元素作用域内的名称空间声明,包括隐含声明但不包括默认声明

l  函数库包括核心函数库、附加和扩展函数。

 

5 模板规则

5.1 处理模型

对源树中一系列节点的处理生成结果树片段,对根节点的处理生成结果树。对源节点列表中的所有节点按照顺序依次处理,将生成的片段追加到结果树中。处理一个节点的过程如下:找出所有模式与该节点匹配的模板规则,选择其中最匹配的一个,以该节点为当前节点、以源节点列表作为当前节点列表实例化选中的模板。模板通常包含选择其他源节点列表进行处理的指令。匹配、实例化、选择这个过程递归执行,直到没有新的待处理源节点结束。

 

5.2 模式

模板规则使用模式来确定应用的节点。除了用于模板规则以外,模式还可用于编号(7.7)和声明键(12.2)。模式指定了选择节点的条件。符合这些条件的节点称为匹配该模式。模式的语法采用了XPath表达式语法 的一个子集。具体来说就是满足一定条件的位置路径表达式可用于模式。比如:

l  para和所有的para元素匹配

l  *匹配任何元素

l  chapter|appendix和所有的chapterappendix元素匹配

l  olist/item和所有父元素为olistitem元素匹配

l  appendix//paraappendix所有后代中的para元素匹配

l  /匹配根节点

l  text()匹配所有文本节点

l  processing-instruction()匹配所有的处理指令

l  node()匹配属性节点和根节点之外的所有节点

l  id(“W11”)匹配IDW11的元素

l  para[1]匹配作为父节点中第一个para孩子出现的所有para元素

l  *[position()=1 and self::para]匹配作为父节点中第一个孩子出现的所有para 元素。

l  para[last()=1]匹配作为父节点中唯一para孩子出现的所有para元素。

l  items/item[position()>1] 匹配items中第一个item元素以外的所有item元素。

l  item[position() mod 2 = 1]匹配父元素中序号为奇数的所有item孩子。

l  div[@class="appendix"]//p匹配class属性等于appendixdiv元素所有后代中的p元素。

l  @class匹配所有的class属性。

l  @*匹配任何属性

模式由|分割的一组位置路径模式组成。位置路径中只能使用孩子和属性轴。虽然不能使用descendant-or-self轴,但可使用///运算符。位置路径模式也可以idkey函数调用开始。模式中的谓词可使用任意表达式。

仅当存在某个上下文对模式表达式求值节点出现在结果节点集中的时候,才称模式与该节点匹配。比方说,p与任何p元素匹配,因为对于任何p元素,当表达式p以其父节点作为上下文计算的时候,结果节点集中都包括p元素。

虽然模式的语义间接通过表达式求值来表达,但直接理解起来也很容易。| 表示“或”,只要匹配其中的一项即可。///表示的步进模式StepPattern从右向左匹配;Child轴首先检查NodeTest是否为真,然后确保不是属性节点;属性轴首先检查NodeTest为真,然后确保是属性节点;如果包含谓词表达式,首选选择符合路径表达式的节点,然后用[]中的条件进行测试。

比如:appendix//ulist/item[position()=1],匹配的过程如下:

l  该节点是一个item元素(节点测试)

l  以该节点为上下文节点,该节点的item兄弟节点组成当前节点列表计算谓词

l  父节点为ulist

l  有一个祖先节点是appendix元素

 

5.3 定义模板规则

<!-- Category:top-level-element -->
<xsl:template
match = pattern name = qnamepriority = number mode = qname>
  <!-- Content: (
xsl:param*, template) -->
</xsl:template>

属性match是一个模式,选择应用该规则的源节点。

没有match属性的话,模板必须有name属性

match属性不能包含变量引用

template元素的内容是应用该模板规则时实例化的模板

 

5.4 应用模板规则

<!-- Category: instruction -->
<xsl:apply-templates
  select = node-set-expression
  mode = qname>
  <!-- Content: (
xsl:sort | xsl:with-param)* -->
</xsl:apply-templates>

下面的例子为chapter元素创建了一个block,然后处理chapter的直接孩子:

<xsl:template match="chapter">

 <fo:block>

   <xsl:apply-templates/>

 </fo:block>

</xsl:template>

由于没有select属性,xsl:apply-templates指令将处理当前节点的所有孩子,包括文本节点(不包括被去除的空白文本节点)。可以使用select属性选择要处理的节点。select属性的值是一个表达式,表达式的计算结果必须是一个节点集。选中的节点按照文档顺序处理。下面的例子处理author-group的所有author孩子:

<xsl:template match="author-group">

 <fo:inline-sequence>

    <xsl:apply-templatesselect="author"/>

 </fo:inline-sequence>

</xsl:template>

下面的例子则处理author-group所有athor孩子的given-name节点:

<xsl:template match="author-group">

 <fo:inline-sequence>

   <xsl:apply-templates select="author/given-name"/>

 </fo:inline-sequence>

</xsl:template>

下例处理book元素的所有heading后代元素:

<xsl:template match="book">

 <fo:block>

   <xsl:apply-templates select=".//heading"/>

 </fo:block>

</xsl:template>

处理不是当前节点后代的其他元素也是可能的。下例假设department元素拥有group孩子和employee后代,首先找到雇员所属的department,然后处理这个departmentgroup孩子:

<xsl:template match="employee">

 <fo:block>

    Employee<xsl:apply-templates select="name"/> belongs to group

   <xsl:apply-templatesselect="ancestor::department/group"/>

 </fo:block>

</xsl:template>

同一个模板中可以包含多个xsl:apply-templates元素来完成简单的排序。下例创建了两个HTML表格,一个是国内销售额,一个是国外销售额:

<xsl:template match="product">

  <table>

   <xsl:apply-templates select="sales/domestic"/>

  </table>

  <table>

   <xsl:apply-templates select="sales/foreign"/>

  </table>

</xsl:template>

有可能存在两个匹配的后代,两者存在后代关系,比如对于源文档:<doc><div><div></div></div></doc>,规则:

<xsl:template match="doc">

 <xsl:apply-templates select=".//div"/>

</xsl:template>

将同时处理外层和内层的div元素。

一般情况下,使用xsl:apply-templates处理当前节点的后代,这种情况下不会造成无限循环。但是如果使用xsl:apply-templates处理当前节点后代以外的节点,有可能造成无限循环。比如:

<xsl:template match="foo">

 <xsl:apply-templates select="."/>

</xsl:template>

 

5.5 模板规则冲突的解决

同一个源节点有可能匹配多个模板规则。这种情况下按照下列规则选择模板:

首先排除低优先级的模板规则。模板规则的优先级由priority属性指定,默认优先级的确定顺序如下:

|分隔的模式分解成多个模板规则

ChildOrAttributeAxisSpecifier+QName/processing-instructions0

ChildOrAttributeAxisSpecifier+NCName:*-0.25

ChildOrAttributeAxisSpecifier+NodeTest-0.5

其他,0.5

即,最常见的检测节点是否具有特定类型和特定扩展名的模式优先级为0;比较宽松,指定类型和名称空间URI的测试优先级为-0.25;更宽松的仅指定类型的测试优先级为-0.5;比常见模式更具体的模式的优先级为0.5

如果经过上述排除后仍然剩下多条规则,则报错。

 

5.6 覆盖模板规则

<!--Category: instruction -->
<xsl:apply-imports />

用于覆盖导入样式表中模板规则的模板规则可使用xsl:apply-imports元素调用被覆盖的模板规则。样式表处理过程中,任何时候都有一项当前模板规则。一旦通过模式匹配选择了一项模板规则,它就成了当前模板规则,对其进行模板实例化。使用xsl:for-each元素的时候,当前模板规则变为null,以便对xsl:for-each元素的内容进行实例化。xml:apply-import使用导入样式表的模板规则处理当前节点,处理的mode采用当前模板规则的mode。如果当前模板规则为null就不能调用xsl:apply-import。比如,假设样式表doc.xsl包含用于example元素的模板规则:

<xsl:template match="example">

 <pre><xsl:apply-templates/></pre>

</xsl:template>

另一个样式表导入了doc.xsl并改变对example元素的处理方法:

<xsl:import href="doc.xsl"/>

 

<xsl:template match="example">

  <divstyle="border: solid red">

    <xsl:apply-imports/>

  </div>

</xsl:template>

结果如下:

<div style="border: solidred"><pre>...</pre></div>

 

5.7 Mode

Mode用于多次处理同一个元素,每次生成不同的结果。如果xsl:template没有match属性,则不能使用mode属性;如果xsl:apply-templates具有mode属性,则仅调用那些具有相同mode属性的xsl:template,否则仅调用那些没有mode属性的模板规则。

 

5.8 内置模板规则

如果样式表中没有匹配的模板规则,则采用内置模板规则,如下:

<xsl:template match="*|/">

 <xsl:apply-templates/>

</xsl:template>

带有mode属性(m)的内置模板规则:

<xsl:template match="*|/"mode="m">

  <xsl:apply-templatesmode="m"/>

</xsl:template>

用于文本和属性节点(复制)的内置模板规则:

<xsl:template match="text()|@*">

 <xsl:value-of select="."/>

</xsl:template>

过滤处理指令和注释的模板规则:

<xsl:templatematch="processing-instruction()|comment()"/>

内置的名称空间模板规则同样什么也不做。由于没有匹配名称空间节点的模式,因此这也是唯一用于名称空间节点的模板规则。

内置模板规则在样式表处理之前隐含导入,因此具有最低的优先级。