电脑爱好者,提供IT资讯信息及各类编程知识文章介绍,欢迎大家来本站学习电脑知识。 最近更新 | 联系我们 RSS订阅本站最新文章
电脑爱好者
站内搜索: 
当前位置:首页>> XML专区>>XML教程第14章 XSL变换 -3:

XML教程第14章 XSL变换 -3

来源:远方网络 | 2006-2-26 | (有2776人读过)

="."告诉格式化程序取匹配的元素(本例中的ATOM)的值。

第二种方法是使用xsl:for-each。xsl:for-each元素依次处理由其select特性选择的每个元素。不过,无需任何附加的模板。例如:

<xsl:template match="PERIODIC_TABLE">

<xsl:for-each select="ATOM">

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

</xsl:for-each>

</xsl:template>

如果省略select特性,那么处理源节点(本例中的PERIODIC_TABLE)的所有子节点。

<xsl:template match="PERIODIC_TABLE">

<xsl:for-each>

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

</xsl:for-each>

</xsl:template>

14.6 匹配节点的模式

xsl:template元素的match特性支持复杂的语法,允许人们精确地表达想要和不想要与哪个节点匹配。xsl:apply-templates、xsl:value-of、xsl:for-each、xsl:copy-of和xsl:sort的select特性支持功能更加强大的语法的超集,允许人们精确地表达想要和不想要选择哪个节点。下面讨论匹配和选择节点的各种模式。

14.6.1 匹配根节点

为了使输出的文档结构整洁。从XSL变换的第一个输出内容应为输出文档的根元素。因此,XSL样式单一般以应用于根节点的规则开始。要在规则中指定根节点,可将其match特性设置为合适的值。例如:

<xsl:template match="/">

<html>

<xsl:apply-templates/>

</html>

</xsl:template>

本规则应用于根节点,并且只应用于输入树形结构的根节点。当读取到此根节点时,就输出<html>标记,处理根节点的子节点,然后输出</html>标记。本规则推翻了根节点的缺省规则。**14-6显示了应用于根节点的带有单一规则的样式单。

**14-6:用于根节点的带有单一规则的XSL样式单

<?xml version="1.0"?>

<xsl:stylesheet

xmlns:xsl="http://www.w3.org/XSL/Transform/1.0">

<xsl:template match="/">

<html>

<head>

<title>Atomic Number vs. Atomic Weight</title>

</head>

<body>

<table>

Atom data will go here

< /table>

</body>

</html >

</xsl:template>

</xsl:stylesheet>

由于本样式单只为根节点提供一条规则,并且由于规则的模板未指明对子节点进行进一步的处理,因而只是按原样输出,所以在模板中所看到的所有内容都将插入到结果文档中。换句话说,将**14-6中的样式单应用于**14-1(或其他任何结构整洁的XML文档)中,所获得的结果如下:

<html><head><title>Atomic Number vs. Atomic

Weight</title></head><body><table>

Atom data will go here

</table></body></html>

14.6.2 匹配元素名

正如前面介绍的那样,最基本的模式只包含一个元素名,用来匹配所有带有该名的元素。例如,下面的模板与ATOM元素相匹配,并将ATOM元素的ATOMIC_NUMBER的子元素标成粗体:

<xsl:template match="ATOM">

<b><xsl:value-of select="ATOMIC_NUMBER"/><b>

</xsl:template>

**14-7显示的是扩充了**14-6的样式单。首先,在根节点的规则模板中包括了xsl:apply-templates元素。此规则使用select特性来确保只有PERIODIC_TABLE元素获得处理。

其次,使用match="PERIODIC_TABLE"语句创建了只适用于PERIODIC_TABLE元素的规则。本规则设置周期表的标题,然后应用模板来从ATOM元素中生成周期表的主体。

最后,ATOM规则使用<xsl:apply-templates select="NAME"/>、<xsl:apply-templates select="ATOMIC_NUMBER"/>和<xsl:apply templates select="ATOMIC_WEIGHT"/>,明确地选择ATOM元素的NAME、ATOMIC_NUMBER和ATOMIC_WEIGHT子元素。它们都包装在HTML的tr和td元素中,以便最终的结果是与原子量相匹配的原子序数表。图14-4显示将**14-7中的样式单应用于整个周期表文档中的输出结果。

对本样式单需要注意的是:在输入文档中的NAME、ATOMIC_NUMBER和ATOMIC_WEIGHT元素的精确顺序是不重要的。它们在输出文档中以选择它们的顺序出现,也就是说首先为原子序数,然后是原子量。相反,在输入文档中,各个原子依字母顺序排序。以后,将会看到如何使用xsl:sort元素来改变这个顺序,以便使用更常规的原子序数的顺序来排列原子。

**14-7:利用select的施用于元素的特定类的模板

<?xml version="1.0"?>

<xsl:stylesheet

xmlns:xsl="http://www.w3.org/XSL/Transform/1.0">

<xsl:template match="/">

<html>

<head>

<title>Atomic Number vs. Atomic Weight</title>

</head>

<body>

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

</body>

</html>

</xsl:template>

<xsl:template match="PERIODIC_TABLE">

<hl>Atomic Number vs. Atomic Weight</hl>

<table>

<th>Element</th>

<th>Atomic Number</th>

<th>Atomic Weight</th>

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

</table>

</xsl:template>

<xsl:template match="ATOM">

<tr>

