> For the complete documentation index, see [llms.txt](https://rocape.gitbook.io/xmllanguage/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://rocape.gitbook.io/xmllanguage/xslt/63xslt-yang-shi-dan-de-yuan-su-he-zhi-ling.md).

# 6.3 XSLT 样式单的元素和指令

\###6.3 XSLT样式单的元素和指令

* `<xsl:stylesheet>`元素
* 每个完整的XSLT样式单都有一个xsl:stylesheet或xsl:transform元素作为其文档元素
  * `<xsl:stylesheet>`和`<xsl:transform>`语义上等同，可互换使用
  * 某些非常简单的XSLT样式单可能没有xsl:stylesheet，但可存在一个HTML文档里面分散包含来自XSLT命名空间的元素
  * xsl:stylesheet开始标签必须有一个version属性（位置）
    * 现在常用1.0
  * 必须有一个命名空间声明
    * 命名空间声明中的其他URL表示非XSLT命名空间中的元素
    * XSLT命名空间前缀：xslt/xsl或其他
* `<xsl:template>`元素
* XSLT处理器在样式表中查找一个match属性值为/的xsl:template元素（根节点）
* 搜索到根节点时就根据模板内容，在目标树中增加一个与模板内容相对应的树形结构
  * 只有一个根节点，则只允许根节点在目标树中添加一次
  * 模板中与根节点匹配的元素大都是HTML或XHTML元素
    * 字面结果元素（Literal Result Elements）
  * 模板中来自XSLT命名空间的元素被称为指令（Instructions）
* 模板是XSLT转换工作的具体规则，所有的转换任务是通过一系列的模板体现出来的。因此，如何声明和调用模板，是XSLT转换任务的关键
* 在XSLT文档中通常至少包含一个模板，即<xsl:templatematch=“/”>，该模板用于处理文档节点（Document Node），相当于程序设计语言中的main()函数
* 模板在很多方面都与函数非常类似，必须首先声明（可以指定模板的名称、参数、返回类型等），然后在合适的地方显式地调用（在遍历文档树节点的过程中或直接调用），才能够执行相应的转换规则
* 完整的模板声明语法

```
<xsl:templatematch=Pattern name=QNamemode=QNamepriority=Number as=Sequence-type>
    <!--other xslelements and literal result elements-->
......
</xsl:template>
```

* `<xsl:template>`和`</xsl:template>`之间的内容相当于一个函数的函数体，表示在调用该模板时应执行的具体操作。而xsl:template元素开始标记中的属性（match, name, mode和priority）用于描述该模板的相关信息
* match属性的取值涉及到模板的调用，分两种方式
  * 根据模板的匹配路径（在遍历的过程中）进行调用，具体有两种情况
    * 对于模板<xsl:templatematch=“/“>，XSLT处理器将在碰到XML文档的文档节点时自动调用该模板，类似程序执行的入口，Java 虚拟机自动调用主类的main()方法
    * 对于其他的模板match=other-pattern，将在模板<xsl:templatematch="/“>的转换规则（函数体）中通过指出匹配路径的方式（使用xsl:apply-templates）进行隐式或者显式地调用
  * 根据模板名称属性（name），使用<xsl:call-templatename=template-name>进行调用

```
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <!--transform the input root (/) and the message element-->
    <xsl:template match="/"> 模板1
        ......
    </xsl:template>
    <xsl:template match="message"> 模板2
        ......
    </xsl:template>
</xsl:stylesheet>
```

* match属性值可以使用绝对路径表达式（比如“/message”），这表示在遍历文档树的过程中碰到/message元素时，需要执行该模板中的内容；如果使用相对路径表达式，模板2将应用于/message、/\*/message 等（所有含message的元素）
* 模板`<xsl:templatematch=“/”>`和`<xsl:templatematch=“message”>`都没有具体的名称，称为**无名模板**
* 这些模板之所以可以没有名称，是因为它们的调用是在遍历文档树的过程中自动进行的，根本不需要名称
* 也可以使用name属性为模板指定一个名称，使其成为命名模板

```
<xsl:stylesheetversion="2.0"xmlns:xsl="http://www.w3.org/1999/XSL/Transform">    
    <xsl:templatematch="/"name="one"><!--命名模板one-->
        <xsl:call-templatename="another"/>    
        </xsl:template>
    <xsl:templatename="another"> <!--命名模板another-->
        <output>Simple output</output>
    </xsl:template></xsl:stylesheet> 
```

```
+ 输出结果为
```

：\` < output

>

Simple output \</ output>\`

* 对于一个模板来说，可以同时使用match和name属性，以便能够在遍历过程中根据路径匹配情况自动地调用，或者使用xsl:call-template直接调用
* 模板的mode属性可用于对模板进行进一步的标识

```
<xsl:templatematch="Name"mode="C"> <!--模板1-->
    ...Do sthfor Company Name...
</xsl:template>
<xsl:templatematch="Name"mode="P"> <!--模板2-->
    ...Do sthfor Person Name...
</xsl:template>
```

```
<Company>
    <Name>Acme</Name>
    <Person>
        <Name>Dave</Name>
        <Phone>123</Phone>
    </Person>
</Company>
```

* priority属性是用来表示模板的优先级

```
<xsl:templatematch="Name" priority="2" ><!--模板1-->
    ...Do sth...
</xsl:template>
<xsl:templatematch="Name" priority=“1" ><!--模板2-->
    ...Do other things...
</xsl:template>
```

* 碰到Name元素时将使用priority取值较大的模板
* 模板返回类型属性as的取值，表示该模板应该返回的数据类型

```
<xsl:template match="Name" as="element()">
    ...Do sth...
</xsl:template>
```

```
<Person>
    <Name>Dave</Name>
    <phone>123</Phone>
</Person>
```

* 表示该模板将会返回一个XML元素作为结果，其中可能包含子元素和文本内容。如果该模板输出多个XML元素组成的序列、非XML元素内容或者文本内容，则XSLT处理器在执行模板的过程中将会报错
* as是一个可选的参数，如果不指定该参数，则模板可以输出任意的文本内容
* `<xsl:apply-templates>`元素
* 与根节点对应的模板中有一个名为xsl:apply-templates的元素
  * 促使XSLT处理器根据select属性（可选）指定要处理的节点集
    * 省略则表示处理元素子节点
    * 可实现对模板的递归引用
  * 模板内容的一部分由LRE组成，一部分由XSLT命名空间元素（xsl:value-of元素）组成

```
<xsl:apply-templatesselect="/People/Person" /> 
... 
<xsl:templatematch="Person">
<h3><xsl:value-ofselect="Name" /></h3>
<p><xsl:value-ofselect="Description" /></p>
<br/>
```

```
+ 路径/People/Person确定了需要搜索的节点，表示People元素是根节点的子节点，Person是People元素的子节点，xsl:apply-templates促使处理器搜索一个与Person元素节点匹配的模板
+ 模板为xsl:apply-templates元素的select属性提供了一个匹配值，则XSLT处理器在/People/Person定位路径中找到Person元素节点时就处理模板的内容，并把内容添加到目标树；应用模板的次数与匹配节点的个数相同
```

* 模板的调用
  * 在遍历（广度优先遍历）的过程中匹配调用
  * 通过名称直接调用
* 使用xsl:apply-templates在广度优先、逐层向下的遍历过程中调用模板
  * XSLT中apply-templates元素的完整语法形式如下

```
<xsl:apply-templatesselect=Expression mode=QName>
......
</xsl:apply-templates>
<xsl:templatematch="/"> <!--模板1-->
    <xsl:apply-templates/>
</xsl:template>
<xsl:templatematch="message"> <!--模板2-->
.....
 </xsl:template>
```

```
<?xml version="1.0"?>
<?xml-stylesheettype="text/xsl" href="hello.xslt"?>
<message>Hello!</message>
```

* select和mode属性都是可选的在xsl:apply-templates元素中可以传递调用参数
* select属性
  * xsl:apply-templates的作用就是指定继续遍历当前节点的所有子节点（以便根据实际路径和模板的match属性取值调用对应的模板），而select属性（取值为一个XPath表达式）允许指定仅遍历当前节点的哪些子节点（以调用相应的模板，如果存在）
  * 如果将上述源码的模板1中的<xsl:apply-templates/>更改为<xsl:apply-templatesselect="message"/>，那么将仅调用message元素所对应的模板（而不会调用处理指令所对应的模板）。这样就可以根据具体的转换要求，仅遍历文档树中的部分内容
* mode属性可实现某个节点多次处理的需要
  * 当xsl:apply-templates有一个mode属性时，只有当match和mode两个属性值都有匹配值时，其模板才可实例化
  * mode属性用于指定需要在match属性取值相同的模板中选择哪一个进行调用
  * 需要与xsl:template元素的mode属性配合使用
* mode属性可实现某个节点多次处理的需要

```
<Company>
    <Name>Acme</Name>
    <Person>
        <Name>Dave</Name>
        <Phone>123</Phone>
    </Person>
</Company>
```

```
<xsl:templatematch="/"><!--模板1-->
    <xsl:apply-templates/>
</xsl:template>
<xsl:templatematch="Company"> <!--模板2-->
    <xsl:apply-templatesselect="Name" mode="C"/>
    <xsl:apply-templatesselect="Person/Name" mode="P"/>
</xsl:template>
<xsl:templatematch="Name"mode="C"> <!--模板3-->
    ...Do sthfor Company Name...
</xsl:template>
<xsl:templatematch="Name"mode="P"> <!--模板4-->
    ...Do sthfor Person Name...
</xsl:template>
```

* 可以为模板3和模板4的match属性取不同的值
* `<xsl:variable>`和`<xsl:param>`元素
* 定义变量和参数
* 引用变量和参数使用$
* 参数可以从外部传递给转换程序，变量则在XSLT样式表内部定义
* 变量赋值 `<xsl:paramname=”searchLetter” select=”’A’”/>`
  * 使用xsl:variable的select属性 `<xsl:variablename=” variableName” select=” someExpression” />`
  * 在xsl:variable元素的起始标签和结束标签之间定义

```
<xsl:variablename=” variableName”>
<!-- Some content goes here which can define the value of the variable. -->
</xsl:variable>
```

```
+ 全局变量（xsl:stylesheet的直接子元素）可在文档转换之前用程序赋值（转换器相关）
```

* 命名模板和`<xsl:call-template>`元素
* 命名模板由xsl:template元素的name属性标识

```
<xsl:templatename=”TemplateName”>
    <!-- The template content goes here. -->
</xsl:template>
```

* 调用命名模板使用xsl:call-template元素 `<xsl:call-templatename=”TemplateName” />`
  * 不带任何参数调用命名模板
* xsl:with-param元素用于在使用xsl:template声明模板时声明参数，也用于在xsl:call-template或者xsl:apply-templates中传递调用参数
  * xsl:with-param的select属性可选，其值为表达式，表示如何选取需要传递的值

```
<xsl:call-templatename=”TemplateName”>
    <xsl:with-paramname=”ParameterName” />
    <!-- More <xsl:with-param> elements can go here. -->
</xsl:call-template>
```

```
+ 使用xsl:with-param传递一个或多个参数给命名模板
```

```
<xsl:templatename=”TemplateName”>
    <xsl:with-paramname=”ParameterName” />
    <!-- Rest of template goes here. -->
</xsl:template>
```

```
+ 要把一个参数传递给一个命名模板，该模板的定义格式（xsl:with-param）用来声明命名模板的参数
```

* 模板参数的声明和传值
* 在xsl:template元素开始标记和结束标记之间，使用xsl:param元素为所在的模板声明相应的模板参数

```
<xsl:templatename="doSth">
    <xsl:paramname="paramOne"/>
    <xsl:paramname="paramTwo"/>
    ...模板正文...
    ...使用"$paramOne" 和"$paramTwo" 引用两个模板参数... 
</xsl:template>
```

* 在xsl:call-template元素的开始标记和结束标记之间，可以使用xsl:with-param元素为所调用的模板传递所需的参数

```
<xsl:call-templatename="doSth">
    <xsl:with-paramname="paramOne"select="'One'"/>
    <xsl:with-paramname="paramTwo"select="."/>
</xsl:call-template>
```

```
+ 使用xsl:with-param元素时必须指明具体的模板参数名称，以便为其进行赋值，所以可以不按照声明时的顺序书写可以使用xsl:with-param元素的as属性，为形式参数指定数据类型 
```

* XSLT中的内置模板
* 内置模板（Built-in Templates）是XSLT中的一个关键内容，对于理解XSLT对XML文档树结构的遍历方式、模板调用机制等都是至关重要的
* 通过一个具体的示例来说明内置模板的存在，并观察和解释各种内置模板的含义、以及处理对象

```
<xsl:stylesheetversion=“1.0"xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:templatematch="*|/"><!--模板1-->
    <xsl:apply-templates/>
</xsl:template>
<xsl:templatematch="text()|@*"> <!--模板2--> 
    <xsl:value-ofselect="."/>
    </xsl:template>
<xsl:templatematch="processing-instruction()|comment()"/> <!--模板3-->
```

* 内置模板的作用在于能够让我们集中精力编写相关节点的处理模板，而无需过多地操心整个遍历过程中模板的逐层调用
* 只有在用户没有自定义处理某个节点的模块规则时，才会调用内置模块中的规则，否则，用户自定义的模块规则将覆盖内置模块中的规则

```
<xsl:stylesheetversion="2.0"xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <!--transform the input root (/) and the message element-->
    <xsl:templatematch="message">
    .....
    </xsl:template>
</xsl:stylesheet>
```

* `<xsl:value-of>`元素
* 提供源树中某一部分的值
  * 必须有一个select属性表明定位路径
  * 模板内容的一部分由LRE组成，一部分由XSLT命名空间元素（xsl:value-of元素）组成

```
<html>
<head>
<title>Information about
<xsl:value-of select="count(/People/Person)" /> people.</title> </head>
<body>
<h3>Information about
<xsl:value-ofselect="count(/People/Person)" />people.</h3> <title>Information about 3 people.</title>
```

```
<xsl:templatematch=“Person”>
<h3><xsl:value-ofselect=“Name” /></h3>
<p><xsl:value-of select=“Description” /></p>
<br/>
</xsl:template>
```

* 上下文节点（Context Node）
  * 上下文是指当前处理器正在处理的节点的位置，该节点称为上下文节点
  * 上下文不只包括上下文节点，也包括上下文位置、上下文大小等

```
<xsl:templatematch=“Person”>
<h3><xsl:value-ofselect=“Name” /></h3>
<p><xsl:value-of select=“Description” /></p>
<br/>
</xsl:template>
```

* 可获得XML文档结构树中所有节点的值 |节点类型|节点值| |-|-| |根节点|用“/”匹配，通常不直接求节点值| |指令|用processing-instruction()匹配，值不包含值令名称、<？和？>| |注释|用comment（）匹配，值不包含\<?--和-->| |元素|可用多种方式匹配，值为元素本身以及元素内容| |元素属性|用@属性名匹配，值为属性值，不含双引导| |元素内容|用text()匹配，元素本身包含的文本内容|
* 节点选择方式
* `<xsl:template>`的match属性用于指定要匹配的节点
* `<xsl:copy-of>`, `<xsl:for-each>`, `<xsl:sort>`, `<xsl:apply-template>`和`<xsl:value-of>`的select属性用于选择节点
* `<xsl:copy>`元素
* 把一个节点复制到目标树，但不复制子孙节点
* 如果上下文节点是一个元素节点，则不会复制节点的任何属性值
  * 使用某个元素并可改变其内容或增删属性

```
<Persons>
    <Person />
    <Person />
    <Person />
</Person>
```

* 只处理xsl:copy

```
<?xml version=“1.0” encoding=“UTF-8”?>
<Persons>
    <Person FirstName=“Jill” LastName=“Harper”/>
    <Person FirstName=“Claire” LastName=“Vogue”/>
    <Person FirstName=“Paul” LastName=“Cathedral”/>
</Persons>
```

* 使用xsl:attribute增加属性
* 深度复制，把一个节点及其所有属性节点和子孙节点都复制到目标树 ||xsl:copy|xsl:copy-of| |-|-|-| |功能|将当前节点从源文档复制到目标树|复制任何节点集到目标树| |对当前节点的处理|仅复制当前节点，不复制其子元素或者属性|复制节点及其所有的子孙节点，包括属性和子元素| |节点内容|可以使用XSLT代码为新的节点创建内容，如果当前节点是元素节点或者根节点|所有的内容都来自select属性中指定的节点集|
* `<xsl:output>`元素
* 使用method属性从XML, HTML或文本文档中选择一种输出格式
  * method属性的值大小写敏感，并且必须小写（xml, html, text）

`<xsl:output method=“output type” />`

* `<xsl:if>`元素
* 测试一个布尔条件
  * 为真则实例化`<xsl:if>`元素的内容
  * 为假则`<xsl:if>`元素的内容不会被添加到目标树
  * 输出一些内容或没有任何输出

```
<Characters>
    <Character age=“99”>Julius Caesar</Character>
    <Character age=“23”>Anne Boleyn</Character>
    <Character age=“41”>George Washington</Character>
    <Character age=“45”>Martin Luther</Character>
    <Character age=“800”>Methuselah</Character>
    <Character age=“119”>Moses</Character>
    <Character age=“50”>Asterixthe Gaul</Character>
</Characters>
```

```
<xsl:templatematch=“Character”> 
    <xsl:iftest=“@age > 110 ” >
    <p><b><xsl:value-ofselect=“.” /></b> is older than expected. Please check if this character’s age, <b><xsl:value-ofselect=“@age” /></b>, is correct.</p>
    </xsl:if>
</xsl:template>
```

* test属性返回false时，Character元素的模板不输出任何内容
* `<xsl:choose>`元素
* 多个选项中选取一个
  * xsl:choose可以有任意个xsl:when元素作为其子元素，每一个都有一个test属性进行逻辑判断
  * 如果xsl:when元素内容均未输出，则输出xsl:otherwise元素内容

```
<xsl:templatematch=“Character”>
    <xsl:choose>
        <xsl:whentest=“@age > 110” >
            <p><b><xsl:value-ofselect=“.” /></b> - too high. Please check if this character’s age, <b><xsl:value-ofselect=“@age” /></b>, is correct.</p>
            </xsl:when>
            <xsl:otherwise>
                <p><b><xsl:value-ofselect=“.” /></b> - ok</p>.         
            </xsl:otherwise>
    </xsl:choose>
</xsl:template>
```

* `<xsl:for-each>`元素
* 把嵌入其中的XSLT指令作用到节点集的每个元素
* 可迭代处理整个节点集，并为节点集中每个节点生成输出文档
  * 理论上处理器可按任意顺序处理节点集中的节点

```
<xsl:templatematch=“Object”>
<ul>
    <xsl:for-eachselect=”Characteristic”>
    <li><xsl:value-ofselect=”.” /></li>
    </xsl:for-each>
</ul>
</xsl:template> 
```

用LRE表示无序列表的起始标签和结束标签（`<ul>`和`</ul>`），上下文节点是Object元素节点，xsl:for-each为上下文节点的每个子节点生成一个列表项，列表项对应于上下文节点的每个Characteristic元素

* `<xsl:sort>`元素
* 可对节点集中的元素排序，可多次使用
  * 元素在输出中的顺序可完全不同于节点在源文档中的顺序
* 可与xsl:apply-templates和xsl:for-each一起使用

```
<xsl:apply-templatesselect=”/Objects/Object” >     
    <xsl:sortselect=”@name” />
</xsl:apply-templates> 
```

* xsl:sort的select属性值是一个相对定位路径@name，是Object的子节点name属性节点

```
<xsl:templatematch=”Object”>
    <h3>Characteristics of <xsl:value-ofselect=”@name” /></h3>
    <ul>
        <xsl:for-eachselect=”Characteristic”>
        <xsl:sortselect=”.” order=”descending” />
        <li><xsl:value-ofselect=”.” /></li>
        </xsl:for-each>
    </ul>
</xsl:template> 
```

* xsl:sort的order属性来说明排序模式，默认排序为升序
* `<xsl:include>`和`<xsl:import>`元素
* 都是xsl:stylesheet的直接子元素
* xsl:include将外部的样式单复制到该元素所在位置，一个样式单只能被包含一次，被包含样式单的模板规则与包含者规则优先级相同

```
<xsl:stylesheetversion="1.0"xmlns:xsl="...">    
    <xsl:includehref="Utility.xsl"/>     
    <xsl:includehref="Tools.xsl"/>
</xsl:stylesheet>
```

```
<xsl:stylesheetversion="1.0"xmlns:xsl="...">
    <xsl:importhref="Utility.xsl"/>
    <xsl:importhref="Tools.xsl"/>
    <xsl:templatematch="node">
    <xsl:apply-imports/>
     ...
</xsl:stylesheet>
```

* xsl:import和xsl:include的区别
* import与include必须为顶层元素，如果import与include同时存在，那么import在include之前声明
* include与原样式表中的模板处于完全相同的地位（具有相同的默认优先级）,没有任何差别，但是import导入的模板则具有较低的默认优先级
* importadds components from another schema with a different namespace nnincludeassociates with the target namespace


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://rocape.gitbook.io/xmllanguage/xslt/63xslt-yang-shi-dan-de-yuan-su-he-zhi-ling.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
