```
`< xsl:if>`标签使用`test =“”`属性指定布尔条件。在这种情况下,将测试 type 属性的值,并且生成的列表会根据值是有序还是无序而更改。
请注意此示例中的两个重要事项:
* 没有 else 子句,也没有返回或退出语句,因此需要两个`< xsl:if>`标签涵盖了两个选项。 (或者可以使用`< xsl:choose>`标签,它提供了 case 语句功能)。
* 属性值周围需要单引号。否则,XSLT 处理器会尝试将有序字解释为 XPath 函数而不是字符串。
现在通过处理 ITEM 元素完成 LIST 处理:
```java
```
## 样式表中的订购模板
到目前为止,您应该知道模板彼此独立,因此它们在文件中出现的位置通常并不重要。因此,从现在开始,我们将仅显示您需要添加的模板。 (为了便于比较,它们总是添加在示例样式表的末尾)。
当两个模板可以应用于同一节点时,顺序确实有所不同。在这种情况下,最后定义的那个是找到并处理的那个。例如,要将缩进列表的顺序更改为使用小写字母,可以指定如下所示的模板模式: `// LIST // LIST` 。在该模板中,您将使用 HTML 选项生成字母枚举,而不是数字枚举。
但是这样的元素也可以通过模式`// LIST`来识别。为了确保正确处理,指定`// LIST`的模板必须出现在指定`// LIST // LIST`的模板之前。
## 过程`<注意>`元素
最后剩下的结构元素是`NOTE`元素。添加以下模板来处理它。
```java
Note:
```
该代码提出了一个有趣的问题,该问题是由于包含`< br />而产生的。`标签。要使文件格式良好的 XML,必须在样式表中将标记指定为`< br />` ,但很多浏览器都无法识别该标签。虽然大多数浏览器都能识别序列`< br>< / br>` ,他们都把它视为一个段落而不是单个换行符。
换句话说,转换必须产生`< br>。`标签,但样式表必须指定`< br />` 。这就是我们在样式表的早期添加的特殊输出标记的主要原因:
```java
[...]
```
该输出规范转换空标签,例如`< br />。`到他们的 HTML 表格,`< br>` ,关于输出。这种转换非常重要,因为大多数浏览器都无法识别空标签。以下是受影响标签的列表:
```java
area frame isindex
base hr link
basefont img meta
br input param
col
```
总而言之,默认情况下,XSLT 在输出上生成格式良好的 XML。并且因为 XSL 样式表是格式良好的 XML,所以你不能轻易地放置诸如`< br>之类的标签。`在它的中间。 `< xsl:output method =“html”/>`标签解决了这个问题,因此您可以编码`< br />样式表中的`但得到`< br>`在输出中。
指定`< xsl:output method =“html”/>的另一个主要原因`就像规范`< xsl:output method =“text”/>一样`,生成的文本未被转义。例如,如果样式表包括`<`实体参考,它将显示为`<生成的文本中的`字符。另一方面,当生成 XML 时,`<样式表中的`实体引用将保持不变,因此它将显示为`<生成的文本中的`。
* * *
**注**:如果你真的想要`<`作为 HTML 输出的一部分生成,您需要将其编码为`& lt;` 。该序列变为`<`关于输出,因为只有`&`转换为`&`字符。
* * *
### 使用`LIST`和`注`元素定义运行`Stylizer`样例
1. **导航至`样例`目录。**
```java
%cd install-dir / jaxp-1_4_2- 释放日期 /样例。
```
2. **[`Download the XSLT examples by clicking this link`](../examples/xslt_samples.zip) 并将它们解压缩到 _install-dir_ `/ jaxp-1_4_2-` _ 释放日期 _ `/样例`目录。**
3. **导航到`xslt`目录。**
```java
cd xslt
```
4. **Compile the `Stylizer` sample.**
键入以下命令:
```java
% javac Stylizer.java
```
5. **Run the `Stylizer` sample on `article2.xml` using the stylesheet `article2.xsl`.**
```java
% java Stylizer data/article2.xsl data/article2.xml
```
以下是您现在运行程序时为第二部分生成的 HTML:
```java
...
<h2>The Second Major Section
</h2>
<p>This section adds a LIST and a NOTE.
</p>
<p>Here is the LIST:
</p>
<ol>
<li>Pears</li>
<li>Grapes</li>
</ol>
<p>And here is the NOTE:
</p>
<blockquote>
<b>Note:</b>
<br>Do not forget to go to the hardware store on your way to the grocery!
</blockquote>
```
## 处理内联(内容)元素
`ARTICLE`类型中唯一剩下的标签是内联标签 - 不在输出中创建换行符的标签,而是集成到它们所属的文本流中。
内联元素与结构元素的不同之处在于内联元素是标记内容的一部分。如果将元素视为文档树中的节点,则每个节点都具有内容和结构。内容由它包含的文本和内联标签组成。该结构由标签下的其他元素(结构元素)组成。
* * *
**注**:本节中描述的示例文档是`article3.xml` ,用于操作它的样式表是`article3.xsl` 。结果是`stylizer3.html` 。
* * *
首先在示例文档中添加一位测试数据:
```java
A Sample ArticleThe First Major Section
[...]
The Second Major Section
[...]
The Third
Major Section
In addition to the inline tag
in the heading,
this section defines the term
inline,
which literally means "no line break".
It also adds a simple link to the main page
for the Java platform
(http://java.sun.com),
as well as a link to the
XML
page.
```
现在处理内联`< DEF>段落中的`元素,将它们重命名为 HTML 斜体标记:
```java
```
接下来,注释掉文本节点规范化。它已经达到了它的目的,现在你需要保留重要的空间:
```java
```
这种修改使我们在诸如`< I>之类的标签之前不会丢失空格。`和`< DEF>` 。 (尝试没有此修改的程序以查看结果)。
现在处理基本的内联 HTML 元素,例如`< B>` ,`< I>`和`< U>`用于粗体,斜体和下划线。
```java
```
`< xsl:element>`标签可让您计算要生成的元素。在这里,您使用当前元素的名称生成适当的内联标记。特别要注意在`name =“..”`表达式中使用花括号( `{}` )。这些花括号使得引号内的文本被处理为 XPath 表达式,而不是被解释为文字字符串。这里,它们使 XPath `name()`函数返回当前节点的名称。
可以在属性值模板可以出现的任何位置识别大括号。 (属性值模板在 XSLT 规范的 7.6.2 节中定义,它们出现在模板定义中的几个位置)。在这样的表达式中,花括号也可以用来指代属性的值`{@foo}` ,或者指向元素`{foo}`的内容。
* * *
**注**:您还可以使用`< xsl:attribute>生成属性。` 。有关更多信息,请参阅 XSLT 规范的 7.1.3 节。
* * *
最后一个元素是`LINK`标签。处理该标记的最简单方法是设置一个我们可以使用参数驱动的命名模板:
```java
```
此模板的主要区别在于,您可以使用`name =“”`子句为模板命名,而不是指定匹配子句。因此,只有在您调用此模板时才会执行此模板。
在模板中,您还可以使用`< xsl:param>指定名为`dest`的参数。`标签。对于一些错误检查,使用 select 子句为该参数提供默认值`UNDEFINED` 。引用`< xsl:value-of>中的变量`标签,指定。
* * *
**注**:回想一下引号中的条目被解释为表达式,除非它进一步用单引号括起来。这就是为什么在`“@ type ='ordered'”`中需要单引号以确保有序被解释为字符串。
* * *
`< xsl:element>`标签生成一个元素。以前,您可以通过编码类似`< html>的内容来简单地指定我们想要的元素。` 。但是在这里,您在`< xsl:element>的主体中动态生成 HTML 锚点(`< a>` )的内容。`标签。并且您使用`< xsl:attribute>动态生成锚点的`href`属性。`标签。
模板的最后一个重要部分是`< apply-templates>`标签,用于插入`LINK`元素下文本节点的文本。没有它,生成的 HTML 链接中将没有文本。
接下来,添加`LINK`标签的模板,并从中调用命名模板:
```java
[...]
```
如果 LINK 标记中存在目标属性,则`test =“@ target”`子句返回 true。所以这`< xsl-if>当链接的文本和为其定义的目标不同时,`标记会生成 HTML 链接。
`< xsl:call-template>`标签调用命名模板,而`< xsl:with-param>`使用 name 子句指定参数,并使用 select 子句指定其值。
作为样式表构建过程的最后一步,添加`< xsl-if>`标签处理没有目标属性的`LINK`标签。
```java
[...]
```
`not(...)`子句反转了之前的测试(记住,没有 else 子句)。因此,当未指定 target 属性时,将解释模板的这一部分。这次,参数值不是来自 select 子句,而是来自`< xsl:with-param>的内容。`元素。
* * *
**注**:只是为了明确:参数和变量(在[中稍后讨论过 XSLT 可以做什么?](#ggyut)可以通过 select 子句指定它们的值,允许您使用 XPath 表达式,或者使用元素的内容,这样可以使用 XSLT 标记。
* * *
在这种情况下,参数的内容由`< xsl:apply-templates />生成。`标签,用于在`LINK`元素下插入文本节点的内容。
### 运行带有内联元素的`样式器`样例
1. **导航至`样例`目录。**
```java
%cd install-dir / jaxp-1_4_2- 释放日期 /样例。
```
2. **[`Download the XSLT examples by clicking this link`](../examples/xslt_samples.zip) 并将它们解压缩到 _install-dir_ `/ jaxp-1_4_2-` _ 释放日期 _ `/样例`目录。**
3. **导航到`xslt`目录。** <
```java
cd xslt
```
4. **Compile the `Stylizer` sample.**
键入以下命令:
```java
% javac Stylizer.java
```
5. **Run the `Stylizer` sample on `article3.xml` using the stylesheet `article3.xsl`.**
```java
% java Stylizer data/article3.xsl data/article3.xml
```
现在运行程序时,结果应如下所示:
```java
[...]
<h2>The <i>Third</i> Major Section</h2>
<p>In addition to the inline tag in the heading, this section defines the term <i>inline</i>, which literally means "no line break". It also adds a simple link to the main page for the Java platform (<a href="http://java.sun.com">http://java.sun.com</a>), as well as a link to the <a href="http://java.sun.com/xml">XML</a> page.</p>
```
干得好!您现在已经将一个相当复杂的 XML 文件转换为 HTML。 (就像它最初看起来一样简单,它确实为探索提供了很多机会)。
## 打印 HTML
您现在已将 XML 文件转换为 HTML。有一天,有人会生成一个 HTML 识别的打印引擎,您可以通过 Java Printing Service API 找到并使用它。此时,您将能够通过生成 HTML 来打印任意 XML 文件。您所要做的就是设置样式表并使用浏览器。
## XSLT 还能做什么?
与本节一样冗长,它只是触及了 XSLT 功能的表面。 XSLT 规范中有许多其他可能性等着您。以下是一些需要注意的事项:
`import` (Section 2.6.2) and `include` (section 2.6.1)
`rt` (第 2.6.2 节)和 include(第 2.6.1 节)使用这些语句来模块化和组合 XSLT 样式表。 include 语句只是插入包含文件中的任何定义。 import 语句允许您使用自己的样式表中的定义覆盖导入文件中的定义。
`for-each` loops (section 8)
循环遍历项目集合并依次处理每个项目。
`choose` (case statement) for conditional processing (section 9.2)
根据输入值分支到多个处理路径之一。
Generating numbers (section 7.7)
动态生成编号的部分,编号的元素和数字文字。 XSLT 提供三种编号模式:
* 单个:单个标题下的数字项,如 HTML 中的有序列表
* 多个:生成多级编号,例如“A.1.3”
* 任何:连续编号项目出现在任何地方,如课程中的脚注。
Formatting numbers (section 12.3)
控制枚举格式,以便您获得数字( `format =“1”`),大写字母( `format =“A”`),小写字母( `format =“a”`)或复合数字,如“A.1”,以及适合特定国际区域的数字和货币金额。
Sorting output (section 10)
以所需的排序顺序生成输出。
Mode-based templates (section 5.7)
多次处理元素,每次都处于不同的“模式”。您将模式属性添加到模板,然后指定`< apply-templates mode =“...”>`仅应用具有匹配模式的模板。结合`< apply-templates select =“...”>`属性将基于模式的处理应用于输入数据的子集。
Variables (section 11)
变量类似于方法参数,因为它们可以让您控制模板的行为。但它们没有您想象的那么有价值。变量的值仅在当前模板的范围内已知或`< xsl:if>`标签(例如)中定义的标签。您不能将值从一个模板传递到另一个模板,甚至不能从模板的封闭部分传递到同一模板的另一部分。
即使对于“全局”变量,这些陈述也是正确的。您可以在模板中更改其值,但更改仅适用于该模板。当评估用于定义全局变量的表达式时,该评估将在结构的根节点的上下文中进行。换句话说,全局变量本质上是运行时常量。这些常量可用于更改模板的行为,尤其是在与 include 和 import 语句结合使用时。但变量不是通用的数据管理机制。
## 变量的麻烦
创建单个模板并为链接的目标设置变量很有诱惑力,而不是设置参数化模板并以两种不同的方式调用它。我们的想法是将变量设置为默认值(例如, `LINK`标签的文本),然后,如果目标属性存在,则将目标变量设置为目标属性的值。
这将是一个好主意 - 如果它奏效。但同样,问题是变量只在定义它们的范围内才知道。所以当你编码`< xsl:if>`标签用于更改变量的值,该值仅在`< xsl:if>的上下文中已知。`标签。一旦`< / xsl:if>遇到`,变量设置的任何更改都将丢失。
同样诱人的想法是用变量()替换`text()| B | I | U | DEF | LINK`规范的可能性。但是因为变量的值由定义的位置确定,所以全局内联变量的值由文本节点,`< B>组成。`节点,等等,恰好存在于根级别。换句话说,在这种情况下,这种变量的值为空。