<td><xsl:value-of select="NAME"/></td>

<td><xsl:value-of select="ATOMIC_NUMBER"/></td>

<td><xsl:value-of select="ATOMIC_WEIGHT"/></td>

</tr>

</xsl:template>

</xsl:stylesheet>

图14-4 Netscape Navigator 4.5中显示的原子序数与原子量的关系表

14.6.3 使用/字符匹配子节点

在match特性中并不局限于当前节点的子节点,可使用/符号来匹配指定的元素后代。当单独使用/符号时,它表示引用根节点。但是,在两个名称之间使用此符号时,表示第二个是第一个的子代。例如,ATOM/NAME引用NAME元素,NAME元素为ATOM元素的子元素。

在xsl:template元素中,这种方法能够用来只与某些给定类型的元素进行匹配。例如,下面的模板规则将ATOM子元素的SYMBOL元素标记为strong。此规则与不是ATOM元素的直系子元素的SYMBOL元素无关。

<xsl:template match="ATOM/SYMBOL">

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

</xsl:template>

请记住,本规则选择的是作为ATOM元素子元素的SYMBOL元素,而不是选择拥有SYMBOL子元素的ATOM元素。换句话说,在<xsl:value-of select="."/>中的.符号引用的是SYMBOL,而不是ATOM。

将模式写成一行的形成,就可以指定更深层的匹配。例如,PERIODIC_TABLE / ATOM / NAME选择的是其父为ATOM元素(其父为PERIODIC_TABLE元素)的NAME元素。

还可以使用*通配符来代替层次结构中的任意元素名。例如,下面的模板规则应用于PERIODIC_TABLE孙元素的所有SYMBOL元素。

<xsl:template match="PERIODIC_TABLE/*/SYMBOL">

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

</xsl:template>

最后一点,就如上面所看到的那样,单独的/本身,表示选择文档的根节点。例如,下面的规则应用于文档根元素的所有PERIODIC_TABLE元素。

<xsl:template match="/PERIODIC_TABLE">

<html><xsl:apply templates/></html>

</xsl:template>

虽然 / 引用根节点,但/* 则引用任意根元素。例如,

<xsl:template match="/*">

<html>

<head>

<title>Atomic Number vs. Atomic Weight</title>

</head>

<body>

<xsl:apply-templates/>

</body>

</html>

</xsl:template>

14.6.4 使用//符号匹配子代

有时候,尤其是使用不规则的层次时,更容易的方法就是越过中间节点、只选择给定类型的所有元素而不管这些元素是不是直系子、孙、重孙或其他所有的元素。双斜杠(//)引用任意级别的后代元素。例如,下面的模板规则应用于PERIODIC_TABLE的所有NAME子代,而不管它们具有何种层次的关系:

<xsl:template match=" PERIODIC_TABLE //NAME">

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

</xsl:template>

周期表实例相当简单,一看就懂,但这种技巧在更深层次,尤其是当元素包含该类的其他元素时(例如ATOM包含ATOM),就显得更加重要。

模式开头的操作符选择根节点的任何子节点。例如,下面的模板规则处理所有的ATOMIC_NUMBER元素,而同时完全忽略其位置:

<xsl:template match="// ATOMIC_NUMBER ">

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

</xsl:template>

14.6.5 通过ID匹配

有人或许想把一特定的样式应用于特定的单一元素中,而不改变该类型的所有其他元素。在XSL中实现此目的的最简单的方法是,将样式与元素的ID匦韵喙亓?墒褂胕d()选择符(其中包括以单引号括起来的ID值)做到这一点。例如,下面的规则使带有ID值为e47的元素变为粗体:

<xsl:template match="id('e47')">

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

</xsl:template>

当然,上面假设以此方式选择的元素具有在源文档的DTD中声明为ID类型的特性。但是,通常情况并非如此。首先,许多文档没有DTD,只不过结构整洁,但不合法。即使有DTD,也无法确保任何元素都有ID类型的特性。可以在样式单中使用xsl:key元素,用来把输入文档中的特定特性声明为应该作为ID来看待。

14.6.6 使用@来匹配特性

正如第5章已经看到的那样,@符号根据特性名与特性相匹配,并选择节点。方法很简单,只需在要选择的特性前加上@符号。例如,**14-8显示一样式单,用它来输出一张原子序数和熔点对照的表格。不仅写出了MELTING_POINT的值,而且也写出了UNITS特性的值。这是由于<xsl :value-of select="@UNITS"/>所获得的结果。

**14-8:使用@来选择UNITS特性的XSL样式单

<?xml version="1.0"?>

<xsl:stylesheet

xmlns:xsl="http://www.w3.org/XSL/Transform/1.0">

<xsl:template match="/PERIODIC_TABLE">

<html>

<body>

<hl>Atomic Number vs. Melting Point</hl>

<table>

<th>Element</th>

<th>Atomic Number</th>

<th>Melting Point</th>

<xsl:apply-templates/>

</table>

</body>

</html>

</xsl:template>

<xsl:template match="ATOM">

<tr>

<td><xsl:value-of select="NAME"/></td>

<td><xsl:value-of select="ATOMIC_NUMBER"/></td>

<td><xsl:apply-templates select="MELTING_POINT"/></td>

</tr>

</xsl:template>

<xsl:template match="MELTING_POINT">

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

<xsl:value-of select="@UNITS"/>

</xsl:template>

</xsl:stylesheet>

回想一下,特性节点的值只是此特性的字符串值。一旦应用**14-8中的样式单,ATOM元素就会格式化成如下形成:

<tr><td>Hydrogen</td><td>l</td><td>13.8lKelvin</td></tr>

 

<tr><td>Helium</td><td>2</td><td>0.95Kelvin</td></tr>

可以使用各种层次操作符将特性与元素组合起来。例如,BOILING_POINT/@UNITS引用BOILING_POINT元素的UNITS特性。ATOM/*/@UNITS就能匹配ATOM子元素的任何UNITS元素。当与模板规则中的特性匹配时,这种做法是特别有用的。必须记住,要匹配的是特性节点,而不是包含它的元素。最常见的错误是,不知不觉地将特性节点与包含它的元素节点搞混淆。例如,请看下面的规则,它试图将模板应用于具有UNITS特性的所有子元素:

<xsl:template match="ATOM">

<xsl:apply-templates select="@UNITS"/>

</xsl:template>

上面语句实际上做的是,将模板应用于ATOM元素中并不存在的UNITS特性。

也可以使用*来选择元素的所有特性,例如,BOILING_POINT/@*可选择BOILING_POINT元素的所有特性。



14.6.7 使用comments()来匹配注释

大多数时候,可能应该完全忽略XML文档中的注释。要使注释成为文档的必不可少的部分,确实不是好主意。但是,当不得不选择注释时,XSL确实提供了选择注释的手段。

为了选择注释,可使用comment()模式。尽管此模式有类似函数的圆括号,但实际上决不带任何参数。要区分不同的注释不太容易。例如,回想一下DENSITY元素具有如下的形式:

<DENSITY UNITS="grams/cubic centimeter"><!- At 300K ->

6.51

</DENSITY>

此模板规则不仅输出密度的值和单位,而且还打印测量密度的条件:

<xsl:template match="DENSITY">

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

<xsl:value-of select="@UNITS"/>

<xsl:apply-templates select="comment()"/>

</xsl:template>

**14-1使用注释而不是特性或元素来指定条件,就是为了用于本例。实际应用时,决不要将重要信息放在注释中。XSL允许人们选择注释的唯一真实的理由是,为了用样式单把一种标记语言变换成另一种标记语言,同时又能使注释保持不变。选择注释的任何其他方面的用途都意味着原文档设计得不好。下面的规则匹配所有的注释,并使用xsl:comment元素将它们再次复制出来。

<xsl:template match="comment()">

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

</xsl:template>

可是,要注意,用于施加模板的缺省规则对注释无效。因此,遇到注释时,如果要使缺省规则起作用,需要包括xsl:apply-templates元素,无论注释放在何处,此元素都能选择注释。

使用层次操作符可以选择特定的注释。例如,下面的规则匹配DENSITY元素内部的注释:

<xsl:template match="DENSITY/comment()">

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

</xsl:template>

14.6.8 使用pi()来匹配处理指令

谈到编写结构化的、智能化的、可维护的XML时,处理指令并不比注释好。但是都有一些必需的应用,其中包括将样式单附加到文档上。

pi()函数选择处理指令。pi()的参数是放在引号内的字符串,表示要选择的处理指令的名称。如果没有参数,则匹配当前节点的第一个处理指令子节点。但是,可以使用层次操作符。例如,下面的规则匹配根节点的第一个处理指令子节点(很可能是xml-stylesheet处理指令)。xsl:pi元素使用指定的名称和输出文档中的值来插入一个处理指令。

<xsl:template match="/pi()">

<xsl:pi name="xml-stylesheet">

type="text/xsl" value="auto.xsl"

</xsl:pi>

</xsl:template/>

下列规则也匹配xml-stylesheet处理指令,但是通过其名称来匹配的:

<xsl:template match="pi( xml-stylesheet )">

<xsl:pi name="xml-stylesheet">

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

</xsl:pi>

</xsl:template/>

事实上,区分根元素和根节点的主要原因之一就是,为了读取和处理序言中的处理指令。尽管xml-stylesheet处理指令使用"名称=值"这样的句法,但XSL并不把它们当做特性看待,这是因为处理指令不是元素。处理指令的值只是跟在其名称后面的空格和结束符?>之间的所有内容。

用来施加模板的缺省规则并不匹配处理指令。因此,遇到xml-stylesheet处理指令时,如果要使缺省规则起作用,需要包括xsl:apply-templates元素,此元素在适当的地方匹配缺省规则。例如,下面这个用于根节点的模板确实将模板应用于处理指令:

<xsl:template match="/">

<xsl:apply-templates select="pi()"/>

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

</xsl:template>

14.6.9 用text()来匹配文本节点

尽管文本节点的值包括在选择的元素值部分中,但它们作为节点通常被忽视。但是,text()操作符确实能够明确选择一个元素的文本子元素。尽管这种操作符有圆括号,但不需要任何参数。例如:

<xsl:template match="SYMBOL">

<xsl:value-of select="text()"/>

</xsl:template>

此操作符存在的主要原因是为了用于缺省规则。无论作者是否指定缺省规则,XSL处理程序必须提供下列的缺省规则:

<xsl:template match="text()">

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

</xsl:template>

这意味着无论何时将模板应用于文本节点,就会输出此节点的文本。如果并不需要这种缺省行为,可以将其推翻。例如,在样式单中,包括下列空模板规则,将会阻止输出文本节点,除非另外的规则明确地匹配。

<xsl:template rnatch="text()">

</xsl:template>

14.6.10 使用"或"操作符|

竖线(|)允许一条模板规则匹配多种模式。如果节点与某种模式相匹配,则此节点将激活该模板。例如,下面模板规则与ATOMIC_NUMBER和ATOMIC_WEIGHT元素都匹配:

<xsl:template match="ATOMIC_NUMBER|ATOMIC_WEIGHT">

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

</xsl:template>

也可以在|两边加入空格,这样使代码更清晰。例如:

<xsl:template match="ATOMIC_NUMBER | ATOMIC_WEIGHT">

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

</xsl:template>

还可以顺次使用两个以上的模式。例如,下面的模板规则作用于A

14.7 选择节点的表达式

在xsl:apply-templates、xsl: value-of、xsl:for-each、xsl:copy-of和xsl:sort中,可使用select特性来精确指定对哪个节点进行操作。此特性值即为表达式(expression)。表达式是前节讨论的匹配模式的超集。也就是说,所有的匹配模式都是选择表达式,但并非所有的选择表达式都是匹配模式。让我们来回顾一下,匹配模式能够使用元素名、子元素、后代以及特性来匹配节点,除此之外,还可以对这些项目进行简单的测试。选择表达式可以使用所有的这些条件来选择节点,而且还可以通过参考父元素、同属元素来选择节点,以及通过更加复杂的测试来选择节点。此外,表达式并不局限于只生成一组节点列表,而且还产生布尔值、数值和字符串。

14.7.1 节点轴

表达式并不局限于指定当前节点的子节点和后代节点。XSL提供许多轴(axe),使用这些轴可以从相对于当前节点(通常为模板匹配的节点)的树形结构的不同部分进行选择。表14-2概述了这些轴及其含义。

 

表14-2 表达式的轴



选自于

from-ancestors()

当前节点的父节点、当前节点的父节点的父节点、当前节点的父节点的父节点的父节点,依次类推至根节点

from-ancestors-or-self()

当前节点的后代以及当前节点本身

from-attributes()

当前节点的特性

from-children()

当前节点的直系子节点

from-descendants()

当前节点的子节点、当前节点的子节点的子节点,依次类推

from-descendants-or-self()

当前节点本身及其后代节点

from-following()

起始于当前节点末尾之后的所有节点

from-following-siblings()

起始于当前节点末尾之后并且与当前节点具有同一个父节点的所有节点

from-parent()

当前节点的单一父节点

from-preceding()

当前节点开始之前开始的所有节点

from-preceding- siblings()

当前节点开始之前开始的所有节点并且与当前节点具有同一个父节点的所有节点

from-self()

当前节点

from-following和from-preceding轴不可靠,可能不会包括在XSL的最终发布版中。如果包括在XSL的最终发布版中,其准确的含义可能会改变。

这些轴的功能是选择表14-2第二列中列出的节点。圆括号中包括要进一步对此节点列表筛选的选择表达式。例如,可能包括由下列模板规则选择的元素名称:

<xsl:template match="ATOM">

<tr>

<td>

<xsl:value-of select="from-children(NAME)"/)

</td>

<td>

<xsl:value-of select="from-children(ATOMIC_NUMBER)"/>

</td>

<td>

<xsl:value-of select="from-children(ATOMIC_WEIGHT)"/>

</td>

</tr>

</xsl:template>

此模板规则匹配ATOM元素。当ATOM元素匹配时,NAME元素、ATOMIC_NUMBER元素和ATOMIC_WEIGHT都从此匹配的ATOM元素的子元素中选择,并作为表的单元格输出。(如果有多个期待的元素��例如,三个NAME元素��那么,只选择第一个。)

from-children()轴不允许做单独使用元素名不能做的任何事情。实际上,select="ATOMIC_WEIGHT"只是select = "from-children (ATOMIC_WEIGHT)"的缩写形式。但是,其他轴更令人感兴趣。

在匹配模式时引用父元素是不合法的,但在选择表达式中引用则是合法。要引用父元素,可使用from-parent()轴。例如,下面的规则输出具有BOILING_POINT子元素的ATOM元素的值:

<xsl:template match="ATOM/BOILING_POINT">

<P><xsl:value-of select="from-parent(ATOM)"/></P>

</xsl:template>

这里匹配的是BOILING_POINT子元素,但输出的是ATOM父元素。

有些放射性原子(如钋)其半衰期是如此之短,以致无法测量重要的性质(如沸点和熔点)。所以并非所有的ATOM元素都必须有BOILING_POINT子元素。上面的规则可用来只输出实际上有沸点的元素。**14-10是此例的扩展,它匹配BOILING_POINT元素,但实际上使用from-parent(ATOM)输出ATOM父元素。

**14-10:只输出有已知熔点的元素的样式单

<?xml version="1.0"?>

<xsl:stylesheet

xmlns:xsl="http://www.w3.org/XSL/Transform/1.0">

<xsl:template match="/">

<html>

<body>

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

</body>

</html>

</xsl:template>

<xsl:template match="PERIODIC_TABLE">

<hl>Elements with known Melting Points</hl>

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

</xsl:template>

<xsl:template match="MELTING_POINT">

<P>

<xsl:value-of select="from-parent(ATOM)"/>

</P>

</xsl:template>

</xsl:stylesheet>

偶尔,可能需要选择给定类型元素的最近的祖先。使用from-ancestors()就可以做到这一点。例如,下面的规则插入最近的PERIODIC_TABLE元素(包含匹配的SYMBOL元素)的值。

<xsl:template match="SYMBOL">

<xsl:value-of select="from-ancestors(PERIODIC_TABLE)"/>

</xsl:template>

from-ancestors-or-self()函数的作用与from-ancestors()函数相似,所不同的是,如果当前节点与参数类型匹配,那么它的返回值为其本身,而不是真正的祖先。例如,下面的规则匹配所有元素。如果匹配的元素是PERIODIC_TABLE,那么在xsl:value-of中选择的正是PERIODIC_TABLE。

<xsl:template match="*">

<xsl:value-of select="from-ancestors-or-self(PERIODIC_TABLE)"/>

</xsl:template>



14.7.1.1 节点类型

from-axis()函数的参数,除了可以使用节点名称和通配符之外,还可以是下列四个节点类型函数之一:

* comment()

* text()

* pi()

* node()

comment()节点类型选择注释节点。text()节点类型选择文本节点。pi()节点类型选择处理指令节点,而node()节点类型选择任何类型的节点(*通配符只选择元素节点)。pi()节点类型还有一个可选的参数,用来指定要选择的处理指令的名称。

例如,下面的规则同时使用带有node()节点类型的from-self(),将匹配的ATOM元素封装在P元素中:

<xsl:template match="ATOM">

<P><xsl:value-of select="from-self(node())"/></P>

</xsl:template>

这里,选择from-self(node())与选择ATOM是不同的。下面的这个规则获取ATOM元素的ATOM子元素的值。此值不是匹配的ATOM元素的值,而是匹配ATOM元素的一个子元素的另一个ATOM元素值:

<xsl:template match="ATOM">

<P><xsl:value of select="ATOM"/></P>

</xsl:template>

14.7.1.2 层次操作符

可以使用/和//操作符来将选择表达式串联在一起。例如,**14-11只将有熔点的那些元素的元素名、原子序数和熔点打印成表。要实现此目的,选择MELTING_POINT元素的父元素,然后使用select="from-parent(*)/from-children(NAME)"来查找父元素的NAME和ATOMIC_NUMBER子元素。

**14-11:熔点与原子序数表

<?xml version="1.0"?>

<xsl:stylesheet

xmlns:xsl="http://www.w3.org/XSL/Transform/1.0">

<xsl:template match="/PERIODIC_TABLE">

<html>

<body>

<hl>Atomic Number vs. Melting Point</hl>

<table>

<th>Element</th>

<th>Atomic Number</th>

<th>Melting Point</th>

<xsl:apply-templates select "from-children(ATOM)"/>

</table>

</body>

</html>

</xsl:template>

<xsl:template match="ATOM">

<xsl:apply-templates

select="from-children(MELTING_POINT)"/>

</xsl:template>

<xsl:template match="MELTING_POINT">

<tr>

<td>

<xsl:value-of

select="from-parent(*)/from-children(NAME)"/>

</td>

<td>

<xsl:value-of

select="from-parent(*)/from-children(ATOMIC_NUMBER)"/>

</td>

<td>

<xsl:value-of select="from-self(*)"/>

<xsl:value-of select="from-attributes(UNITS)"/>

</td>

</tr>

</xsl:template>

</xsl:stylesheet>

这并不是解决这一问题的唯一方法。另外一种可能的方法是使用from-preceding-siblings()和from-following-siblings()轴或相对位置(前面或后面)不确定时同时使用两者。用于MELTING_POINT元素的必要模板规则如下所示:

<xsl:template match="MELTING_POINT">

<tr>

<td>

<xsl:value-of

select="from-preceding-siblings(NAME)

| from-following-siblings(NAME)"/>

</td>

<td>

<xsl:value-of

select="from-preceding-siblings(ATOMIC_NUMBER)

| from-following-siblings(ATOMIC_NUMBER)"/>

</td>

<td>

<xsl:value-of select="from-self(*)"/>

<xsl:value-of select="from-attributes(UNITS)"/>

</td>

</tr>

</xsl:template>

14.7.1.3 缩写句法

表14-2中的各种from-axis()函数对于轻松的打字工作来说过于冗长。XSL还定义了缩写句法,以便代替最常用的轴,在实际过程中使用更广。表14-3显示的是完整句法形式与缩写词的对等关系。

表14-3 选择表达式的缩写句法

缩写词

完整句法形式

.

from-self(node())

..

from-parent(node())

Name

from-children(name)

@name

from-attributes(name)

//

/from-descendants-or-self(node())/

使用缩写句法重写**14-11,得到**14-12。但这两个样式单所获得的输出结果是完全一样的。

**14-12:使用缩写句法获得的熔点和原子序数对照表

<?xml version="1.0"?>

<xsl:stylesheet

xmlns:xsl="http://www.w3.org/XSL/Transform/I.O">

<xsl:template match="/PERIODIC_TABLE">

<html>

<body>

<hl>Atomic Number vs. Melting Point</hl>

<table>

<th>Element</th>

<th>Atomic Number</th>

<th>Melting Point</th>

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

</table>

</body>

</html>

</xsl:template>

<xsl:template match="ATOM">

<xsl:apply-templates

select="MELTING_POINT"/>

</xsl:template>

<xsl:template match="MELTING_POINT">

<tr>

<td>

<xsl:value-of

select="../NAME"/>

</td>

<td>

<xsl:value-of

select="../ATOMIC_NUMBER"/>

</td>

<td>

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

<xsl:value-of select="@UNITS"/>

</td>

</tr>

</xsl:template>

</xsl:stylesheet>

匹配模式可以只使用缩写句法(并非使用所有的缩写句法)。对于选择表达式,只能使用表14-2中的from-axis()函数的完整句法形式。

14.7.2 表达式类型

每个表达式都计算出唯一的值。例如,表达式3+2运算值为5。上面所使用的表达式求出的都是节点集合。但是,在XSL中,有如下五种类型的表达式:

* 节点集合类型

* 布尔类型

* 数值类型

* 字符串类型

* 结果树形片段

14.7.2.1 节点集合

节点集合(node set)是输入文档的一组节点的列表。表14-2中的from-axis()函数返回包含匹配节点的节点集合。哪些节点处于某一函数返回的节点集合中,这要根据当前节点(也可以认为是上下文节点)、函数的参数而定,当然也依赖于它是哪个函数。

习惯于面向对象语言(如Java和C++)的程序员可能将当前节点看作为调用函数的对象;也就是说,在a.doSomething(b, c)中,当前节点为a。但是,在XSL中,当前节点总是明确的;也就是说,按照定义a类的文件所规定的形式,更可能写成doSomething(b, c)形式。

例如当当前节点为例14-1中的PERIODIC_TABLE元素时,表达式select="from-children(ATOM)"返回的节点集合含有两个ATOM元素。当上下文节点为例14-1中的PERIODIC_TABLE元素时,表达式select="from-children(ATOM)/from-children(NAME)" 返回的节点集合含有<NAME> Hydrogen </NAME>和<NAME> Helium </NAME>两个元素节点。

上下文节点(context node)是上下文节点列表(context node list)的一个成员。上下文节点列表是同时都与同一个规则相匹配的元素集合,通常是xsl:apply-templates或xsl:for-each调用的结果。例如,当**14-12应用于**14-1时,ATOM模板调用两次,第一次用于氢原子,第二次用于氦原子。第一次调用时,上下文节点就是氢的ATOM元素。第二次调用时,上下文节点就是氦的ATOM元素。但是,在这两次调用中,上下文节点列表则是包含氢和氦的ATOM元素的集合。

表14-4列举了许多既可以作为参数,也可以作为上下文节点对节点集合进行操作的函数。

表14-4 对节点集合进行操作的函数

函数

返回值类型

返回值

position()

数值

上下文节点列表中上下文节点的位置。列表中的第一个节点其位置为1

last()

数值

上下文节点集合中的节点数

count(node-set)

数值

在node-set参数指明的节点集合中的节点数

id(string)

节点集合

节点集合,其中只有一个元素(在同一个文档的任何位置)其ID为string;或者空集合(如果任何元素都没有指定的ID)

idref(node-set)

节点集合

节点集合,包括文档中的某些元素,其ID属性为在参数node-set中指明节点值中的(以空格分开)记号之一

key(string name, string value)

节点集合

节点集合,包括文档中所有具有指定值的关键字的节点。关键字是使用顶层xsl:key元素来设置的

keyref(string name, node set values)

节点集合

节点集合,包括文档中所有具有某种关键字节点,此关键字的值与第二个参数中的节点值相同

doc(string URI)

节点集合

文档或由URI引用的文档部分中的节点集合;这些节点从URI使用的命名的anchor标记或XPointer中选择。如果没有命名的anchor标记或Xpointer,那么所指文档的根元素就存在于节点集合中。相对URI是相对于输入文档中的当前节点的

docref(node set)

节点集合

节点集合,包括由URI引用的,其值为node set参数的所有节点

local-part(node set)

字符串

node set参数中第一个节点的本地部分(命名域前缀后面的所有内容);当不使用任何参数时可用于获取上下文节点的本地部分

namespace(node set)

字符串

节点集合中第一个节点命名域的URI;当不使用任何参数时,可用于获得上下文节点的命名域URI;如果节点处于缺省命名域内,则返回空字符

qname(node set)

字符串

node set参数中第一个节点的合法名称(可以为前缀和本地部分);要获得上下文节点的合法名称,可不使用任何参数

generate-id(node set)

字符串

参数node set中第一个节点的唯一标识符;不带参数使用时,可生成上下文节点的ID

第18章"命名域"将讨论命名域URI、前缀和本地部分。

 

doc()和docref()函数有点模糊,特别是如果URI只引用非结构完整的XML节点或数据片段,就更是如此。细节还要留待XSL规范的未来版本加以澄清。

如果向这些函数传递了一个错误类型的参数,那么XSL试图将此参数转变成正确的类型;例如,将数字12转变成字符串"12"。但是,任何参数都不能转变成节点集合。

position()函数可用来对元素进行计数。**14-13是一个样式单,它使用<xsl:value-of select = "position"/>,将元素在文档中的位置作为原子名的名称的前缀。

**14-13:按照文档中的顺序对原子进行编号的样式单

<?xml version="1.0"?>

<xsl:stylesheet

xmlns:xsl="http://www.w3.org/XSL/Transform/1.0">

<xsl:template match="/PFRIODIC_TABLE">

<HTML>

<HEAD><TITLE>The Elements</TITLE></HEAD>

<BODY>

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

</BODY>

</HTML>

</xsl:template>

<xsl:template match="ATOM">

<P>

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

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

</P>

</xsl:template>

</xsl:stylesheet>

将此样式单应用于**14-1时,其输出结果如下:

<HTML><HEAD><TITLE>The Elements</TITLE></HEAD><BODY><P>1.

Hydrogen</P><P>2.

Helium</P></BODY></HTML>

14.7.2.2 布尔类型

布尔值为两个值之一:true(真)或false(假)。XSL允许将任何类型的数据转变成布尔值。当在可望为布尔值的地方使用了字符串或数值或节点集合时,通常就暗示需要这样做,xsl:if元素的test特性中正是这样情况。根据下列这些规则,也可以使用boolean()函数来完成这种变换过程,此函数将任何类型(或如果不提供参数即为上下文节点)的参数转变成布尔值:

* 如果数值为零或NaN(一种特定的符号,意为Not a Number,即不是数字,用于表示被零除所获得的结果以及类似的非法操作),则此值为false,否则为true

* 空节点集合为false;所有的其他节点集合为true

* 空结果片段为false;所有其他结果片段都为true

* 零长度字符串为false;所有其他字符串为true

使用下列操作符所获得的表达式的结果也可以得到布尔值:

= 等于号

< 小于号(实际使用<)

> 大于号

< = 小于等于(实际使用<=)

> = 大于等于

在特性值中<符号是非法的。因此,必须用<来代替,甚至作为小于运算符时也是如此。

这些运算符最常用于判断是否调用某个规则。选择表达式不仅含有选择某些节点的模式,而且还可以含有判断条件,从而使用此判断条件对所选的节点列表进一步筛选。例如,from-children(ATOM)选择当前节点的所有ATOM子节点。但是,from-children(ATOME[position()=1])只选择当前节点的第一个ATOM子节点。[position()=1]为一判断语句,它在节点上测试ATOM,返回一个布尔结果值,如果当前节点的位置等于1,则返回的结果为true,否则为false。对每个节点的测试都可能有任何判断值。但是,大于1的值则是不常见到的。

例如,下面的模板规则通过测试元素的位置是否等于1,来决定将此规则应用于周期表中第一个ATOM元素,而不是后续元素。

<xsl:template match="PERIODIC_TABLE/ATOM[position()=l]">

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

</xsl:template>

下面的模板规则通过测试元素的恢檬欠翊笥?,来将此规则应用于非PERIODIC_TABLE第一个子元素的所有ATOM元素:

<xsl:template match="PERIODIC_TABLE/ATOM[position()>1]">

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

</xsl:template>

关键字and和or根据正常的逻辑规则,将两个布尔表达式进行逻辑组合。例如,假设要将模板应用于ATOMIC_NUMBER元素,它既不是其父元素的第一个子元素,也不是其父元素的最后一个子元素;也就是说,它就是父元素本身。下面的模板规则使用and来完成此项工作:

<xsl:template

match="ATOMIC_NUMBER[position()=l and position()=last()]">

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

</xsl:template>

下面的模板规则通过匹配位置是1还是最后一个,应用于其父元素中的第一个和最后一个ATOM元素:

<xsl:template match="ATOM[position()=l or positiono=last()]">

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

</xsl:template>

这是逻辑上的“或”,所以如果两个条件都为真,它也将匹配。也就是说,它将既与其父元素的第一个子元素ATOM元素进行匹配,也与其父元素的最后一个子元素ATOM元素进行匹配。

在XSL中没有not关键字,但有not()函数。将操作放在not()括号中,可实现对操作的取反。例如,下面的模板规则选择除其父元素的第一个子元素外的所有ATOM元素:

<xsl:template match="ATOM[not(position()=l)]">

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

</xsl:template>

下面的模板规则选择除其父元素的第一个和最后一个ATOM子元素外的所有ATOM元素:

<xsl:template match =

"ATOM[not(position()=l or position()=last())]">

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

</xsl:template>

不存在“异或”操作符。但巧妙地使用not()、and和or可以形成"异或"效果。例如,下面的规则要么选择第一个子元素的ATOM元素,要么选择最后一个子元素的ATOM元素,但不会同时选择第一个和最后一个子元素的ATOM元素。

<xsl:template

match="ATOM[(position()=l or position()=last())

and not(position()=l and position()=last())]">

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

</xsl:template>

下列还有三个函数返回布尔值:

* true()总是返回true

* false()总是返回false

* lang(code)如果当前节点的语言(由xml:lang特性给出)与code参数相同,则返回true



14.7.2.3 数值

XSL的数值为64位IEEE双精度浮点数。看起来像整数数值(如42或-7000)也是以双精度保存的。非数字值(如字符串和布尔值)根据结果可转化为数字,或使用下面的规则由数值函数将非数字值转化为数字:

* 如果为true,布尔值为1;如果为false,则为0。

* 字符串去首尾空白;然后按要求转化成数字;例如,字符串“12"转化为数字12。如果字符串无法作为数字表示,那么就转换为0。

* 节点集合和结果片段转换成字符串,然后将此字符串转换成数字。

例如,下面的规则只输出自然界不存在的反铀(trans-uranium)元素以及原子序数大于92(铀原子序数)的元素。于是,ATOMIC_NUMBER产生的节点集合被隐式地转变成当前ATOMIC_NUMBER节点的字符串值。

<xsl:template match="/PERIODIC_TABLE">

<HTML>

<HEAD><TITLE>The TransUranium Elements</TITLE></HEAD>

<BODY>

<xsl:apply-templates select="ATOM[ATOMIC_NUMBER>92]"/>

</BODY>

</HTML>

</xsl:template>

XSL提供了四个标准的算术运算符:

* + 加法

* - 减法

* * 乘法

* div除法(最通用的 / 在XSL中已用于其他目的)

例如,<xsl:value-of select="2+2"/>将字符串“4"插入到输出文档中。这些运算更常用作测试。例如,下面的规则选择原子量大于原子序数两倍的元素:

<xsl:template match="/PERIODIC_TABLE">

<HTML>

<BODY>

<Hl>High Atomic Weight to Atomic Number Ratios</Hl>

<xsl:apply-templates

select="ATOM[ATOMIC_WEIGHT > 2 * ATOMIC_NUMBER]"/>

</BODY>

</HTML>

</xsl:template>

下面的模板实际上打印原子量与原子序数的比值:

<xsl:template match="ATOM">

<P>

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

<xsl:value-of select="ATOMIC_WEIGHT div ATOMIC_NUMBER"/>

</P>

</xsl:template>

XSL还提供两个不常用的二进制运算符:

* mod:用于对两个数求余

* quo:用于两个数相除,然后截去小数部分,形成一个整数

XSL还有对数字进行操作的四个函数:

floor()返回比此值小的最大整数

ceiling()返回比此值大的最小整数

round()将数值四舍五入成最接近的整数

sum()返回其参数的和

例如下面的模板规则将原子量(各同位素在自然界分布的中子数与质子数之和的加权平均数)减去原子序数(质子数),计算出原子中的中子数,并四舍五入成最接近的整数:

<xsl:template match="ATOM">

<P>

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

<xsl:value-of

select="round(ATOMIC_WEIGHT - ATOMIC_NUMBER)"/>

</P>

</xsl:template>

下面的规则将所有的原子量相加,然后除以原子的个数,从而计算出表中所有原子的平均原子量:

<xsl:template match="/PERIODIC_TABLE">

<HTML>

<BODY>

<H1>Average Atomic Weight</H1>

<xsl:value-of

select="sum(from-descendants(ATOMIC_WEIGHT))

div count(from-descendants(ATOMIC_WEIGHT))"/>

</BODY>

</HTML>

</xsl:template>

14.7.2.4 字符串

字符串是Unicode字符序列。按照下面的准则,使用string()函数,就可以将其他数据类型转换成字符串类型:

* 节点集合转换的结果是将集合中的节点值连接在一起。根据表14-1所给出的规则,由xsl:value-of元素计算出集合中的节点值。

* 结果树形片段(result tree fragment)在转换时,很像是一个元素,并取此假想的元素值。而此假想的元素值是根据表14-1所给出的规则,由xsl:value-of元素计算出的。

* 数字转换成欧洲风格的数字字符串,如“-12"或"3.1415292"。

* 布尔值的false转换成英语单词的"false";布尔值的true转换成英语单词的" true"。

除了string( )之外,XSL还有七个对字符进行操作的函数。现总结于表14-5中。

表14-5 对字符串进行操作的函数

函数

返回值类型

返回值

starts-with(main_string, prefix_string)

布尔

如果main_string以prefix_string开始,则为true;否则为false

Contains(containing_string, contained_string)

布尔

如果contained_string参数是containing_string参数的一部分,则为true;否则为false

Substring-before(string, marker-string)

字符串

从string的第一个字符直到第一次出现marker-string止(但不包括)的部分

Substring-after(string, marker-string)

字符串

从第一次出现marker-string之后到string最后一个字符为止的部分

Normalize(string)

字符串

截去string首尾空白后的部分,并且一连串的空白以一个空格代替;如果忽略string参数,则将上下文节点的字符串值变成为正常字符串

Translate(string, replaced_text, replacement_text)

字符串

返回string中由replacement_text中的相应字符来代替replaced_text中的字符后的结果

concat(string1, string2, )

字符串

将以参数形式传递的所有字符串连接起来,并返回这种连接后的字符串,其顺序为传递时的顺序

format-number(number, format-string, locale-string)

字符串

返回number参数格式化后的字符串形式。格式化是按照由locale-string参数指定的位置中的format-string参数所指定的格式进行的。其工作方式就好像由Java 1.1中的java.text.DecimalFormat类所进行的格式化一样(请参考http://java.sun.com/ products/jdk/1.1/docs/api/java.text. DecimalFormat.html)

14.7.2.5 结果树形片段

结果树形片段是XML文档的一部分,而不是一个完整的节点或节点集合。例如,使用带有指向元素中间的URI的doc()函数,其结果可能产生一结果树形片段。有些扩展函数(专门用于特定的XSL实现或安装的函数)也可以返回结果树形片段。

由于结果树形片段不是结构整洁的XML,所以不能用它们来做什么事。实际上,唯一允许的操作是分别使用string()和boolean()函数,来将它们转换成字符串值或布尔值。

XML专区热门文章排行
网站赞助商
购买此位置

 

关于我们 | 网站地图 | 文档一览 | 友情链接| 联系我们

Copyright © 2003-2024 电脑爱好者 版权所有 备案号:鲁ICP备09059398号